Skip to content

Commit 33453c7

Browse files
authored
Merge pull request #57 from boolean-uk/41-api-create-new-cohort-and-get-a-cohort-by-id
41 api create new cohort Looking good
2 parents 58f446f + 7529149 commit 33453c7

File tree

8 files changed

+99
-11
lines changed

8 files changed

+99
-11
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+

2+
using System.ComponentModel.DataAnnotations;
3+
using System.ComponentModel.DataAnnotations.Schema;
4+
using System.Text.Json.Serialization;
5+
6+
namespace exercise.wwwapi.Models;
7+
8+
public class CohortDTO
9+
{
10+
[JsonPropertyName("course_id")]
11+
12+
public int CohortNumber { get; set; }
13+
14+
public string CohortName { get; set; }
15+
16+
public DateTime StartDate { get; set; }
17+
public DateTime EndDate { get; set; }
18+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+

2+
using System.Text.Json.Serialization;
3+
4+
public class CohortPostDTO
5+
{
6+
public string CohortName { get; set; }
7+
8+
public DateTime StartDate { get; set; }
9+
public DateTime EndDate { get; set; }
10+
}

exercise.wwwapi/Data/ModelSeeder.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,6 @@ private static void SeedCohorts(ref ModelBuilder modelBuilder)
255255
EndDate = new DateTime(2026, 3, 29),
256256
}
257257

258-
259258
);
260259
}
261260

@@ -306,8 +305,6 @@ private static void SeedUserCC(ref ModelBuilder modelBuilder)
306305
CcId = 1,
307306
UserId = 3
308307
}
309-
310-
311308
);
312309
}
313310

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
using Microsoft.AspNetCore.Mvc;
1+
using exercise.wwwapi.DTOs;
2+
using exercise.wwwapi.Enums;
3+
using exercise.wwwapi.Models;
4+
using exercise.wwwapi.Repository;
5+
using Microsoft.AspNetCore.Mvc;
6+
using Microsoft.EntityFrameworkCore;
7+
using Npgsql;
28

39
namespace exercise.wwwapi.Endpoints;
410

@@ -9,9 +15,57 @@ public static void ConfigureCohortEndpoints(this WebApplication app)
915
var cohorts = app.MapGroup("cohorts");
1016
cohorts.MapPost("/", CreateCohort).WithSummary("Create a cohort");
1117
}
12-
[ProducesResponseType(StatusCodes.Status200OK)]
13-
public static async Task<IResult> CreateCohort()
18+
[ProducesResponseType(StatusCodes.Status201Created)]
19+
[ProducesResponseType(StatusCodes.Status400BadRequest)]
20+
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
21+
public static async Task<IResult> CreateCohort(IRepository<Cohort> cohortRepo, CohortPostDTO? postCohort)
1422
{
15-
return TypedResults.Ok();
23+
if (postCohort == null || postCohort.StartDate == DateTime.MinValue || postCohort.EndDate == DateTime.MinValue)
24+
{
25+
return TypedResults.BadRequest("Missing cohort data");
26+
}
27+
28+
bool success = false;
29+
int attempts = 0;
30+
int newCohortNumber = 0;
31+
32+
while (!success && attempts < 5)
33+
{
34+
try
35+
{
36+
var maxCohortNumber = (int?) await cohortRepo.GetMaxValueAsync(c => c.CohortNumber);
37+
if (maxCohortNumber == null)
38+
{
39+
maxCohortNumber = 0;
40+
}
41+
if (postCohort.CohortName == null)
42+
{
43+
postCohort.CohortName = $"Cohort {maxCohortNumber + 1}";
44+
}
45+
46+
newCohortNumber = (int)(maxCohortNumber + 1);
47+
Cohort newCohort = new Cohort { CohortNumber = newCohortNumber, CohortName = postCohort.CohortName, StartDate = postCohort.StartDate, EndDate = postCohort.EndDate };
48+
49+
cohortRepo.Insert(newCohort);
50+
await cohortRepo.SaveAsync();
51+
success = true;
52+
}
53+
catch (DbUpdateException ex)
54+
{
55+
if (ex.InnerException is PostgresException CohortNumberEx &&
56+
CohortNumberEx.SqlState == "23505") //23505 = Cohort number value already exists
57+
{
58+
attempts++;
59+
}
60+
else
61+
{
62+
Console.WriteLine($"DB update error: {ex.StackTrace}");
63+
return TypedResults.InternalServerError($"Error while updating the database: {ex.Message}");
64+
}
65+
}
66+
}
67+
68+
return TypedResults.Created($"/cohorts/{newCohortNumber}");
1669
}
70+
1771
}

exercise.wwwapi/Endpoints/UserEndpoints.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,4 @@ private static bool AuthorizeStudent(ClaimsPrincipal claims)
428428

429429
return false;
430430
}
431-
}
431+
}

exercise.wwwapi/Repository/IRepository.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ public interface IRepository<T>
2020
void Delete(T obj);
2121
void Save();
2222
Task SaveAsync();
23+
Task<object> GetMaxValueAsync(Expression<Func<T, object>> columnSelection);
2324
}

exercise.wwwapi/Repository/Repository.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using exercise.wwwapi.Data;
22
using Microsoft.EntityFrameworkCore;
33
using System.Linq.Expressions;
4+
using System.Numerics;
5+
using System.Reflection.Metadata.Ecma335;
46

57
namespace exercise.wwwapi.Repository;
68

@@ -45,7 +47,7 @@ public async Task<IEnumerable<T>> GetAllAsync(params Expression<Func<T, object>>
4547

4648
return await _table.ToListAsync();
4749
}
48-
50+
4951
public T? GetById(object id, params Expression<Func<T, object>>[] includeExpressions)
5052
{
5153
if (includeExpressions.Length != 0)
@@ -81,7 +83,8 @@ public async Task<IEnumerable<T>> GetAllAsync(params Expression<Func<T, object>>
8183
return await query.FirstOrDefaultAsync(e => EF.Property<object>(e, "Id").Equals(id));
8284
}
8385

84-
return await _table.FindAsync(id); }
86+
return await _table.FindAsync(id);
87+
}
8588

8689
public void Insert(T obj)
8790
{
@@ -127,4 +130,9 @@ public async Task<T> GetByIdWithIncludes(Func<IQueryable<T>, IQueryable<T>>? inc
127130
var res = await query.Where(a => a.Id == id).FirstOrDefaultAsync();
128131
return res;
129132
}
133+
134+
public Task<object> GetMaxValueAsync(Expression<Func<T, object>> columnSelection)
135+
{
136+
return _table.MaxAsync(columnSelection);
137+
}
130138
}

exercise.wwwapi/appsettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
"ConnectionStrings": {
1414
"DefaultConnection": "Host=${Neon:Host}; Database=${Neon:Database}; Username=${Neon:Username}; Password=${Neon:Password}; SSL Mode=VerifyFull; Channel Binding=Require;"
1515
}
16-
}
16+
}

0 commit comments

Comments
 (0)