Skip to content

Commit

Permalink
Merge pull request #168 from Avanade/167-approve-multiple-requests
Browse files Browse the repository at this point in the history
167 approve multiple requests
  • Loading branch information
iibuan authored Dec 3, 2024
2 parents d63d343 + 813bf10 commit 56ca74d
Show file tree
Hide file tree
Showing 15 changed files with 1,212 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/goapp/controller/item/item-controller-dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,27 @@ type RespondePageData struct {
ApproveText string
RejectText string
}

type GetItemsByApproverResponse struct {
Data []Item `json:"data"`
Page int `json:"page"`
Filter int `json:"filter"`
Total int `json:"total"`
}

type PostProcessMultipleResponseRequest struct {
Requests []model.ProcessResponseRequest `json:"request"`
}

type Item struct {
Id string `json:"id"`
Subject string `json:"subject"`
Application string `json:"application"`
ApplicationId string `json:"applicationId"`
Module string `json:"module"`
ModuleId string `json:"moduleId"`
RequestedBy string `json:"requestedBy"`
RequestedOn string `json:"requestedOn"`
Approvers []string `json:"approvers"`
Body string `json:"body"`
}
3 changes: 3 additions & 0 deletions src/goapp/controller/item/item-controller-interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import "net/http"

type ItemController interface {
GetItems(w http.ResponseWriter, r *http.Request)
GetItemsByApprover(w http.ResponseWriter, r *http.Request)
CreateItem(w http.ResponseWriter, r *http.Request)
ProcessResponse(w http.ResponseWriter, r *http.Request)
ProcessMultipleResponse(w http.ResponseWriter, r *http.Request)
ReassignItem(w http.ResponseWriter, r *http.Request)
}

type ItemPageController interface {
MyRequests(w http.ResponseWriter, r *http.Request)
MyApprovals(w http.ResponseWriter, r *http.Request)
MultipleApprovals(w http.ResponseWriter, r *http.Request)
RespondToItem(w http.ResponseWriter, r *http.Request)
ReassignApproval(w http.ResponseWriter, r *http.Request)
}
151 changes: 151 additions & 0 deletions src/goapp/controller/item/item-controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"main/service"
"net/http"
"strconv"
"sync"
"time"

"github.com/gorilla/mux"
Expand Down Expand Up @@ -102,6 +103,84 @@ func (c *itemController) GetItems(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(result)
}

func (c *itemController) GetItemsByApprover(w http.ResponseWriter, r *http.Request) {
// Get all items
var filterOptions model.FilterOptions

user, err := c.Authenticator.GetAuthenticatedUser(r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

params := r.URL.Query()

var requestType string
if params.Has("requestType") {
requestType = params["requestType"][0]
}

var organization string
if params.Has("organization") {
organization = params["organization"][0]
}

filterOptions.Page = 0 // Default page is 1 which is 0 in the database
if params.Has("page") {
filterOptions.Page, err = strconv.Atoi(params["page"][0])
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
filterOptions.Page = filterOptions.Page - 1
}

if params.Has("filter") {
filterOptions.Filter, err = strconv.Atoi(params["filter"][0])
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
} else {
filterOptions.Filter = 50
}

result, total, err := c.Service.Item.GetByApprover(user.Email, requestType, organization, filterOptions)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

var response GetItemsByApproverResponse
for _, item := range result {
itemResponse := Item{
Id: item.Id,
Subject: item.Subject,
Application: item.Application,
ApplicationId: item.ApplicationId,
Module: item.Module,
ModuleId: item.ModuleId,
RequestedBy: item.RequestedBy,
RequestedOn: item.Created,
Approvers: item.Approvers,
Body: item.Body,
}

response.Data = append(response.Data, itemResponse)
}
if len(response.Data) == 0 {
response.Data = []Item{}
}
response.Page = filterOptions.Page + 1
response.Filter = filterOptions.Filter
response.Total = total

// Return the result
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
}

func (c *itemController) CreateItem(w http.ResponseWriter, r *http.Request) {
// Decode payload
var req model.ItemInsertRequest
Expand Down Expand Up @@ -204,6 +283,78 @@ func (c *itemController) ProcessResponse(w http.ResponseWriter, r *http.Request)
w.WriteHeader(http.StatusOK)
}

func (c *itemController) ProcessMultipleResponse(w http.ResponseWriter, r *http.Request) {
// Decode payload
var req PostProcessMultipleResponseRequest
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

user, err := c.Authenticator.GetAuthenticatedUser(r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

vars := mux.Vars(r)
response := vars["response"]

var isApproved string
if response == "approve" {
isApproved = "true"
} else if response == "reject" {
isApproved = "false"
} else {
http.Error(w, "Invalid response", http.StatusBadRequest)
return
}

for index, _ := range req.Requests {
req.Requests[index].ApproverEmail = user.Email
req.Requests[index].IsApproved = isApproved
}

var wg sync.WaitGroup
concurrencyLimit := make(chan struct{}, 50) // Limit to 50 concurrent goroutines

// Validate All Requests
for _, request := range req.Requests {
wg.Add(1)
concurrencyLimit <- struct{}{} // Acquire a slot

go func() {
defer wg.Done()
defer func() { <-concurrencyLimit }() // Release the slot

// Validate payload
valid, err := c.Service.Item.ValidateItem(request)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

if !valid {
http.Error(w, "Invalid request", http.StatusBadRequest)
return
}

// Update item response
err = c.Service.Item.UpdateItemResponse(request)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

// Post callback
c.postCallback(request.ItemId)
}()
}

w.WriteHeader(http.StatusOK)
}

func (c *itemController) ReassignItem(w http.ResponseWriter, r *http.Request) {
// Get user info
user, err := c.Authenticator.GetAuthenticatedUser(r)
Expand Down
27 changes: 27 additions & 0 deletions src/goapp/controller/item/item-page-controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,30 @@ func (c *itemPageController) ReassignApproval(w http.ResponseWriter, r *http.Req
}
}
}

func (c *itemPageController) MultipleApprovals(w http.ResponseWriter, r *http.Request) {
user, err := c.Service.Authenticator.GetAuthenticatedUser(r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

application, err := c.Service.Application.GetApplicationById(c.CommunityPortalAppId)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

b, err := json.Marshal(application)
if err != nil {
fmt.Println(err)
return
}

t, d := c.Service.Template.UseTemplate("multiple-approvals", r.URL.Path, *user, string(b))

err = t.Execute(w, d)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
9 changes: 9 additions & 0 deletions src/goapp/model/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package model

type FilterOptions struct {
Filter int
Page int
Search string
Orderby string
Ordertype string
}
2 changes: 2 additions & 0 deletions src/goapp/model/item.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package model
type Item struct {
Id string `json:"id"`
Application string `json:"application"`
ApplicationId string `json:"applicationId"`
ApproverRemarks string `json:"approverRemarks"`
Body string `json:"body"`
Created string `json:"created"`
DateResponded string `json:"dateResponded"`
DateSent string `json:"dateSent"`
IsApproved bool `json:"isApproved"`
Module string `json:"module"`
ModuleId string `json:"moduleId"`
Subject string `json:"subject"`
ApproveText string `json:"approveText"`
CallbackUrl string `json:"callbackUrl"`
Expand Down
Loading

0 comments on commit 56ca74d

Please sign in to comment.