作者 yangfu

refactor: 工时统计修改(根据打卡时间内的休息时间段)

... ... @@ -35,7 +35,7 @@ type ProductCalendarDto struct {
// 休息时间周期列表
BreakTimePeriods []*domain.ProductCalendarBreakTimePeriod `json:"breakTimePeriods"`
// 累计休息时间 (单位 h)
TotalBreakTime float64 `json:"totalBreakTime"`
// TotalBreakTime float64 `json:"totalBreakTime"`
}
func (d *ProductCalendarDto) LoadDto(m *domain.ProductCalendar, orgId int) *ProductCalendarDto {
... ... @@ -53,8 +53,8 @@ func (d *ProductCalendarDto) LoadDto(m *domain.ProductCalendar, orgId int) *Prod
d.OrgName = m.Ext.OrgName
}
d.BreakTimePeriods = m.BreakTimePeriods
for _, v := range d.BreakTimePeriods {
d.TotalBreakTime += v.BreakTime
}
//for _, v := range d.BreakTimePeriods {
// d.TotalBreakTime += v.BreakTime
//}
return d
}
... ...
... ... @@ -82,7 +82,7 @@ func (productAttendanceRecord *ProductAttendanceRecord) ComputeWorkTimeBefore(pr
if productCalendar == nil {
return wt
}
wt = wt - productCalendar.BreakTime
wt = wt - productAttendanceRecord.AttendanceBreakTime(productCalendar)
if wt < 0 {
return 0
}
... ... @@ -156,3 +156,34 @@ func (productAttendanceRecord *ProductAttendanceRecord) ApproveUser() *User {
UserName: productAttendanceRecord.Ext.AttendanceExt.ApproveUserName,
}
}
// 计算考勤休息时间
//
// 考勤打卡时间内有休息时间进行累计
func (productAttendanceRecord *ProductAttendanceRecord) AttendanceBreakTime(productCalendar *ProductCalendar) float64 {
var (
signIn = productAttendanceRecord.SignIn
signOut = productAttendanceRecord.SignOut
)
if signIn.IsZero() {
return 0
}
if signOut.IsZero() {
return 0
}
if productCalendar == nil {
return 0
}
var bt float64
for _, v := range productCalendar.BreakTimePeriods {
var (
checkSignIn, checkSignOut time.Time
)
checkSignIn = v.GetCheckBeginTime(signIn)
checkSignOut = v.GetCheckEndTime(signIn)
if xtime.BeforeEqual(signIn, checkSignIn) && xtime.AfterEqual(signOut, checkSignOut) {
bt += v.BreakTime
}
}
return bt
}
... ...
package domain
import (
"fmt"
"github.com/linmadan/egglib-go/utils/xtime"
"github.com/stretchr/testify/assert"
"testing"
)
func TestComputeWorkTimeBefore(t *testing.T) {
var input = []struct {
name string
begin string
end string
overDay bool
breakTime float64
records []*ProductAttendanceRecord
}{
{
"normal",
"11:00",
"12:00",
false,
1,
[]*ProductAttendanceRecord{
{
SignIn: xtime.MustParse("2022-05-05 09:00:00"),
SignOut: xtime.MustParse("2022-05-05 12:00:00"),
WorkTimeBefore: 2,
},
{
SignIn: xtime.MustParse("2022-05-05 12:00:00"),
SignOut: xtime.MustParse("2022-05-05 17:00:00"),
WorkTimeBefore: 5,
},
{
SignIn: xtime.MustParse("2022-05-05 17:00:00"),
SignOut: xtime.MustParse("2022-05-06 07:00:00"),
WorkTimeBefore: 14,
},
},
},
{
"over day",
"23:45",
"00:45",
true,
1,
[]*ProductAttendanceRecord{
{
SignIn: xtime.MustParse("2022-05-05 09:00:00"),
SignOut: xtime.MustParse("2022-05-05 12:00:00"),
WorkTimeBefore: 3,
},
{
SignIn: xtime.MustParse("2022-05-05 12:00:00"),
SignOut: xtime.MustParse("2022-05-05 17:00:00"),
WorkTimeBefore: 5,
},
{
SignIn: xtime.MustParse("2022-05-05 17:00:00"),
SignOut: xtime.MustParse("2022-05-06 07:00:00"),
WorkTimeBefore: 13,
},
},
},
}
for _, v := range input {
p := NewProductCalendarBreakTimePeriod(v.begin, v.end, v.breakTime)
for _, r := range v.records {
t.Run(v.name, func(t *testing.T) {
wt := r.ComputeWorkTimeBefore(&ProductCalendar{
BreakTimePeriods: []*ProductCalendarBreakTimePeriod{p},
})
assert.Equal(t, r.WorkTimeBefore, wt, fmt.Sprintf("except work time %v got :%v", r.WorkTimeBefore, wt))
})
}
}
}
... ...
package domain
import (
"strconv"
"strings"
"time"
)
type ProductCalendarBreakTimePeriod struct {
// 开始时间 eg: 11:00
BeginAt string `json:"beginAt,omitempty"`
... ... @@ -10,3 +16,44 @@ type ProductCalendarBreakTimePeriod struct {
// 备注 eg:午饭
Remark string `json:"remark,omitempty"`
}
func (period *ProductCalendarBreakTimePeriod) CheckOverDay() (bool, error) {
inHour, parseInHourErr := strconv.Atoi(strings.Split(period.BeginAt, ":")[0])
if parseInHourErr != nil {
return false, parseInHourErr
}
outHour, parseOutHourErr := strconv.Atoi(strings.Split(period.EndAt, ":")[0])
if parseOutHourErr != nil {
return false, parseOutHourErr
}
if inHour <= outHour {
return false, nil // eg: 7:00 17:00 t 9:00
}
return true, nil
}
func (period *ProductCalendarBreakTimePeriod) GetCheckBeginTime(t time.Time) time.Time {
y, m, d := t.Date()
inHour, _ := strconv.Atoi(strings.Split(period.BeginAt, ":")[0])
inMinuter, _ := strconv.Atoi(strings.Split(period.BeginAt, ":")[1])
return time.Date(y, m, d, inHour, inMinuter, 0, 0, t.Location())
}
func (period *ProductCalendarBreakTimePeriod) GetCheckEndTime(t time.Time) time.Time {
y, m, d := t.Date()
inHour, _ := strconv.Atoi(strings.Split(period.EndAt, ":")[0])
inMinuter, _ := strconv.Atoi(strings.Split(period.EndAt, ":")[1])
checkTime := time.Date(y, m, d, inHour, inMinuter, 0, 0, t.Location())
if overDay, err := period.CheckOverDay(); overDay && err == nil {
return checkTime.AddDate(0, 0, 1)
}
return checkTime
}
func NewProductCalendarBreakTimePeriod(begin, end string, breakTime float64) *ProductCalendarBreakTimePeriod {
return &ProductCalendarBreakTimePeriod{
BeginAt: begin,
EndAt: end,
BreakTime: breakTime,
}
}
... ...
package domain
import (
"fmt"
"github.com/stretchr/testify/assert"
"testing"
"time"
)
func TestCheckOverDay(t *testing.T) {
var input = []struct {
name string
begin string
end string
overDay bool
}{
{
"normal",
"11:00",
"12:00",
false,
},
{
"over day",
"23:45",
"00:45",
true,
},
}
for _, v := range input {
p := NewProductCalendarBreakTimePeriod(v.begin, v.end, 0)
t.Run(v.name, func(t *testing.T) {
ok, err := p.CheckOverDay()
assert.Equal(t, v.overDay, ok)
assert.Nil(t, err)
})
}
}
func TestGetCheckTime(t *testing.T) {
var input = []struct {
name string
begin string
end string
overDay bool
in time.Time
}{
{
"normal",
"11:00",
"12:00",
false,
time.Date(2022, 5, 5, 9, 0, 0, 0, time.Local),
},
{
"over day",
"23:45",
"00:45",
true,
time.Date(2022, 5, 5, 23, 0, 0, 0, time.Local),
},
}
for _, v := range input {
p := NewProductCalendarBreakTimePeriod(v.begin, v.end, 0)
t.Run(v.name, func(t *testing.T) {
begin := p.GetCheckBeginTime(time.Now())
end := p.GetCheckEndTime(time.Now())
overDay := begin.Day() != end.Day()
assert.Equal(t, v.overDay, overDay, fmt.Sprintf("begin:%v end:%v", begin, end))
})
}
}
... ...