Processed
-You have already {{.response}} this item.
+You have already {{.Response}} this item.
diff --git a/src/goapp/controller/item/item-controller-dto.go b/src/goapp/controller/item/item-controller-dto.go
index 5e760de..f0734f8 100644
--- a/src/goapp/controller/item/item-controller-dto.go
+++ b/src/goapp/controller/item/item-controller-dto.go
@@ -1,5 +1,7 @@
package item
+import "main/model"
+
type ReassignItemCallback struct {
Id string `json:"Id"`
ApproverEmail string `json:"ApproverEmail"`
@@ -9,3 +11,14 @@ type ReassignItemCallback struct {
ApproveText string `json:"ApproveText"`
RejectText string `json:"RejectText"`
}
+
+type RespondePageData struct {
+ ApplicationId string
+ ApplicationModuleId string
+ ItemId string
+ ApproverEmail string
+ IsApproved string
+ Data model.Item
+ RequireRemarks bool
+ Response string
+}
diff --git a/src/goapp/controller/item/item-controller-interface.go b/src/goapp/controller/item/item-controller-interface.go
index 82633c9..3df1d01 100644
--- a/src/goapp/controller/item/item-controller-interface.go
+++ b/src/goapp/controller/item/item-controller-interface.go
@@ -12,4 +12,5 @@ type ItemController interface {
type ItemPageController interface {
MyRequests(w http.ResponseWriter, r *http.Request)
MyApprovals(w http.ResponseWriter, r *http.Request)
+ RespondToItem(w http.ResponseWriter, r *http.Request)
}
diff --git a/src/goapp/controller/item/item-page-controller.go b/src/goapp/controller/item/item-page-controller.go
index fa8657a..ae4a103 100644
--- a/src/goapp/controller/item/item-page-controller.go
+++ b/src/goapp/controller/item/item-page-controller.go
@@ -8,6 +8,8 @@ import (
"main/pkg/session"
"main/service"
"net/http"
+
+ "github.com/gorilla/mux"
)
type itemPageController struct {
@@ -99,3 +101,81 @@ func (c *itemPageController) MyApprovals(w http.ResponseWriter, r *http.Request)
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
+
+func (c *itemPageController) RespondToItem(w http.ResponseWriter, r *http.Request) {
+ session, _ := session.Store.Get(r, "auth-session")
+
+ var profile map[string]interface{}
+ u := session.Values["profile"]
+ profile, ok := u.(map[string]interface{})
+ if !ok {
+ http.Error(w, "Error getting user data", http.StatusInternalServerError)
+ return
+ }
+ user := model.AzureUser{
+ Name: profile["name"].(string),
+ Email: profile["preferred_username"].(string),
+ }
+
+ params := mux.Vars(r)
+
+ itemIsAuthorized, err := c.Service.Item.ItemIsAuthorized(
+ params["appGuid"],
+ params["appModuleGuid"],
+ params["itemGuid"],
+ user.Email,
+ )
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ if !itemIsAuthorized.IsAuthorized {
+ t, d := c.Service.Template.UseTemplate("Unauthorized", r.URL.Path, user, nil)
+ err = t.Execute(w, d)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+ } else {
+ if itemIsAuthorized.IsApproved != nil {
+ var text string
+ if itemIsAuthorized.IsApproved.Value {
+ text = "approved"
+ } else {
+ text = "rejected"
+ }
+
+ data := RespondePageData{
+ Response: text,
+ }
+
+ t, d := c.Service.Template.UseTemplate("already-processed", r.URL.Path, user, data)
+ err = t.Execute(w, d)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+ } else {
+ item, err := c.Service.Item.GetItemById(params["itemGuid"])
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ data := RespondePageData{
+ ApplicationId: params["appGuid"],
+ ApplicationModuleId: params["appModuleGuid"],
+ ItemId: params["itemGuid"],
+ ApproverEmail: user.Email,
+ IsApproved: params["isApproved"],
+ Data: *item,
+ RequireRemarks: itemIsAuthorized.RequireRemarks,
+ }
+
+ t, d := c.Service.Template.UseTemplate("response", r.URL.Path, user, data)
+ err = t.Execute(w, d)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+ }
+ }
+}
diff --git a/src/goapp/infrastructure/database/database.go b/src/goapp/infrastructure/database/database.go
index ed3f706..ed861e3 100644
--- a/src/goapp/infrastructure/database/database.go
+++ b/src/goapp/infrastructure/database/database.go
@@ -5,40 +5,44 @@ import (
"database/sql"
"fmt"
"main/config"
+ "time"
_ "github.com/microsoft/go-mssqldb"
)
type Database struct {
- connString string
+ db *sql.DB
}
func NewDatabase(config config.ConfigManager) Database {
- fmt.Println("ConnectDb New")
connectionString := config.GetDatabaseConnectionString()
- return Database{
- connString: connectionString,
- }
-}
-func (d *Database) Connect() (*sql.DB, error) {
- conn, err := sql.Open("sqlserver", d.connString)
+ conn, err := sql.Open("sqlserver", connectionString)
if err != nil {
- return nil, err
+ fmt.Println(err.Error())
+ return Database{db: nil}
}
- return conn, nil
-}
+ conn.SetMaxOpenConns(10)
+ conn.SetMaxIdleConns(10)
+ conn.SetConnMaxLifetime(5 * time.Minute)
-func (d *Database) Query(query string, args ...any) (*sql.Rows, error) {
- conn, err := d.Connect()
+ err = conn.Ping()
if err != nil {
- return nil, err
+ fmt.Println(err.Error())
+ return Database{db: nil}
+ }
+
+ fmt.Println("Database connection established and configured.")
+
+ return Database{
+ db: conn,
}
- defer conn.Close()
+}
+func (d *Database) Query(query string, args ...any) (*sql.Rows, error) {
ctx := context.Background()
- rows, err := conn.QueryContext(ctx, query, args...)
+ rows, err := d.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
}
@@ -46,29 +50,18 @@ func (d *Database) Query(query string, args ...any) (*sql.Rows, error) {
}
func (d *Database) QueryRow(query string, args ...any) (*sql.Row, error) {
- conn, err := d.Connect()
- if err != nil {
- return nil, err
- }
- defer conn.Close()
-
ctx := context.Background()
- row := conn.QueryRowContext(ctx, query, args...)
+ row := d.db.QueryRowContext(ctx, query, args...)
if row == nil {
- err = fmt.Errorf("QueryRowContext returned nil")
+ err := fmt.Errorf("QueryRowContext returned nil")
+ return nil, err
}
return row, nil
}
func (d *Database) Execute(query string, args ...any) error {
- conn, err := d.Connect()
- if err != nil {
- return err
- }
- defer conn.Close()
-
ctx := context.Background()
- _, err = conn.ExecContext(ctx, query, args...)
+ _, err := d.db.ExecContext(ctx, query, args...)
if err != nil {
return err
}
diff --git a/src/goapp/model/item.go b/src/goapp/model/item.go
index cf47c9e..5cba394 100644
--- a/src/goapp/model/item.go
+++ b/src/goapp/model/item.go
@@ -89,3 +89,13 @@ type ResponseCallback struct {
ResponseDate string `json:"responseDate"`
RespondedBy string `json:"respondedBy"`
}
+
+type ItemIsAuthorized struct {
+ IsAuthorized bool `json:"isAuthorized"`
+ IsApproved *NullBool `json:"isApproved"`
+ RequireRemarks bool `json:"requireRemarks"`
+}
+
+type NullBool struct {
+ Value bool
+}
diff --git a/src/goapp/model/template.go b/src/goapp/model/template.go
index dfec85b..1d5f36c 100644
--- a/src/goapp/model/template.go
+++ b/src/goapp/model/template.go
@@ -3,7 +3,7 @@ package model
type MasterPageData struct {
Header Headers
Profile AzureUser
- Content interface{}
+ Content interface{} `json:"content"`
Footers []Footer
OrganizationName string
}
diff --git a/src/goapp/public/css/output.css b/src/goapp/public/css/output.css
index cdceecd..2c929e6 100644
--- a/src/goapp/public/css/output.css
+++ b/src/goapp/public/css/output.css
@@ -1847,18 +1847,14 @@ select {
top: 50%;
}
-.top-5 {
- top: 1.25rem;
+.top-8 {
+ top: 2rem;
}
.top-full {
top: 100%;
}
-.top-8 {
- top: 2rem;
-}
-
.isolate {
isolation: isolate;
}
diff --git a/src/goapp/repository/app-module/app-module-repository.go b/src/goapp/repository/app-module/app-module-repository.go
index 10bb996..31aa6c2 100644
--- a/src/goapp/repository/app-module/app-module-repository.go
+++ b/src/goapp/repository/app-module/app-module-repository.go
@@ -24,6 +24,7 @@ func (r *applicationModuleRepository) GetApplicationModuleByIdAndApplicationId(a
if err != nil {
return nil, err
}
+ defer rowApplicationModule.Close()
applicationModule, err := r.RowsToMap(rowApplicationModule)
if err != nil {
@@ -61,6 +62,7 @@ func (r *applicationModuleRepository) GetAll() ([]model.ApplicationModule, error
if err != nil {
return nil, err
}
+ defer rowApplicationModules.Close()
applicationModules, err := r.RowsToMap(rowApplicationModules)
if err != nil {
diff --git a/src/goapp/repository/approval-request-approver/approval-request-approver-repository.go b/src/goapp/repository/approval-request-approver/approval-request-approver-repository.go
index 3199f50..fbe9742 100644
--- a/src/goapp/repository/approval-request-approver/approval-request-approver-repository.go
+++ b/src/goapp/repository/approval-request-approver/approval-request-approver-repository.go
@@ -17,7 +17,7 @@ func NewApprovalRequestApproverRepository(db *db.Database) ApprovalRequestApprov
}
func (r *approvalRequestApproverRepository) InsertApprovalRequestApprover(approver model.ApprovalRequestApprover) error {
- _, err := r.Query("PR_ApprovalRequestApprovers_Insert",
+ row, err := r.Query("PR_ApprovalRequestApprovers_Insert",
sql.Named("ItemId", approver.ItemId),
sql.Named("ApproverEmail", approver.ApproverEmail),
)
@@ -25,6 +25,7 @@ func (r *approvalRequestApproverRepository) InsertApprovalRequestApprover(approv
if err != nil {
return err
}
+ defer row.Close()
return nil
}
@@ -35,6 +36,7 @@ func (r *approvalRequestApproverRepository) GetApproversByItemId(itemId string)
if err != nil {
return nil, err
}
+ defer rowApprovers.Close()
approvers, err := r.RowsToMap(rowApprovers)
if err != nil {
diff --git a/src/goapp/repository/item/item-repository-interface.go b/src/goapp/repository/item/item-repository-interface.go
index 80e6231..60ddf81 100644
--- a/src/goapp/repository/item/item-repository-interface.go
+++ b/src/goapp/repository/item/item-repository-interface.go
@@ -9,6 +9,7 @@ type ItemRepository interface {
GetItemsBy(itemOptions model.ItemOptions) ([]model.Item, error)
GetTotalItemsBy(itemOptions model.ItemOptions) (int, error)
InsertItem(appModuleId, subject, body, requesterEmail string) (string, error)
+ ItemIsAuthorized(appId, appModuleId, itemId, approverEmail string) (*model.ItemIsAuthorized, error)
UpdateItemApproverEmail(id, approverEmail, username string) error
UpdateItemCallback(id string, isCallbackFailed bool) error
UpdateItemDateSent(id string) error
diff --git a/src/goapp/repository/item/item-repository.go b/src/goapp/repository/item/item-repository.go
index 0f1c3e2..6b12d3b 100644
--- a/src/goapp/repository/item/item-repository.go
+++ b/src/goapp/repository/item/item-repository.go
@@ -24,6 +24,7 @@ func (r *itemRepository) GetItemById(id string) (*model.Item, error) {
if err != nil {
return nil, err
}
+ defer row.Close()
result, err := r.RowsToMap(row)
if err != nil {
@@ -102,6 +103,7 @@ func (r *itemRepository) GetItemsBy(itemOptions model.ItemOptions) ([]model.Item
if err != nil {
return []model.Item{}, err
}
+ defer resList.Close()
result, err := r.RowsToMap(resList)
if err != nil {
@@ -185,6 +187,7 @@ func (r *itemRepository) GetTotalItemsBy(itemOptions model.ItemOptions) (int, er
if err != nil {
return 0, err
}
+ defer rowTotal.Close()
resultTotal, err := r.RowsToMap(rowTotal)
if err != nil {
@@ -210,6 +213,7 @@ func (r *itemRepository) InsertItem(appModuleId, subject, body, requesterEmail s
if err != nil {
return "", err
}
+ defer rowItem.Close()
resultItem, err := r.RowsToMap(rowItem)
if err != nil {
@@ -220,7 +224,7 @@ func (r *itemRepository) InsertItem(appModuleId, subject, body, requesterEmail s
}
func (r *itemRepository) UpdateItemApproverEmail(id, approverEmail, username string) error {
- _, err := r.Query("PR_Items_Update_ApproverEmail",
+ row, err := r.Query("PR_Items_Update_ApproverEmail",
sql.Named("Id", id),
sql.Named("ApproverEmail", approverEmail),
sql.Named("Username", username),
@@ -228,34 +232,70 @@ func (r *itemRepository) UpdateItemApproverEmail(id, approverEmail, username str
if err != nil {
return err
}
+ defer row.Close()
return nil
}
+func (r *itemRepository) ItemIsAuthorized(appId, appModuleId, itemId, approverEmail string) (*model.ItemIsAuthorized, error) {
+ row, err := r.Query("PR_Items_IsAuthorized",
+ sql.Named("ApplicationId", appId),
+ sql.Named("ApplicationModuleId", appModuleId),
+ sql.Named("ItemId", itemId),
+ sql.Named("ApproverEmail", approverEmail),
+ )
+ if err != nil {
+ return nil, err
+ }
+ defer row.Close()
+
+ result, err := r.RowsToMap(row)
+ if err != nil {
+ return nil, err
+ }
+
+ i := model.ItemIsAuthorized{
+ IsAuthorized: result[0]["IsAuthorized"] == "1",
+ }
+
+ if result[0]["IsApproved"] != nil {
+ i.IsApproved = &model.NullBool{Value: result[0]["IsApproved"].(bool)}
+ } else {
+ i.IsApproved = nil
+ }
+
+ if result[0]["RequireRemarks"] != nil {
+ i.RequireRemarks = result[0]["RequireRemarks"].(bool)
+ }
+
+ return &i, nil
+}
func (r *itemRepository) UpdateItemCallback(id string, isCallbackFailed bool) error {
- _, err := r.Query("PR_Items_Update_Callback",
+ row, err := r.Query("PR_Items_Update_Callback",
sql.Named("ItemId", id),
sql.Named("IsCallbackFailed", isCallbackFailed),
)
if err != nil {
return err
}
+ defer row.Close()
return nil
}
func (r *itemRepository) UpdateItemDateSent(id string) error {
- _, err := r.Query("PR_Items_Update_DateSent",
+ row, err := r.Query("PR_Items_Update_DateSent",
sql.Named("Id", id),
)
if err != nil {
return err
}
+ defer row.Close()
return nil
}
func (r *itemRepository) UpdateItemResponse(id, remarks, email string, isApproved bool) error {
- _, err := r.Query("PR_Items_Update_Response",
+ row, err := r.Query("PR_Items_Update_Response",
sql.Named("Id", id),
sql.Named("ApproverRemarks", remarks),
sql.Named("Username", email),
@@ -264,6 +304,7 @@ func (r *itemRepository) UpdateItemResponse(id, remarks, email string, isApprove
if err != nil {
return err
}
+ defer row.Close()
return nil
}
@@ -277,6 +318,7 @@ func (r *itemRepository) ValidateItem(appId, appModuleId, itemId, email string)
if err != nil {
return false, err
}
+ defer row.Close()
result, err := r.RowsToMap(row)
if err != nil {
diff --git a/src/goapp/routes.go b/src/goapp/routes.go
index 2aad4f4..29dc4fe 100644
--- a/src/goapp/routes.go
+++ b/src/goapp/routes.go
@@ -11,7 +11,7 @@ import (
func setPageRoutes() {
httpRouter.GET("/", m.Chain(ctrl.ItemPage.MyRequests, m.AzureAuth()))
httpRouter.GET("/myapprovals", m.Chain(ctrl.ItemPage.MyApprovals, m.AzureAuth()))
- httpRouter.GET("/response/{appGuid}/{appModuleGuid}/{itemGuid}/{isApproved}", m.Chain(rtApprovals.ResponseHandler, m.AzureAuth()))
+ httpRouter.GET("/response/{appGuid}/{appModuleGuid}/{itemGuid}/{isApproved}", m.Chain(ctrl.ItemPage.RespondToItem, m.AzureAuth()))
httpRouter.GET("/responsereassigned/{appGuid}/{appModuleGuid}/{itemGuid}/{isApproved}/{ApproveText}/{RejectText}", m.Chain(rtApprovals.ResponseReassignedeHandler, m.AzureAuth()))
httpRouter.GET("/loginredirect", rtPages.LoginRedirectHandler)
diff --git a/src/goapp/routes/pages/approvals/response.go b/src/goapp/routes/pages/approvals/response.go
index 0d5e73d..0ab7119 100644
--- a/src/goapp/routes/pages/approvals/response.go
+++ b/src/goapp/routes/pages/approvals/response.go
@@ -108,76 +108,6 @@ func ResponseReassignedeHandler(w http.ResponseWriter, r *http.Request) {
}
}
-func ResponseHandler(w http.ResponseWriter, r *http.Request) {
- switch r.Method {
- case "GET":
- var username string
- sessionaz, _ := session.Store.Get(r, "auth-session")
- iprofile := sessionaz.Values["profile"]
-
- if iprofile != nil {
- profile := iprofile.(map[string]interface{})
- username = profile["preferred_username"].(string)
- }
- params := mux.Vars(r)
-
- appGuid := params["appGuid"]
- appModuleGuid := params["appModuleGuid"]
- itemGuid := params["itemGuid"]
- isApproved := params["isApproved"]
-
- sqlParamsIsAuth := map[string]interface{}{
- "ApplicationId": appGuid,
- "ApplicationModuleId": appModuleGuid,
- "ItemId": itemGuid,
- "ApproverEmail": username,
- }
-
- sqlParamsItems := map[string]interface{}{
- "Id": itemGuid,
- }
-
- db := connectSql()
- defer db.Close()
- resIsAuth, err := db.ExecuteStoredProcedureWithResult("PR_RESPONSE_IsAuthorized", sqlParamsIsAuth)
- handleErrorReturn(w, err)
-
- isAuth := resIsAuth[0]["IsAuthorized"]
- if isAuth == "0" {
- template.UseTemplate(&w, r, "Unauthorized", nil)
- } else {
- isProcessed := resIsAuth[0]["IsApproved"]
- if isProcessed != nil {
- var text string
- if isProcessed == true {
- text = "approved"
- } else {
- text = "rejected"
- }
- data := map[string]interface{}{
- "response": text,
- }
- template.UseTemplate(&w, r, "AlreadyProcessed", data)
- } else {
- resItems, err := db.ExecuteStoredProcedureWithResult("PR_Items_Select_ById", sqlParamsItems)
-
- handleErrorReturn(w, err)
- requireRemarks := resIsAuth[0]["RequireRemarks"]
- data := map[string]interface{}{
- "ApplicationId": appGuid,
- "ApplicationModuleId": appModuleGuid,
- "ItemId": itemGuid,
- "ApproverEmail": username,
- "IsApproved": isApproved,
- "Data": resItems[0],
- "RequireRemarks": requireRemarks,
- }
- template.UseTemplate(&w, r, "response", data)
- }
-
- }
- }
-}
func ProcessFailedCallbacks() {
db := connectSql()
diff --git a/src/goapp/service/item/item-service-interface.go b/src/goapp/service/item/item-service-interface.go
index 92e3da0..da2a83b 100644
--- a/src/goapp/service/item/item-service-interface.go
+++ b/src/goapp/service/item/item-service-interface.go
@@ -8,6 +8,7 @@ type ItemService interface {
GetItemById(id string) (*model.Item, error)
GetAll(itemOptions model.ItemOptions) (model.Response, error)
InsertItem(item model.ItemInsertRequest) (string, error)
+ ItemIsAuthorized(appId, appModuleId, itemId, approverEmail string) (*model.ItemIsAuthorized, error)
UpdateItemApproverEmail(itemId, approverEmail, username string) error
UpdateItemCallback(itemId string, isCallbackFailed bool) error
UpdateItemDateSent(itemId string) error
diff --git a/src/goapp/service/item/item-service.go b/src/goapp/service/item/item-service.go
index 1658c9c..5c368dd 100644
--- a/src/goapp/service/item/item-service.go
+++ b/src/goapp/service/item/item-service.go
@@ -43,7 +43,7 @@ func (s *itemService) GetAll(itemOptions model.ItemOptions) (model.Response, err
}
var wg sync.WaitGroup
- maxGoroutines := 10
+ maxGoroutines := 2
guard := make(chan struct{}, maxGoroutines)
for i := range data {
@@ -83,6 +83,14 @@ func (s *itemService) InsertItem(item model.ItemInsertRequest) (string, error) {
return id, nil
}
+func (s *itemService) ItemIsAuthorized(appId, appModuleId, itemId, approverEmail string) (*model.ItemIsAuthorized, error) {
+ itemIsAuthorized, err := s.Repository.Item.ItemIsAuthorized(appId, appModuleId, itemId, approverEmail)
+ if err != nil {
+ return nil, err
+ }
+ return itemIsAuthorized, nil
+}
+
func (s *itemService) UpdateItemApproverEmail(itemId, approverEmail, username string) error {
err := s.Repository.Item.UpdateItemApproverEmail(itemId, approverEmail, username)
if err != nil {
diff --git a/src/goapp/templates/AlreadyProcessed.html b/src/goapp/templates/already-processed.html
similarity index 93%
rename from src/goapp/templates/AlreadyProcessed.html
rename to src/goapp/templates/already-processed.html
index e8a48c8..0048c4a 100644
--- a/src/goapp/templates/AlreadyProcessed.html
+++ b/src/goapp/templates/already-processed.html
@@ -4,7 +4,7 @@
You have already {{.response}} this item. You have already {{.Response}} this item.Processed
-