mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
2978 files. The fork is 2026-07-15 (rebrand: gitea.dev -> github.com/hanzoai/git), so 2026 is the year, and "Copyright 2026 Hanzo AI, Inc." was already the form used by the handful of files that had ours. Shape is now: // Copyright 2026 Hanzo AI, Inc. All rights reserved. // Copyright 2015 The Gogs Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT Ours on top, theirs retained verbatim. Retained because MIT requires it, and separately because they are true — those authors did write that code. Not renamed to "The Git Authors": Git is a different project under a different license, and putting its name here would attribute this code to people who have nothing to do with it. Adding our line is the fix; overwriting theirs would have been both a licence violation and a false statement. gofmt still reports import-order drift in some of these files. It predates this change (verified against a stash) and is left alone rather than burying a one-line-per-file legal change under 3000 files of unrelated reordering. Build clean. Co-authored-by: Hanzo Dev <[email protected]>
106 lines
3.7 KiB
Go
106 lines
3.7 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package organization
|
|
|
|
import (
|
|
"context"
|
|
"sort"
|
|
|
|
"github.com/hanzoai/git/models/db"
|
|
|
|
"github.com/hanzoai/builder"
|
|
)
|
|
|
|
type WorktimeSumByRepos struct {
|
|
RepoName string
|
|
SumTime int64
|
|
}
|
|
|
|
func GetWorktimeByRepos(ctx context.Context, org *Organization, unitFrom, unixTo int64) (results []WorktimeSumByRepos, err error) {
|
|
err = db.GetEngine(ctx).
|
|
Select("repository.name AS repo_name, SUM(tracked_time.time) AS sum_time").
|
|
Table("tracked_time").
|
|
Join("INNER", "issue", "tracked_time.issue_id = issue.id").
|
|
Join("INNER", "repository", "issue.repo_id = repository.id").
|
|
Where(builder.Eq{"repository.owner_id": org.ID}).
|
|
And(builder.Eq{"tracked_time.deleted": false}).
|
|
And(builder.Gte{"tracked_time.created_unix": unitFrom}).
|
|
And(builder.Lte{"tracked_time.created_unix": unixTo}).
|
|
GroupBy("repository.name").
|
|
OrderBy("repository.name").
|
|
Find(&results)
|
|
return results, err
|
|
}
|
|
|
|
type WorktimeSumByMilestones struct {
|
|
RepoName string
|
|
MilestoneName string
|
|
MilestoneID int64
|
|
MilestoneDeadline int64
|
|
SumTime int64
|
|
HideRepoName bool
|
|
}
|
|
|
|
func GetWorktimeByMilestones(ctx context.Context, org *Organization, unitFrom, unixTo int64) (results []WorktimeSumByMilestones, err error) {
|
|
err = db.GetEngine(ctx).
|
|
Select("repository.name AS repo_name, milestone.name AS milestone_name, milestone.id AS milestone_id, milestone.deadline_unix as milestone_deadline, SUM(tracked_time.time) AS sum_time").
|
|
Table("tracked_time").
|
|
Join("INNER", "issue", "tracked_time.issue_id = issue.id").
|
|
Join("INNER", "repository", "issue.repo_id = repository.id").
|
|
Join("LEFT", "milestone", "issue.milestone_id = milestone.id").
|
|
Where(builder.Eq{"repository.owner_id": org.ID}).
|
|
And(builder.Eq{"tracked_time.deleted": false}).
|
|
And(builder.Gte{"tracked_time.created_unix": unitFrom}).
|
|
And(builder.Lte{"tracked_time.created_unix": unixTo}).
|
|
GroupBy("repository.name, milestone.name, milestone.deadline_unix, milestone.id").
|
|
OrderBy("repository.name, milestone.deadline_unix, milestone.id").
|
|
Find(&results)
|
|
|
|
// TODO: pgsql: NULL values are sorted last in default ascending order, so we need to sort them manually again.
|
|
sort.Slice(results, func(i, j int) bool {
|
|
if results[i].RepoName != results[j].RepoName {
|
|
return results[i].RepoName < results[j].RepoName
|
|
}
|
|
if results[i].MilestoneDeadline != results[j].MilestoneDeadline {
|
|
return results[i].MilestoneDeadline < results[j].MilestoneDeadline
|
|
}
|
|
return results[i].MilestoneID < results[j].MilestoneID
|
|
})
|
|
|
|
// Show only the first RepoName, for nicer output.
|
|
prevRepoName := ""
|
|
for i := 0; i < len(results); i++ {
|
|
res := &results[i]
|
|
res.MilestoneDeadline = 0 // clear the deadline because we do not really need it
|
|
if prevRepoName == res.RepoName {
|
|
res.HideRepoName = true
|
|
}
|
|
prevRepoName = res.RepoName
|
|
}
|
|
return results, err
|
|
}
|
|
|
|
type WorktimeSumByMembers struct {
|
|
UserName string
|
|
SumTime int64
|
|
}
|
|
|
|
func GetWorktimeByMembers(ctx context.Context, org *Organization, unitFrom, unixTo int64) (results []WorktimeSumByMembers, err error) {
|
|
err = db.GetEngine(ctx).
|
|
Select("`user`.name AS user_name, SUM(tracked_time.time) AS sum_time").
|
|
Table("tracked_time").
|
|
Join("INNER", "issue", "tracked_time.issue_id = issue.id").
|
|
Join("INNER", "repository", "issue.repo_id = repository.id").
|
|
Join("INNER", "`user`", "tracked_time.user_id = `user`.id").
|
|
Where(builder.Eq{"repository.owner_id": org.ID}).
|
|
And(builder.Eq{"tracked_time.deleted": false}).
|
|
And(builder.Gte{"tracked_time.created_unix": unitFrom}).
|
|
And(builder.Lte{"tracked_time.created_unix": unixTo}).
|
|
GroupBy("`user`.name").
|
|
OrderBy("sum_time DESC").
|
|
Find(&results)
|
|
return results, err
|
|
}
|