网站放到国外空间,智能软件开发就业前景,江苏宜安建设有限公司 网站,苏州中心有什么好玩的报表是每个记账应用所具备的功能#xff0c;要实现报表功能就需要把账本的核心功能#xff08;记账#xff09;完成#xff0c;因此报表服务作为本专栏第一部分单体应用开发中最后一个要实现的功能#xff0c;这一篇文章很简单#xff0c;我们一起来实现一个简单的报表服…报表是每个记账应用所具备的功能要实现报表功能就需要把账本的核心功能记账完成因此报表服务作为本专栏第一部分单体应用开发中最后一个要实现的功能这一篇文章很简单我们一起来实现一个简单的报表服务。
一、需求
需求很简单我们只需要提供一个接口供客户端查询时使用下面是需求。
编号需求说明1报表查询1. 传入报表类型年份、月份查询对应的报表数据2. 月份参数可以为空3. 报表类型包括月报表、季度报表、年报表
二、功能编写 模型编写 根据上一小节的需求我们得出了传入的参数需要包含报表类型、年份以及月份其中月份可以为空视图模型如下 using System.ComponentModel.DataAnnotations;namespace SporeAccounting.Models.ViewModels;/// summary
/// 报表视图模型
/// /summary
public class ReportViewModel
{/// summary/// 报表类型/// /summary[Required(ErrorMessage 报表类型不能为空)]public ReportTypeEnum ReportType { get; set; }/// summary/// 年份/// /summary[Required(ErrorMessage 年份不能为空)]public int Year { get; set; }/// summary/// 月份/// /summarypublic int? Month { get; set; }
}我们一起来看看数据库表映射类需要包含哪些属性吧。首先需要年份、月份和季度这几个字段它们可以提供清晰的时间维度方便用户在不同时间范围内查询和统计数据比如生成年度报告、月度账单或季度分析等。 其次需要一个主题或用途字段用于标识报表的具体内容。此外还需要一个报表类型字段可以用枚举值来区分不同类型的报表如季度报表、月度报表、年度报表。 因为报表通常涉及金额所以必须有一个金额字段来准确记录相关数据。为了帮助用户清楚了解每个支出分类的具体占比和总金额还需要一个支出分类字段。 最后考虑到每个报表只能对应一个用户我们还需要一个字段来标识用户以确保报表和用户之间的关联关系。 这样设计既能满足报表统计和分析的需求也能保证数据结构清晰合理。通过分析我们得出如下代码 using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using SporeAccounting.BaseModels;namespace SporeAccounting.Models;/// summary
/// 报表
/// /summary
[Table(Report)]
public class Report : BaseModel
{/// summary/// 年份/// /summary[Required][Column(TypeName int)]public int Year { get; set; }/// summary/// 月份/// /summary[Column(TypeName int)]public int? Month { get; set; }/// summary/// 季度/// /summary[Column(TypeName int)]public int? Quarter { get; set; }/// summary/// 报表名称/// /summary[Required][Column(TypeName nvarchar(100))]public string Name { get; set; }/// summary/// 报表类型/// /summary[Required][Column(TypeName int)]public ReportTypeEnum Type { get; set; }/// summary/// 金额/// /summary[Required][Column(TypeName decimal(18,2))]public decimal Amount { get; set; }/// summary/// 用户Id/// /summary[Required][Column(TypeName nvarchar(36))][ForeignKey(FK_Report_SysUser_UserId)]public string UserId { get; set; }/// summary/// 分类Id/// /summary[Required][Column(TypeName nvarchar(36))][ForeignKey(FK_Report_Classification_ClassificationId)]public string ClassificationId { get; set; }/// summary/// 导航属性/// /summarypublic SysUser User { get; set; }/// summary/// 导航属性/// /summarypublic IncomeExpenditureClassification Classification { get; set; }
}功能实现 我们这里只展示和查询报表有关的功能代码其他代码不再展示。首先我们要定义数据服务接口IReportServer,在这个接口中添加获取报表的方法。 using SporeAccounting.Models;namespace SporeAccounting.Server.Interface;/// summary
/// 报表服务
/// /summary
public interface IReportServer
{ /// summary/// 获取报表数据/// /summary/// param nameuserId/param/// param nameyear/param/// param namereportType/param/// returns/returnsListReport QueryReport(string userId, int year,ReportTypeEnum reportType);
}然后我们实现这个接口实现也很简单很简单我就不具体讲解了。 using SporeAccounting.Models;
using SporeAccounting.Server.Interface;namespace SporeAccounting.Server;/// summary
/// 报表服务实现
/// /summary
public class ReportImp : IReportServer
{private readonly SporeAccountingDBContext _sporeAccountingDbContext;public ReportImp(SporeAccountingDBContext sporeAccountingDbContext){_sporeAccountingDbContext sporeAccountingDbContext;}/// summary/// 获取报表数据/// /summary/// param nameuserId/param/// param nameyear/param/// returns/returnspublic ListReport QueryReport(string userId, int year, ReportTypeEnum reportType){try{IQueryableReport reports _sporeAccountingDbContext.Reports.Where(p p.UserId userId p.Year year p.Type reportType);return reports.ToList();}catch (Exception e){throw;}}
}最后我们一起编写Controller。 using System.Net;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using SporeAccounting.BaseModels;
using SporeAccounting.Models.ViewModels;
using SporeAccounting.Server.Interface;namespace SporeAccounting.Controllers
{/// summary/// 报表控制器/// /summary[Route(api/[controller])][ApiController]public class ReportController : BaseController{/// summary/// 报表服务/// /summaryprivate IReportServer _reportServer;/// summary/// 映射/// /summaryprivate IMapper _mapper;/// summary/// 构造函数/// /summary/// param namereportServer/param/// param namemapper/parampublic ReportController(IReportServer reportServer, IMapper mapper){_reportServer reportServer;_mapper mapper;}/// summary/// 获取报表/// /summary/// param namereport/param/// returns/returns[HttpPost][Route(GetReport)]public ActionResultResponseDataListReportResponseViewModel GetReport([FromBody] ReportViewModel report){try{string userId GetUserId();var reports _reportServer.QueryReport(userId, report.Year, report.ReportType);ListReportResponseViewModel response _mapper.MapListReportResponseViewModel(reports);return Ok(new ResponseDataListReportResponseViewModel(HttpStatusCode.OK, data: response));}catch (Exception ex){return Ok(new ResponseDatabool(HttpStatusCode.BadRequest, errorMessage: ex.Message));}}}
}三、总结
本文介绍了记账应用中的报表功能实现作为单体应用开发的最后环节其核心是提供一个接口供客户端查询报表数据。本功能实现以清晰的需求分析为起点逐步完成了模型设计、服务接口定义、接口实现以及控制器编写。需求方面报表查询需支持按报表类型包括月报、季报、年报和时间维度年份、月份进行查询其中月份参数为可选。功能设计中视图模型定义了报表类型、年份和月份的基本字段并通过校验属性确保必填字段的正确性。数据库模型进一步扩展了字段设计涵盖了年份、月份、季度、报表名称、类型、金额、用户关联等内容满足多维度数据统计和查询需求。服务层通过IReportServer接口和实现类ReportImp完成核心数据查询逻辑利用数据库上下文筛选符合条件的报表数据。最后控制器ReportController提供了一个GetReport接口负责接收客户端请求并返回查询结果。通过依赖注入服务和自动映射工具接口实现高效、简洁。整体设计从需求到实现逻辑清晰功能模块化便于后续扩展和维护。 在下一篇文章中我们将一起编写报表定时器实现定时汇总支出数据功能。