Compare commits

...

14 Commits

Author SHA1 Message Date
Developer 02
ddc0c9c6f3 feat: DELETE-Anforderungsmethode zu API-Diensten im Angular-Frontend hinzufügen 2024-08-21 18:13:32 +02:00
Developer 02
489c2a2a9f refactor: Receiver-Update-Endpunkt entfernen durch Überschreiben und Hinzufügen des [NonAction]-Attributs 2024-08-21 18:02:09 +02:00
Developer 02
320e81719b feat: HTTP-Anforderungsdienste mit HttpClient im Frontend implementieren 2024-08-21 17:59:55 +02:00
Developer 02
66a8471f05 refactor: Code in Regionen für entfernte Endpunkte organisieren 2024-08-21 17:16:44 +02:00
Developer 02
c7a4ef4722 fix: Füge try-catch-Blöcke zur Fehlerbehandlung in der Delete-Methode und dem Service hinzu 2024-08-21 17:14:06 +02:00
Developer 02
1673ea81df fix: Füge try-catch-Blöcke zur Fehlerbehandlung in der Delete-Methode und dem Service hinzu 2024-08-21 17:09:16 +02:00
Developer 02
306956a7be feat: Löschen nach E-Mail oder Signatur zur Delete-Methode und zum Service hinzugefügt
- Die `Delete`-Methode im Controller aktualisiert, um das Löschen nach `id`, `emailAddress` oder `signature` zu unterstützen.
- `DeleteByAsync`-Methode im Service hinzugefügt, um Datensätze basierend auf `emailAddress` und `signature` zu löschen.
- Fehlerbehandlung mit Protokollierung für fehlgeschlagene Löschversuche verbessert.
2024-08-21 16:37:54 +02:00
Developer 02
bfe3d38ecc fix: E-Mail-Formatvalidierung zu ReceiverCreateDto hinzugefügt und Modellvalidierung im Create-Methoden behandelt
- `[EmailAddress]`-Attribut auf `EmailAddress` in `ReceiverCreateDto` angewendet, um das E-Mail-Format zu validieren.
- `ModelState.IsValid`-Überprüfung zur `Create`-Methode hinzugefügt, um Validierungsfehler vor dem Aufruf der Basis-`Create`-Methode zu behandeln.
2024-08-21 16:19:18 +02:00
Developer 02
6e5bb58f65 feat: E-Mail-Formatvalidierung in der Receiver-Entität mit [EmailAddress]-Attribut hinzugefügt 2024-08-21 15:10:07 +02:00
Developer 02
b96c6c10f8 feat: Filterung nach emailAddress und signature im Receiver-Repository, -Service und -Controller hinzugefügt
- `ReadBy`-Methode im Receiver-Repository implementiert, um nach `emailAddress` und `signature` zu filtern.
- `ReadByAsync`-Methode im Receiver-Service hinzugefügt, um Receiver-Daten abzurufen und zuzuordnen.
- Controller-`Get`-Endpunkt aktualisiert, um optionale `emailAddress` und `signature` Query-Parameter für die Filterung zu unterstützen.
- Fehlerbehandlung mit Protokollierung für fehlgeschlagene Service-Operationen im Controller hinzugefügt.
2024-08-21 15:05:18 +02:00
Developer 02
afedfdd596 refactor: Receiver-Service in CRUD-Service umgewandelt und DTOs aktualisiert
- Receiver-Service von einfachem CRUD zu generischem CRUD-Service umgewandelt.
- `ReceiverDto` in `ReceiverReadDto` umbenannt.
- Neues `ReceiverCreateDto` mit automatischer SHA-256-Signaturerstellung und aktuellem Zeitstempel erstellt.
- Leeres `ReceiverUpdateDto` für zukünftige Updates hinzugefügt.
2024-08-21 14:37:45 +02:00
Developer 02
3a7099feb4 fix: Füge required-Attribut zu Receiver-Eigenschaften hinzu 2024-08-21 11:29:39 +02:00
Developer 02
c704d222f0 fix: Beseitige Duplikation von formControlName="firstCtrl" 2024-08-21 11:27:17 +02:00
Developer 02
83ce528e2f feat: Füge Eingaben für die Umschlagstabelle und Statusfilteroptionen hinzu
- `data`, `displayedColumns` und `schema` wurden als `@Input`-Eigenschaften für die Umschlagstabelle hinzugefügt.
- `min`, `max` und `ignore` Statusfilter wurden als Objekt-Eingaben für Statusbeschränkungen eingeführt.
- Die Methode `getEnvelopeReceiver` wurde aktualisiert, um Statusfilter über Abfrageparameter zu unterstützen.
- `getEnvelopeReceiverAsync` wurde für die Promise-basierte Verarbeitung von Status-gefilterten Anfragen hinzugefügt.
- Die Umschlag-Tab-Konfiguration wurde geändert, um Statusfilter dynamisch anzuwenden.
2024-08-21 11:13:31 +02:00
24 changed files with 312 additions and 49 deletions

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using static EnvelopeGenerator.Common.Constants;
@@ -22,7 +22,7 @@ namespace EnvelopeGenerator.Application.Contracts
Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null);
Task<IEnumerable<ReceiverDto>> ReadRejectingReceivers(int envelopeId);
Task<IEnumerable<ReceiverReadDto>> ReadRejectingReceivers(int envelopeId);
Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null);
}

