Enhance envelope creation and update functionality
Added new optional properties to `CreateEnvelopeCommand` for detailed configuration, including `EnvelopeId`, `Language`, `UseAccessCode`, and expiration settings. Introduced `ResolveEnvelopeSettingsAsync` to centralize settings resolution logic. Updated `CreateEnvelopeCommandHandler` to handle new properties and improve envelope creation/update flow. Added `EnvelopeSettings` record for structured settings management. Enhanced SQL update logic with `UseSQLExecutor` support. Improved handling of language resolution, reminders, and expiration rules.
This commit is contained in:
@@ -12,8 +12,66 @@ namespace EnvelopeGenerator.Application.Envelopes.Commands;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public record CreateEnvelopeCommand : IRequest<EnvelopeDto?>
|
public record CreateEnvelopeCommand : IRequest<EnvelopeDto?>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Optionale Umschlag-ID fuer Aktualisierungsvorgaenge.
|
||||||
|
/// </summary>
|
||||||
public int? EnvelopeId { get; init; }
|
public int? EnvelopeId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Kennung des ausgewaehlten Umschlagtyps (Vorlage).
|
||||||
|
/// </summary>
|
||||||
|
public int? EnvelopeTypeId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sprachcode fuer Umschlaginhalt und Benachrichtigungen.
|
||||||
|
/// </summary>
|
||||||
|
public string? Language { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gibt an, ob der Zugriffscode fuer Empfaenger aktiviert ist.
|
||||||
|
/// </summary>
|
||||||
|
public bool? UseAccessCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Zertifizierungstyp fuer den Signaturprozess.
|
||||||
|
/// </summary>
|
||||||
|
public int? CertificationType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finale E-Mail-Einstellung fuer den Ersteller.
|
||||||
|
/// </summary>
|
||||||
|
public int? FinalEmailToCreator { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finale E-Mail-Einstellung fuer die Empfaenger.
|
||||||
|
/// </summary>
|
||||||
|
public int? FinalEmailToReceivers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gibt an, ob Erinnerungs-E-Mails aktiviert sind.
|
||||||
|
/// </summary>
|
||||||
|
public bool? SendReminderEmails { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Anzahl der Tage bis zur ersten Erinnerung.
|
||||||
|
/// </summary>
|
||||||
|
public int? FirstReminderDays { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Intervall in Tagen zwischen Erinnerungs-E-Mails.
|
||||||
|
/// </summary>
|
||||||
|
public int? ReminderIntervalDays { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Anzahl der Tage bis zum Ablauf des Umschlags.
|
||||||
|
/// </summary>
|
||||||
|
public int? ExpiresWhenDays { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Anzahl der Tage vor Ablauf, ab denen gewarnt wird.
|
||||||
|
/// </summary>
|
||||||
|
public int? ExpiresWarningWhenDays { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Der Titel des Umschlags. Dies ist ein Pflichtfeld.
|
/// Der Titel des Umschlags. Dies ist ein Pflichtfeld.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -29,10 +87,19 @@ public record CreateEnvelopeCommand : IRequest<EnvelopeDto?>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TFAEnabled { get; set; } = false;
|
public bool TFAEnabled { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gibt an, ob der Umschlag nach dem Speichern sofort versendet werden soll.
|
||||||
|
/// </summary>
|
||||||
public bool Send { get; init; }
|
public bool Send { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optionaler PDF-Dokumentinhalt als Base64.
|
||||||
|
/// </summary>
|
||||||
public CreateEnvelopeDocumentDto? Document { get; init; }
|
public CreateEnvelopeDocumentDto? Document { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Empfaengerliste inklusive optionaler Signaturfeld-Koordinaten.
|
||||||
|
/// </summary>
|
||||||
public List<CreateEnvelopeReceiverDto> Receivers { get; init; } = new();
|
public List<CreateEnvelopeReceiverDto> Receivers { get; init; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ public class CreateEnvelopeCommandHandler : IRequestHandler<CreateEnvelopeComman
|
|||||||
|
|
||||||
private IRepository<EnvelopeReceiver> EnvelopeReceiverRepository => _provider.GetRequiredService<IRepository<EnvelopeReceiver>>();
|
private IRepository<EnvelopeReceiver> EnvelopeReceiverRepository => _provider.GetRequiredService<IRepository<EnvelopeReceiver>>();
|
||||||
|
|
||||||
|
private IRepository<EnvelopeType> EnvelopeTypeRepository => _provider.GetRequiredService<IRepository<EnvelopeType>>();
|
||||||
|
|
||||||
private IRepository<Receiver> ReceiverRepository => _provider.GetRequiredService<IRepository<Receiver>>();
|
private IRepository<Receiver> ReceiverRepository => _provider.GetRequiredService<IRepository<Receiver>>();
|
||||||
|
|
||||||
private IRepository<DocReceiverElement> DocReceiverElementRepository => _provider.GetRequiredService<IRepository<DocReceiverElement>>();
|
private IRepository<DocReceiverElement> DocReceiverElementRepository => _provider.GetRequiredService<IRepository<DocReceiverElement>>();
|
||||||
@@ -73,6 +75,7 @@ public class CreateEnvelopeCommandHandler : IRequestHandler<CreateEnvelopeComman
|
|||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
var title = request.Title?.Trim() ?? string.Empty;
|
var title = request.Title?.Trim() ?? string.Empty;
|
||||||
var message = request.Message?.Trim() ?? string.Empty;
|
var message = request.Message?.Trim() ?? string.Empty;
|
||||||
|
var settings = await ResolveEnvelopeSettingsAsync(request, existing: null, cancel);
|
||||||
|
|
||||||
Envelope envelope;
|
Envelope envelope;
|
||||||
if (request.EnvelopeId is int envelopeId)
|
if (request.EnvelopeId is int envelopeId)
|
||||||
@@ -85,11 +88,27 @@ public class CreateEnvelopeCommandHandler : IRequestHandler<CreateEnvelopeComman
|
|||||||
if (envelope.UserId != request.UserId)
|
if (envelope.UserId != request.UserId)
|
||||||
throw new ForbiddenException();
|
throw new ForbiddenException();
|
||||||
|
|
||||||
|
settings = await ResolveEnvelopeSettingsAsync(request, envelope, cancel);
|
||||||
|
|
||||||
await Repository.UpdateAsync(e =>
|
await Repository.UpdateAsync(e =>
|
||||||
{
|
{
|
||||||
e.Title = title;
|
e.Title = title;
|
||||||
e.Message = message;
|
e.Message = message;
|
||||||
e.TfaEnabled = request.TFAEnabled;
|
e.TfaEnabled = request.TFAEnabled;
|
||||||
|
e.EnvelopeTypeId = settings.EnvelopeTypeId;
|
||||||
|
e.Language = settings.Language;
|
||||||
|
e.UseAccessCode = settings.UseAccessCode;
|
||||||
|
e.CertificationType = settings.CertificationType;
|
||||||
|
e.FinalEmailToCreator = settings.FinalEmailToCreator;
|
||||||
|
e.FinalEmailToReceivers = settings.FinalEmailToReceivers;
|
||||||
|
e.SendReminderEmails = settings.SendReminderEmails;
|
||||||
|
e.FirstReminderDays = settings.FirstReminderDays;
|
||||||
|
e.ReminderIntervalDays = settings.ReminderIntervalDays;
|
||||||
|
e.ExpiresWhenDays = settings.ExpiresWhenDays;
|
||||||
|
e.ExpiresWarningWhenDays = settings.ExpiresWarningWhenDays;
|
||||||
|
e.ContractType = settings.ContractType;
|
||||||
|
e.ExpiresWhen = settings.ExpiresWhen;
|
||||||
|
e.ExpiresWarningWhen = settings.ExpiresWarningWhen;
|
||||||
e.Status = EnvelopeStatus.EnvelopeSaved;
|
e.Status = EnvelopeStatus.EnvelopeSaved;
|
||||||
e.ChangedWhen = now;
|
e.ChangedWhen = now;
|
||||||
}, e => e.Id == envelopeId, cancel);
|
}, e => e.Id == envelopeId, cancel);
|
||||||
@@ -97,6 +116,20 @@ public class CreateEnvelopeCommandHandler : IRequestHandler<CreateEnvelopeComman
|
|||||||
envelope.Title = title;
|
envelope.Title = title;
|
||||||
envelope.Message = message;
|
envelope.Message = message;
|
||||||
envelope.TfaEnabled = request.TFAEnabled;
|
envelope.TfaEnabled = request.TFAEnabled;
|
||||||
|
envelope.EnvelopeTypeId = settings.EnvelopeTypeId;
|
||||||
|
envelope.Language = settings.Language;
|
||||||
|
envelope.UseAccessCode = settings.UseAccessCode;
|
||||||
|
envelope.CertificationType = settings.CertificationType;
|
||||||
|
envelope.FinalEmailToCreator = settings.FinalEmailToCreator;
|
||||||
|
envelope.FinalEmailToReceivers = settings.FinalEmailToReceivers;
|
||||||
|
envelope.SendReminderEmails = settings.SendReminderEmails;
|
||||||
|
envelope.FirstReminderDays = settings.FirstReminderDays;
|
||||||
|
envelope.ReminderIntervalDays = settings.ReminderIntervalDays;
|
||||||
|
envelope.ExpiresWhenDays = settings.ExpiresWhenDays;
|
||||||
|
envelope.ExpiresWarningWhenDays = settings.ExpiresWarningWhenDays;
|
||||||
|
envelope.ContractType = settings.ContractType;
|
||||||
|
envelope.ExpiresWhen = settings.ExpiresWhen;
|
||||||
|
envelope.ExpiresWarningWhen = settings.ExpiresWarningWhen;
|
||||||
envelope.Status = EnvelopeStatus.EnvelopeSaved;
|
envelope.Status = EnvelopeStatus.EnvelopeSaved;
|
||||||
envelope.ChangedWhen = now;
|
envelope.ChangedWhen = now;
|
||||||
}
|
}
|
||||||
@@ -114,12 +147,61 @@ public class CreateEnvelopeCommandHandler : IRequestHandler<CreateEnvelopeComman
|
|||||||
AddedWhen = now,
|
AddedWhen = now,
|
||||||
ChangedWhen = now,
|
ChangedWhen = now,
|
||||||
Comment = string.Empty,
|
Comment = string.Empty,
|
||||||
Language = "de-DE",
|
EnvelopeTypeId = settings.EnvelopeTypeId,
|
||||||
|
Language = settings.Language,
|
||||||
TfaEnabled = request.TFAEnabled,
|
TfaEnabled = request.TFAEnabled,
|
||||||
UseAccessCode = false,
|
UseAccessCode = settings.UseAccessCode,
|
||||||
SendReminderEmails = false
|
CertificationType = settings.CertificationType,
|
||||||
|
FinalEmailToCreator = settings.FinalEmailToCreator,
|
||||||
|
FinalEmailToReceivers = settings.FinalEmailToReceivers,
|
||||||
|
SendReminderEmails = settings.SendReminderEmails,
|
||||||
|
FirstReminderDays = settings.FirstReminderDays,
|
||||||
|
ReminderIntervalDays = settings.ReminderIntervalDays,
|
||||||
|
ExpiresWhenDays = settings.ExpiresWhenDays,
|
||||||
|
ExpiresWarningWhenDays = settings.ExpiresWarningWhenDays,
|
||||||
|
ExpiresWhen = settings.ExpiresWhen,
|
||||||
|
ExpiresWarningWhen = settings.ExpiresWarningWhen,
|
||||||
|
ContractType = settings.ContractType
|
||||||
}, cancel);
|
}, cancel);
|
||||||
|
|
||||||
|
if (request.UseSQLExecutor)
|
||||||
|
{
|
||||||
|
await Repository.UpdateAsync(e =>
|
||||||
|
{
|
||||||
|
e.EnvelopeTypeId = settings.EnvelopeTypeId;
|
||||||
|
e.Language = settings.Language;
|
||||||
|
e.UseAccessCode = settings.UseAccessCode;
|
||||||
|
e.CertificationType = settings.CertificationType;
|
||||||
|
e.FinalEmailToCreator = settings.FinalEmailToCreator;
|
||||||
|
e.FinalEmailToReceivers = settings.FinalEmailToReceivers;
|
||||||
|
e.SendReminderEmails = settings.SendReminderEmails;
|
||||||
|
e.FirstReminderDays = settings.FirstReminderDays;
|
||||||
|
e.ReminderIntervalDays = settings.ReminderIntervalDays;
|
||||||
|
e.ExpiresWhenDays = settings.ExpiresWhenDays;
|
||||||
|
e.ExpiresWarningWhenDays = settings.ExpiresWarningWhenDays;
|
||||||
|
e.ExpiresWhen = settings.ExpiresWhen;
|
||||||
|
e.ExpiresWarningWhen = settings.ExpiresWarningWhen;
|
||||||
|
e.ContractType = settings.ContractType;
|
||||||
|
e.ChangedWhen = now;
|
||||||
|
}, e => e.Id == envelope.Id, cancel);
|
||||||
|
|
||||||
|
envelope.EnvelopeTypeId = settings.EnvelopeTypeId;
|
||||||
|
envelope.Language = settings.Language;
|
||||||
|
envelope.UseAccessCode = settings.UseAccessCode;
|
||||||
|
envelope.CertificationType = settings.CertificationType;
|
||||||
|
envelope.FinalEmailToCreator = settings.FinalEmailToCreator;
|
||||||
|
envelope.FinalEmailToReceivers = settings.FinalEmailToReceivers;
|
||||||
|
envelope.SendReminderEmails = settings.SendReminderEmails;
|
||||||
|
envelope.FirstReminderDays = settings.FirstReminderDays;
|
||||||
|
envelope.ReminderIntervalDays = settings.ReminderIntervalDays;
|
||||||
|
envelope.ExpiresWhenDays = settings.ExpiresWhenDays;
|
||||||
|
envelope.ExpiresWarningWhenDays = settings.ExpiresWarningWhenDays;
|
||||||
|
envelope.ExpiresWhen = settings.ExpiresWhen;
|
||||||
|
envelope.ExpiresWarningWhen = settings.ExpiresWarningWhen;
|
||||||
|
envelope.ContractType = settings.ContractType;
|
||||||
|
envelope.ChangedWhen = now;
|
||||||
|
}
|
||||||
|
|
||||||
await Mediator.Send(new CreateHistoryCommand
|
await Mediator.Send(new CreateHistoryCommand
|
||||||
{
|
{
|
||||||
EnvelopeId = envelope.Id,
|
EnvelopeId = envelope.Id,
|
||||||
@@ -143,6 +225,105 @@ public class CreateEnvelopeCommandHandler : IRequestHandler<CreateEnvelopeComman
|
|||||||
return _mapper.Map<EnvelopeDto>(envelope);
|
return _mapper.Map<EnvelopeDto>(envelope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<EnvelopeSettings> ResolveEnvelopeSettingsAsync(CreateEnvelopeCommand request, Envelope? existing, CancellationToken cancel)
|
||||||
|
{
|
||||||
|
EnvelopeType? selectedType = null;
|
||||||
|
if (request.EnvelopeTypeId is int envelopeTypeId && envelopeTypeId > 0)
|
||||||
|
{
|
||||||
|
selectedType = await EnvelopeTypeRepository.Query
|
||||||
|
.FirstOrDefaultAsync(t => t.Id == envelopeTypeId, cancel)
|
||||||
|
?? throw new BadRequestException($"Envelope type {envelopeTypeId} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var expiresWhenDays = Math.Max(0,
|
||||||
|
request.ExpiresWhenDays
|
||||||
|
?? selectedType?.ExpiresWhenDays
|
||||||
|
?? existing?.ExpiresWhenDays
|
||||||
|
?? 0);
|
||||||
|
|
||||||
|
var expiresWarningWhenDays = Math.Max(0,
|
||||||
|
request.ExpiresWarningWhenDays
|
||||||
|
?? selectedType?.ExpiresWarningWhenDays
|
||||||
|
?? existing?.ExpiresWarningWhenDays
|
||||||
|
?? 0);
|
||||||
|
|
||||||
|
var useAccessCode = request.UseAccessCode
|
||||||
|
?? selectedType?.UseAccessCode
|
||||||
|
?? existing?.UseAccessCode
|
||||||
|
?? false;
|
||||||
|
|
||||||
|
if (request.TFAEnabled)
|
||||||
|
useAccessCode = true;
|
||||||
|
|
||||||
|
return new EnvelopeSettings(
|
||||||
|
EnvelopeTypeId: request.EnvelopeTypeId ?? existing?.EnvelopeTypeId,
|
||||||
|
Language: ResolveLanguage(request.Language, selectedType?.Language, existing?.Language),
|
||||||
|
UseAccessCode: useAccessCode,
|
||||||
|
CertificationType: request.CertificationType
|
||||||
|
?? (int?)selectedType?.CertificationType
|
||||||
|
?? existing?.CertificationType
|
||||||
|
?? (int)CertificationType.AdvancedElectronicSignature,
|
||||||
|
FinalEmailToCreator: request.FinalEmailToCreator
|
||||||
|
?? (int?)selectedType?.FinalEmailToCreator
|
||||||
|
?? existing?.FinalEmailToCreator
|
||||||
|
?? (int)FinalEmailType.No,
|
||||||
|
FinalEmailToReceivers: request.FinalEmailToReceivers
|
||||||
|
?? (int?)selectedType?.FinalEmailToReceivers
|
||||||
|
?? existing?.FinalEmailToReceivers
|
||||||
|
?? (int)FinalEmailType.No,
|
||||||
|
SendReminderEmails: request.SendReminderEmails
|
||||||
|
?? selectedType?.SendReminderEmails
|
||||||
|
?? existing?.SendReminderEmails
|
||||||
|
?? false,
|
||||||
|
FirstReminderDays: Math.Max(0,
|
||||||
|
request.FirstReminderDays
|
||||||
|
?? selectedType?.FirstReminderDays
|
||||||
|
?? existing?.FirstReminderDays
|
||||||
|
?? 0),
|
||||||
|
ReminderIntervalDays: Math.Max(0,
|
||||||
|
request.ReminderIntervalDays
|
||||||
|
?? selectedType?.ReminderIntervalDays
|
||||||
|
?? existing?.ReminderIntervalDays
|
||||||
|
?? 0),
|
||||||
|
ExpiresWhenDays: expiresWhenDays,
|
||||||
|
ExpiresWarningWhenDays: expiresWarningWhenDays,
|
||||||
|
ExpiresWhen: expiresWhenDays > 0 ? DateTime.Now.AddDays(expiresWhenDays) : null,
|
||||||
|
ExpiresWarningWhen: expiresWarningWhenDays > 0 ? DateTime.Now.AddDays(expiresWarningWhenDays) : null,
|
||||||
|
ContractType: existing?.ContractType
|
||||||
|
?? selectedType?.ContractType
|
||||||
|
?? (int)ContractType.Contract);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveLanguage(string? preferred, string? fallback1, string? fallback2)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(preferred))
|
||||||
|
return preferred.Trim();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(fallback1))
|
||||||
|
return fallback1.Trim();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(fallback2))
|
||||||
|
return fallback2.Trim();
|
||||||
|
|
||||||
|
return "de-DE";
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed record EnvelopeSettings(
|
||||||
|
int? EnvelopeTypeId,
|
||||||
|
string Language,
|
||||||
|
bool UseAccessCode,
|
||||||
|
int CertificationType,
|
||||||
|
int FinalEmailToCreator,
|
||||||
|
int FinalEmailToReceivers,
|
||||||
|
bool SendReminderEmails,
|
||||||
|
int FirstReminderDays,
|
||||||
|
int ReminderIntervalDays,
|
||||||
|
int ExpiresWhenDays,
|
||||||
|
int ExpiresWarningWhenDays,
|
||||||
|
DateTime? ExpiresWhen,
|
||||||
|
DateTime? ExpiresWarningWhen,
|
||||||
|
int ContractType);
|
||||||
|
|
||||||
private async Task<string> ResolveSenderReferenceAsync(Envelope envelope, CancellationToken cancel)
|
private async Task<string> ResolveSenderReferenceAsync(Envelope envelope, CancellationToken cancel)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(envelope.User?.Email))
|
if (!string.IsNullOrWhiteSpace(envelope.User?.Email))
|
||||||
|
|||||||
Reference in New Issue
Block a user