Skip to content

Commit 087e1f5

Browse files
Merge branch 'release/2.0.0-hotfix1' into release/2.0.1
2 parents f0a30f0 + 03b14b0 commit 087e1f5

File tree

13 files changed

+556
-237
lines changed

13 files changed

+556
-237
lines changed

src/Spd.Manager.Printing/Contract.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ namespace Spd.Manager.Printing;
55
public interface IPrintingManager
66
{
77
public Task<ResultResponse> Handle(StartPrintJobCommand cmd, CancellationToken ct);
8+
public Task<ResultResponse> Handle(PrintCardsInBatchCommand cmd, CancellationToken ct);
89
public Task<ResultResponse> Handle(PrintJobStatusQuery cmd, CancellationToken ct);
910
public Task<PreviewDocumentResp> Handle(PreviewDocumentCommand request, CancellationToken ct);
1011
public Task<PreviewDocumentResp> Handle(PrintingEventImageQuery request, CancellationToken ct);
1112
}
1213
public record StartPrintJobCommand(Guid EventId) : IRequest<ResultResponse>;
14+
public record PrintCardsInBatchCommand() : IRequest<ResultResponse>;
1315
public record PrintJobStatusQuery(Guid EventId) : IRequest<ResultResponse>;
1416
public record PreviewDocumentCommand(Guid LicenceId) : IRequest<PreviewDocumentResp>;
1517
public record PrintingEventImageQuery(Guid EventId) : IRequest<PreviewDocumentResp>;

src/Spd.Manager.Printing/Documents/TransformationStrategies/PersonalLicencePrintingTransformStrategy.cs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,39 @@
11
using AutoMapper;
22
using Spd.Resource.Repository.Licence;
33
using Spd.Utilities.Printing.BCMailPlus;
4-
using Spd.Utilities.Shared.Exceptions;
54
using System.Text.Json.Serialization;
65

76
namespace Spd.Manager.Printing.Documents.TransformationStrategies;
87

98
internal class PersonalLicencePrintingTransformStrategy(
109
ILicenceRepository licenceRepository,
1110
IMapper mapper)
12-
: BcMailPlusTransformStrategyBase<PersonalLicencePrintingTransformRequest, PersonalLicencePrinting>(Jobs.PersonalLicenseRelease)
11+
: BcMailPlusTransformStrategyBase<PersonalLicenceBatchPrintingTransformRequest, PersonalLicencePrinting>(Jobs.PersonalLicenseRelease)
1312
{
14-
protected override async Task<PersonalLicencePrinting> CreateDocument(PersonalLicencePrintingTransformRequest request, CancellationToken cancellationToken)
13+
protected override async Task<PersonalLicencePrinting> CreateDocument(PersonalLicenceBatchPrintingTransformRequest request, CancellationToken cancellationToken)
1514
{
16-
LicenceResp? licence = await licenceRepository.GetAsync(request.LicenceId, cancellationToken);
17-
18-
if (licence?.PrintingPreviewJobId == null)
19-
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "Cannot find the preview job id");
20-
21-
return new PersonalLicencePrinting()
15+
if (request.CardPrintEvents.Any())
2216
{
23-
Jobs = new List<string> { licence?.PrintingPreviewJobId }
24-
};
17+
var result = new PersonalLicencePrinting()
18+
{
19+
Jobs = request.CardPrintEvents.Where(p => p.PrintingPreviewJobId != null)
20+
.Select(p => p.PrintingPreviewJobId)
21+
.ToList(),
22+
};
23+
if (result.Jobs.Any()) return result;
24+
}
25+
return null;
2526
}
26-
2727
}
2828

