From f5b73de2c12560c3822f53a595df95c8e753777c Mon Sep 17 00:00:00 2001 From: Jason Sylvestre Date: Fri, 26 Sep 2025 08:17:47 -0700 Subject: [PATCH 1/6] Adds invoice type selection to teams Adds the ability to select allowed invoice types for teams, enabling control over payment methods. This change introduces a radio button selection in the team creation and settings edit views, allowing admins to specify whether a team can accept Credit Card payments, Recharge payments, or both. --- .../Controllers/SettingsController.cs | 84 ++++++++++--------- .../Controllers/TeamsController.cs | 17 ++-- .../TeamViewModels/BaseTeamViewModel.cs | 6 ++ src/Payments.Mvc/Views/Settings/Edit.cshtml | 29 ++++++- src/Payments.Mvc/Views/Teams/Create.cshtml | 27 +++++- 5 files changed, 110 insertions(+), 53 deletions(-) diff --git a/src/Payments.Mvc/Controllers/SettingsController.cs b/src/Payments.Mvc/Controllers/SettingsController.cs index e9aa605d..b7d30da3 100644 --- a/src/Payments.Mvc/Controllers/SettingsController.cs +++ b/src/Payments.Mvc/Controllers/SettingsController.cs @@ -63,15 +63,15 @@ public async Task Index() var model = new TeamDetailsModel { - Name = team.Name, - Slug = team.Slug, - ContactName = team.ContactName, - ContactEmail = team.ContactEmail, + Name = team.Name, + Slug = team.Slug, + ContactName = team.ContactName, + ContactEmail = team.ContactEmail, ContactPhoneNumber = team.ContactPhoneNumber, - ApiKey = userCanEdit ? team.ApiKey : "", - IsActive = team.IsActive, - UserCanEdit = userCanEdit, - WebHookApiKey = team.WebHookApiKey + ApiKey = userCanEdit ? team.ApiKey : "", + IsActive = team.IsActive, + UserCanEdit = userCanEdit, + WebHookApiKey = team.WebHookApiKey }; return View(model); @@ -91,13 +91,14 @@ public async Task Edit() var model = new EditTeamViewModel() { - Name = team.Name, - Slug = team.Slug, - ContactName = team.ContactName, - ContactEmail = team.ContactEmail, + Name = team.Name, + Slug = team.Slug, + ContactName = team.ContactName, + ContactEmail = team.ContactEmail, ContactPhoneNumber = team.ContactPhoneNumber, - IsActive = team.IsActive, - WebHookApiKey = team.WebHookApiKey + IsActive = team.IsActive, + WebHookApiKey = team.WebHookApiKey, + AllowedInvoiceType = team.AllowedInvoiceType }; return View(model); @@ -126,12 +127,13 @@ public async Task Edit(EditTeamViewModel model) return View(model); } - team.Name = model.Name; - team.Slug = model.Slug; - team.ContactName = model.ContactName; - team.ContactEmail = model.ContactEmail; + team.Name = model.Name; + team.Slug = model.Slug; + team.ContactName = model.ContactName; + team.ContactEmail = model.ContactEmail; team.ContactPhoneNumber = model.ContactPhoneNumber; - team.WebHookApiKey = model.WebHookApiKey; + team.WebHookApiKey = model.WebHookApiKey; + team.AllowedInvoiceType = model.AllowedInvoiceType; // only admins can change active if (User.IsInRole(ApplicationRoleCodes.Admin)) @@ -165,14 +167,14 @@ public async Task Roles() var model = new TeamDetailsModel { - Name = team.Name, - Slug = team.Slug, - ContactName = team.ContactName, - ContactEmail = team.ContactEmail, + Name = team.Name, + Slug = team.Slug, + ContactName = team.ContactName, + ContactEmail = team.ContactEmail, ContactPhoneNumber = team.ContactPhoneNumber, - IsActive = team.IsActive, - Permissions = permissions, - UserCanEdit = userCanEdit + IsActive = team.IsActive, + Permissions = permissions, + UserCanEdit = userCanEdit }; return View(model); @@ -246,10 +248,10 @@ public async Task CreatePermission(CreateTeamPermissionViewModel { var userToCreate = new User { - Email = user.Mail, - UserName = user.Mail, + Email = user.Mail, + UserName = user.Mail, CampusKerberos = user.Kerberos, - Name = user.FullName + Name = user.FullName }; var userPrincipal = new ClaimsPrincipal(); @@ -427,11 +429,11 @@ public async Task CreateWebHook(CreateWebHookViewModel model) // create webhook and add it var webHook = new WebHook() { - Team = team, - Url = model.Url, - ContentType = model.ContentType, - IsActive = model.IsActive, - TriggerOnPaid = model.TriggerOnPaid, + Team = team, + Url = model.Url, + ContentType = model.ContentType, + IsActive = model.IsActive, + TriggerOnPaid = model.TriggerOnPaid, TriggerOnReconcile = model.TriggerOnReconcile, }; @@ -460,9 +462,9 @@ public async Task EditWebHook(int id) var model = new EditWebHookViewModel() { - Id = webHook.Id, - Url = webHook.Url, - IsActive = webHook.IsActive, + Id = webHook.Id, + Url = webHook.Url, + IsActive = webHook.IsActive, TriggerOnPaid = webHook.TriggerOnPaid, }; @@ -494,10 +496,10 @@ public async Task EditWebHook(int id, EditWebHookViewModel model) } // update model - webHook.Url = model.Url; - webHook.ContentType = model.ContentType; - webHook.IsActive = model.IsActive; - webHook.TriggerOnPaid = model.TriggerOnPaid; + webHook.Url = model.Url; + webHook.ContentType = model.ContentType; + webHook.IsActive = model.IsActive; + webHook.TriggerOnPaid = model.TriggerOnPaid; webHook.TriggerOnReconcile = model.TriggerOnReconcile; await _context.SaveChangesAsync(); diff --git a/src/Payments.Mvc/Controllers/TeamsController.cs b/src/Payments.Mvc/Controllers/TeamsController.cs index 0820b376..327e5a47 100644 --- a/src/Payments.Mvc/Controllers/TeamsController.cs +++ b/src/Payments.Mvc/Controllers/TeamsController.cs @@ -65,18 +65,19 @@ public async Task Create(CreateTeamViewModel model) if (!ModelState.IsValid) { return View(model); - } + } var team = new Team() { - Name = model.Name, - Slug = model.Slug, - ContactName = model.ContactName, - ContactEmail = model.ContactEmail, + Name = model.Name, + Slug = model.Slug, + ContactName = model.ContactName, + ContactEmail = model.ContactEmail, ContactPhoneNumber = model.ContactPhoneNumber, - IsActive = true, - ApiKey = Guid.NewGuid().ToString("N").ToUpper(), - WebHookApiKey = model.WebHookApiKey, + IsActive = true, + ApiKey = Guid.NewGuid().ToString("N").ToUpper(), + WebHookApiKey = model.WebHookApiKey, + AllowedInvoiceType = model.AllowedInvoiceType, }; // add user to team diff --git a/src/Payments.Mvc/Models/TeamViewModels/BaseTeamViewModel.cs b/src/Payments.Mvc/Models/TeamViewModels/BaseTeamViewModel.cs index 25f806b0..c35a5be8 100644 --- a/src/Payments.Mvc/Models/TeamViewModels/BaseTeamViewModel.cs +++ b/src/Payments.Mvc/Models/TeamViewModels/BaseTeamViewModel.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; +using static Payments.Core.Domain.Team; namespace Payments.Mvc.Models.TeamViewModels { @@ -38,5 +39,10 @@ public class BaseTeamViewModel [Display(Name = "WebHook API Key")] [RegularExpression(@"^[a-zA-Z0-9\-._~]*$", ErrorMessage = "WebHook API Key may only contain URL-safe characters. (a-z A-Z 0-9 - . _ ~)")] public string WebHookApiKey { get; set; } + + [Required] + [StringLength(10)] + [Display(Name = "Allowed Invoice Type")] + public string AllowedInvoiceType { get; set; } = AllowedInvoiceTypes.CreditCard; } } diff --git a/src/Payments.Mvc/Views/Settings/Edit.cshtml b/src/Payments.Mvc/Views/Settings/Edit.cshtml index 96a06c18..c5de5654 100644 --- a/src/Payments.Mvc/Views/Settings/Edit.cshtml +++ b/src/Payments.Mvc/Views/Settings/Edit.cshtml @@ -1,4 +1,5 @@ @using Payments.Mvc.Models.Roles +@using Payments.Core.Domain @model Payments.Mvc.Models.TeamViewModels.EditTeamViewModel @{ @@ -45,7 +46,31 @@ -
Leave blank if you don't want to pass authorization to your webhook URL
+
Leave blank if you don't want to pass authorization to your webhook URL +
+ + +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+
@if (User.IsInRole(ApplicationRoleCodes.Admin)) @@ -103,4 +128,4 @@ } }); -} +} \ No newline at end of file diff --git a/src/Payments.Mvc/Views/Teams/Create.cshtml b/src/Payments.Mvc/Views/Teams/Create.cshtml index 362623eb..804cc0ea 100644 --- a/src/Payments.Mvc/Views/Teams/Create.cshtml +++ b/src/Payments.Mvc/Views/Teams/Create.cshtml @@ -1,4 +1,5 @@ @using Payments.Mvc.Models.TeamViewModels +@using Payments.Core.Domain @model CreateTeamViewModel @{ @@ -45,7 +46,29 @@ - Leave blank if you don't want to pass authorization to your webhook URL + Leave blank if you don't want to pass authorization to your webhook + URL + +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+
@@ -90,4 +113,4 @@ } }); -} +} \ No newline at end of file From c31935d740300930853e8f63c9b2d36af7713783 Mon Sep 17 00:00:00 2001 From: Jason Sylvestre Date: Fri, 26 Sep 2025 08:51:42 -0700 Subject: [PATCH 2/6] Improves form checkbox spacing Updates form checkbox styles to improve spacing and alignment. This ensures consistent rendering across different browsers and devices. --- src/Payments.Mvc/ClientApp/src/css/_vendor.scss | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Payments.Mvc/ClientApp/src/css/_vendor.scss b/src/Payments.Mvc/ClientApp/src/css/_vendor.scss index d221c075..720eab75 100644 --- a/src/Payments.Mvc/ClientApp/src/css/_vendor.scss +++ b/src/Payments.Mvc/ClientApp/src/css/_vendor.scss @@ -104,12 +104,11 @@ input[type=number]::-webkit-outer-spin-button { // fix spacing on checkboxes .form-check { - padding-left: 2rem; + padding-left: 2rem; - .form-check-input { - margin-top: 0.6rem; - margin-left: -2rem; - } + .form-check-input { + margin-left: -2rem; + } } .progress-bar { From 5dab9dedebddf2593bef8404f913ca3d7c3ab667 Mon Sep 17 00:00:00 2001 From: Jason Sylvestre Date: Fri, 26 Sep 2025 08:57:55 -0700 Subject: [PATCH 3/6] not needed --- src/Payments.Mvc/Views/Settings/Edit.cshtml | 6 +++--- src/Payments.Mvc/Views/Teams/Create.cshtml | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Payments.Mvc/Views/Settings/Edit.cshtml b/src/Payments.Mvc/Views/Settings/Edit.cshtml index c5de5654..2b7f3f60 100644 --- a/src/Payments.Mvc/Views/Settings/Edit.cshtml +++ b/src/Payments.Mvc/Views/Settings/Edit.cshtml @@ -53,18 +53,18 @@
-
+
-
+
-
+
diff --git a/src/Payments.Mvc/Views/Teams/Create.cshtml b/src/Payments.Mvc/Views/Teams/Create.cshtml index 804cc0ea..146a8986 100644 --- a/src/Payments.Mvc/Views/Teams/Create.cshtml +++ b/src/Payments.Mvc/Views/Teams/Create.cshtml @@ -52,17 +52,18 @@
-
+
- +
-
+
-
+
From 703aa9f5ed1e6a6e4c8e019d23f668ff880cefee Mon Sep 17 00:00:00 2001 From: Jason Sylvestre Date: Fri, 26 Sep 2025 09:05:54 -0700 Subject: [PATCH 4/6] Displays allowed invoice type in team details Adds the "Allowed Invoice Type" field to the team details view. This allows users to see at a glance which invoice types (Credit Card, Recharge, or Both) are enabled for a given team. Displays the allowed invoice type using a badge with different colors for each type, improving visual clarity. --- .../Controllers/SettingsController.cs | 3 +- .../Models/TeamViewModels/TeamDetailsModel.cs | 19 ++++++----- src/Payments.Mvc/Views/Settings/Index.cshtml | 34 +++++++++++++++++-- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/Payments.Mvc/Controllers/SettingsController.cs b/src/Payments.Mvc/Controllers/SettingsController.cs index b7d30da3..c418d298 100644 --- a/src/Payments.Mvc/Controllers/SettingsController.cs +++ b/src/Payments.Mvc/Controllers/SettingsController.cs @@ -71,7 +71,8 @@ public async Task Index() ApiKey = userCanEdit ? team.ApiKey : "", IsActive = team.IsActive, UserCanEdit = userCanEdit, - WebHookApiKey = team.WebHookApiKey + WebHookApiKey = team.WebHookApiKey, + AllowedInvoiceType = team.AllowedInvoiceType }; return View(model); diff --git a/src/Payments.Mvc/Models/TeamViewModels/TeamDetailsModel.cs b/src/Payments.Mvc/Models/TeamViewModels/TeamDetailsModel.cs index f1a4f17a..c1babc62 100644 --- a/src/Payments.Mvc/Models/TeamViewModels/TeamDetailsModel.cs +++ b/src/Payments.Mvc/Models/TeamViewModels/TeamDetailsModel.cs @@ -22,23 +22,26 @@ public class TeamDetailsModel public string ContactPhoneNumber { get; set; } [Display(Name = "ApiKey")] - public string ApiKey { get; set; } - - [Display(Name = "WebHook API Key")] + public string ApiKey { get; set; } + + [Display(Name = "WebHook API Key")] public string WebHookApiKey { get; set; } [Display(Name = "Active?")] public bool IsActive { get; set; } + [Display(Name = "Allowed Invoice Type")] + public string AllowedInvoiceType { get; set; } + public IList Accounts { get; set; } public IList Permissions { get; set; } - public bool UserCanEdit { get; set; } - - public bool ShowCoa { get; set; } - public bool UseCoa { get; set; } - + public bool UserCanEdit { get; set; } + + public bool ShowCoa { get; set; } + public bool UseCoa { get; set; } + public string WarningMessage { get; set; } //Because the temp data isn't showing this right. } } diff --git a/src/Payments.Mvc/Views/Settings/Index.cshtml b/src/Payments.Mvc/Views/Settings/Index.cshtml index 6e55a064..b67cc5f2 100644 --- a/src/Payments.Mvc/Views/Settings/Index.cshtml +++ b/src/Payments.Mvc/Views/Settings/Index.cshtml @@ -41,7 +41,7 @@ @Html.DisplayNameFor(model => model.WebHookApiKey)
- @if(!string.IsNullOrWhiteSpace(Model.WebHookApiKey)) + @if (!string.IsNullOrWhiteSpace(Model.WebHookApiKey)) { @Html.DisplayFor(model => model.WebHookApiKey) } @@ -71,6 +71,36 @@
@Html.DisplayFor(model => model.ContactPhoneNumber)
+
+ @Html.DisplayNameFor(model => model.AllowedInvoiceType) +
+
+ @{ + string displayText = ""; + string badgeClass = ""; + + switch (Model.AllowedInvoiceType) + { + case "CC": + displayText = "Credit Card Only"; + badgeClass = "badge bg-primary"; + break; + case "Recharge": + displayText = "Recharge Only"; + badgeClass = "badge bg-success"; + break; + case "Both": + displayText = "Both Credit Card and Recharge"; + badgeClass = "badge bg-info"; + break; + default: + displayText = Model.AllowedInvoiceType; + badgeClass = "badge bg-secondary"; + break; + } + } + @displayText +
@@ -113,4 +143,4 @@ +
\ No newline at end of file From 05265abddc909dc8416a498fd2ed3ebffe812deb Mon Sep 17 00:00:00 2001 From: Jason Sylvestre Date: Fri, 26 Sep 2025 12:23:09 -0700 Subject: [PATCH 5/6] Restricts invoice type editing to admins. Moves the allowed invoice type setting to be only editable by administrators. Displays the allowed invoice type as read-only with a message prompting users to create a help ticket if they need to change it. --- .../Controllers/SettingsController.cs | 3 +- src/Payments.Mvc/Views/Settings/Edit.cshtml | 76 +++++++++++++------ 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/Payments.Mvc/Controllers/SettingsController.cs b/src/Payments.Mvc/Controllers/SettingsController.cs index c418d298..08375e79 100644 --- a/src/Payments.Mvc/Controllers/SettingsController.cs +++ b/src/Payments.Mvc/Controllers/SettingsController.cs @@ -134,12 +134,13 @@ public async Task Edit(EditTeamViewModel model) team.ContactEmail = model.ContactEmail; team.ContactPhoneNumber = model.ContactPhoneNumber; team.WebHookApiKey = model.WebHookApiKey; - team.AllowedInvoiceType = model.AllowedInvoiceType; + // only admins can change active if (User.IsInRole(ApplicationRoleCodes.Admin)) { team.IsActive = model.IsActive; + team.AllowedInvoiceType = model.AllowedInvoiceType; } await _context.SaveChangesAsync(); diff --git a/src/Payments.Mvc/Views/Settings/Edit.cshtml b/src/Payments.Mvc/Views/Settings/Edit.cshtml index 2b7f3f60..1c757652 100644 --- a/src/Payments.Mvc/Views/Settings/Edit.cshtml +++ b/src/Payments.Mvc/Views/Settings/Edit.cshtml @@ -50,31 +50,36 @@
-
- -
-
- - -
-
- - -
-
- - -
-
- -
+ @if (User.IsInRole(ApplicationRoleCodes.Admin)) { +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ +
} + else + { +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+
If you need to change the allowed invoice type, please submit + a help ticket.
+
+ }
From 8f518ea3c1631617b5b5512b804429e37b68341e Mon Sep 17 00:00:00 2001 From: Jason Sylvestre Date: Fri, 26 Sep 2025 12:51:06 -0700 Subject: [PATCH 6/6] Restricts invoice type modification to admins Disables the invoice type selection for non-admin users and displays a message prompting them to submit a help ticket for changes. This ensures that only administrators can modify the allowed invoice types. --- src/Payments.Mvc/Views/Settings/Edit.cshtml | 83 ++++++++------------- 1 file changed, 30 insertions(+), 53 deletions(-) diff --git a/src/Payments.Mvc/Views/Settings/Edit.cshtml b/src/Payments.Mvc/Views/Settings/Edit.cshtml index 1c757652..17b3f427 100644 --- a/src/Payments.Mvc/Views/Settings/Edit.cshtml +++ b/src/Payments.Mvc/Views/Settings/Edit.cshtml @@ -50,36 +50,40 @@
+ @{ + bool isAdmin = User.IsInRole(ApplicationRoleCodes.Admin); + string labelClass = isAdmin ? "form-check-label ms-2" : "form-check-label ms-2 text-muted"; + } - - @if (User.IsInRole(ApplicationRoleCodes.Admin)) - { -
- -
-
- - -
-
- - -
-
- - -
+
+ +
+
+ + +
+
+ + +
+
+ +
-
+ @if (!isAdmin) + { +
If you need to change the allowed invoice type, please submit + a help ticket.
+ } + +
- + @if (isAdmin) + {
} - else - { -
- -
-
- - -
-
- - -
-
- - -
-
-
If you need to change the allowed invoice type, please submit - a help ticket.
-
- }