diff --git a/source/ticketAPI/api/Controllers/TicketController.cs b/source/ticketAPI/api/Controllers/TicketController.cs
index df1fec6..537debe 100644
--- a/source/ticketAPI/api/Controllers/TicketController.cs
+++ b/source/ticketAPI/api/Controllers/TicketController.cs
@@ -60,4 +60,25 @@ public class TicketController(
return BadRequest(e.Message);
}
}
+
+ ///
+ /// Searches for a ticket with a given ticketId and validates it against the event associated with it.
+ ///
+ /// A string representing a GUID value
+ /// Ticket Search Result
+ [HttpGet]
+ public ActionResult Get(string ticketId)
+ {
+ //TODO: Protect Endpoint
+
+ try
+ {
+ var result = ticketManager.SearchTicket(ticketId);
+ return Ok(result);
+ }
+ catch (Exception e)
+ {
+ return BadRequest(e.Message);
+ }
+ }
}
\ No newline at end of file
diff --git a/source/ticketAPI/api/Interfaces/ITicketManager.cs b/source/ticketAPI/api/Interfaces/ITicketManager.cs
index 7cf4fd7..fc229f9 100644
--- a/source/ticketAPI/api/Interfaces/ITicketManager.cs
+++ b/source/ticketAPI/api/Interfaces/ITicketManager.cs
@@ -1,8 +1,11 @@
using models.Core;
+using models.Response;
namespace api.Interfaces;
public interface ITicketManager
{
void SaveMintedTicket(Ticket ticket);
+
+ TicketSearch SearchTicket(string ticketId);
}
\ No newline at end of file
diff --git a/source/ticketAPI/api/RestFiles/event.http b/source/ticketAPI/api/RestFiles/event.http
index 4a97ac9..b6a6464 100644
--- a/source/ticketAPI/api/RestFiles/event.http
+++ b/source/ticketAPI/api/RestFiles/event.http
@@ -1,4 +1,5 @@
@api_HostAddress = http://localhost:5168
+@eventId = b9f4478b-701b-4223-9aaa-042b6f53b83a
POST {{api_HostAddress}}/event
Accept: application/json
@@ -30,8 +31,8 @@ Accept: application/json
Content-Type: application/json
{
- "Id": "1a06c032-b073-4715-9b95-9f3410e7abd9",
- "Date": "2024-12-03T15:00:00.991Z",
+ "Id": "{{eventId}}",
+ "Date": "2024-12-05T15:00:00.991Z",
"EventName": "Winter Concert",
"EventDescription": "A wintery journey of classical music",
"Venue": {
diff --git a/source/ticketAPI/api/RestFiles/ticket.http b/source/ticketAPI/api/RestFiles/ticket.http
index d8173d1..cf347d9 100644
--- a/source/ticketAPI/api/RestFiles/ticket.http
+++ b/source/ticketAPI/api/RestFiles/ticket.http
@@ -1,4 +1,6 @@
@api_HostAddress = http://localhost:5168
+@ticketId = 59ae05ea-fd07-481a-9a6b-663444cc426d
+@eventId = b9f4478b-701b-4223-9aaa-042b6f53b83a
POST {{api_HostAddress}}/ticket
Accept: application/json
@@ -6,7 +8,11 @@ Content-Type: application/json
{
"ticketType": "Single",
- "eventId": "1a06c032-b073-4715-9b95-9f3410e7abd9"
+ "eventId": "{{eventId}}"
}
###
+
+GET {{api_HostAddress}}/ticket?ticketId={{ticketId}}
+Accept: application/json
+Content-Type: application/json
\ No newline at end of file
diff --git a/source/ticketAPI/api/Services/TicketManager.cs b/source/ticketAPI/api/Services/TicketManager.cs
index ddaa6fe..f7b9ffd 100644
--- a/source/ticketAPI/api/Services/TicketManager.cs
+++ b/source/ticketAPI/api/Services/TicketManager.cs
@@ -1,6 +1,7 @@
using api.Interfaces;
-using data.Tickets;
using models.Core;
+using models.Enumerations;
+using models.Response;
namespace api.Services;
@@ -8,7 +9,49 @@ public class TicketManager : ITicketManager
{
public void SaveMintedTicket(Ticket ticket)
{
- //TODO: Add Ticket to Event
- new Save().Execute(ticket);
+ new data.Tickets.Save().Execute(ticket);
+ new data.Events.AddTicket().Execute(ticket.Id, ticket.EventId);
+ }
+
+ public TicketSearch SearchTicket(string ticketId)
+ {
+ var ticket = new data.Tickets.Find().Execute(ticketId);
+
+ if (ticket == null)
+ {
+ throw new Exception("Ticket not found");
+ }
+
+ var @event = new data.Events.Find().Execute(ticket.EventId);
+
+ if (@event == null)
+ {
+ throw new Exception("Event not found");
+ }
+
+ var result = new TicketSearch
+ {
+ Type = ticket.Type,
+ Validity = DetermineValidity(@event)
+ };
+
+ return result;
+ }
+
+ private static TicketValidity DetermineValidity(Event @event)
+ {
+ if (@event.Date < DateTime.Now)
+ {
+ return TicketValidity.Expired;
+ }
+
+ if (@event.Date != DateTime.Today) return TicketValidity.Invalid;
+
+ if (DateTime.Now.Hour < @event.Date.Hour - 2)
+ {
+ return TicketValidity.Early;
+ }
+
+ return DateTime.Now.Hour > @event.Date.Hour + 5 ? TicketValidity.Expired : TicketValidity.Valid;
}
}
\ No newline at end of file
diff --git a/source/ticketAPI/data/Events/AddTicket.cs b/source/ticketAPI/data/Events/AddTicket.cs
new file mode 100644
index 0000000..c024de6
--- /dev/null
+++ b/source/ticketAPI/data/Events/AddTicket.cs
@@ -0,0 +1,18 @@
+using models.Core;
+using MongoDB.Driver;
+
+namespace data.Events;
+
+public class AddTicket
+{
+ public void Execute(Guid ticketId, Guid eventId)
+ {
+ var database = MongoFactory.GetDatabase();
+ var collection = database.GetCollection("events");
+ var filter = Builders.Filter.Eq(e => e.Id, eventId);
+
+ var update = Builders.Update.Push("TicketIds", ticketId);
+
+ collection.FindOneAndUpdate(filter, update);
+ }
+}
\ No newline at end of file
diff --git a/source/ticketAPI/data/Events/Find.cs b/source/ticketAPI/data/Events/Find.cs
new file mode 100644
index 0000000..f4da66a
--- /dev/null
+++ b/source/ticketAPI/data/Events/Find.cs
@@ -0,0 +1,15 @@
+using models.Core;
+using MongoDB.Driver;
+
+namespace data.Events;
+
+public class Find
+{
+ public Event Execute(Guid eventId)
+ {
+ var database = MongoFactory.GetDatabase();
+ var collection = database.GetCollection("events");
+ var filter = Builders.Filter.Eq("Id", eventId);
+ return collection.Find(filter).FirstOrDefault();
+ }
+}
\ No newline at end of file
diff --git a/source/ticketAPI/data/Events/Update.cs b/source/ticketAPI/data/Events/Update.cs
index 3e5c2d4..365aaa3 100644
--- a/source/ticketAPI/data/Events/Update.cs
+++ b/source/ticketAPI/data/Events/Update.cs
@@ -11,7 +11,7 @@ public class Update
var database = MongoFactory.GetDatabase();
var collection = database.GetCollection("events");
- var filter = Builders.Filter.Eq(e => e.Id, request.Id);
+ var filter = Builders.Filter.Eq("_id", request.Id);
var newEvent = new Event
{
diff --git a/source/ticketAPI/data/MongoFactory.cs b/source/ticketAPI/data/MongoFactory.cs
index 2e6ab44..8339827 100644
--- a/source/ticketAPI/data/MongoFactory.cs
+++ b/source/ticketAPI/data/MongoFactory.cs
@@ -1,4 +1,7 @@
using Microsoft.Extensions.Configuration;
+using MongoDB.Bson;
+using MongoDB.Bson.Serialization;
+using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Driver;
namespace data;
@@ -13,6 +16,8 @@ public static class MongoFactory
///
public static void InitConfig(IConfiguration config)
{
+ //set up the use of guids globally for the mongo connection
+ BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
_config = config;
}
diff --git a/source/ticketAPI/data/Tickets/Find.cs b/source/ticketAPI/data/Tickets/Find.cs
new file mode 100644
index 0000000..09afd59
--- /dev/null
+++ b/source/ticketAPI/data/Tickets/Find.cs
@@ -0,0 +1,15 @@
+using models.Core;
+using MongoDB.Driver;
+
+namespace data.Tickets;
+
+public class Find
+{
+ public Ticket Execute(string ticketId)
+ {
+ var database = MongoFactory.GetDatabase();
+ var collection = database.GetCollection("tickets");
+ var filter = Builders.Filter.Eq("Id", ticketId);
+ return collection.Find(filter).FirstOrDefault();
+ }
+}
\ No newline at end of file
diff --git a/source/ticketAPI/models/Core/Event.cs b/source/ticketAPI/models/Core/Event.cs
index 9cf2abd..c860925 100644
--- a/source/ticketAPI/models/Core/Event.cs
+++ b/source/ticketAPI/models/Core/Event.cs
@@ -1,11 +1,7 @@
-using MongoDB.Bson;
-using MongoDB.Bson.Serialization.Attributes;
-
namespace models.Core;
public class Event
{
- [BsonGuidRepresentation(GuidRepresentation.Standard)]
public Guid Id { get; set; }
public DateTime Date { get; set; }
public required string EventName { get; set; }
diff --git a/source/ticketAPI/models/Core/Talent.cs b/source/ticketAPI/models/Core/Talent.cs
index 4403510..b1902b6 100644
--- a/source/ticketAPI/models/Core/Talent.cs
+++ b/source/ticketAPI/models/Core/Talent.cs
@@ -1,6 +1,3 @@
-using MongoDB.Bson;
-using MongoDB.Bson.Serialization.Attributes;
-
namespace models.Core;
public class Talent
diff --git a/source/ticketAPI/models/Core/Ticket.cs b/source/ticketAPI/models/Core/Ticket.cs
index f238560..169d716 100644
--- a/source/ticketAPI/models/Core/Ticket.cs
+++ b/source/ticketAPI/models/Core/Ticket.cs
@@ -1,14 +1,10 @@
using models.Enumerations;
-using MongoDB.Bson;
-using MongoDB.Bson.Serialization.Attributes;
namespace models.Core;
public class Ticket
{
- [BsonGuidRepresentation(GuidRepresentation.Standard)]
public Guid Id { get; set; }
- [BsonGuidRepresentation(GuidRepresentation.Standard)]
public Guid EventId { get; set; }
public TicketType Type { get; set; }
public required string QrCode { get; set; }
diff --git a/source/ticketAPI/models/Enumerations/TicketValidity.cs b/source/ticketAPI/models/Enumerations/TicketValidity.cs
new file mode 100644
index 0000000..137f9db
--- /dev/null
+++ b/source/ticketAPI/models/Enumerations/TicketValidity.cs
@@ -0,0 +1,9 @@
+namespace models.Enumerations;
+
+public enum TicketValidity
+{
+ Valid,
+ Expired,
+ Early,
+ Invalid
+}
\ No newline at end of file
diff --git a/source/ticketAPI/models/Response/TicketSearch.cs b/source/ticketAPI/models/Response/TicketSearch.cs
new file mode 100644
index 0000000..9ce941b
--- /dev/null
+++ b/source/ticketAPI/models/Response/TicketSearch.cs
@@ -0,0 +1,9 @@
+using models.Enumerations;
+
+namespace models.Response;
+
+public class TicketSearch
+{
+ public TicketType Type { get; set; }
+ public TicketValidity Validity { get; set; }
+}
\ No newline at end of file
diff --git a/source/ticketAPI/ticketAPI.sln.DotSettings.user b/source/ticketAPI/ticketAPI.sln.DotSettings.user
index 942f032..aa3a83d 100644
--- a/source/ticketAPI/ticketAPI.sln.DotSettings.user
+++ b/source/ticketAPI/ticketAPI.sln.DotSettings.user
@@ -2,4 +2,5 @@
ForceIncluded
ForceIncluded
ForceIncluded
+ ForceIncluded
ForceIncluded
\ No newline at end of file
diff --git a/source/ticketUI/src/app/services/event.service.ts b/source/ticketUI/src/app/services/event.service.ts
index 1cbc82b..940984f 100644
--- a/source/ticketUI/src/app/services/event.service.ts
+++ b/source/ticketUI/src/app/services/event.service.ts
@@ -1,4 +1,4 @@
-import {inject, Injectable} from '@angular/core';
+import {inject, Injectable, signal, WritableSignal} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {AddEventRequest} from '../../models/request/add-event-request';
import {ApiUtils} from './api-utils';
@@ -10,6 +10,7 @@ import {catchError, of} from 'rxjs';
providedIn: 'root'
})
export class EventService extends ApiUtils {
+ public eventSignal: WritableSignal = signal(null);
private httpClient = inject(HttpClient);
constructor() {
@@ -45,4 +46,17 @@ export class EventService extends ApiUtils {
})
).subscribe();
}
+
+ public searchEvents(startDate: Date, endDate: Date): void {
+ const options = this.setHttpRequestOptions();
+ const url = environment.apiBase + Endpoints.EVENT;
+
+ this.httpClient.get(url, options)
+ .pipe(
+ catchError(error => {
+ console.log(error);
+ return of(undefined);
+ })
+ ).subscribe();
+ }
}
diff --git a/source/ticketUI/src/app/services/ticket.service.ts b/source/ticketUI/src/app/services/ticket.service.ts
index 841e9b3..017e0f8 100644
--- a/source/ticketUI/src/app/services/ticket.service.ts
+++ b/source/ticketUI/src/app/services/ticket.service.ts
@@ -1,4 +1,4 @@
-import {inject, Injectable} from '@angular/core';
+import {inject, Injectable, WritableSignal} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {signal} from '@angular/core';
import {catchError, map, of} from 'rxjs';
@@ -7,12 +7,14 @@ import {MintResponse} from '../../models/response/mint-response';
import {Endpoints} from '../../models/endpoints';
import {MintRequest} from '../../models/request/mint-request';
import {ApiUtils} from './api-utils';
+import {TicketValidity} from '../../models/enums/ticket-validity.enum';
@Injectable({
providedIn: 'root'
})
export class TicketService extends ApiUtils {
- public dataSignal = signal('');
+ public dataSignal: WritableSignal = signal('');
+ public validitySignal: WritableSignal = signal(null);
private httpClient = inject(HttpClient);
constructor() {
@@ -36,4 +38,22 @@ export class TicketService extends ApiUtils {
}
});
}
+
+ public searchTicket(ticketId: string): void {
+ const options = this.setHttpRequestOptions();
+ const url = environment.apiBase + Endpoints.TICKET_SEARCH(ticketId);
+
+ this.httpClient.get(url, options)
+ .pipe(
+ map((response: any) => response.body),
+ catchError(error => {
+ console.log(error);
+ return of(undefined);
+ })
+ ).subscribe((res: TicketValidity) => {
+ if (res !== undefined) {
+ this.validitySignal.set(res);
+ }
+ });
+ }
}
diff --git a/source/ticketUI/src/models/endpoints.ts b/source/ticketUI/src/models/endpoints.ts
index a315e8e..3dcab34 100644
--- a/source/ticketUI/src/models/endpoints.ts
+++ b/source/ticketUI/src/models/endpoints.ts
@@ -1,5 +1,17 @@
export class Endpoints {
- public static readonly TICKET = 'ticket';
+ /* Ticket Routes */
+ public static readonly TICKET: string = 'ticket';
- public static readonly EVENT = 'events';
+ /* Calculated Routes */
+ public static TICKET_SEARCH(ticketId: string): string {
+ return `${Endpoints.TICKET}?ticketId=${ticketId}`;
+ }
+
+ /* Event Routes */
+ public static readonly EVENT: string = 'events';
+
+ /* Calculated Routes */
+ public static EVENT_DATE_SEARCH(startDate: Date, endDate: Date): string {
+ return `${Endpoints.EVENT}?startDate=${startDate}&endDate=${endDate}`;
+ }
}
diff --git a/source/ticketUI/src/models/enums/ticket-validity.enum.ts b/source/ticketUI/src/models/enums/ticket-validity.enum.ts
new file mode 100644
index 0000000..3876b42
--- /dev/null
+++ b/source/ticketUI/src/models/enums/ticket-validity.enum.ts
@@ -0,0 +1,6 @@
+export enum TicketValidity {
+ Valid,
+ Expired,
+ Early,
+ Invalid
+}
diff --git a/source/ticketUI/src/models/request/patch-event.ts b/source/ticketUI/src/models/request/patch-event.ts
new file mode 100644
index 0000000..1bd35eb
--- /dev/null
+++ b/source/ticketUI/src/models/request/patch-event.ts
@@ -0,0 +1,11 @@
+import {Venue} from '../core/venue';
+import {Talent} from '../core/talent';
+
+export interface PatchEvent {
+ id: string,
+ date: Date,
+ eventName: string,
+ eventDescription: string,
+ venue: Venue,
+ talent: Talent
+}
diff --git a/source/ticketUI/src/models/response/ticket-search.ts b/source/ticketUI/src/models/response/ticket-search.ts
new file mode 100644
index 0000000..78de130
--- /dev/null
+++ b/source/ticketUI/src/models/response/ticket-search.ts
@@ -0,0 +1,7 @@
+import {TicketTypeEnum} from '../enums/ticket-type.enum';
+import {TicketValidity} from '../enums/ticket-validity.enum';
+
+export interface TicketSearch {
+ ticketType: TicketTypeEnum,
+ ticketValidity: TicketValidity
+}