Skip to content

Commit 0424d75

Browse files
authored
🎨 #3323 【企业微信】获取企业所有打卡规则接口增加官方新添加的late_rule等字段
1 parent e61ad44 commit 0424d75

File tree

2 files changed

+296
-0
lines changed

2 files changed

+296
-0
lines changed

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/WxCpCheckinGroupBase.java

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,30 @@ public static class CheckinDate implements Serializable {
151151
*/
152152
@SerializedName("flex_off_duty_time")
153153
private Integer flexOffDutyTime;
154+
155+
/**
156+
* 是否允许弹性时间
157+
*/
158+
@SerializedName("allow_flex")
159+
private Boolean allowFlex;
160+
161+
/**
162+
* 迟到规则
163+
*/
164+
@SerializedName("late_rule")
165+
private LateRule lateRule;
166+
167+
/**
168+
* 最早可打卡时间限制
169+
*/
170+
@SerializedName("max_allow_arrive_early")
171+
private Integer maxAllowArriveEarly;
172+
173+
/**
174+
* 最晚可打卡时间限制
175+
*/
176+
@SerializedName("max_allow_arrive_late")
177+
private Integer maxAllowArriveLate;
154178
}
155179

156180
/**
@@ -160,6 +184,13 @@ public static class CheckinDate implements Serializable {
160184
public static class CheckinTime implements Serializable {
161185

162186
private static final long serialVersionUID = -5507709858609705279L;
187+
188+
/**
189+
* 时段id,为班次中某一堆上下班时间组合的id
190+
*/
191+
@SerializedName("time_id")
192+
private Integer timeId;
193+
163194
/**
164195
* 上班时间,表示为距离当天0点的秒数。
165196
*/
@@ -183,6 +214,60 @@ public static class CheckinTime implements Serializable {
183214
*/
184215
@SerializedName("remind_off_work_sec")
185216
private Integer remindOffWorkSec;
217+
218+
/**
219+
* 休息开始时间,仅单时段支持,距离0点的秒
220+
*/
221+
@SerializedName("rest_begin_time")
222+
private Integer restBeginTime;
223+
224+
/**
225+
* 休息结束时间,仅单时段支持,距离0点的秒
226+
*/
227+
@SerializedName("rest_end_time")
228+
private Integer restEndTime;
229+
230+
/**
231+
* 是否允许休息
232+
*/
233+
@SerializedName("allow_rest")
234+
private Boolean allowRest;
235+
236+
/**
237+
* 最早可打卡时间,距离0点的秒数
238+
*/
239+
@SerializedName("earliest_work_sec")
240+
private Integer earliestWorkSec;
241+
242+
/**
243+
* 最晚可打卡时间,距离0点的秒数
244+
*/
245+
@SerializedName("latest_work_sec")
246+
private Integer latestWorkSec;
247+
248+
/**
249+
* 最早可下班打卡时间,距离0点的秒数
250+
*/
251+
@SerializedName("earliest_off_work_sec")
252+
private Integer earliestOffWorkSec;
253+
254+
/**
255+
* 最晚可下班打卡时间,距离0点的秒数
256+
*/
257+
@SerializedName("latest_off_work_sec")
258+
private Integer latestOffWorkSec;
259+
260+
/**
261+
* 上班无需打卡
262+
*/
263+
@SerializedName("no_need_checkon")
264+
private Boolean noNeedCheckon;
265+
266+
/**
267+
* 下班无需打卡
268+
*/
269+
@SerializedName("no_need_checkoff")
270+
private Boolean noNeedCheckoff;
186271
}
187272

188273
/**
@@ -438,6 +523,17 @@ public static class LateRule implements Serializable {
438523

439524
private static final long serialVersionUID = 5604969713950037053L;
440525

526+
/**
527+
* 晚走的时间 距离最晚一个下班的时间单位:秒
528+
*/
529+
@SerializedName("offwork_after_time")
530+
private Integer offWorkAfterTime;
531+
532+
/**
533+
* 第二天第一个班次允许迟到的弹性时间单位:秒
534+
*/
535+
@SerializedName("onwork_flex_time")
536+
private Integer onWorkFlexTime;
441537

