Skip to content

Commit

Permalink
Merge pull request #16 from vshn/impersonation
Browse files Browse the repository at this point in the history
Add support to create report for someone else
  • Loading branch information
ccremer authored Nov 9, 2021
2 parents a842763 + e6f8128 commit 974d355
Show file tree
Hide file tree
Showing 11 changed files with 144 additions and 21 deletions.
9 changes: 4 additions & 5 deletions pkg/odoo/attendance.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,6 @@ func (reason *ActionReason) String() string {
return reason.Name
}

type readAttendancesResult struct {
Length int `json:"length,omitempty"`
Records []Attendance `json:"records,omitempty"`
}

func (c Client) ReadAllAttendances(sid string, uid int) ([]Attendance, error) {
// Prepare "search attendances" request
body, err := NewJsonRpcRequest(&ReadModelRequest{
Expand All @@ -94,6 +89,10 @@ func (c Client) ReadAllAttendances(sid string, uid int) ([]Attendance, error) {
return nil, err
}

type readAttendancesResult struct {
Length int `json:"length,omitempty"`
Records []Attendance `json:"records,omitempty"`
}
result := &readAttendancesResult{}
if err := c.unmarshalResponse(res.Body, result); err != nil {
return nil, err
Expand Down
77 changes: 77 additions & 0 deletions pkg/odoo/employee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package odoo

import "fmt"

type Employee struct {
ID int `json:"id"`
Name string `json:"name"`
}

// SearchEmployee searches for an Employee with the given searchString in the Employee.Name.
// If multiple employees are found, the first is returned.
// Returns nil if none found.
func (c *Client) SearchEmployee(searchString string, sid string) (*Employee, error) {
// Prepare request
body, err := NewJsonRpcRequest(&ReadModelRequest{
Model: "hr.employee",
Domain: []Filter{{"name", "ilike", searchString}},
Fields: []string{"name"},
Limit: 0,
Offset: 0,
}).Encode()
if err != nil {
return nil, fmt.Errorf("encoding request: %w", err)
}

res, err := c.makeRequest(sid, body)
if err != nil {
return nil, err
}
type readResults struct {
Length int `json:"length,omitempty"`
Records []Employee `json:"records,omitempty"`
}

result := &readResults{}
if err := c.unmarshalResponse(res.Body, result); err != nil {
return nil, err
}
if len(result.Records) >= 1 {
return &result.Records[0], nil
}
return nil, nil
}

// FetchEmployee fetches an Employee for the given user ID.
// Returns nil if not found.
func (c *Client) FetchEmployee(userId int, sid string) (*Employee, error) {
// Prepare request
body, err := NewJsonRpcRequest(&ReadModelRequest{
Model: "hr.employee",
Domain: []Filter{{"user_id", "=", userId}},
Fields: []string{"name"},
Limit: 0,
Offset: 0,
}).Encode()
if err != nil {
return nil, fmt.Errorf("encoding request: %w", err)
}

res, err := c.makeRequest(sid, body)
if err != nil {
return nil, err
}
type readResults struct {
Length int `json:"length,omitempty"`
Records []Employee `json:"records,omitempty"`
}

result := &readResults{}
if err := c.unmarshalResponse(res.Body, result); err != nil {
return nil, err
}
if len(result.Records) >= 1 {
return &result.Records[0], nil
}
return nil, nil
}
9 changes: 4 additions & 5 deletions pkg/odoo/leave.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ func (c *Client) ReadAllLeaves(sid string, uid int) ([]Leave, error) {
return nil, err
}

type readLeavesResult struct {
Length int `json:"length,omitempty"`
Records []Leave `json:"records,omitempty"`
}
result := &readLeavesResult{}
if err := c.unmarshalResponse(res.Body, result); err != nil {
return nil, err
Expand Down Expand Up @@ -98,11 +102,6 @@ func (l Leave) SplitByDay() []Leave {

////////////////// Boilerplate

type readLeavesResult struct {
Length int `json:"length,omitempty"`
Records []Leave `json:"records,omitempty"`
}

func (leaveType LeaveType) MarshalJSON() ([]byte, error) {
if leaveType.Name == "" {
return []byte("false"), nil
Expand Down
6 changes: 5 additions & 1 deletion pkg/timesheet/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,23 @@ type Summary struct {
type Report struct {
DailySummaries []*DailySummary
Summary Summary
Employee *odoo.Employee
}

type Reporter struct {
attendances []odoo.Attendance
leaves []odoo.Leave
employee *odoo.Employee
year int
month int
fteRatio float64
}

func NewReporter(attendances []odoo.Attendance, leaves []odoo.Leave) *Reporter {
func NewReporter(attendances []odoo.Attendance, leaves []odoo.Leave, employee *odoo.Employee) *Reporter {
return &Reporter{
attendances: attendances,
leaves: leaves,
employee: employee,
year: now().UTC().Year(),
month: int(now().UTC().Month()),
fteRatio: float64(1),
Expand Down Expand Up @@ -95,6 +98,7 @@ func (r *Reporter) CalculateReport() Report {
return Report{
DailySummaries: dailySummaries,
Summary: summary,
Employee: r.employee,
}
}

Expand Down
33 changes: 30 additions & 3 deletions pkg/web/attendance_handlers.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package web

import (
"fmt"
"net/http"
"strconv"
"time"

"github.com/vshn/odootools/pkg/odoo"
"github.com/vshn/odootools/pkg/timesheet"
"github.com/vshn/odootools/pkg/web/html"
)
Expand All @@ -20,13 +22,38 @@ func (s Server) OvertimeReport() http.Handler {
}
view := html.NewOvertimeReportView(s.html)

attendances, err := s.odoo.ReadAllAttendances(session.ID, session.UID)
forAnotherUser := r.FormValue("userscope") == "user-foreign-radio"
searchUser := r.FormValue("username")

userId := session.UID
var employee *odoo.Employee
if forAnotherUser {
e, err := s.odoo.SearchEmployee(searchUser, session.ID)
if err != nil {
view.ShowError(w, err)
return
}
if e == nil {
view.ShowError(w, fmt.Errorf("no user matching '%s' found", searchUser))
return
}
employee = e
} else {
e, err := s.odoo.FetchEmployee(userId, session.ID)
if err != nil {
view.ShowError(w, err)
return
}
employee = e
}

attendances, err := s.odoo.ReadAllAttendances(session.ID, userId)
if err != nil {
view.ShowError(w, err)
return
}

leaves, err := s.odoo.ReadAllLeaves(session.ID, session.UID)
leaves, err := s.odoo.ReadAllLeaves(session.ID, userId)
if err != nil {
view.ShowError(w, err)
return
Expand All @@ -36,7 +63,7 @@ func (s Server) OvertimeReport() http.Handler {
month := parseIntOrDefault(r.FormValue("month"), int(time.Now().Month()))
fte := parseFloatOrDefault(r.FormValue("ftepercentage"), 100)

reporter := timesheet.NewReporter(attendances, leaves).SetFteRatio(fte/100).SetMonth(year, month)
reporter := timesheet.NewReporter(attendances, leaves, employee).SetFteRatio(fte/100).SetMonth(year, month)
report := reporter.CalculateReport()
view.ShowAttendanceReport(w, report)
})
Expand Down
1 change: 1 addition & 0 deletions pkg/web/html/overtimereport_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,6 @@ func (v *OvertimeReportView) prepareValues(report timesheet.Report) Values {
"LoggedIn": true,
"ActiveView": v.template,
},
"Username": report.Employee.Name,
}
}
2 changes: 1 addition & 1 deletion pkg/web/html/requestreport_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type RequestReportView struct {
func NewRequestReportView(renderer *Renderer) *RequestReportView {
return &RequestReportView{
renderer: renderer,
template: "report",
template: "createreport",
}
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/web/session_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (s Server) Login() http.Handler {
HttpOnly: true,
Secure: true,
})
http.Redirect(w, r, "/report", http.StatusTemporaryRedirect)
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
})
}

Expand Down
20 changes: 18 additions & 2 deletions templates/report.html → templates/createreport.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,29 @@ <h1>Create Report</h1>
<input type="number" class="form-control" name="year" id="year" min="2014" value="2020">
</div>
<div class="mb-3">
<label for="month"class="form-label">Month</label>
<label for="month" class="form-label">Month</label>
<input type="number" class="form-control" name="month" id="month" min="1" max="12" value="1">
</div>
<div class="mb-3">
<label for="fte"class="form-label">FTE percentage</label>
<label for="fte" class="form-label">FTE percentage</label>
<input type="number" class="form-control" name="ftepercentage" id="fte" min="1" max="100" value="100">
</div>
<div class="mb-3 form-check">
<input class="form-check-input" type="radio" id="userselfradio" name="userscope" value="user-self-radio"
checked>
<label class="form-check-label" for="userselfradio">
For myself
</label>
</div>
<div class="mb-3 form-check form-check-inline">
<input class="form-check-input" type="radio" id="userforeignradio" name="userscope" value="user-foreign-radio">
<label class="form-check-label" for="userforeignradio">
For someone else (you'll need appropriate permissions)
</label>
<span>
<input class="form-control" type="text" name="username" id="username" placeholder="Search Username">
</span>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary">Create Report</button>
</div>
Expand Down
2 changes: 1 addition & 1 deletion templates/overtimereport.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{ define "main" }}
<h1>Attendance</h1>
<h1>Attendance for {{ .Username }}</h1>
{{ with .Error }}
<div class="alert alert-warning" role="alert">{{ . }}</div>
{{ end }}
Expand Down
4 changes: 2 additions & 2 deletions test/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ func TestLoginSuccess(t *testing.T) {
res := httptest.NewRecorder()
newServer(odooMock.URL).ServeHTTP(res, req)

is.Equal(res.Code, http.StatusTemporaryRedirect) // HTTP status
is.Equal(res.Header().Get("Location"), "/report") // Location header
is.Equal(res.Code, http.StatusTemporaryRedirect) // HTTP status
is.Equal(res.Header().Get("Location"), "/") // Location header

is.Equal(1, len(res.Result().Cookies())) // number of cookies
c := res.Result().Cookies()[0]
Expand Down

0 comments on commit 974d355

Please sign in to comment.