Compare commits

..
41 Commits
Author SHA1 Message Date
Kham 23edfc8b0c merge config 2026-09-20 18:08:02 +10:00
Kham 7d632d46c8 check all change left with format make it look nice 2026-09-18 15:42:23 +10:00
Kham 3807524412 change over primeng v22 2026-09-18 15:19:16 +10:00
Kham f74125a92c update v10 2026-09-17 16:23:11 +10:00
Kham 12504e61f4 in all in one 2026-04-22 08:48:04 +10:00
Kham a994d72640 put in ignore first 2026-04-22 08:47:14 +10:00
Kham fe6bf7f412 sort latest first 2025-11-11 09:09:40 +11:00
Kham e4f9104eea remove this Microsoft.IdentityModel.Tokens then the jwt is worked 2025-11-11 08:23:12 +11:00
Kham 6344546157 allow to get report. security problem on controller 2025-11-10 13:28:42 +11:00
Kham f693e70d10 remove hard code swagger version 2025-11-10 12:12:01 +11:00
Kham e318260acd upgrade to v8 remove automap too. 2025-11-10 11:32:00 +11:00
Kham d6bf268167 PUT IN NEW FILE 2024-06-26 14:00:21 +10:00
Kham 028f6bcf16 modified default for user 2024-06-06 10:13:49 +10:00
Kham 78936cf602 add user report and angular too. 2022-12-05 09:52:11 +11:00
Kham 67f87e2f21 check in column size 2022-12-02 16:04:07 +11:00
Kham 93fa738d72 update to .NET 6.0 2022-12-02 15:53:33 +11:00
Kham b32d02b001 add check id > 0 before assign 2022-02-11 08:24:42 +11:00
Kham 9e2c976c0d check update check string before trim 2022-02-08 08:04:20 +11:00
Kham b72107d14b make it compile 2022-02-03 08:20:23 +11:00
Kham 3ad64671ec Merge branch 'master' of L:\ICT\DISTBIDS\Git_Source_Code\CarParkValidation\CarParkValidationAPI 2021-12-10 11:30:41 +11:00
Kham 52d2af93e2 put in the file auto mapping and change file.
change spelling too.
2021-12-10 11:30:30 +11:00
Kham 07ed7a5f60 merge in 2021-11-24 09:29:39 +11:00
Kham 4e3cc0750c commit change all folder 2021-11-24 09:28:37 +11:00
Kham 87c89897c2 add new login post one. 2021-11-16 14:09:49 +11:00
Kham 9dab5536c2 commit all change 2021-11-05 13:49:24 +11:00
Kham f409ff1afb add in the check user already exist. 2021-11-05 09:29:10 +11:00
Kham 1131159112 put in the compile 2021-09-24 17:07:56 +10:00
Kham 7a0c53facc Release with this version 1.0.0 2021-09-17 08:31:29 +10:00
Kham cd38e7a644 add new RoleType and validationPoint to AdminUser 2021-09-06 16:43:20 +10:00
Kham 28f627a36e commit change first 2021-09-06 10:27:55 +10:00
Kham 7a28a0fc3b add trim and can report name 2021-09-03 15:52:49 +10:00
Kham da0b1337eb check in the file for delete and trim string. 2021-09-02 13:41:57 +10:00
Kham 39a7931a97 add modified the check logic if insert > 0 else > 1. 2021-09-01 20:55:31 +10:00
Kham 85abcfa068 add order by date for report 2021-09-01 16:21:56 +10:00
Kham cc276d4a17 add lastmodified and lastmodifiedid to table also add code for modified and create 2021-09-01 16:03:05 +10:00
Kham c5ab17115d Add in the middle ware and Fallbackcontroller. 2021-08-30 17:02:26 +10:00
Kham 8bdf6dabdc add frozen for excel format 2021-08-25 16:09:04 +10:00
Kham 1155deaf1a check in all the work is good to go now. 2021-08-25 15:42:06 +10:00
Kham 4792acea76 add for allow header for dowload file on client Content-Disposition 2021-08-23 17:08:27 +10:00
Kham d90e73dfcc Add project files. 2021-08-23 08:18:46 +10:00
Kham 9ab1447381 Add .gitignore and .gitattributes. 2021-08-23 08:18:44 +10:00
316 changed files with 43514 additions and 2 deletions
+52 -2
View File
@@ -1,3 +1,54 @@
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
# Compiled output
#**/dist
dist/
**/tmp
**/out-tsc
**/bazel-out
#Visual studio 2022
**/bin
**/obj
**/.vs
# Node
node_modules/
npm-debug.log
yarn-error.log
# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# Miscellaneous
**/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
# System files
.DS_Store
Thumbs.db
/API/Properties/PublishProfiles
/API/.config
/API/CarParkValidationAPI.csproj.user
=======
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
## ##
@@ -359,5 +410,4 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder # Ionide (cross platform F# VS Code tools) working folder
.ionide/ .ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
+1
View File
@@ -0,0 +1 @@
{}
+63
View File
@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
@@ -0,0 +1,8 @@
using System;
namespace CarParkValidationAPI.Authorization
{
[AttributeUsage(AttributeTargets.Method)]
public class AllowAnonymousAttribute : Attribute
{ }
}
+38
View File
@@ -0,0 +1,38 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Models;
namespace CarParkValidationAPI.Authorization
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
{
private readonly IList<AdminRole> _roles;
public AuthorizeAttribute(params AdminRole[] roles)
{
_roles = roles ?? new AdminRole[] { };
}
public void OnAuthorization(AuthorizationFilterContext context)
{
// skip authorization if action is decorated with [AllowAnonymous] attribute
var allowAnonymous = context.ActionDescriptor.EndpointMetadata.OfType<AllowAnonymousAttribute>().Any();
if (allowAnonymous)
return;
// authorization
var user = (User)context.HttpContext.Items["User"];
if (user == null || (_roles.Any() && !_roles.Contains(user.Role)))
{
// not logged in or role not authorized
context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
}
}
}
}
+36
View File
@@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System.Linq;
using System.Threading.Tasks;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Repository;
using CarParkValidationAPI.Interface;
namespace CarParkValidationAPI.Authorization
{
public class JwtMiddleware
{
private readonly RequestDelegate _next;
private readonly AppSettings _appSettings;
public JwtMiddleware(RequestDelegate next, IOptions<AppSettings> appSettings)
{
_next = next;
_appSettings = appSettings.Value;
}
public async Task Invoke(HttpContext context, IUserService userService, IJwtUtils jwtUtils)
{
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
var user = jwtUtils.ValidateJwtToken(token);
if (user != null)
{
// attach user to context on successful jwt validation
//here to put in the real user
//TODO if you want to add information for User
context.Items["User"] = user;
}
await _next(context);
}
}
}
+105
View File
@@ -0,0 +1,105 @@
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Interface;
using CarParkValidationAPI.Models;
namespace CarParkValidationAPI.Authorization;
public class JwtUtils : IJwtUtils
{
private readonly AppSettings _appSettings;
public JwtUtils(IOptions<AppSettings> appSettings)
{
_appSettings = appSettings.Value;
}
public string GenerateJwtToken(User user)
{
// generate token that is valid for 2 days
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] {
new Claim("id", user.Id.ToString()),
new Claim("subject", user.Username)
//add more if we need it
}
),
Expires = DateTime.UtcNow.AddDays(2),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
// get back id and username. in subject
public User? ValidateJwtToken(string token)
{
if (token == null)
return null;
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
try
{
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateLifetime = true,
ValidateAudience = false,
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
// ClockSkew = TimeSpan.Zero
ClockSkew = TimeSpan.FromDays(2),
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
// var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value); //old
int userId = 0;
string username = "";
Claim claim;
for (int i = 0; i < jwtToken.Claims.Count(); i++)
{
claim = jwtToken.Claims.ElementAt(i);
if (claim.Type == "id")
{
userId = int.Parse(claim.Value);
}
else if (claim.Type == "subject")
{
username = claim.Value;
}
if (!string.IsNullOrEmpty(username) && userId > 0)
{
break;
}
}
User user = new User();
user.Id = userId;
user.Username = username;
// return user id from JWT token if validation successful
return user;
}
catch (Exception ex)
{
{
Console.WriteLine(ex.ToString());
// return null if validation fails
return null;
}
}
}
}
+27
View File
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<UserSecretsId>punt</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="2.20.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.12" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\CommonAD6\CommonAD.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="SpreadsheetLight">
<HintPath>..\..\commonDLL\SpreadsheetLight.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
+31
View File
@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 18
VisualStudioVersion = 18.10.12210.168 stable
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CarParkValidationAPI", "CarParkValidationAPI.csproj", "{74980A36-AF9D-44B4-991D-994E033AD54A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonAD", "..\..\CommonAD6\CommonAD.csproj", "{48F9F9E4-C310-5B1A-D153-BD8BD910F815}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{74980A36-AF9D-44B4-991D-994E033AD54A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{74980A36-AF9D-44B4-991D-994E033AD54A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74980A36-AF9D-44B4-991D-994E033AD54A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74980A36-AF9D-44B4-991D-994E033AD54A}.Release|Any CPU.Build.0 = Release|Any CPU
{48F9F9E4-C310-5B1A-D153-BD8BD910F815}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48F9F9E4-C310-5B1A-D153-BD8BD910F815}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48F9F9E4-C310-5B1A-D153-BD8BD910F815}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48F9F9E4-C310-5B1A-D153-BD8BD910F815}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FB2BDB7C-3C90-4CBB-BD6B-CFD125C87D0F}
EndGlobalSection
EndGlobal
+62
View File
@@ -0,0 +1,62 @@
using Microsoft.AspNetCore.Mvc;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Interface;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Controllers
{
// [Authorize]
[ApiController]
[Route("api/v1/[controller]")]
public class AdminUserController : ControllerBase
{
private IAdminUser _adminUser;
public AdminUserController(IAdminUser adminUser)
{
_adminUser = adminUser;
}
[HttpPost]
public async Task<IActionResult> AdminUser([FromBody] AdminUserDto model)
{
var currentUser = (User)HttpContext.Items["User"];
if (null == currentUser)
return Unauthorized(new { message = "Unauthorized" });
_adminUser.SetCurrentUser(currentUser.Username);
var response = await _adminUser.SaveAdminUserAsync(model);
return Ok(response);
}
[HttpGet]
public async Task<IActionResult> AdminUser(bool onlyActive=true)
{
var retval = await _adminUser.LoadAdminUserAsync(onlyActive);
return Ok(retval);
}
[HttpGet("{id:int}")]
public async Task<IActionResult> AdminUser(int id)
{
/*
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (id != currentUser.Id && currentUser.Role != Role.Admin)
return Unauthorized(new { message = "Unauthorized" });
*/
var retval = await _adminUser.LoadAdminUserByIdAsync(id);
return Ok(retval);
}
[HttpDelete("{id:int}")]
public async Task<IActionResult> DeleteAdminUser(int id)
{
var currentUser = (User)HttpContext.Items["User"];
if (null == currentUser)
return Unauthorized(new { message = "Unauthorized" });
_adminUser.SetCurrentUser(currentUser.Username);
var retval = await _adminUser.DeleteAdminUserAsync(id);
return Ok(retval);
}
}
}
@@ -0,0 +1,66 @@
using Microsoft.AspNetCore.Mvc;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Interface;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Controllers
{
//[Authorize]
[ApiController]
[Route("api/v1/[controller]")]
public class ConcessionTypeController : ControllerBase
{
private IConcessionType _concessionType;
public ConcessionTypeController(IConcessionType concessionType)
{
_concessionType = concessionType;
}
[HttpPost]
public async Task<IActionResult> ConcessionType([FromBody] ConcessionTypeDto model)
{
var currentUser = (User)HttpContext.Items["User"];
if (null == currentUser)
return Unauthorized(new { message = "Unauthorized" });
_concessionType.SetCurrentUser(currentUser.Username);
var response = await _concessionType.SaveConcessionTypeAsync(model);
return Ok(response);
}
[HttpGet]
public async Task<IActionResult> ConcessionType(bool onlyActive =true)
{
var retval = await _concessionType.LoadConcessionTypeAsync(onlyActive);
return Ok(retval);
}
[HttpGet("{id:int}")]
public async Task<IActionResult> ConcessionType(int id)
{
/*
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (id != currentUser.Id && currentUser.Role != Role.Admin)
return Unauthorized(new { message = "Unauthorized" });
*/
var retval = await _concessionType.LoadConcessionTypeByIdAsync(id);
return Ok(retval);
}
[HttpDelete("{id:int}")]
public async Task<IActionResult> DeleteConcessionType(int id)
{
/*
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (id != currentUser.Id && currentUser.Role != Role.Admin)
return Unauthorized(new { message = "Unauthorized" });
*/
var retval = await _concessionType.DeleteConcessionTypeAsync(id);
return Ok(retval);
}
}
}
@@ -0,0 +1,119 @@
using Microsoft.AspNetCore.Mvc;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Interface;
using System.Threading.Tasks;
using System;
using Microsoft.AspNetCore.StaticFiles;
using CarParkValidationAPI.Repository;
namespace CarParkValidationAPI.Controllers
{
[ApiController]
[Route("api/v1/[controller]")]
public class ConcessionValidationController : ControllerBase
{
private ConcessionValidationReportRepository _concessionValidationReport;
private IConcessionValidation _concessionValidation;
private readonly FileExtensionContentTypeProvider _contentTypeProvider;
public ConcessionValidationController(IConcessionValidation concessionValidation,
ConcessionValidationReportRepository concesionReportReport)
{
_concessionValidationReport = concesionReportReport;
_concessionValidation = concessionValidation;
}
[HttpPost]
public async Task<IActionResult> ConcessionValidation([FromBody] ConcessionValidationDto model)
{
var currentUser = (User)HttpContext.Items["User"];
if (null == currentUser)
return Unauthorized(new { message = "Unauthorized" });
_concessionValidation.SetCurrentUser(currentUser.Username);
var response = await _concessionValidation.SaveConcessionValidationAsync(model);
return Ok(response);
}
[HttpGet]
public async Task<IActionResult> ConcessionValidation(bool onlyActive=true)
{
var retval = await _concessionValidation.LoadConcessionValidationAsync(onlyActive);
return Ok(retval);
}
[HttpGet("[action]")]
public async Task<IActionResult> ConcessionValidationByStaff(string staffLinkNo, DateTime fromDate, DateTime toDate)
{
var retval = await _concessionValidation.LoadConcessionValidationStaffLinkNoAsync(staffLinkNo, fromDate, toDate);
return Ok(retval);
}
[HttpGet("[action]")]
public async Task<IActionResult> CheckConcessionValidationByStaff(string staffLinkNo, string concessionCard, DateTime currentDate, int id)
{
var retval = await _concessionValidation.CheckConcessionValidationStaffLinkNoAsync(staffLinkNo, concessionCard, currentDate, id);
return Ok(retval);
}
[HttpGet("{id:int}")]
public async Task<IActionResult> ConcessionValidation(int id)
{
/*
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (id != currentUser.Id && currentUser.Role != Role.Admin)
return Unauthorized(new { message = "Unauthorized" });
*/
var retval = await _concessionValidation.LoadConcessionValidationByIdAsync(id);
return Ok(retval);
}
[HttpPost("[action]")]
public async Task<IActionResult> GetConcessionCard(CardNoCriteria criteria)
{
/*
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (id != currentUser.Id && currentUser.Role != Role.Admin)
return Unauthorized(new { message = "Unauthorized" });
*/
var retval = await _concessionValidation.LoadConcessionValidationByCardNumberAsync(criteria.CardNo);
return Ok(retval);
}
[HttpDelete("{id:int}")]
public async Task<IActionResult> DeleteConcessionValidation(int id)
{
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (null == currentUser)
return Unauthorized(new { message = "Unauthorized" });
_concessionValidation.SetCurrentUser(currentUser.Username);
var retval = await _concessionValidation.DeleteConcessionValidationAsync(id);
return Ok(retval);
}
/* download the excel file */
[HttpGet("[action]")]
public async Task<IActionResult> GetReportFile(DateTime fromDate , DateTime toDate)
{
// this.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
var result = await _concessionValidationReport.GetConcessionValidationReport(fromDate, toDate); // _concessionValidation.GetReport(fromDate, toDate);
string fileContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; //Map(result.Data.FileName);
return File(result.Data.Content, fileContentType, result.Data.FileName);
}
[NonAction]
private string Map(string fileName)
{
if (!_contentTypeProvider.TryGetContentType(fileName, out string contentType))
{
contentType = "application/octet-stream";
}
return contentType;
}
}
}
+18
View File
@@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Controllers
{
public class FallbackController : Controller
{
public IActionResult Index()
{
return PhysicalFile(Path.Combine(Directory.GetCurrentDirectory(),
"wwwroot", "index.html"), "text/HTML");
}
}
}
+37
View File
@@ -0,0 +1,37 @@
using Microsoft.AspNetCore.Mvc;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Interface;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Controllers
{
// [Authorize]
[ApiController]
[Route("api/v1/[controller]")]
public class LookupCodeController : ControllerBase
{
private readonly ILookupCode _lookupCodeService;
public LookupCodeController(ILookupCode lookupCode)
{
_lookupCodeService = lookupCode;
}
[HttpGet("[action]")]
public async Task<IActionResult> ConcessionTypes(bool onlyActive=true)
{
var retval = await _lookupCodeService.LoadConcessionTypeAsync(onlyActive);
return Ok(retval);
}
[HttpGet("[action]")]
public async Task<IActionResult> ValidationPoints(bool onlyActive= true)
{
var retval = await _lookupCodeService.LoadValidationPointAsync(onlyActive);
return Ok(retval);
}
}
}
+93
View File
@@ -0,0 +1,93 @@
using Microsoft.AspNetCore.Mvc;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Models.Users;
using CarParkValidationAPI.Interface;
using System.Threading.Tasks;
using CarParkValidationAPI.Models;
using System;
namespace CarParkValidationAPI.Controllers
{
//[Authorize]
[ApiController]
[Route("api/v1/[controller]")]
public class UsersController : ControllerBase
{
private IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
[AllowAnonymous]
[HttpPost("[action]")]
public IActionResult Authenticate(AuthenticateRequest model)
{
var response = _userService.Authenticate(model);
return Ok(response);
}
[AllowAnonymous]
[HttpPost("[action]")]
public async Task<IActionResult> LoginAD([FromBody] AuthenticateRequest model)
{
var response = await _userService.LoginAD(model);
return Ok(response);
}
[AllowAnonymous]
[HttpPost("[action]")]
public async Task<IActionResult> LoginApiAD([FromBody] AuthenticateRequest model)
{
var response = await _userService.LoginApiAD(model);
return Ok(response);
}
[AllowAnonymous]
[HttpGet("[action]")]
public async Task<IActionResult> SearchApiStaff(string stafflinkNo)
{
var user = await _userService.SearchApiStaff(stafflinkNo);
return Ok(user);
}
[AllowAnonymous]
[HttpGet("[action]")]
public async Task<ResultModel<User>> SearchADStaff(string stafflinkNo)
{
var user = await _userService.SearchADStaff(stafflinkNo);
return user;
}
// [Authorize(AdminRole.Admin)]
[HttpGet]
public async Task<IActionResult> GetAllUsers()
{
var users = await _userService.GetAllUsers();
return Ok(users);
}
[AllowAnonymous]
[HttpGet("{id:int}")]
public async Task<IActionResult> GetById(int id)
{
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (id != currentUser.Id && currentUser.Role != AdminRole.Admin)
return Unauthorized(new { message = "Unauthorized" });
var user = await _userService.GetById(id);
return Ok(user);
}
/* download the excel file */
[AllowAnonymous]
[HttpGet("[action]")]
public async Task<IActionResult> GetReportFile()
{
// this.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
var result = await _userService.GetAllUserReport(); // .GetReport(fromDate, toDate);
string fileContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; //Map(result.Data.FileName);
return File(result.Data.Content, fileContentType, result.Data.FileName);
}
}
}
@@ -0,0 +1,65 @@
using Microsoft.AspNetCore.Mvc;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Interface;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Controllers
{
/* [Authorize] */
[ApiController]
[Route("api/v1/[controller]")]
public class ValidationPointController : ControllerBase
{
private IValidationPoint _validationPoint;
public ValidationPointController(IValidationPoint validationPoint)
{
_validationPoint = validationPoint;
}
[HttpPost]
public async Task<IActionResult> ValidationPoint([FromBody] ValidationPointDto model)
{
var currentUser = (User)HttpContext.Items["User"];
if (null == currentUser)
return Unauthorized(new { message = "Unauthorized" });
_validationPoint.SetCurrentUser(currentUser.Username);
var response = await _validationPoint.SaveValidationPointAsync(model);
return Ok(response);
}
[HttpGet]
public async Task<IActionResult> ValidationPoint(bool onlyActive=true)
{
var retval = await _validationPoint.LoadValidationPointAsync(onlyActive);
return Ok(retval);
}
[HttpGet("{id:int}")]
public async Task<IActionResult> ValidationPoint(int id)
{
/*
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (id != currentUser.Id && currentUser.Role != Role.Admin)
return Unauthorized(new { message = "Unauthorized" });
*/
var retval = await _validationPoint.LoadValidationPointByIdAsync(id);
return Ok(retval);
}
[HttpDelete("{id:int}")]
public async Task<IActionResult> DeleteConcessionType(int id)
{
// only admins can access other user records
var currentUser = (User)HttpContext.Items["User"];
if (null == currentUser)
return Unauthorized(new { message = "Unauthorized" });
_validationPoint.SetCurrentUser(currentUser.Username);
var retval = await _validationPoint.DeleteValidationPointAsync(id);
return Ok(retval);
}
}
}
+230
View File
@@ -0,0 +1,230 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Models;
using Microsoft.Extensions.Options;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Data;
using System.Data.Common;
namespace CarParkValidationAPI.Datas
{
public class DataContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<AdminUser> AdminUsers { get; set; }
public DbSet<ValidationPoint> Validations { get; set; }
public DbSet<ConcessionValidation> ConcessionValidations { get; set; }
public DbSet<ConcessionType> ConcessionTypes { get; set; }
private readonly IConfiguration Configuration;
private IOptions<AppSettings> _appSettings;
public DataContext(IConfiguration configuration, IOptions<AppSettings> appSettings)
{
Configuration = configuration;
_appSettings = appSettings;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ValidationPoint>().ToTable("ValidationPoint");
modelBuilder.Entity<ConcessionValidation>().ToTable("ConcessionValidation");
modelBuilder.Entity<ConcessionType>().ToTable("ConcessionType");
modelBuilder.Entity<AdminUser>().ToTable("AdminUser");
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// in memory database used for simplicity, change to a real db for production applications
// options.UseInMemoryDatabase("TestDb");
options.UseSqlServer(_appSettings.Value.SQLConnectionString);
}
private ConcessionValidationExtDto PopulateItem(IDataReader reader)
{
ConcessionValidationExtDto item = new ConcessionValidationExtDto();
object myobj;
myobj = reader["ValidationID"];
if (myobj != System.DBNull.Value)
item.Id = (int) myobj;
myobj = reader["ValidateDate"];
if (myobj != System.DBNull.Value)
item.ValidateDate = (DateTime)myobj;
myobj = reader["ConcessionCard"];
if (myobj != System.DBNull.Value)
item.ConcessionCard = (string) myobj;
myobj = reader["ConcessionHolder"];
if (myobj != System.DBNull.Value)
item.ConcessionHolder = (string) myobj;
myobj = reader["ConcessionExpiry"];
if (myobj != System.DBNull.Value)
item.ConcessionExpiry = (bool) myobj;
/*
myobj = reader["ConcessionTypeID"];
if (myobj != System.DBNull.Value)
item.ConcessionTypeId = (int)myobj;
*/
myobj = reader["StafflinkNo"];
if (myobj != System.DBNull.Value)
item.StafflinkNo = (string) myobj;
myobj = reader["ConcessionType"];
if (myobj != System.DBNull.Value)
item.ConcessionType = (string) myobj;
myobj = reader["ValidationPoint"];
if (myobj != System.DBNull.Value)
item.ValidationPoint = (string) myobj;
myobj = reader["StaffFirstName"];
if (myobj != System.DBNull.Value)
item.StaffFirstName = (string) myobj;
myobj = reader["StaffLastName"];
if (myobj != System.DBNull.Value)
item.StaffLastName = (string) myobj;
myobj = reader["StaffEmail"];
if (myobj != System.DBNull.Value)
item.StaffEmail = (string) myobj;
/*
myobj = reader["ValidationPointID"];
if (myobj != System.DBNull.Value)
item.ValidationPointId = (int)myobj;
*/
myobj = reader["Active"];
if (myobj != System.DBNull.Value)
item.Active = (bool)myobj;
return item;
}
public async Task<List<ConcessionValidationExtDto>> SelectConcessionValidationByStaffId(bool activeOnly, string stafflinkNo, DateTime fromDate, DateTime toDate)
{
var pfromDate = new SqlParameter
{
ParameterName = "fromDate",
Value = fromDate.Date
};
var pStaffLink = new SqlParameter
{
ParameterName = "StafflinkNo",
Value = string.IsNullOrEmpty(stafflinkNo) ? "" : stafflinkNo,
};
var pToDate = new SqlParameter
{
ParameterName = "toDate",
Value = toDate.Date
};
ConcessionValidationExtDto item;
List<ConcessionValidationExtDto> result = new List<ConcessionValidationExtDto>();
using (var command = this.Database.GetDbConnection().CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = ("capv_ConValidation_Sel");
command.Parameters.Add(pfromDate);
command.Parameters.Add(pToDate);
command.Parameters.Add(pStaffLink);
this.Database.OpenConnection();
using (DbDataReader reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
item = PopulateItem(reader);
result.Add(item);
}
}
}
return result;
}
public async Task<List<int>> SelectCheckConcessionValidationAsync(DateTime fromDate, string concessionCard, string staffLinkNo)
{
var pfromDate = new SqlParameter
{
ParameterName = "FromDate",
Value = fromDate.Date,
};
var pStaffLink = new SqlParameter
{
ParameterName = "StaffLinkNo",
Value = staffLinkNo,
};
var pConcessionCard = new SqlParameter
{
ParameterName = "ConcessionCard",
Value = concessionCard,
};
ConcessionValidationExtDto item;
List<int> result = new List<int>();
object myobj;
int id;
using (var command = this.Database.GetDbConnection().CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = ("capv_CheckConValidation_Sel");
command.Parameters.Add(pfromDate);
command.Parameters.Add(pStaffLink);
command.Parameters.Add(pConcessionCard);
this.Database.OpenConnection();
using (DbDataReader reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
myobj = reader["ValidationID"];
if (myobj != System.DBNull.Value)
{
id = (int)myobj;
result.Add(id);
}
}
}
}
return result;
}
public async Task<List<ConcessionValidationExtDto>> SelectConcessionValidationByDate(bool activeOnly, DateTime fromDate, DateTime toDate)
{
var pfromDate = new SqlParameter
{
ParameterName = "fromDate",
Value = fromDate.Date
};
var pToDate = new SqlParameter
{
ParameterName = "toDate",
Value = toDate.Date
};
ConcessionValidationExtDto item;
List<ConcessionValidationExtDto> result = new List<ConcessionValidationExtDto>();
using (var command = this.Database.GetDbConnection().CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = ("capv_ConValidationDate_Sel");
command.Parameters.Add(pfromDate);
command.Parameters.Add(pToDate);
this.Database.OpenConnection();
using (DbDataReader reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
item = PopulateItem(reader);
result.Add(item);
}
}
}
result.Sort((x, y) => x.ValidateDate.Date.CompareTo(y.ValidateDate.Date));
return result;
}
}
}
+47
View File
@@ -0,0 +1,47 @@
using CarParkValidationAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Entities
{
public class AdminUserDto
{
#region public Member
public int Id { get; set; }
public string StafflinkNo { get; set; }
public string Name { get; set; }
public string AddedBy { get; set; }
public DateTime AddedOn { get; set; }
public bool Active { get; set; }
public AdminRole RoleType { get; set; }
public int ValidationPointId { get; set; }
#endregion
}
public class AdminUserViewDto
{
#region public Member
public int Id { get; set; }
public string StafflinkNo { get; set; }
public string Name { get; set; }
public string AddedBy { get; set; }
public DateTime AddedOn { get; set; }
public bool Active { get; set; }
public string RoleType { get; set; }
public string ValidationPoint { get; set; }
#endregion
}
}
+21
View File
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Entities
{
public class ApiException
{
public ApiException(int statusCode, string message = null, string details = null)
{
StatusCode = statusCode;
Message = message;
Details = details;
}
public int StatusCode { get; set; }
public string Message { get; set; }
public string Details { get; set; }
}
}
+20
View File
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Entities
{
public class ConcessionTypeDto
{
#region public Member
public int Id { get; set; }
public string Description { get; set; }
public string Display { get; set; }
public bool Active { get; set; }
#endregion
}
}
+45
View File
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Entities
{
public class CardNoCriteria
{
public string CardNo { get; set; }
}
public class ConcessionValidationExtDto: ConcessionValidationDto
{
public string ConcessionType { get; set; }
public string ValidationPoint { get; set; }
}
public partial class ConcessionValidationDto
{
#region public Member
public int Id { get; set; }
public DateTime ValidateDate { get; set; }
public string ConcessionCard { get; set; }
public string ConcessionHolder { get; set; }
public bool ConcessionExpiry { get; set; }
public int ConcessionTypeId { get; set; }
public string StafflinkNo { get; set; }
public int ValidationPointId { get; set; }
public bool Active { get; set; }
public string StaffFirstName { get; set; }
public string StaffLastName { get; set; }
public string StaffEmail { get; set; }
#endregion
}
}
+13
View File
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Entities
{
public class FileContent
{
public byte[] Content { get; set; }
public string FileName { get; set; }
}
}
+20
View File
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Entities
{
public class LookupCodeDto
{
public int Id
{
get; set;
}
public string Description
{
get; set;
}
}
}
+24
View File
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Entities
{
public class ValidationPointDto
{
#region public Member
public int Id { get; set; }
[Required]
public string Description { get; set; }
public string Display { get; set; }
public bool Active { get; set; }
#endregion
}
}
+73
View File
@@ -0,0 +1,73 @@
using CarParkValidationAPI.Entities;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Helpers
{
public class ErrorHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlerMiddleware> _logger;
private readonly IHostEnvironment _env;
public ErrorHandlerMiddleware(RequestDelegate next,
ILogger<ErrorHandlerMiddleware> logger, IHostEnvironment env)
{
_next = next;
_logger = logger;
_env = env;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
var response = context.Response;
response.ContentType = "application/json";
_logger.LogError(ex, ex.Message);
/*
switch (ex)
{
// case Exception e:
// // custom application error
// response.StatusCode = (int)HttpStatusCode.BadRequest;
// break;
case KeyNotFoundException:
// not found error
response.StatusCode = (int)HttpStatusCode.NotFound;
break;
default:
// unhandled error
response.StatusCode = (int)HttpStatusCode.InternalServerError;
break;
} */
response.StatusCode = ex switch
{
// case Exception e:
// // custom application error
// response.StatusCode = (int)HttpStatusCode.BadRequest;
// break;
KeyNotFoundException => (int)HttpStatusCode.NotFound,// not found error
_ => (int)HttpStatusCode.InternalServerError,// unhandled error
};
//response.StatusCode = (int)HttpStatusCode.InternalServerError;
var res = _env.IsDevelopment() ?
new ApiException(response.StatusCode, ex.Message, ex.StackTrace?.ToString())
: new ApiException(response.StatusCode, "Internal Server Error");
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var json = JsonSerializer.Serialize(res, options);
await response.WriteAsync(json);
}
}
}
}
+20
View File
@@ -0,0 +1,20 @@
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Interface
{
public interface IAdminUser
{
Task<ResultModel<List<AdminUserViewDto>>> LoadAdminUserAsync(bool OnlyActive);
Task<ResultModel<bool>> CheckAdminUserByStaffLinkNoAsync(string staffLinkNo);
Task<ResultModel<int>> SaveAdminUserAsync(AdminUserDto item);
Task<ResultModel<AdminUserDto>> LoadAdminUserByIdAsync(int id);
Task<ResultModel<bool>> DeleteAdminUserAsync(int id);
void SetCurrentUser(string username);
}
}
+20
View File
@@ -0,0 +1,20 @@
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Interface
{
public interface IConcessionType
{
Task<ResultModel<List<ConcessionTypeDto>>> LoadConcessionTypeAsync(bool OnlyActive);
Task<ResultModel<int>> SaveConcessionTypeAsync(ConcessionTypeDto item);
Task<ResultModel<ConcessionTypeDto>> LoadConcessionTypeByIdAsync(int id);
Task<ResultModel<bool>> DeleteConcessionTypeAsync(int id);
Task<ResultModel<Dictionary<int, LookupCodeDto>>> GetConcessionTypeDicAsync();
void SetCurrentUser(string username);
}
}
+24
View File
@@ -0,0 +1,24 @@
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CarParkValidationAPI.Repository;
namespace CarParkValidationAPI.Interface
{
public interface IConcessionValidation
{
Task<ResultModel<List<ConcessionValidationExtDto>>> LoadConcessionValidationAsync(bool OnlyActive);
Task<ResultModel<List<ConcessionValidationExtDto>>> LoadConcessionValidationStaffLinkNoAsync(string staffLinkNo, DateTime currentDate, DateTime toDate);
Task<ResultModel<int>> CheckConcessionValidationStaffLinkNoAsync(string staffLinkNo, string concessionCard, DateTime currentDate, int id);
Task<ResultModel<int>> SaveConcessionValidationAsync(ConcessionValidationDto item);
Task<ResultModel<ConcessionValidationDto>> LoadConcessionValidationByIdAsync(int id);
Task<ResultModel<ConcessionValidationDto>> LoadConcessionValidationByCardNumberAsync(string cardNo);
Task<ResultModel<bool>> DeleteConcessionValidationAsync(int id);
void SetCurrentUser(string username);
}
}
+16
View File
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CarParkValidationAPI.Interface;
using CarParkValidationAPI.Models;
namespace CarParkValidationAPI.Interface
{
public interface IJwtUtils
{
public string GenerateJwtToken(User user);
public User? ValidateJwtToken(string token);
}
}
+17
View File
@@ -0,0 +1,17 @@
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Interface
{
public interface ILookupCode
{
Task<ResultModel<List<LookupCodeDto>>> LoadConcessionTypeAsync(bool OnlyActive);
Task<ResultModel<List<LookupCodeDto>>> LoadValidationPointAsync(bool OnlyActive);
}
}
+22
View File
@@ -0,0 +1,22 @@
using CarParkValidationAPI.Models.Users;
using CarParkValidationAPI.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CarParkValidationAPI.Models;
namespace CarParkValidationAPI.Interface
{
public interface IUserService
{
AuthenticateResponse Authenticate(AuthenticateRequest model);
Task<ResultModel<AuthenticateResponse>> LoginApiAD(AuthenticateRequest model);
Task<ResultModel<AuthenticateResponse>> LoginAD(AuthenticateRequest model);
Task<ResultModel<List<User>>> GetAllUsers();
Task<ResultModel<User>> GetById(int id);
Task<ResultModel<User>> SearchApiStaff(string staffLinkNo);
Task<ResultModel<User>> SearchADStaff(string staffLinkNo);
Task<ResultModel<FileContent>> GetAllUserReport();
}
}
+20
View File
@@ -0,0 +1,20 @@
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Interface
{
public interface IValidationPoint
{
Task<ResultModel<List<ValidationPointDto>>> LoadValidationPointAsync(bool OnlyActive);
Task<ResultModel<int>> SaveValidationPointAsync(ValidationPointDto item);
Task<ResultModel<ValidationPointDto>> LoadValidationPointByIdAsync(int id);
Task<ResultModel<bool>> DeleteValidationPointAsync(int id);
Task<ResultModel<Dictionary<int, LookupCodeDto>>> GetValidationPointDicAsync();
void SetCurrentUser(string username);
}
}
Binary file not shown.
+65
View File
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
namespace CarParkValidationAPI.Models
{
public enum AdminRole
{
Normal = 1,
Admin = 2
}
public partial class AdminUserCriteria
{
public AdminUserCriteria()
{
}
#region public Member
public int? UserID { get; set; }
public int? StafflinkNo { get; set; }
public string Name { get; set; }
public string AddedBy { get; set; }
public DateTime? AddedOn { get; set; }
public bool? Active { get; set; }
public int? RoleType { get; set; }
#endregion
}
[Table("AdminUser")]
public partial class AdminUser
{
public AdminUser()
{
}
#region public Member
[Key]
public int UserID { get; set; }
public string StafflinkNo { get; set; }
public string Name { get; set; }
public string AddedBy { get; set; }
public DateTime AddedOn { get; set; }
public bool Active { get; set; }
public AdminRole RoleType { get; set; }
public int? ValidationPointID { get; set; }
public DateTime? LastModified { get; set; }
public string? LastModifiedId { get; set; }
#endregion
}
}
+28
View File
@@ -0,0 +1,28 @@
using System;
namespace CarParkValidationAPI.Models
{
public class AppSettings
{
public string Secret { get; set; }
public string SQLConnectionString { get; set; }
public string LDAPPath { get; set; }
public string LDAPUser { get; set; }
public string LDAPPassword { get; set; }
public string LoginWebAPI { get; set; }
/// <summary>
/// for convert to time. use GetADTimeOut
/// TimeSpan.FromSeconds(Convert.ToDouble(ConfigurationManager.AppSettings["ADTimeOut"]));
public string ADTimeOut { get; set; }
public TimeSpan GetADTimeOut()
{
if (!string.IsNullOrEmpty(ADTimeOut))
return TimeSpan.FromSeconds(Convert.ToDouble(ADTimeOut));
else
return TimeSpan.FromSeconds(0);
}
}
}
+28
View File
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.ComponentModel.DataAnnotations;
namespace CarParkValidationAPI.Models
{
public partial class ConcessionType
{
public ConcessionType()
{
}
#region public Member
[Key]
public int ConcessionTypeID { get; set; }
public string ConcessionDesc { get; set; }
public string ConcessionDisplay { get; set; }
public bool Active { get; set; }
public DateTime? LastModified { get; set; }
public string? LastModifiedId { get; set; }
#endregion
}
}
+55
View File
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace CarParkValidationAPI.Models
{
[NotMapped]
public class ConcessionValidationExt: ConcessionValidation
{
#region public Member
public string ConcessionType { get; set; }
public string ValidationPiont { get; set; }
#endregion
}
public partial class ConcessionValidation
{
public ConcessionValidation()
{
}
#region public Member
[Key]
public int ValidationID { get; set; }
public DateTime ValidateDate { get; set; }
public string ConcessionCard { get; set; }
public string ConcessionHolder { get; set; }
public bool ConcessionExpiry { get; set; }
public int ConcessionTypeID { get; set; }
public string StafflinkNo { get; set; }
public int ValidationPointID { get; set; }
public bool Active { get; set; }
public string StaffFirstName { get; set; }
public string StaffLastName { get; set; }
public string StaffEmail { get; set; }
public DateTime? CreatedDate { get; set; }
public string? CreatedId { get; set; }
public DateTime? LastModified { get; set; }
public string? LastModifiedId{ get; set; }
#endregion
}
}
+14
View File
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Models
{
public class ResultModel<T>
{
public T Data { get; set; }
public int StatusCode { get; set; }
public string Message { get; set; }
}
}
+18
View File
@@ -0,0 +1,18 @@
using System.Text.Json.Serialization;
namespace CarParkValidationAPI.Models
{
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Username { get; set; }
public AdminRole Role { get; set; }
public int ValidationPointId { get; set; }
[JsonIgnore]
public string PasswordHash { get; set; }
}
}
+13
View File
@@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace CarParkValidationAPI.Models.Users
{
public class AuthenticateRequest
{
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
}
}
+27
View File
@@ -0,0 +1,27 @@
using CarParkValidationAPI.Entities;
namespace CarParkValidationAPI.Models.Users
{
public class AuthenticateResponse
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username { get; set; }
public AdminRole Role { get; set; }
public int ValidationPointId { get; set; }
public string Token { get; set; }
public string Email { get; set; }
public AuthenticateResponse(User user, string token)
{
Id = user.Id;
FirstName = user.FirstName;
LastName = user.LastName;
Username = user.Username;
Email = user.Email;
Role = user.Role;
Token = token;
ValidationPointId = user.ValidationPointId;
}
}
}
+26
View File
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.ComponentModel.DataAnnotations;
namespace CarParkValidationAPI.Models
{
public class ValidationPoint
{
[Key]
public int ValidationPointID { get; set; }
public string Description { get; set; }
public string DisplayName { get; set; }
public bool Active { get; set; }
public DateTime? LastModified { get; set; }
public string? LastModifiedId { get; set; }
}
}
+26
View File
@@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
+35
View File
@@ -0,0 +1,35 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iis": {
"applicationUrl": "http://localhost/CarParkValidationAPI",
"sslPort": 0
},
"iisExpress": {
"applicationUrl": "http://localhost:61744",
"sslPort": 0
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"CarParkValidationAPI": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": "true",
"applicationUrl": "http://localhost:5100"
}
}
}
+206
View File
@@ -0,0 +1,206 @@
//using BCryptNet = BCrypt.Net.BCrypt;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Helpers;
using CarParkValidationAPI.Models.Users;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Datas;
using CarParkValidationAPI.Interface;
using Microsoft.EntityFrameworkCore;
using System;
namespace CarParkValidationAPI.Repository
{
public class AdminUserFakeRepository : IAdminUser
{
private DataContext _context;
private string _currentUser = "";
List<AdminUserViewDto> _resultList = new List<AdminUserViewDto>();
private readonly AppSettings _appSettings;
public AdminUserFakeRepository(
DataContext context,
IOptions<AppSettings> appSettings)
{
_context = context;
_appSettings = appSettings.Value;
}
public void SetCurrentUser(string username)
{
_currentUser = username;
}
private AdminUserDto FillAdminUserDto(AdminUser model)
{
AdminUserDto dto = new AdminUserDto();
dto.Id = model.UserID;
dto.Name = model.Name;
dto.RoleType = model.RoleType;
dto.StafflinkNo = model.StafflinkNo;
dto.Active = model.Active;
dto.AddedBy = model.AddedBy;
dto.AddedOn = model.AddedOn;
return dto;
}
private AdminUser FillAdminUser(AdminUserDto dto, AdminUser model)
{
model.UserID = dto.Id;
model.Name = dto.Name;
model.RoleType = dto.RoleType;
model.StafflinkNo = dto.StafflinkNo;
model.Active = dto.Active;
model.AddedBy = dto.AddedBy;
model.AddedOn = dto.AddedOn;
return model;
}
public async Task<ResultModel<bool>> CheckAdminUserByStaffLinkNoAsync(string staffLinkNo)
{
var list = await _context.AdminUsers.Where(x => x.StafflinkNo == staffLinkNo).ToListAsync();
return new ResultModel<bool>()
{
Data = false,
StatusCode = 1
};
}
public async Task<ResultModel<List<AdminUserViewDto>>> LoadAdminUserAsync(bool onlyActive)
{
/*
List<AdminUserDto> resultList = new List<AdminUserDto>();
try
{
var it = await _context.AdminUsers.AsQueryable().ToListAsync();
AdminUserDto dto;
for (int i = 0; i < it.Count; i++)
{
dto = FillAdminUserDto(it[i]);
resultList.Add(dto);
}
//var it = await Task.Run(() => _list);
return new ResultModel<List<AdminUserDto>>()
{
Data = resultList,
StateCode = 1
};
}
catch (Exception ex)
{
throw ex;
}
*/
var list = await _context.AdminUsers.Where(x => x.Active == onlyActive).ToListAsync();
for (int i =0; i < list.Count; i++)
{
AdminUserViewDto dto = new AdminUserViewDto();
dto.Id = i;
dto.Name = $"Name {i}";
dto.RoleType = AdminRole.Admin.ToString();
dto.StafflinkNo = $"{i+40000}";
dto.Active = true;
dto.AddedOn = DateTime.Today.AddDays(i);
dto.AddedBy = "ddfed";
_resultList.Add(dto);
}
return new ResultModel<List<AdminUserViewDto>>()
{
Data = _resultList,
StatusCode = 1
};
}
public async Task<ResultModel<AdminUserDto>> LoadAdminUserByIdAsync(int id)
{
AdminUserDto result = null;
try
{
if (id > 0)
{
AdminUser model = await _context.AdminUsers.FindAsync(id);
result = FillAdminUserDto(model);
}
}
catch (Exception ex)
{
throw ex;
}
return new ResultModel<AdminUserDto>()
{
Data = result,
StatusCode = 1
};
}
public async Task<ResultModel<int>> SaveAdminUserAsync(AdminUserDto item)
{
int result = default(int);
try
{
AdminUser model;
if (item.Id > 0)
{
model = await _context.AdminUsers.FindAsync(item.Id);
model = FillAdminUser(item, model);
await _context.SaveChangesAsync();
}
else
{
model = new AdminUser();
model = FillAdminUser(item, model);
_context.AdminUsers.Add(model);
await _context.SaveChangesAsync();
}
result = 1;
}
catch (Exception ex)
{
result = -1;
throw ex;
}
return new ResultModel<int>()
{
Data = result,
StatusCode = 1
};
}
public async Task<ResultModel<bool>> DeleteAdminUserAsync(int id)
{
bool result = true;
try
{
if (id > 0)
{
AdminUser model = await _context.AdminUsers.FindAsync(id);
model.Active = false;
await _context.SaveChangesAsync();
}
}
catch (Exception ex)
{
result = false;
throw ex;
}
return new ResultModel<bool>()
{
Data = result,
StatusCode = 1
};
}
}
}
+275
View File
@@ -0,0 +1,275 @@
//using BCryptNet = BCrypt.Net.BCrypt;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Helpers;
using CarParkValidationAPI.Models.Users;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Datas;
using CarParkValidationAPI.Interface;
using Microsoft.EntityFrameworkCore;
using System;
namespace CarParkValidationAPI.Repository
{
public class AdminUserRepository : IAdminUser
{
private DataContext _context;
private string _currentUser = "";
private readonly AppSettings _appSettings;
private Dictionary<int, string> _ValidationPointDic = null;
public AdminUserRepository(
DataContext context,
IOptions<AppSettings> appSettings)
{
_context = context;
_appSettings = appSettings.Value;
}
public void SetCurrentUser(string username)
{
_currentUser = username;
}
private string GetValidtionPointDesc(int id)
{
string result = "";
if (_ValidationPointDic != null && _ValidationPointDic.ContainsKey(id))
result = _ValidationPointDic[id];
return result;
}
private AdminUserViewDto FillAdminUserViewDto(AdminUser model)
{
AdminUserViewDto dto = new AdminUserViewDto();
dto.Id = model.UserID;
dto.Name = model.Name;
dto.RoleType = model.RoleType.ToString();
dto.StafflinkNo = model.StafflinkNo;
dto.Active = model.Active;
dto.AddedBy = model.AddedBy;
dto.AddedOn = model.AddedOn;
dto.ValidationPoint = GetValidtionPointDesc(model.ValidationPointID??0);
return dto;
}
private AdminUserDto FillAdminUserDto(AdminUser model)
{
AdminUserDto dto = new AdminUserDto();
dto.Id = model.UserID;
dto.Name = model.Name;
dto.RoleType = model.RoleType;
dto.StafflinkNo = model.StafflinkNo;
dto.Active = model.Active;
dto.AddedBy = model.AddedBy;
dto.AddedOn = model.AddedOn;
dto.ValidationPointId = model.ValidationPointID ?? 0;
return dto;
}
private AdminUser FillAdminUser(AdminUserDto dto, AdminUser model)
{
if (dto.Id > 0)
model.UserID = dto.Id;
model.Name = dto.Name;
model.RoleType = dto.RoleType;
model.StafflinkNo = dto.StafflinkNo;
model.Active = dto.Active;
model.AddedBy = dto.AddedBy;
model.AddedOn = dto.AddedOn.ToLocalTime();
model.ValidationPointID = dto.ValidationPointId;
return model;
}
public async Task<ResultModel<List<AdminUserViewDto>>> LoadAdminUserAsync(bool onlyActive)
{
List<AdminUserViewDto> resultList = new List<AdminUserViewDto>();
int statuscode = 0;
string error = "";
try
{
_ValidationPointDic = await _context.Validations.Where(x => x.Active == true).ToDictionaryAsync((x) => x.ValidationPointID, y => y.Description);
//var list = await _context.AdminUsers.Where(x => x.Active == onlyActive).ToListAsync();
var list = await _context.AdminUsers.AsQueryable().ToListAsync();
AdminUserViewDto dto;
AdminUser user;
for (int i = 0; i < list.Count; i++)
{
user = list[i];
dto = FillAdminUserViewDto(user);
resultList.Add(dto);
}
statuscode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
throw ex;
}
return new ResultModel<List<AdminUserViewDto>>()
{
Data = resultList,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<bool>> CheckAdminUserByStaffLinkNoAsync(string staffLinkNo)
{
bool result = false;
int statuscode = 0;
string error = "";
try
{
if (!string.IsNullOrEmpty(staffLinkNo))
{
var list = await _context.AdminUsers.Where( x=> x.StafflinkNo == staffLinkNo).ToListAsync();
if (list.Count > 0)
{
result = true;
statuscode = 1;
}
}
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
throw ex;
}
return new ResultModel<bool>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<AdminUserDto>> LoadAdminUserByIdAsync(int id)
{
AdminUserDto result = null;
int statuscode = 0;
string error = "";
try
{
if (id > 0)
{
AdminUser model = await _context.AdminUsers.FindAsync(id);
result = FillAdminUserDto(model);
statuscode = 1;
}
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
throw ex;
}
return new ResultModel<AdminUserDto>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<int>> SaveAdminUserAsync(AdminUserDto item)
{
int result = default(int);
int statuscode = 0;
string error = "";
try
{
AdminUser model;
if (item.Id > 0)
{
model = await _context.AdminUsers.FindAsync(item.Id);
model = FillAdminUser(item, model);
model.LastModified = DateTime.Now;
model.LastModifiedId = _currentUser;
await _context.SaveChangesAsync();
result = model.UserID;
statuscode = 1;
}
else
{
ResultModel<bool> found = await CheckAdminUserByStaffLinkNoAsync(item.StafflinkNo);
if (!found.Data)
{
model = new AdminUser();
model = FillAdminUser(item, model);
_context.AdminUsers.Add(model);
await _context.SaveChangesAsync();
result = model.UserID;
statuscode = 1;
}
else
{
error = "staff link No '" + item.StafflinkNo + "' already in admin user";
statuscode = 0;
result = 0;
}
}
}
catch (Exception ex)
{
result = -1;
error = ex.ToString();
statuscode = 0;
throw ex;
}
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<bool>> DeleteAdminUserAsync(int id)
{
bool result = true;
int statuscode = 0;
string error = "";
try
{
if (id > 0)
{
AdminUser model = await _context.AdminUsers.FindAsync(id);
model.Active = false;
model.LastModified = DateTime.Now;
model.LastModifiedId = _currentUser;
await _context.SaveChangesAsync();
statuscode = 1;
}
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
result = false;
throw ex;
}
return new ResultModel<bool>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
}
}
+239
View File
@@ -0,0 +1,239 @@
//using BCryptNet = BCrypt.Net.BCrypt;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Helpers;
using CarParkValidationAPI.Models.Users;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Datas;
using CarParkValidationAPI.Interface;
using Microsoft.EntityFrameworkCore;
using System;
namespace CarParkValidationAPI.Repository
{
public class ConcessionTypeRepository : IConcessionType
{
private DataContext _context;
private string _currentUser = "";
private readonly AppSettings _appSettings;
public ConcessionTypeRepository(
DataContext context,
IOptions<AppSettings> appSettings)
{
_context = context;
_appSettings = appSettings.Value;
}
public void SetCurrentUser(string username)
{
_currentUser = username;
}
private ConcessionTypeDto FillConcessionTypeDto(ConcessionType model)
{
ConcessionTypeDto dto = new ConcessionTypeDto();
dto.Active = model.Active;
dto.Description = model.ConcessionDesc;
dto.Display = model.ConcessionDisplay;
dto.Id = model.ConcessionTypeID;
return dto;
}
private ConcessionType FillConcessionType(ConcessionTypeDto dto, ConcessionType model)
{
model.Active = dto.Active;
model.ConcessionDesc = dto.Description.Trim();
if (!string.IsNullOrEmpty(dto.Display))
model.ConcessionDisplay = dto.Display.Trim();
if (dto.Id > 0)
model.ConcessionTypeID = dto.Id;
return model;
}
public async Task<ResultModel<List<ConcessionTypeDto>>> LoadConcessionTypeAsync(bool onlyActive)
{
List<ConcessionTypeDto> result = null;
int statuscode = 0;
string error = "";
try
{
result = await _context.ConcessionTypes.Select(
x => new ConcessionTypeDto()
{
Id = x.ConcessionTypeID,
Description = x.ConcessionDesc,
Display = x.ConcessionDisplay,
Active = x.Active
}).ToListAsync();
//var olist = await _context.ConcessionTypes.ToListAsync();
//result = _mapper.Map<List<ConcessionTypeDto>>(olist);
statuscode = 1;
result.Sort((x, y) => x.Description.CompareTo(y.Description));
}
catch (Exception ex)
{
result = null;
error = ex.ToString();
statuscode = 0;
throw ex;
}
return new ResultModel<List<ConcessionTypeDto>>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<ConcessionTypeDto>> LoadConcessionTypeByIdAsync(int id)
{
ConcessionType result = null;
int statuscode = 0;
string error = "";
ConcessionTypeDto dto;
try
{
result = await _context.ConcessionTypes.FindAsync(id);
dto = new();
if (result != null)
{
dto.Id = id;
dto.Active = result.Active;
dto.Description = result.ConcessionDesc;
dto.Display = result.ConcessionDisplay;
}
// dto = _mapper.Map<ConcessionTypeDto>(result);
//dto = FillConcessionTypeDto(result);
//result = _list.Find(x => x.Id == id);
//var dto = await Task.Run(() => result);
statuscode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
throw ex;
}
return new ResultModel<ConcessionTypeDto>()
{
Data = dto,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<int>> SaveConcessionTypeAsync(ConcessionTypeDto item)
{
int result = default(int);
int statuscode = 0;
string error = "";
try
{
ConcessionType model;
if (item.Id > 0)
{
model = await _context.ConcessionTypes.FindAsync(item.Id);
model = FillConcessionType(item, model);
model.LastModified = DateTime.Now;
model.LastModifiedId = _currentUser;
await _context.SaveChangesAsync();
result = item.Id;
}
else //new record
{
model = new ConcessionType();
model = FillConcessionType(item, model);
model.LastModified = DateTime.Now;
model.LastModifiedId = _currentUser;
_context.ConcessionTypes.Add(model);
var id = await _context.SaveChangesAsync();
result = model.ConcessionTypeID;
}
statuscode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
throw ex;
}
//var dto = await Task.Run(() => result);
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<bool>> DeleteConcessionTypeAsync(int id)
{
bool result = true;
int statuscode = 0;
string error = "";
try
{
ConcessionType model;
if (id > 0)
{
model = await _context.ConcessionTypes.FindAsync(id);
model.Active = false;
//_context.ConcessionTypes.Remove(model);
await _context.SaveChangesAsync();
statuscode = 1;
}
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
throw;
}
//var dto = await Task.Run(() => result);
return new ResultModel<bool>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<Dictionary<int, LookupCodeDto>>> GetConcessionTypeDicAsync()
{
Dictionary<int, LookupCodeDto> resultList = new();
int statusCode = 0;
string error = "";
try
{
resultList = await _context.ConcessionTypes.Where(x => x.Active == true)
.Select(item => new LookupCodeDto { Id = item.ConcessionTypeID, Description = item.ConcessionDesc ?? "" })
.ToDictionaryAsync(x => x.Id);
statusCode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = 0;
throw ex;
}
return new ResultModel<Dictionary<int, LookupCodeDto>>()
{
Data = resultList,
StatusCode = statusCode,
Message = error
};
}
}
}
@@ -0,0 +1,139 @@
using CarParkValidationAPI.Datas;
using CarParkValidationAPI.Models;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using SpreadsheetLight;
using CarParkValidationAPI.Entities;
using System.IO;
namespace CarParkValidationAPI.Repository
{
public class ConcessionValidationReportRepository
{
private readonly DataContext _context;
private readonly IOptions<AppSettings> _appSettings;
const string DateFormat = "dd-MM-yyyy HH:mm";
const string dateFormat = "dd-MM-yyyyy";
public ConcessionValidationReportRepository(
DataContext context, IOptions<AppSettings> appSettings)
{
_context = context;
_appSettings = appSettings;
}
public async Task<ResultModel<FileContent>> GetConcessionValidationReport(DateTime fromDate, DateTime toDate)
{
//excel SLDocument sl = new SLDocument();
int statusCode = 1;
ConcessionValidationExtDto item;
int col = 1;
int row = 1;
SLDocument sl = new SLDocument();
//first sheetName
sl.RenameWorksheet(SLDocument.DefaultFirstSheetName, "ConcessionValidation");
SLStyle style = sl.CreateStyle();
style.SetFontUnderline(DocumentFormat.OpenXml.Spreadsheet.UnderlineValues.Single);
style.SetFontBold(true);
style.SetFont("Arial Black", 16);
sl.SetCellStyle(1, 5, style);
sl.SetRowHeight(1, 1, 25);
sl.SetCellValue(row++, 5, "The Concession Validation Report");
sl.SetCellValue(row, 3, "Date Range: " + fromDate.ToString(dateFormat) + " - " + toDate.ToString(dateFormat) );
sl.SetCellValue(1, 6, " " + DateTime.Now.ToString("ddd dd/MM/yyyy HH:mm"));
int startTitleRow = 3;
row = startTitleRow;
//make the title bold
style = sl.CreateStyle();
style.Font.Bold = true;
sl.SetRowStyle(startTitleRow, style);
//set it height
sl.SetRowHeight(startTitleRow, startTitleRow, 25);
// add the title first
sl.SetCellValue(row, col++, "Date");
sl.SetCellValue(row, col++, "Concession Card Number");
sl.SetCellValue(row, col++, "Concession Holder Name");
sl.SetCellValue(row, col++, "Expiry date checked");
sl.SetCellValue(row, col++, "ConcessionType");
sl.SetCellValue(row, col++, "Validation Piont");
// sl.SetCellValue(row, col++, "StaffLink No");
sl.SetCellValue(row, col++, "Enter by");
// sl.SetCellValue(row, col++, "Staff Last name");
// sl.SetCellValue(row, col++, "Staff Email");
sl.FreezePanes(row, col - 1); //frozen the row.
//wrap text on is concession Expiry
style = sl.CreateStyle();
style.SetWrapText(true);
sl.SetColumnStyle(4, style);
//format date
style = sl.CreateStyle();
style.FormatCode = "dd/MM/yyyy HH:MM";
sl.SetColumnStyle(1, style);
//make column width
sl.SetColumnWidth(1, 20);
sl.SetColumnWidth(2, 18);
sl.SetColumnWidth(3, 25);
sl.SetColumnWidth(4, 20);
sl.SetColumnWidth(5, 50);
sl.SetColumnWidth(6, 40);
sl.SetColumnWidth(7, 40);
// sl.SetColumnWidth(8, 20);
// sl.SetColumnWidth(9, 20);
// sl.SetColumnWidth(10, 20);
int startRowFrom = startTitleRow+1;
var list = await _context.SelectConcessionValidationByDate(true, fromDate.ToLocalTime(), toDate.ToLocalTime());
for (int i = 0; i < list.Count; i++)
{
col = 1;
item = list[i];
row = i + startRowFrom;
sl.SetCellValue(row, col++, item.ValidateDate);
sl.SetCellValue(row, col++, item.ConcessionCard);
sl.SetCellValue(row, col++, item.ConcessionHolder);
sl.SetCellValue(row, col++, item.ConcessionExpiry ? "Yes": "No");
sl.SetCellValue(row, col++, item.ConcessionType);
sl.SetCellValue(row, col++, item.ValidationPoint);
// sl.SetCellValue(row, col++, item.StafflinkNo);
sl.SetCellValue(row, col++, item.StaffFirstName + " " + item.StaffLastName);
// sl.SetCellValue(row, col++, item.StaffLastName);
// sl.SetCellValue(row, col++, item.StaffEmail);
}
byte[] array;
// sl.SaveAs("C:\\Temp\\Report\\ConcessionValidationDate" + DateTime.Now.ToString("yyyyMMddHHmm") + ".xlsx");
using (MemoryStream ws = new MemoryStream())
{
sl.SaveAs(ws);
array = ws.ToArray();
/*
using (FileStream fs = new FileStream("c:\\temp\\Report\\conReport.xlsx",FileMode.Create,FileAccess.Write))
{
ws.WriteTo(fs);
fs.Close();
}
*/
ws.Close();
}
var result = new FileContent
{
Content = array,
FileName = "ConcessionValidation" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm")+ ".xlsx",
};
return new ResultModel<FileContent>
{
Data = result,
StatusCode = statusCode
};
}
}
}
@@ -0,0 +1,409 @@
//using BCryptNet = BCrypt.Net.BCrypt;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Helpers;
using CarParkValidationAPI.Models.Users;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Datas;
using CarParkValidationAPI.Interface;
using Microsoft.EntityFrameworkCore;
using System;
using System.Security.Cryptography.Xml;
namespace CarParkValidationAPI.Repository
{
public class ConcessionValidationRepository : IConcessionValidation
{
private DataContext _context;
private string _currentUser = "";
private readonly AppSettings _appSettings;
public ConcessionValidationRepository(
DataContext context,
IOptions<AppSettings> appSettings)
{
_context = context;
_appSettings = appSettings.Value;
}
public void SetCurrentUser(string username)
{
_currentUser = username;
}
private ConcessionValidationDto FillConcessionValidationDto(ConcessionValidation model)
{
ConcessionValidationDto dto = new ConcessionValidationDto();
dto.Active = model.Active;
dto.ConcessionCard = model.ConcessionCard;
dto.ConcessionExpiry = model.ConcessionExpiry;
dto.ConcessionHolder = model.ConcessionHolder;
dto.ConcessionTypeId = model.ConcessionTypeID;
dto.Id = model.ValidationID;
dto.StafflinkNo = model.StafflinkNo;
dto.ValidateDate = model.ValidateDate;
dto.ValidationPointId = model.ValidationPointID;
dto.StaffFirstName = model.StaffFirstName;
dto.StaffLastName = model.StaffLastName;
dto.StaffEmail = model.StaffEmail;
return dto;
}
private ConcessionValidationExtDto FillConcessionValidationExtDto(ConcessionValidation model)
{
ConcessionValidationExtDto dto = new ConcessionValidationExtDto();
dto.Active = model.Active;
dto.ConcessionCard = model.ConcessionCard;
dto.ConcessionExpiry = model.ConcessionExpiry;
dto.ConcessionHolder = model.ConcessionHolder;
dto.ConcessionTypeId = model.ConcessionTypeID;
dto.Id = model.ValidationID;
dto.StaffFirstName = model.StaffFirstName;
dto.StaffLastName = model.StaffLastName;
dto.StaffEmail = model.StaffEmail;
dto.ValidateDate = model.ValidateDate;
dto.ValidationPointId = model.ValidationPointID;
return dto;
}
private ConcessionValidation FillConcessionValidation(ConcessionValidationDto dto, ConcessionValidation model)
{
model.Active = dto.Active;
model.ConcessionCard = dto.ConcessionCard.Trim();
model.ConcessionExpiry = dto.ConcessionExpiry;
model.ConcessionHolder = dto.ConcessionHolder.Trim();
model.ConcessionTypeID = dto.ConcessionTypeId;
if (dto.Id > 0)
model.ValidationID = dto.Id;
model.StafflinkNo = dto.StafflinkNo;
model.StaffFirstName = dto.StaffFirstName.Trim();
model.StaffLastName = dto.StaffLastName.Trim();
model.StaffEmail = dto.StaffEmail.Trim();
model.ValidateDate = dto.ValidateDate.ToLocalTime();
model.ValidationPointID = dto.ValidationPointId;
return model;
}
public async Task<ResultModel<List<ConcessionValidationExtDto>>> LoadConcessionValidationAsync(bool onlyActive)
{
int statuscode = 0;
string error = "";
List<ConcessionValidationExtDto> result = new List<ConcessionValidationExtDto>();
ConcessionValidationExtDto dto;
ConcessionValidation model;
try
{
List<ConcessionValidation> clist = await _context.ConcessionValidations.Where(x => x.Active == true).ToListAsync();
for (int i = 0; i < clist.Count; i++)
{
model = clist[i];
dto = FillConcessionValidationExtDto(model);
result.Add(dto);
}
statuscode = 1;
}
catch (Exception ex)
{
statuscode = 0;
error = ex.ToString();
throw;
}
return new ResultModel<List<ConcessionValidationExtDto>>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<List<ConcessionValidationExtDto>>> LoadConcessionValidationStaffLinkNoAsync(string staffLinkNo, DateTime fromDate, DateTime toDate)
{
List<ConcessionValidationExtDto> result = new List<ConcessionValidationExtDto>();
// ConcessionValidationExtDto dto;
// ConcessionValidation model;
int statuscode = 0;
string error = "";
try
{
//List<ConcessionValidation> clist = await _context.ConcessionValidations.Where(x =>
// x.Active == true
// && x.StafflinkNo == staffLinkNo
// && x.ValidateDate.Date == currentDate.Date
//).ToListAsync();
result = await _context.SelectConcessionValidationByStaffId(true, staffLinkNo, fromDate, toDate);
/*
//var clist = await _context.SPSelectValidation(true, staffLinkNo, currentDate);
for (int i = 0; i < clist.Count; i++)
{
model = clist[i];
dto = FillConcessionValidationExtDto(model);
result.Add(dto);
}
*/
statuscode = 1;
result.Sort((x, y) => y.ValidateDate.CompareTo(x.ValidateDate));
}
catch (Exception ex)
{
statuscode = 0;
error = ex.ToString();
throw;
}
return new ResultModel<List<ConcessionValidationExtDto>>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<int>> CheckConcessionValidationStaffLinkNoAsync(string staffLinkNo, string concessionCard, DateTime currentDate, int id)
{
int statuscode = 1;
int result = 1;
int number = id < 1 ? 0 : 1; // if insert check > 0 . if modify > 1
string message = "warning you already add concession card on this date!";
try
{
var anyRecord = await _context.SelectCheckConcessionValidationAsync(currentDate.ToLocalTime().Date, concessionCard.Trim(), staffLinkNo.Trim());
if (anyRecord.Count > number)
{
result = -1;
}
else
{
result = 1; //test
message = "test OK just one time";
}
statuscode = 1;
}
catch (Exception ex)
{
message = "Error " + ex.ToString();
statuscode = 0;
result = 0;
}
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = message,
};
}
public async Task<ResultModel<int>> CheckConcessionValidationStaffLinkNoAsync_old(string staffLinkNo, string concessionCard, DateTime currentDate)
{
int statuscode = 1;
int result = 1;
string concard = concessionCard.Trim();
string message = "warning you already add concession card on this date!";
try
{
var anyRecord = await _context.ConcessionValidations.Where(x =>
x.StafflinkNo == staffLinkNo
&& x.ConcessionCard == concard
&& x.Active == true
&& x.ValidateDate.Date == currentDate.ToLocalTime().Date
).ToListAsync();
if (anyRecord.Count > 0)
{
result = -1;
}
else
{
result = 1; //test
message = "test OK just one time";
}
statuscode = 1;
}
catch (Exception ex)
{
message = "Error " + ex.ToString();
statuscode = 0;
result = 0;
}
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = message,
};
}
public async Task<ResultModel<ConcessionValidationDto>> LoadConcessionValidationByIdAsync(int id)
{
ConcessionValidationDto result = null;
int statuscode = 0;
string error = "";
try
{
if (id > 0)
{
ConcessionValidation model = await _context.ConcessionValidations.FindAsync(id);
result = FillConcessionValidationDto(model);
statuscode = 1;
}
}
catch (Exception ex)
{
statuscode = 0;
error = ex.ToString();
throw;
}
return new ResultModel<ConcessionValidationDto>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<ConcessionValidationDto>> LoadConcessionValidationByCardNumberAsync(string cardNo)
{
ConcessionValidationDto result = null;
int statuscode = 0;
string error = "";
try
{
if (!string.IsNullOrEmpty(cardNo))
{
var list = await _context.ConcessionValidations.Where(x => x.ConcessionCard == cardNo).ToListAsync();
if (list != null && list.Count > 0)
{
result = FillConcessionValidationDto(list[0]);
statuscode = 1;
}
else
statuscode = -1;
}
}
catch (Exception ex)
{
statuscode = 0;
error = ex.ToString();
throw;
}
return new ResultModel<ConcessionValidationDto>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<int>> SaveConcessionValidationAsync(ConcessionValidationDto item)
{
int result = default(int);
int statuscode = 0;
string error = "";
//_currentUser = item.StafflinkNo;
try
{
ConcessionValidation model;
if (item.Id > 0)
{
model = await _context.ConcessionValidations.FindAsync(item.Id);
model = FillConcessionValidation(item, model);
model.LastModified = DateTime.Now;
model.LastModifiedId = _currentUser;
result = await _context.SaveChangesAsync();
}
else
{
model = new ConcessionValidation();
model = FillConcessionValidation(item, model);
model.LastModified = DateTime.Now;
model.LastModifiedId = _currentUser;
model.CreatedDate = DateTime.Now;
model.CreatedId = _currentUser;
_context.ConcessionValidations.Add(model);
result = await _context.SaveChangesAsync();
result = model.ValidationID;
}
statuscode = 1;
}
catch (Exception ex)
{
statuscode = 0;
error = ex.ToString();
throw;
}
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<bool>> DeleteConcessionValidationAsync(int id)
{
bool result = true;
int statuscode = 0;
string error = "";
try
{
if (id > 0)
{
ConcessionValidation model = await _context.ConcessionValidations.FindAsync(id);
model.Active = false;
model.LastModified = DateTime.Now;
model.LastModifiedId = _currentUser;
//_context.ConcessionValidations.Remove(model);
await _context.SaveChangesAsync();
statuscode = 1;
}
}
catch (Exception ex)
{
result = false;
statuscode = 0;
error = ex.ToString();
throw;
}
return new ResultModel<bool>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<FileContent>> GetReport(DateTime fromDate, DateTime toDate)
{
int statusCode = 1;
string fileContext = "filecontain as string this is file contain in string format";
//await this._concessionValidationReport.GetConcessionValidationReport(DateTime.Today.AddDays(-30), DateTime.Today.AddDays(30));
var result = new FileContent
{
Content = Convert.FromBase64String(fileContext),
FileName = "excel extension"
};
var task = await Task.Run(() => 1);
return new ResultModel<FileContent>
{
Data = result,
StatusCode = statusCode
};
}
}
}
+95
View File
@@ -0,0 +1,95 @@
//using BCryptNet = BCrypt.Net.BCrypt;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Helpers;
using CarParkValidationAPI.Models.Users;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Datas;
using CarParkValidationAPI.Interface;
using Microsoft.EntityFrameworkCore;
using System;
namespace CarParkValidationAPI.Repository
{
public class LookupCodeRepository: ILookupCode
{
private DataContext _context;
private readonly AppSettings _appSettings;
public LookupCodeRepository(
DataContext context,
IOptions<AppSettings> appSettings)
{
_context = context;
_appSettings = appSettings.Value;
}
public async Task<ResultModel<List<LookupCodeDto>>> LoadConcessionTypeAsync(bool onlyActive)
{
List<LookupCodeDto> result = null;
int statuscode = 0;
string error = "";
try
{
result = await _context.ConcessionTypes.Where(x => x.Active == onlyActive).Select(
x => new LookupCodeDto()
{
Id = x.ConcessionTypeID,
Description = x.ConcessionDesc,
}).ToListAsync();
statuscode = 1;
result.Sort((x,y) => x.Description.CompareTo(y.Description));
}
catch (Exception ex)
{
statuscode = 0;
error = ex.ToString();
throw;
}
return new ResultModel<List<LookupCodeDto>>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<List<LookupCodeDto>>> LoadValidationPointAsync(bool onlyActive)
{
List<LookupCodeDto> result = null;
int statuscode = 0;
string error = "";
try
{
result = await _context.Validations.Where(x => x.Active == onlyActive).Select(
x => new LookupCodeDto()
{
Id = x.ValidationPointID,
Description = x.Description
}).ToListAsync();
result.Sort((x, y) => x.Description.CompareTo(y.Description));
statuscode = 1;
}
catch (Exception ex)
{
statuscode = 0;
error = ex.ToString();
throw;
}
return new ResultModel<List<LookupCodeDto>>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
}
}
+384
View File
@@ -0,0 +1,384 @@
//using BCryptNet = BCrypt.Net.BCrypt;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Helpers;
using CarParkValidationAPI.Models.Users;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Datas;
using CarParkValidationAPI.Interface;
using Microsoft.EntityFrameworkCore;
using CommonAD;
using SpreadsheetLight;
using System.IO;
using System;
namespace CarParkValidationAPI.Repository
{
public class UserRepository : IUserService
{
private DataContext _context;
private IJwtUtils _jwtUtils;
private readonly AppSettings _appSettings;
private readonly IValidationPoint _validationPoint;
private Dictionary<int, LookupCodeDto> _validationPointDic;
public UserRepository(
DataContext context,
IJwtUtils jwtUtils,
IValidationPoint validationPoint,
IOptions<AppSettings> appSettings)
{
_context = context;
_jwtUtils = jwtUtils;
_validationPoint = validationPoint;
_appSettings = appSettings.Value;
}
public AuthenticateResponse Authenticate(AuthenticateRequest model)
{
var user = _context.Users.SingleOrDefault(x => x.Username == model.Username);
// validate
// if (user == null || !BCryptNet.Verify(model.Password, user.PasswordHash))
if (user == null || (model.Password != user.PasswordHash))
throw new System.Exception("Username or password is incorrect");
// authentication successful so generate jwt token
var jwtToken = _jwtUtils.GenerateJwtToken(user);
return new AuthenticateResponse(user, jwtToken);
}
public async Task<ResultModel<AuthenticateResponse>> LoginApiAD(AuthenticateRequest model)
{
User myUser = null;
AuthenticateResponse retval = null;
int statuscode = 0;
string error = "";
string webAPIUrl = _appSettings.LoginWebAPI;
var loginInfo = await CommonAD.WebAPIUtil.PostLoginADAsync(webAPIUrl, "CheckCredentials", model.Username, model.Password);
if (loginInfo != null && loginInfo.result)
{
myUser = new User();
myUser.Email = loginInfo.email;
myUser.FirstName = loginInfo.firstName;
myUser.LastName = loginInfo.lastName;
myUser.Username = loginInfo.stafflinkNo;
//now check the adminuser table
var user = _context.AdminUsers.
SingleOrDefault(x => x.StafflinkNo == model.Username
&& x.Active == true);
if (user != null)
{
myUser.Role = user.RoleType;
myUser.Id = user.UserID;
myUser.ValidationPointId = user.ValidationPointID??0;
statuscode = 1;
}
else //not allow
{
statuscode = 0;
error = "username is not exist in admimuser.";
myUser.Role = AdminRole.Normal;
}
// validate
// if (user == null || !BCryptNet.Verify(model.Password, user.PasswordHash))
// authentication successful so generate jwt token
var jwtToken = _jwtUtils.GenerateJwtToken(myUser);
//statuscode = 1;
retval = new AuthenticateResponse(myUser, jwtToken);
}
else
error = "error username or password is invalid";
return new ResultModel<AuthenticateResponse>()
{
Data = retval,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<AuthenticateResponse>> LoginAD(AuthenticateRequest model)
{
User myUser = null;
AuthenticateResponse retval = null;
string error = "user name is not in DB or user Name profile is not generic";
int statuscode = 0;
string webAPIUrl = _appSettings.LoginWebAPI;
//KCO, D204KCO
//now check the adminuser table
//ward clerk
try
{
var loginInfo = await CommonAD.WebAPIUtil.PostLoginADAsync(webAPIUrl, "CheckCredentials", model.Username, model.Password);
if (loginInfo != null && loginInfo.result)
{
myUser = new User();
myUser.Email = loginInfo.email;
myUser.FirstName = loginInfo.firstName;
myUser.LastName = loginInfo.lastName;
myUser.Username = loginInfo.stafflinkNo;
//myUser.Department = loginInfo.department;
//myUser.Position = loginInfo.jobTitle;
//myUser.ManagerEmail = loginInfo.managerEmail;
//myUser.Phone = loginInfo.phone;
//now check the adminuser table
var user = _context.AdminUsers.
SingleOrDefault(x => x.StafflinkNo == model.Username
&& true == x.Active);
if (user != null)
{
// myUser.Role = user.RoleType;
myUser.Id = user.UserID;
myUser.Role = user.RoleType;
//myUser.ValidationPointId = user.ValidationPointID ?? 0;
statuscode = 1;
}
else // allow
{
statuscode = 1;
myUser.Role = AdminRole.Normal;
myUser.Id = -1;
//error = "user name does not exist in adminUser";
}
// validate
// if (user == null || !BCryptNet.Verify(model.Password, user.PasswordHash))
// authentication successful so generate jwt token
if (statuscode == 1)
{
var jwtToken = _jwtUtils.GenerateJwtToken(myUser);
retval = new AuthenticateResponse(myUser, jwtToken);
error = "";
}
}
else
{
error = "user name or password is not correct";
}
}
catch (Exception ex)
{
retval = null;
error = ex.ToString();
statuscode = 0;
throw ex;
}
return new ResultModel<AuthenticateResponse>()
{
Data = retval,
StatusCode = statuscode
};
}
public async Task<ResultModel<List<User>>> GetAllUsers()
{
var retval = await _context.Users.ToListAsync();
return new ResultModel<List<User>>()
{
Data = retval,
StatusCode = 1
};
}
public async Task<ResultModel<User>> GetById(int id)
{
var user = await _context.Users.FindAsync(id);
if (user == null) throw new KeyNotFoundException("User not found");
return new ResultModel<User>()
{
Data = user,
StatusCode = 1
};
}
public async Task<ResultModel<User>> SearchApiStaff(string staffLinkNo)
{
User myUser = null;
int statuscode = 0;
string webAPIUrl = _appSettings.LoginWebAPI;
var loginInfo = await CommonAD.WebAPIUtil.SearchStaffAsync(webAPIUrl, "SearchStaff", staffLinkNo);
if (loginInfo != null && loginInfo.result)
{
myUser = new User();
myUser.Email = loginInfo.email;
myUser.FirstName = loginInfo.firstName;
myUser.LastName = loginInfo.lastName;
myUser.Username = loginInfo.stafflinkNo;
statuscode = 1;
}
return new ResultModel<User>()
{
Data = myUser,
StatusCode = statuscode
};
// return myUser;
}
public async Task<ResultModel<User>> SearchADStaff(string staffLinkNo)
{
int statuscode = 0;
User myUser = null;
AuthenticateResponse retval = null;
string webAPIUrl = _appSettings.LoginWebAPI;
var loginInfo = await CommonAD.WebAPIUtil.SearchStaffAsync(webAPIUrl, "SearchStaff", staffLinkNo);
if (!string.IsNullOrEmpty(loginInfo.firstName))
{
myUser = new();
myUser.FirstName = loginInfo.firstName;
myUser.LastName = loginInfo.lastName;
myUser.Username = staffLinkNo;
myUser.Email = loginInfo.email;
/*
myUser.Department = loginInfo.department;
myUser.Position = loginInfo.jobTitle;
myUser.Phone = loginInfo.phone;
myUser.ManagerEmail = loginInfo.managerEmail;
*/
statuscode = 1;
}
return new ResultModel<User>()
{
Data = myUser,
StatusCode = statuscode
};
}
private string GetVPDesc(int? idn)
{
string result = "";
int id = idn ?? 1;
if (_validationPointDic.ContainsKey(id))
{
result = _validationPointDic[id].Description;
}
return result;
}
public async Task<ResultModel<FileContent>> GetAllUserReport()
{
//excel SLDocument sl = new SLDocument();
int statusCode = 1;
AdminUser item;
int col = 1;
int row = 1;
SLDocument sl = new SLDocument();
var ret = await _validationPoint.GetValidationPointDicAsync();
if (ret.StatusCode == 1)
_validationPointDic = ret.Data;
//first sheetName
sl.RenameWorksheet(SLDocument.DefaultFirstSheetName, "All User");
SLStyle style = sl.CreateStyle();
style.SetFontUnderline(DocumentFormat.OpenXml.Spreadsheet.UnderlineValues.Single);
style.SetFontBold(true);
style.SetFont("Arial Black", 16);
sl.SetCellStyle(1, 5, style);
sl.SetRowHeight(1, 1, 25);
sl.SetCellValue(row++, 5, "The User Report");
sl.SetCellValue(1, 6, " " + DateTime.Now.ToString("ddd dd/MM/yyyy HH:mm"));
int startTitleRow = 3;
row = startTitleRow;
//make the title bold
style = sl.CreateStyle();
style.Font.Bold = true;
sl.SetRowStyle(startTitleRow, style);
//set it height
sl.SetRowHeight(startTitleRow, startTitleRow, 25);
// add the title first
sl.SetCellValue(row, col++, "Stafflink ID");
sl.SetCellValue(row, col++, "Name");
sl.SetCellValue(row, col++, "Role");
sl.SetCellValue(row, col++, "Validation Point");
sl.SetCellValue(row, col++, "Active");
sl.FreezePanes(row,0); //frozen the row.
//wrap text on is concession Expiry
style = sl.CreateStyle();
style.SetWrapText(true);
sl.SetColumnStyle(4, style);
//format date
style = sl.CreateStyle();
style.FormatCode = "dd/MM/yyyy HH:MM";
sl.SetColumnStyle(1, style);
//make column width
sl.SetColumnWidth(1, 20);
sl.SetColumnWidth(2, 50);
sl.SetColumnWidth(3, 20);
sl.SetColumnWidth(4, 30);
sl.SetColumnWidth(5, 40);
/*
public enum AdminRole
{
Normal = 1,
Admin = 2
}
*/
int startRowFrom = startTitleRow + 1;
var list = await _context.AdminUsers.ToListAsync();
for (int i = 0; i < list.Count; i++)
{
col = 1;
item = list[i];
row = i + startRowFrom;
sl.SetCellValue(row, col++, item.StafflinkNo);
sl.SetCellValue(row, col++, item.Name);
sl.SetCellValue(row, col++, (int) item.RoleType == 1 ? "Normal": "Admin");
sl.SetCellValue(row, col++, GetVPDesc(item.ValidationPointID) );
sl.SetCellValue(row, col++, item.Active ? "Yes" : "No");
}
byte[] array;
// sl.SaveAs("C:\\Temp\\Report\\ConcessionValidationDate" + DateTime.Now.ToString("yyyyMMddHHmm") + ".xlsx");
using (MemoryStream ws = new MemoryStream())
{
sl.SaveAs(ws);
array = ws.ToArray();
/*
using (FileStream fs = new FileStream("c:\\temp\\Report\\conReport.xlsx",FileMode.Create,FileAccess.Write))
{
ws.WriteTo(fs);
fs.Close();
}
*/
ws.Close();
}
var result = new FileContent
{
Content = array,
FileName = "UserReport" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm") + ".xlsx",
};
return new ResultModel<FileContent>
{
Data = result,
StatusCode = statusCode
};
}
}
}
@@ -0,0 +1,207 @@
using CarParkValidationAPI.Datas;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Interface;
using CarParkValidationAPI.Models;
using DocumentFormat.OpenXml.VariantTypes;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Repository
{
public class ValidationPointFakeRepository : IValidationPoint
{
private DataContext _context;
private readonly AppSettings _appSettings;
private string _currentUser = "";
private List<ValidationPointDto> _list = new List<ValidationPointDto>();
public ValidationPointFakeRepository(
DataContext context,
IOptions<AppSettings> appSettings)
{
_context = context;
_appSettings = appSettings.Value;
}
public void SetCurrentUser(string username)
{
_currentUser = username;
}
private ValidationPointDto FillValidationDto(ValidationPoint item)
{
ValidationPointDto dto = new ValidationPointDto();
dto.Active = item.Active;
dto.Description = item.Description;
dto.Display = item.DisplayName;
dto.Id = item.ValidationPointID;
return dto;
}
private ValidationPoint FillValidationModel(ValidationPointDto item, ValidationPoint model) {
model.Active = item.Active;
model.Description = item.Description;
model.DisplayName = item.Display;
model.ValidationPointID = item.Id;
return model;
}
public async Task<ResultModel<List<ValidationPointDto>>> LoadValidationPointAsync(bool onlyActive)
{
try
{
/*
var it = await _context.Validations.AsQueryable().ToListAsync();
*/
ValidationPointDto dto;
ValidationPoint val;
for (int i = 0; i < 10; i++)
{
val = new ValidationPoint()
{
ValidationPointID = i,
Description = $"Validation {i}",
DisplayName = $"Display {i}",
Active = true,
};
dto = FillValidationDto(val);
_list.Add(dto);
}
//var it = await Task.Run(() => _list);
return new ResultModel<List<ValidationPointDto>>()
{
Data = _list,
StatusCode = 1
};
}
catch (Exception ex)
{
throw ex;
}
}
public async Task<ResultModel<ValidationPointDto>> LoadValidationPointByIdAsync(int id)
{
ValidationPoint result = null;
try
{
ValidationPointDto dto;
result = await _context.Validations.FindAsync(id);
dto = FillValidationDto(result);
//result = _list.Find(x => x.Id == id);
//var dto = await Task.Run(() => result);
return new ResultModel<ValidationPointDto>()
{
Data = dto,
StatusCode = 1
};
}
catch (Exception ex)
{
throw ex;
}
}
public async Task<ResultModel<int>> SaveValidationPointAsync(ValidationPointDto item)
{
int result = default(int);
try
{
ValidationPoint model;
if (item.Id > 0)
{
model = await _context.Validations.FindAsync(item.Id);
model = FillValidationModel(item, model);
await _context.SaveChangesAsync();
result = item.Id;
}
else //new record
{
model = new ValidationPoint();
model = FillValidationModel(item, model);
_context.Validations.Add(model);
var id = await _context.SaveChangesAsync();
result = id;
item.Id = id;
}
//var dto = await Task.Run(() => result);
return new ResultModel<int>()
{
Data = result,
StatusCode = 1
};
}
catch (Exception ex)
{
throw ex;
}
/*
ConcessionTypeDA dataAccess = new ConcessionTypeDA();
try
{
result = await dataAccess.InsertConcessionTypeAsync(item);
}
catch (Exception ex)
{
throw ex;
}
*/
}
public async Task<ResultModel<bool>> DeleteValidationPointAsync(int id)
{
bool result = true;
try
{
ValidationPoint model;
if (id > 0)
{
model = await _context.Validations.FindAsync(id);
model.Active = false;
//_context.Validations.Remove(model);
await _context.SaveChangesAsync();
}
//var dto = await Task.Run(() => result);
return new ResultModel<bool>()
{
Data = result,
StatusCode = 1
};
}
catch (Exception ex)
{
throw;
}
}
public async Task<ResultModel<Dictionary<int, LookupCodeDto>>> GetValidationPointDicAsync()
{
Dictionary<int, LookupCodeDto> resultList = new();
return new ResultModel<Dictionary<int, LookupCodeDto>>()
{
Data = resultList,
StatusCode = 1,
Message = ""
};
}
}
}
+217
View File
@@ -0,0 +1,217 @@
using CarParkValidationAPI.Datas;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Interface;
using CarParkValidationAPI.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CarParkValidationAPI.Repository
{
public class ValidationPointRepository : IValidationPoint
{
private DataContext _context;
private readonly AppSettings _appSettings;
private string _currentUser = "";
private List<ValidationPointDto> _list = new List<ValidationPointDto>();
public ValidationPointRepository(
DataContext context,
IOptions<AppSettings> appSettings)
{
_context = context;
_appSettings = appSettings.Value;
}
public void SetCurrentUser(string username)
{
_currentUser = username;
}
private ValidationPointDto FillValidationDto(ValidationPoint item)
{
ValidationPointDto dto = new ValidationPointDto();
dto.Active = item.Active;
dto.Description = item.Description;
dto.Display = item.DisplayName;
dto.Id = item.ValidationPointID;
return dto;
}
private ValidationPoint FillValidationModel(ValidationPointDto item, ValidationPoint model) {
model.Active = item.Active;
model.Description = item.Description.Trim();
if (!string.IsNullOrEmpty(item.Display))
model.DisplayName = item.Display.Trim();
if (item.Id > 0)
model.ValidationPointID = item.Id;
return model;
}
public async Task<ResultModel<List<ValidationPointDto>>> LoadValidationPointAsync(bool onlyActive)
{
int statuscode = 0;
string error = "";
try
{
var it = await _context.Validations.ToListAsync();
ValidationPointDto dto;
for (int i = 0; i < it.Count; i++)
{
dto = FillValidationDto(it[i]);
_list.Add(dto);
}
_list.Sort((x, y) => x.Description.CompareTo(y.Description));
statuscode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
throw ex;
}
return new ResultModel<List<ValidationPointDto>>()
{
Data = _list,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<ValidationPointDto>> LoadValidationPointByIdAsync(int id)
{
ValidationPoint result = null;
int statuscode = 0;
string error = "";
ValidationPointDto dto = null;
try
{
result = await _context.Validations.FindAsync(id);
dto = FillValidationDto(result);
//result = _list.Find(x => x.Id == id);
//var dto = await Task.Run(() => result);
statuscode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
}
return new ResultModel<ValidationPointDto>()
{
Data = dto,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<int>> SaveValidationPointAsync(ValidationPointDto item)
{
int result = default(int);
int statuscode = 0;
string error = "";
try
{
ValidationPoint model;
if (item.Id > 0)
{
model = await _context.Validations.FindAsync(item.Id);
model = FillValidationModel(item, model);
model.LastModified = DateTime.Now;
model.LastModifiedId = _currentUser;
await _context.SaveChangesAsync();
result = item.Id;
}
else //new record
{
model = new ValidationPoint();
model.LastModified = DateTime.Now;
model.LastModifiedId = _currentUser;
model = FillValidationModel(item, model);
_context.Validations.Add(model);
var id = await _context.SaveChangesAsync();
result = model.ValidationPointID;
}
statuscode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
}
//var dto = await Task.Run(() => result);
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<bool>> DeleteValidationPointAsync(int id)
{
bool result = true;
int statuscode = 0;
string error = "";
try
{
ValidationPoint model;
if (id > 0)
{
model = await _context.Validations.FindAsync(id);
model.Active = false;
//_context.Validations.Remove(model);
await _context.SaveChangesAsync();
statuscode = 1;
}
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = 0;
throw;
}
//var dto = await Task.Run(() => result);
return new ResultModel<bool>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<Dictionary<int, LookupCodeDto>>> GetValidationPointDicAsync()
{
Dictionary<int, LookupCodeDto> resultList = new();
int statusCode = 0;
string error = "";
try
{
resultList = await _context.Validations.Where(x => x.Active == true)
.Select(item => new LookupCodeDto { Id = item.ValidationPointID, Description = item.Description ?? "" })
.ToDictionaryAsync(x => x.Id);
statusCode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statusCode = 0;
throw ex;
}
return new ResultModel<Dictionary<int, LookupCodeDto>>()
{
Data = resultList,
StatusCode = statusCode,
Message = error
};
}
}
}
+135
View File
@@ -0,0 +1,135 @@
using CarParkValidationAPI.Authorization;
using CarParkValidationAPI.Datas;
using CarParkValidationAPI.Entities;
using CarParkValidationAPI.Helpers;
using CarParkValidationAPI.Interface;
using CarParkValidationAPI.Models;
using CarParkValidationAPI.Repository;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System.Text;
namespace CarParkValidationAPI
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
//** security
var appSettingsSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection);
var appSettings = appSettingsSection.Get<AppSettings>();
var key = Encoding.ASCII.GetBytes(appSettings.Secret);
//***
services.AddDbContext<DataContext>();
services.AddCors();
//***
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
// services.AddAutoMapper(typeof(Startup));
//**
//publish need to take comment out
services.AddSwaggerGen();
/*
services.AddSwaggerGen(option =>
{
option.UseAllOfForInheritance();
option.UseAllOfToExtendReferenceSchemas();
option.IgnoreObsoleteActions();
option.IgnoreObsoleteProperties();
option.ResolveConflictingActions(api => api.First());
});
*/
services.AddScoped<IJwtUtils, JwtUtils>();
//services.AddScoped<IUserService, UserFakeRepository>();
services.AddScoped<IUserService, UserRepository>();
services.AddScoped<IConcessionType, ConcessionTypeRepository>();
services.AddScoped<IValidationPoint, ValidationPointRepository>();
services.AddScoped<IAdminUser, AdminUserRepository>();
services.AddScoped<IConcessionValidation, ConcessionValidationRepository>();
services.AddScoped<ILookupCode, LookupCodeRepository>();
services.AddScoped(typeof(ConcessionValidationReportRepository));
services.AddHttpContextAccessor();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext context)
{
/*
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
*/
// global cors policy
app.UseCors(x => x
.SetIsOriginAllowed(origin => true)
.AllowAnyMethod()
.AllowAnyHeader()
.WithExposedHeaders("Content-Disposition")
.AllowCredentials());
app.UseMiddleware<JwtMiddleware>();
app.UseMiddleware<ErrorHandlerMiddleware>(); // use this exception
app.UseSwagger();
app.UseSwaggerUI();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseAuthentication();
app.UseAuthorization();
}
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
/*
"SQLConnectionString": "Server=NEPHICT-040931L;Initial Catalog=CarParkValidation;Persist Security Info=False;User ID=bids_admin;Password=Password4BI;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;",
user id=bids_admin;password=Password4BI;
Server=tcp:10.60.207.82,1433;
*/
+24
View File
@@ -0,0 +1,24 @@
{
"AppSettings": {
"Secret": "Nepean Blue Mountain Super Secret SIGN AND VERIFY JWT TOKENS, BEARER TOKEN USE WHEN CALLING THIS API.",
"SQLConnectionString": "Server=NEPHMDB-SQL007;Initial Catalog=CarParkValidation;Persist Security Info=False;User ID=bids_admin;Password=Password4BI;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;",
"LDAPPath": "",
"LDAPUser": "S",
"LDAPPassword": "",
"ADTimeOut": "30",
"LoginWebAPI": "http://NEPHMDB-SQL007/CommonWebApiAD/api/AD"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"OLDLoginWebAPI": "http://virtapp-mdb048/CommonAPI/api/AD/",
"LADP": "http://NEPHMDB-SQL007/CommonWebApiAD/api/AD/",
"AllowedHosts": "*",
"SQLConnectionString": "Server=NEPHMDB-SQL007;Initial Catalog=CarParkValidation;Persist Security Info=False;User ID=bids_admin;Password=Password4BI;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;",
"SQLConnectionStringold": "Server=tcp:10.60.207.82,1433;Initial Catalog=CarParkValidation;Persist Security Info=False;User ID=bids_admin;Password=Password4BI;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;"
}
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="bin\Debug\net5.0\CarParkValidationAPI.exe" arguments="" stdoutLogEnabled="false" hostingModel="InProcess">
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</location>
</configuration>
+17
View File
@@ -0,0 +1,17 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
ij_typescript_use_double_quotes = false
[*.md]
max_line_length = off
trim_trailing_whitespace = false
+58
View File
@@ -0,0 +1,58 @@
You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
## TypeScript Best Practices
- Use strict type checking
- Prefer type inference when the type is obvious
- Avoid the `any` type; use `unknown` when type is uncertain
## Angular Best Practices
- Always use standalone components over NgModules
- Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
- Do NOT set `changeDetection: ChangeDetectionStrategy.OnPush` explicitly. `OnPush` is the default in Angular v22+.
- Use signals for state management
- Implement lazy loading for feature routes
- Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
- Use `NgOptimizedImage` for all static images.
- `NgOptimizedImage` does not work for inline base64 images.
## Accessibility Requirements
- It MUST pass all AXE checks.
- It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
### Components
- Keep components small and focused on a single responsibility
- Use `input()` and `output()` functions instead of decorators
- Use `model()` for two-way bound properties with `[(prop)]` syntax instead of pairing `input()` with `output()`
- Use `computed()` for derived state
- Use `linkedSignal()` for state derived from multiple reactive sources that must stay synchronized
- Prefer inline templates for small components
- Prefer Signal Forms (`@angular/forms/signals`) for new forms. They are stable in Angular v22+ and provide signal-based state, type-safe field access, and schema-based validation
- When not using Signal Forms, prefer Reactive forms instead of Template-driven ones
- Do NOT use `ngClass`, use `class` bindings instead
- Do NOT use `ngStyle`, use `style` bindings instead
- When using external templates/styles, use paths relative to the component TS file.
## State Management
- Use signals for local component state
- Use `computed()` for derived state
- Keep state transformations pure and predictable
- Do NOT use `mutate` on signals, use `update` or `set` instead
## Templates
- Keep templates simple and avoid complex logic
- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
- Use the async pipe to handle observables
- Do not assume globals like (`new Date()`) are available.
## Services
- Design services around a single responsibility
- Use the `providedIn: 'root'` option for singleton services
- Prefer the `@Service` decorator over `@Injectable({providedIn: 'root'})` for new singleton services (Angular v22+)
- Use the `inject()` function instead of constructor injection
+11
View File
@@ -0,0 +1,11 @@
{
"mcpServers": {
"angular-cli": {
"command": "npx",
"args": ["-y", "@angular/cli", "mcp"]
}
},
"ui": {
"showLineNumbers": false
}
}
+44
View File
@@ -0,0 +1,44 @@
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
# Compiled output
/dist
/tmp
/out-tsc
/bazel-out
# Node
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/mcp.json
.history/*
# Miscellaneous
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
__screenshots__/
# System files
.DS_Store
Thumbs.db
+5
View File
@@ -0,0 +1,5 @@
{
"plugins": {
"@tailwindcss/postcss": {}
}
}
+12
View File
@@ -0,0 +1,12 @@
{
"printWidth": 100,
"singleQuote": true,
"overrides": [
{
"files": "*.html",
"options": {
"parser": "angular"
}
}
]
}
+4
View File
@@ -0,0 +1,4 @@
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
"recommendations": ["angular.ng-template"]
}
+20
View File
@@ -0,0 +1,20 @@
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "ng serve",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: start",
"url": "http://localhost:4200/"
},
{
"name": "ng test",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: test",
"url": "http://localhost:9876/debug.html"
}
]
}
+42
View File
@@ -0,0 +1,42 @@
{
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "start",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "Changes detected"
},
"endsPattern": {
"regexp": "bundle generation (complete|failed)"
}
}
}
},
{
"type": "npm",
"script": "test",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "Changes detected"
},
"endsPattern": {
"regexp": "bundle generation (complete|failed)"
}
}
}
}
]
}
+64
View File
@@ -0,0 +1,64 @@
# Carparkvalidation
https://www.youtube.com/watch?v=KpNzBU4fNdU
# install AI google
npm install -g @google/gemini-cli
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 22.1.6.
## Development server
To start a local development server, run:
```bash
ng serve
```
Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
## Code scaffolding
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
```bash
ng generate component component-name
```
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
```bash
ng generate --help
```
## Building
To build the project run:
```bash
ng build
```
This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
## Running unit tests
To execute unit tests with the [Vitest](https://vitest.dev/) test runner, use the following command:
```bash
ng test
```
## Running end-to-end tests
For end-to-end (e2e) testing, run:
```bash
ng e2e
```
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
## Additional Resources
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
+73
View File
@@ -0,0 +1,73 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"cli": {
"packageManager": "npm"
},
"newProjectRoot": "projects",
"projects": {
"carparkvalidation": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular/build:application",
"options": {
"browser": "src/main.ts",
"tsConfig": "tsconfig.app.json",
"assets": [
{
"glob": "**/*",
"input": "public"
}
],
"styles": [
"src/styles.css"
]
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kB",
"maximumError": "1MB"
},
{
"type": "anyComponentStyle",
"maximumWarning": "4kB",
"maximumError": "8kB"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular/build:dev-server",
"configurations": {
"production": {
"buildTarget": "carparkvalidation:build:production"
},
"development": {
"buildTarget": "carparkvalidation:build:development"
}
},
"defaultConfiguration": "development"
},
"test": {
"builder": "@angular/build:unit-test"
}
}
}
}
}
+8582
View File
File diff suppressed because it is too large Load Diff
+40
View File
@@ -0,0 +1,40 @@
{
"name": "carparkvalidation",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"packageManager": "npm@11.12.1",
"dependencies": {
"@angular/common": "^22.1.0",
"@angular/compiler": "^22.1.0",
"@angular/core": "^22.1.0",
"@angular/forms": "^22.1.0",
"@angular/platform-browser": "^22.1.0",
"@angular/router": "^22.1.0",
"@google/generative-ai": "^0.24.1",
"@primeicons/angular": "^8.0.1",
"@primeuix/themes": "^3.0.1",
"moment": "^2.31.0",
"primeng": "^22.1.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0"
},
"devDependencies": {
"@angular/build": "^22.1.6",
"@angular/cli": "^22.1.6",
"@angular/compiler-cli": "^22.1.0",
"@tailwindcss/postcss": "^4.1.12",
"jsdom": "^28.0.0",
"postcss": "^8.5.3",
"prettier": "^3.8.1",
"tailwindcss": "^4.1.12",
"typescript": "~6.0.2",
"vitest": "^4.0.8"
}
}
+10
View File
@@ -0,0 +1,10 @@
{
"baseUrl4": "http://localhost:5100",
"baseUrl": "http://nephmdb-sql007/CarParkValidationAPI",
"loginUrl": "api/login",
"updatePersonUrl": "api/updatePerson",
"getAllUrl": "api/v1/Users/GetAllUsers",
"authenticateUrl": "api/v1/Users/Authenticate",
"validationPoint": "api/v1/ValidationPoint",
"adminEmail": "NBMLHD-parking@health.nsw.gov.au"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

@@ -0,0 +1,12 @@
table {
width: 100%;
}
.mat-form-field {
font-size: 14px;
width: 100%;
}
td.mat-column-edit, .mat-column-delete {
width: 35px;
padding-right: 2px;
}
@@ -0,0 +1,56 @@
<div class="edit-content ml-6">
<h3>Application Administrators</h3>
<a class="p-ripple p-button p-component flex justify-self-end mb-2" [routerLink]='["/adminuser", -1]' [queryParams]="{returnUrl:'/home/adminuser'}">
Add User
</a>
<div class="mb-3 flex justify-end">
<p-iconfield iconPosition="left">
<p-inputicon>
<svg data-p-icon="search" ></svg>
</p-inputicon>
<input pInputText pSize="small" type="text" (input)="dt.filterGlobal($event.target.value, 'contains')" placeholder="Keyword Search" />
</p-iconfield>
</div>
<p-table #dt [value]="dataSource()" rowHover="true" dataKey="id"
[rows]="25" [rowsPerPageOptions]="[ 25, 50,100]" [paginator]="true"
[globalFilterFields]="['stafflinkNo', 'name', 'roleType', 'validationPoint']" >
<ng-template #header>
<tr>
<th>Stafflink Id</th>
<th>Name</th>
<th>Role</th>
<th>Validation Point</th>
<th>Active</th>
<th>Edit</th>
</tr>
</ng-template>
<ng-template #body let-item>
<tr>
<td>{{ item.stafflinkNo }}</td>
<td>{{ item.name }}</td>
<td>{{ item.roleType }}</td>
<td>{{ item.validationPoint }}</td>
<td>
@if(item.active == true) {
<svg data-p-icon="check" color="green"></svg>
}
@else {
<svg data-p-icon="times" color="red"></svg>
}
</td>
<td>
<button pButton (click)="showEdit(item)">
<svg data-p-icon="pencil"></svg>
</button>
</td>
</tr>
</ng-template>
</p-table>
</div>
@@ -0,0 +1,96 @@
import { Component, OnInit, signal, OnDestroy } from '@angular/core';
import { AdminUserView } from '../models';
import { take } from 'rxjs/operators';
import { Subscription } from 'rxjs';
import { Router, RouterModule } from '@angular/router';
import { AdminUserService } from './adminuser.service';
import { MessageService } from 'primeng/api';
import { TableModule } from 'primeng/table';
import { Check } from '@primeicons/angular/check';
import { Times } from '@primeicons/angular/times';
import { Pencil } from '@primeicons/angular/pencil';
import { Search } from '@primeicons/angular/search';
import { IconFieldModule } from 'primeng/iconfield';
import { InputIconModule } from 'primeng/inputicon';
import { InputTextModule } from 'primeng/inputtext';
@Component({
selector: 'adminuser-list',
templateUrl: './adminuser.component.html',
imports: [TableModule, RouterModule, Times, Check, Pencil, InputIconModule, IconFieldModule, Search, InputTextModule],
styleUrls: ['./adminuser.component.css']
})
export class AdminUserComponent implements OnInit, OnDestroy {
dataSource = signal<AdminUserView[]>([]);
private subscription: Subscription = new Subscription();
displayedColumns: string[] = ['stafflinkNo', 'name', 'roleType', 'validationPoint', 'active', 'edit'];
msg = "[AdminUser component]";
/*
private store: Store<appValidationState>
*/
constructor(
private adminUserService: AdminUserService,
private router: Router,
private messageService: MessageService,
) {
}
//KeyboardEvent
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
//this.dataSource.filter = filterValue.trim().toLowerCase();
}
ngOnInit(): void {
this.subscription.add(
this.adminUserService.loadAdminusers().subscribe(result => {
// console.log(this.msg + "onInit load Data", result);
this.dataSource.set(result.data);
}, error => {
console.log("error ", error);
})
);
/*
this.store.dispatch(validationActions.LoadValidationpoints());
this.store.pipe(select(validationSelector.getAllValidations)).subscribe(result => this.dataSource.data = result);
*/
}
showEdit(item: AdminUserView) {
console.log(this.msg + "on row click", item);
this.router.navigate(['/adminuser/' + item.id], { queryParams: { returnUrl: '/adminuser' } });
}
deleteItem(id: number): void {
this.adminUserService.deleteAdminuser(id)
.pipe(take(1))
.subscribe({
next: result => {
console.log(this.msg + " deleteItem success", result);
let data = this.dataSource();
let index: number = data.findIndex(d => d.id === id);
console.log(this.msg + "delete from datasource");
data.splice(index, 1)
this.dataSource.set(data);
},
error: e => console.error('error loading', e)
});
console.log(this.msg + "click button to delete");
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
@@ -0,0 +1,12 @@
table {
width: 100%;
}
.mat-form-field {
font-size: 14px;
width: 100%;
}
td.mat-column-edit, .mat-column-delete {
width: 35px;
padding-right: 2px;
}
@@ -0,0 +1,48 @@
<div class="edit-content">
<div class="title">
{{getEditText()}}
</div>
<form [formGroup]="adminuserForm" (ngSubmit)="onSubmit()" class="ml-10 flex flex-col gap-2">
<div class="flex flex-col">
<div>
<label class="flex w-full">Stafflink Number<strong class="app-require">*</strong></label>
<input pInputText formControlName="stafflinkNo" (blur)="searchUser()" maxlength="10" name="stafflinkno"
placeholder="Stafflink Number" #mystaffid>
</div>
<div>
<label class="flex w-full">Name</label>
<input pInputText formControlName="name" maxlength="100" name="name" placeholder="Name">
</div>
<div>
<label class="flex w-full">Role<strong class="app-require">*</strong></label>
<p-select formControlName="roleType" [options]="Roles()"
optionLabel="description" optionValue="categoryId"
>
</p-select>
</div>
<div>
<label class="flex w-full">Validation Point<strong class="app-require">*</strong></label>
<p-select formControlName="validationPointId" [options]="validationPoints()"
optionLabel="description" optionValue="id"
>
</p-select>
</div>
<div>
<label for="acheckbox" class="mr-2 text-sm">Active</label>
<p-checkbox formControlName="active" [binary]="true" inputId="acheckbox" size="small" />
</div>
</div>
<div class="flex justify-content-end mt-2">
<button type="submit" pButton class="mr-2" [disabled]="isFieldsChange">Submit</button>
<button type="button" pButton="" (click)="goBack()">Cancel</button>
</div>
</form>
<!--pre>{{ adminuserForm.value|json}}</pre-->
</div>
@@ -0,0 +1,203 @@
import { Component, inject, OnDestroy, OnInit, signal, ViewChild } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { FormGroup, Validators, ReactiveFormsModule, FormBuilder, FormControl } from '@angular/forms';
import { Subject, pipe, Subscription, single } from 'rxjs';
import { AdminUser, Lookup, userRole } from '../models';
import { LookupService, Utils } from '../shares';
import { AdminUserService } from './adminuser.service';
import { MessageService } from 'primeng/api';
import { InputTextModule } from 'primeng/inputtext';
import { SelectModule } from 'primeng/select';
import { ButtonModule } from 'primeng/button';
import { CheckboxModule } from 'primeng/checkbox';
@Component({
templateUrl: 'adminuser.edit.component.html',
imports: [InputTextModule, ButtonModule, ReactiveFormsModule, SelectModule, CheckboxModule],
selector: 'adminuser-edit',
styleUrls: ['adminuser.edit.component.css']
})
export class AdminUserEditComponent implements OnInit, OnDestroy {
returnUrl = '';
loginUser = '';
_id = -1;
Roles = signal<Lookup[]>([]);
validationPoints = signal<Lookup[]>([]);
msg = "[adminUser Component] ";
//for focus input
// @ViewChild('mystaffid') mystaffNo!: MatInput;
isChange = true; // disable use false//true for not disable. make sure it true is disable button.
private subscription: Subscription = new Subscription();
subChanged$ = new Subject<boolean>();
private formBuilder = inject(FormBuilder);
private adminUserService = inject(AdminUserService);
private messageService = inject(MessageService);
private lookupService = inject(LookupService);
adminuserForm = this.formBuilder.group({
id: [0], //Validators.required
stafflinkNo: [''], //Validators.required
name: [''], //Validators.required
addedBy: [''], //Validators.required
addedOn: new FormControl<Date | null>(null), //Validators.required
active: [false], //Validators.required
roleType: [0, Validators.required],
validationPointId: [0, Validators.required]
});
constructor(
private router: Router, private route: ActivatedRoute,
) {
const roles = [];
let item: Lookup = { id: userRole.Admin, categoryId: userRole.Admin, description: 'Admin' };
roles.push(item);
item = { id: userRole.Normal, categoryId: userRole.Normal, description: 'Normal' };
roles.push(item);
this.Roles.set(roles);
}
loadData(id: number): void {
this.subscription.add(
this.lookupService.loadValidationPoint()
.subscribe({
next: x => {
this.validationPoints.set(x.data);
if (id > 0) {
this.subscription.add(
this.adminUserService.loadAdminuserById(id)
.subscribe({
next: x => this.assignValue(x.data),
error: e => console.error("error ", e.message)
}));
}
},
error: e => console.error("error ", e)
}
));
}
ngOnInit(): void {
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/adminuser';
const id = Number(this.route.snapshot.paramMap.get('id'));
// now load thing up
const user = Utils.getCurrentUser();
// console.log(this.msg + "current login user ", user);
if (user.username === '')
alert("you are not login.");
else
this.loginUser = user.firstName;
this._id = id;
//console.log(this.msg + " " + id );
this.subscription.add(this.adminuserForm.valueChanges.subscribe(x => this.isChange = false));
this.subscription.add(this.subChanged$.subscribe(x => this.isChange = x));
this.loadData(id);
}
getEditText(): string {
if (this._id > 0)
return "Edit Admin User";
else
return "New Admin User";
}
// this for disable submit button
get isFieldsChange() {
const chan = this.isChange || !this.adminuserForm.valid; // this disable so need true valid = true not
//console.log(this.msg + 'is fields change', chan);
return chan;
}
searchUser(): void {
const staffid = this.adminuserForm.controls["stafflinkNo"].value ?? '';
// console.log(this.msg + " the staffid is ", staffid);
if (staffid != '') {
//this.form.controls['your form control name'].value
this.adminUserService.getStaffLinkId(staffid).subscribe(
{
next: x => {
//console.log(this.msg + " this is stafflink no ", x);
// now get current user.
if (x.data) {
//this.error = true;
const fname = x.data.firstName + " " + x.data.lastName;
this.adminuserForm.patchValue({ name: fname, addedBy: this.loginUser });
}
else {
this.messageService.add({ severity: 'error', summary: 'Error', detail: "can not find stafflinkNo:" + staffid });
// this.adminuserForm.patchValue({name:x.data.firstName + " " + x.data.lastName
}
},
error: e => {
console.log("error ", e);
}
});
}
else {
this.messageService.add({ severity: 'error', summary: 'Error', detail: "please enter staff link no" });
}
}
assignValue(adminuser: AdminUser): void {
this.adminuserForm.patchValue({
id: adminuser.id,
stafflinkNo: adminuser.stafflinkNo,
name: adminuser.name,
addedBy: adminuser.addedBy,
addedOn: adminuser.addedOn,
active: adminuser.active,
roleType: adminuser.roleType,
validationPointId: adminuser.validationPointId
});
// disable use false//true for not disable.
this.subChanged$.next(true);
}
// convenience getter for easy access in form fields
get f() { return this.adminuserForm.controls; }
onSubmit(): void {
// if form valid then go save
//make sure
const okToSave = this.adminuserForm.valid;
if (okToSave) {
let adminuserValue = this.adminuserForm.value;
let adminuser: AdminUser = {
id: adminuserValue.id ?? -1,
stafflinkNo: adminuserValue.stafflinkNo ?? '',
name: adminuserValue.name ?? '',
addedBy: adminuserValue.addedBy ?? '',
addedOn: new Date(),
active: adminuserValue.active ?? false,
roleType: adminuserValue.roleType ?? 0,
validationPointId: adminuserValue.validationPointId ?? 0,
};
this.subscription.add(
this.adminUserService.saveAdminuser(adminuser).subscribe(x => {
if (x.statusCode >= 1) {
this.messageService.add({ severity: 'success', summary: 'Success', detail: "Save is OK" });
this.router.navigate([this.returnUrl]);
}
else {
this.messageService.add({ severity: 'error', summary: 'Error', detail: "Fail to save" });
}
},
error => {
console.log("error ", error);
}
)
);
}
}
goBack(): void {
console.log("the return url", this.returnUrl);
this.router.navigate([this.returnUrl]);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
@@ -0,0 +1,51 @@
import { Injectable, Inject } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AdminUser, AdminUserView, ResultModel,ConfigureUrl,User } from '../models';
import { AppSettingService } from '../shares';
@Injectable({ providedIn: 'root' })
export class AdminUserService {
constructor(private http: HttpClient,
private appSetting :AppSettingService
) {}
loadAdminusers(): Observable<ResultModel<AdminUserView[]>> {
let config = { headers : { 'Content-Type': 'application/json' } };
//const baseUrl = ConfigureUrl.baseUrl + "/"+ ConfigureUrl.adminUserUrl;
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.adminUserUrl;
return this.http.get<ResultModel<AdminUserView[]>>(baseUrl);
}
getStaffLinkId(staffid:string) :Observable<ResultModel<User>>{
const userUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.userByStaffIdUrl;
let params = new HttpParams().set("stafflinkNo", ""+staffid);
let headers = new HttpHeaders().set('Content-Type', 'application/json');
let options = {
headers: headers,
params: params
};
return this.http.get<ResultModel<User>>(userUrl, options);
}
loadAdminuserById(id:number): Observable<ResultModel<AdminUser>> {
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.adminUserUrl;
let params = new HttpParams().set("id", ""+id);
let headers = new HttpHeaders().set('Content-Type', 'application/json');
let options = {
headers: headers,
params: params
};
//return this.http.get<AdminUser>(this.baseUrl + 'api/Adminuser/LoadAdminuserById',options);
return this.http.get<ResultModel<AdminUser>>(baseUrl + "/" + id);
}
saveAdminuser(jsData:AdminUser): Observable<ResultModel<number>> { //insert Adminuser
let config = { headers : { 'Content-Type': 'application/json' } };
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.adminUserUrl;
return this.http.post<ResultModel<number>>(baseUrl, jsData, config);
}
deleteAdminuser(id:number): Observable<ResultModel<number>>{
const baseUrl = this.appSetting.appSetting.baseUrl + "/"+ ConfigureUrl.adminUserUrl;
let config = { headers : { 'Content-Type': 'application/json' } };
return this.http.delete<ResultModel<number>>(baseUrl + "/" + id);
}
}
+4
View File
@@ -0,0 +1,4 @@
export * from './adminuser.component';
export * from './adminuser.edit.component';
export * from './adminuser.service';
+48
View File
@@ -0,0 +1,48 @@
import { ApplicationConfig, inject, provideAppInitializer, provideBrowserGlobalErrorListeners } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { PrimeNG, providePrimeNG } from 'primeng/config';
import { ConfirmationService, MessageService } from 'primeng/api';
import { provideHttpClient, withInterceptors, withXhr } from '@angular/common/http';
import { AppSettingService, ErrorInterceptor, initializeApp, JwtInterceptor } from './shares';
import MyPreset from './mytheme_aura';
export const appConfig: ApplicationConfig = {
providers: [
MessageService,
ConfirmationService,
provideAppInitializer(() => {
const primeNG = inject(PrimeNG);
const appSettingService = inject(AppSettingService);
const loadAppSetting = initializeApp();
// Return the promise chain so Angular blocks app loading until the request completes
return loadAppSetting().then((result) => {
// Read the setting directly from the populated service instance
const settings = appSettingService.appSetting;
console.log('Loaded app settings:', settings, result);
const licenseKey = settings?.primeNGLicense || '';
console.log("primeng license", licenseKey);
// Apply configuration to PrimeNG
primeNG.setConfig({
license: licenseKey,
theme: {
preset: MyPreset,
options: {
cssLayer: {
name: 'primeng',
order: 'theme, base, primeng'
}
}
}
});
});
}),
provideHttpClient(withXhr(), withInterceptors([JwtInterceptor, ErrorInterceptor])),
provideBrowserGlobalErrorListeners(),
provideRouter(routes)
]
};
View File
+6
View File
@@ -0,0 +1,6 @@
@if (isAuth() == true) {
<app-nav-toolbar ></app-nav-toolbar>
}
<router-outlet />
<p-confirmdialog></p-confirmdialog>
<p-toast></p-toast>
+28
View File
@@ -0,0 +1,28 @@
import { Routes } from '@angular/router';
import { AuthGuard } from './route-guard';
import { AdminUserComponent, AdminUserEditComponent } from './adminuser';
import { LoginComponent } from './login';
import { ConcessionTypeComponent, ConcessiontypeEditComponent } from './concessiontype';
import { ValidationPointComponent, ValidationpointEditComponent } from './validationPoint';
import { ConcessionValidationComponent, ConcessionValidationEditComponent } from './concessionValidation';
import { ConcessionvalidationReportComponent } from './concessionvalidationreport';
export const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'adminuser', component: AdminUserComponent, canActivate: [AuthGuard], data: { roleAllowed: 'Admin' } },
{ path: 'adminuser/:id', component: AdminUserEditComponent, canActivate: [AuthGuard], data: { roleAllowed: 'Admin' } },
{ path: 'concessiontype', component: ConcessionTypeComponent, canActivate: [AuthGuard], data: { roleAllowed: 'Admin' } },
{ path: 'concessiontype/:id', component: ConcessiontypeEditComponent, canActivate: [AuthGuard], data: { roleAllowed: 'Admin' } },
{ path: 'validationpoint', component: ValidationPointComponent, canActivate: [AuthGuard], data: { roleAllowed: 'Admin' } },
{ path: 'validationpoint/:id', component: ValidationpointEditComponent, canActivate: [AuthGuard], data: { roleAllowed: 'Admin' } },
{ path: 'concessionvalidation', component: ConcessionValidationComponent, canActivate: [AuthGuard] },
{ path: 'concessionvalidation/:id', component: ConcessionValidationEditComponent, canActivate: [AuthGuard] },
{ path: 'app-concessionvalidation-report', component: ConcessionvalidationReportComponent, canActivate: [AuthGuard], data: { roleAllowed: 'Admin' } },
{ path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: '**', redirectTo: 'login' },
];
+19
View File
@@ -0,0 +1,19 @@
import { Component, computed, inject, signal, viewChild } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { ConfirmDialogModule } from 'primeng/confirmdialog';
import { ToastModule } from 'primeng/toast';
import { NavToolarComponent } from './nav-toolbar/nav-toolbar.component';
import { AuthenticationService } from './user-services';
@Component({
imports: [RouterOutlet, ConfirmDialogModule, ToastModule, NavToolarComponent],
selector: 'app-root',
styleUrl: './app.css',
templateUrl: './app.html',
})
export class App {
authService = inject(AuthenticationService);
protected readonly title = signal('carparkvalidation');
isAuth = computed(() => this.authService.authChange().firstName != '');
}
@@ -0,0 +1,12 @@
table {
width: 100%;
}
.mat-form-field {
font-size: 14px;
width: 100%;
}
td.mat-column-edit, .mat-column-delete {
width: 35px;
padding-right: 2px;
}
@@ -0,0 +1,99 @@
<div class="edit-content">
<h3>Concession Validation</h3>
@if (isAdmin) {
<div >
<div class="flex flex-row gap-2 w-full">
<label>Choose a from date</label>
<p-datepicker [(ngModel)]="fromDate" dateFormat="dd/mm/yy" />
<label>Choose a to date</label>
<p-datepicker [(ngModel)]="toDate" dateFormat="dd/mm/yy" />
<button pButton (click)="onLoad()" >
Load
</button>
</div>
</div>
}
<div class="addlink">
<a class="p-ripple p-button p-component flex justify-self-end mb-2" [routerLink]='["/concessionvalidation", 0]'
[queryParams]="{returnUrl:'/concessionvalidation'}"
(click)="setDate()">
Add Concession Validation
</a>
</div>
<p-table [value]="dataSource()" rowHover="true" dataKey="id"
[rows]="25" [rowsPerPageOptions]="[ 25, 50,100]" [paginator]="true">
<ng-template #header>
<tr>
<th >Date </th>
<th >Concession Type </th>
<th >Concession Card Number</th>
<th >Concession Holder Name</th>
<th >Validation Point </th>
<th>Expiry date checked</th>
@if(isAdmin) {
<th >Staff Name</th>
<th>Delete</th>
}
<th >Edit</th>
<!-- validateDate Column -->
</ng-template>
<ng-template #body let-element>
<tr>
<td > {{element.validateDate | date: 'dd/MM/yyyy HH:mm'}} </td>
<td > {{element.concessionType}} </td>
<td > {{element.concessionCard}} </td>
<td > {{element.concessionHolder}} </td>
<td > {{element.validationPoint}} </td>
<td >
@if (element.concessionExpiry == true)
{
<svg data-p-icon="check" color="green"></svg>
}
@else {
<svg data-p-icon="times" color="red"></svg>
}
</td>
<!-- staffFirstName Column -->
@if(isAdmin) {
<td >{{element.staffFirstName}} {{element.staffLastName}} </td>
<td >
<button pButton (click)='deleteItem(element.id)'>
<svg data-p-icon="times"></svg>
</button>
</td>
}
<td>
<button pButton (click)="showEdit(element)" >
<svg data-p-icon="pencil"></svg>
</button>
</td>
</ng-template>
</p-table>
@@ -0,0 +1,149 @@
import { Component, OnInit, OnDestroy, signal, inject } from '@angular/core';
import { ConcessionValidation } from '../models';
import { Utils } from '../shares';
import { Router, RouterModule } from '@angular/router';
import { Subscription } from 'rxjs';
import { ConcessionValidationService } from './concessionvalidation.service';
import { DatePickerModule } from 'primeng/datepicker';
import { ConfirmationService, MessageService } from 'primeng/api';
import { TableModule } from 'primeng/table';
import { ButtonModule } from 'primeng/button';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Pencil } from '@primeicons/angular/pencil';
import { Times } from '@primeicons/angular/times';
import { Check } from '@primeicons/angular/check';
@Component({
selector: 'concessionvalidation-list',
templateUrl: './concessionvalidation.component.html',
imports: [TableModule, ButtonModule, CommonModule, FormsModule, Check, Times, Pencil, DatePickerModule, RouterModule],
styleUrls: ['./concessionvalidation.component.css']
})
export class ConcessionValidationComponent implements OnInit, OnDestroy {
private concessionValidationService = inject(ConcessionValidationService);
private router = inject(Router);
private messageService = inject(MessageService);
private confirmationService = inject(ConfirmationService);
dataSource = signal<ConcessionValidation[]>([]);
isAdmin = false;
isAllowFilter = true;
fromDate = new Date();
toDate = new Date();
username = '';
private subscription: Subscription = new Subscription();
msg = "[ConcessionValidation component]";
/*
private store: Store<appValidationState>
*/
constructor(
) {
this.isAdmin = Utils.getIsAdmin();
}
//KeyboardEvent
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
// this.dataSource.filter = filterValue.trim().toLowerCase();
}
ngOnInit(): void {
const user = Utils.getCurrentUser();
// console.log(this.msg + "current login user ", user);
if (user.username === "") {
user.username = "60249360";
this.messageService.add({ severity: 'error', summary: 'Error', detail: "you are not login! using my number " + user.username });
}
this.username = user.username;
if (this.isAdmin)
this.username = '';
const dateRange = this.concessionValidationService.getDate();
// console.log("the date range for now ", dateRange);
if (dateRange.fromDate != '')
this.fromDate = dateRange.fromDate;
if (dateRange.toDate != '')
this.toDate = dateRange.toDate;
this.onLoad();
/*
this.store.dispatch(validationActions.LoadValidationpoints());
this.store.pipe(select(validationSelector.getAllValidations)).subscribe(result => this.dataSource.data = result);
*/
}
onLoad(): void {
const cDate = this.fromDate;
const tDate = this.toDate;
this.subscription.add(
this.concessionValidationService.loadConcessionvalidationByStaffId(this.username, cDate, tDate)
.subscribe({
next: result => {
//console.log(this.msg + "onInit load Data by staffId "+ this.username, result);
this.dataSource.set(result.data);
}, error: e => console.error("error in loading concession validation", e)
})
);
//this.dataList$ = this.concessionValidationService.loadConcessionvalidationByStaffId(this.username, cDate, tDate)
// .pipe(catchError(err => {this.toastr.error(err.message); return EMPTY}));
}
setDate(): void {
this.concessionValidationService.setDateRange(this.fromDate, this.toDate);
}
showEdit(item: ConcessionValidation) {
// console.log(this.msg + "on row click", item);
this.setDate();
this.router.navigate(['/concessionvalidation/' + item.id], { queryParams: { returnUrl: '/concessionvalidation' } });
}
deleteItem(id: number): void {
const message = "Are you sure you want to delete this?";
const title = " Confirmation";
this.confirmationService.confirm({
message: message,
header: title,
icon: 'pi pi-exclamation-triangle',
accept: () => {
this.concessionValidationService.deleteConcessionvalidation(id)
.subscribe(result => {
console.log(this.msg + " deleteItem success", result);
let data = this.dataSource();
let index: number = data.findIndex(d => d.id === id);
console.log(this.msg + "delete from datasource");
data.splice(index, 1)
this.dataSource.set(data);
},
error => {
console.log("error ", error);
}
);
},
reject: () => {
console.log(this.msg + "click on No to delete");
}
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
@@ -0,0 +1,12 @@
table {
width: 100%;
}
.mat-form-field {
font-size: 14px;
width: 100%;
}
td.mat-column-edit, .mat-column-delete {
width: 35px;
padding-right: 2px;
}
@@ -0,0 +1,68 @@
<div class="p-10">
<div class="title">
{{getEditText()}}
</div>
<form [formGroup]="concessionvalidationForm" (ngSubmit)="onSubmit()">
<div class="flex flex-col">
<div class="m-2">
<label class="flex w-full">Concession Card Number<strong class="app-require">*</strong></label>
<input pInputText formControlName="concessionCard" maxlength="60" name="concessionCard" (blur)="searchCard()"
placeholder="Concession Card Number" required>
</div>
@if(isAdmin) {
<div class="m-2">
<label for="time" class="flex w-full">Current Date</label>
<p-datepicker formControlName="validateDate" [showTime]="true" inputId="time"
dateFormat="dd/mm/yy"></p-datepicker>
</div>
}
<!--end-->
<div class="m-2">
<label class="flex w-full">Concession Type<strong class="app-require">*</strong></label>
<p-select formControlName="concessionTypeId"
[options]="concessionTypes()"
optionLabel="description" optionValue="id">
</p-select>
</div>
<div class="m-2">
<label class="flex w-full">Concession Holder Name<strong class="app-require">*</strong></label>
<input pInputText formControlName="concessionHolder" maxlength="100" name=""
placeholder="Concession Holder Name" >
</div>
<div class="m-2">
<label class="flex w-full"> Expiry date checked <strong
class="app-require">*</strong> </label>
<p-checkbox formControlName="concessionExpiry" [binary]="true"></p-checkbox>
@if(isAdmin) {
<div >
<label class="flex w-full">Validation Point<strong class="app-require">*</strong></label>
<p-select formControlName="validationPointId" [options]="validationPoints()" optionLabel="description" optionValue="id">
</p-select>
</div>
}
</div>
</div>
<div class="flex justify-content-end mt-2">
<button class="mr-2" type="submit" pButton [disabled]="isFieldsChange">Submit</button>
<button type="button" pButton (click)="goBack()">Cancel</button>
</div>
</form>
<!--pre>{{ concessionvalidationForm.value|json}}</pre-->
</div>
@@ -0,0 +1,296 @@
import { Component, inject, OnDestroy, OnInit, signal, ViewChild } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { FormGroup, Validators, ReactiveFormsModule, FormBuilder, FormControl } from '@angular/forms';
import { ConcessionValidation, Lookup, ResultModel } from '../models';
import { Subject, Subscription } from 'rxjs';
import { LookupService } from '../shares';
import { ConcessionValidationService } from './concessionvalidation.service';
import { Utils } from '../shares';
import moment from 'moment';
import { ConfirmationService, MessageService } from 'primeng/api';
import { ButtonModule } from 'primeng/button';
import { InputTextModule } from 'primeng/inputtext';
import { CheckboxModule } from 'primeng/checkbox';
import { DatePickerModule } from 'primeng/datepicker';
import { SelectModule } from 'primeng/select';
@Component({
templateUrl: 'concessionvalidation.edit.component.html',
selector: 'concessionvalidation-edit',
imports: [ButtonModule, InputTextModule, CheckboxModule, DatePickerModule,
SelectModule, ReactiveFormsModule],
styleUrls: ['concessionvalidation.edit.component.css']
})
export class ConcessionValidationEditComponent implements OnInit, OnDestroy {
returnUrl = "";
private formBuilder = inject(FormBuilder);
private lookupService = inject(LookupService);
private concessionValidationService = inject(ConcessionValidationService);
private router = inject(Router);
private confirmationService = inject(ConfirmationService);
private messageService = inject(MessageService);
private route = inject(ActivatedRoute);
msg = "[concessionvalidation edit Component] "
isChange = true; // disable use false//true for not disable. make sure it true is disable button.
subChanged$ = new Subject<boolean>();
_id = -1;
isAdmin = false;
concessionTypes = signal<Lookup[]>([]);
validationPoints = signal<Lookup[]>([]);
private subscription: Subscription = new Subscription();
concessionvalidationForm = this.formBuilder.group({
id: [0], //Validators.required
validateDate: new FormControl<Date | null>(null), //Validators.required
concessionCard: ['', Validators.required],
concessionHolder: ['', Validators.required],
concessionExpiry: [false, Validators.required], //Validators.required
concessionTypeId: [-1, Validators.min(1)],
stafflinkNo: [''], //Validators.required
validationPointId: [-1, Validators.min(1)],
validationPoint: [''], //Validators.required
staffFirstName: [''], //Validators.required
staffLastName: [''], //Validators.required
staffEmail: [''], //Validators.required
active: [false], //Validators.required
});
constructor() {
/*
this.concessionTypes = [];
let item:Lookup = {id:1,categoryId:0, description:'Health Care Card'};
this.concessionTypes.push(item);
item = {id:3,categoryId:1, description:'Gold Veterans Affairs Card'};
this.concessionTypes.push(item);
item = {id:3,categoryId:1, description:'Pensioner Concession Card'};
this.concessionTypes.push(item);
*/
}
searchCard(): void {
const cardNo = this.concessionvalidationForm.controls["concessionCard"].value ?? '';
if (cardNo != "") {
const card$ = this.concessionValidationService.loadConcessionvalidationByCard(cardNo);
this.subscription.add(card$.subscribe({
next: x => {
if (x.statusCode == 1) {
const data = x.data;
this.concessionvalidationForm.patchValue({
concessionHolder: data.concessionHolder,
concessionTypeId: data.concessionTypeId,
});
}
}
})
);
}
}
ngOnInit(): void {
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
const id = Number(this.route.snapshot.paramMap.get('id'));
// now load thing up
this._id = id;
this.isAdmin = Utils.getIsAdmin();
this.subscription.add(this.lookupService.loadConcessionType().subscribe({
next: x => this.concessionTypes.set(x.data),
error: e => console.error("error loading concession type", e)
}
));
this.subscription.add(
this.lookupService.loadValidationPoint().subscribe({
next: x => this.validationPoints.set(x.data),
error: e => console.error("error validation Point", e)
})
);
this.subscription.add(this.concessionvalidationForm.valueChanges.subscribe(x => this.isChange = false));
this.subscription.add(this.subChanged$.subscribe(x => this.isChange = x));
const user = Utils.getCurrentUser();
console.log(this.msg + "current login user ", user);
if (user.username === "") {
user.username = "60249360";
this.messageService.add({ severity: 'error', summary: 'Error', detail: "you are not login! using my number " + user.username });
}
if (this._id < 1) {
this.concessionvalidationForm.patchValue({
validateDate: new Date(),
stafflinkNo: user.username,
staffFirstName: user.firstName,
staffLastName: user.lastName,
staffEmail: user.email,
validationPointId: user.validationPointId,
active: true
});
}
else {
this.subscription.add(
this.concessionValidationService.loadConcessionvalidationById(id)
.subscribe({
next: x => this.assignValue(x.data),
error: e => console.log(e.message)
}));
// console.log(this.msg + " load from db"+id);
}
}
get isFieldsChange() {
const chan = this.isChange || !this.concessionvalidationForm.valid; // this disable so need true valid = true not
const fvalid = this.concessionvalidationForm.valid;
// console.log(this.msg + "is fields change is valid: " + fvalid , chan,);
return chan;
}
getEditText(): string {
if (this._id > 0)
return "Edit Concession Validation";
else
return "New Concession Validation";
}
onChangeValidation($event: Event) {
//$event.target.value
//this.selectedCar = (event.target as HTMLSelectElement).value;
var val = ($event.target as HTMLSelectElement).value;
// console.log("the log for val " , val);
}
assignValue(concessionvalidation: ConcessionValidation): void {
this.concessionvalidationForm.patchValue({
id: concessionvalidation.id,
validateDate: moment(concessionvalidation.validateDate).toDate(),
concessionCard: concessionvalidation.concessionCard,
concessionHolder: concessionvalidation.concessionHolder,
concessionExpiry: concessionvalidation.concessionExpiry,
concessionTypeId: concessionvalidation.concessionTypeId,
stafflinkNo: concessionvalidation.stafflinkNo,
staffFirstName: concessionvalidation.staffFirstName,
staffLastName: concessionvalidation.staffLastName,
staffEmail: concessionvalidation.staffEmail,
validationPointId: concessionvalidation.validationPointId,
active: concessionvalidation.active,
});
// disable use false//true for not disable.
this.subChanged$.next(true);
}
// convenience getter for easy access in form fields
get f() { return this.concessionvalidationForm.controls; }
onSubmit(): void {
const OkToSave = this.concessionvalidationForm.valid;
const checkActive = this.concessionvalidationForm.value.concessionExpiry ?? false;
console.log("onsubmit value", checkActive, this.concessionvalidationForm.value);
if (checkActive == false) {
this.messageService.add({ severity: 'error', summary: 'Check Concession Expiry', detail: 'Not Check Concession Expiry' });
return;
}
if (OkToSave) {
const concessionvalidationValue = this.concessionvalidationForm.value;
const concessionvalidation: ConcessionValidation = {
id: concessionvalidationValue.id ?? 0,
validateDate: moment(concessionvalidationValue.validateDate).toDate(),
concessionCard: concessionvalidationValue.concessionCard ?? '',
concessionHolder: concessionvalidationValue.concessionHolder ?? '',
concessionExpiry: concessionvalidationValue.concessionExpiry ?? false,
concessionTypeId: concessionvalidationValue.concessionTypeId ?? 0,
stafflinkNo: concessionvalidationValue.stafflinkNo ?? '',
staffFirstName: concessionvalidationValue.staffFirstName ?? '',
staffLastName: concessionvalidationValue.staffLastName ?? '',
staffEmail: concessionvalidationValue.staffEmail ?? '',
validationPointId: concessionvalidationValue.validationPointId ?? 0,
active: concessionvalidationValue.active ?? false,
};
// console.log(this.msg + "this is OKTOsave", concessionvalidation);
//if edit mode just save it don't check
if (concessionvalidation.id > 0) {
this.saveConcession(concessionvalidation);
}
else {
//check first only if new
this.checkAndSave(concessionvalidation);
}
}
else {
// console.log(this.msg + "this is NOT OKTOsave");
this.messageService.add({ severity: 'error', summary: 'Error', detail: "please fill in the required fields" });
}
}
checkAndSave(concessionvalidation: ConcessionValidation): void {
const currentDate = moment(concessionvalidation.validateDate).format("YYYY-MM-DD");
const id = concessionvalidation.id;
this.subscription.add(
this.concessionValidationService.checkConcessionValidationByStaff(concessionvalidation.stafflinkNo,
concessionvalidation.concessionCard, currentDate, id)
.subscribe(x => {
let okTo = true;
if (x.data < 0) {
const message = "This card was used earlier today. Is it Ok to continue?";
const title = "Alert";
this.confirmationService.confirm({
message: message,
header: 'Confirmation',
icon: 'pi pi-exclamation-triangle',
accept: () => {
this.saveConcession(concessionvalidation);
},
reject: () => {
this.router.navigate([this.returnUrl]);
}
});
}
else {
this.saveConcession(concessionvalidation);
}
})
);
}
saveConcession(concessionvalidation: ConcessionValidation): void {
//console.log(this.msg + " Save Concession validation to server");
this.subscription.add(
this.concessionValidationService.saveConcessionvalidation(concessionvalidation)
.subscribe({
next: x => {
if (x.statusCode >= 1) {
this.messageService.add({ severity: 'success', summary: 'Success', detail: "Save is OK" });
this.router.navigate([this.returnUrl]);
}
else
this.messageService.add({ severity: 'error', summary: 'Fail to Save', detail: x.message });
}, error: e => {
const message = e || e.message;
this.messageService.add({ severity: 'error', summary: 'Fail to Save', detail: message });
console.log("error ", e);
}
}
));
}
goBack(): void {
this.router.navigate([this.returnUrl]);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
@@ -0,0 +1,102 @@
import { Injectable, Inject } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { ConcessionValidation, ResultModel, ConfigureUrl } from '../models';
import moment from 'moment';
import { AppSettingService } from '../shares';
@Injectable({ providedIn: 'root' })
export class ConcessionValidationService {
private dateRange: any;
constructor(private http: HttpClient,
private appSetting: AppSettingService
) {
this.dateRange = {};
this.dateRange.fromDate = '';
this.dateRange.toDate = '';
console.log("constructor concessionValidationService daterange", this.dateRange);
}
public setDateRange(fromDate: any, toDate: any) {
this.dateRange.fromDate = moment(fromDate).toDate();
this.dateRange.toDate = moment(toDate).toDate();
// console.log("concessionValidationService setdaterange", this.dateRange);
}
public getDate(): any {
// console.log("concessionValidationService getdaterange", this.dateRange);
return this.dateRange;
}
loadConcessionvalidations(): Observable<ResultModel<ConcessionValidation[]>> {
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.concessionValidationUrl;
let config = { headers: { 'Content-Type': 'application/json' } };
// console.log("the concession", baseUrl);
return this.http.get<ResultModel<ConcessionValidation[]>>(baseUrl);
}
loadConcessionvalidationByStaffId(staffLinkId: string, fromDate: Date, toDate: Date): Observable<ResultModel<ConcessionValidation[]>> {
this.setDateRange(fromDate, toDate);
const strDate = moment(fromDate).format("YYYY-MM-DD");
const strtoDate = moment(toDate).format("YYYY-MM-DD");
const url = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.concessionValidationByIdUrl;
const params = new HttpParams().set("staffLinkNo", staffLinkId)
.set("fromDate", strDate)
.set("toDate", strtoDate);
const headers = new HttpHeaders().set('Content-Type', 'application/json');
const options = {
headers: headers,
params: params
};
//console.log("loadConcessionvalidationByStaffId url", url);
return this.http.get<ResultModel<ConcessionValidation[]>>(url, options);
}
loadConcessionvalidationById(id: number): Observable<ResultModel<ConcessionValidation>> {
let params = new HttpParams().set("id", "" + id);
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.concessionValidationUrl;
let headers = new HttpHeaders().set('Content-Type', 'application/json');
let options = {
headers: headers,
params: params
};
//return this.http.get<Concessionvalidation>(this.baseUrl + 'api/Concessionvalidation/LoadConcessionvalidationById',options);
return this.http.get<ResultModel<ConcessionValidation>>(baseUrl + "/" + id);
}
loadConcessionvalidationByCard(cardNo: string): Observable<ResultModel<ConcessionValidation>> {
const data = { cardNo };
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.concessionValidationUrl + "/GetConcessionCard";
/*
let params = new HttpParams().set("id", "" + id);
let headers = new HttpHeaders().set('Content-Type', 'application/json');
let options = {
headers: headers,
params: params
};
*/
//return this.http.get<Concessionvalidation>(this.baseUrl + 'api/Concessionvalidation/LoadConcessionvalidationById',options);
return this.http.post<ResultModel<ConcessionValidation>>(baseUrl, data);
}
checkConcessionValidationByStaff(staffLinkNo: string, concessionCard: string, currentDate: string, id: number): Observable<ResultModel<number>> {
let params = new HttpParams().set("staffLinkNo", staffLinkNo)
.set("concessionCard", concessionCard)
.set("currentDate", currentDate)
.set("id", "" + id);
let headers = new HttpHeaders().set('Content-Type', 'application/json');
let options = {
headers: headers,
params: params
};
const baseUrl = this.appSetting.appSetting.baseUrl;
const url = baseUrl + "/" + ConfigureUrl.CheckConcessionValidationByStaffUrl;
//return this.http.get<Concessionvalidation>(this.baseUrl + 'api/Concessionvalidation/LoadConcessionvalidationById',options);
return this.http.get<ResultModel<number>>(url, options);
}
saveConcessionvalidation(item: ConcessionValidation): Observable<ResultModel<number>> { //insert Concessionvalidation
let config = { headers: { 'Content-Type': 'application/json' } };
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.concessionValidationUrl;
return this.http.post<ResultModel<number>>(baseUrl, item, config);
}
deleteConcessionvalidation(Id: number): Observable<ResultModel<number>> {
let config = { headers: { 'Content-Type': 'application/json' } };
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.concessionValidationUrl;
return this.http.delete<ResultModel<number>>(baseUrl + "/" + Id);
}
}
@@ -0,0 +1,4 @@
export * from './concessionvalidation.component';
export * from './concessionvalidation.edit.component';
export * from './concessionvalidation.service';
@@ -0,0 +1,12 @@
table {
width: 100%;
}
.mat-form-field {
font-size: 14px;
width: 100%;
}
td.mat-column-edit, .mat-column-delete {
width: 35px;
padding-right: 2px;
}
@@ -0,0 +1,45 @@
<div class="edit-content">
<h3>Concession Type</h3>
<div class="addlink">
<a class="p-ripple p-button p-component flex justify-self-end mb-2" [routerLink]='["/concessiontype", -1]' [queryParams]="{returnUrl:'/concessiontype'}">
Add Concession Type
</a>
</div>
<p-table [value]="dataSource()" rowHover="true" dataKey="id"
[rows]="25" [rowsPerPageOptions]="[ 25, 50,100]" [paginator]="true">
<ng-template #header>
<tr>
<th>Description</th>
<th>Display</th>
<th>Active</th>
<th>Edit</th>
</tr>
</ng-template>
<ng-template #body let-item>
<tr>
<td>{{ item.description }}</td>
<td> {{item.display}}</td>
<td>
@if(item.active == true) {
<svg data-p-icon="check" color="green"></svg>
}
@else {
<svg data-p-icon="times" color="red"></svg>
}
</td>
<td>
<button pButton (click)="showEdit(item)">
<svg data-p-icon="pencil"></svg>
</button>
</td>
</tr>
</ng-template>
</p-table>
</div>
@@ -0,0 +1,99 @@
import { Component, OnInit, OnDestroy, signal, inject } from '@angular/core';
import { ConcessionTypeService } from './concessiontype.service';
import { ConcessionType } from '../models';
import { take } from 'rxjs/operators';
import { Router, RouterModule } from '@angular/router';
import { Subscription } from 'rxjs';
import { MessageService } from 'primeng/api';
import { ButtonModule } from 'primeng/button';
import { Pencil } from '@primeicons/angular/pencil';
import { TableModule } from 'primeng/table';
import { Check } from '@primeicons/angular/check';
import { Times } from '@primeicons/angular/times';
@Component({
selector: 'concessiontype-list',
templateUrl: './concessiontype.component.html',
imports: [ButtonModule, TableModule, RouterModule, Pencil, Check, Times],
styleUrls: ['./concessiontype.component.css']
})
export class ConcessionTypeComponent implements OnInit, OnDestroy {
private concessionTypeService = inject(ConcessionTypeService);
private messageService = inject(MessageService);
private router = inject(Router);
dataSource = signal<ConcessionType[]>([]);
private subscription: Subscription = new Subscription();
msg = "[concessionType.com]";
/*
private store: Store<appValidationState>
*/
constructor(
) {
}
/*
applyFilter($event:any) {
const filterValue = $event.target.value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}
*/
ngOnInit(): void {
this.subscription.add(
this.concessionTypeService.loadConcessiontypes().subscribe(
{
next: result => {
// console.log(this.msg + "onInit", result);
this.dataSource.set(result.data);
}, error: e => {
console.log("error ", e);
}
}
)
);
/*
this.store.dispatch(validationActions.LoadValidationpoints());
this.store.pipe(select(validationSelector.getAllValidations)).subscribe(result => this.dataSource.data = result);
*/
}
showEdit(item: ConcessionType) {
console.log(this.msg + "on row click", item);
this.router.navigate(['/concessiontype/' + item.id], { queryParams: { returnUrl: '/concessiontype' } });
}
deleteItem(id: number): void {
this.concessionTypeService.deleteConcessiontype(id)
.pipe(take(1))
.subscribe(result => {
// console.log(this.msg + " deleteItem success", result);
let data = this.dataSource();
let index: number = data.findIndex(d => d.id === id);
// console.log(this.msg + "delete from datasource");
data.splice(index, 1)
this.dataSource.set(data);
},
error => {
console.log("error ", error);
}
);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}

Some files were not shown because too many files have changed in this diff Show More