Skip to content

Commit 7562dfa

Browse files
feat: Update authentication and data seeding process
- Added default seeded users for the Sales API to facilitate login and avoid 401 errors during persistence. - Modified DatabaseSeeder to ensure authentication data is seeded first, preventing access issues during subsequent data seeding. - Enhanced customer and provider list components to handle null results gracefully, improving user experience and data loading reliability.
1 parent 6f7ee29 commit 7562dfa

File tree

5 files changed

+83
-11
lines changed

5 files changed

+83
-11
lines changed

AUTH.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,17 @@ public async Task<IResult> CreateInvoice(...) { }
100100
| `/api/auth/refresh` | POST | Refresh access token using refresh token |
101101
| `/api/auth/logout` | POST | Revoke refresh token |
102102

103+
### Default seeded users (Sales API)
104+
105+
After database seed (run at API startup), the following users exist. Use these to log in and avoid 401 when persisting.
106+
107+
| Username | Password | Role |
108+
|----------|-------------|---------|
109+
| **admin** | **Admin123!** | Admin |
110+
| Nieze | Manager123! | Manager |
111+
112+
Username is case-sensitive: use **admin** (lowercase), not Admin.
113+
103114
---
104115

105116
## Frontend (Blazor Server WebApp)

src/Modules/Sales/TunNetCom.SilkRoadErp.Sales.Api/Infrastructure/DataSeeder/DatabaseSeeder.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ public async Task SeedAsync(SalesContext context)
4949
}
5050
}
5151

52+
// Seed auth first so Admin user and roles exist before any other seed (avoids 401 when persisting)
53+
await SeedAuthAsync(context);
54+
5255
await SeedAccountingYearAsync(context);
5356
await SeedClientsAsync(context);
5457
await SeedFournisseursAsync(context);
@@ -58,7 +61,6 @@ public async Task SeedAsync(SalesContext context)
5861
await SeedProduitsAsync(context);
5962
await SeedBanquesAsync(context);
6063
await SeedInstallationTechniciansAsync(context);
61-
await SeedAuthAsync(context);
6264

6365
_logger.LogInformation("=== SEEDING DE LA BASE DE DONNÉES TERMINÉ AVEC SUCCÈS ===");
6466
}

src/Modules/Sales/TunNetCom.SilkRoadErp.Sales.WebApp/Components/Pages/Customers/CustomersList.razor

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
@using TunNetCom.DeleteModal
1111
@using TunNetCom.SilkRoadErp.Sales.Contracts.Sorting
1212
@using TunNetCom.SilkRoadErp.Sales.WebApp.Components.Pages.Providers
13+
@using TunNetCom.SilkRoadErp.Sales.WebApp.Helpers
1314
@inject NavigationManager navigationManager
1415
@inject IStringLocalizer<SharedResource> Localizer
1516
@inject ICustomersApiClient customerService
@@ -214,20 +215,21 @@
214215

