Report App Service
This commit is contained in:
parent
b6efa5c3fd
commit
cd51347f3b
5 changed files with 233 additions and 87 deletions
|
|
@ -4,23 +4,24 @@ using System.Linq;
|
|||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Kurs.Platform.Entities;
|
||||
using Kurs.Platform.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Kurs.Platform.Reports;
|
||||
|
||||
[Authorize()]
|
||||
public class ReportAppService : PlatformAppService, IReportAppService
|
||||
{
|
||||
private readonly IReportTemplateRepository _reportTemplateRepository;
|
||||
private readonly IGeneratedReportRepository _generatedReportRepository;
|
||||
private readonly IRepository<ReportTemplate, Guid> _reportTemplateRepository;
|
||||
private readonly IRepository<GeneratedReport, Guid> _generatedReportRepository;
|
||||
private readonly IRepository<ReportParameter, Guid> _reportParameterRepository;
|
||||
|
||||
public ReportAppService(
|
||||
IReportTemplateRepository reportTemplateRepository,
|
||||
IGeneratedReportRepository generatedReportRepository,
|
||||
IRepository<ReportTemplate, Guid> reportTemplateRepository,
|
||||
IRepository<GeneratedReport, Guid> generatedReportRepository,
|
||||
IRepository<ReportParameter, Guid> reportParameterRepository)
|
||||
{
|
||||
_reportTemplateRepository = reportTemplateRepository;
|
||||
|
|
@ -30,22 +31,50 @@ public class ReportAppService : PlatformAppService, IReportAppService
|
|||
|
||||
public async Task<PagedResultDto<ReportTemplateDto>> GetTemplatesAsync(GetReportTemplatesInput input)
|
||||
{
|
||||
var totalCount = await _reportTemplateRepository.GetCountAsync(input.Filter, input.Category);
|
||||
var templates = await _reportTemplateRepository.GetListAsync(
|
||||
input.SkipCount,
|
||||
input.MaxResultCount,
|
||||
input.Sorting,
|
||||
input.Filter,
|
||||
input.Category);
|
||||
// IQueryable başlat
|
||||
var query = await _reportTemplateRepository.GetQueryableAsync();
|
||||
|
||||
// Filtreleme
|
||||
if (!string.IsNullOrWhiteSpace(input.Filter))
|
||||
{
|
||||
query = query.Where(x =>
|
||||
x.Name.Contains(input.Filter) ||
|
||||
x.Description.Contains(input.Filter) ||
|
||||
x.Category.Contains(input.Filter)
|
||||
);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(input.Category))
|
||||
{
|
||||
query = query.Where(x => x.Category == input.Category);
|
||||
}
|
||||
|
||||
// Toplam kayıt sayısı
|
||||
var totalCount = await AsyncExecuter.CountAsync(query);
|
||||
|
||||
// Sıralama (ABP default olarak sorting null ise Id'ye göre sıralar)
|
||||
query = query.OrderBy(input.Sorting ?? nameof(ReportTemplate.Name));
|
||||
|
||||
// Sayfalama
|
||||
var templates = await AsyncExecuter.ToListAsync(
|
||||
query
|
||||
.Skip(input.SkipCount)
|
||||
.Take(input.MaxResultCount)
|
||||
);
|
||||
|
||||
// DTO dönüşümü
|
||||
var templateDtos = templates.Select(MapToReportTemplateDto).ToList();
|
||||
|
||||
return new PagedResultDto<ReportTemplateDto>(totalCount, templateDtos);
|
||||
return new PagedResultDto<ReportTemplateDto>(
|
||||
totalCount,
|
||||
templateDtos
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<ReportTemplateDto> GetTemplateAsync(Guid id)
|
||||
{
|
||||
var template = await _reportTemplateRepository.GetByIdWithParametersAsync(id);
|
||||
var template = await _reportTemplateRepository.GetAsync(id);
|
||||
|
||||
return MapToReportTemplateDto(template);
|
||||
}
|
||||
|
||||
|
|
@ -56,9 +85,10 @@ public class ReportAppService : PlatformAppService, IReportAppService
|
|||
input.Name,
|
||||
input.Description,
|
||||
input.HtmlContent,
|
||||
input.Category ?? "Genel");
|
||||
|
||||
template.Tags = JsonSerializer.Serialize(input.Tags);
|
||||
input.Category ?? "Genel")
|
||||
{
|
||||
Tags = JsonSerializer.Serialize(input.Tags)
|
||||
};
|
||||
|
||||
template = await _reportTemplateRepository.InsertAsync(template, true);
|
||||
|
||||
|
|
@ -71,10 +101,11 @@ public class ReportAppService : PlatformAppService, IReportAppService
|
|||
paramDto.Name,
|
||||
paramDto.Placeholder,
|
||||
(Entities.ReportParameterType)paramDto.Type,
|
||||
paramDto.Required);
|
||||
|
||||
parameter.DefaultValue = paramDto.DefaultValue;
|
||||
parameter.Description = paramDto.Description;
|
||||
paramDto.Required)
|
||||
{
|
||||
DefaultValue = paramDto.DefaultValue,
|
||||
Description = paramDto.Description
|
||||
};
|
||||
|
||||
await _reportParameterRepository.InsertAsync(parameter);
|
||||
}
|
||||
|
|
@ -84,7 +115,7 @@ public class ReportAppService : PlatformAppService, IReportAppService
|
|||
|
||||
public async Task<ReportTemplateDto> UpdateTemplateAsync(Guid id, UpdateReportTemplateDto input)
|
||||
{
|
||||
var template = await _reportTemplateRepository.GetByIdWithParametersAsync(id);
|
||||
var template = await _reportTemplateRepository.GetAsync(id);
|
||||
|
||||
template.Name = input.Name;
|
||||
template.Description = input.Description;
|
||||
|
|
@ -128,14 +159,41 @@ public class ReportAppService : PlatformAppService, IReportAppService
|
|||
|
||||
public async Task<PagedResultDto<GeneratedReportDto>> GetGeneratedReportsAsync(GetGeneratedReportsInput input)
|
||||
{
|
||||
var totalCount = await _generatedReportRepository.GetCountAsync(input.Filter, input.TemplateId);
|
||||
var reports = await _generatedReportRepository.GetListAsync(
|
||||
input.SkipCount,
|
||||
input.MaxResultCount,
|
||||
input.Sorting,
|
||||
input.Filter,
|
||||
input.TemplateId);
|
||||
var query = await _generatedReportRepository.GetQueryableAsync();
|
||||
|
||||
// Okuma senaryosu: tracking gerekmiyor + Template'ı eager load edelim
|
||||
query = query.AsNoTracking()
|
||||
.Include(x => x.Template);
|
||||
|
||||
// Filtre
|
||||
if (!string.IsNullOrWhiteSpace(input.Filter))
|
||||
{
|
||||
query = query.Where(x =>
|
||||
x.TemplateName.Contains(input.Filter) ||
|
||||
x.GeneratedContent.Contains(input.Filter)
|
||||
);
|
||||
}
|
||||
|
||||
if (input.TemplateId.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.TemplateId == input.TemplateId.Value);
|
||||
}
|
||||
|
||||
// Toplam kayıt
|
||||
var totalCount = await AsyncExecuter.CountAsync(query);
|
||||
|
||||
// Sıralama
|
||||
if (!string.IsNullOrWhiteSpace(input.Sorting))
|
||||
query = query.OrderBy(input.Sorting); // ör. "generatedAt DESC" veya "templateName"
|
||||
else
|
||||
query = query.OrderByDescending(x => x.GeneratedAt);
|
||||
|
||||
// Sayfalama
|
||||
var reports = await AsyncExecuter.ToListAsync(
|
||||
query.Skip(input.SkipCount).Take(input.MaxResultCount)
|
||||
);
|
||||
|
||||
// DTO map
|
||||
var reportDtos = reports.Select(MapToGeneratedReportDto).ToList();
|
||||
|
||||
return new PagedResultDto<GeneratedReportDto>(totalCount, reportDtos);
|
||||
|
|
@ -143,13 +201,14 @@ public class ReportAppService : PlatformAppService, IReportAppService
|
|||
|
||||
public async Task<GeneratedReportDto> GetGeneratedReportAsync(Guid id)
|
||||
{
|
||||
var report = await _generatedReportRepository.GetByIdWithTemplateAsync(id);
|
||||
var report = await _generatedReportRepository.GetAsync(id);
|
||||
|
||||
return MapToGeneratedReportDto(report);
|
||||
}
|
||||
|
||||
public async Task<GeneratedReportDto> GenerateReportAsync(GenerateReportDto input)
|
||||
{
|
||||
var template = await _reportTemplateRepository.GetByIdWithParametersAsync(input.TemplateId);
|
||||
var template = await _reportTemplateRepository.GetAsync(input.TemplateId);
|
||||
if (template == null)
|
||||
{
|
||||
throw new ArgumentException("Template not found");
|
||||
|
|
@ -214,7 +273,7 @@ public class ReportAppService : PlatformAppService, IReportAppService
|
|||
try
|
||||
{
|
||||
dto.Tags = string.IsNullOrEmpty(template.Tags)
|
||||
? new List<string>()
|
||||
? []
|
||||
: JsonSerializer.Deserialize<List<string>>(template.Tags);
|
||||
}
|
||||
catch
|
||||
|
|
@ -233,7 +292,7 @@ public class ReportAppService : PlatformAppService, IReportAppService
|
|||
DefaultValue = p.DefaultValue,
|
||||
Required = p.Required,
|
||||
Description = p.Description
|
||||
}).ToList() ?? new List<ReportParameterDto>();
|
||||
}).ToList() ?? [];
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
|
@ -262,7 +321,7 @@ public class ReportAppService : PlatformAppService, IReportAppService
|
|||
}
|
||||
catch
|
||||
{
|
||||
dto.Parameters = new Dictionary<string, string>();
|
||||
dto.Parameters = [];
|
||||
}
|
||||
|
||||
// Template mapping
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
|||
namespace Kurs.Platform.Migrations
|
||||
{
|
||||
[DbContext(typeof(PlatformDbContext))]
|
||||
[Migration("20250815090839_Reports")]
|
||||
[Migration("20250815110914_Reports")]
|
||||
partial class Reports
|
||||
{
|
||||
/// <inheritdoc />
|
||||
|
|
@ -1,32 +1,118 @@
|
|||
export interface ReportTemplateDto {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
htmlContent: string;
|
||||
parameters: ReportParameterDto[];
|
||||
creationTime: Date;
|
||||
lastModificationTime: Date;
|
||||
category: string;
|
||||
tags: string[];
|
||||
// reports.models.ts
|
||||
|
||||
/** Enum, backend ile birebir (0..4) */
|
||||
export enum ReportParameterType {
|
||||
Text = 0,
|
||||
Number = 1,
|
||||
Date = 2,
|
||||
Email = 3,
|
||||
Url = 4,
|
||||
}
|
||||
|
||||
export type ReportParameterType = "text" | "number" | "date" | "email" | "url";
|
||||
/** ---- API MODELLERİ (Raw JSON) ---- */
|
||||
/** Not: Tarihler API’den ISO string olarak gelir (Date değil) */
|
||||
|
||||
export interface ReportParameterDto {
|
||||
id: string;
|
||||
name: string;
|
||||
placeholder: string;
|
||||
type: ReportParameterType;
|
||||
defaultValue?: string;
|
||||
required: boolean;
|
||||
description?: string;
|
||||
id: string
|
||||
reportTemplateId: string
|
||||
name: string
|
||||
placeholder?: string
|
||||
type: ReportParameterType // enum (0..4)
|
||||
defaultValue?: string
|
||||
required: boolean
|
||||
description?: string
|
||||
}
|
||||
|
||||
export interface ReportTemplateDto {
|
||||
id: string
|
||||
name: string
|
||||
description?: string
|
||||
htmlContent: string
|
||||
category?: string
|
||||
tags: string[]
|
||||
parameters: ReportParameterDto[]
|
||||
|
||||
// FullAuditedEntityDto alanları
|
||||
creationTime: string // ISO
|
||||
lastModificationTime?: string // ISO | undefined
|
||||
creatorId?: string
|
||||
lastModifierId?: string
|
||||
}
|
||||
|
||||
export interface GeneratedReportDto {
|
||||
id: string;
|
||||
templateId: string;
|
||||
templateName: string;
|
||||
generatedContent: string;
|
||||
parameters: Record<string, string>;
|
||||
generatedAt: Date;
|
||||
id: string
|
||||
templateId?: string | null
|
||||
templateName: string
|
||||
generatedContent: string
|
||||
parameters: Record<string, string>
|
||||
generatedAt: string // ISO
|
||||
|
||||
// FullAuditedEntityDto alanları
|
||||
creationTime: string // ISO
|
||||
lastModificationTime?: string // ISO | undefined
|
||||
creatorId?: string
|
||||
lastModifierId?: string
|
||||
|
||||
template?: ReportTemplateDto // dolu gelebilir
|
||||
}
|
||||
|
||||
/** Create / Update input’ları */
|
||||
export interface CreateReportParameterDto {
|
||||
name: string
|
||||
placeholder?: string
|
||||
type: ReportParameterType
|
||||
defaultValue?: string
|
||||
required: boolean
|
||||
description?: string
|
||||
}
|
||||
|
||||
export interface UpdateReportParameterDto extends CreateReportParameterDto {
|
||||
id?: string // opsiyonel
|
||||
}
|
||||
|
||||
export interface CreateReportTemplateDto {
|
||||
name: string
|
||||
description?: string
|
||||
htmlContent: string
|
||||
category?: string
|
||||
tags?: string[]
|
||||
parameters: CreateReportParameterDto[]
|
||||
}
|
||||
|
||||
export interface UpdateReportTemplateDto {
|
||||
name: string
|
||||
description?: string
|
||||
htmlContent: string
|
||||
category?: string
|
||||
tags?: string[]
|
||||
parameters: UpdateReportParameterDto[]
|
||||
}
|
||||
|
||||
/** Generate input’u */
|
||||
export interface GenerateReportDto {
|
||||
templateId: string
|
||||
parameters: Record<string, string>
|
||||
}
|
||||
|
||||
/** List input’ları (query string) */
|
||||
export interface GetReportTemplatesInput {
|
||||
skipCount?: number
|
||||
maxResultCount?: number
|
||||
sorting?: string
|
||||
filter?: string
|
||||
category?: string
|
||||
}
|
||||
|
||||
export interface GetGeneratedReportsInput {
|
||||
skipCount?: number
|
||||
maxResultCount?: number
|
||||
sorting?: string
|
||||
filter?: string
|
||||
templateId?: string
|
||||
}
|
||||
|
||||
/** (Opsiyonel) Paged wrapper — projende zaten varsa bunu kullanmana gerek yok */
|
||||
export interface PagedResultDto<T> {
|
||||
items: T[]
|
||||
totalCount: number
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
import { GeneratedReportDto, ReportTemplateDto } from '@/proxy/reports/models'
|
||||
import apiService, { Config } from './api.service'
|
||||
import {
|
||||
ReportTemplateDto,
|
||||
GeneratedReportDto,
|
||||
CreateReportTemplateDto,
|
||||
UpdateReportTemplateDto,
|
||||
GenerateReportDto, // backend'deki GenerateReportDto (templateId + parameters)
|
||||
} from '@/proxy/reports/models'
|
||||
import apiService from './api.service'
|
||||
import { PagedAndSortedResultRequestDto, PagedResultDto } from '@/proxy'
|
||||
|
||||
export interface ReportsData {
|
||||
|
|
@ -7,20 +13,15 @@ export interface ReportsData {
|
|||
generatedReports: GeneratedReportDto[]
|
||||
}
|
||||
|
||||
export interface GenerateReportRequestDto {
|
||||
templateId: string
|
||||
parameters: Record<string, string>
|
||||
}
|
||||
|
||||
export class ReportsService {
|
||||
apiName = 'Default'
|
||||
|
||||
// Template operations
|
||||
// TEMPLATES
|
||||
getTemplates = (input: PagedAndSortedResultRequestDto) =>
|
||||
apiService.fetchData<PagedResultDto<ReportTemplateDto>, PagedAndSortedResultRequestDto>(
|
||||
{
|
||||
method: 'GET',
|
||||
url: '/api/app/reports/templates',
|
||||
url: '/api/app/report/templates', // ✔ Swagger: GET /api/app/report/templates
|
||||
params: {
|
||||
sorting: input.sorting,
|
||||
skipCount: input.skipCount,
|
||||
|
|
@ -34,27 +35,27 @@ export class ReportsService {
|
|||
apiService.fetchData<ReportTemplateDto>(
|
||||
{
|
||||
method: 'GET',
|
||||
url: `/api/app/reports/templates/${id}`,
|
||||
url: `/api/app/report/${id}/template`, // ✔ Swagger: GET /api/app/report/{id}/template
|
||||
},
|
||||
{ apiName: this.apiName },
|
||||
)
|
||||
|
||||
createTemplate = (input: ReportTemplateDto) =>
|
||||
apiService.fetchData(
|
||||
createTemplate = (input: CreateReportTemplateDto) =>
|
||||
apiService.fetchData<ReportTemplateDto, CreateReportTemplateDto>(
|
||||
{
|
||||
method: 'POST',
|
||||
url: '/api/app/reports/templates',
|
||||
url: '/api/app/report/template', // ✔ Swagger: POST /api/app/report/template
|
||||
data: input,
|
||||
},
|
||||
{ apiName: this.apiName },
|
||||
)
|
||||
|
||||
updateTemplate = (id: string, input: ReportTemplateDto) =>
|
||||
apiService.fetchData<ReportTemplateDto, ReportTemplateDto>(
|
||||
updateTemplate = (id: string, input: UpdateReportTemplateDto) =>
|
||||
apiService.fetchData<ReportTemplateDto, UpdateReportTemplateDto>(
|
||||
{
|
||||
method: 'PUT',
|
||||
url: `/api/app/reports/templates/${id}`,
|
||||
data: input as any,
|
||||
url: `/api/app/report/${id}/template`, // ✔ Swagger: PUT /api/app/report/{id}/template
|
||||
data: input,
|
||||
},
|
||||
{ apiName: this.apiName },
|
||||
)
|
||||
|
|
@ -63,17 +64,17 @@ export class ReportsService {
|
|||
apiService.fetchData(
|
||||
{
|
||||
method: 'DELETE',
|
||||
url: `/api/app/reports/templates/${id}`,
|
||||
url: `/api/app/report/${id}/template`, // ✔ Swagger: DELETE /api/app/report/{id}/template
|
||||
},
|
||||
{ apiName: this.apiName },
|
||||
)
|
||||
|
||||
// Generated Reports operations
|
||||
// GENERATED REPORTS
|
||||
getGeneratedReports = (input: PagedAndSortedResultRequestDto) =>
|
||||
apiService.fetchData<PagedResultDto<GeneratedReportDto>, PagedAndSortedResultRequestDto>(
|
||||
{
|
||||
method: 'GET',
|
||||
url: '/api/app/reports/generated',
|
||||
url: '/api/app/report/generated-reports', // ✔ Swagger: GET /api/app/report/generated-reports
|
||||
params: {
|
||||
sorting: input.sorting,
|
||||
skipCount: input.skipCount,
|
||||
|
|
@ -87,17 +88,17 @@ export class ReportsService {
|
|||
apiService.fetchData<GeneratedReportDto>(
|
||||
{
|
||||
method: 'GET',
|
||||
url: `/api/app/reports/generated/${id}`,
|
||||
url: `/api/app/report/${id}/generated-report`, // ✔ Swagger: GET /api/app/report/{id}/generated-report
|
||||
},
|
||||
{ apiName: this.apiName },
|
||||
)
|
||||
|
||||
generateReport = (input: GeneratedReportDto) =>
|
||||
apiService.fetchData<GeneratedReportDto>(
|
||||
generateReport = (input: GenerateReportDto) =>
|
||||
apiService.fetchData<GeneratedReportDto, GenerateReportDto>(
|
||||
{
|
||||
method: 'POST',
|
||||
url: '/api/app/reports/generate',
|
||||
data: input as any,
|
||||
url: '/api/app/report/generate-report', // ✔ Swagger: POST /api/app/report/generate-report
|
||||
data: input,
|
||||
},
|
||||
{ apiName: this.apiName },
|
||||
)
|
||||
|
|
@ -106,17 +107,17 @@ export class ReportsService {
|
|||
apiService.fetchData(
|
||||
{
|
||||
method: 'DELETE',
|
||||
url: `/api/app/reports/generated/${id}`,
|
||||
url: `/api/app/report/${id}/generated-report`, // ✔ Swagger: DELETE /api/app/report/{id}/generated-report
|
||||
},
|
||||
{ apiName: this.apiName },
|
||||
)
|
||||
|
||||
// Bulk operations
|
||||
// BULK
|
||||
getAllData = () =>
|
||||
apiService.fetchData<ReportsData>(
|
||||
{
|
||||
method: 'GET',
|
||||
url: '/api/app/reports/all',
|
||||
url: '/api/app/report/data', // ✔ Swagger: GET /api/app/report/data
|
||||
},
|
||||
{ apiName: this.apiName },
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue