Skip to content

Commit a5fac98

Browse files
authored
Merge pull request #191 from qccoders/scanning-backend
Implement scanning backend
2 parents 632ec7d + add4924 commit a5fac98

File tree

2 files changed

+96
-23
lines changed

2 files changed

+96
-23
lines changed

api/QCVOC.Api/Scans/Controller/ScansController.cs

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace QCVOC.Api.Scans.Controller
1616
using QCVOC.Api.Events.Data.Model;
1717
using QCVOC.Api.Scans.Data.DTO;
1818
using QCVOC.Api.Scans.Data.Model;
19+
using QCVOC.Api.Services.Data.Model;
1920
using QCVOC.Api.Veterans;
2021
using QCVOC.Api.Veterans.Data.Model;
2122

@@ -34,16 +35,19 @@ public class ScansController : Controller
3435
/// <param name="scanRepository">The repository used for Scan data access.</param>
3536
/// <param name="eventRepository">The repository used for Event data access.</param>
3637
/// <param name="veteranRepository">The repository used for Veteran data access.</param>
37-
public ScansController(ITripleKeyRepository<Scan> scanRepository, ISingleKeyRepository<Event> eventRepository, ISingleKeyRepository<Veteran> veteranRepository)
38+
/// <param name="serviceRepository">The repository used for Service data access.</param>
39+
public ScansController(ITripleKeyRepository<Scan> scanRepository, ISingleKeyRepository<Event> eventRepository, ISingleKeyRepository<Veteran> veteranRepository, ISingleKeyRepository<Service> serviceRepository)
3840
{
3941
ScanRepository = scanRepository;
4042
EventRepository = eventRepository;
4143
VeteranRepository = veteranRepository;
44+
ServiceRepository = serviceRepository;
4245
}
4346

4447
private ITripleKeyRepository<Scan> ScanRepository { get; set; }
4548
private ISingleKeyRepository<Event> EventRepository { get; }
4649
private ISingleKeyRepository<Veteran> VeteranRepository { get; set; }
50+
private ISingleKeyRepository<Service> ServiceRepository { get; set; }
4751

4852
/// <summary>
4953
/// Returns a list of Scans.
@@ -68,12 +72,12 @@ public IActionResult GetAll([FromQuery]ScanFilters filters)
6872
/// </summary>
6973
/// <param name="scan">The scan context.</param>
7074
/// <returns>See attributes.</returns>
71-
/// <response code="200">The Veteran is already checked in.</response>
72-
/// <response code="201">The Veteran was checked in.</response>
75+
/// <response code="200">The Scan has already been recorded.</response>
76+
/// <response code="201">The Scan was recorded or updated.</response>
7377
/// <response code="400">The specified Scan was invalid.</response>
7478
/// <response code="401">Unauthorized.</response>
7579
/// <response code="403">The Veteran has not checked in for the Event.</response>
76-
/// <response code="404">Either the specified Veteran or Event was invalid.</response>
80+
/// <response code="404">The specified Veteran, Event or Service was invalid.</response>
7781
/// <response code="500">The server encountered an error while processing the request.</response>
7882
[HttpPost("")]
7983
[Authorize]
@@ -95,7 +99,7 @@ public IActionResult Scan([FromBody]ScanRequest scan)
9599

96100
if (@event == default(Event))
97101
{
98-
StatusCode(403, "The specified Event is not found.");
102+
StatusCode(404, "The specified Event could not be found.");
99103
}
100104

101105
var veteran = VeteranRepository
@@ -104,12 +108,47 @@ public IActionResult Scan([FromBody]ScanRequest scan)
104108

105109
if (veteran == default(Veteran))
106110
{
107-
return StatusCode(403, "The specified Card Id doesn't match an enrolled Veteran.");
111+
return StatusCode(404, "The specified Card Id doesn't match an enrolled Veteran.");
108112
}
109113

114+
var scanRecord = new Scan()
115+
{
116+
EventId = (Guid)scan.EventId,
117+
VeteranId = veteran.Id,
118+
ServiceId = scan.ServiceId,
119+
PlusOne = scan.PlusOne,
120+
ScanById = User.GetId(),
121+
ScanDate = DateTime.UtcNow,
122+
};
123+
110124
var previousScans = ScanRepository.GetAll(new ScanFilters() { EventId = scan.EventId, VeteranId = veteran.Id });
111125

112-
if (scan.ServiceId == Guid.Empty && !previousScans.Where(s => s.ServiceId == Guid.Empty).Any())
126+
if (scan.ServiceId == Guid.Empty)
127+
{
128+
var existingCheckIn = previousScans.Where(s => s.ServiceId == Guid.Empty).SingleOrDefault();
129+
130+
if (existingCheckIn == default(Scan))
131+
{
132+
return CreateScan(scanRecord);
133+
}
134+
else if (existingCheckIn.PlusOne != scan.PlusOne)
135+
{
136+
return UpdateScan(scanRecord);
137+
}
138+
else
139+
{
140+
return StatusCode(200, existingCheckIn);
141+
}
142+
}
143+
144+
var service = ServiceRepository.Get(scan.ServiceId);
145+
146+
if (service == default(Service))
147+
{
148+
return StatusCode(404, "The specified Service could not be found.");
149+
}
150+
151+
if (!previousScans.Where(s => s.ServiceId == Guid.Empty).Any())
113152
{
114153
return StatusCode(403, "The Veteran has not checked in for this Event.");
115154
}
@@ -119,25 +158,33 @@ public IActionResult Scan([FromBody]ScanRequest scan)
119158
return StatusCode(200, previousScans.Where(s => s.ServiceId == scan.ServiceId).SingleOrDefault());
120159
}
121160

122-
var scanRecord = new Scan()
123-
{
124-
EventId = (Guid)scan.EventId,
125-
VeteranId = veteran.Id,
126-
ServiceId = scan.ServiceId,
127-
PlusOne = scan.PlusOne,
128-
ScanById = User.GetId(),
129-
ScanDate = DateTime.UtcNow,
130-
};
161+
return CreateScan(scanRecord);
162+
}
131163

164+
private IActionResult CreateScan(Scan scan)
165+
{
132166
try
133167
{
134-
var createdScan = ScanRepository.Create(scanRecord);
168+
var createdScan = ScanRepository.Create(scan);
135169
return StatusCode(201, createdScan);
136170
}
137171
catch (Exception ex)
138172
{
139173
throw new Exception($"Error processing Scan: {ex.Message}. See inner Exception for details.", ex);
140174
}
141175
}
176+
177+
private IActionResult UpdateScan(Scan scan)
178+
{
179+
try
180+
{
181+
var updatedScan = ScanRepository.Update(scan);
182+
return StatusCode(201, updatedScan);
183+
}
184+
catch (Exception ex)
185+
{
186+
throw new Exception($"Error processing Scan: {ex.Message}. See inner Exception for details.", ex);
187+
}
188+
}
142189
}
143190
}

api/QCVOC.Api/Scans/Data/Repository/ScanRepository.cs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,41 @@ LIMIT @limit OFFSET @offset
170170
}
171171

172172
/// <summary>
173-
/// Not implemented; Scan records are immutable.
173+
/// Updates the specified <paramref name="scan"/>.
174174
/// </summary>
175-
/// <param name="scan">N/A</param>
176-
/// <returns>Nothing</returns>
177-
/// <exception cref="NotImplementedException">Thrown on invocation.</exception>
178-
[Obsolete("Scan records may not be updated.", true)]
175+
/// <param name="scan">the Scan to update.</param>
176+
/// <returns>The updated Scan.</returns>
179177
public Scan Update(Scan scan)
180178
{
181-
throw new NotImplementedException("Scan records may not be updated.");
179+
var builder = new SqlBuilder();
180+
181+
var query = builder.AddTemplate(@"
182+
UPDATE scans
183+
SET
184+
plusone = @plusone,
185+
scandate = @scandate,
186+
scanbyid = @scanbyid
187+
WHERE eventid = @eventid
188+
AND veteranid = @veteranid
189+
AND serviceid = @serviceid
190+
");
191+
192+
builder.AddParameters(new
193+
{
194+
plusone = scan.PlusOne,
195+
scandate = scan.ScanDate,
196+
scanbyid = scan.ScanById,
197+
eventid = scan.EventId,
198+
veteranid = scan.VeteranId,
199+
serviceid = scan.ServiceId,
200+
});
201+
202+
using (var db = ConnectionFactory.CreateConnection())
203+
{
204+
db.Execute(query.RawSql, query.Parameters);
205+
}
206+
207+
return Get(scan.EventId, scan.VeteranId, scan.ServiceId);
182208
}
183209
}
184210
}

0 commit comments

Comments
 (0)