215216
async Task LoadCustomerData(LoadDataArgs args)
216217
{
218+
var paging = PaginationHelper.FromLoadDataArgs(args, _defaultPageSize);
217219

218220
var parameters = new QueryStringParameters
219221
{
220-
PageNumber = (args.Skip.Value / _defaultPageSize) + 1,
221-
PageSize = args.Top ?? 10,
222+
PageNumber = paging.PageNumber,
223+
PageSize = paging.PageSize,
222224
SearchKeyword = searchKeyword ?? args.Filter,
223225
};
224226

225227
isLoadingCustomers = true;
226228
await Task.Yield();
227229

228230
var result = await customerService.GetAsync(parameters, cancellationTokenSource.Token);
229-
customers = result.Items;
230-
totalCustomers = result.TotalCount;
231+
customers = result?.Items ?? new List<CustomerResponse>();
232+
totalCustomers = result?.TotalCount ?? 0;
231233

232234
isLoadingCustomers = false;
233235
await InvokeAsync(StateHasChanged);

src/Modules/Sales/TunNetCom.SilkRoadErp.Sales.WebApp/Components/Pages/Providers/ProvidersList.razor

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
@using TunNetCom.DeleteModal
1212
@using Microsoft.JSInterop
1313
@using System.Text.Json
14+
@using TunNetCom.SilkRoadErp.Sales.WebApp.Helpers
1415

1516
@inject DialogService DialogService
1617
@inject IJSRuntime JSRuntime
@@ -234,16 +235,18 @@
234235

235236
private async Task LoadData(LoadDataArgs args)
236237
{
238+
var paging = PaginationHelper.FromLoadDataArgs(args, PageSize);
239+
237240
var queryParameters = new QueryStringParameters
238241
{
239-
PageNumber = (args.Skip ?? 0) / (args.Top ?? PageSize) + 1,
240-
PageSize = args.Top ?? PageSize,
242+
PageNumber = paging.PageNumber,
243+
PageSize = paging.PageSize,
241244
SearchKeyword = args.Filter
242245
};
243246

244247
var result = await providerService.GetPagedAsync(queryParameters, cancellationTokenSource.Token);
245-
providers = result.Items;
246-
totalCount = result.TotalCount;
248+
providers = result?.Items ?? new List<ProviderResponse>();
249+
totalCount = result?.TotalCount ?? 0;
247250
await InvokeAsync(StateHasChanged);
248251
}
249252

@@ -258,8 +261,8 @@
258261
};
259262

260263
var result = await providerService.GetPagedAsync(queryParameters, cancellationTokenSource.Token);
261-
providers = result.Items;
262-
totalCount = result.TotalCount;
264+
providers = result?.Items ?? new List<ProviderResponse>();
265+
totalCount = result?.TotalCount ?? 0;
263266
await InvokeAsync(StateHasChanged);
264267
}
265268

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using Radzen;
2+
3+
namespace TunNetCom.SilkRoadErp.Sales.WebApp.Helpers;
4+
5+
/// <summary>
6+
/// Helper pour les calculs de pagination à partir de Radzen LoadDataArgs.
7+
/// </summary>
8+
public static class PaginationHelper
9+
{
10+
/// <summary>
11+
/// Retourne le nombre d'éléments à ignorer (skip), jamais null.
12+
/// </summary>
13+
public static int GetSafeSkip(LoadDataArgs args) => args.Skip ?? 0;
14+
15+
/// <summary>
16+
/// Retourne la taille de page (top), toujours &gt; 0. Si args.Top est null ou 0, utilise defaultPageSize.
17+
/// </summary>
18+
public static int GetSafeTop(LoadDataArgs args, int defaultPageSize)
19+
{
20+
var top = args.Top ?? defaultPageSize;
21+
return top > 0 ? top : defaultPageSize;
22+
}
23+
24+
/// <summary>
25+
/// Calcule le numéro de page (1-based) à partir de skip et top.
26+
/// </summary>
27+
public static int GetPageNumber(int skip, int top)
28+
{
29+
if (top <= 0) return 1;
30+
return (skip / top) + 1;
31+
}
32+
33+
/// <summary>
34+
/// DTO pour les paramètres de pagination dérivés de LoadDataArgs.
35+
/// </summary>
36+
public readonly record struct PagingParams(int Skip, int Top, int PageNumber)
37+
{
38+
public int PageSize => Top;
39+
}
40+
41+
/// <summary>
42+
/// Extrait des paramètres de pagination sûrs à partir de LoadDataArgs.
43+
/// </summary>
44+
/// <param name="args">Arguments du RadzenDataGrid LoadData.</param>
45+
/// <param name="defaultPageSize">Taille de page par défaut si args.Top est null ou 0.</param>
46+
/// <returns>Skip, Top (toujours &gt; 0), et PageNumber (1-based).</returns>
47+
public static PagingParams FromLoadDataArgs(LoadDataArgs args, int defaultPageSize)
48+
{
49+
var skip = GetSafeSkip(args);
50+
var top = GetSafeTop(args, defaultPageSize);
51+
var pageNumber = GetPageNumber(skip, top);
52+
return new PagingParams(skip, top, pageNumber);
53+
}
54+
}

0 commit comments

Comments
 (0)