feat: add attendance APIs
This commit is contained in:
+125
-4
@@ -915,6 +915,9 @@ func (a *adapter) CreateDb(reset bool) error {
|
||||
if err = createIMOrganizationTables(tx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = createIMAttendanceTables(tx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = createIMMeetingTables(tx); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1142,10 +1145,11 @@ func createIMWorkbenchTables(tx *sql.Tx) error {
|
||||
`INSERT INTO im_workbench_apps(code,name,route,sort_order,unread_key,enabled,permission)
|
||||
VALUES
|
||||
('organization','组织架构','/organization',10,'organization',1,'enabled'),
|
||||
('meetings','会议通知','/meetings',20,'meetings',1,'enabled'),
|
||||
('daily_reports','日报','/reports/daily',30,'daily_reports',1,'enabled'),
|
||||
('monthly_reports','月报','/reports/monthly',40,'monthly_reports',1,'enabled'),
|
||||
('executive_mailbox','总经理信箱','/executive-mailbox',50,'executive_mailbox',1,'enabled')
|
||||
('attendance','打卡','/attendance',20,'attendance',1,'enabled'),
|
||||
('meetings','会议通知','/meetings',30,'meetings',1,'enabled'),
|
||||
('daily_reports','日报','/reports/daily',40,'daily_reports',1,'enabled'),
|
||||
('monthly_reports','月报','/reports/monthly',50,'monthly_reports',1,'enabled'),
|
||||
('executive_mailbox','总经理信箱','/executive-mailbox',60,'executive_mailbox',1,'enabled')
|
||||
ON DUPLICATE KEY UPDATE
|
||||
name=VALUES(name),
|
||||
route=VALUES(route),
|
||||
@@ -1231,6 +1235,123 @@ func ensureIMOrganizationVisibilityTables(exec sqlExecutor) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func createIMAttendanceTables(tx *sql.Tx) error {
|
||||
statements := []string{
|
||||
`CREATE TABLE im_attendance_rules(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||
rule_id VARCHAR(64) NOT NULL,
|
||||
name VARCHAR(128) NOT NULL,
|
||||
workday TINYINT NOT NULL DEFAULT 1,
|
||||
location_required TINYINT NOT NULL DEFAULT 0,
|
||||
wifi_required TINYINT NOT NULL DEFAULT 0,
|
||||
allow_outside_checkin TINYINT NOT NULL DEFAULT 1,
|
||||
appeal_allowed TINYINT NOT NULL DEFAULT 1,
|
||||
effective_from DATE,
|
||||
effective_to DATE,
|
||||
state VARCHAR(16) NOT NULL DEFAULT 'active',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
PRIMARY KEY(id),
|
||||
UNIQUE INDEX uk_im_attendance_rules_rule(rule_id),
|
||||
INDEX idx_im_attendance_rules_state(state,effective_from,effective_to)
|
||||
)`,
|
||||
`CREATE TABLE im_attendance_shifts(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||
shift_id VARCHAR(64) NOT NULL,
|
||||
rule_id VARCHAR(64) NOT NULL,
|
||||
name VARCHAR(128) NOT NULL,
|
||||
work_start TIME NOT NULL,
|
||||
work_end TIME NOT NULL,
|
||||
checkin_start TIME NOT NULL,
|
||||
checkout_end TIME NOT NULL,
|
||||
state VARCHAR(16) NOT NULL DEFAULT 'active',
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
PRIMARY KEY(id),
|
||||
UNIQUE INDEX uk_im_attendance_shifts_shift(shift_id),
|
||||
INDEX idx_im_attendance_shifts_rule(rule_id,state,sort_order)
|
||||
)`,
|
||||
`CREATE TABLE im_attendance_records(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||
record_id VARCHAR(64) NOT NULL,
|
||||
user_id BIGINT NOT NULL,
|
||||
record_date DATE NOT NULL,
|
||||
rule_id VARCHAR(64) NOT NULL,
|
||||
shift_id VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL DEFAULT 'not_checked',
|
||||
exceptions JSON,
|
||||
appeal_status VARCHAR(32) NOT NULL DEFAULT '',
|
||||
version INT NOT NULL DEFAULT 1,
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
PRIMARY KEY(id),
|
||||
UNIQUE INDEX uk_im_attendance_records_record(record_id),
|
||||
UNIQUE INDEX uk_im_attendance_records_user_date_shift(user_id,record_date,shift_id),
|
||||
INDEX idx_im_attendance_records_user_id(user_id,id DESC),
|
||||
INDEX idx_im_attendance_records_date_status(record_date,status,id DESC)
|
||||
)`,
|
||||
`CREATE TABLE im_attendance_checkins(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||
checkin_id VARCHAR(64) NOT NULL,
|
||||
record_id VARCHAR(64) NOT NULL,
|
||||
user_id BIGINT NOT NULL,
|
||||
record_date DATE NOT NULL,
|
||||
action VARCHAR(32) NOT NULL,
|
||||
rule_id VARCHAR(64) NOT NULL,
|
||||
shift_id VARCHAR(64) NOT NULL,
|
||||
client_time DATETIME(3) NOT NULL,
|
||||
server_time DATETIME(3) NOT NULL,
|
||||
result VARCHAR(32) NOT NULL,
|
||||
location JSON,
|
||||
wifi JSON,
|
||||
device JSON,
|
||||
idempotency_key VARCHAR(128) NOT NULL,
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
PRIMARY KEY(id),
|
||||
UNIQUE INDEX uk_im_attendance_checkins_checkin(checkin_id),
|
||||
UNIQUE INDEX uk_im_attendance_checkins_idempotency(user_id,idempotency_key),
|
||||
INDEX idx_im_attendance_checkins_record(record_id,id)
|
||||
)`,
|
||||
`CREATE TABLE im_attendance_appeals(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||
appeal_id VARCHAR(64) NOT NULL,
|
||||
record_id VARCHAR(64) NOT NULL,
|
||||
user_id BIGINT NOT NULL,
|
||||
appeal_type VARCHAR(64) NOT NULL,
|
||||
reason VARCHAR(512) NOT NULL,
|
||||
target_action VARCHAR(32) NOT NULL DEFAULT '',
|
||||
target_time DATETIME(3),
|
||||
attachment_file_ids JSON,
|
||||
status VARCHAR(32) NOT NULL DEFAULT 'pending',
|
||||
version INT NOT NULL DEFAULT 1,
|
||||
idempotency_key VARCHAR(128) NOT NULL,
|
||||
submitted_at DATETIME(3) NOT NULL,
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
PRIMARY KEY(id),
|
||||
UNIQUE INDEX uk_im_attendance_appeals_appeal(appeal_id),
|
||||
UNIQUE INDEX uk_im_attendance_appeals_idempotency(user_id,idempotency_key),
|
||||
INDEX idx_im_attendance_appeals_record(record_id),
|
||||
INDEX idx_im_attendance_appeals_user_status(user_id,status,id DESC)
|
||||
)`,
|
||||
}
|
||||
for _, stmt := range statements {
|
||||
if _, err := tx.Exec(stmt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := tx.Exec(`INSERT INTO im_attendance_rules(rule_id,name,workday,location_required,wifi_required,allow_outside_checkin,appeal_allowed)
|
||||
VALUES('att_rule_default','默认考勤规则',1,0,0,1,1)
|
||||
ON DUPLICATE KEY UPDATE updated_at=updated_at`); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tx.Exec(`INSERT INTO im_attendance_shifts(shift_id,rule_id,name,work_start,work_end,checkin_start,checkout_end,sort_order)
|
||||
VALUES('shift_default','att_rule_default','默认班次','09:00:00','18:00:00','08:30:00','20:00:00',10)
|
||||
ON DUPLICATE KEY UPDATE updated_at=updated_at`)
|
||||
return err
|
||||
}
|
||||
|
||||
func createIMMeetingTables(tx *sql.Tx) error {
|
||||
statements := []string{
|
||||
`CREATE TABLE im_meetings(
|
||||
|
||||
Reference in New Issue
Block a user