View File

@@ -1,10 +1,14 @@
using DigitalData.Core.Abstractions.Application;
using EnvelopeGenerator.Application.DTOs;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts
{
public interface IReceiverService : IBasicCRUDService<ReceiverDto, Receiver, int>
public interface IReceiverService : ICRUDService<ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>
{
public Task<DataResult<ReceiverReadDto>> ReadByAsync(string? emailAddress = null, string? signature = null);
public Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null);
}
}

View File

@@ -1,5 +1,6 @@
using DigitalData.Core.DTO;
using DigitalData.UserManager.Application.DTOs.User;
using EnvelopeGenerator.Application.DTOs.Receiver;
using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
@@ -12,7 +13,7 @@ namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
DateTime AddedWhen,
DateTime? ActionDate,
UserCreateDto? Sender,
ReceiverDto? Receiver,
ReceiverReadDto? Receiver,
ReferenceType ReferenceType,
string? Comment = null) : BaseDTO<long>(Id);
}

View File

@@ -1,4 +1,5 @@
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using EnvelopeGenerator.Application.DTOs.Receiver;
namespace EnvelopeGenerator.Application.DTOs
{
@@ -25,6 +26,6 @@ namespace EnvelopeGenerator.Application.DTOs
public EnvelopeDto? Envelope { get; set; }
public ReceiverDto? Receiver { get; set; }
public ReceiverReadDto? Receiver { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
using System.Security.Cryptography;
using System.Text;
namespace EnvelopeGenerator.Application.DTOs.Receiver
{
public record ReceiverCreateDto([EmailAddress] string EmailAddress)
{
public string Signature => sha256HexOfMail.Value;
private readonly Lazy<string> sha256HexOfMail = new(() =>
{
var bytes_arr = Encoding.UTF8.GetBytes(EmailAddress.ToUpper());
var hash_arr = SHA256.HashData(bytes_arr);
var hexa_str = BitConverter.ToString(hash_arr);
return hexa_str.Replace("-", string.Empty);
});
public DateTime AddedWhen { get; } = DateTime.Now;
};
}

View File

@@ -1,8 +1,8 @@
using DigitalData.Core.DTO;
namespace EnvelopeGenerator.Application.DTOs
namespace EnvelopeGenerator.Application.DTOs.Receiver
{
public record ReceiverDto(
public record ReceiverReadDto(
int Id,
string EmailAddress,
string Signature,

View File

@@ -0,0 +1,4 @@
namespace EnvelopeGenerator.Application.DTOs.Receiver
{
public record ReceiverUpdateDto();
}

View File

@@ -1,6 +1,7 @@
using AutoMapper;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.MappingProfiles
@@ -21,7 +22,9 @@ namespace EnvelopeGenerator.Application.MappingProfiles
CreateMap<EnvelopeHistory, EnvelopeHistoryCreateDto>();
CreateMap<EnvelopeReceiver, EnvelopeReceiverDto>();
CreateMap<EnvelopeType, EnvelopeTypeDto>();
CreateMap<Receiver, ReceiverDto>();
CreateMap<Receiver, ReceiverReadDto>();
CreateMap<Receiver, ReceiverCreateDto>();
CreateMap<Receiver, ReceiverUpdateDto>();
CreateMap<UserReceiver, UserReceiverDto>();
// DTO to Entity mappings
@@ -36,7 +39,9 @@ namespace EnvelopeGenerator.Application.MappingProfiles
CreateMap<EnvelopeHistoryCreateDto, EnvelopeHistory>();
CreateMap<EnvelopeReceiverDto, EnvelopeReceiver>();
CreateMap<EnvelopeTypeDto, EnvelopeType>();
CreateMap<ReceiverDto, Receiver>();
CreateMap<ReceiverReadDto, Receiver>();
CreateMap<ReceiverCreateDto, Receiver>();
CreateMap<ReceiverUpdateDto, Receiver>();
CreateMap<UserReceiverDto, UserReceiver>();
}
}

View File

@@ -8,7 +8,7 @@ using static EnvelopeGenerator.Common.Constants;
using EnvelopeGenerator.Application.Resources;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.Receiver;
namespace EnvelopeGenerator.Application.Services
{
@@ -67,11 +67,11 @@ namespace EnvelopeGenerator.Application.Services
await ReadAsync(envelopeId: envelopeId, userReference: userReference, status: (int)EnvelopeStatus.DocumentRejected, withReceiver:true);
//TODO: use IQueryable in repository to incerease the performance
public async Task<IEnumerable<ReceiverDto>> ReadRejectingReceivers(int envelopeId)
public async Task<IEnumerable<ReceiverReadDto>> ReadRejectingReceivers(int envelopeId)
{
var envelopes = await ReadRejectedAsync(envelopeId);
return envelopes is null
? Enumerable.Empty<ReceiverDto>()
? Enumerable.Empty<ReceiverReadDto>()
: envelopes
.Where(eh => eh?.Receiver != null)
.Select(eh => eh.Receiver!);

View File

@@ -2,19 +2,39 @@
using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Application.Resources;
using Microsoft.AspNetCore.Mvc;
using EnvelopeGenerator.Application.DTOs.Receiver;
using DigitalData.Core.DTO;
namespace EnvelopeGenerator.Application.Services
{
public class ReceiverService : BasicCRUDService<IReceiverRepository, ReceiverDto, Receiver, int>, IReceiverService
public class ReceiverService : CRUDService<IReceiverRepository, ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>, IReceiverService
{
public ReceiverService(IReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper)
: base(repository, mapper)
{
}
public async Task<DataResult<ReceiverReadDto>> ReadByAsync(string? emailAddress = null, string? signature = null)
{
var rcv = await _repository.ReadByAsync(emailAddress: emailAddress, signature: signature);
if (rcv is null)
return Result.Fail<ReceiverReadDto>();
return Result.Success(_mapper.MapOrThrow<ReceiverReadDto>(rcv));
}
public async Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null)
{
var rcv = await _repository.ReadByAsync(emailAddress: emailAddress, signature: signature);
if (rcv is null)
return Result.Fail();
return await _repository.DeleteAsync(rcv) ? Result.Success() : Result.Fail();
}
}
}

View File

@@ -10,14 +10,14 @@ namespace EnvelopeGenerator.Domain.Entities
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("GUID")]
public int Id { get; set; }
[Required]
[Required, EmailAddress]
[Column("EMAIL_ADDRESS", TypeName = "nvarchar(128)")]
public string EmailAddress { get; set; }
public required string EmailAddress { get; set; }
[Required]
[Column("SIGNATURE", TypeName = "nvarchar(64)")]
public string Signature { get; set; }
public required string Signature { get; set; }
[Required]
[Column("ADDED_WHEN", TypeName = "datetime")]

View File

@@ -1,10 +1,11 @@
import { Component, ViewChild } from '@angular/core';
import { Component, Input, ViewChild } from '@angular/core';
import { EnvelopeReceiverService } from '../../services/envelope-receiver.service';
import { MatTable, MatTableModule } from '@angular/material/table';
import { CommonModule } from '@angular/common'
import {MatIconModule} from '@angular/material/icon';
import {MatButtonModule} from '@angular/material/button';
import {animate, state, style, transition, trigger} from '@angular/animations';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { Status } from '../../enums/envelope-const'
@Component({
selector: 'app-envelope-table',
@@ -13,8 +14,8 @@ import {animate, state, style, transition, trigger} from '@angular/animations';
templateUrl: './envelope-table.component.html',
animations: [
trigger('detailExpand', [
state('collapsed,void', style({height: '0px', minHeight: '0'})),
state('expanded', style({height: '*'})),
state('collapsed,void', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
],
@@ -22,12 +23,13 @@ import {animate, state, style, transition, trigger} from '@angular/animations';
})
export class EnvelopeTableComponent {
data: Array<any> = []
@Input() data: Array<any> = []
public displayedColumns: string[] = ['title', 'status', 'type', 'privateMessage', 'addedWhen'];
columnsToDisplayWithExpand = [...this.displayedColumns, 'expand'];
schema: any = {
@Input() options?: { min_status?: number; max_status?: number; ignore_status?: number[] }
@Input() displayedColumns: string[] = ['title', 'status', 'type', 'privateMessage', 'addedWhen'];
@Input() schema: Record<string, { header: string; field: (element: any) => any; }> = {
'title': {
header: 'Title',
field: (element: any) => element.envelope.title
@@ -50,6 +52,8 @@ export class EnvelopeTableComponent {
},
}
columnsToDisplayWithExpand = [...this.displayedColumns, 'expand'];
expandedElement: any | null;
@ViewChild(MatTable) table!: MatTable<any>;
@@ -57,7 +61,8 @@ export class EnvelopeTableComponent {
constructor(private erService: EnvelopeReceiverService) { }
async ngOnInit() {
this.data = await this.erService.getEnvelopeReceiver();
if (this.data.length === 0)
this.data = await this.erService.getEnvelopeReceiverAsync(this.options);
}
public updateTable() {
@@ -66,5 +71,5 @@ export class EnvelopeTableComponent {
isExpandedRow(index: number, row: any): boolean {
return (row?.envelopeId === this.expandedElement?.envelopeId) && (row?.receiverId === this.expandedElement?.receiverId);
}
}
}

View File

@@ -1,4 +1,4 @@
export enum Status {
enum Status {
Invalid = 0,
EnvelopeCreated = 1001,
EnvelopeSaved = 1002,
@@ -20,4 +20,6 @@ export enum Status {
MessageConfirmationSent = 3003,
MessageDeletionSent = 3004,
MessageCompletionSent = 3005
}
}
export { Status }

View File

@@ -8,7 +8,7 @@
</mat-form-field>
<mat-form-field class="ms-5">
<mat-label>Vertragstyp</mat-label>
<mat-select [(value)]="selectedType" [formControl]="typeControl" formControlName="firstCtrl" required>
<mat-select [(value)]="selectedType" [formControl]="typeControl" required>
@for (type of types; track type) {
<mat-option [value]="type.value">{{type.viewValue}}</mat-option>
}

View File

@@ -5,6 +5,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatStepperModule } from '@angular/material/stepper';
import { MatButtonModule } from '@angular/material/button';
import { MatSelectModule } from '@angular/material/select';
import { ReceiverService } from '../../services/receiver.service';
@Component({
selector: 'app-envelope-creation',
@@ -23,6 +24,9 @@ import { MatSelectModule } from '@angular/material/select';
})
export class EnvelopeCreationComponent {
constructor(private receiverService: ReceiverService) {
}
ngOnInit() {
this.selectedType = this.types[0].value;
}
@@ -39,8 +43,8 @@ export class EnvelopeCreationComponent {
selectedType: string = "Mietvertrag"
types: any[] = [
{value: 0, viewValue: 'Mietvertrag'},
{value: 1, viewValue: 'Kaufvertrag'}
{ value: 0, viewValue: 'Mietvertrag' },
{ value: 1, viewValue: 'Kaufvertrag' }
];
typeControl = new FormControl('Mietvertrag', [Validators.required]);
}

View File

@@ -1,10 +1,10 @@
<div id="table">
<mat-tab-group>
<mat-tab label="Offene Umschläge">
<app-envelope-table></app-envelope-table>
<app-envelope-table [options]="{max_status: Status.EnvelopePartlySigned}"></app-envelope-table>
</mat-tab>
<mat-tab label="Abgeschlossene Umschläge">
<app-envelope-table></app-envelope-table>
<app-envelope-table [options]="{min_status: Status.EnvelopeCompletelySigned, ignore_status: [Status.EnvelopeDeleted]}"></app-envelope-table>
</mat-tab>
</mat-tab-group>
</div>

View File

@@ -2,8 +2,7 @@ import { Component } from '@angular/core';
import { EnvelopeTableComponent } from "../../components/envelope-table/envelope-table.component";
import { MatTabsModule } from '@angular/material/tabs';
import { LocalizationService } from '../../services/localization.service';
import { firstValueFrom } from 'rxjs/internal/firstValueFrom';
import { Status } from '../../enums/envelope-const'
@Component({
selector: 'app-envelope',
standalone: true,
@@ -13,6 +12,8 @@ import { firstValueFrom } from 'rxjs/internal/firstValueFrom';
})
export class EnvelopeComponent {
readonly Status = Status;
private localizer: any = {};
constructor(private localizationService: LocalizationService) {

View File

@@ -1,5 +1,5 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, firstValueFrom } from 'rxjs';
import { API_URL } from '../tokens/index';
@@ -7,14 +7,28 @@ import { API_URL } from '../tokens/index';
providedIn: 'root'
})
export class EnvelopeReceiverService {
private url: string;
protected url: string;
constructor(private http: HttpClient) {
const api_url = inject(API_URL);
this.url = `${api_url}/envelopereceiver`;
}
getEnvelopeReceiver(): Promise<any> {
return firstValueFrom(this.http.get<any>(this.url));
getEnvelopeReceiver(options?: { min_status?: number; max_status?: number; ignore_status?: number[] }): Observable<any> {
let params = new HttpParams();
if (options) {
if (options.min_status)
params = params.set('min_status', options.min_status.toString());
if (options.max_status)
params = params.set('max_status', options.max_status.toString());
if (options.ignore_status)
params = params.set('ignore_status', options.ignore_status.join(','));
}
return this.http.get<any>(this.url, { params });
}
getEnvelopeReceiverAsync(options?: { min_status?: number; max_status?: number; ignore_status?: number[] }): Promise<any> {
return firstValueFrom(this.getEnvelopeReceiver(options));
}
}

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { ReceiverService } from './receiver.service';
describe('ReceiverService', () => {
let service: ReceiverService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(ReceiverService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,58 @@
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { API_URL } from '../tokens';
import { Observable, firstValueFrom } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ReceiverService {
protected url: string;
constructor(private http: HttpClient) {
const api_url = inject(API_URL);
this.url = `${api_url}/receiver`;
}
public getReceiver(options?: { emailAdress?: string; signature?: string; }): Observable<any> {
let params = new HttpParams();
if (options) {
if (options.emailAdress)
params = params.set('emailAdress', options?.emailAdress);
if (options.signature)
params = params.set('signature', options?.signature);
}
return this.http.get<any>(this.url, { params });
}
public async getReceiverAsync(options?: { emailAdress?: string; signature?: string; }): Promise<any> {
return await firstValueFrom(this.getReceiver(options));
}
public createReceiver(emailAddress: string): Observable<any> {
return this.http.post<any>(this.url, { emailAddress: emailAddress });
}
public async createReceiverAsync(emailAddress: string): Promise<any> {
return await firstValueFrom(this.createReceiver(emailAddress));
}
public deleteReceiver(options: { id: number, emailAdress?: string; signature?: string; }): Observable<any> {
let params = new HttpParams();
if (options.emailAdress)
params = params.set('emailAdress', options?.emailAdress);
if (options.signature)
params = params.set('signature', options?.signature);
if (options.id)
params = params.set('id', options?.id.toString());
return this.http.get<any>(this.url, { params });
}
public async deleteReceiverAsync(options: { id: number, emailAdress?: string; signature?: string; }): Promise<any> {
return await firstValueFrom(this.deleteReceiver(options));
}
}

View File

@@ -0,0 +1,91 @@
using DigitalData.Core.API;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.GeneratorAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ReceiverController : CRUDControllerBaseWithErrorHandling<IReceiverService, ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>
{
public ReceiverController(ILogger<ReceiverController> logger, IReceiverService service) : base(logger, service)
{
}
[HttpGet]
public async Task<IActionResult> Get([FromQuery] string? emailAddress = null, [FromQuery] string? signature = null)
{
if (emailAddress is null && signature is null)
return await base.GetAll();
try
{
return await _service.ReadByAsync(emailAddress: emailAddress, signature: signature).ThenAsync(
Success: Ok,
Fail: IActionResult (msg, ntc) =>
{
_logger.LogNotice(ntc);
return StatusCode(StatusCodes.Status500InternalServerError);
});
}
catch(Exception ex)
{
_logger.LogError(ex, "{Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost]
public async override Task<IActionResult> Create(ReceiverCreateDto createDto)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
return await base.Create(createDto);
}
[HttpDelete]
public async Task<IActionResult> Delete([FromQuery] int? id = null, [FromQuery]string? emailAddress = null, [FromQuery] string? signature = null)
{
if(id is int id_int)
return await base.Delete(id_int);
try
{
if (emailAddress is not null || signature is not null)
return await _service.DeleteByAsync(emailAddress: emailAddress, signature: signature).ThenAsync(
Success: Ok,
Fail: IActionResult (msg, ntc) =>
{
_logger.LogNotice(ntc);
return StatusCode(StatusCodes.Status500InternalServerError);
});
}
catch(Exception ex)
{
_logger.LogError(ex, "{Message}", ex.Message);
return StatusCode(500);
}
return BadRequest();
}
#region REMOVED ENDPOINTS
[NonAction]
public override Task<IActionResult> GetAll() => base.GetAll();
[NonAction]
public override Task<IActionResult> Delete([FromRoute] int id) => base.Delete(id);
[NonAction]
public override Task<IActionResult> Update(ReceiverUpdateDto updateDto) => base.Update(updateDto);
#endregion
}
}

View File

@@ -5,5 +5,6 @@ namespace EnvelopeGenerator.Infrastructure.Contracts
{
public interface IReceiverRepository : ICRUDRepository<Receiver, int>
{
Task<Receiver?> ReadByAsync(string? emailAddress = null, string? signature = null);
}
}

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Infrastructure;
using DigitalData.UserManager.Infrastructure.Repositories;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.EntityFrameworkCore;
namespace EnvelopeGenerator.Infrastructure.Repositories
{
@@ -10,5 +10,20 @@ namespace EnvelopeGenerator.Infrastructure.Repositories
public ReceiverRepository(EGDbContext dbContext) : base(dbContext)
{
}
protected IQueryable<Receiver> ReadBy(string? emailAddress = null, string? signature = null)
{
IQueryable<Receiver> query = _dbSet.AsNoTracking();
if(emailAddress is not null)
query = query.Where(r => r.EmailAddress == emailAddress);
if(signature is not null)
query = query.Where(r => r.Signature == signature);
return query;
}
public async Task<Receiver?> ReadByAsync(string? emailAddress = null, string? signature = null) => await ReadBy(emailAddress, signature).FirstOrDefaultAsync();
}
}

View File

@@ -1,10 +1,10 @@
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Web.Controllers.Test
{
public class TestReceiverController : TestControllerBase<IReceiverService, ReceiverDto, Receiver, int>
public class TestReceiverController : TestControllerBase<IReceiverService, ReceiverReadDto, Receiver, int>
{
public TestReceiverController(ILogger<TestReceiverController> logger, IReceiverService service) : base(logger, service)
{