(〃'▽'〃)_v2026_08_发布:新增 HRM 人力资源管理系统、FMS 财务管理系统,支持独立手机端操作

This commit is contained in:
YunaiV
2026-08-30 21:02:24 +08:00
parent 14ee55f4dd
commit f3b6a0a853
930 changed files with 0 additions and 111682 deletions
@@ -1,342 +0,0 @@
package cn.iocoder.yudao.framework.common.util.date;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.TimeRange;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link LocalDateTimeUtils} 的单元测试
*
* @author 芋道源码
*/
public class LocalDateTimeUtilsTest {
@Test
public void testDateCompare() {
// 准备参数
LocalDate firstDate = LocalDate.of(2026, 7, 23);
LocalDate secondDate = LocalDate.of(2026, 7, 24);
// 调用,并断言
assertTrue(LocalDateTimeUtils.isBeforeOrEqual(firstDate, secondDate));
assertTrue(LocalDateTimeUtils.isBeforeOrEqual(secondDate, secondDate));
assertFalse(LocalDateTimeUtils.isBeforeOrEqual(secondDate, firstDate));
assertTrue(LocalDateTimeUtils.isAfterOrEqual(secondDate, firstDate));
assertTrue(LocalDateTimeUtils.isAfterOrEqual(secondDate, secondDate));
assertFalse(LocalDateTimeUtils.isAfterOrEqual(firstDate, secondDate));
}
@Test
public void testDateTimeCompare() {
// 准备参数
LocalDateTime firstTime = LocalDateTime.of(2026, 7, 24, 9, 0);
LocalDateTime secondTime = LocalDateTime.of(2026, 7, 24, 18, 0);
// 调用,并断言
assertTrue(LocalDateTimeUtils.isBeforeOrEqual(firstTime, secondTime));
assertTrue(LocalDateTimeUtils.isBeforeOrEqual(secondTime, secondTime));
assertFalse(LocalDateTimeUtils.isBeforeOrEqual(secondTime, firstTime));
assertTrue(LocalDateTimeUtils.isAfterOrEqual(secondTime, firstTime));
assertTrue(LocalDateTimeUtils.isAfterOrEqual(secondTime, secondTime));
assertFalse(LocalDateTimeUtils.isAfterOrEqual(firstTime, secondTime));
}
@Test
public void testIsTimeRangeValid() {
// 准备参数
LocalDateTime beginTime = LocalDateTime.of(2026, 7, 24, 9, 0);
LocalDateTime endTime = LocalDateTime.of(2026, 7, 24, 18, 0);
// 调用,并断言
assertTrue(LocalDateTimeUtils.isTimeRangeValid(beginTime, endTime));
assertFalse(LocalDateTimeUtils.isTimeRangeValid(beginTime, beginTime));
assertFalse(LocalDateTimeUtils.isTimeRangeValid(endTime, beginTime));
assertFalse(LocalDateTimeUtils.isTimeRangeValid(null, endTime));
assertFalse(LocalDateTimeUtils.isTimeRangeValid(beginTime, null));
}
@Test
public void testIsTimeRangePresent() {
// 准备参数
LocalDateTime time = LocalDateTime.of(2026, 7, 24, 9, 0);
// 调用,并断言:空数组和双空边界都不是有效范围
assertFalse(LocalDateTimeUtils.isTimeRangePresent(null));
assertFalse(LocalDateTimeUtils.isTimeRangePresent(new LocalDateTime[0]));
assertFalse(LocalDateTimeUtils.isTimeRangePresent(new LocalDateTime[]{null, null}));
// 调用,并断言:单边或双边存在即为有效范围
assertTrue(LocalDateTimeUtils.isTimeRangePresent(new LocalDateTime[]{time}));
assertTrue(LocalDateTimeUtils.isTimeRangePresent(new LocalDateTime[]{null, time}));
assertTrue(LocalDateTimeUtils.isTimeRangePresent(new LocalDateTime[]{time, time.plusHours(1)}));
}
@Test
public void testGetDayTime() {
// 准备参数
LocalDate date = LocalDate.of(2026, 7, 24);
LocalDateTime time = date.atTime(15, 30);
// 调用,并断言
assertEquals(LocalDateTime.of(2026, 7, 24, 0, 0),
LocalDateTimeUtils.getDayBeginTime(date));
assertEquals(LocalDateTime.of(2026, 7, 24, 0, 0),
LocalDateTimeUtils.getDayBeginTime(time));
assertNull(LocalDateTimeUtils.getDayBeginTime((LocalDateTime) null));
assertEquals(LocalDateTime.of(date, LocalTime.MAX),
LocalDateTimeUtils.getDayEndTime(date));
}
@Test
public void testGetDateTimeRange() {
// 准备参数
LocalDate beginDate = LocalDate.of(2026, 7, 1);
LocalDate endDate = LocalDate.of(2026, 7, 31);
// 调用,并断言:左右两端均为闭区间边界
LocalDateTime[] result = LocalDateTimeUtils.getDateTimeRange(beginDate, endDate);
assertEquals(beginDate.atStartOfDay(), result[0]);
assertEquals(endDate.atTime(LocalTime.MAX), result[1]);
// 调用,并断言:支持单边范围
result = LocalDateTimeUtils.getDateTimeRange(beginDate, null);
assertEquals(beginDate.atStartOfDay(), result[0]);
assertNull(result[1]);
result = LocalDateTimeUtils.getDateTimeRange(null, endDate);
assertNull(result[0]);
assertEquals(endDate.atTime(LocalTime.MAX), result[1]);
// 调用,并断言:两个边界都为空时不生成范围
assertNull(LocalDateTimeUtils.getDateTimeRange(null, null));
}
@Test
public void testGetMonthDateTimeRange() {
// 调用:闰年二月
LocalDateTime[] result = LocalDateTimeUtils.getMonthDateTimeRange(2024, 2);
// 断言:完整包含闰年二月的首尾时刻
assertEquals(LocalDateTime.of(2024, 2, 1, 0, 0), result[0]);
assertEquals(LocalDate.of(2024, 2, 29).atTime(LocalTime.MAX), result[1]);
}
@Test
public void testGetMonthBeginTime() {
// 准备参数
YearMonth month = YearMonth.of(2026, 12);
// 调用,并断言
assertEquals(LocalDateTime.of(2026, 12, 1, 0, 0),
LocalDateTimeUtils.getMonthBeginTime(month));
assertEquals(LocalDateTime.of(2027, 1, 1, 0, 0),
LocalDateTimeUtils.getNextMonthBeginTime(month));
}
@Test
public void testIsBetween() {
// 准备参数
LocalDate beginDate = LocalDate.of(2026, 7, 23);
LocalDate endDate = LocalDate.of(2026, 7, 25);
LocalDateTime beginTime = beginDate.atTime(9, 0);
LocalDateTime endTime = beginDate.atTime(18, 0);
// 调用,并断言:日期闭区间
assertTrue(LocalDateTimeUtils.isBetween(beginDate, endDate, beginDate));
assertTrue(LocalDateTimeUtils.isBetween(beginDate, endDate, LocalDate.of(2026, 7, 24)));
assertTrue(LocalDateTimeUtils.isBetween(beginDate, endDate, endDate));
assertFalse(LocalDateTimeUtils.isBetween(beginDate, endDate, LocalDate.of(2026, 7, 26)));
assertFalse(LocalDateTimeUtils.isBetween(beginDate, endDate, null));
assertFalse(LocalDateTimeUtils.isNotBetween(beginDate, endDate, beginDate));
assertTrue(LocalDateTimeUtils.isNotBetween(beginDate, endDate, LocalDate.of(2026, 7, 26)));
assertTrue(LocalDateTimeUtils.isNotBetween(beginDate, endDate, null));
// 调用,并断言:时间闭区间
assertTrue(LocalDateTimeUtils.isBetween(beginTime, endTime, beginTime));
assertTrue(LocalDateTimeUtils.isBetween(beginTime, endTime, beginDate.atTime(12, 0)));
assertTrue(LocalDateTimeUtils.isBetween(beginTime, endTime, endTime));
assertFalse(LocalDateTimeUtils.isBetween(beginTime, endTime, beginDate.atTime(18, 1)));
assertFalse(LocalDateTimeUtils.isBetween(beginTime, endTime, (LocalDateTime) null));
assertFalse(LocalDateTimeUtils.isNotBetween(beginTime, endTime, endTime));
assertTrue(LocalDateTimeUtils.isNotBetween(beginTime, endTime, beginDate.atTime(18, 1)));
assertTrue(LocalDateTimeUtils.isNotBetween(beginTime, endTime, null));
}
@Test
public void testIsClosedRangeOverlap() {
// 准备参数
LocalDateTime firstBeginTime = LocalDateTime.of(2026, 7, 24, 9, 0);
LocalDateTime firstEndTime = LocalDateTime.of(2026, 7, 24, 12, 0);
// 调用,并断言:首尾相接属于闭区间重叠
assertTrue(LocalDateTimeUtils.isClosedRangeOverlap(
firstBeginTime, firstEndTime, firstEndTime, firstEndTime.plusHours(1)));
assertTrue(LocalDateTimeUtils.isClosedRangeOverlap(
firstBeginTime, firstEndTime, firstBeginTime.minusHours(1), firstBeginTime));
assertFalse(LocalDateTimeUtils.isClosedRangeOverlap(
firstBeginTime, firstEndTime, firstEndTime.plusNanos(1), firstEndTime.plusHours(1)));
assertFalse(LocalDateTimeUtils.isClosedRangeOverlap(
firstBeginTime, firstEndTime, null, firstEndTime));
}
@Test
public void testSubtractTimeRanges() {
// 准备参数
LocalDate date = LocalDate.of(2026, 7, 24);
TimeRange sourceRange = new TimeRange(date.atTime(9, 0), date.atTime(18, 0));
// 调用:扣除原时段中间的一段
List<TimeRange> result = LocalDateTimeUtils.subtractTimeRanges(
Collections.singletonList(sourceRange),
new TimeRange(date.atTime(12, 0), date.atTime(13, 0)));
// 断言:原时段被拆分为两段
assertEquals(2, result.size());
assertTimeRange(CollUtil.getFirst(result), date.atTime(9, 0), date.atTime(12, 0));
assertTimeRange(result.get(1), date.atTime(13, 0), date.atTime(18, 0));
// 调用,并断言:扣除时段完整覆盖原时段
result = LocalDateTimeUtils.subtractTimeRanges(
Collections.singletonList(sourceRange),
new TimeRange(date.atTime(8, 0), date.atTime(19, 0)));
assertTrue(result.isEmpty());
// 调用:扣除时段与原时段首尾相接
result = LocalDateTimeUtils.subtractTimeRanges(
Collections.singletonList(sourceRange),
new TimeRange(date.atTime(18, 0), date.atTime(19, 0)));
// 断言:两个时段仅首尾相接,没有正时长交集,原时段保持不变
assertEquals(1, result.size());
assertTimeRange(CollUtil.getFirst(result), date.atTime(9, 0), date.atTime(18, 0));
}
@Test
public void testMergeTimeRanges() {
// 准备参数
LocalDate date = LocalDate.of(2026, 7, 24);
List<TimeRange> timeRanges = Arrays.asList(
new TimeRange(date.atTime(13, 0), date.atTime(14, 0)),
new TimeRange(date.atTime(9, 0), date.atTime(11, 0)),
new TimeRange(date.atTime(10, 0), date.atTime(13, 0)),
new TimeRange(date.atTime(16, 0), date.atTime(17, 0)));
// 调用
List<TimeRange> result = LocalDateTimeUtils.mergeTimeRanges(timeRanges);
// 断言:重叠或首尾相接的时段被合并,独立时段保持不变
assertEquals(2, result.size());
assertTimeRange(CollUtil.getFirst(result), date.atTime(9, 0), date.atTime(14, 0));
assertTimeRange(result.get(1), date.atTime(16, 0), date.atTime(17, 0));
// 调用,并断言:空列表
assertTrue(LocalDateTimeUtils.mergeTimeRanges(Collections.emptyList()).isEmpty());
}
@Test
public void testIntersectTimeRanges() {
// 准备参数
LocalDate date = LocalDate.of(2026, 7, 24);
List<TimeRange> firstRanges = Arrays.asList(
new TimeRange(date.atTime(9, 0), date.atTime(12, 0)),
new TimeRange(date.atTime(13, 0), date.atTime(18, 0)));
List<TimeRange> secondRanges = Arrays.asList(
new TimeRange(date.atTime(10, 0), date.atTime(14, 0)),
new TimeRange(date.atTime(17, 0), date.atTime(19, 0)));
// 调用
List<TimeRange> result = LocalDateTimeUtils.intersectTimeRanges(firstRanges, secondRanges);
// 断言
assertEquals(3, result.size());
assertTimeRange(CollUtil.getFirst(result), date.atTime(10, 0), date.atTime(12, 0));
assertTimeRange(result.get(1), date.atTime(13, 0), date.atTime(14, 0));
assertTimeRange(result.get(2), date.atTime(17, 0), date.atTime(18, 0));
// 调用,并断言:两个时段仅首尾相接时不生成零时长交集
assertNull(LocalDateTimeUtils.intersectTimeRange(
new TimeRange(date.atTime(9, 0), date.atTime(10, 0)),
new TimeRange(date.atTime(10, 0), date.atTime(11, 0))));
}
@Test
public void testCalculateDurationMinutes() {
// 准备参数
LocalDate date = LocalDate.of(2026, 7, 24);
List<TimeRange> timeRanges = Arrays.asList(
new TimeRange(date.atTime(9, 0), date.atTime(10, 0)),
new TimeRange(date.atTime(13, 0), date.atTime(14, 30)));
// 调用,并断言
assertEquals(150, LocalDateTimeUtils.calculateDurationMinutes(timeRanges));
// 调用,并断言:空列表
assertEquals(0, LocalDateTimeUtils.calculateDurationMinutes(Collections.emptyList()));
}
@Test
public void testBuildDailyTimeRanges() {
// 准备参数
LocalDate beginDate = LocalDate.of(2026, 7, 24);
LocalDate endDate = LocalDate.of(2026, 7, 25);
// 调用:构建跨天时间范围
List<TimeRange> result = LocalDateTimeUtils.buildDailyTimeRanges(
beginDate, endDate, LocalTime.of(22, 0), LocalTime.of(6, 0));
// 断言
assertEquals(2, result.size());
assertTimeRange(CollUtil.getFirst(result), beginDate.atTime(22, 0), beginDate.plusDays(1).atTime(6, 0));
assertTimeRange(result.get(1), endDate.atTime(22, 0), endDate.plusDays(1).atTime(6, 0));
// 调用:每日开始和结束时刻相同
result = LocalDateTimeUtils.buildDailyTimeRanges(
beginDate, beginDate, LocalTime.of(9, 0), LocalTime.of(9, 0));
// 断言:按完整一天处理
assertEquals(1, result.size());
assertTimeRange(CollUtil.getFirst(result), beginDate.atTime(9, 0), beginDate.plusDays(1).atTime(9, 0));
// 调用,并断言:开始日期晚于结束日期
assertTrue(LocalDateTimeUtils.buildDailyTimeRanges(
endDate, beginDate, LocalTime.of(9, 0), LocalTime.of(18, 0)).isEmpty());
}
@Test
public void testFindDailyTimeRange() {
// 准备参数
LocalDate date = LocalDate.of(2026, 7, 8);
// 调用,并断言普通时间范围的左右边界
TimeRange result = LocalDateTimeUtils.findDailyTimeRange(
date, LocalTime.of(8, 0), LocalTime.of(10, 0), date.atTime(8, 0));
assertEquals(date.atTime(8, 0), result.getStartTime());
assertEquals(date.atTime(10, 0), result.getEndTime());
assertNotNull(LocalDateTimeUtils.findDailyTimeRange(
date, LocalTime.of(8, 0), LocalTime.of(10, 0), date.atTime(10, 0)));
// 调用,并断言跨日时间范围
result = LocalDateTimeUtils.findDailyTimeRange(
date, LocalTime.of(20, 0), LocalTime.of(6, 0), date.plusDays(1).atTime(5, 0));
assertEquals(date.atTime(20, 0), result.getStartTime());
assertEquals(date.plusDays(1).atTime(6, 0), result.getEndTime());
assertNull(LocalDateTimeUtils.findDailyTimeRange(
date, LocalTime.of(8, 0), LocalTime.of(10, 0), date.atTime(12, 0)));
}
private static void assertTimeRange(TimeRange timeRange,
LocalDateTime expectedStartTime,
LocalDateTime expectedEndTime) {
assertEquals(expectedStartTime, timeRange.getStartTime());
assertEquals(expectedEndTime, timeRange.getEndTime());
}
}
@@ -1,61 +0,0 @@
package cn.iocoder.yudao.framework.excel.core.util;
import cn.idev.excel.FastExcelFactory;
import cn.idev.excel.annotation.ExcelProperty;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockMultipartFile;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@link ExcelUtils} 的单元测试
*
* @author 芋道源码
*/
public class ExcelUtilsTest {
@Test
public void testRead_maxRowCount() throws Exception {
// mock 数据
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
FastExcelFactory.write(outputStream, TestRow.class).sheet().doWrite(Arrays.asList(
new TestRow("员工一"), new TestRow("员工二"), new TestRow("员工三")));
MockMultipartFile file = new MockMultipartFile(
"file", "employees.xlsx", null, outputStream.toByteArray());
// 调用
List<TestRow> rows = ExcelUtils.read(file, TestRow.class, 2);
// 断言
assertEquals(2, rows.size());
assertEquals("员工一", rows.get(0).getName());
assertEquals("员工二", rows.get(1).getName());
}
public static class TestRow {
@ExcelProperty("姓名")
private String name;
public TestRow() {
}
public TestRow(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
@@ -1,67 +0,0 @@
package cn.iocoder.yudao.framework.mybatis.core.query;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import lombok.Data;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link LambdaQueryWrapperX} 的单元测试
*
* @author 芋道源码
*/
public class LambdaQueryWrapperXTest {
@BeforeAll
public static void initTableInfo() {
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), TestDO.class);
}
@Test
public void testBetweenIfPresent_overlap() {
// 调用,并断言:空范围不追加条件
assertEquals("", new LambdaQueryWrapperX<TestDO>()
.betweenIfPresent(TestDO::getStartTime, TestDO::getEndTime, null)
.getSqlSegment());
// 调用,并断言:双边范围使用闭区间重叠条件
LocalDateTime beginTime = LocalDateTime.of(2026, 8, 1, 0, 0);
LocalDateTime endTime = LocalDateTime.of(2026, 8, 31, 23, 59);
String sqlSegment = new LambdaQueryWrapperX<TestDO>()
.betweenIfPresent(TestDO::getStartTime, TestDO::getEndTime,
new LocalDateTime[]{beginTime, endTime})
.getSqlSegment();
assertTrue(sqlSegment.contains("start_time <="));
assertTrue(sqlSegment.contains("end_time >="));
// 调用,并断言:单边范围只追加对应的重叠边界
sqlSegment = new LambdaQueryWrapperX<TestDO>()
.betweenIfPresent(TestDO::getStartTime, TestDO::getEndTime,
new LocalDateTime[]{beginTime})
.getSqlSegment();
assertTrue(sqlSegment.contains("end_time >="));
sqlSegment = new LambdaQueryWrapperX<TestDO>()
.betweenIfPresent(TestDO::getStartTime, TestDO::getEndTime,
new LocalDateTime[]{null, endTime})
.getSqlSegment();
assertTrue(sqlSegment.contains("start_time <="));
}
@Data
@TableName("test_data")
private static class TestDO {
private LocalDateTime startTime;
private LocalDateTime endTime;
}
}
@@ -1,32 +0,0 @@
package cn.iocoder.yudao.framework.mybatis.core.query;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link QueryWrapperX} 的单元测试
*
* @author 芋道源码
*/
public class QueryWrapperXTest {
@Test
public void testBetweenIfPresent_array() {
// 调用,并断言:空范围不追加条件
assertEquals("", new QueryWrapperX<>().betweenIfPresent("create_time", (Object[]) null).getSqlSegment());
assertEquals("", new QueryWrapperX<>().betweenIfPresent("create_time", new Object[0]).getSqlSegment());
// 调用,并断言:单边范围安全降级为大于等于或小于等于
assertTrue(new QueryWrapperX<>().betweenIfPresent("create_time", new Object[]{1})
.getSqlSegment().contains("create_time >="));
assertTrue(new QueryWrapperX<>().betweenIfPresent("create_time", new Object[]{null, 2})
.getSqlSegment().contains("create_time <="));
// 调用,并断言:双边范围使用左右闭合的 BETWEEN
assertTrue(new QueryWrapperX<>().betweenIfPresent("create_time", new Object[]{1, 2})
.getSqlSegment().contains("create_time BETWEEN"));
}
}
-67
View File
@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao</artifactId>
<version>${revision}</version>
</parent>
<artifactId>yudao-module-fms</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
fms 包下,财务管理(Financial Management System)
例如说:凭证、账簿、报表、结账等等
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-infra</artifactId>
<version>${revision}</version>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- 现金流量表公式计算 -->
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -1,63 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsClosingOverviewRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsClosingQueryReqVO;
import cn.iocoder.yudao.module.fms.service.closing.FmsClosingPeriodService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 结账期间")
@RestController
@RequestMapping("/fms/closing/period")
@Validated
public class FmsClosingPeriodController {
@Resource
private FmsClosingPeriodService closingPeriodService;
@GetMapping("/current-month")
@Operation(summary = "获得当前会计期间")
public CommonResult<String> getCurrentMonth(@RequestParam("accountSetId") @NotNull Long accountSetId) {
return success(closingPeriodService.getCurrentMonth(accountSetId, getLoginUserId()));
}
@GetMapping("/overview")
@Operation(summary = "获得结账概况")
@PreAuthorize("@ss.hasPermission('fms:closing:query')")
public CommonResult<FmsClosingOverviewRespVO> getClosingOverview(@Valid FmsClosingQueryReqVO queryReqVO) {
return success(closingPeriodService.getClosingOverview(queryReqVO, getLoginUserId()));
}
@PutMapping("/close")
@Operation(summary = "结账")
@PreAuthorize("@ss.hasPermission('fms:closing:close')")
public CommonResult<Boolean> closePeriod(@Valid @RequestBody FmsClosingQueryReqVO queryReqVO) {
closingPeriodService.closePeriod(queryReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/cancel")
@Operation(summary = "反结账")
@PreAuthorize("@ss.hasPermission('fms:closing:cancel')")
public CommonResult<Boolean> cancelClosePeriod(@Valid FmsClosingQueryReqVO queryReqVO) {
closingPeriodService.cancelClosePeriod(queryReqVO, getLoginUserId());
return success(true);
}
}
@@ -1,86 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsClosingQueryReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsClosingSchemeRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsClosingSchemeSaveReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsProfitLossSettingsSaveReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsSpecialClosingSettingsSaveReqVO;
import cn.iocoder.yudao.module.fms.service.closing.FmsClosingSchemeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 结账方案")
@RestController
@RequestMapping("/fms/closing/scheme")
@Validated
public class FmsClosingSchemeController {
@Resource
private FmsClosingSchemeService closingSchemeService;
@GetMapping("/list")
@Operation(summary = "获得结账方案列表")
@PreAuthorize("@ss.hasPermission('fms:closing:query')")
public CommonResult<List<FmsClosingSchemeRespVO>> getClosingSchemeList(@Valid FmsClosingQueryReqVO queryReqVO) {
return success(closingSchemeService.getClosingSchemeList(queryReqVO, getLoginUserId()));
}
@PostMapping("/create")
@Operation(summary = "创建结账方案")
@PreAuthorize("@ss.hasPermission('fms:closing:update')")
public CommonResult<Long> createClosingScheme(@Valid @RequestBody FmsClosingSchemeSaveReqVO createReqVO) {
return success(closingSchemeService.createClosingScheme(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "修改结账方案")
@PreAuthorize("@ss.hasPermission('fms:closing:update')")
public CommonResult<Boolean> updateClosingScheme(@Valid @RequestBody FmsClosingSchemeSaveReqVO updateReqVO) {
closingSchemeService.updateClosingScheme(updateReqVO, getLoginUserId());
return success(true);
}
@PutMapping("/update-profit-loss-settings")
@Operation(summary = "保存结转损益设置")
@PreAuthorize("@ss.hasPermission('fms:closing:update')")
public CommonResult<Long> saveProfitLossSettings(@Valid @RequestBody FmsProfitLossSettingsSaveReqVO saveReqVO) {
return success(closingSchemeService.saveProfitLossSettings(saveReqVO, getLoginUserId()));
}
@PutMapping("/update-special-settings")
@Operation(summary = "保存专用结转设置")
@PreAuthorize("@ss.hasPermission('fms:closing:update')")
public CommonResult<Boolean> updateSpecialClosingSettings(@Valid @RequestBody FmsSpecialClosingSettingsSaveReqVO updateReqVO) {
closingSchemeService.updateSpecialClosingSettings(updateReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除结账方案")
@PreAuthorize("@ss.hasPermission('fms:closing:update')")
public CommonResult<Boolean> deleteClosingScheme(@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
closingSchemeService.deleteClosingScheme(accountSetId, id, getLoginUserId());
return success(true);
}
}
@@ -1,78 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsClosingTemplateRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsClosingTemplateSaveReqVO;
import cn.iocoder.yudao.module.fms.service.closing.FmsClosingTemplateService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 结账模板")
@RestController
@RequestMapping("/fms/closing/template")
@Validated
public class FmsClosingTemplateController {
@Resource
private FmsClosingTemplateService closingTemplateService;
@GetMapping("/list")
@Operation(summary = "获得结账模板列表")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:closing:query')")
public CommonResult<List<FmsClosingTemplateRespVO>> getClosingTemplateList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
return success(closingTemplateService.getClosingTemplateList(accountSetId, getLoginUserId()));
}
@PostMapping("/create")
@Operation(summary = "创建结账模板")
@PreAuthorize("@ss.hasPermission('fms:closing:update')")
public CommonResult<Long> createClosingTemplate(
@Valid @RequestBody FmsClosingTemplateSaveReqVO createReqVO) {
return success(closingTemplateService.createClosingTemplate(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "更新结账模板")
@PreAuthorize("@ss.hasPermission('fms:closing:update')")
public CommonResult<Boolean> updateClosingTemplate(
@Valid @RequestBody FmsClosingTemplateSaveReqVO updateReqVO) {
closingTemplateService.updateClosingTemplate(updateReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除结账模板")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024"),
@Parameter(name = "id", description = "结账模板编号", required = true, example = "1024")
})
@PreAuthorize("@ss.hasPermission('fms:closing:update')")
public CommonResult<Boolean> deleteClosingTemplate(@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
closingTemplateService.deleteClosingTemplate(accountSetId, id, getLoginUserId());
return success(true);
}
}
@@ -1,54 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsClosingSchemeGenerateReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsClosingVoucherGenerateReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.closing.vo.FmsProfitLossGenerateReqVO;
import cn.iocoder.yudao.module.fms.service.closing.FmsClosingVoucherService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 结转凭证")
@RestController
@RequestMapping("/fms/closing/voucher")
@Validated
public class FmsClosingVoucherController {
@Resource
private FmsClosingVoucherService closingVoucherService;
@PostMapping("/generate-profit-loss")
@Operation(summary = "生成结转损益凭证")
@PreAuthorize("@ss.hasPermission('fms:closing:profit-loss')")
public CommonResult<Long> generateProfitLossVoucher(@Valid @RequestBody FmsProfitLossGenerateReqVO generateReqVO) {
return success(closingVoucherService.generateProfitLossVoucher(generateReqVO, getLoginUserId()));
}
@PostMapping("/generate-scheme")
@Operation(summary = "生成结账方案凭证")
@PreAuthorize("@ss.hasPermission('fms:closing:profit-loss')")
public CommonResult<Long> generateClosingSchemeVoucher(@Valid @RequestBody FmsClosingSchemeGenerateReqVO generateReqVO) {
return success(closingVoucherService.generateClosingSchemeVoucher(generateReqVO, getLoginUserId()));
}
@PostMapping("/generate-list")
@Operation(summary = "批量生成结转凭证")
@PreAuthorize("@ss.hasPermission('fms:closing:profit-loss')")
public CommonResult<List<Long>> generateClosingVoucherList(@Valid @RequestBody FmsClosingVoucherGenerateReqVO generateReqVO) {
return success(closingVoucherService.generateClosingVoucherList(generateReqVO, getLoginUserId()));
}
}
@@ -1,63 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - FMS 结账概况 Response VO")
@Data
public class FmsClosingOverviewRespVO {
@Schema(description = "会计期间", example = "2026-08")
private String month;
@Schema(description = "是否已结账")
private Boolean closed;
@Schema(description = "是否要求凭证审核")
private Boolean voucherReviewRequired;
@Schema(description = "未审核凭证数量", example = "2")
private Long pendingVoucherCount;
@Schema(description = "凭证数量", example = "12")
private Long voucherCount;
@Schema(description = "损益类科目余额", example = "9100.00")
private BigDecimal profitLossBalance;
@Schema(description = "资产负债表差额", example = "0.00")
private BigDecimal balanceSheetDifference;
@Schema(description = "结转损益凭证编号", example = "1024")
private Long profitLossVoucherId;
@Schema(description = "初始余额是否试算平衡")
private Boolean initialBalanceBalanced;
@Schema(description = "凭证编号是否连续")
private Boolean voucherNumberContinuous;
@Schema(description = "需要结转损益时是否已生成凭证")
private Boolean profitLossVoucherGenerated;
@Schema(description = "利润表勾稽是否平衡")
private Boolean incomeStatementBalanced;
@Schema(description = "利润表未纳入公式的科目数量", example = "0")
private Integer incomeStatementUnmappedSubjectCount;
@Schema(description = "资产负债表损益是否已结转")
private Boolean balanceSheetProfitLossTransferred;
@Schema(description = "资产负债表是否平衡")
private Boolean balanceSheetBalanced;
@Schema(description = "资产负债表未纳入公式的科目数量", example = "0")
private Integer balanceSheetUnmappedSubjectCount;
@Schema(description = "是否满足全部结账条件")
private Boolean canClose;
}
@@ -1,22 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@Schema(description = "管理后台 - FMS 结账查询 Request VO")
@Data
public class FmsClosingQueryReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套不能为空")
private Long accountSetId;
@Schema(description = "目标会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
@NotBlank(message = "会计期间不能为空")
@Pattern(regexp = "\\d{4}-(0[1-9]|1[0-2])", message = "会计期间格式不正确")
private String month;
}
@@ -1,26 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@Schema(description = "管理后台 - FMS 结账方案生成凭证 Request VO")
@Data
public class FmsClosingSchemeGenerateReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账套不能为空")
private Long accountSetId;
@Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "方案编号不能为空")
private Long id;
@Schema(description = "会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
@NotBlank(message = "会计期间不能为空")
@Pattern(regexp = "\\d{4}-(0[1-9]|1[0-2])", message = "会计期间格式不正确")
private String month;
}
@@ -1,90 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - FMS 结账方案 Response VO")
@Data
public class FmsClosingSchemeRespVO {
@Schema(description = "方案编号", example = "1024")
private Long id;
@Schema(description = "账套编号", example = "1")
private Long accountSetId;
@Schema(description = "方案名称", example = "结转本月房租")
private String name;
@Schema(description = "是否期末结转")
private Boolean periodEnd;
@Schema(description = "来源科目编号", example = "1024")
private Long subjectId;
@Schema(description = "取数规则", example = "0")
private Integer formulaRule;
@Schema(description = "取数时间类型", example = "1")
private Integer timeType;
@Schema(description = "凭证字编号", example = "11")
private Long voucherWordId;
@Schema(description = "凭证摘要", example = "结转损益")
private String digest;
@Schema(description = "结转凭证类型", example = "2")
private Integer voucherType;
@Schema(description = "以前年度损益调整科目编号", example = "1024")
private Long priorYearAdjustmentSubjectId;
@Schema(description = "以前年度损益调整结转科目编号", example = "1025")
private Long adjustmentClosingSubjectId;
@Schema(description = "其他损益结转科目编号", example = "1026")
private Long otherClosingSubjectId;
@Schema(description = "是否按余额反向结转")
private Boolean reverseBalance;
@Schema(description = "结转日期", example = "31")
private Integer closingDay;
@Schema(description = "类型", example = "1")
private Integer type;
@Schema(description = "结转科目规则数组")
private List<SubjectRule> subjects;
@Schema(description = "待结转金额", example = "12000.00")
private BigDecimal balance;
@Schema(description = "当前期间已生成凭证编号数组")
private List<Long> voucherIds;
@Schema(description = "管理后台 - FMS 结账方案科目规则")
@Data
public static class SubjectRule {
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "科目编码快照", example = "6602")
private String subjectCode;
@Schema(description = "摘要", example = "结转本月房租")
private String digest;
@Schema(description = "借贷方向", example = "1")
private Integer direction;
@Schema(description = "金额比例", example = "100")
private BigDecimal amountRatio;
}
}
@@ -1,89 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.common.FmsDebitCreditDirectionEnum;
import cn.iocoder.yudao.module.fms.enums.closing.FmsClosingTimeTypeEnum;
import cn.iocoder.yudao.module.fms.enums.report.FmsFormulaRuleEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - FMS 结账方案保存 Request VO")
@Data
public class FmsClosingSchemeSaveReqVO {
@Schema(description = "方案编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账套不能为空")
private Long accountSetId;
@Schema(description = "方案名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "结转本月房租")
@NotBlank(message = "方案名称不能为空")
@Size(max = 255, message = "方案名称长度不能超过 255 个字符")
private String name;
@Schema(description = "是否期末结转", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "是否期末结转不能为空")
private Boolean periodEnd;
@Schema(description = "来源科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "来源科目不能为空")
private Long subjectId;
@Schema(description = "取数规则", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "取数规则不能为空")
@InEnum(FmsFormulaRuleEnum.class)
private Integer formulaRule;
@Schema(description = "取数时间类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "取数时间类型不能为空")
@InEnum(FmsClosingTimeTypeEnum.class)
private Integer timeType;
@Schema(description = "凭证字编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11")
@NotNull(message = "凭证字不能为空")
private Long voucherWordId;
@Schema(description = "结转科目规则数组", requiredMode = Schema.RequiredMode.REQUIRED)
@Valid
@NotEmpty(message = "结转科目规则不能为空")
@Size(min = 2, message = "结转科目规则至少需要两条")
private List<SubjectRule> subjects;
@Schema(description = "管理后台 - FMS 结账方案科目规则")
@Data
public static class SubjectRule {
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "科目不能为空")
private Long subjectId;
@Schema(description = "摘要", requiredMode = Schema.RequiredMode.REQUIRED, example = "结转本月房租")
@NotBlank(message = "摘要不能为空")
@Size(max = 500, message = "摘要长度不能超过 500 个字符")
private String digest;
@Schema(description = "借贷方向", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "借贷方向不能为空")
@InEnum(FmsDebitCreditDirectionEnum.class)
private Integer direction;
@Schema(description = "金额比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "金额比例不能为空")
@DecimalMin(value = "0", inclusive = false, message = "金额比例必须大于 0")
@DecimalMax(value = "100", message = "金额比例不能超过 100")
private BigDecimal amountRatio;
}
}
@@ -1,70 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - FMS 结账模板 Response VO")
@Data
public class FmsClosingTemplateRespVO {
@Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long accountSetId;
@Schema(description = "系统预置编码", example = "daily-travel-reimbursement")
private String presetCode;
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "报销差旅费")
private String name;
@Schema(description = "模板分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer category;
@Schema(description = "是否期末结转", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean periodEnd;
@Schema(description = "来源科目编号", example = "1024")
private Long subjectId;
@Schema(description = "取数规则", example = "0")
private Integer formulaRule;
@Schema(description = "取数时间类型", example = "1")
private Integer timeType;
@Schema(description = "结转科目规则数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<SubjectRule> subjects;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer sort;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "管理后台 - FMS 结账模板科目规则")
@Data
public static class SubjectRule {
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long subjectId;
@Schema(description = "科目编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "560107")
private String subjectCode;
@Schema(description = "摘要", requiredMode = Schema.RequiredMode.REQUIRED, example = "报销差旅费")
private String digest;
@Schema(description = "借贷方向", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer direction;
@Schema(description = "金额比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private BigDecimal amountRatio;
}
}
@@ -1,92 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.closing.FmsClosingTemplateCategoryEnum;
import cn.iocoder.yudao.module.fms.enums.closing.FmsClosingTimeTypeEnum;
import cn.iocoder.yudao.module.fms.enums.common.FmsDebitCreditDirectionEnum;
import cn.iocoder.yudao.module.fms.enums.report.FmsFormulaRuleEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - FMS 结账模板保存 Request VO")
@Data
public class FmsClosingTemplateSaveReqVO {
@Schema(description = "模板编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账套不能为空")
private Long accountSetId;
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "报销差旅费")
@NotBlank(message = "模板名称不能为空")
@Size(max = 255, message = "模板名称长度不能超过 255 个字符")
private String name;
@Schema(description = "模板分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "模板分类不能为空")
@InEnum(FmsClosingTemplateCategoryEnum.class)
private Integer category;
@Schema(description = "是否期末结转", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "是否期末结转不能为空")
private Boolean periodEnd;
@Schema(description = "来源科目编号", example = "1024")
private Long subjectId;
@Schema(description = "取数规则", example = "0")
@InEnum(FmsFormulaRuleEnum.class)
private Integer formulaRule;
@Schema(description = "取数时间类型", example = "1")
@InEnum(FmsClosingTimeTypeEnum.class)
private Integer timeType;
@Schema(description = "结转科目规则数组", requiredMode = Schema.RequiredMode.REQUIRED)
@Valid
@NotEmpty(message = "结转科目规则不能为空")
@Size(min = 2, message = "结转科目规则至少需要两条")
private List<SubjectRule> subjects;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "显示顺序不能为空")
private Integer sort;
@Schema(description = "管理后台 - FMS 结账模板科目规则")
@Data
public static class SubjectRule {
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "科目不能为空")
private Long subjectId;
@Schema(description = "摘要", requiredMode = Schema.RequiredMode.REQUIRED, example = "报销差旅费")
@NotBlank(message = "摘要不能为空")
@Size(max = 500, message = "摘要长度不能超过 500 个字符")
private String digest;
@Schema(description = "借贷方向", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "借贷方向不能为空")
@InEnum(FmsDebitCreditDirectionEnum.class)
private Integer direction;
@Schema(description = "金额比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "金额比例不能为空")
@DecimalMin(value = "0", inclusive = false, message = "金额比例必须大于 0")
@DecimalMax(value = "100", message = "金额比例不能超过 100")
private BigDecimal amountRatio;
}
}
@@ -1,29 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - FMS 批量生成结转凭证 Request VO")
@Data
public class FmsClosingVoucherGenerateReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账套不能为空")
private Long accountSetId;
@Schema(description = "方案编号数组", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "方案编号不能为空")
private List<@NotNull(message = "方案编号不能为空") Long> ids;
@Schema(description = "会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
@NotBlank(message = "会计期间不能为空")
@Pattern(regexp = "\\d{4}-(0[1-9]|1[0-2])", message = "会计期间格式不正确")
private String month;
}
@@ -1,22 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@Schema(description = "管理后台 - FMS 生成结转损益凭证 Request VO")
@Data
public class FmsProfitLossGenerateReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套不能为空")
private Long accountSetId;
@Schema(description = "会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
@NotBlank(message = "会计期间不能为空")
@Pattern(regexp = "\\d{4}-(0[1-9]|1[0-2])", message = "会计期间格式不正确")
private String month;
}
@@ -1,60 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.closing.FmsClosingVoucherTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - FMS 结转损益设置保存 Request VO")
@Data
public class FmsProfitLossSettingsSaveReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套不能为空")
private Long accountSetId;
@Schema(description = "凭证字编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11")
@NotNull(message = "凭证字不能为空")
private Long voucherWordId;
@Schema(description = "凭证摘要", requiredMode = Schema.RequiredMode.REQUIRED, example = "结转损益")
@NotBlank(message = "凭证摘要不能为空")
@Size(max = 500, message = "凭证摘要长度不能超过 500 个字符")
private String digest;
@Schema(description = "结转凭证类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "结转凭证类型不能为空")
@InEnum(FmsClosingVoucherTypeEnum.class)
private Integer voucherType;
@Schema(description = "以前年度损益调整科目编号", requiredMode = Schema.RequiredMode.REQUIRED,
example = "1024")
@NotNull(message = "以前年度损益调整科目不能为空")
private Long priorYearAdjustmentSubjectId;
@Schema(description = "以前年度损益调整结转科目编号", requiredMode = Schema.RequiredMode.REQUIRED,
example = "1025")
@NotNull(message = "以前年度损益调整结转科目不能为空")
private Long adjustmentClosingSubjectId;
@Schema(description = "其他损益结转科目编号", requiredMode = Schema.RequiredMode.REQUIRED,
example = "1026")
@NotNull(message = "其他损益结转科目不能为空")
private Long otherClosingSubjectId;
@Schema(description = "是否按余额反向结转", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "结转方式不能为空")
private Boolean reverseBalance;
@Schema(description = "结转日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "31")
@NotNull(message = "结转日期不能为空")
@Min(value = 1, message = "结转日期不能小于 1")
@Max(value = 31, message = "结转日期不能大于 31")
private Integer closingDay;
}
@@ -1,65 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.closing.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.common.FmsDebitCreditDirectionEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - FMS 专用结转设置保存 Request VO")
@Data
public class FmsSpecialClosingSettingsSaveReqVO {
@Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "方案编号不能为空")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账套不能为空")
private Long accountSetId;
@Schema(description = "凭证字编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11")
@NotNull(message = "凭证字不能为空")
private Long voucherWordId;
@Schema(description = "结转科目规则数组", requiredMode = Schema.RequiredMode.REQUIRED)
@Valid
@NotEmpty(message = "结转科目规则不能为空")
@Size(min = 2, message = "结转科目规则至少需要两条")
private List<SubjectRule> subjects;
@Schema(description = "管理后台 - FMS 专用结转科目规则")
@Data
public static class SubjectRule {
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "科目不能为空")
private Long subjectId;
@Schema(description = "摘要", requiredMode = Schema.RequiredMode.REQUIRED, example = "计提所得税")
@NotBlank(message = "摘要不能为空")
@Size(max = 500, message = "摘要长度不能超过 500 个字符")
private String digest;
@Schema(description = "借贷方向", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "借贷方向不能为空")
@InEnum(FmsDebitCreditDirectionEnum.class)
private Integer direction;
@Schema(description = "金额比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "25")
@NotNull(message = "金额比例不能为空")
@DecimalMin(value = "0", inclusive = false, message = "金额比例必须大于 0")
@DecimalMax(value = "100", message = "金额比例不能超过 100")
private BigDecimal amountRatio;
}
}
@@ -1,105 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.accountset.FmsAccountSetInitializeReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.accountset.FmsAccountSetRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.accountset.FmsAccountSetSaveReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsAccountSetDO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsAccountUserDO;
import cn.iocoder.yudao.module.fms.service.config.FmsAccountSetService;
import cn.iocoder.yudao.module.fms.service.config.FmsAccountUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 账套")
@RestController
@RequestMapping("/fms/config/account-set")
@Validated
public class FmsAccountSetController {
@Resource
private FmsAccountSetService accountSetService;
@Resource
private FmsAccountUserService accountUserService;
@PostMapping("/create")
@Operation(summary = "创建账套")
@PreAuthorize("@ss.hasPermission('fms:config:account-set:create')")
public CommonResult<Long> createAccountSet(@Valid @RequestBody FmsAccountSetSaveReqVO createReqVO) {
return success(accountSetService.createAccountSet(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "更新账套")
@PreAuthorize("@ss.hasPermission('fms:config:account-set:update')")
public CommonResult<Boolean> updateAccountSet(@Valid @RequestBody FmsAccountSetSaveReqVO updateReqVO) {
accountSetService.updateAccountSet(updateReqVO, getLoginUserId());
return success(true);
}
@PutMapping("/initialize")
@Operation(summary = "初始化账套")
@PreAuthorize("@ss.hasPermission('fms:config:account-set:initialize')")
public CommonResult<Boolean> initializeAccountSet(
@Valid @RequestBody FmsAccountSetInitializeReqVO initializeReqVO) {
accountSetService.initializeAccountSet(initializeReqVO, getLoginUserId());
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得账套")
@Parameter(name = "id", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:account-set:query')")
public CommonResult<FmsAccountSetRespVO> getAccountSet(@RequestParam("id") Long id) {
FmsAccountSetDO accountSet = accountSetService.validateAccountSetReadPermission(id, getLoginUserId());
FmsAccountUserDO accountUser = accountUserService.getAccountUser(id, getLoginUserId());
return success(buildAccountSetRespVO(accountSet, accountUser));
}
@GetMapping("/list")
@Operation(summary = "获得当前用户账套列表")
@PreAuthorize("@ss.hasPermission('fms:config:account-set:query')")
public CommonResult<List<FmsAccountSetRespVO>> getAccountSetList() {
List<FmsAccountUserDO> accountUsers = accountUserService.getAccountUserList(getLoginUserId());
Map<Long, FmsAccountSetDO> accountSetMap = accountSetService.getAccountSetMap(
convertSet(accountUsers, FmsAccountUserDO::getAccountSetId));
return success(buildAccountSetRespVOList(accountSetMap, accountUsers));
}
// ==================== 拼接 VO ====================
private FmsAccountSetRespVO buildAccountSetRespVO(
FmsAccountSetDO accountSet, FmsAccountUserDO accountUser) {
return BeanUtils.toBean(accountSet, FmsAccountSetRespVO.class)
.setDefaultStatus(accountUser.getDefaultStatus()).setFounder(accountUser.getFounder())
.setLevel(accountUser.getLevel());
}
private List<FmsAccountSetRespVO> buildAccountSetRespVOList(
Map<Long, FmsAccountSetDO> accountSetMap, List<FmsAccountUserDO> accountUsers) {
return convertList(accountUsers, accountUser -> buildAccountSetRespVO(
accountSetMap.get(accountUser.getAccountSetId()), accountUser));
}
}
@@ -1,95 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.accountuser.FmsAccountUserRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.accountuser.FmsAccountUserUpdateReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsAccountUserDO;
import cn.iocoder.yudao.module.fms.service.config.FmsAccountUserService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 账套用户")
@RestController
@RequestMapping("/fms/config/account-user")
@Validated
public class FmsAccountUserController {
@Resource
private FmsAccountUserService accountUserService;
@Resource
private AdminUserApi adminUserApi;
@Resource
private DeptApi deptApi;
@GetMapping("/list")
@Operation(summary = "获得账套用户列表")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:account-set:authorize')")
public CommonResult<List<FmsAccountUserRespVO>> getAccountUserList(
@RequestParam("accountSetId") Long accountSetId) {
List<FmsAccountUserDO> accountUsers = accountUserService.getAccountUserList(
accountSetId, getLoginUserId());
return success(buildAccountUserRespVOList(accountUsers));
}
@PutMapping("/update")
@Operation(summary = "更新账套用户列表")
@PreAuthorize("@ss.hasPermission('fms:config:account-set:authorize')")
public CommonResult<Boolean> updateAccountUserList(
@Valid @RequestBody FmsAccountUserUpdateReqVO updateReqVO) {
accountUserService.updateAccountUserList(updateReqVO, getLoginUserId());
return success(true);
}
@PutMapping("/update-default-status")
@Operation(summary = "更新默认账套状态")
@PreAuthorize("@ss.hasPermission('fms:config:account-set:query')")
public CommonResult<Boolean> updateAccountSetDefaultStatus(@RequestParam("accountSetId") Long accountSetId) {
accountUserService.updateAccountSetDefaultStatus(accountSetId, getLoginUserId());
return success(true);
}
// ==================== 拼接 VO ====================
private List<FmsAccountUserRespVO> buildAccountUserRespVOList(List<FmsAccountUserDO> accountUsers) {
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSet(accountUsers, FmsAccountUserDO::getUserId));
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(
convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
return convertList(accountUsers, accountUser -> {
FmsAccountUserRespVO respVO = BeanUtils.toBean(accountUser, FmsAccountUserRespVO.class);
findAndThen(userMap, accountUser.getUserId(), user -> {
respVO.setNickname(user.getNickname()).setMobile(user.getMobile())
.setEmail(user.getEmail()).setStatus(user.getStatus());
findAndThen(deptMap, user.getDeptId(), dept -> respVO.setDeptName(dept.getName()));
});
return respVO;
});
}
}
@@ -1,228 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem.FmsAuxiliaryItemImportExcelVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem.FmsAuxiliaryItemImportRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem.FmsAuxiliaryItemPageReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem.FmsAuxiliaryItemRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem.FmsAuxiliaryItemSaveReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem.FmsAuxiliaryItemStatusReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsAuxiliaryItemDO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsAuxiliaryTypeDO;
import cn.iocoder.yudao.module.fms.enums.config.FmsAuxiliaryTypeEnum;
import cn.iocoder.yudao.module.fms.service.config.FmsAuxiliaryItemService;
import cn.iocoder.yudao.module.fms.service.config.FmsAuxiliaryTypeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 辅助核算项目")
@RestController
@RequestMapping("/fms/config/auxiliary-item")
@Validated
public class FmsAuxiliaryItemController {
@Resource
private FmsAuxiliaryItemService auxiliaryItemService;
@Resource
private FmsAuxiliaryTypeService auxiliaryTypeService;
@PostMapping("/create")
@Operation(summary = "创建辅助核算项目")
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:create')")
public CommonResult<Long> createAuxiliaryItem(@Valid @RequestBody FmsAuxiliaryItemSaveReqVO createReqVO) {
return success(auxiliaryItemService.createAuxiliaryItem(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "更新辅助核算项目")
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:update')")
public CommonResult<Boolean> updateAuxiliaryItem(
@Valid @RequestBody FmsAuxiliaryItemSaveReqVO updateReqVO) {
auxiliaryItemService.updateAuxiliaryItem(updateReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "删除辅助核算项目")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024"),
@Parameter(name = "ids", description = "辅助核算项目编号数组", required = true, example = "[1024]")
})
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:delete')")
public CommonResult<Boolean> deleteAuxiliaryItemList(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("ids") @NotEmpty List<Long> ids) {
auxiliaryItemService.deleteAuxiliaryItemList(accountSetId, ids, getLoginUserId());
return success(true);
}
@PutMapping("/update-status")
@Operation(summary = "更新辅助核算项目状态")
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:update')")
public CommonResult<Boolean> updateAuxiliaryItemStatus(
@Valid @RequestBody FmsAuxiliaryItemStatusReqVO reqVO) {
auxiliaryItemService.updateAuxiliaryItemStatus(
reqVO.getAccountSetId(), reqVO.getId(), reqVO.getStatus(), getLoginUserId());
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得辅助核算项目")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024"),
@Parameter(name = "id", description = "辅助核算项目编号", required = true, example = "1024")
})
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:query')")
public CommonResult<FmsAuxiliaryItemRespVO> getAuxiliaryItem(@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
FmsAuxiliaryItemDO item = auxiliaryItemService.getAuxiliaryItem(accountSetId, id, getLoginUserId());
return success(BeanUtils.toBean(item, FmsAuxiliaryItemRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得辅助核算项目分页")
@PreAuthorize("@ss.hasAnyPermissions('fms:config:auxiliary:query', 'fms:voucher:create', "
+ "'fms:voucher:update')")
public CommonResult<PageResult<FmsAuxiliaryItemRespVO>> getAuxiliaryItemPage(
@Valid FmsAuxiliaryItemPageReqVO pageReqVO) {
PageResult<FmsAuxiliaryItemDO> pageResult = auxiliaryItemService
.getAuxiliaryItemPage(pageReqVO, getLoginUserId());
return success(BeanUtils.toBean(pageResult, FmsAuxiliaryItemRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得辅助核算项目精简列表", description = "只包含启用的项目,主要用于前端下拉选项")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024"),
@Parameter(name = "auxiliaryTypeId", description = "辅助核算类别编号", required = true,
example = "1024")
})
public CommonResult<List<FmsAuxiliaryItemRespVO>> getAuxiliaryItemSimpleList(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("auxiliaryTypeId") @NotNull Long auxiliaryTypeId) {
List<FmsAuxiliaryItemDO> list = auxiliaryItemService
.getAuxiliaryItemListByAccountSetIdAndAuxiliaryTypeIdAndStatus(
accountSetId, auxiliaryTypeId, CommonStatusEnum.ENABLE.getStatus(), getLoginUserId());
return success(convertList(list, item -> new FmsAuxiliaryItemRespVO()
.setId(item.getId()).setCode(item.getCode()).setName(item.getName())));
}
@GetMapping("/export-excel")
@Operation(summary = "导出辅助核算项目")
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportAuxiliaryItemExcel(
@Valid FmsAuxiliaryItemPageReqVO pageReqVO, HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<FmsAuxiliaryItemDO> list = auxiliaryItemService
.getAuxiliaryItemPage(pageReqVO, getLoginUserId()).getList();
FmsAuxiliaryTypeDO auxiliaryType = auxiliaryTypeService.getAuxiliaryType(
pageReqVO.getAccountSetId(), pageReqVO.getAuxiliaryTypeId(), getLoginUserId());
ExcelUtils.write(response, auxiliaryType.getName() + ".xlsx", "辅助核算项目",
buildAuxiliaryItemExcelHead(auxiliaryType.getType()), buildAuxiliaryItemExcelData(list,
auxiliaryType.getType()));
}
@GetMapping("/get-import-template")
@Operation(summary = "获得辅助核算项目导入模板")
@Parameter(name = "type", description = "辅助核算类别类型", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:import')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void getAuxiliaryItemImportTemplate(
@RequestParam("type") @InEnum(FmsAuxiliaryTypeEnum.class) Integer type,
HttpServletResponse response) throws IOException {
FmsAuxiliaryItemImportExcelVO example = new FmsAuxiliaryItemImportExcelVO()
.setCode("001").setName("示例项目").setRemark("示例备注");
if (FmsAuxiliaryTypeEnum.INVENTORY.getType().equals(type)) {
example.setSpecification("标准版").setUnit("个");
}
ExcelUtils.write(response, "辅助核算项目导入模板.xlsx", "辅助核算项目",
FmsAuxiliaryItemImportExcelVO.class, Collections.singletonList(example));
}
@PostMapping("/import")
@Operation(summary = "导入辅助核算项目")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true),
@Parameter(name = "auxiliaryTypeId", description = "辅助核算类别编号", required = true),
@Parameter(name = "file", description = "Excel 文件", required = true)
})
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:import')")
@ApiAccessLog(operateType = OperateTypeEnum.IMPORT)
public CommonResult<FmsAuxiliaryItemImportRespVO> importAuxiliaryItem(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("auxiliaryTypeId") @NotNull Long auxiliaryTypeId,
@RequestParam("file") MultipartFile file) throws Exception {
List<FmsAuxiliaryItemImportExcelVO> importItems = ExcelUtils.read(
file, FmsAuxiliaryItemImportExcelVO.class);
return success(auxiliaryItemService.importAuxiliaryItemList(
accountSetId, auxiliaryTypeId, importItems, getLoginUserId()));
}
/** 构建辅助核算项目导出的动态表头 */
private List<List<String>> buildAuxiliaryItemExcelHead(Integer type) {
if (FmsAuxiliaryTypeEnum.CUSTOMER.getType().equals(type)
|| FmsAuxiliaryTypeEnum.SUPPLIER.getType().equals(type)) {
return Arrays.asList(Collections.singletonList("编码"), Collections.singletonList("名称"),
Collections.singletonList("备注"));
}
if (FmsAuxiliaryTypeEnum.INVENTORY.getType().equals(type)) {
return Arrays.asList(Collections.singletonList("编码"), Collections.singletonList("名称"),
Collections.singletonList("规格"), Collections.singletonList("单位"));
}
return Arrays.asList(Collections.singletonList("编码"), Collections.singletonList("名称"));
}
/** 构建辅助核算项目导出的动态数据 */
private List<List<Object>> buildAuxiliaryItemExcelData(List<FmsAuxiliaryItemDO> items, Integer type) {
List<List<Object>> rows = new ArrayList<>(items.size());
for (FmsAuxiliaryItemDO item : items) {
if (FmsAuxiliaryTypeEnum.CUSTOMER.getType().equals(type)
|| FmsAuxiliaryTypeEnum.SUPPLIER.getType().equals(type)) {
rows.add(Arrays.asList(item.getCode(), item.getName(), item.getRemark()));
} else if (FmsAuxiliaryTypeEnum.INVENTORY.getType().equals(type)) {
rows.add(Arrays.asList(item.getCode(), item.getName(), item.getSpecification(), item.getUnit()));
} else {
rows.add(Arrays.asList(item.getCode(), item.getName()));
}
}
return rows;
}
}
@@ -1,92 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliarytype.FmsAuxiliaryTypeRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliarytype.FmsAuxiliaryTypeSaveReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsAuxiliaryTypeDO;
import cn.iocoder.yudao.module.fms.service.config.FmsAuxiliaryTypeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 辅助核算类别")
@RestController
@RequestMapping("/fms/config/auxiliary-type")
@Validated
public class FmsAuxiliaryTypeController {
@Resource
private FmsAuxiliaryTypeService auxiliaryTypeService;
@PostMapping("/create")
@Operation(summary = "创建辅助核算类别")
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:create')")
public CommonResult<Long> createAuxiliaryType(@Valid @RequestBody FmsAuxiliaryTypeSaveReqVO createReqVO) {
return success(auxiliaryTypeService.createAuxiliaryType(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "更新辅助核算类别")
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:update')")
public CommonResult<Boolean> updateAuxiliaryType(@Valid @RequestBody FmsAuxiliaryTypeSaveReqVO updateReqVO) {
auxiliaryTypeService.updateAuxiliaryType(updateReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除辅助核算类别")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024"),
@Parameter(name = "id", description = "辅助核算类别编号", required = true, example = "1024")
})
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:delete')")
public CommonResult<Boolean> deleteAuxiliaryType(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
auxiliaryTypeService.deleteAuxiliaryType(accountSetId, id, getLoginUserId());
return success(true);
}
@GetMapping("/list")
@Operation(summary = "获得辅助核算类别列表")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:auxiliary:query')")
public CommonResult<List<FmsAuxiliaryTypeRespVO>> getAuxiliaryTypeList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
return success(BeanUtils.toBean(auxiliaryTypeService.getAuxiliaryTypeList(
accountSetId, getLoginUserId()), FmsAuxiliaryTypeRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得辅助核算类别精简列表", description = "主要用于前端的下拉选项")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
public CommonResult<List<FmsAuxiliaryTypeRespVO>> getAuxiliaryTypeSimpleList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
List<FmsAuxiliaryTypeDO> list = auxiliaryTypeService.getAuxiliaryTypeList(
accountSetId, getLoginUserId());
return success(convertList(list, auxiliaryType -> new FmsAuxiliaryTypeRespVO()
.setId(auxiliaryType.getId()).setName(auxiliaryType.getName()).setType(auxiliaryType.getType())));
}
}
@@ -1,92 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.currency.FmsCurrencyRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.currency.FmsCurrencySaveReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsCurrencyDO;
import cn.iocoder.yudao.module.fms.service.config.FmsCurrencyService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 币别")
@RestController
@RequestMapping("/fms/config/currency")
@Validated
public class FmsCurrencyController {
@Resource
private FmsCurrencyService currencyService;
@PostMapping("/create")
@Operation(summary = "创建币别")
@PreAuthorize("@ss.hasPermission('fms:config:currency:create')")
public CommonResult<Long> createCurrency(@Valid @RequestBody FmsCurrencySaveReqVO createReqVO) {
return success(currencyService.createCurrency(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "更新币别")
@PreAuthorize("@ss.hasPermission('fms:config:currency:update')")
public CommonResult<Boolean> updateCurrency(@Valid @RequestBody FmsCurrencySaveReqVO updateReqVO) {
currencyService.updateCurrency(updateReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除币别")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024"),
@Parameter(name = "id", description = "币别编号", required = true, example = "1024")
})
@PreAuthorize("@ss.hasPermission('fms:config:currency:delete')")
public CommonResult<Boolean> deleteCurrency(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
currencyService.deleteCurrency(accountSetId, id, getLoginUserId());
return success(true);
}
@GetMapping("/list")
@Operation(summary = "获得币别列表")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:currency:query')")
public CommonResult<List<FmsCurrencyRespVO>> getCurrencyList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
List<FmsCurrencyDO> list = currencyService.getCurrencyList(accountSetId, getLoginUserId());
return success(BeanUtils.toBean(list, FmsCurrencyRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得币别精简列表", description = "主要用于前端的下拉选项")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
public CommonResult<List<FmsCurrencyRespVO>> getCurrencySimpleList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
List<FmsCurrencyDO> list = currencyService.getCurrencyList(accountSetId, getLoginUserId());
return success(convertList(list, currency -> new FmsCurrencyRespVO()
.setId(currency.getId()).setCode(currency.getCode()).setName(currency.getName())
.setExchangeRate(currency.getExchangeRate()).setStandard(currency.getStandard())));
}
}
@@ -1,91 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.digest.FmsDigestRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.digest.FmsDigestSaveReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsDigestDO;
import cn.iocoder.yudao.module.fms.service.config.FmsDigestService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
/**
* FMS 常用摘要 Controller
*
* @author 芋道源码
*/
@Tag(name = "管理后台 - FMS 常用摘要")
@RestController
@RequestMapping("/fms/config/digest")
@Validated
public class FmsDigestController {
@Resource
private FmsDigestService digestService;
@PostMapping("/create")
@Operation(summary = "创建常用摘要")
@PreAuthorize("@ss.hasPermission('fms:config:digest:create')")
public CommonResult<Long> createDigest(@Valid @RequestBody FmsDigestSaveReqVO createReqVO) {
return success(digestService.createDigest(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "修改常用摘要")
@PreAuthorize("@ss.hasPermission('fms:config:digest:update')")
public CommonResult<Boolean> updateDigest(@Valid @RequestBody FmsDigestSaveReqVO updateReqVO) {
digestService.updateDigest(updateReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除常用摘要")
@Parameter(name = "id", description = "常用摘要编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:digest:delete')")
public CommonResult<Boolean> deleteDigest(@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
digestService.deleteDigest(accountSetId, id, getLoginUserId());
return success(true);
}
@GetMapping("/list")
@Operation(summary = "获得常用摘要管理列表")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:digest:query')")
public CommonResult<List<FmsDigestRespVO>> getDigestList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
List<FmsDigestDO> list = digestService.getDigestList(accountSetId, getLoginUserId());
return success(BeanUtils.toBean(list, FmsDigestRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得常用摘要精简列表")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
public CommonResult<List<FmsDigestRespVO>> getDigestSimpleList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
List<FmsDigestDO> list = digestService.getDigestList(accountSetId, getLoginUserId());
return success(convertList(list, digest -> new FmsDigestRespVO()
.setId(digest.getId()).setAccountSetId(digest.getAccountSetId()).setContent(digest.getContent())));
}
}
@@ -1,86 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.financeindicator.FmsFinanceIndicatorRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.financeindicator.FmsFinanceIndicatorSaveReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsFinanceIndicatorDO;
import cn.iocoder.yudao.module.fms.service.config.FmsFinanceIndicatorService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 财务指标")
@RestController
@RequestMapping("/fms/config/finance-indicator")
@Validated
public class FmsFinanceIndicatorController {
@Resource
private FmsFinanceIndicatorService financeIndicatorService;
@PostMapping("/create")
@Operation(summary = "创建首页财务指标")
@PreAuthorize("@ss.hasPermission('fms:config:finance-indicator:create')")
public CommonResult<Long> create(@Valid @RequestBody FmsFinanceIndicatorSaveReqVO reqVO) {
return success(financeIndicatorService.createFinanceIndicator(reqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "修改首页财务指标")
@PreAuthorize("@ss.hasPermission('fms:config:finance-indicator:update')")
public CommonResult<Boolean> update(@Valid @RequestBody FmsFinanceIndicatorSaveReqVO reqVO) {
financeIndicatorService.updateFinanceIndicator(reqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除首页财务指标")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@Parameter(name = "id", description = "指标编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:finance-indicator:delete')")
public CommonResult<Boolean> delete(@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
financeIndicatorService.deleteFinanceIndicator(accountSetId, id, getLoginUserId());
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得首页财务指标")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@Parameter(name = "id", description = "指标编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:finance-indicator:query')")
public CommonResult<FmsFinanceIndicatorRespVO> get(@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
FmsFinanceIndicatorDO indicator = financeIndicatorService.getFinanceIndicator(accountSetId, id, getLoginUserId());
return success(BeanUtils.toBean(indicator, FmsFinanceIndicatorRespVO.class));
}
@GetMapping("/list")
@Operation(summary = "获得首页财务指标列表")
@PreAuthorize("@ss.hasPermission('fms:config:finance-indicator:query')")
public CommonResult<List<FmsFinanceIndicatorRespVO>> getList(@RequestParam("accountSetId") @NotNull Long accountSetId) {
List<FmsFinanceIndicatorDO> list = financeIndicatorService.getFinanceIndicatorList(accountSetId,
getLoginUserId());
return success(BeanUtils.toBean(list, FmsFinanceIndicatorRespVO.class));
}
}
@@ -1,55 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.financeparameter.FmsFinanceParameterRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.financeparameter.FmsFinanceParameterUpdateReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsFinanceParameterDO;
import cn.iocoder.yudao.module.fms.service.config.FmsFinanceParameterService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 财务参数")
@RestController
@RequestMapping("/fms/config/finance-parameter")
@Validated
public class FmsFinanceParameterController {
@Resource
private FmsFinanceParameterService financeParameterService;
@GetMapping("/get")
@Operation(summary = "获得财务参数")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:finance-parameter:query')")
public CommonResult<FmsFinanceParameterRespVO> getFinanceParameter(
@RequestParam("accountSetId") Long accountSetId) {
FmsFinanceParameterDO financeParameter = financeParameterService.getFinanceParameter(
accountSetId, getLoginUserId());
return success(BeanUtils.toBean(financeParameter, FmsFinanceParameterRespVO.class));
}
@PutMapping("/update")
@Operation(summary = "更新财务参数")
@PreAuthorize("@ss.hasPermission('fms:config:finance-parameter:update')")
public CommonResult<Boolean> updateFinanceParameter(
@Valid @RequestBody FmsFinanceParameterUpdateReqVO updateReqVO) {
financeParameterService.updateFinanceParameter(updateReqVO, getLoginUserId());
return success(true);
}
}
@@ -1,136 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance.FmsInitialBalanceRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance.FmsInitialBalanceSaveReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance.FmsTrialBalanceRespVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsAccountSetDO;
import cn.iocoder.yudao.module.fms.service.config.FmsAccountSetService;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance.FmsInitialBalanceExcelVO;
import cn.iocoder.yudao.module.fms.service.config.FmsInitialBalanceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.fms.enums.ErrorCodeConstants.INITIAL_BALANCE_IMPORT_TEMPLATE_INVALID;
@Tag(name = "管理后台 - FMS 初始余额")
@RestController
@RequestMapping("/fms/config/initial-balance")
@Validated
public class FmsInitialBalanceController {
@Resource
private FmsInitialBalanceService initialBalanceService;
@Resource
private FmsAccountSetService accountSetService;
@GetMapping("/list")
@Operation(summary = "获得初始余额列表")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@Parameter(name = "subjectType", description = "科目类型", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('fms:config:initial-balance:query')")
public CommonResult<List<FmsInitialBalanceRespVO>> getInitialBalanceList(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("subjectType") @NotNull Integer subjectType) {
return success(initialBalanceService.getInitialBalanceList(accountSetId, subjectType, getLoginUserId()));
}
@PutMapping("/save")
@Operation(summary = "保存初始余额")
@PreAuthorize("@ss.hasPermission('fms:config:initial-balance:update')")
public CommonResult<Boolean> saveInitialBalance(@Valid @RequestBody FmsInitialBalanceSaveReqVO saveReqVO) {
initialBalanceService.saveInitialBalance(saveReqVO, getLoginUserId());
return success(true);
}
@GetMapping("/trial-balance")
@Operation(summary = "获得试算平衡结果")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:initial-balance:query')")
public CommonResult<FmsTrialBalanceRespVO> getTrialBalance(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
return success(initialBalanceService.getTrialBalance(accountSetId, getLoginUserId()));
}
@GetMapping("/export-excel")
@Operation(summary = "导出初始余额")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:initial-balance:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportInitialBalance(
@RequestParam("accountSetId") @NotNull Long accountSetId,
HttpServletResponse response) throws IOException {
// 1. 读取初始余额列表,并展开为 Excel 行
List<FmsInitialBalanceExcelVO> rows = FmsInitialBalanceExcelHelper.toRows(
initialBalanceService.getInitialBalanceList(accountSetId, null, getLoginUserId()), true);
// 2. 输出 Excel
ExcelUtils.write(response, "财务初始余额.xlsx", "财务初始余额",
FmsInitialBalanceExcelVO.class, rows);
}
@GetMapping("/get-import-template")
@Operation(summary = "获得初始余额导入模板")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:initial-balance:import')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void getInitialBalanceImportTemplate(@RequestParam("accountSetId") @NotNull Long accountSetId,
HttpServletResponse response)
throws IOException {
// 1. 读取初始余额列表,并展开为 Excel 行
Long userId = getLoginUserId();
List<FmsInitialBalanceRespVO> initialBalances = initialBalanceService.getInitialBalanceList(accountSetId, null, userId);
List<FmsInitialBalanceExcelVO> rows = FmsInitialBalanceExcelHelper.toRows(initialBalances, false);
// 2. 生成导入模板,一月启用时只需要录入期初余额
FmsAccountSetDO accountSet = accountSetService.validateAccountSetReadPermission(accountSetId, userId);
byte[] content = FmsInitialBalanceExcelHelper.writeTemplate(
rows, LocalDateTimeUtils.isJanuary(accountSet.getStartTime()));
// 3. 写入响应
ServletUtils.writeAttachment(response, "财务初始余额导入模板.xlsx", content);
}
@PostMapping("/import")
@Operation(summary = "导入初始余额")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:initial-balance:import')")
@ApiAccessLog(operateType = OperateTypeEnum.IMPORT)
public CommonResult<Integer> importInitialBalance(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("file") MultipartFile file) throws IOException {
// 1. 读取 Excel
List<FmsInitialBalanceExcelVO> rows;
try {
rows = FmsInitialBalanceExcelHelper.read(file);
} catch (IllegalArgumentException | IOException ex) {
throw exception(INITIAL_BALANCE_IMPORT_TEMPLATE_INVALID);
}
// 2. 导入数据
return success(initialBalanceService.importInitialBalance(accountSetId, rows, getLoginUserId()));
}
}
@@ -1,343 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance.FmsInitialBalanceRespVO;
import cn.iocoder.yudao.module.fms.enums.common.FmsDebitCreditDirectionEnum;
import cn.iocoder.yudao.module.fms.enums.config.FmsSubjectTypeEnum;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance.FmsInitialBalanceExcelVO;
import lombok.experimental.UtilityClass;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.number.NumberUtils.zeroIfNull;
import static cn.iocoder.yudao.framework.excel.core.util.PoiExcelUtils.createDataStyle;
import static cn.iocoder.yudao.framework.excel.core.util.PoiExcelUtils.createHeaderStyle;
import static cn.iocoder.yudao.framework.excel.core.util.PoiExcelUtils.createNumberStyle;
import static cn.iocoder.yudao.framework.excel.core.util.PoiExcelUtils.getCellText;
import static cn.iocoder.yudao.framework.excel.core.util.PoiExcelUtils.getDecimal;
import static cn.iocoder.yudao.framework.excel.core.util.PoiExcelUtils.isEmptyRow;
import static cn.iocoder.yudao.framework.excel.core.util.PoiExcelUtils.mergeHeader;
import static cn.iocoder.yudao.framework.excel.core.util.PoiExcelUtils.writeFormula;
import static cn.iocoder.yudao.framework.excel.core.util.PoiExcelUtils.writeNumber;
import static cn.iocoder.yudao.framework.excel.core.util.PoiExcelUtils.writeText;
/**
* FMS 初始余额 Excel 工具
*
* @author 芋道源码
*/
@UtilityClass
public final class FmsInitialBalanceExcelHelper {
private static final String TEMPLATE_SHEET_NAME = "初始余额模板";
/**
* 展开初始余额平铺列表为 Excel 行
*
* 父级科目仅在 includeParent 时输出行;启用辅助核算且存在明细的科目按明细逐行输出
*/
public static List<FmsInitialBalanceExcelVO> toRows(List<FmsInitialBalanceRespVO> results,
boolean includeParent) {
Set<Long> parentIds = convertSet(results, FmsInitialBalanceRespVO::getParentId);
List<FmsInitialBalanceExcelVO> rows = new ArrayList<>();
results.forEach(result -> {
if (parentIds.contains(result.getSubjectId())) {
if (includeParent) {
rows.add(buildRow(result, null));
}
return;
}
if (Boolean.FALSE.equals(result.getAuxiliaryAccounting())
|| CollUtil.isEmpty(result.getAssistBalances())) {
rows.add(buildRow(result, null));
return;
}
result.getAssistBalances().forEach(assist -> rows.add(buildRow(result, assist)));
});
return rows;
}
/**
* 构建单个科目或辅助核算明细对应的 Excel 行
*/
private static FmsInitialBalanceExcelVO buildRow(FmsInitialBalanceRespVO result,
FmsInitialBalanceRespVO.AssistBalance assist) {
FmsInitialBalanceExcelVO row = new FmsInitialBalanceExcelVO()
.setSubjectCode(result.getSubjectCode()).setSubjectName(result.getSubjectName())
.setDirectionName(FmsDebitCreditDirectionEnum.valueOf(result.getBalanceDirection()).getName())
.setSubjectType(result.getType()).setQuantityAccounting(result.getQuantityAccounting())
.setAuxiliaryAccounting(result.getAuxiliaryAccounting());
if (assist == null) {
copyAmounts(result, row);
} else {
// 辅助核算项目拼接为“类别:名称/类别:名称”,与导入解析的格式对应
Map<Long, String> auxiliaryTypeNameMap = convertMap(result.getAuxiliaryConfigs(),
FmsInitialBalanceRespVO.AuxiliaryConfig::getAuxiliaryTypeId,
FmsInitialBalanceRespVO.AuxiliaryConfig::getName);
row.setAuxiliaryItems(String.join("/", convertList(assist.getAuxiliaries(),
item -> auxiliaryTypeNameMap.get(item.getTypeId()) + ":" + item.getName())));
copyAmounts(assist, row);
}
return row;
}
private static void copyAmounts(FmsInitialBalanceRespVO source, FmsInitialBalanceExcelVO target) {
target.setOpeningAmount(zeroIfNull(source.getOpeningAmount()))
.setOpeningQuantity(zeroIfNull(source.getOpeningQuantity()))
.setYearDebitAmount(zeroIfNull(source.getYearDebitAmount()))
.setYearDebitQuantity(zeroIfNull(source.getYearDebitQuantity()))
.setYearCreditAmount(zeroIfNull(source.getYearCreditAmount()))
.setYearCreditQuantity(zeroIfNull(source.getYearCreditQuantity()))
.setYearOpeningAmount(zeroIfNull(source.getYearOpeningAmount()))
.setYearOpeningQuantity(zeroIfNull(source.getYearOpeningQuantity()))
.setProfitLossAmount(zeroIfNull(source.getProfitLossAmount()))
.setProfitLossQuantity(zeroIfNull(source.getProfitLossQuantity()));
}
private static void copyAmounts(FmsInitialBalanceRespVO.AssistBalance source,
FmsInitialBalanceExcelVO target) {
target.setOpeningAmount(zeroIfNull(source.getOpeningAmount()))
.setOpeningQuantity(zeroIfNull(source.getOpeningQuantity()))
.setYearDebitAmount(zeroIfNull(source.getYearDebitAmount()))
.setYearDebitQuantity(zeroIfNull(source.getYearDebitQuantity()))
.setYearCreditAmount(zeroIfNull(source.getYearCreditAmount()))
.setYearCreditQuantity(zeroIfNull(source.getYearCreditQuantity()))
.setYearOpeningAmount(zeroIfNull(source.getYearOpeningAmount()))
.setYearOpeningQuantity(zeroIfNull(source.getYearOpeningQuantity()))
.setProfitLossAmount(zeroIfNull(source.getProfitLossAmount()))
.setProfitLossQuantity(zeroIfNull(source.getProfitLossQuantity()));
}
/**
* 生成导入模板
*
* 模板锁定系统生成列,年初余额列写入公式,并通过 protectSheet 防止误改
*/
public static byte[] writeTemplate(List<FmsInitialBalanceExcelVO> rows,
boolean january) throws IOException {
try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream output = new ByteArrayOutputStream()) {
// 1. 写入表头,一月启用时只保留期初余额
Sheet sheet = workbook.createSheet(TEMPLATE_SHEET_NAME);
writeHeaders(workbook, sheet, 0, january);
// 2. 写入科目数据,系统生成列锁定,可填写列解锁
CellStyle lockedStyle = createDataStyle(workbook, true, IndexedColors.GREY_25_PERCENT);
CellStyle editableStyle = createDataStyle(workbook, false, IndexedColors.WHITE);
CellStyle numberLockedStyle = createNumberStyle(workbook, lockedStyle, "#,##0.0000");
CellStyle amountLockedStyle = createNumberStyle(workbook, lockedStyle, "#,##0.00");
CellStyle numberEditableStyle = createNumberStyle(workbook, editableStyle, "#,##0.0000");
CellStyle amountEditableStyle = createNumberStyle(workbook, editableStyle, "#,##0.00");
for (int index = 0; index < rows.size(); index++) {
writeDataRow(sheet.createRow(index + 2), rows.get(index), january, true,
lockedStyle, editableStyle, numberLockedStyle, amountLockedStyle,
numberEditableStyle, amountEditableStyle);
}
// 3. 保护工作表并补充填写说明
sheet.protectSheet("yudao-fms");
sheet.createFreezePane(4, 2);
writeInstructions(workbook);
workbook.write(output);
return output.toByteArray();
}
}
/**
* 读取导入文件
*
* 按模板表头校验文件合法性,年初余额等公式单元格取公式计算值;不限制导入行数
*/
public static List<FmsInitialBalanceExcelVO> read(MultipartFile file) throws IOException {
try (Workbook workbook = WorkbookFactory.create(file.getInputStream())) {
// 1. 校验模板 sheet 和表头
Sheet sheet = workbook.getSheet(TEMPLATE_SHEET_NAME);
if (sheet == null || !hasValidHeaders(sheet)) {
throw new IllegalArgumentException("初始余额模板表头不正确");
}
// 2. 逐行解析,跳过空行
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
boolean january = sheet.getRow(1).getLastCellNum() <= 6;
List<FmsInitialBalanceExcelVO> rows = new ArrayList<>();
for (int rowIndex = 2; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
Row row = sheet.getRow(rowIndex);
if (isEmptyRow(row, evaluator, Arrays.asList(0, 1, 3, 4, 5))) {
continue;
}
rows.add(parseRow(row, january, evaluator));
}
return rows;
}
}
/**
* 写入双行表头,数量和金额成组;一月启用时只保留期初余额组
*/
private static void writeHeaders(Workbook workbook, Sheet sheet, int rowIndex, boolean january) {
CellStyle style = createHeaderStyle(workbook, IndexedColors.GREY_25_PERCENT);
int lastColumn = january ? 5 : 13;
Row firstRow = sheet.createRow(rowIndex);
Row secondRow = sheet.createRow(rowIndex + 1);
mergeHeader(sheet, firstRow, secondRow, 0, 0, "科目编码", style);
mergeHeader(sheet, firstRow, secondRow, 1, 1, "科目名称", style);
mergeHeader(sheet, firstRow, secondRow, 2, 2, "方向", style);
mergeHeader(sheet, firstRow, secondRow, 3, 3, "辅助核算项目", style);
writeGroupHeader(sheet, firstRow, secondRow, 4, "期初余额", style);
if (!january) {
writeGroupHeader(sheet, firstRow, secondRow, 6, "本年累计借方", style);
writeGroupHeader(sheet, firstRow, secondRow, 8, "本年累计贷方", style);
writeGroupHeader(sheet, firstRow, secondRow, 10, "年初余额", style);
writeGroupHeader(sheet, firstRow, secondRow, 12, "实际损益发生额", style);
}
for (int column = 0; column <= lastColumn; column++) {
sheet.setColumnWidth(column, column == 1 || column == 3 ? 7_000 : 4_000);
}
firstRow.setHeightInPoints(28);
secondRow.setHeightInPoints(24);
}
/**
* 写入“数量/金额”成组表头,第一行合并组名,第二行拆出数量和金额
*/
private static void writeGroupHeader(Sheet sheet, Row firstRow, Row secondRow,
int beginColumn, String title, CellStyle style) {
sheet.addMergedRegion(new CellRangeAddress(firstRow.getRowNum(), firstRow.getRowNum(), beginColumn, beginColumn + 1));
Cell groupCell = firstRow.createCell(beginColumn);
groupCell.setCellValue(title);
groupCell.setCellStyle(style);
firstRow.createCell(beginColumn + 1).setCellStyle(style);
Cell quantityCell = secondRow.createCell(beginColumn);
quantityCell.setCellValue("数量");
quantityCell.setCellStyle(style);
Cell amountCell = secondRow.createCell(beginColumn + 1);
amountCell.setCellValue("金额");
amountCell.setCellStyle(style);
}
/**
* 写入一行数据
*
* 模板模式下按科目配置解锁可填写单元格(数量列仅数量核算科目可填,损益列仅损益类科目可填),
* 年初余额列写入“期初 ± 累计借贷”公式
*/
private static void writeDataRow(Row excelRow, FmsInitialBalanceExcelVO data,
boolean january, boolean template, CellStyle lockedStyle, CellStyle editableStyle,
CellStyle numberLockedStyle, CellStyle amountLockedStyle,
CellStyle numberEditableStyle, CellStyle amountEditableStyle) {
writeText(excelRow, 0, data.getSubjectCode(), lockedStyle);
writeText(excelRow, 1, data.getSubjectName(), lockedStyle);
writeText(excelRow, 2, data.getDirectionName(), lockedStyle);
writeText(excelRow, 3, data.getAuxiliaryItems(),
template && Boolean.TRUE.equals(data.getAuxiliaryAccounting()) ? editableStyle : lockedStyle);
writeNumber(excelRow, 4, data.getOpeningQuantity(),
template && Boolean.TRUE.equals(data.getQuantityAccounting())
? numberEditableStyle : numberLockedStyle);
writeNumber(excelRow, 5, data.getOpeningAmount(), template ? amountEditableStyle : amountLockedStyle);
if (january) {
return;
}
writeNumber(excelRow, 6, data.getYearDebitQuantity(),
template && Boolean.TRUE.equals(data.getQuantityAccounting())
? numberEditableStyle : numberLockedStyle);
writeNumber(excelRow, 7, data.getYearDebitAmount(), template ? amountEditableStyle : amountLockedStyle);
writeNumber(excelRow, 8, data.getYearCreditQuantity(),
template && Boolean.TRUE.equals(data.getQuantityAccounting())
? numberEditableStyle : numberLockedStyle);
writeNumber(excelRow, 9, data.getYearCreditAmount(), template ? amountEditableStyle : amountLockedStyle);
if (template) {
String quantityFormula = "借".equals(data.getDirectionName())
? "E" + (excelRow.getRowNum() + 1) + "-G" + (excelRow.getRowNum() + 1)
+ "+I" + (excelRow.getRowNum() + 1)
: "E" + (excelRow.getRowNum() + 1) + "+G" + (excelRow.getRowNum() + 1)
+ "-I" + (excelRow.getRowNum() + 1);
String amountFormula = "借".equals(data.getDirectionName())
? "F" + (excelRow.getRowNum() + 1) + "-H" + (excelRow.getRowNum() + 1)
+ "+J" + (excelRow.getRowNum() + 1)
: "F" + (excelRow.getRowNum() + 1) + "+H" + (excelRow.getRowNum() + 1)
+ "-J" + (excelRow.getRowNum() + 1);
writeFormula(excelRow, 10, quantityFormula, numberLockedStyle);
writeFormula(excelRow, 11, amountFormula, amountLockedStyle);
} else {
writeNumber(excelRow, 10, data.getYearOpeningQuantity(), numberLockedStyle);
writeNumber(excelRow, 11, data.getYearOpeningAmount(), amountLockedStyle);
}
boolean profitLoss = FmsSubjectTypeEnum.PROFIT_LOSS.getType().equals(data.getSubjectType());
writeNumber(excelRow, 12, profitLoss ? data.getProfitLossQuantity() : null,
template && profitLoss && Boolean.TRUE.equals(data.getQuantityAccounting())
? numberEditableStyle : numberLockedStyle);
writeNumber(excelRow, 13, profitLoss ? data.getProfitLossAmount() : null,
template && profitLoss ? amountEditableStyle : amountLockedStyle);
}
/**
* 解析一行数据,公式单元格通过 evaluator 取计算值
*/
private static FmsInitialBalanceExcelVO parseRow(Row row, boolean january, FormulaEvaluator evaluator) {
FmsInitialBalanceExcelVO result = new FmsInitialBalanceExcelVO()
.setRowNumber(row.getRowNum() + 1)
.setSubjectCode(getCellText(row, 0, evaluator))
.setSubjectName(getCellText(row, 1, evaluator))
.setDirectionName(getCellText(row, 2, evaluator))
.setAuxiliaryItems(getCellText(row, 3, evaluator))
.setOpeningQuantity(getDecimal(row, 4, evaluator))
.setOpeningAmount(getDecimal(row, 5, evaluator));
if (!january) {
result.setYearDebitQuantity(getDecimal(row, 6, evaluator))
.setYearDebitAmount(getDecimal(row, 7, evaluator))
.setYearCreditQuantity(getDecimal(row, 8, evaluator))
.setYearCreditAmount(getDecimal(row, 9, evaluator))
.setYearOpeningQuantity(getDecimal(row, 10, evaluator))
.setYearOpeningAmount(getDecimal(row, 11, evaluator))
.setProfitLossQuantity(getDecimal(row, 12, evaluator))
.setProfitLossAmount(getDecimal(row, 13, evaluator));
}
return result;
}
private static boolean hasValidHeaders(Sheet sheet) {
Row firstRow = sheet.getRow(0);
Row secondRow = sheet.getRow(1);
return firstRow != null && secondRow != null
&& "科目编码".equals(getCellText(firstRow, 0, null))
&& "科目名称".equals(getCellText(firstRow, 1, null))
&& "方向".equals(getCellText(firstRow, 2, null))
&& "辅助核算项目".equals(getCellText(firstRow, 3, null))
&& "期初余额".equals(getCellText(firstRow, 4, null))
&& "数量".equals(getCellText(secondRow, 4, null))
&& "金额".equals(getCellText(secondRow, 5, null));
}
private static void writeInstructions(Workbook workbook) {
Sheet sheet = workbook.createSheet("填写说明");
String[] instructions = {
"1. 灰色单元格由系统生成,请勿修改",
"2. 仅末级科目可以导入初始余额",
"3. 辅助核算项目使用“类别:名称/类别:名称”格式,例如“客户:北京客户/部门:销售部”",
"4. 数量核算科目可填写数量,金额和数量不能小于 0",
"5. 年初余额由期初余额和本年累计发生额自动计算"
};
for (int index = 0; index < instructions.length; index++) {
sheet.createRow(index).createCell(0).setCellValue(instructions[index]);
}
sheet.setColumnWidth(0, 20_000);
}
}
@@ -1,195 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject.FmsSubjectDeleteReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject.FmsSubjectImportExcelVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject.FmsSubjectImportRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject.FmsSubjectListReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject.FmsSubjectRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject.FmsSubjectSaveReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject.FmsSubjectStatusReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject.FmsSubjectUsageRespVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsAuxiliaryTypeDO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsSubjectDO;
import cn.iocoder.yudao.module.fms.service.config.FmsAuxiliaryTypeService;
import cn.iocoder.yudao.module.fms.service.config.FmsSubjectService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 会计科目")
@RestController
@RequestMapping("/fms/config/subject")
@Validated
public class FmsSubjectController {
@Resource
private FmsSubjectService subjectService;
@Resource
private FmsAuxiliaryTypeService auxiliaryTypeService;
@PostMapping("/create")
@Operation(summary = "创建科目")
@PreAuthorize("@ss.hasPermission('fms:config:subject:create')")
public CommonResult<Long> createSubject(@Valid @RequestBody FmsSubjectSaveReqVO createReqVO) {
return success(subjectService.createSubject(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "更新科目")
@PreAuthorize("@ss.hasPermission('fms:config:subject:update')")
public CommonResult<Boolean> updateSubject(@Valid @RequestBody FmsSubjectSaveReqVO updateReqVO) {
subjectService.updateSubject(updateReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "删除科目")
@PreAuthorize("@ss.hasPermission('fms:config:subject:delete')")
public CommonResult<Boolean> deleteSubjectList(@Valid @RequestBody FmsSubjectDeleteReqVO deleteReqVO) {
subjectService.deleteSubjectList(deleteReqVO, getLoginUserId());
return success(true);
}
@PutMapping("/update-status")
@Operation(summary = "更新科目状态")
@PreAuthorize("@ss.hasPermission('fms:config:subject:update')")
public CommonResult<Boolean> updateSubjectStatus(@Valid @RequestBody FmsSubjectStatusReqVO statusReqVO) {
subjectService.updateSubjectStatus(statusReqVO, getLoginUserId());
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得科目")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024"),
@Parameter(name = "id", description = "科目编号", required = true, example = "1024")
})
@PreAuthorize("@ss.hasPermission('fms:config:subject:query')")
public CommonResult<FmsSubjectRespVO> getSubject(@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
FmsSubjectDO subject = subjectService.getSubject(accountSetId, id, getLoginUserId());
return success(buildSubjectRespVO(subject));
}
@GetMapping("/get-usage")
@Operation(summary = "获得科目使用情况")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024"),
@Parameter(name = "id", description = "科目编号", required = true, example = "1024")
})
@PreAuthorize("@ss.hasPermission('fms:config:subject:query')")
public CommonResult<FmsSubjectUsageRespVO> getSubjectUsage(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
return success(subjectService.getSubjectUsage(accountSetId, id, getLoginUserId()));
}
@GetMapping("/list")
@Operation(summary = "获得科目列表")
@PreAuthorize("@ss.hasPermission('fms:config:subject:query')")
public CommonResult<List<FmsSubjectRespVO>> getSubjectList(@Valid FmsSubjectListReqVO listReqVO) {
List<FmsSubjectDO> subjects = subjectService.getSubjectList(listReqVO, getLoginUserId());
return success(buildSubjectRespVOList(subjects));
}
@GetMapping("/simple-list")
@Operation(summary = "获得科目精简列表")
public CommonResult<List<FmsSubjectRespVO>> getSubjectSimpleList(@Valid FmsSubjectListReqVO listReqVO) {
List<FmsSubjectDO> subjects = subjectService.getSubjectList(listReqVO, getLoginUserId());
return success(convertList(subjects, subject -> new FmsSubjectRespVO()
.setId(subject.getId()).setParentId(subject.getParentId())
.setCode(subject.getCode()).setName(subject.getName()).setType(subject.getType())
.setBalanceDirection(subject.getBalanceDirection()).setStatus(subject.getStatus())
.setLevel(subject.getLevel()).setAuxiliaryTypeIds(subject.getAuxiliaryTypeIds())
.setQuantityAccounting(subject.getQuantityAccounting()).setQuantityUnit(subject.getQuantityUnit())));
}
@GetMapping("/export-excel")
@Operation(summary = "导出科目")
@PreAuthorize("@ss.hasPermission('fms:config:subject:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportSubject(@Valid FmsSubjectListReqVO listReqVO,
HttpServletResponse response) throws IOException {
List<FmsSubjectDO> subjects = subjectService.getSubjectList(listReqVO, getLoginUserId());
ExcelUtils.write(response, "科目设置.xlsx", "科目设置", FmsSubjectRespVO.class,
buildSubjectRespVOList(subjects));
}
@GetMapping("/get-import-template")
@Operation(summary = "获得科目导入模板")
@PreAuthorize("@ss.hasPermission('fms:config:subject:import')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void getSubjectImportTemplate(HttpServletResponse response) throws IOException {
List<FmsSubjectImportExcelVO> list = Arrays.asList(
FmsSubjectImportExcelVO.builder().code("1001").name("库存现金")
.parentSubjectCode("0").balanceDirection("借").categoryName("流动资产").build(),
FmsSubjectImportExcelVO.builder().code("100101").name("人民币现金")
.parentSubjectCode("1001").balanceDirection("借").categoryName("流动资产")
.auxiliaryNames("部门/职员").build());
ExcelUtils.write(response, "科目导入模板.xlsx", "科目列表", FmsSubjectImportExcelVO.class, list);
}
@PostMapping("/import")
@Operation(summary = "导入科目")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024"),
@Parameter(name = "file", description = "Excel 文件", required = true)
})
@PreAuthorize("@ss.hasPermission('fms:config:subject:import')")
@ApiAccessLog(operateType = OperateTypeEnum.IMPORT)
public CommonResult<FmsSubjectImportRespVO> importSubject(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("file") MultipartFile file) throws IOException {
List<FmsSubjectImportExcelVO> importSubjects = ExcelUtils.read(file, FmsSubjectImportExcelVO.class);
return success(subjectService.importSubjectList(accountSetId, importSubjects, getLoginUserId()));
}
// ==================== 拼接 VO ====================
private List<FmsSubjectRespVO> buildSubjectRespVOList(List<FmsSubjectDO> subjects) {
Map<Long, FmsAuxiliaryTypeDO> auxiliaryTypeMap = auxiliaryTypeService.getAuxiliaryTypeMap(
convertSetByFlatMap(subjects, FmsSubjectDO::getAuxiliaryTypeIds, List::stream));
return convertList(subjects, subject -> {
FmsSubjectRespVO subjectVO = BeanUtils.toBean(subject, FmsSubjectRespVO.class)
.setCategoryDictValue(subject.getType() + "-" + subject.getCategory());
subjectVO.setAuxiliaryTypeNames(convertList(subject.getAuxiliaryTypeIds(),
auxiliaryTypeId -> auxiliaryTypeMap.get(auxiliaryTypeId).getName()));
if (Boolean.FALSE.equals(subject.getQuantityAccounting())) {
subjectVO.setQuantityUnit("");
}
return subjectVO;
});
}
private FmsSubjectRespVO buildSubjectRespVO(FmsSubjectDO subject) {
return subject == null ? null
: CollUtil.getFirst(buildSubjectRespVOList(Collections.singletonList(subject)));
}
}
@@ -1,89 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.vouchertemplatecategory.FmsVoucherTemplateCategoryRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.vouchertemplatecategory.FmsVoucherTemplateCategorySaveReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsVoucherTemplateCategoryDO;
import cn.iocoder.yudao.module.fms.service.config.FmsAccountSetService;
import cn.iocoder.yudao.module.fms.service.config.FmsVoucherTemplateService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 凭证模板分类")
@RestController
@RequestMapping("/fms/config/voucher-template-category")
@Validated
public class FmsVoucherTemplateCategoryController {
@Resource
private FmsVoucherTemplateService voucherTemplateService;
@Resource
private FmsAccountSetService accountSetService;
@PostMapping("/create")
@Operation(summary = "创建凭证模板分类")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-template-category:create')")
public CommonResult<Long> createTemplateCategory(
@Valid @RequestBody FmsVoucherTemplateCategorySaveReqVO createReqVO) {
return success(voucherTemplateService.createTemplateCategory(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "修改凭证模板分类")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-template-category:update')")
public CommonResult<Boolean> updateTemplateCategory(
@Valid @RequestBody FmsVoucherTemplateCategorySaveReqVO updateReqVO) {
voucherTemplateService.updateTemplateCategory(updateReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除凭证模板分类")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-template-category:delete')")
public CommonResult<Boolean> deleteTemplateCategory(@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
voucherTemplateService.deleteTemplateCategory(accountSetId, id, getLoginUserId());
return success(true);
}
@GetMapping("/list")
@Operation(summary = "获得凭证模板分类列表")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-template-category:query')")
public CommonResult<List<FmsVoucherTemplateCategoryRespVO>> getTemplateCategoryList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
accountSetService.validateAccountSetReadPermission(accountSetId, getLoginUserId());
List<FmsVoucherTemplateCategoryDO> categories = voucherTemplateService.getTemplateCategoryList(accountSetId);
return success(BeanUtils.toBean(categories, FmsVoucherTemplateCategoryRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得凭证模板分类精简列表", description = "主要用于前端的下拉选项")
public CommonResult<List<FmsVoucherTemplateCategoryRespVO>> getTemplateCategorySimpleList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
accountSetService.validateAccountSetReadPermission(accountSetId, getLoginUserId());
List<FmsVoucherTemplateCategoryDO> categories = voucherTemplateService.getTemplateCategoryList(accountSetId);
return success(convertList(categories, category -> new FmsVoucherTemplateCategoryRespVO()
.setId(category.getId()).setName(category.getName())));
}
}
@@ -1,100 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.vouchertemplate.FmsVoucherTemplateRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.vouchertemplate.FmsVoucherTemplateSaveReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsVoucherTemplateCategoryDO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsVoucherTemplateDO;
import cn.iocoder.yudao.module.fms.service.config.FmsAccountSetService;
import cn.iocoder.yudao.module.fms.service.config.FmsVoucherTemplateService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 凭证模板")
@RestController
@RequestMapping("/fms/config/voucher-template")
@Validated
public class FmsVoucherTemplateController {
@Resource
private FmsVoucherTemplateService voucherTemplateService;
@Resource
private FmsAccountSetService accountSetService;
@PostMapping("/create")
@Operation(summary = "创建凭证模板")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-template:create')")
public CommonResult<Long> createVoucherTemplate(
@Valid @RequestBody FmsVoucherTemplateSaveReqVO createReqVO) {
return success(voucherTemplateService.createVoucherTemplate(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "修改凭证模板")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-template:update')")
public CommonResult<Boolean> updateVoucherTemplate(
@Valid @RequestBody FmsVoucherTemplateSaveReqVO updateReqVO) {
voucherTemplateService.updateVoucherTemplate(updateReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除凭证模板")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-template:delete')")
public CommonResult<Boolean> deleteVoucherTemplate(@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
voucherTemplateService.deleteVoucherTemplate(accountSetId, id, getLoginUserId());
return success(true);
}
@GetMapping("/list")
@Operation(summary = "获得凭证模板列表")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-template:query')")
public CommonResult<List<FmsVoucherTemplateRespVO>> getVoucherTemplateList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
accountSetService.validateAccountSetReadPermission(accountSetId, getLoginUserId());
return success(buildVoucherTemplateRespVOList(accountSetId));
}
@GetMapping("/simple-list")
@Operation(summary = "获得凭证模板精简列表", description = "主要用于录凭证时套用凭证模板")
public CommonResult<List<FmsVoucherTemplateRespVO>> getVoucherTemplateSimpleList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
accountSetService.validateAccountSetReadPermission(accountSetId, getLoginUserId());
return success(buildVoucherTemplateRespVOList(accountSetId));
}
// ==================== 拼接 VO ====================
private List<FmsVoucherTemplateRespVO> buildVoucherTemplateRespVOList(Long accountSetId) {
Map<Long, FmsVoucherTemplateCategoryDO> categoryMap =
voucherTemplateService.getTemplateCategoryMap(accountSetId);
List<FmsVoucherTemplateDO> templates = voucherTemplateService.getVoucherTemplateList(accountSetId);
return BeanUtils.toBean(templates, FmsVoucherTemplateRespVO.class, template -> {
findAndThen(categoryMap, template.getCategoryId(),
category -> template.setCategoryName(category.getName()));
});
}
}
@@ -1,93 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.voucherword.FmsVoucherWordRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.voucherword.FmsVoucherWordSaveReqVO;
import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsVoucherWordDO;
import cn.iocoder.yudao.module.fms.service.config.FmsVoucherWordService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
/**
* FMS 凭证字 Controller
*
* @author 芋道源码
*/
@Tag(name = "管理后台 - FMS 凭证字")
@RestController
@RequestMapping("/fms/config/voucher-word")
@Validated
public class FmsVoucherWordController {
@Resource
private FmsVoucherWordService voucherWordService;
@PostMapping("/create")
@Operation(summary = "创建凭证字")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-word:create')")
public CommonResult<Long> createVoucherWord(@Valid @RequestBody FmsVoucherWordSaveReqVO createReqVO) {
return success(voucherWordService.createVoucherWord(createReqVO, getLoginUserId()));
}
@PutMapping("/update")
@Operation(summary = "修改凭证字")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-word:update')")
public CommonResult<Boolean> updateVoucherWord(@Valid @RequestBody FmsVoucherWordSaveReqVO updateReqVO) {
voucherWordService.updateVoucherWord(updateReqVO, getLoginUserId());
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除凭证字")
@Parameter(name = "id", description = "凭证字编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-word:delete')")
public CommonResult<Boolean> deleteVoucherWord(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("id") @NotNull Long id) {
voucherWordService.deleteVoucherWord(accountSetId, id, getLoginUserId());
return success(true);
}
@GetMapping("/list")
@Operation(summary = "获得凭证字管理列表")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:config:voucher-word:query')")
public CommonResult<List<FmsVoucherWordRespVO>> getVoucherWordList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
List<FmsVoucherWordDO> list = voucherWordService.getVoucherWordList(accountSetId, getLoginUserId());
return success(BeanUtils.toBean(list, FmsVoucherWordRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得凭证字精简列表")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
public CommonResult<List<FmsVoucherWordRespVO>> getVoucherWordSimpleList(
@RequestParam("accountSetId") @NotNull Long accountSetId) {
return success(convertList(voucherWordService.getVoucherWordList(
accountSetId, getLoginUserId()), voucherWord -> new FmsVoucherWordRespVO()
.setId(voucherWord.getId()).setName(voucherWord.getName())
.setDefaultStatus(voucherWord.getDefaultStatus())));
}
}
@@ -1,55 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.accountset;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.config.FmsAccountingStandardEnum;
import cn.iocoder.yudao.module.fms.enums.config.FmsCurrencyPresetEnum;
import cn.iocoder.yudao.module.fms.enums.ledger.FmsLedgerBalanceModeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - FMS 账套初始化 Request VO")
@Data
public class FmsAccountSetInitializeReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "本位币编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "RMB")
@NotBlank(message = "本位币不能为空")
@InEnum(value = FmsCurrencyPresetEnum.class, message = "本位币必须是 {value}")
private String currencyCode;
@Schema(description = "启用期间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "启用期间不能为空")
private LocalDateTime startTime;
@Schema(description = "会计制度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "会计制度不能为空")
@InEnum(value = FmsAccountingStandardEnum.class, message = "会计制度必须是 {value}")
private Integer standard;
@Schema(description = "科目层级", requiredMode = Schema.RequiredMode.REQUIRED, example = "4")
@NotNull(message = "科目层级不能为空")
@Min(value = 1, message = "科目层级不能小于 1")
@Max(value = 8, message = "科目层级不能大于 8")
private Integer level;
@Schema(description = "科目编码规则", requiredMode = Schema.RequiredMode.REQUIRED, example = "4-2-2-2")
@NotBlank(message = "科目编码规则不能为空")
@Size(max = 64, message = "科目编码规则不能超过 64 个字符")
private String subjectCodeRule;
@Schema(description = "账簿余额方向模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账簿余额方向模式不能为空")
@InEnum(FmsLedgerBalanceModeEnum.class)
private Integer ledgerBalanceMode;
}
@@ -1,95 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.accountset;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - FMS 账套 Response VO")
@Data
public class FmsAccountSetRespVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "公司编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "WK001")
private String companyCode;
@Schema(description = "公司名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试科技有限公司")
private String companyName;
@Schema(description = "公司简介", example = "专注企业数字化服务")
private String companyProfile;
@Schema(description = "所在行业", example = "软件和信息技术服务业")
private String industry;
@Schema(description = "所在地", example = "上海市浦东新区")
private String location;
@Schema(description = "法人代表", example = "张三")
private String legalRepresentative;
@Schema(description = "法人身份证号", example = "310101199001011234")
private String legalRepresentativeIdNumber;
@Schema(description = "营业执照号", example = "91310000MA1K123456")
private String businessLicenseNumber;
@Schema(description = "组织机构代码", example = "MA1K12345")
private String organizationCode;
@Schema(description = "备注", example = "一般纳税人")
private String remark;
@Schema(description = "联系人", example = "李四")
private String contactName;
@Schema(description = "办公电话", example = "021-12345678")
private String officeTelephone;
@Schema(description = "手机号码", example = "15601691399")
private String mobile;
@Schema(description = "传真号码", example = "021-87654321")
private String faxNumber;
@Schema(description = "QQ 号码", example = "12345678")
private String qqNumber;
@Schema(description = "邮箱", example = "finance@example.com")
private String email;
@Schema(description = "其他联系方式", example = "企业微信:wk-finance")
private String otherContact;
@Schema(description = "详细地址", example = "张江高科技园区 1 号楼")
private String address;
@Schema(description = "币种编号", example = "1024")
private Long currencyId;
@Schema(description = "启用期间")
private LocalDateTime startTime;
@Schema(description = "会计制度", example = "1")
private Integer standard;
@Schema(description = "是否已初始化", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean initialized;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
// ==================== 来自 FmsAccountUserDO ====================
@Schema(description = "是否默认账套", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean defaultStatus;
@Schema(description = "是否账套创建人", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean founder;
@Schema(description = "当前用户的成员权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
private Integer level;
}
@@ -1,110 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.accountset;
import com.mzt.logapi.starter.annotation.DiffLogField;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - FMS 账套新增/修改 Request VO")
@Data
public class FmsAccountSetSaveReqVO {
@Schema(description = "账套编号", example = "1024")
private Long id;
@Schema(description = "公司编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "WK001")
@NotBlank(message = "公司编码不能为空")
@Size(max = 64, message = "公司编码不能超过 64 个字符")
@DiffLogField(name = "公司编码")
private String companyCode;
@Schema(description = "公司名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试科技有限公司")
@NotBlank(message = "公司名称不能为空")
@Size(max = 255, message = "公司名称不能超过 255 个字符")
@DiffLogField(name = "公司名称")
private String companyName;
@Schema(description = "公司简介", example = "专注企业数字化服务")
@Size(max = 500, message = "公司简介不能超过 500 个字符")
@DiffLogField(name = "公司简介")
private String companyProfile;
@Schema(description = "所在行业", example = "软件和信息技术服务业")
@Size(max = 255, message = "所在行业不能超过 255 个字符")
@DiffLogField(name = "所在行业")
private String industry;
@Schema(description = "所在地", example = "上海市浦东新区")
@Size(max = 255, message = "所在地不能超过 255 个字符")
@DiffLogField(name = "所在地")
private String location;
@Schema(description = "法人代表", example = "张三")
@Size(max = 255, message = "法人代表不能超过 255 个字符")
@DiffLogField(name = "法人代表")
private String legalRepresentative;
@Schema(description = "法人身份证号", example = "310101199001011234")
@Size(max = 255, message = "法人身份证号不能超过 255 个字符")
@DiffLogField(name = "法人身份证号")
private String legalRepresentativeIdNumber;
@Schema(description = "营业执照号", example = "91310000MA1K123456")
@Size(max = 255, message = "营业执照号不能超过 255 个字符")
@DiffLogField(name = "营业执照号")
private String businessLicenseNumber;
@Schema(description = "组织机构代码", example = "MA1K12345")
@Size(max = 255, message = "组织机构代码不能超过 255 个字符")
@DiffLogField(name = "组织机构代码")
private String organizationCode;
@Schema(description = "备注", example = "一般纳税人")
@Size(max = 500, message = "备注不能超过 500 个字符")
@DiffLogField(name = "备注")
private String remark;
@Schema(description = "联系人", example = "李四")
@Size(max = 255, message = "联系人不能超过 255 个字符")
@DiffLogField(name = "联系人")
private String contactName;
@Schema(description = "办公电话", example = "021-12345678")
@Size(max = 32, message = "办公电话不能超过 32 个字符")
@DiffLogField(name = "办公电话")
private String officeTelephone;
@Schema(description = "手机号码", example = "15601691399")
@Size(max = 32, message = "手机号码不能超过 32 个字符")
@DiffLogField(name = "手机号码")
private String mobile;
@Schema(description = "传真号码", example = "021-87654321")
@Size(max = 32, message = "传真号码不能超过 32 个字符")
@DiffLogField(name = "传真号码")
private String faxNumber;
@Schema(description = "QQ 号码", example = "12345678")
@Size(max = 255, message = "QQ 号码不能超过 255 个字符")
@DiffLogField(name = "QQ 号码")
private String qqNumber;
@Schema(description = "邮箱", example = "finance@example.com")
@Email(message = "邮箱格式不正确")
@Size(max = 255, message = "邮箱不能超过 255 个字符")
@DiffLogField(name = "邮箱")
private String email;
@Schema(description = "其他联系方式", example = "企业微信:wk-finance")
@Size(max = 255, message = "其他联系方式不能超过 255 个字符")
@DiffLogField(name = "其他联系方式")
private String otherContact;
@Schema(description = "详细地址", example = "张江高科技园区 1 号楼")
@Size(max = 255, message = "详细地址不能超过 255 个字符")
@DiffLogField(name = "详细地址")
private String address;
}
@@ -1,37 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.accountuser;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - FMS 账套用户 Response VO")
@Data
public class FmsAccountUserRespVO {
@Schema(description = "后台用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long userId;
@Schema(description = "用户昵称", example = "芋道")
private String nickname;
@Schema(description = "部门名称", example = "财务部")
private String deptName;
@Schema(description = "手机号码", example = "15601691399")
private String mobile;
@Schema(description = "用户邮箱", example = "finance@example.com")
private String email;
@Schema(description = "用户状态", example = "0")
private Integer status;
@Schema(description = "是否默认账套", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean defaultStatus;
@Schema(description = "是否账套创建人", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean founder;
@Schema(description = "成员权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer level;
}
@@ -1,42 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.accountuser;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.config.FmsAccountUserLevelEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - FMS 账套用户更新 Request VO")
@Data
public class FmsAccountUserUpdateReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "账套成员数组", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "账套成员数组不能为空")
@Size(max = 100, message = "单个账套最多授权 100 名成员")
@Valid
private List<Member> members;
@Schema(description = "管理后台 - FMS 账套成员")
@Data
public static class Member {
@Schema(description = "后台用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "成员用户编号不能为空")
private Long userId;
@Schema(description = "成员权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "成员权限级别不能为空")
@InEnum(FmsAccountUserLevelEnum.class)
private Integer level;
}
}
@@ -1,38 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem;
import cn.idev.excel.annotation.ExcelProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
/**
* FMS 辅助核算项目 Excel 导入 VO
*
* @author 芋道源码
*/
@Data
public class FmsAuxiliaryItemImportExcelVO {
@ExcelProperty("编码")
@NotBlank(message = "编码不能为空")
@Size(max = 64, message = "编码长度不能超过 64 个字符")
private String code;
@ExcelProperty("名称")
@NotBlank(message = "名称不能为空")
@Size(max = 255, message = "名称长度不能超过 255 个字符")
private String name;
@ExcelProperty("备注")
@Size(max = 500, message = "备注长度不能超过 500 个字符")
private String remark;
@ExcelProperty("规格")
@Size(max = 255, message = "规格长度不能超过 255 个字符")
private String specification;
@ExcelProperty("单位")
@Size(max = 255, message = "单位长度不能超过 255 个字符")
private String unit;
}
@@ -1,27 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* FMS 辅助核算项目导入结果 Response VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 辅助核算项目导入结果 Response VO")
@Data
public class FmsAuxiliaryItemImportRespVO {
@Schema(description = "总数量", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer totalCount;
@Schema(description = "成功编码数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> successItemCodes;
@Schema(description = "失败原因 Map", requiredMode = Schema.RequiredMode.REQUIRED)
private Map<String, String> failureReasons;
}
@@ -1,30 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* FMS 辅助核算项目分页 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 辅助核算项目分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class FmsAuxiliaryItemPageReqVO extends PageParam {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "辅助核算类别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "辅助核算类别编号不能为空")
private Long auxiliaryTypeId;
@Schema(description = "关键词,匹配编码或名称", example = "测试")
private String search;
}
@@ -1,55 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* FMS 辅助核算项目 Response VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 辅助核算项目 Response VO")
@Data
@ExcelIgnoreUnannotated
public class FmsAuxiliaryItemRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long accountSetId;
@Schema(description = "辅助核算类别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long auxiliaryTypeId;
@Schema(description = "编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "KH001")
@ExcelProperty("编码")
private String code;
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海测试数字科技有限公司")
@ExcelProperty("名称")
private String name;
@Schema(description = "备注", example = "重点客户")
@ExcelProperty("备注")
private String remark;
@Schema(description = "规格", example = "标准版")
@ExcelProperty("规格")
private String specification;
@Schema(description = "单位", example = "台")
@ExcelProperty("单位")
private String unit;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
@@ -1,51 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
/**
* FMS 辅助核算项目创建或修改 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 辅助核算项目创建或修改 Request VO")
@Data
public class FmsAuxiliaryItemSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "辅助核算类别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "辅助核算类别编号不能为空")
private Long auxiliaryTypeId;
@Schema(description = "编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "KH001")
@NotBlank(message = "编码不能为空")
@Size(max = 64, message = "编码长度不能超过 64 个字符")
private String code;
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海测试数字科技有限公司")
@NotBlank(message = "名称不能为空")
@Size(max = 255, message = "名称长度不能超过 255 个字符")
private String name;
@Schema(description = "备注", example = "重点客户")
@Size(max = 500, message = "备注长度不能超过 500 个字符")
private String remark;
@Schema(description = "规格", example = "标准版")
@Size(max = 255, message = "规格长度不能超过 255 个字符")
private String specification;
@Schema(description = "单位", example = "台")
@Size(max = 255, message = "单位长度不能超过 255 个字符")
private String unit;
}
@@ -1,31 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* FMS 辅助核算项目状态更新 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 辅助核算项目状态更新 Request VO")
@Data
public class FmsAuxiliaryItemStatusReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "编号不能为空")
private Long id;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "状态不能为空")
@InEnum(CommonStatusEnum.class)
private Integer status;
}
@@ -1,30 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliarytype;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* FMS 辅助核算类别 Response VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 辅助核算类别 Response VO")
@Data
public class FmsAuxiliaryTypeRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "客户")
private String name;
@Schema(description = "是否系统预置", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean systemPreset;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long accountSetId;
@Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
}
@@ -1,30 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliarytype;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
/**
* FMS 辅助核算类别创建或修改 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 辅助核算类别创建或修改 Request VO")
@Data
public class FmsAuxiliaryTypeSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "门店")
@NotBlank(message = "名称不能为空")
@Size(max = 255, message = "名称长度不能超过 255 个字符")
private String name;
}
@@ -1,39 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.currency;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* FMS 币别 Response VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 币别 Response VO")
@Data
public class FmsCurrencyRespVO {
@Schema(description = "币别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long accountSetId;
@Schema(description = "币别编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "USD")
private String code;
@Schema(description = "币别名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "美元")
private String name;
@Schema(description = "汇率", requiredMode = Schema.RequiredMode.REQUIRED, example = "7.120000")
private BigDecimal exchangeRate;
@Schema(description = "是否本位币", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean standard;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
@@ -1,47 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.currency;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.math.BigDecimal;
/**
* FMS 币别保存 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 币别保存 Request VO")
@Data
public class FmsCurrencySaveReqVO {
@Schema(description = "币别编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套不能为空")
private Long accountSetId;
@Schema(description = "币别编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "USD")
@NotBlank(message = "币别编码不能为空")
@Size(max = 64, message = "币别编码长度不能超过 64 个字符")
@Pattern(regexp = "^[A-Za-z][A-Za-z0-9_]*$", message = "币别编码必须以字母开头,只能包含字母、数字和下划线")
private String code;
@Schema(description = "币别名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "美元")
@NotBlank(message = "币别名称不能为空")
@Size(max = 255, message = "币别名称长度不能超过 255 个字符")
private String name;
@Schema(description = "汇率", requiredMode = Schema.RequiredMode.REQUIRED, example = "7.120000")
@NotNull(message = "汇率不能为空")
@DecimalMin(value = "0", inclusive = false, message = "汇率必须大于 0")
@Digits(integer = 12, fraction = 6, message = "汇率最多 12 位整数和 6 位小数")
private BigDecimal exchangeRate;
}
@@ -1,29 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.digest;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* FMS 常用摘要 Response VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 常用摘要 Response VO")
@Data
public class FmsDigestRespVO {
@Schema(description = "常用摘要编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long accountSetId;
@Schema(description = "摘要内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "购买办公用品")
private String content;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
@@ -1,30 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.digest;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
/**
* FMS 常用摘要保存 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 常用摘要保存 Request VO")
@Data
public class FmsDigestSaveReqVO {
@Schema(description = "常用摘要编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "摘要内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "购买办公用品")
@NotBlank(message = "摘要内容不能为空")
@Size(max = 500, message = "摘要内容长度不能超过 500 个字符")
private String content;
}
@@ -1,40 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.financeindicator;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
// TODO DONE @AI:字段 Swagger 注解和空行已补齐。
@Schema(description = "管理后台 - FMS 财务指标 Response VO")
@Data
public class FmsFinanceIndicatorRespVO {
@Schema(description = "指标编号", example = "1024")
private Long id;
@Schema(description = "账套编号", example = "1")
private Long accountSetId;
@Schema(description = "指标名称", example = "现金")
private String name;
@Schema(description = "指标编码", example = "cash")
private String code;
@Schema(description = "取数报表类型", example = "1")
private Integer type;
@Schema(description = "指标公式")
private String formula;
@Schema(description = "展示顺序", example = "10")
private Integer sort;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Integer status;
@Schema(description = "创建时间")
private LocalDateTime createTime;
}
@@ -1,53 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.financeindicator;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.config.FmsFinanceIndicatorTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
// TODO DONE @AI:字段空行已对齐现有 SaveReqVO。
@Schema(description = "管理后台 - FMS 财务指标保存 Request VO")
@Data
public class FmsFinanceIndicatorSaveReqVO {
@Schema(description = "指标编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "指标名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "现金")
@NotBlank(message = "指标名称不能为空")
@Size(max = 100, message = "指标名称长度不能超过 100 个字符")
private String name;
@Schema(description = "指标编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "cash")
@NotBlank(message = "指标编码不能为空")
@Size(max = 64, message = "指标编码长度不能超过 64 个字符")
private String code;
@Schema(description = "取数报表类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "取数报表类型不能为空")
@InEnum(FmsFinanceIndicatorTypeEnum.class)
private Integer type;
@Schema(description = "指标公式,支持 L1+L2 或科目公式 JSON", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "指标公式不能为空")
@Size(max = 2000, message = "指标公式长度不能超过 2000 个字符")
private String formula;
@Schema(description = "展示顺序", example = "10")
@NotNull(message = "展示顺序不能为空")
private Integer sort;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "状态不能为空")
@InEnum(CommonStatusEnum.class)
private Integer status;
}
@@ -1,25 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.financeparameter;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - FMS 财务参数 Response VO")
@Data
public class FmsFinanceParameterRespVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long accountSetId;
@Schema(description = "科目层级", requiredMode = Schema.RequiredMode.REQUIRED, example = "4")
private Integer level;
@Schema(description = "科目编码规则", requiredMode = Schema.RequiredMode.REQUIRED, example = "4-2-2-2")
private String subjectCodeRule;
@Schema(description = "账簿余额方向模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer ledgerBalanceMode;
@Schema(description = "结账前是否要求凭证审核", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean voucherReviewRequired;
}
@@ -1,53 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.financeparameter;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.ledger.FmsLedgerBalanceModeEnum;
import cn.iocoder.yudao.module.fms.enums.config.FmsAccountingStandardEnum;
import com.mzt.logapi.starter.annotation.DiffLogField;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - FMS 财务参数更新 Request VO")
@Data
public class FmsFinanceParameterUpdateReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "会计制度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "会计制度不能为空")
@InEnum(FmsAccountingStandardEnum.class)
@DiffLogField(name = "会计制度")
private Integer standard;
@Schema(description = "科目层级", requiredMode = Schema.RequiredMode.REQUIRED, example = "4")
@NotNull(message = "科目层级不能为空")
@Min(value = 1, message = "科目层级不能小于 1")
@Max(value = 8, message = "科目层级不能大于 8")
@DiffLogField(name = "科目层级")
private Integer level;
@Schema(description = "科目编码规则", requiredMode = Schema.RequiredMode.REQUIRED, example = "4-2-2-2")
@NotBlank(message = "科目编码规则不能为空")
@Size(max = 64, message = "科目编码规则不能超过 64 个字符")
@DiffLogField(name = "科目编码规则")
private String subjectCodeRule;
@Schema(description = "账簿余额方向模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账簿余额方向模式不能为空")
@InEnum(FmsLedgerBalanceModeEnum.class)
@DiffLogField(name = "账簿余额方向")
private Integer ledgerBalanceMode;
@Schema(description = "结账前是否要求凭证审核", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "结账前凭证审核设置不能为空")
@DiffLogField(name = "凭证审核后才允许结账")
private Boolean voucherReviewRequired;
}
@@ -1,105 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* FMS 初始余额 Excel VO
*
* @author 芋道源码
*/
@Data
@ExcelIgnoreUnannotated
public class FmsInitialBalanceExcelVO {
/**
* Excel 行号
*/
private Integer rowNumber;
/**
* 科目编码
*/
@ExcelProperty("科目编码")
private String subjectCode;
/**
* 科目名称
*/
@ExcelProperty("科目名称")
private String subjectName;
/**
* 余额方向名称
*/
@ExcelProperty("方向")
private String directionName;
/**
* 辅助核算项目,格式为“类别:名称/类别:名称”
*/
@ExcelProperty("辅助核算项目")
private String auxiliaryItems;
/**
* 科目类型
*/
private Integer subjectType;
/**
* 是否启用数量核算
*/
private Boolean quantityAccounting;
/**
* 是否启用辅助核算
*/
private Boolean auxiliaryAccounting;
/**
* 期初数量
*/
@ExcelProperty("期初数量")
private BigDecimal openingQuantity;
/**
* 期初金额
*/
@ExcelProperty("期初金额")
private BigDecimal openingAmount;
/**
* 本年累计借方数量
*/
@ExcelProperty("本年累计借方数量")
private BigDecimal yearDebitQuantity;
/**
* 本年累计借方金额
*/
@ExcelProperty("本年累计借方金额")
private BigDecimal yearDebitAmount;
/**
* 本年累计贷方数量
*/
@ExcelProperty("本年累计贷方数量")
private BigDecimal yearCreditQuantity;
/**
* 本年累计贷方金额
*/
@ExcelProperty("本年累计贷方金额")
private BigDecimal yearCreditAmount;
/**
* 年初数量
*/
@ExcelProperty("年初数量")
private BigDecimal yearOpeningQuantity;
/**
* 年初金额
*/
@ExcelProperty("年初金额")
private BigDecimal yearOpeningAmount;
/**
* 实际损益发生数量
*/
@ExcelProperty("实际损益发生数量")
private BigDecimal profitLossQuantity;
/**
* 实际损益发生金额
*/
@ExcelProperty("实际损益发生金额")
private BigDecimal profitLossAmount;
}
@@ -1,154 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - FMS 初始余额 Response VO")
@Data
public class FmsInitialBalanceRespVO {
@Schema(description = "初始余额编号", example = "1024")
private Long id;
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long subjectId;
@Schema(description = "科目编码", requiredMode = Schema.RequiredMode.REQUIRED)
private String subjectCode;
@Schema(description = "科目名称", requiredMode = Schema.RequiredMode.REQUIRED)
private String subjectName;
@Schema(description = "上级科目编号", example = "1024")
private Long parentId;
@Schema(description = "科目类型", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer type;
@Schema(description = "余额方向", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer balanceDirection;
@Schema(description = "是否启用数量核算", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean quantityAccounting;
@Schema(description = "数量单位")
private String quantityUnit;
@Schema(description = "是否启用辅助核算", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean auxiliaryAccounting;
@Schema(description = "期初金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000.00")
private BigDecimal openingAmount;
@Schema(description = "期初数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.0000")
private BigDecimal openingQuantity;
@Schema(description = "本年累计借方金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal yearDebitAmount;
@Schema(description = "本年累计借方数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1.0000")
private BigDecimal yearDebitQuantity;
@Schema(description = "本年累计贷方金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "50.00")
private BigDecimal yearCreditAmount;
@Schema(description = "本年累计贷方数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1.0000")
private BigDecimal yearCreditQuantity;
@Schema(description = "年初金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "950.00")
private BigDecimal yearOpeningAmount;
@Schema(description = "年初数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.0000")
private BigDecimal yearOpeningQuantity;
@Schema(description = "实际损益发生额", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.00")
private BigDecimal profitLossAmount;
@Schema(description = "实际损益发生数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1.0000")
private BigDecimal profitLossQuantity;
@Schema(description = "辅助核算配置数组")
private List<AuxiliaryConfig> auxiliaryConfigs;
@Schema(description = "辅助核算余额数组")
private List<AssistBalance> assistBalances;
@Schema(description = "管理后台 - FMS 初始余额辅助核算配置")
@Data
public static class AuxiliaryConfig {
@Schema(description = "辅助核算类别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long auxiliaryTypeId;
@Schema(description = "辅助核算类型", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer type;
@Schema(description = "辅助核算类别名称", requiredMode = Schema.RequiredMode.REQUIRED)
private String name;
}
@Schema(description = "管理后台 - FMS 初始余额辅助核算余额")
@Data
public static class AssistBalance {
@Schema(description = "辅助核算组合编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long assistCombinationId;
@Schema(description = "辅助核算项目数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<AuxiliaryItem> auxiliaries;
@Schema(description = "期初金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000.00")
private BigDecimal openingAmount;
@Schema(description = "期初数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.0000")
private BigDecimal openingQuantity;
@Schema(description = "本年累计借方金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal yearDebitAmount;
@Schema(description = "本年累计借方数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1.0000")
private BigDecimal yearDebitQuantity;
@Schema(description = "本年累计贷方金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "50.00")
private BigDecimal yearCreditAmount;
@Schema(description = "本年累计贷方数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1.0000")
private BigDecimal yearCreditQuantity;
@Schema(description = "年初金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "950.00")
private BigDecimal yearOpeningAmount;
@Schema(description = "年初数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.0000")
private BigDecimal yearOpeningQuantity;
@Schema(description = "实际损益发生额", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.00")
private BigDecimal profitLossAmount;
@Schema(description = "实际损益发生数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1.0000")
private BigDecimal profitLossQuantity;
}
@Schema(description = "管理后台 - FMS 初始余额辅助核算项目")
@Data
public static class AuxiliaryItem {
@Schema(description = "辅助核算类型", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer type;
@Schema(description = "辅助核算类别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long typeId;
@Schema(description = "辅助核算项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long itemId;
@Schema(description = "辅助核算项目名称", requiredMode = Schema.RequiredMode.REQUIRED)
private String name;
}
}
@@ -1,91 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - FMS 初始余额保存 Request VO")
@Data
public class FmsInitialBalanceSaveReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "科目余额数组", requiredMode = Schema.RequiredMode.REQUIRED)
@Valid
@NotEmpty(message = "科目余额不能为空")
private List<Balance> balances;
@Data
public static class Balance extends Amounts {
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "科目编号不能为空")
private Long subjectId;
@Schema(description = "辅助核算余额数组")
@Valid
private List<AssistBalance> assistBalances;
}
@Data
public static class AssistBalance extends Amounts {
@Schema(description = "辅助核算项目编号数组", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "辅助核算项目不能为空")
private List<Long> auxiliaryItemIds;
}
@Data
public static class Amounts {
@Schema(description = "期初金额", example = "1000.00")
@DecimalMin(value = "0", message = "期初金额不能小于 0")
private BigDecimal openingAmount;
@Schema(description = "期初数量", example = "10.0000")
@DecimalMin(value = "0", message = "期初数量不能小于 0")
private BigDecimal openingQuantity;
@Schema(description = "本年累计借方金额", example = "100.00")
@DecimalMin(value = "0", message = "本年累计借方金额不能小于 0")
private BigDecimal yearDebitAmount;
@Schema(description = "本年累计借方数量", example = "1.0000")
@DecimalMin(value = "0", message = "本年累计借方数量不能小于 0")
private BigDecimal yearDebitQuantity;
@Schema(description = "本年累计贷方金额", example = "50.00")
@DecimalMin(value = "0", message = "本年累计贷方金额不能小于 0")
private BigDecimal yearCreditAmount;
@Schema(description = "本年累计贷方数量", example = "1.0000")
@DecimalMin(value = "0", message = "本年累计贷方数量不能小于 0")
private BigDecimal yearCreditQuantity;
@Schema(description = "年初金额", example = "950.00")
@DecimalMin(value = "0", message = "年初金额不能小于 0")
private BigDecimal yearOpeningAmount;
@Schema(description = "年初数量", example = "10.0000")
@DecimalMin(value = "0", message = "年初数量不能小于 0")
private BigDecimal yearOpeningQuantity;
@Schema(description = "实际损益发生额", example = "0.00")
@DecimalMin(value = "0", message = "实际损益发生额不能小于 0")
private BigDecimal profitLossAmount;
@Schema(description = "实际损益发生数量", example = "1.0000")
@DecimalMin(value = "0", message = "实际损益发生数量不能小于 0")
private BigDecimal profitLossQuantity;
}
}
@@ -1,33 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - FMS 试算平衡 Response VO")
@Data
public class FmsTrialBalanceRespVO {
@Schema(description = "期初借方金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000.00")
private BigDecimal openingDebitAmount;
@Schema(description = "期初贷方金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000.00")
private BigDecimal openingCreditAmount;
@Schema(description = "期初差额", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.00")
private BigDecimal openingDifferenceAmount;
@Schema(description = "本年累计借方金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal yearDebitAmount;
@Schema(description = "本年累计贷方金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal yearCreditAmount;
@Schema(description = "本年累计差额", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.00")
private BigDecimal yearDifferenceAmount;
@Schema(description = "是否平衡", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean balanced;
}
@@ -1,27 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
/**
* FMS 科目删除 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 科目删除 Request VO")
@Data
public class FmsSubjectDeleteReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "科目编号数组", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "科目编号数组不能为空")
private List<Long> ids;
}
@@ -1,43 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject;
import cn.idev.excel.annotation.ExcelProperty;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* FMS 科目 Excel 导入 VO
*
* @author 芋道源码
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FmsSubjectImportExcelVO {
@ExcelProperty("科目编码")
@NotBlank(message = "科目编码不能为空")
private String code;
@ExcelProperty("科目名称")
@NotBlank(message = "科目名称不能为空")
private String name;
@ExcelProperty("上级科目编码")
private String parentSubjectCode;
@ExcelProperty("余额方向")
@NotBlank(message = "余额方向不能为空")
private String balanceDirection;
@ExcelProperty("类别")
@NotBlank(message = "类别不能为空")
private String categoryName;
@ExcelProperty("辅助核算")
private String auxiliaryNames;
}
@@ -1,22 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Schema(description = "管理后台 - FMS 科目导入结果 Response VO")
@Data
public class FmsSubjectImportRespVO {
@Schema(description = "总数量", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer totalCount;
@Schema(description = "成功科目编码数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> successSubjectCodes;
@Schema(description = "失败原因 Map", requiredMode = Schema.RequiredMode.REQUIRED)
private Map<String, String> failureReasons;
}
@@ -1,26 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.config.FmsSubjectTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* FMS 科目列表 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 科目列表 Request VO")
@Data
public class FmsSubjectListReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "科目类型", example = "1")
@InEnum(FmsSubjectTypeEnum.class)
private Integer type;
}
@@ -1,92 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.framework.excel.core.convert.StringListConvert;
import cn.iocoder.yudao.module.fms.enums.DictTypeConstants;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.module.infra.enums.DictTypeConstants.BOOLEAN_STRING;
/**
* FMS 科目 Response VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 科目 Response VO")
@Data
@ExcelIgnoreUnannotated
public class FmsSubjectRespVO {
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long accountSetId;
@Schema(description = "科目编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1001")
@ExcelProperty(value = "编码", index = 0)
private String code;
@Schema(description = "科目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "库存现金")
@ExcelProperty(value = "名称", index = 1)
private String name;
@Schema(description = "上级科目编号", example = "1024")
private Long parentId;
@Schema(description = "科目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
@Schema(description = "科目类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer category;
@JsonIgnore // 仅 excel 导出使用
@ExcelProperty(value = "类别", index = 2, converter = DictConvert.class)
@DictFormat(DictTypeConstants.SUBJECT_CATEGORY)
private String categoryDictValue;
@Schema(description = "余额方向", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "余额方向", index = 3, converter = DictConvert.class)
@DictFormat(DictTypeConstants.DEBIT_CREDIT_DIRECTION)
private Integer balanceDirection;
@Schema(description = "辅助核算类别编号数组")
private List<Long> auxiliaryTypeIds;
@Schema(description = "外币核算币别编号数组")
private List<Long> currencyIds;
@Schema(description = "是否启用数量核算", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean quantityAccounting;
@Schema(description = "数量单位", example = "件")
@ExcelProperty(value = "数量", index = 5)
private String quantityUnit;
@Schema(description = "是否现金及现金等价物", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty(value = "是否现金项", index = 6, converter = DictConvert.class)
@DictFormat(BOOLEAN_STRING)
private Boolean cash;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "层级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer level;
@Schema(description = "辅助核算类别名称数组")
@ExcelProperty(value = "辅助核算", index = 4, converter = StringListConvert.class)
private List<String> auxiliaryTypeNames;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
@@ -1,113 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.common.FmsDebitCreditDirectionEnum;
import cn.iocoder.yudao.module.fms.enums.config.FmsSubjectCategoryEnum;
import cn.iocoder.yudao.module.fms.enums.config.FmsSubjectTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.AssertTrue;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.util.List;
/**
* FMS 科目保存 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 科目保存 Request VO")
@Data
public class FmsSubjectSaveReqVO {
@Schema(description = "科目编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "科目编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1001")
@NotBlank(message = "科目编码不能为空")
@Size(max = 64, message = "科目编码长度不能超过 64 个字符")
private String code;
@Schema(description = "科目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "库存现金")
@NotBlank(message = "科目名称不能为空")
@Size(max = 255, message = "科目名称长度不能超过 255 个字符")
private String name;
@Schema(description = "上级科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "上级科目编号不能为空")
private Long parentId;
@Schema(description = "科目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "科目类型不能为空")
@InEnum(FmsSubjectTypeEnum.class)
private Integer type;
@Schema(description = "科目类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "科目类别不能为空")
private Integer category;
@Schema(description = "余额方向", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "余额方向不能为空")
@InEnum(FmsDebitCreditDirectionEnum.class)
private Integer balanceDirection;
@Schema(description = "辅助核算类别编号数组")
@NotNull(message = "辅助核算类别编号数组不能为空")
private List<Long> auxiliaryTypeIds;
@Schema(description = "外币核算币别编号数组")
@NotNull(message = "外币核算币别编号数组不能为空")
private List<Long> currencyIds;
@Schema(description = "是否启用数量核算", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "是否启用数量核算不能为空")
private Boolean quantityAccounting;
@Schema(description = "数量单位", example = "件")
@Size(max = 255, message = "数量单位长度不能超过 255 个字符")
private String quantityUnit;
@Schema(description = "是否现金及现金等价物", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "是否现金及现金等价物不能为空")
private Boolean cash;
@Schema(description = "是否迁移上级科目历史数据")
private Boolean migrateParentData;
@Schema(description = "辅助核算历史数据迁移项目数组")
private List<AuxiliaryMapping> auxiliaryMappings;
@AssertTrue(message = "科目类别与科目类型不匹配")
public boolean isCategoryValid() {
return type == null || category == null || FmsSubjectCategoryEnum.valueOf(type, category) != null;
}
@AssertTrue(message = "启用数量核算时数量单位不能为空")
public boolean isQuantityUnitValid() {
return !Boolean.TRUE.equals(quantityAccounting) || StrUtil.isNotBlank(quantityUnit);
}
/**
* 辅助核算历史数据迁移项目
*/
@Data
public static class AuxiliaryMapping {
@Schema(description = "辅助核算类别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "辅助核算类别编号不能为空")
private Long typeId;
@Schema(description = "辅助核算项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "辅助核算项目编号不能为空")
private Long itemId;
}
}
@@ -1,34 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
/**
* FMS 科目状态更新 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 科目状态更新 Request VO")
@Data
public class FmsSubjectStatusReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "科目编号数组", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "科目编号数组不能为空")
private List<Long> ids;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
@InEnum(CommonStatusEnum.class)
private Integer status;
}
@@ -1,33 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* FMS 科目使用情况 Response VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 科目使用情况 Response VO")
@Data
public class FmsSubjectUsageRespVO {
@Schema(description = "下级科目数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Long childCount;
@Schema(description = "凭证分录数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long voucherEntryCount;
@Schema(description = "初始余额数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long initialBalanceCount;
@Schema(description = "辅助核算组合数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
private Long auxiliaryCombinationCount;
@Schema(description = "包含数量数据的记录数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long quantityDataCount;
@Schema(description = "是否已被业务使用", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean used;
}
@@ -1,69 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.vouchertemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - FMS 凭证模板分录 VO")
@Data
public class FmsVoucherTemplateEntryVO {
@Schema(description = "摘要内容", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "摘要不能为空")
@Size(max = 500, message = "摘要长度不能超过 500 个字符")
private String digest;
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "科目不能为空")
private Long subjectId;
@Schema(description = "数量")
@DecimalMin(value = "0", message = "数量不能小于 0")
@Digits(integer = 14, fraction = 4, message = "数量最多保留 4 位小数")
private BigDecimal quantity;
@Schema(description = "单价")
@DecimalMin(value = "0", message = "单价不能小于 0")
@Digits(integer = 12, fraction = 6, message = "单价最多保留 6 位小数")
private BigDecimal unitPrice;
@Schema(description = "借方金额")
@Digits(integer = 16, fraction = 2, message = "借方金额最多保留 2 位小数")
private BigDecimal debitAmount;
@Schema(description = "贷方金额")
@Digits(integer = 16, fraction = 2, message = "贷方金额最多保留 2 位小数")
private BigDecimal creditAmount;
@Schema(description = "辅助核算项目数组")
@Valid
private List<AuxiliaryItem> auxiliaries;
@Schema(description = "管理后台 - FMS 凭证模板分录辅助核算项目")
@Data
public static class AuxiliaryItem {
@Schema(description = "辅助核算类型")
private Integer type;
@Schema(description = "辅助核算类别编号", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "辅助核算类别不能为空")
private Long typeId;
@Schema(description = "辅助核算项目编号", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "辅助核算项目不能为空")
private Long itemId;
@Schema(description = "辅助核算项目名称")
private String name;
}
}
@@ -1,30 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.vouchertemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - FMS 凭证模板 Response VO")
@Data
public class FmsVoucherTemplateRespVO {
@Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long accountSetId;
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED)
private String name;
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED)
private Long categoryId;
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED)
private String categoryName;
@Schema(description = "凭证模板分录数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<FmsVoucherTemplateEntryVO> entries;
}
@@ -1,39 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.vouchertemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - FMS 凭证模板保存 Request VO")
@Data
public class FmsVoucherTemplateSaveReqVO {
@Schema(description = "模板编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "办公用品采购")
@NotBlank(message = "模板名称不能为空")
@Size(max = 255, message = "模板名称长度不能超过 255 个字符")
private String name;
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "模板分类不能为空")
private Long categoryId;
@Schema(description = "凭证模板分录数组", requiredMode = Schema.RequiredMode.REQUIRED)
@Valid
@NotEmpty(message = "凭证模板分录不能为空")
@Size(min = 2, message = "凭证模板至少需要两条分录")
private List<FmsVoucherTemplateEntryVO> entries;
}
@@ -1,19 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.vouchertemplatecategory;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - FMS 凭证模板分类 Response VO")
@Data
public class FmsVoucherTemplateCategoryRespVO {
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long accountSetId;
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "日常收支")
private String name;
}
@@ -1,25 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.vouchertemplatecategory;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - FMS 凭证模板分类保存 Request VO")
@Data
public class FmsVoucherTemplateCategorySaveReqVO {
@Schema(description = "分类编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "日常收支")
@NotBlank(message = "分类名称不能为空")
@Size(max = 255, message = "分类名称长度不能超过 255 个字符")
private String name;
}
@@ -1,38 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.voucherword;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* FMS 凭证字 Response VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 凭证字 Response VO")
@Data
public class FmsVoucherWordRespVO {
@Schema(description = "凭证字编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "凭证字", requiredMode = Schema.RequiredMode.REQUIRED, example = "记")
private String name;
@Schema(description = "打印标题", example = "记账凭证")
private String printTitle;
@Schema(description = "是否默认凭证字", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean defaultStatus;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer sort;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long accountSetId;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
@@ -1,38 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.config.vo.voucherword;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
/**
* FMS 凭证字保存 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - FMS 凭证字保存 Request VO")
@Data
public class FmsVoucherWordSaveReqVO {
@Schema(description = "凭证字编号", example = "1024")
private Long id;
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "凭证字", requiredMode = Schema.RequiredMode.REQUIRED, example = "记")
@NotBlank(message = "凭证字不能为空")
@Size(max = 255, message = "凭证字长度不能超过 255 个字符")
private String name;
@Schema(description = "打印标题", example = "记账凭证")
@Size(max = 255, message = "打印标题长度不能超过 255 个字符")
private String printTitle;
@Schema(description = "是否默认凭证字", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "是否默认凭证字不能为空")
private Boolean defaultStatus;
}
@@ -1,54 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.home;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.fms.controller.admin.home.vo.FmsHomeMetricDetailRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.home.vo.FmsHomeRespVO;
import cn.iocoder.yudao.module.fms.service.home.FmsHomeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 首页")
@RestController
@RequestMapping("/fms/home")
@Validated
public class FmsHomeController {
@Resource
private FmsHomeService homeService;
@GetMapping("/get")
@Operation(summary = "获得首页")
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('fms:home:query')")
public CommonResult<FmsHomeRespVO> getHome(@RequestParam("accountSetId") @NotNull Long accountSetId) {
return success(homeService.getHome(accountSetId, getLoginUserId()));
}
@GetMapping("/metric-detail")
@Operation(summary = "获得财务指标明细")
@Parameters({
@Parameter(name = "accountSetId", description = "账套编号", required = true, example = "1024"),
@Parameter(name = "metricKey", description = "财务指标标识", required = true, example = "income")
})
@PreAuthorize("@ss.hasPermission('fms:home:query')")
public CommonResult<FmsHomeMetricDetailRespVO> getMetricDetail(
@RequestParam("accountSetId") @NotNull Long accountSetId,
@RequestParam("metricKey") @NotBlank String metricKey) {
return success(homeService.getMetricDetail(accountSetId, metricKey, getLoginUserId()));
}
}
@@ -1,55 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.home.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - FMS 首页财务指标明细 Response VO")
@Data
public class FmsHomeMetricDetailRespVO {
@Schema(description = "指标标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "income")
private String key;
@Schema(description = "指标名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "收入")
private String name;
@Schema(description = "财务指标趋势数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Trend> trends;
@Schema(description = "当期科目构成数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Structure> structure;
@Schema(description = "管理后台 - FMS 首页财务指标趋势 Response VO")
@Data
public static class Trend {
@Schema(description = "会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
private String month;
@Schema(description = "指标金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000.00")
private BigDecimal amount;
}
@Schema(description = "管理后台 - FMS 首页财务指标科目构成 Response VO")
@Data
public static class Structure {
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long subjectId;
@Schema(description = "科目编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "5001")
private String subjectCode;
@Schema(description = "科目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "主营业务收入")
private String subjectName;
@Schema(description = "科目金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "8000.00")
private BigDecimal amount;
}
}
@@ -1,64 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.home.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - FMS 首页 Response VO")
@Data
public class FmsHomeRespVO {
@Schema(description = "当前会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
private String currentMonth;
@Schema(description = "当期财务指标数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Metric> metrics;
@Schema(description = "财务指标趋势数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Trend> trends;
@Schema(description = "管理后台 - FMS 首页财务指标 Response VO")
@Data
public static class Metric {
@Schema(description = "指标标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "income")
private String key;
@Schema(description = "指标名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "收入")
private String name;
@Schema(description = "指标金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000.00")
private BigDecimal amount;
}
@Schema(description = "管理后台 - FMS 首页财务指标趋势 Response VO")
@Data
public static class Trend {
@Schema(description = "会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
private String month;
@Schema(description = "动态财务指标数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Metric> metrics;
@Schema(description = "收入", requiredMode = Schema.RequiredMode.REQUIRED)
private BigDecimal income;
@Schema(description = "成本", requiredMode = Schema.RequiredMode.REQUIRED)
private BigDecimal operatingCost;
@Schema(description = "利润", requiredMode = Schema.RequiredMode.REQUIRED)
private BigDecimal profit;
@Schema(description = "费用", requiredMode = Schema.RequiredMode.REQUIRED)
private BigDecimal expense;
@Schema(description = "其他", requiredMode = Schema.RequiredMode.REQUIRED)
private BigDecimal other;
}
}
@@ -1,236 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject.FmsSubjectRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.FmsLedgerAuxiliaryListReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.FmsLedgerListReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.auxiliarybalance.FmsLedgerAuxiliaryBalanceRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.auxiliarydetail.FmsLedgerAuxiliaryDetailRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail.FmsLedgerDetailExportRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail.FmsLedgerDetailRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.general.FmsLedgerGeneralRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.multicolumn.FmsLedgerMultiColumnRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.quantitydetail.FmsLedgerQuantityDetailRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.quantitygeneral.FmsLedgerQuantityGeneralRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.subjectbalance.FmsLedgerSubjectBalanceRespVO;
import cn.iocoder.yudao.module.fms.service.ledger.FmsLedgerService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 账簿")
@RestController
@RequestMapping("/fms/ledger")
@Validated
public class FmsLedgerController {
@Resource
private FmsLedgerService ledgerService;
// ==================== 明细账 ====================
@GetMapping("/detail/list")
@Operation(summary = "获得明细账")
@PreAuthorize("@ss.hasPermission('fms:ledger:detail:query')")
public CommonResult<List<FmsLedgerDetailRespVO>> getDetailList(@Valid FmsLedgerListReqVO listReqVO) {
return success(ledgerService.getDetailList(listReqVO, getLoginUserId()));
}
@GetMapping("/detail/subject-list")
@Operation(summary = "获得指定期间有发生额的明细账科目")
public CommonResult<List<FmsSubjectRespVO>> getDetailSubjectList(@Valid FmsLedgerListReqVO listReqVO) {
// TODO @AI:先查询出来,list 变量;然后在去 convert;字段不多,倒是可以考虑 beanutils 去 copy 下?
return success(convertList(ledgerService.getDetailSubjectList(listReqVO, getLoginUserId()), subject ->
new FmsSubjectRespVO().setId(subject.getId()).setParentId(subject.getParentId())
.setCode(subject.getCode()).setName(subject.getName()).setType(subject.getType())
.setBalanceDirection(subject.getBalanceDirection()).setStatus(subject.getStatus())
.setLevel(subject.getLevel()).setAuxiliaryTypeIds(subject.getAuxiliaryTypeIds())
.setQuantityAccounting(subject.getQuantityAccounting()).setQuantityUnit(subject.getQuantityUnit())));
}
@GetMapping("/detail/export-excel")
@Operation(summary = "导出明细账")
@PreAuthorize("@ss.hasPermission('fms:ledger:detail:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportDetail(@Valid FmsLedgerListReqVO listReqVO, HttpServletResponse response) throws IOException {
List<FmsLedgerDetailExportRespVO> rows = convertList(
ledgerService.getDetailList(listReqVO, getLoginUserId()), item ->
BeanUtils.toBean(item, FmsLedgerDetailExportRespVO.class)
.setSubject(item.getSubjectCode() + " " + item.getSubjectName()));
ExcelUtils.write(response, "明细账.xls", "明细账", FmsLedgerDetailExportRespVO.class, rows);
}
// ==================== 总账 ====================
@GetMapping("/general/list")
@Operation(summary = "获得总账")
@PreAuthorize("@ss.hasPermission('fms:ledger:general:query')")
public CommonResult<List<FmsLedgerGeneralRespVO>> getGeneralList(@Valid FmsLedgerListReqVO listReqVO) {
return success(ledgerService.getGeneralList(listReqVO, getLoginUserId()));
}
@GetMapping("/general/export-excel")
@Operation(summary = "导出总账")
@PreAuthorize("@ss.hasPermission('fms:ledger:general:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportGeneral(@Valid FmsLedgerListReqVO listReqVO, HttpServletResponse response) throws IOException {
ExcelUtils.write(response, "总账.xls", "总账", FmsLedgerGeneralRespVO.class,
ledgerService.getGeneralList(listReqVO, getLoginUserId()));
}
// ==================== 科目余额表 ====================
@GetMapping("/subject-balance/list")
@Operation(summary = "获得科目余额表")
@PreAuthorize("@ss.hasPermission('fms:ledger:subject-balance:query')")
public CommonResult<List<FmsLedgerSubjectBalanceRespVO>> getSubjectBalanceList(@Valid FmsLedgerListReqVO listReqVO) {
return success(ledgerService.getSubjectBalanceList(listReqVO, getLoginUserId()));
}
@GetMapping("/subject-balance/export-excel")
@Operation(summary = "导出科目余额表")
@PreAuthorize("@ss.hasPermission('fms:ledger:subject-balance:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportSubjectBalance(@Valid FmsLedgerListReqVO listReqVO, HttpServletResponse response) throws IOException {
ExcelUtils.write(response, "科目余额表.xls", "科目余额表", FmsLedgerSubjectBalanceRespVO.class,
flattenSubjectBalanceList(ledgerService.getSubjectBalanceList(listReqVO, getLoginUserId())));
}
// ==================== 多栏账 ====================
@GetMapping("/multi-column/list")
@Operation(summary = "获得多栏账")
@PreAuthorize("@ss.hasPermission('fms:ledger:multi-column:query')")
public CommonResult<FmsLedgerMultiColumnRespVO> getMultiColumn(@Valid FmsLedgerListReqVO listReqVO) {
return success(ledgerService.getMultiColumn(listReqVO, getLoginUserId()));
}
@GetMapping("/multi-column/export-excel")
@Operation(summary = "导出多栏账")
@PreAuthorize("@ss.hasPermission('fms:ledger:multi-column:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportMultiColumn(@Valid FmsLedgerListReqVO listReqVO, HttpServletResponse response) throws IOException {
FmsLedgerMultiColumnRespVO result = ledgerService.getMultiColumn(listReqVO, getLoginUserId());
ExcelUtils.write(response, "多栏账.xls", "多栏账",
FmsLedgerMultiColumnExcelHelper.buildHead(result),
FmsLedgerMultiColumnExcelHelper.buildData(result));
}
// ==================== 核算项目明细账 ====================
@GetMapping("/auxiliary-detail/list")
@Operation(summary = "获得核算项目明细账")
@PreAuthorize("@ss.hasPermission('fms:ledger:detail:query')")
public CommonResult<List<FmsLedgerAuxiliaryDetailRespVO>> getAuxiliaryDetailList(@Valid FmsLedgerAuxiliaryListReqVO listReqVO) {
return success(ledgerService.getAuxiliaryDetailList(listReqVO, getLoginUserId()));
}
@GetMapping("/auxiliary-detail/export-excel")
@Operation(summary = "导出核算项目明细账")
@PreAuthorize("@ss.hasPermission('fms:ledger:detail:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportAuxiliaryDetail(@Valid FmsLedgerAuxiliaryListReqVO listReqVO, HttpServletResponse response) throws IOException {
ExcelUtils.write(response, "核算项目明细账.xls", "核算项目明细账",
FmsLedgerAuxiliaryDetailRespVO.class,
ledgerService.getAuxiliaryDetailList(listReqVO, getLoginUserId()));
}
// ==================== 核算项目余额表 ====================
@GetMapping("/auxiliary-balance/list")
@Operation(summary = "获得核算项目余额表")
@PreAuthorize("@ss.hasPermission('fms:ledger:subject-balance:query')")
public CommonResult<List<FmsLedgerAuxiliaryBalanceRespVO>> getAuxiliaryBalanceList(@Valid FmsLedgerAuxiliaryListReqVO listReqVO) {
return success(ledgerService.getAuxiliaryBalanceList(listReqVO, getLoginUserId()));
}
@GetMapping("/auxiliary-balance/export-excel")
@Operation(summary = "导出核算项目余额表")
@PreAuthorize("@ss.hasPermission('fms:ledger:subject-balance:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportAuxiliaryBalance(@Valid FmsLedgerAuxiliaryListReqVO listReqVO, HttpServletResponse response) throws IOException {
ExcelUtils.write(response, "核算项目余额表.xls", "核算项目余额表",
FmsLedgerAuxiliaryBalanceRespVO.class,
ledgerService.getAuxiliaryBalanceList(listReqVO, getLoginUserId()));
}
// ==================== 数量金额明细账 ====================
@GetMapping("/quantity-detail/list")
@Operation(summary = "获得数量金额明细账")
@PreAuthorize("@ss.hasPermission('fms:ledger:detail:query')")
public CommonResult<List<FmsLedgerQuantityDetailRespVO>> getQuantityDetailList(@Valid FmsLedgerListReqVO listReqVO) {
return success(ledgerService.getQuantityDetailList(listReqVO, getLoginUserId()));
}
@GetMapping("/quantity-detail/export-excel")
@Operation(summary = "导出数量金额明细账")
@PreAuthorize("@ss.hasPermission('fms:ledger:detail:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportQuantityDetail(@Valid FmsLedgerListReqVO listReqVO, HttpServletResponse response) throws IOException {
ExcelUtils.write(response, "数量金额明细账.xls", "数量金额明细账",
FmsLedgerQuantityDetailRespVO.class,
ledgerService.getQuantityDetailList(listReqVO, getLoginUserId()));
}
// ==================== 数量金额总账 ====================
@GetMapping("/quantity-general/list")
@Operation(summary = "获得数量金额总账")
@PreAuthorize("@ss.hasPermission('fms:ledger:general:query')")
public CommonResult<List<FmsLedgerQuantityGeneralRespVO>> getQuantityGeneralList(@Valid FmsLedgerListReqVO listReqVO) {
return success(ledgerService.getQuantityGeneralList(listReqVO, getLoginUserId()));
}
@GetMapping("/quantity-general/export-excel")
@Operation(summary = "导出数量金额总账")
@PreAuthorize("@ss.hasPermission('fms:ledger:general:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportQuantityGeneral(@Valid FmsLedgerListReqVO listReqVO, HttpServletResponse response) throws IOException {
ExcelUtils.write(response, "数量金额总账.xls", "数量金额总账",
FmsLedgerQuantityGeneralRespVO.class,
flattenQuantityGeneralList(ledgerService.getQuantityGeneralList(
listReqVO, getLoginUserId())));
}
private static List<FmsLedgerSubjectBalanceRespVO> flattenSubjectBalanceList(List<FmsLedgerSubjectBalanceRespVO> list) {
List<FmsLedgerSubjectBalanceRespVO> result = new ArrayList<>();
list.forEach(item -> {
result.add(item);
result.addAll(flattenSubjectBalanceList(item.getChildren()));
});
return result;
}
private static List<FmsLedgerQuantityGeneralRespVO> flattenQuantityGeneralList(List<FmsLedgerQuantityGeneralRespVO> list) {
List<FmsLedgerQuantityGeneralRespVO> result = new ArrayList<>();
list.forEach(item -> {
if (Boolean.TRUE.equals(item.getQuantityAccounting()) || CollUtil.isNotEmpty(item.getChildren())) {
result.add(item);
}
result.addAll(flattenQuantityGeneralList(item.getChildren()));
});
return result;
}
}
@@ -1,81 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail.FmsLedgerDetailRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.multicolumn.FmsLedgerMultiColumnRespVO;
import cn.iocoder.yudao.module.fms.enums.common.FmsDebitCreditDirectionEnum;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
/**
* FMS 多栏账 Excel 构建工具
*
* @author 芋道源码
*/
public class FmsLedgerMultiColumnExcelHelper {
private FmsLedgerMultiColumnExcelHelper() {
}
/**
* 构建多栏账动态表头
*
* @param result 多栏账结果
* @return 动态表头
*/
public static List<List<String>> buildHead(FmsLedgerMultiColumnRespVO result) {
List<List<String>> head = new ArrayList<>();
head.add(Arrays.asList("日期", "日期"));
head.add(Arrays.asList("凭证字号", "凭证字号"));
head.add(Arrays.asList("摘要", "摘要"));
head.add(Arrays.asList("发生额", "借方"));
head.add(Arrays.asList("发生额", "贷方"));
head.add(Arrays.asList("余额", "方向"));
head.add(Arrays.asList("余额", "金额"));
for (FmsLedgerMultiColumnRespVO.Column column : getColumns(result,
FmsDebitCreditDirectionEnum.DEBIT.getType())) {
head.add(Arrays.asList(FmsDebitCreditDirectionEnum.DEBIT.getName(),
column.getSubjectCode() + "/" + column.getSubjectName()));
}
for (FmsLedgerMultiColumnRespVO.Column column : getColumns(result,
FmsDebitCreditDirectionEnum.CREDIT.getType())) {
head.add(Arrays.asList(FmsDebitCreditDirectionEnum.CREDIT.getName(),
column.getSubjectCode() + "/" + column.getSubjectName()));
}
return head;
}
/**
* 构建多栏账动态数据
*
* @param result 多栏账结果
* @return 动态数据
*/
public static List<List<Object>> buildData(FmsLedgerMultiColumnRespVO result) {
List<FmsLedgerMultiColumnRespVO.Column> debitColumns = getColumns(
result, FmsDebitCreditDirectionEnum.DEBIT.getType());
List<FmsLedgerMultiColumnRespVO.Column> creditColumns = getColumns(
result, FmsDebitCreditDirectionEnum.CREDIT.getType());
List<List<Object>> data = new ArrayList<>();
for (FmsLedgerDetailRespVO row : CollUtil.emptyIfNull(result.getRows())) {
List<Object> values = new ArrayList<>(Arrays.asList(row.getAccountDate(), row.getVoucherNumber(),
row.getDigest(), row.getDebitAmount(), row.getCreditAmount(),
row.getBalanceDirection(), row.getBalance()));
debitColumns.forEach(column -> values.add(row.getColumnAmounts().get(column.getSubjectId())));
creditColumns.forEach(column -> values.add(row.getColumnAmounts().get(column.getSubjectId())));
data.add(values);
}
return data;
}
private static List<FmsLedgerMultiColumnRespVO.Column> getColumns(
FmsLedgerMultiColumnRespVO result, Integer balanceDirection) {
return filterList(CollUtil.emptyIfNull(result.getColumns()),
column -> balanceDirection.equals(column.getBalanceDirection()));
}
}
@@ -1,36 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@Schema(description = "管理后台 - FMS 核算项目账簿列表查询 Request VO")
@Data
public class FmsLedgerAuxiliaryListReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "开始会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
@NotNull(message = "开始会计期间不能为空")
@Pattern(regexp = "\\d{4}-(0[1-9]|1[0-2])", message = "开始会计期间格式不正确")
private String startMonth;
@Schema(description = "结束会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-12")
@NotNull(message = "结束会计期间不能为空")
@Pattern(regexp = "\\d{4}-(0[1-9]|1[0-2])", message = "结束会计期间格式不正确")
private String endMonth;
@Schema(description = "辅助核算类别编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "辅助核算类别编号不能为空")
private Long auxiliaryTypeId;
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "辅助核算项目编号", example = "1024")
private Long auxiliaryItemId;
}
@@ -1,75 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo;
import cn.iocoder.yudao.module.fms.dal.dataobject.voucher.FmsVoucherEntryDO;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
/**
* FMS 账簿凭证分录 VO
*
* @author 芋道源码
*/
@Data
public class FmsLedgerEntryVO {
/**
* 分录编号
*/
private Long entryId;
/**
* 凭证编号
*/
private Long voucherId;
/**
* 科目编号
*/
private Long subjectId;
/**
* 凭证日期
*/
private LocalDateTime voucherTime;
/**
* 凭证号
*/
private Integer voucherNumber;
/**
* 凭证字名称
*/
private String voucherWordName;
/**
* 摘要内容
*/
private String digest;
/**
* 借方金额
*/
private BigDecimal debitAmount;
/**
* 贷方金额
*/
private BigDecimal creditAmount;
/**
* 数量
*/
private BigDecimal quantity;
/**
* 单价
*/
private BigDecimal unitPrice;
/**
* 显示顺序
*/
private Integer sort;
/**
* 辅助核算组合编号
*/
private Long assistCombinationId;
/**
* 辅助核算项目数组
*/
private List<FmsVoucherEntryDO.AuxiliaryItem> auxiliaries;
}
@@ -1,47 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@Schema(description = "管理后台 - FMS 账簿列表查询 Request VO")
@Data
public class FmsLedgerListReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "开始会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
@NotNull(message = "开始会计期间不能为空")
@Pattern(regexp = "\\d{4}-(0[1-9]|1[0-2])", message = "开始会计期间格式不正确")
private String startMonth;
@Schema(description = "结束会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-12")
@NotNull(message = "结束会计期间不能为空")
@Pattern(regexp = "\\d{4}-(0[1-9]|1[0-2])", message = "结束会计期间格式不正确")
private String endMonth;
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "起始科目编号", example = "1024")
private Long startSubjectId;
@Schema(description = "结束科目编号", example = "2048")
private Long endSubjectId;
@Schema(description = "最小科目级次", example = "1")
@Min(value = 1, message = "最小科目级次不能小于 1")
@Max(value = 10, message = "最小科目级次不能大于 10")
private Integer minLevel;
@Schema(description = "最大科目级次", example = "4")
@Min(value = 1, message = "最大科目级次不能小于 1")
@Max(value = 10, message = "最大科目级次不能大于 10")
private Integer maxLevel;
}
@@ -1,59 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.auxiliarybalance;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Schema(description = "管理后台 - FMS 核算项目余额 Response VO")
@Data
@ExcelIgnoreUnannotated
public class FmsLedgerAuxiliaryBalanceRespVO {
@Schema(description = "辅助核算项目编号", requiredMode = Schema.RequiredMode.REQUIRED)
private Long auxiliaryItemId;
@Schema(description = "编码", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("编码")
private String code;
@Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("项目名称")
private String name;
@Schema(description = "期初借方余额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("期初借方")
private BigDecimal openingDebitAmount;
@Schema(description = "期初贷方余额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("期初贷方")
private BigDecimal openingCreditAmount;
@Schema(description = "本期借方发生额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("本期借方")
private BigDecimal periodDebitAmount;
@Schema(description = "本期贷方发生额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("本期贷方")
private BigDecimal periodCreditAmount;
@Schema(description = "本年累计借方发生额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("本年累计借方")
private BigDecimal yearDebitAmount;
@Schema(description = "本年累计贷方发生额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("本年累计贷方")
private BigDecimal yearCreditAmount;
@Schema(description = "期末借方余额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("期末借方")
private BigDecimal endingDebitAmount;
@Schema(description = "期末贷方余额", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("期末贷方")
private BigDecimal endingCreditAmount;
}
@@ -1,72 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.auxiliarydetail;
import com.fasterxml.jackson.annotation.JsonFormat;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
@Schema(description = "管理后台 - FMS 核算项目明细账 Response VO")
@Data
@ExcelIgnoreUnannotated
public class FmsLedgerAuxiliaryDetailRespVO {
public static final Integer ROW_TYPE_OPENING = 1;
public static final Integer ROW_TYPE_VOUCHER = 2;
public static final Integer ROW_TYPE_PERIOD_TOTAL = 3;
public static final Integer ROW_TYPE_YEAR_TOTAL = 4;
@Schema(description = "行类型", example = "2")
private Integer rowType;
@Schema(description = "分录编号", example = "1024")
private Long entryId;
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "科目编码", example = "1001")
private String subjectCode;
@Schema(description = "科目名称", example = "库存现金")
private String subjectName;
@Schema(description = "会计期间", example = "2026-08")
private String period;
@Schema(description = "日期")
@JsonFormat(pattern = "yyyy-MM-dd")
@ExcelProperty("日期")
private LocalDate accountDate;
@Schema(description = "凭证编号", example = "1024")
private Long voucherId;
@Schema(description = "凭证字号", example = "记-1")
@ExcelProperty("凭证字号")
private String voucherNumber;
@Schema(description = "摘要", example = "报销办公用品")
@ExcelProperty("摘要")
private String digest;
@Schema(description = "借方金额")
@ExcelProperty("借方")
private BigDecimal debitAmount;
@Schema(description = "贷方金额")
@ExcelProperty("贷方")
private BigDecimal creditAmount;
@Schema(description = "余额方向", example = "借")
@ExcelProperty("方向")
private String balanceDirection;
@Schema(description = "余额")
@ExcelProperty("余额")
private BigDecimal balance;
}
@@ -1,43 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* FMS 明细账导出 Response VO
*
* @author 芋道源码
*/
@Data
@ExcelIgnoreUnannotated
public class FmsLedgerDetailExportRespVO {
@ExcelProperty("科目")
private String subject;
@ExcelProperty("日期")
private LocalDate accountDate;
@ExcelProperty("凭证字号")
private String voucherNumber;
@ExcelProperty("摘要")
private String digest;
@ExcelProperty("借方")
private BigDecimal debitAmount;
@ExcelProperty("贷方")
private BigDecimal creditAmount;
@ExcelProperty("方向")
private String balanceDirection;
@ExcelProperty("余额")
private BigDecimal balance;
}
@@ -1,94 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail;
import com.fasterxml.jackson.annotation.JsonFormat;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
@Schema(description = "管理后台 - FMS 账簿明细 Response VO")
@Data
@ExcelIgnoreUnannotated
public class FmsLedgerDetailRespVO {
public static final Integer ROW_TYPE_OPENING = 1;
public static final Integer ROW_TYPE_VOUCHER = 2;
public static final Integer ROW_TYPE_PERIOD_TOTAL = 3;
public static final Integer ROW_TYPE_YEAR_TOTAL = 4;
public static final Integer ROW_TYPE_ENDING = 5;
@Schema(description = "行类型", example = "2")
private Integer rowType;
@Schema(description = "分录编号", example = "1024")
private Long entryId;
@Schema(description = "分录科目编号", example = "1024")
private Long entrySubjectId;
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "科目编码", example = "1001")
private String subjectCode;
@Schema(description = "科目名称", example = "库存现金")
private String subjectName;
@Schema(description = "会计期间", example = "2026-08")
private String period;
@Schema(description = "日期")
@JsonFormat(pattern = "yyyy-MM-dd")
@ExcelProperty("日期")
private LocalDate accountDate;
@Schema(description = "凭证编号", example = "1024")
private Long voucherId;
@Schema(description = "凭证字号", example = "记-1")
@ExcelProperty("凭证字号")
private String voucherNumber;
@Schema(description = "摘要", example = "报销办公用品")
@ExcelProperty("摘要")
private String digest;
@Schema(description = "借方金额")
@ExcelProperty("借方")
private BigDecimal debitAmount;
@Schema(description = "贷方金额")
@ExcelProperty("贷方")
private BigDecimal creditAmount;
@Schema(description = "余额方向", example = "借")
@ExcelProperty("方向")
private String balanceDirection;
@Schema(description = "余额")
@ExcelProperty("余额")
private BigDecimal balance;
@Schema(description = "借方数量")
private BigDecimal debitQuantity;
@Schema(description = "贷方数量")
private BigDecimal creditQuantity;
@Schema(description = "结存数量")
private BigDecimal balanceQuantity;
@Schema(description = "单价")
private BigDecimal unitPrice;
@Schema(description = "计量单位", example = "件")
private String quantityUnit;
@Schema(description = "多栏账科目金额")
private java.util.Map<Long, BigDecimal> columnAmounts;
}
@@ -1,53 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.general;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - FMS 总账 Response VO")
@Data
@ExcelIgnoreUnannotated
public class FmsLedgerGeneralRespVO {
@Schema(description = "行类型", example = "2")
private Integer rowType;
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "科目编码", example = "1001")
@ExcelProperty("科目编码")
private String subjectCode;
@Schema(description = "科目名称", example = "库存现金")
@ExcelProperty("科目名称")
private String subjectName;
@Schema(description = "会计期间", example = "2026-08")
@ExcelProperty("期间")
private String period;
@Schema(description = "摘要", example = "本期合计")
@ExcelProperty("摘要")
private String digest;
@Schema(description = "借方金额")
@ExcelProperty("借方")
private BigDecimal debitAmount;
@Schema(description = "贷方金额")
@ExcelProperty("贷方")
private BigDecimal creditAmount;
@Schema(description = "余额方向", example = "借")
@ExcelProperty("方向")
private String balanceDirection;
@Schema(description = "余额")
@ExcelProperty("余额")
private BigDecimal balance;
}
@@ -1,40 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.multicolumn;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail.FmsLedgerDetailRespVO;
import java.util.List;
@Schema(description = "管理后台 - FMS 多栏账 Response VO")
@Data
@Accessors(chain = true)
public class FmsLedgerMultiColumnRespVO {
@Schema(description = "动态科目列")
private List<Column> columns;
@Schema(description = "账簿行")
private List<FmsLedgerDetailRespVO> rows;
@Schema(description = "管理后台 - FMS 多栏账科目列 Response VO")
@Data
public static class Column {
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "科目编码", example = "560101")
private String subjectCode;
@Schema(description = "科目名称", example = "办公用品")
private String subjectName;
@Schema(description = "余额方向", example = "1")
private Integer balanceDirection;
}
}
@@ -1,104 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.quantitydetail;
import com.fasterxml.jackson.annotation.JsonFormat;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
@Schema(description = "管理后台 - FMS 数量金额明细账 Response VO")
@Data
@ExcelIgnoreUnannotated
public class FmsLedgerQuantityDetailRespVO {
public static final Integer ROW_TYPE_OPENING = 1;
public static final Integer ROW_TYPE_VOUCHER = 2;
public static final Integer ROW_TYPE_PERIOD_TOTAL = 3;
public static final Integer ROW_TYPE_YEAR_TOTAL = 4;
@Schema(description = "行类型", example = "2")
private Integer rowType;
@Schema(description = "分录编号", example = "1024")
private Long entryId;
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "科目编码", example = "1405")
private String subjectCode;
@Schema(description = "科目名称", example = "库存商品")
private String subjectName;
@Schema(description = "会计期间", example = "2026-08")
private String period;
@Schema(description = "日期")
@JsonFormat(pattern = "yyyy-MM-dd")
@ExcelProperty("日期")
private LocalDate accountDate;
@Schema(description = "凭证编号", example = "1024")
private Long voucherId;
@Schema(description = "凭证字号", example = "记-1")
@ExcelProperty("凭证字号")
private String voucherNumber;
@Schema(description = "摘要", example = "采购商品")
@ExcelProperty("摘要")
private String digest;
@Schema(description = "借方金额")
@ExcelProperty("借方金额")
private BigDecimal debitAmount;
@Schema(description = "贷方金额")
@ExcelProperty("贷方金额")
private BigDecimal creditAmount;
@Schema(description = "余额方向", example = "借")
@ExcelProperty("方向")
private String balanceDirection;
@Schema(description = "余额")
@ExcelProperty("结存金额")
private BigDecimal balance;
@Schema(description = "借方数量")
@ExcelProperty("借方数量")
private BigDecimal debitQuantity;
@Schema(description = "贷方数量")
@ExcelProperty("贷方数量")
private BigDecimal creditQuantity;
@Schema(description = "结存数量")
@ExcelProperty("结存数量")
private BigDecimal balanceQuantity;
@Schema(description = "单价")
@ExcelProperty("分录单价")
private BigDecimal unitPrice;
@ExcelProperty("期初单价")
private BigDecimal openingUnitPrice;
@ExcelProperty("本期单价")
private BigDecimal periodUnitPrice;
@ExcelProperty("累计单价")
private BigDecimal yearUnitPrice;
@ExcelProperty("期末单价")
private BigDecimal endingUnitPrice;
@Schema(description = "计量单位", example = "件")
@ExcelProperty("单位")
private String quantityUnit;
}
@@ -1,120 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.quantitygeneral;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Schema(description = "管理后台 - FMS 数量金额总账 Response VO")
@Data
@ExcelIgnoreUnannotated
public class FmsLedgerQuantityGeneralRespVO {
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "科目编码", example = "1405")
@ExcelProperty({"科目", "编码"})
private String subjectCode;
@Schema(description = "科目名称", example = "库存商品")
@ExcelProperty({"科目", "名称"})
private String subjectName;
@Schema(description = "科目级次", example = "1")
private Integer level;
@Schema(description = "是否启用数量核算")
private Boolean quantityAccounting;
@Schema(description = "计量单位", example = "件")
@ExcelProperty({"基础信息", "单位"})
private String quantityUnit;
@Schema(description = "期初余额方向", example = "借")
@ExcelProperty({"期初余额", "方向"})
private String openingBalanceDirection;
@Schema(description = "期初数量")
@ExcelProperty({"期初余额", "数量"})
private BigDecimal openingQuantity;
@Schema(description = "期初单价")
@ExcelProperty({"期初余额", "单价"})
private BigDecimal openingUnitPrice;
@Schema(description = "期初借方余额")
@ExcelIgnore
private BigDecimal openingDebitAmount;
@Schema(description = "期初贷方余额")
@ExcelIgnore
private BigDecimal openingCreditAmount;
@ExcelProperty({"期初余额", "金额"})
private BigDecimal openingAmount;
@Schema(description = "本期借方数量")
@ExcelProperty({"本期借方", "数量"})
private BigDecimal periodDebitQuantity;
@Schema(description = "本期借方发生额")
@ExcelProperty({"本期借方", "金额"})
private BigDecimal periodDebitAmount;
@Schema(description = "本期贷方数量")
@ExcelProperty({"本期贷方", "数量"})
private BigDecimal periodCreditQuantity;
@Schema(description = "本期贷方发生额")
@ExcelProperty({"本期贷方", "金额"})
private BigDecimal periodCreditAmount;
@Schema(description = "本年累计借方数量")
@ExcelProperty({"本年累计借方", "数量"})
private BigDecimal yearDebitQuantity;
@Schema(description = "本年累计借方发生额")
@ExcelProperty({"本年累计借方", "金额"})
private BigDecimal yearDebitAmount;
@Schema(description = "本年累计贷方数量")
@ExcelProperty({"本年累计贷方", "数量"})
private BigDecimal yearCreditQuantity;
@Schema(description = "本年累计贷方发生额")
@ExcelProperty({"本年累计贷方", "金额"})
private BigDecimal yearCreditAmount;
@Schema(description = "期末余额方向", example = "借")
@ExcelProperty({"期末余额", "方向"})
private String endingBalanceDirection;
@Schema(description = "期末数量")
@ExcelProperty({"期末余额", "数量"})
private BigDecimal endingQuantity;
@Schema(description = "期末单价")
@ExcelProperty({"期末余额", "单价"})
private BigDecimal endingUnitPrice;
@Schema(description = "期末借方余额")
@ExcelIgnore
private BigDecimal endingDebitAmount;
@Schema(description = "期末贷方余额")
@ExcelIgnore
private BigDecimal endingCreditAmount;
@ExcelProperty({"期末余额", "金额"})
private BigDecimal endingAmount;
@Schema(description = "下级科目")
private List<FmsLedgerQuantityGeneralRespVO> children = new ArrayList<>();
}
@@ -1,116 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.subjectbalance;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Schema(description = "管理后台 - FMS 科目余额 Response VO")
@Data
@Accessors(chain = true)
@ExcelIgnoreUnannotated
public class FmsLedgerSubjectBalanceRespVO {
public static final int NODE_TYPE_SUBJECT = 1;
public static final int NODE_TYPE_AUXILIARY_COMBINATION = 2;
@Schema(description = "节点唯一键", example = "S:1024")
private String nodeKey;
@Schema(description = "节点类型", example = "1")
private Integer nodeType;
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "辅助核算组合编号", example = "2048")
private Long assistCombinationId;
@Schema(description = "科目编码", example = "1001")
@ExcelProperty("科目编码")
private String subjectCode;
@Schema(description = "科目名称", example = "库存现金")
@ExcelProperty("科目名称")
private String subjectName;
@Schema(description = "科目级次", example = "1")
private Integer level;
@Schema(description = "是否启用数量核算")
private Boolean quantityAccounting;
@Schema(description = "计量单位", example = "件")
private String quantityUnit;
@Schema(description = "期初借方余额")
@ExcelProperty("期初借方")
private BigDecimal openingDebitAmount;
@Schema(description = "期初贷方余额")
@ExcelProperty("期初贷方")
private BigDecimal openingCreditAmount;
@Schema(description = "期初余额方向", example = "借")
private String openingBalanceDirection;
@Schema(description = "期初数量")
private BigDecimal openingQuantity;
@Schema(description = "期初单价")
private BigDecimal openingUnitPrice;
@Schema(description = "本期借方发生额")
@ExcelProperty("本期借方")
private BigDecimal periodDebitAmount;
@Schema(description = "本期贷方发生额")
@ExcelProperty("本期贷方")
private BigDecimal periodCreditAmount;
@Schema(description = "本期借方数量")
private BigDecimal periodDebitQuantity;
@Schema(description = "本期贷方数量")
private BigDecimal periodCreditQuantity;
@Schema(description = "本年累计借方发生额")
@ExcelProperty("本年累计借方")
private BigDecimal yearDebitAmount;
@Schema(description = "本年累计贷方发生额")
@ExcelProperty("本年累计贷方")
private BigDecimal yearCreditAmount;
@Schema(description = "本年累计借方数量")
private BigDecimal yearDebitQuantity;
@Schema(description = "本年累计贷方数量")
private BigDecimal yearCreditQuantity;
@Schema(description = "期末借方余额")
@ExcelProperty("期末借方")
private BigDecimal endingDebitAmount;
@Schema(description = "期末贷方余额")
@ExcelProperty("期末贷方")
private BigDecimal endingCreditAmount;
@Schema(description = "期末余额方向", example = "借")
private String endingBalanceDirection;
@Schema(description = "期末数量")
private BigDecimal endingQuantity;
@Schema(description = "期末单价")
private BigDecimal endingUnitPrice;
@Schema(description = "下级科目")
private List<FmsLedgerSubjectBalanceRespVO> children = new ArrayList<>();
}
@@ -1,72 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.report;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.balance.FmsBalanceSheetCheckRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.balance.FmsBalanceSheetRowRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.FmsReportFormulaUpdateReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.FmsReportListReqVO;
import cn.iocoder.yudao.module.fms.service.report.FmsBalanceSheetService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 资产负债表")
@RestController
@RequestMapping("/fms/report/balance-sheet")
@Validated
public class FmsBalanceSheetController {
@Resource
private FmsBalanceSheetService balanceSheetService;
@GetMapping("/get")
@Operation(summary = "获得资产负债表")
@PreAuthorize("@ss.hasPermission('fms:report:balance-sheet:query')")
public CommonResult<List<FmsBalanceSheetRowRespVO>> getBalanceSheet(@Valid FmsReportListReqVO listReqVO) {
return success(balanceSheetService.getBalanceSheet(listReqVO, getLoginUserId()));
}
@GetMapping("/export-excel")
@Operation(summary = "导出资产负债表")
@PreAuthorize("@ss.hasPermission('fms:report:balance-sheet:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportBalanceSheet(@Valid FmsReportListReqVO listReqVO,
HttpServletResponse response) throws IOException {
List<FmsBalanceSheetRowRespVO> list = balanceSheetService.getBalanceSheet(listReqVO, getLoginUserId());
ExcelUtils.write(response, "资产负债表.xls", "资产负债表", FmsBalanceSheetRowRespVO.class, list);
}
@PutMapping("/update")
@Operation(summary = "更新资产负债表公式")
@PreAuthorize("@ss.hasPermission('fms:report:balance-sheet:update')")
public CommonResult<Boolean> updateBalanceSheetFormula(@Valid @RequestBody FmsReportFormulaUpdateReqVO updateReqVO) {
balanceSheetService.updateBalanceSheetFormula(updateReqVO, getLoginUserId());
return success(true);
}
@GetMapping("/check")
@Operation(summary = "检查资产负债表")
@PreAuthorize("@ss.hasPermission('fms:report:balance-sheet:query')")
public CommonResult<FmsBalanceSheetCheckRespVO> checkBalanceSheet(@Valid FmsReportListReqVO listReqVO) {
return success(balanceSheetService.checkBalanceSheet(listReqVO, getLoginUserId()));
}
}
@@ -1,102 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.report;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.cashflow.FmsCashFlowAdjustmentRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.cashflow.FmsCashFlowAdjustmentUpdateReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.cashflow.FmsCashFlowCheckRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.cashflow.FmsCashFlowStatementUpdateReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.FmsReportFormulaUpdateReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.FmsReportItemRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.FmsReportListReqVO;
import cn.iocoder.yudao.module.fms.service.report.FmsCashFlowStatementService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 现金流量表")
@RestController
@RequestMapping("/fms/report/cash-flow-statement")
@Validated
public class FmsCashFlowStatementController {
@Resource
private FmsCashFlowStatementService cashFlowStatementService;
@GetMapping("/get")
@Operation(summary = "获得现金流量表")
@PreAuthorize("@ss.hasPermission('fms:report:cash-flow-statement:query')")
public CommonResult<List<FmsReportItemRespVO>> getCashFlowStatement(
@Valid FmsReportListReqVO listReqVO) {
return success(cashFlowStatementService.getCashFlowStatement(listReqVO, getLoginUserId()));
}
@GetMapping("/export-excel")
@Operation(summary = "导出现金流量表")
@PreAuthorize("@ss.hasPermission('fms:report:cash-flow-statement:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportCashFlowStatement(@Valid FmsReportListReqVO listReqVO,
HttpServletResponse response) throws IOException {
List<FmsReportItemRespVO> list = cashFlowStatementService.getCashFlowStatement(
listReqVO, getLoginUserId());
ExcelUtils.write(response, "现金流量表.xls", "现金流量表", FmsReportItemRespVO.class, list);
}
@PutMapping("/update")
@Operation(summary = "更新现金流量表")
@PreAuthorize("@ss.hasPermission('fms:report:cash-flow-statement:update')")
public CommonResult<Boolean> updateCashFlowStatement(
@Valid @RequestBody FmsCashFlowStatementUpdateReqVO updateReqVO) {
cashFlowStatementService.updateCashFlowStatement(updateReqVO, getLoginUserId());
return success(true);
}
@GetMapping("/check")
@Operation(summary = "检查现金流量表")
@PreAuthorize("@ss.hasPermission('fms:report:cash-flow-statement:query')")
public CommonResult<FmsCashFlowCheckRespVO> checkCashFlowStatement(
@Valid FmsReportListReqVO listReqVO) {
return success(cashFlowStatementService.checkCashFlowStatement(listReqVO, getLoginUserId()));
}
@GetMapping("/adjustment/list")
@Operation(summary = "获得现金流量辅助数据列表")
@PreAuthorize("@ss.hasPermission('fms:report:cash-flow-statement:query')")
public CommonResult<List<FmsCashFlowAdjustmentRespVO>> getCashFlowAdjustmentList(@Valid FmsReportListReqVO listReqVO) {
return success(cashFlowStatementService.getCashFlowAdjustmentList(listReqVO, getLoginUserId()));
}
@PutMapping("/adjustment/update")
@Operation(summary = "更新现金流量辅助数据")
@PreAuthorize("@ss.hasPermission('fms:report:cash-flow-statement:update')")
public CommonResult<Boolean> updateCashFlowAdjustment(@Valid @RequestBody FmsCashFlowAdjustmentUpdateReqVO updateReqVO) {
cashFlowStatementService.updateCashFlowAdjustment(updateReqVO, getLoginUserId());
return success(true);
}
@PutMapping("/adjustment/update-formula")
@Operation(summary = "更新现金流量辅助数据公式")
@PreAuthorize("@ss.hasPermission('fms:report:cash-flow-statement:update')")
public CommonResult<Boolean> updateCashFlowAdjustmentFormula(@Valid @RequestBody FmsReportFormulaUpdateReqVO updateReqVO) {
cashFlowStatementService.updateCashFlowAdjustmentFormula(updateReqVO, getLoginUserId());
return success(true);
}
}
@@ -1,71 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.report;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.income.FmsIncomeStatementCheckRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.FmsReportFormulaUpdateReqVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.FmsReportItemRespVO;
import cn.iocoder.yudao.module.fms.controller.admin.report.vo.FmsReportListReqVO;
import cn.iocoder.yudao.module.fms.service.report.FmsIncomeStatementService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - FMS 利润表")
@RestController
@RequestMapping("/fms/report/income-statement")
@Validated
public class FmsIncomeStatementController {
@Resource
private FmsIncomeStatementService incomeStatementService;
@GetMapping("/get")
@Operation(summary = "获得利润表")
@PreAuthorize("@ss.hasPermission('fms:report:income-statement:query')")
public CommonResult<List<FmsReportItemRespVO>> getIncomeStatement(@Valid FmsReportListReqVO listReqVO) {
return success(incomeStatementService.getIncomeStatement(listReqVO, getLoginUserId()));
}
@GetMapping("/export-excel")
@Operation(summary = "导出利润表")
@PreAuthorize("@ss.hasPermission('fms:report:income-statement:export')")
@ApiAccessLog(operateType = OperateTypeEnum.EXPORT)
public void exportIncomeStatement(@Valid FmsReportListReqVO listReqVO, HttpServletResponse response) throws IOException {
List<FmsReportItemRespVO> list = incomeStatementService.getIncomeStatement(listReqVO, getLoginUserId());
ExcelUtils.write(response, "利润表.xls", "利润表", FmsReportItemRespVO.class, list);
}
@PutMapping("/update")
@Operation(summary = "更新利润表公式")
@PreAuthorize("@ss.hasPermission('fms:report:income-statement:update')")
public CommonResult<Boolean> updateIncomeStatementFormula(@Valid @RequestBody FmsReportFormulaUpdateReqVO updateReqVO) {
incomeStatementService.updateIncomeStatementFormula(updateReqVO, getLoginUserId());
return success(true);
}
@GetMapping("/check")
@Operation(summary = "检查利润表")
@PreAuthorize("@ss.hasPermission('fms:report:income-statement:query')")
public CommonResult<FmsIncomeStatementCheckRespVO> checkIncomeStatement(@Valid FmsReportListReqVO listReqVO) {
return success(incomeStatementService.checkIncomeStatement(listReqVO, getLoginUserId()));
}
}
@@ -1,39 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.report.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - FMS 报表公式项 Response VO")
@Data
public class FmsReportFormulaRespVO {
@Schema(description = "科目编号", example = "1024")
private Long subjectId;
@Schema(description = "科目名称", example = "库存现金")
private String subjectName;
@Schema(description = "科目编码", example = "1001")
private String subjectNumber;
@Schema(description = "运算符", example = "+")
private String operator;
@Schema(description = "取数规则", example = "0")
private Integer rules;
@Schema(description = "期初金额", example = "100.00")
private BigDecimal openingAmount;
@Schema(description = "期末金额", example = "200.00")
private BigDecimal closingAmount;
@Schema(description = "本期金额", example = "100.00")
private BigDecimal currentAmount;
@Schema(description = "本年累计金额", example = "200.00")
private BigDecimal yearAmount;
}
@@ -1,51 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.report.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.fms.enums.report.FmsFormulaRuleEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Schema(description = "管理后台 - FMS 报表公式更新 Request VO")
@Data
public class FmsReportFormulaUpdateReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "配置编号不能为空")
private Long id;
@Schema(description = "公式项数组", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "公式项数组不能为空")
@Valid
private List<Formula> formulas = new ArrayList<>();
@Schema(description = "管理后台 - FMS 报表公式项 Request VO")
@Data
public static class Formula {
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "科目编号不能为空")
private Long subjectId;
@Schema(description = "运算符", requiredMode = Schema.RequiredMode.REQUIRED, example = "+")
@NotNull(message = "运算符不能为空")
@Pattern(regexp = "[+-]", message = "运算符必须是 + 或 -")
private String operator;
@Schema(description = "取数规则", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "取数规则不能为空")
@InEnum(value = FmsFormulaRuleEnum.class, message = "取数规则必须是 {value}")
private Integer rules;
}
}
@@ -1,49 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.report.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - FMS 财务报表项目 Response VO")
@Data
@ExcelIgnoreUnannotated
public class FmsReportItemRespVO {
@Schema(description = "配置编号", example = "1024")
private Long id;
@Schema(description = "项目名称", example = "货币资金")
@ExcelProperty("项目")
private String name;
@Schema(description = "行次", example = "1")
@ExcelProperty("行次")
private Integer rowNo;
@Schema(description = "层级", example = "2")
private Integer level;
@Schema(description = "是否可编辑", example = "true")
private Boolean editable;
@Schema(description = "公式")
private String formula;
@Schema(description = "期初金额", example = "100.00")
private BigDecimal openingAmount;
@Schema(description = "期末金额", example = "200.00")
private BigDecimal closingAmount;
@Schema(description = "本年累计金额", example = "200.00")
@ExcelProperty("本年累计金额")
private BigDecimal yearAmount;
@Schema(description = "本期金额", example = "100.00")
@ExcelProperty("本期金额")
private BigDecimal currentAmount;
}
@@ -1,26 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.report.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@Schema(description = "管理后台 - FMS 财务报表查询 Request VO")
@Data
public class FmsReportListReqVO {
@Schema(description = "账套编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "账套编号不能为空")
private Long accountSetId;
@Schema(description = "开始会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
@NotNull(message = "开始会计期间不能为空")
@Pattern(regexp = "\\d{4}-(0[1-9]|1[0-2])", message = "开始会计期间格式不正确")
private String startMonth;
@Schema(description = "结束会计期间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-08")
@NotNull(message = "结束会计期间不能为空")
@Pattern(regexp = "\\d{4}-(0[1-9]|1[0-2])", message = "结束会计期间格式不正确")
private String endMonth;
}
@@ -1,46 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.report.vo.balance;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - FMS 资产负债表检查 Response VO")
@Data
public class FmsBalanceSheetCheckRespVO {
@Schema(description = "报表是否平衡", example = "true")
private Boolean balanced;
@Schema(description = "初始余额是否平衡", example = "true")
private Boolean initialBalanceBalanced;
@Schema(description = "损益是否已结转", example = "true")
private Boolean profitLossTransferred;
@Schema(description = "年初余额差额", example = "0.00")
private BigDecimal openingDifferenceAmount;
@Schema(description = "期末余额差额", example = "0.00")
private BigDecimal closingDifferenceAmount;
@Schema(description = "未纳入报表公式的科目")
private List<UnmappedSubject> unmappedSubjects;
@Schema(description = "管理后台 - FMS 未纳入报表公式的科目")
@Data
public static class UnmappedSubject {
@Schema(description = "科目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "科目编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1001")
private String code;
@Schema(description = "科目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "库存现金")
private String name;
}
}
@@ -1,74 +0,0 @@
package cn.iocoder.yudao.module.fms.controller.admin.report.vo.balance;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - FMS 资产负债表行 Response VO")
@Data
@ExcelIgnoreUnannotated
public class FmsBalanceSheetRowRespVO {
@Schema(description = "行编号", example = "1")
private Integer rowId;
@Schema(description = "资产项目配置编号", example = "1024")
private Long assetId;
@Schema(description = "资产项目名称", example = "货币资金")
@ExcelProperty("资产")
private String assetName;
@Schema(description = "资产项目行次", example = "1")
@ExcelProperty("行次")
private Integer assetRowNo;
@Schema(description = "资产项目期末余额", example = "200.00")
@ExcelProperty("期末余额")
private BigDecimal assetClosingAmount;
@Schema(description = "资产项目年初余额", example = "100.00")
@ExcelProperty("年初余额")
private BigDecimal assetOpeningAmount;
@Schema(description = "资产项目层级", example = "2")
private Integer assetLevel;
@Schema(description = "资产项目是否可编辑", example = "true")
private Boolean assetEditable;
@Schema(description = "资产项目公式")
private String assetFormula;
@Schema(description = "负债和所有者权益项目配置编号", example = "1024")
private Long liabilityId;
@Schema(description = "负债和所有者权益项目名称", example = "短期借款")
@ExcelProperty("负债和所有者权益")
private String liabilityName;
@Schema(description = "负债和所有者权益项目行次", example = "31")
@ExcelProperty("行次")
private Integer liabilityRowNo;
@Schema(description = "负债和所有者权益项目期末余额", example = "200.00")
@ExcelProperty("期末余额")
private BigDecimal liabilityClosingAmount;
@Schema(description = "负债和所有者权益项目年初余额", example = "100.00")
@ExcelProperty("年初余额")
private BigDecimal liabilityOpeningAmount;
@Schema(description = "负债和所有者权益项目层级", example = "2")
private Integer liabilityLevel;
@Schema(description = "负债和所有者权益项目是否可编辑", example = "true")
private Boolean liabilityEditable;
@Schema(description = "负债和所有者权益项目公式")
private String liabilityFormula;
}

Some files were not shown because too many files have changed in this diff Show More