442538
/**
443539
* 是否允许超时下班(下班晚走次日晚到)允许时onwork_flex_time,offwork_after_time才有意义

weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImplTest.java

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,206 @@ public void testOtInfoV2Deserialization() {
209209
System.out.println(gson.toJson(option.getOtInfoV2()));
210210
}
211211

212+
/**
213+
* Test late_rule field deserialization in getCropCheckinOption response.
214+
*/
215+
@Test
216+
public void testLateRuleDeserialization() {
217+
// Test JSON with late_rule structure based on the issue #3323
218+
String jsonWithLateRule = "{\n" +
219+
" \"grouptype\": 1,\n" +
220+
" \"groupid\": 1,\n" +
221+
" \"checkindate\": [\n" +
222+
" {\n" +
223+
" \"workdays\": [1, 2, 3, 4, 5],\n" +
224+
" \"checkintime\": [\n" +
225+
" {\n" +
226+
" \"time_id\": 1,\n" +
227+
" \"work_sec\": 32400,\n" +
228+
" \"off_work_sec\": 64800,\n" +
229+
" \"remind_work_sec\": 31800,\n" +
230+
" \"remind_off_work_sec\": 64800,\n" +
231+
" \"rest_begin_time\": 43200,\n" +
232+
" \"rest_end_time\": 48600,\n" +
233+
" \"allow_rest\": true,\n" +
234+
" \"earliest_work_sec\": 21600,\n" +
235+
" \"latest_work_sec\": 64740,\n" +
236+
" \"earliest_off_work_sec\": 32460,\n" +
237+
" \"latest_off_work_sec\": 107940,\n" +
238+
" \"no_need_checkon\": false,\n" +
239+
" \"no_need_checkoff\": false\n" +
240+
" }\n" +
241+
" ],\n" +
242+
" \"noneed_offwork\": false,\n" +
243+
" \"limit_aheadtime\": 0,\n" +
244+
" \"flex_on_duty_time\": 0,\n" +
245+
" \"flex_off_duty_time\": 0,\n" +
246+
" \"allow_flex\": false,\n" +
247+
" \"late_rule\": {\n" +
248+
" \"offwork_after_time\": 3600,\n" +
249+
" \"onwork_flex_time\": 3600,\n" +
250+
" \"allow_offwork_after_time\": true,\n" +
251+
" \"timerules\": [\n" +
252+
" {\n" +
253+
" \"offwork_after_time\": 18000,\n" +
254+
" \"onwork_flex_time\": 3600\n" +
255+
" },\n" +
256+
" {\n" +
257+
" \"offwork_after_time\": 21600,\n" +
258+
" \"onwork_flex_time\": 7200\n" +
259+
" }\n" +
260+
" ]\n" +
261+
" },\n" +
262+
" \"max_allow_arrive_early\": 0,\n" +
263+
" \"max_allow_arrive_late\": 0\n" +
264+
" }\n" +
265+
" ],\n" +
266+
" \"groupname\": \"打卡\",\n" +
267+
" \"need_photo\": false\n" +
268+
"}";
269+
270+
WxCpCropCheckinOption option = WxCpGsonBuilder.create().fromJson(jsonWithLateRule, WxCpCropCheckinOption.class);
271+
assertThat(option).isNotNull();
272+
assertThat(option.getCheckinDate()).isNotNull();
273+
assertThat(option.getCheckinDate().size()).isEqualTo(1);
274+
275+
WxCpCheckinGroupBase.CheckinDate checkinDate = option.getCheckinDate().get(0);
276+
assertThat(checkinDate).isNotNull();
277+
assertThat(checkinDate.getAllowFlex()).isFalse();
278+
assertThat(checkinDate.getMaxAllowArriveEarly()).isEqualTo(0);
279+
assertThat(checkinDate.getMaxAllowArriveLate()).isEqualTo(0);
280+
281+
// Test late_rule field
282+
assertThat(checkinDate.getLateRule()).isNotNull();
283+
assertThat(checkinDate.getLateRule().getOffWorkAfterTime()).isEqualTo(3600);
284+
assertThat(checkinDate.getLateRule().getOnWorkFlexTime()).isEqualTo(3600);
285+
assertThat(checkinDate.getLateRule().getAllowOffWorkAfterTime()).isTrue();
286+
assertThat(checkinDate.getLateRule().getTimerules()).isNotNull();
287+
assertThat(checkinDate.getLateRule().getTimerules().size()).isEqualTo(2);
288+
289+
// Test timerules
290+
WxCpCheckinGroupBase.TimeRule firstRule = checkinDate.getLateRule().getTimerules().get(0);
291+
assertThat(firstRule.getOffWorkAfterTime()).isEqualTo(18000);
292+
assertThat(firstRule.getOnWorkFlexTime()).isEqualTo(3600);
293+
294+
// Test CheckinTime fields
295+
assertThat(checkinDate.getCheckinTime()).isNotNull();
296+
assertThat(checkinDate.getCheckinTime().size()).isEqualTo(1);
297+
298+
WxCpCheckinGroupBase.CheckinTime checkinTime = checkinDate.getCheckinTime().get(0);
299+
assertThat(checkinTime.getTimeId()).isEqualTo(1);
300+
assertThat(checkinTime.getRestBeginTime()).isEqualTo(43200);
301+
assertThat(checkinTime.getRestEndTime()).isEqualTo(48600);
302+
assertThat(checkinTime.getAllowRest()).isTrue();
303+
assertThat(checkinTime.getEarliestWorkSec()).isEqualTo(21600);
304+
assertThat(checkinTime.getLatestWorkSec()).isEqualTo(64740);
305+
assertThat(checkinTime.getEarliestOffWorkSec()).isEqualTo(32460);
306+
assertThat(checkinTime.getLatestOffWorkSec()).isEqualTo(107940);
307+
assertThat(checkinTime.getNoNeedCheckon()).isFalse();
308+
assertThat(checkinTime.getNoNeedCheckoff()).isFalse();
309+
310+
System.out.println("Successfully parsed late_rule and new checkintime fields:");
311+
System.out.println(gson.toJson(option));
312+
}
313+
314+
/**
315+
* Test issue #3323 - full JSON from the issue report.
316+
*/
317+
@Test
318+
public void testIssue3323FullJson() {
319+
// Full JSON from issue #3323
320+
String issueJson = "{\n" +
321+
" \"grouptype\": 1,\n" +
322+
" \"groupid\": 1,\n" +
323+
" \"checkindate\": [\n" +
324+
" {\n" +
325+
" \"workdays\": [\n" +
326+
" 1,\n" +
327+
" 2,\n" +
328+
" 3,\n" +
329+
" 4,\n" +
330+
" 5\n" +
331+
" ],\n" +
332+
" \"checkintime\": [\n" +
333+
" {\n" +
334+
" \"time_id\": 1,\n" +
335+
" \"work_sec\": 32400,\n" +
336+
" \"off_work_sec\": 64800,\n" +
337+
" \"remind_work_sec\": 31800,\n" +
338+
" \"remind_off_work_sec\": 64800,\n" +
339+
" \"rest_begin_time\": 43200,\n" +
340+
" \"rest_end_time\": 48600,\n" +
341+
" \"allow_rest\": true,\n" +
342+
" \"earliest_work_sec\": 21600,\n" +
343+
" \"latest_work_sec\": 64740,\n" +
344+
" \"earliest_off_work_sec\": 32460,\n" +
345+
" \"latest_off_work_sec\": 107940,\n" +
346+
" \"no_need_checkon\": false,\n" +
347+
" \"no_need_checkoff\": false\n" +
348+
" }\n" +
349+
" ],\n" +
350+
" \"noneed_offwork\": false,\n" +
351+
" \"limit_aheadtime\": 0,\n" +
352+
" \"flex_on_duty_time\": 0,\n" +
353+
" \"flex_off_duty_time\": 0,\n" +
354+
" \"allow_flex\": false,\n" +
355+
" \"late_rule\": {\n" +
356+
" \"offwork_after_time\": 3600,\n" +
357+
" \"onwork_flex_time\": 3600,\n" +
358+
" \"allow_offwork_after_time\": true,\n" +
359+
" \"timerules\": [\n" +
360+
" {\n" +
361+
" \"offwork_after_time\": 18000,\n" +
362+
" \"onwork_flex_time\": 3600\n" +
363+
" },\n" +
364+
" {\n" +
365+
" \"offwork_after_time\": 21600,\n" +
366+
" \"onwork_flex_time\": 7200\n" +
367+
" },\n" +
368+
" {\n" +
369+
" \"offwork_after_time\": 28800,\n" +
370+
" \"onwork_flex_time\": 10800\n" +
371+
" }\n" +
372+
" ]\n" +
373+
" },\n" +
374+
" \"max_allow_arrive_early\": 0,\n" +
375+
" \"max_allow_arrive_late\": 0\n" +
376+
" }\n" +
377+
" ],\n" +
378+
" \"spe_workdays\": [],\n" +
379+
" \"spe_offdays\": [],\n" +
380+
" \"sync_holidays\": true,\n" +
381+
" \"groupname\": \"打卡\",\n" +
382+
" \"need_photo\": false,\n" +
383+
" \"wifimac_infos\": [],\n" +
384+
" \"note_can_use_local_pic\": true,\n" +
385+
" \"allow_checkin_offworkday\": false,\n" +
386+
" \"allow_apply_offworkday\": false,\n" +
387+
" \"loc_infos\": []\n" +
388+
" }";
389+
390+
WxCpCropCheckinOption option = WxCpGsonBuilder.create().fromJson(issueJson, WxCpCropCheckinOption.class);
391+
assertThat(option).isNotNull();
392+
assertThat(option.getGroupId()).isEqualTo(1);
393+
assertThat(option.getGroupName()).isEqualTo("打卡");
394+
assertThat(option.getCheckinDate()).isNotNull();
395+
assertThat(option.getCheckinDate().size()).isEqualTo(1);
396+
397+
WxCpCheckinGroupBase.CheckinDate checkinDate = option.getCheckinDate().get(0);
398+
assertThat(checkinDate.getLateRule()).isNotNull();
399+
assertThat(checkinDate.getLateRule().getOffWorkAfterTime()).isEqualTo(3600);
400+
assertThat(checkinDate.getLateRule().getOnWorkFlexTime()).isEqualTo(3600);
401+
assertThat(checkinDate.getLateRule().getAllowOffWorkAfterTime()).isTrue();
402+
assertThat(checkinDate.getLateRule().getTimerules()).isNotNull();
403+
assertThat(checkinDate.getLateRule().getTimerules().size()).isEqualTo(3);
404+
405+
System.out.println("✓ Successfully parsed full JSON from issue #3323");
406+
System.out.println("✓ Late Rule offwork_after_time: " + checkinDate.getLateRule().getOffWorkAfterTime());
407+
System.out.println("✓ Late Rule onwork_flex_time: " + checkinDate.getLateRule().getOnWorkFlexTime());
408+
System.out.println("✓ Late Rule allow_offwork_after_time: " + checkinDate.getLateRule().getAllowOffWorkAfterTime());
409+
System.out.println("✓ Late Rule timerules count: " + checkinDate.getLateRule().getTimerules().size());
410+
}
411+
212412
/**
213413
* Test get approval info.
214414
*

0 commit comments

Comments
 (0)