正在显示
5 个修改的文件
包含
234 行增加
和
5 行删除
@@ -35,7 +35,7 @@ type ProductCalendarDto struct { | @@ -35,7 +35,7 @@ type ProductCalendarDto struct { | ||
35 | // 休息时间周期列表 | 35 | // 休息时间周期列表 |
36 | BreakTimePeriods []*domain.ProductCalendarBreakTimePeriod `json:"breakTimePeriods"` | 36 | BreakTimePeriods []*domain.ProductCalendarBreakTimePeriod `json:"breakTimePeriods"` |
37 | // 累计休息时间 (单位 h) | 37 | // 累计休息时间 (单位 h) |
38 | - TotalBreakTime float64 `json:"totalBreakTime"` | 38 | + // TotalBreakTime float64 `json:"totalBreakTime"` |
39 | } | 39 | } |
40 | 40 | ||
41 | func (d *ProductCalendarDto) LoadDto(m *domain.ProductCalendar, orgId int) *ProductCalendarDto { | 41 | func (d *ProductCalendarDto) LoadDto(m *domain.ProductCalendar, orgId int) *ProductCalendarDto { |
@@ -53,8 +53,8 @@ func (d *ProductCalendarDto) LoadDto(m *domain.ProductCalendar, orgId int) *Prod | @@ -53,8 +53,8 @@ func (d *ProductCalendarDto) LoadDto(m *domain.ProductCalendar, orgId int) *Prod | ||
53 | d.OrgName = m.Ext.OrgName | 53 | d.OrgName = m.Ext.OrgName |
54 | } | 54 | } |
55 | d.BreakTimePeriods = m.BreakTimePeriods | 55 | d.BreakTimePeriods = m.BreakTimePeriods |
56 | - for _, v := range d.BreakTimePeriods { | ||
57 | - d.TotalBreakTime += v.BreakTime | ||
58 | - } | 56 | + //for _, v := range d.BreakTimePeriods { |
57 | + // d.TotalBreakTime += v.BreakTime | ||
58 | + //} | ||
59 | return d | 59 | return d |
60 | } | 60 | } |
@@ -82,7 +82,7 @@ func (productAttendanceRecord *ProductAttendanceRecord) ComputeWorkTimeBefore(pr | @@ -82,7 +82,7 @@ func (productAttendanceRecord *ProductAttendanceRecord) ComputeWorkTimeBefore(pr | ||
82 | if productCalendar == nil { | 82 | if productCalendar == nil { |
83 | return wt | 83 | return wt |
84 | } | 84 | } |
85 | - wt = wt - productCalendar.BreakTime | 85 | + wt = wt - productAttendanceRecord.AttendanceBreakTime(productCalendar) |
86 | if wt < 0 { | 86 | if wt < 0 { |
87 | return 0 | 87 | return 0 |
88 | } | 88 | } |
@@ -156,3 +156,34 @@ func (productAttendanceRecord *ProductAttendanceRecord) ApproveUser() *User { | @@ -156,3 +156,34 @@ func (productAttendanceRecord *ProductAttendanceRecord) ApproveUser() *User { | ||
156 | UserName: productAttendanceRecord.Ext.AttendanceExt.ApproveUserName, | 156 | UserName: productAttendanceRecord.Ext.AttendanceExt.ApproveUserName, |
157 | } | 157 | } |
158 | } | 158 | } |
159 | + | ||
160 | +// 计算考勤休息时间 | ||
161 | +// | ||
162 | +// 考勤打卡时间内有休息时间进行累计 | ||
163 | +func (productAttendanceRecord *ProductAttendanceRecord) AttendanceBreakTime(productCalendar *ProductCalendar) float64 { | ||
164 | + var ( | ||
165 | + signIn = productAttendanceRecord.SignIn | ||
166 | + signOut = productAttendanceRecord.SignOut | ||
167 | + ) | ||
168 | + if signIn.IsZero() { | ||
169 | + return 0 | ||
170 | + } | ||
171 | + if signOut.IsZero() { | ||
172 | + return 0 | ||
173 | + } | ||
174 | + if productCalendar == nil { | ||
175 | + return 0 | ||
176 | + } | ||
177 | + var bt float64 | ||
178 | + for _, v := range productCalendar.BreakTimePeriods { | ||
179 | + var ( | ||
180 | + checkSignIn, checkSignOut time.Time | ||
181 | + ) | ||
182 | + checkSignIn = v.GetCheckBeginTime(signIn) | ||
183 | + checkSignOut = v.GetCheckEndTime(signIn) | ||
184 | + if xtime.BeforeEqual(signIn, checkSignIn) && xtime.AfterEqual(signOut, checkSignOut) { | ||
185 | + bt += v.BreakTime | ||
186 | + } | ||
187 | + } | ||
188 | + return bt | ||
189 | +} |
pkg/domain/product_attendance_record_test.go
0 → 100644
1 | +package domain | ||
2 | + | ||
3 | +import ( | ||
4 | + "fmt" | ||
5 | + "github.com/linmadan/egglib-go/utils/xtime" | ||
6 | + "github.com/stretchr/testify/assert" | ||
7 | + "testing" | ||
8 | +) | ||
9 | + | ||
10 | +func TestComputeWorkTimeBefore(t *testing.T) { | ||
11 | + var input = []struct { | ||
12 | + name string | ||
13 | + begin string | ||
14 | + end string | ||
15 | + overDay bool | ||
16 | + breakTime float64 | ||
17 | + records []*ProductAttendanceRecord | ||
18 | + }{ | ||
19 | + { | ||
20 | + "normal", | ||
21 | + "11:00", | ||
22 | + "12:00", | ||
23 | + false, | ||
24 | + 1, | ||
25 | + []*ProductAttendanceRecord{ | ||
26 | + { | ||
27 | + SignIn: xtime.MustParse("2022-05-05 09:00:00"), | ||
28 | + SignOut: xtime.MustParse("2022-05-05 12:00:00"), | ||
29 | + WorkTimeBefore: 2, | ||
30 | + }, | ||
31 | + { | ||
32 | + SignIn: xtime.MustParse("2022-05-05 12:00:00"), | ||
33 | + SignOut: xtime.MustParse("2022-05-05 17:00:00"), | ||
34 | + WorkTimeBefore: 5, | ||
35 | + }, | ||
36 | + { | ||
37 | + SignIn: xtime.MustParse("2022-05-05 17:00:00"), | ||
38 | + SignOut: xtime.MustParse("2022-05-06 07:00:00"), | ||
39 | + WorkTimeBefore: 14, | ||
40 | + }, | ||
41 | + }, | ||
42 | + }, | ||
43 | + { | ||
44 | + "over day", | ||
45 | + "23:45", | ||
46 | + "00:45", | ||
47 | + true, | ||
48 | + 1, | ||
49 | + []*ProductAttendanceRecord{ | ||
50 | + { | ||
51 | + SignIn: xtime.MustParse("2022-05-05 09:00:00"), | ||
52 | + SignOut: xtime.MustParse("2022-05-05 12:00:00"), | ||
53 | + WorkTimeBefore: 3, | ||
54 | + }, | ||
55 | + { | ||
56 | + SignIn: xtime.MustParse("2022-05-05 12:00:00"), | ||
57 | + SignOut: xtime.MustParse("2022-05-05 17:00:00"), | ||
58 | + WorkTimeBefore: 5, | ||
59 | + }, | ||
60 | + { | ||
61 | + SignIn: xtime.MustParse("2022-05-05 17:00:00"), | ||
62 | + SignOut: xtime.MustParse("2022-05-06 07:00:00"), | ||
63 | + WorkTimeBefore: 13, | ||
64 | + }, | ||
65 | + }, | ||
66 | + }, | ||
67 | + } | ||
68 | + for _, v := range input { | ||
69 | + p := NewProductCalendarBreakTimePeriod(v.begin, v.end, v.breakTime) | ||
70 | + for _, r := range v.records { | ||
71 | + t.Run(v.name, func(t *testing.T) { | ||
72 | + wt := r.ComputeWorkTimeBefore(&ProductCalendar{ | ||
73 | + BreakTimePeriods: []*ProductCalendarBreakTimePeriod{p}, | ||
74 | + }) | ||
75 | + assert.Equal(t, r.WorkTimeBefore, wt, fmt.Sprintf("except work time %v got :%v", r.WorkTimeBefore, wt)) | ||
76 | + }) | ||
77 | + } | ||
78 | + } | ||
79 | +} |
1 | package domain | 1 | package domain |
2 | 2 | ||
3 | +import ( | ||
4 | + "strconv" | ||
5 | + "strings" | ||
6 | + "time" | ||
7 | +) | ||
8 | + | ||
3 | type ProductCalendarBreakTimePeriod struct { | 9 | type ProductCalendarBreakTimePeriod struct { |
4 | // 开始时间 eg: 11:00 | 10 | // 开始时间 eg: 11:00 |
5 | BeginAt string `json:"beginAt,omitempty"` | 11 | BeginAt string `json:"beginAt,omitempty"` |
@@ -10,3 +16,44 @@ type ProductCalendarBreakTimePeriod struct { | @@ -10,3 +16,44 @@ type ProductCalendarBreakTimePeriod struct { | ||
10 | // 备注 eg:午饭 | 16 | // 备注 eg:午饭 |
11 | Remark string `json:"remark,omitempty"` | 17 | Remark string `json:"remark,omitempty"` |
12 | } | 18 | } |
19 | + | ||
20 | +func (period *ProductCalendarBreakTimePeriod) CheckOverDay() (bool, error) { | ||
21 | + inHour, parseInHourErr := strconv.Atoi(strings.Split(period.BeginAt, ":")[0]) | ||
22 | + if parseInHourErr != nil { | ||
23 | + return false, parseInHourErr | ||
24 | + } | ||
25 | + outHour, parseOutHourErr := strconv.Atoi(strings.Split(period.EndAt, ":")[0]) | ||
26 | + if parseOutHourErr != nil { | ||
27 | + return false, parseOutHourErr | ||
28 | + } | ||
29 | + if inHour <= outHour { | ||
30 | + return false, nil // eg: 7:00 17:00 t 9:00 | ||
31 | + } | ||
32 | + return true, nil | ||
33 | +} | ||
34 | + | ||
35 | +func (period *ProductCalendarBreakTimePeriod) GetCheckBeginTime(t time.Time) time.Time { | ||
36 | + y, m, d := t.Date() | ||
37 | + inHour, _ := strconv.Atoi(strings.Split(period.BeginAt, ":")[0]) | ||
38 | + inMinuter, _ := strconv.Atoi(strings.Split(period.BeginAt, ":")[1]) | ||
39 | + return time.Date(y, m, d, inHour, inMinuter, 0, 0, t.Location()) | ||
40 | +} | ||
41 | + | ||
42 | +func (period *ProductCalendarBreakTimePeriod) GetCheckEndTime(t time.Time) time.Time { | ||
43 | + y, m, d := t.Date() | ||
44 | + inHour, _ := strconv.Atoi(strings.Split(period.EndAt, ":")[0]) | ||
45 | + inMinuter, _ := strconv.Atoi(strings.Split(period.EndAt, ":")[1]) | ||
46 | + checkTime := time.Date(y, m, d, inHour, inMinuter, 0, 0, t.Location()) | ||
47 | + if overDay, err := period.CheckOverDay(); overDay && err == nil { | ||
48 | + return checkTime.AddDate(0, 0, 1) | ||
49 | + } | ||
50 | + return checkTime | ||
51 | +} | ||
52 | + | ||
53 | +func NewProductCalendarBreakTimePeriod(begin, end string, breakTime float64) *ProductCalendarBreakTimePeriod { | ||
54 | + return &ProductCalendarBreakTimePeriod{ | ||
55 | + BeginAt: begin, | ||
56 | + EndAt: end, | ||
57 | + BreakTime: breakTime, | ||
58 | + } | ||
59 | +} |
1 | +package domain | ||
2 | + | ||
3 | +import ( | ||
4 | + "fmt" | ||
5 | + "github.com/stretchr/testify/assert" | ||
6 | + "testing" | ||
7 | + "time" | ||
8 | +) | ||
9 | + | ||
10 | +func TestCheckOverDay(t *testing.T) { | ||
11 | + var input = []struct { | ||
12 | + name string | ||
13 | + begin string | ||
14 | + end string | ||
15 | + overDay bool | ||
16 | + }{ | ||
17 | + { | ||
18 | + "normal", | ||
19 | + "11:00", | ||
20 | + "12:00", | ||
21 | + false, | ||
22 | + }, | ||
23 | + { | ||
24 | + "over day", | ||
25 | + "23:45", | ||
26 | + "00:45", | ||
27 | + true, | ||
28 | + }, | ||
29 | + } | ||
30 | + for _, v := range input { | ||
31 | + p := NewProductCalendarBreakTimePeriod(v.begin, v.end, 0) | ||
32 | + t.Run(v.name, func(t *testing.T) { | ||
33 | + ok, err := p.CheckOverDay() | ||
34 | + assert.Equal(t, v.overDay, ok) | ||
35 | + assert.Nil(t, err) | ||
36 | + }) | ||
37 | + } | ||
38 | +} | ||
39 | + | ||
40 | +func TestGetCheckTime(t *testing.T) { | ||
41 | + var input = []struct { | ||
42 | + name string | ||
43 | + begin string | ||
44 | + end string | ||
45 | + overDay bool | ||
46 | + in time.Time | ||
47 | + }{ | ||
48 | + { | ||
49 | + "normal", | ||
50 | + "11:00", | ||
51 | + "12:00", | ||
52 | + false, | ||
53 | + time.Date(2022, 5, 5, 9, 0, 0, 0, time.Local), | ||
54 | + }, | ||
55 | + { | ||
56 | + "over day", | ||
57 | + "23:45", | ||
58 | + "00:45", | ||
59 | + true, | ||
60 | + time.Date(2022, 5, 5, 23, 0, 0, 0, time.Local), | ||
61 | + }, | ||
62 | + } | ||
63 | + for _, v := range input { | ||
64 | + p := NewProductCalendarBreakTimePeriod(v.begin, v.end, 0) | ||
65 | + t.Run(v.name, func(t *testing.T) { | ||
66 | + begin := p.GetCheckBeginTime(time.Now()) | ||
67 | + end := p.GetCheckEndTime(time.Now()) | ||
68 | + overDay := begin.Day() != end.Day() | ||
69 | + assert.Equal(t, v.overDay, overDay, fmt.Sprintf("begin:%v end:%v", begin, end)) | ||
70 | + }) | ||
71 | + } | ||
72 | +} |
-
请 注册 或 登录 后发表评论