29-
public record PersonalLicencePrintingTransformRequest(Guid LicenceId) : DocumentTransformRequest;
30-
29+
public record PersonalLicenceBatchPrintingTransformRequest(List<CardPrintEvent> CardPrintEvents) : DocumentTransformRequest;
30+
public record CardPrintEvent
31+
{
32+
public Guid EventQueueId { get; set; }
33+
public string? PrintingPreviewJobId { get; set; }
34+
public bool? IsSuccess { get; set; }
35+
public string? ErrMsg { get; set; }
36+
}
3137
public record PersonalLicencePrinting
3238
{
3339
[JsonPropertyName("Jobs")]

src/Spd.Manager.Printing/PrintingManager.cs

Lines changed: 112 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ namespace Spd.Manager.Printing;
1313

1414
internal class PrintingManager
1515
: IRequestHandler<StartPrintJobCommand, ResultResponse>,
16+
IRequestHandler<PrintCardsInBatchCommand, ResultResponse>,
1617
IRequestHandler<PrintJobStatusQuery, ResultResponse>,
1718
IRequestHandler<PreviewDocumentCommand, PreviewDocumentResp>,
1819
IRequestHandler<PrintingEventImageQuery, PreviewDocumentResp>,
@@ -81,6 +82,44 @@ public async Task<ResultResponse> Handle(StartPrintJobCommand request, Cancellat
8182
return null;
8283
}
8384

85+
public async Task<ResultResponse> Handle(PrintCardsInBatchCommand request, CancellationToken cancellationToken)
86+
{
87+
PersonalLicenceBatchPrintingTransformRequest transformRequest = await CreatePersonalLicenceBatchPrintingTransformRequest(cancellationToken);
88+
89+
if (transformRequest.CardPrintEvents.Any())
90+
{
91+
try
92+
{
93+
var transformResponse = await _documentTransformationEngine.Transform(
94+
transformRequest,
95+
cancellationToken);
96+
if (transformResponse is BcMailPlusTransformResponse)
97+
{
98+
BcMailPlusTransformResponse transformResult = (BcMailPlusTransformResponse)transformResponse;
99+
var printResponse = await _printer.Send(
100+
new BCMailPlusPrintRequest(transformResult.JobTemplateId, transformResult.Document),
101+
cancellationToken);
102+
ResultResponse result = _mapper.Map<ResultResponse>(printResponse);
103+
await UpdateResultInEvents(result, transformRequest.CardPrintEvents, cancellationToken);
104+
return result;
105+
}
106+
}
107+
catch (Exception ex)
108+
{
109+
_logger.LogError(ex, ex.Message, null);
110+
ResultResponse result = new()
111+
{
112+
PrintJobId = null,
113+
Status = JobStatusCode.Error,
114+
Error = $"{ex.Message} {ex.InnerException?.Message}"
115+
};
116+
await UpdateResultInEvents(result, transformRequest.CardPrintEvents, cancellationToken);
117+
return result;
118+
}
119+
}
120+
return null;
121+
}
122+
84123
public async Task<ResultResponse> Handle(PrintJobStatusQuery request, CancellationToken cancellationToken)
85124
{
86125
//get event
@@ -144,41 +183,90 @@ private static DocumentTransformRequest CreateDocumentTransformRequest(EventResp
144183
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPScreeningFingerprintPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_application"))
145184
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "ApplicationId cannot be null if it is BCMPScreeningFingerprintPrinting");
146185

147-
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPSecurityWorkerLicencePrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
148-
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPSecurityWorkerLicencePrinting");
149-
150-
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPArmouredVehiclePermitPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
151-
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPArmouredVehiclePermitPrinting");
152-
153-
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPBodyArmourPermitPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
154-
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPBodyArmourPermitPrinting");
155-
156-
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPGuideDogServiceDogTeamPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
157-
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPGuideDogServiceDogTeamPrinting");
158-
159-
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPDogTrainerPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
160-
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPDogTrainerPrinting");
161-
162-
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPRetiredServiceDogPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
163-
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPRetiredServiceDogPrinting");
164-
165186
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPBusinessLicencePrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
166187
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPBusinessLicencePrinting");
167188

168189
return eventResp.EventTypeEnum switch
169190
{
170191
EventTypeEnum.BCMPScreeningFingerprintPrinting => new FingerprintLetterTransformRequest(eventResp.RegardingObjectId.Value),
171-
EventTypeEnum.BCMPSecurityWorkerLicencePrinting => new PersonalLicencePrintingTransformRequest((Guid)eventResp.RegardingObjectId),
172-
EventTypeEnum.BCMPBodyArmourPermitPrinting => new PersonalLicencePrintingTransformRequest((Guid)eventResp.RegardingObjectId),
173-
EventTypeEnum.BCMPArmouredVehiclePermitPrinting => new PersonalLicencePrintingTransformRequest((Guid)eventResp.RegardingObjectId),
174-
EventTypeEnum.BCMPGuideDogServiceDogTeamPrinting => new PersonalLicencePrintingTransformRequest((Guid)eventResp.RegardingObjectId),
175-
EventTypeEnum.BCMPDogTrainerPrinting => new PersonalLicencePrintingTransformRequest((Guid)eventResp.RegardingObjectId),
176-
EventTypeEnum.BCMPRetiredServiceDogPrinting => new PersonalLicencePrintingTransformRequest((Guid)eventResp.RegardingObjectId),
177192
EventTypeEnum.BCMPBusinessLicencePrinting => new BizLicencePrintingTransformRequest((Guid)eventResp.RegardingObjectId),
178193
_ => throw new NotImplementedException()
179194
};
180195
}
181196

197+
private async Task<PersonalLicenceBatchPrintingTransformRequest> CreatePersonalLicenceBatchPrintingTransformRequest(CancellationToken ct)
198+
{
199+
IEnumerable<EventResp?> eventResps = await _eventRepo.QueryAsync(
200+
new EventQuery()
201+
{
202+
EventStatusReasonEnum = EventStatusReasonEnum.Ready,
203+
EventTypeEnums = new List<EventTypeEnum>()
204+
{
205+
EventTypeEnum.BCMPSecurityWorkerLicencePrinting,
206+
EventTypeEnum.BCMPArmouredVehiclePermitPrinting,
207+
EventTypeEnum.BCMPBodyArmourPermitPrinting,
208+
//EventTypeEnum.BCMPRetiredServiceDogPrinting,
209+
//EventTypeEnum.BCMPDogTrainerPrinting,
210+
//EventTypeEnum.BCMPGuideDogServiceDogTeamPrinting
211+
},
212+
CutOffDateTime = DateTimeOffset.UtcNow,
213+
}, ct);
214+
215+
List<CardPrintEvent> cardPrints = new List<CardPrintEvent>();
216+
foreach (var eventResp in eventResps)
217+
{
218+
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPSecurityWorkerLicencePrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
219+
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPSecurityWorkerLicencePrinting");
220+
221+
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPArmouredVehiclePermitPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
222+
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPArmouredVehiclePermitPrinting");
223+
224+
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPBodyArmourPermitPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
225+
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPBodyArmourPermitPrinting");
226+
227+
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPGuideDogServiceDogTeamPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
228+
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPGuideDogServiceDogTeamPrinting");
229+
230+
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPDogTrainerPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
231+
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPDogTrainerPrinting");
232+
233+
if (eventResp.EventTypeEnum == EventTypeEnum.BCMPRetiredServiceDogPrinting && (eventResp.RegardingObjectId == null || eventResp.RegardingObjectName != "spd_licence"))
234+
throw new ApiException(System.Net.HttpStatusCode.BadRequest, "LicenceId cannot be null if it is BCMPRetiredServiceDogPrinting");
235+
var licence = await _licenceRepository.GetBasicAsync((Guid)eventResp.RegardingObjectId, ct);
236+
var cardPrint = new CardPrintEvent
237+
{
238+
EventQueueId = eventResp.Id,
239+
PrintingPreviewJobId = licence?.PrintingPreviewJobId,
240+
IsSuccess = licence?.PrintingPreviewJobId == null ? false : null,
241+
ErrMsg = licence?.PrintingPreviewJobId == null ? "Cannot find the preview job id" : null
242+
};
243+
cardPrints.Add(cardPrint);
244+
}
245+
return new PersonalLicenceBatchPrintingTransformRequest(cardPrints);
246+
}
247+
248+
private async Task UpdateResultInEvents(ResultResponse resultResponse, List<CardPrintEvent> events, CancellationToken cancellationToken)
249+
{
250+
//update event queues
251+
List<EventUpdateCmd> cmds = new List<EventUpdateCmd>();
252+
foreach (var e in events)
253+
{
254+
var cmd = _mapper.Map<EventUpdateCmd>(resultResponse);
255+
if (e.IsSuccess == false) //those events has data issue, even though it is supposed to be in print batch, but as there is error, it does not go to print batch.
256+
{
257+
cmd.JobId = null;
258+
cmd.ErrorDescription = e.ErrMsg;
259+
cmd.StateCode = 1;
260+
cmd.EventStatusReasonEnum = EventStatusReasonEnum.Fail;
261+
}
262+
cmd.Id = e.EventQueueId;
263+
cmds.Add(cmd);
264+
}
265+
266+
await _eventRepo.ManageInBatchAsync(cmds, cancellationToken);
267+
return;
268+
}
269+
182270
private async Task UpdateResultInEvent(ResultResponse resultResponse, Guid eventId, CancellationToken cancellationToken)
183271
{
184272
//update event queue

src/Spd.Presentation.Dynamics/Controllers/PrintingController.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class PrintingController(IMediator mediator, IMapper mapper) : SpdControl
1515
/// a GET request that takes an event id. It should be like
1616
/// GET /api/printjobs/{eventid}
1717
/// where eventid is the GUID for spd_eventqueue record.
18-
/// Now, it will exe the event according to the eventype (now, only finger print), and update the event according to the response from bcMail plus.
18+
/// Now, it will exe the event according to the eventype (now, only finger print. sbl and msdr), and update the event according to the response from bcMail plus.
1919
/// </summary>
2020
/// <param name="eventId"></param>
2121
/// <param name="ct"></param>
@@ -26,6 +26,18 @@ public async Task<ResultResponse> GetPrintJob([FromRoute] Guid eventId, Cancella
2626
return await mediator.Send(new StartPrintJobCommand(eventId), ct);
2727
}
2828

29+
/// <summary>
30+
/// a GET request that will print all cards (swl, permit) in event queue
31+
/// Now, it will find all previous event queues which is for printing swl, permit and gdsd card printing, and create batch job, then update the events according to the response from bcMail plus.
32+
/// </summary>
33+
/// <param name="eventId"></param>
34+
/// <param name="ct"></param>
35+
/// <returns></returns>
36+
[HttpGet("api/print-cards-in-batch")]
37+
public async Task<ResultResponse> PrintCardsInBatch(CancellationToken ct)
38+
{
39+
return await mediator.Send(new PrintCardsInBatchCommand(), ct);
40+
}
2941
/// <summary>
3042
/// return the preview picture of licence.
3143
/// The bcmp job id will be returned in the http header as "bcmp-personal-licence-preview-jobid"

src/Spd.Resource.Repository/Event/Contract.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ public interface IEventRepository
66
{
77
public Task<EventResp> GetAsync(Guid eventId, CancellationToken cancellationToken);
88
public Task<Unit> ManageAsync(EventUpdateCmd cmd, CancellationToken ct);
9+
public Task<Unit> ManageInBatchAsync(List<EventUpdateCmd> cmd, CancellationToken ct);
10+
public Task<IEnumerable<EventResp>> QueryAsync(EventQuery qry, CancellationToken cancellationToken);
911
}
1012

1113
public record EventResp()
@@ -28,6 +30,13 @@ public record EventUpdateCmd()
2830
public EventStatusReasonEnum EventStatusReasonEnum { get; set; }
2931
}
3032

33+
public record EventQuery()
34+
{
35+
public IEnumerable<EventTypeEnum> EventTypeEnums { get; set; }
36+
public EventStatusReasonEnum EventStatusReasonEnum { get; set; }
37+
public DateTimeOffset? CutOffDateTime { get; set; }
38+
}
39+
3140
public enum EventTypeEnum
3241
{
3342
BCMPScreeningFingerprintPrinting,

src/Spd.Resource.Repository/Event/EventRepository.cs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
using AutoMapper;
22
using MediatR;
33
using Microsoft.Dynamics.CRM;
4+
using Microsoft.Extensions.Logging;
5+
using Microsoft.OData.Client;
46
using Spd.Utilities.Dynamics;
57

68
namespace Spd.Resource.Repository.Event;
79
internal class EventRepository : IEventRepository
810
{
911
private readonly DynamicsContext _context;
1012
private readonly IMapper _mapper;
13+
private readonly ILogger<IEventRepository> _logger;
14+
1115
public EventRepository(IDynamicsContextFactory ctx,
12-
IMapper mapper)
16+
IMapper mapper,
17+
ILogger<IEventRepository> logger)
1318
{
1419
_context = ctx.Create();
1520
_mapper = mapper;
21+
_logger = logger;
1622
}
1723

1824
public async Task<EventResp?> GetAsync(Guid eventId, CancellationToken ct)
@@ -21,6 +27,28 @@ public EventRepository(IDynamicsContextFactory ctx,
2127
return _mapper.Map<EventResp>(eventQueue);
2228
}
2329

30+
public async Task<IEnumerable<EventResp>?> QueryAsync(EventQuery qry, CancellationToken ct)
31+
{
32+
IQueryable<spd_eventqueue> eventQueues = _context.spd_eventqueues;
33+
if (qry.EventStatusReasonEnum != null)
34+
{
35+
int status = (int)SharedMappingFuncs.GetOptionset<EventStatusReasonEnum, EventStatusReasonOptionSet>(qry.EventStatusReasonEnum);
36+
eventQueues = eventQueues.Where(i => i.statuscode == status);
37+
}
38+
39+
if (qry.CutOffDateTime != null)
40+
eventQueues = eventQueues.Where(e => e.spd_eventdate < qry.CutOffDateTime);
41+
42+
var eventQueuesList = eventQueues.ToList();
43+
if (qry.EventTypeEnums != null && qry.EventTypeEnums.Any())
44+
{
45+
int[] types = qry.EventTypeEnums.Select(e => (int)SharedMappingFuncs.GetOptionset<EventTypeEnum, EventTypeOptionSet>(e)).ToArray();
46+
eventQueuesList = eventQueuesList.Where(e => types.Any(t => t == e.spd_eventtype)).ToList();
47+
}
48+
49+
return _mapper.Map<IEnumerable<EventResp>>(eventQueuesList);
50+
}
51+
2452
public async Task<Unit> ManageAsync(EventUpdateCmd cmd, CancellationToken ct)
2553
{
2654
spd_eventqueue? eventQueue = await _context.GetEventById(cmd.Id, ct);
@@ -29,4 +57,24 @@ public async Task<Unit> ManageAsync(EventUpdateCmd cmd, CancellationToken ct)
2957
await _context.SaveChangesAsync(ct);
3058
return default;
3159
}
60+
public async Task<Unit> ManageInBatchAsync(List<EventUpdateCmd> cmds, CancellationToken ct)
61+
{
62+
try
63+
{
64+
foreach (var cmd in cmds)
65+
{
66+
spd_eventqueue? eventQueue = await _context.spd_eventqueues
67+
.Where(l => l.spd_eventqueueid == cmd.Id)
68+
.FirstOrDefaultAsync(ct);
69+
_mapper.Map<EventUpdateCmd, spd_eventqueue>(cmd, eventQueue);
70+
_context.UpdateObject(eventQueue);
71+
}
72+
await _context.SaveChangesAsync(SaveChangesOptions.BatchWithSingleChangeset, ct);
73+
}
74+
catch (Exception e)
75+
{
76+
_logger.LogError(e.ToString());
77+
}
78+
return default;
79+
}
3280
}

0 commit comments

Comments
 (0)