Add contribution payment options to registries
- Added support for single and amount-specific QR codes. - Updated `RegistrySettings` model and database schema. - Enhanced `RegistryAdmin` to configure payment options. - Introduced `RegistryContributionAmount` for partial fulfillment. - Updated `RegistryPublic` to display contribution progress. - Added new models for payment methods and QR code handling. - Improved privacy by limiting contributor visibility.
This commit is contained in:
@@ -2,6 +2,19 @@ using BirthList.Domain.Entities;
|
||||
|
||||
namespace BirthList.Web.Features.Registries;
|
||||
|
||||
public enum ContributionPaymentMethodType
|
||||
{
|
||||
Iban = 1,
|
||||
SingleQrCode = 2,
|
||||
AmountSpecificQrCode = 3
|
||||
}
|
||||
|
||||
public sealed class ContributionAmountQrCodeModel
|
||||
{
|
||||
public decimal Amount { get; set; }
|
||||
public string QrCodeUrl { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public sealed class RegistryCreateModel
|
||||
{
|
||||
public string Title { get; set; } = string.Empty;
|
||||
@@ -47,6 +60,8 @@ public sealed class RegistrySettingsEditModel
|
||||
public string? BankAccountBic { get; set; }
|
||||
public string? BankAccountDisplayName { get; set; }
|
||||
public bool ShowBankAccountName { get; set; }
|
||||
public string? ContributionQrCodeUrl { get; set; }
|
||||
public List<ContributionAmountQrCodeModel> ContributionAmountQrCodes { get; set; } = [];
|
||||
}
|
||||
|
||||
public sealed class RegistrySummaryViewModel
|
||||
@@ -73,6 +88,8 @@ public sealed class RegistryPublicViewModel
|
||||
public string? BankAccountBic { get; init; }
|
||||
public string? BankAccountDisplayName { get; init; }
|
||||
public bool ShowBankAccountName { get; init; }
|
||||
public string? ContributionQrCodeUrl { get; init; }
|
||||
public IReadOnlyList<ContributionAmountQrCodeModel> ContributionAmountQrCodes { get; init; } = [];
|
||||
public string? CurrentUserId { get; init; }
|
||||
public bool IsAdmin { get; init; }
|
||||
public IReadOnlyList<RegistryPublicItemViewModel> Items { get; init; } = [];
|
||||
|
||||
@@ -4,6 +4,7 @@ using BirthList.Web.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace BirthList.Web.Features.Registries;
|
||||
|
||||
@@ -210,6 +211,8 @@ internal sealed class RegistryService(RegistryDbContext registryDbContext, Appli
|
||||
BankAccountBic = settings?.BankAccountBic,
|
||||
BankAccountDisplayName = settings?.BankAccountDisplayName,
|
||||
ShowBankAccountName = settings?.ShowBankAccountName ?? false,
|
||||
ContributionQrCodeUrl = settings?.ContributionQrCodeUrl,
|
||||
ContributionAmountQrCodes = ParseContributionAmountQrCodes(settings?.ContributionAmountQrCodesJson),
|
||||
CurrentUserId = userId,
|
||||
IsAdmin = isAdmin,
|
||||
Items = registry.Items
|
||||
@@ -289,7 +292,9 @@ internal sealed class RegistryService(RegistryDbContext registryDbContext, Appli
|
||||
BankAccountIban = settings?.BankAccountIban,
|
||||
BankAccountBic = settings?.BankAccountBic,
|
||||
BankAccountDisplayName = settings?.BankAccountDisplayName,
|
||||
ShowBankAccountName = settings?.ShowBankAccountName ?? false
|
||||
ShowBankAccountName = settings?.ShowBankAccountName ?? false,
|
||||
ContributionQrCodeUrl = settings?.ContributionQrCodeUrl,
|
||||
ContributionAmountQrCodes = ParseContributionAmountQrCodes(settings?.ContributionAmountQrCodesJson).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -325,10 +330,68 @@ internal sealed class RegistryService(RegistryDbContext registryDbContext, Appli
|
||||
settings.BankAccountBic = string.IsNullOrWhiteSpace(model.BankAccountBic) ? null : model.BankAccountBic.Trim();
|
||||
settings.BankAccountDisplayName = string.IsNullOrWhiteSpace(model.BankAccountDisplayName) ? null : model.BankAccountDisplayName.Trim();
|
||||
settings.ShowBankAccountName = model.ShowBankAccountName;
|
||||
settings.ContributionQrCodeUrl = string.IsNullOrWhiteSpace(model.ContributionQrCodeUrl) ? null : model.ContributionQrCodeUrl.Trim();
|
||||
settings.ContributionAmountQrCodesJson = SerializeContributionAmountQrCodes(model.ContributionAmountQrCodes);
|
||||
|
||||
await registryDbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<ContributionAmountQrCodeModel> ParseContributionAmountQrCodes(string? json)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(json))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var items = JsonSerializer.Deserialize<List<ContributionAmountQrCodeModel>>(json);
|
||||
if (items is null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
return items
|
||||
.Where(x => x.Amount > 0 && !string.IsNullOrWhiteSpace(x.QrCodeUrl))
|
||||
.Select(x => new ContributionAmountQrCodeModel
|
||||
{
|
||||
Amount = x.Amount,
|
||||
QrCodeUrl = x.QrCodeUrl.Trim()
|
||||
})
|
||||
.OrderBy(x => x.Amount)
|
||||
.ToList();
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private static string? SerializeContributionAmountQrCodes(IEnumerable<ContributionAmountQrCodeModel>? amountQrCodes)
|
||||
{
|
||||
if (amountQrCodes is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var normalized = amountQrCodes
|
||||
.Where(x => x.Amount > 0 && !string.IsNullOrWhiteSpace(x.QrCodeUrl))
|
||||
.Select(x => new ContributionAmountQrCodeModel
|
||||
{
|
||||
Amount = x.Amount,
|
||||
QrCodeUrl = x.QrCodeUrl.Trim()
|
||||
})
|
||||
.OrderBy(x => x.Amount)
|
||||
.ToList();
|
||||
|
||||
if (normalized.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonSerializer.Serialize(normalized);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<RegistryItemEditModel>> GetRegistryItemsAsync(Guid registryId, CancellationToken cancellationToken)
|
||||
{
|
||||
var items = await registryDbContext.RegistryItems
|
||||
|
||||
Reference in New Issue
Block a user