Files
olons_server/internal/store/tenant_init.go
T

102 lines
4.0 KiB
Go

package store
import (
"context"
"time"
)
// TenantInitializationResult reports how many missing defaults were created.
// Existing tenant customizations are deliberately left untouched.
type TenantInitializationResult struct {
WorkbenchApps int64
AttendanceRules int64
AttendanceShifts int64
MailboxConfigs int64
FeedbackConfigs int64
}
// InitializeTenantDefaults creates the minimum workbench data required by a tenant.
// Tenant-scoped unique indexes make this operation safe to retry.
func (s *Store) InitializeTenantDefaults(ctx context.Context) (*TenantInitializationResult, error) {
tx, err := s.db.BeginTxx(ctx, nil)
if err != nil {
return nil, err
}
defer func() { _ = tx.Rollback() }()
now := time.Now().UTC().Round(time.Millisecond)
result := &TenantInitializationResult{}
apps := []struct {
code, name, route string
sort int
}{
{code: "attendance", name: "打卡", route: "/attendance", sort: 10},
{code: "monthly_reports", name: "月报", route: "/reports/monthly", sort: 20},
{code: "daily_reports", name: "日报", route: "/reports/daily", sort: 30},
{code: "organization", name: "部门框架", route: "/organization", sort: 40},
{code: "executive_mailbox", name: "举报信箱", route: "/executive-mailbox", sort: 50},
{code: "meetings", name: "会议通知", route: "/meetings", sort: 60},
{code: "meeting_notes", name: "会议笔记", route: "/meeting-notes", sort: 70},
}
for _, app := range apps {
res, execErr := tx.ExecContext(ctx, `INSERT INTO im_workbench_apps
(tenant_id,code,name,icon_file_id,route,sort_order,unread_key,enabled,permission,created_at,updated_at)
VALUES(?,?,?,?,?,?,?,?,?,?,?)
ON DUPLICATE KEY UPDATE tenant_id=VALUES(tenant_id)`,
s.tenant(), app.code, app.name, "", app.route, app.sort, "", 1, "enabled", now, now)
if execErr != nil {
return nil, execErr
}
rows, _ := res.RowsAffected()
if rows == 1 {
result.WorkbenchApps++
}
}
res, err := tx.ExecContext(ctx, `INSERT INTO im_attendance_rules
(tenant_id,rule_id,name,workday,location_required,wifi_required,allow_outside_checkin,appeal_allowed,effective_from,effective_to,state,created_at,updated_at)
VALUES(?,?,?,?,?,?,?,?,CURDATE(),NULL,'active',?,?)
ON DUPLICATE KEY UPDATE tenant_id=VALUES(tenant_id)`,
s.tenant(), "att_rule_default", "默认考勤规则", "1,2,3,4,5", 0, 0, 1, 1, now, now)
if err != nil {
return nil, err
}
result.AttendanceRules, _ = res.RowsAffected()
res, err = tx.ExecContext(ctx, `INSERT INTO im_attendance_shifts
(tenant_id,shift_id,rule_id,name,work_start,work_end,checkin_start,checkout_end,state,sort_order,created_at,updated_at)
VALUES(?,?,?,?,?,?,?,?,?,?,?,?)
ON DUPLICATE KEY UPDATE tenant_id=VALUES(tenant_id)`,
s.tenant(), "shift_default", "att_rule_default", "默认班次", "09:00:00", "18:00:00", "08:00:00", "19:00:00", "active", 10, now, now)
if err != nil {
return nil, err
}
result.AttendanceShifts, _ = res.RowsAffected()
res, err = tx.ExecContext(ctx, `INSERT INTO im_mailbox_config
(tenant_id,enabled,allow_anonymous,required_fields,max_length,attachment_policy,notice_title,notice_content,notice_updated_at,created_at,updated_at)
VALUES(?,1,1,?,5000,?,'总经理信箱','请如实填写诉求。',?,?,?)
ON DUPLICATE KEY UPDATE tenant_id=VALUES(tenant_id)`,
s.tenant(), `["subject","content"]`, `{"max_files":5,"purpose":"executive_mailbox"}`, now, now, now)
if err != nil {
return nil, err
}
result.MailboxConfigs, _ = res.RowsAffected()
res, err = tx.ExecContext(ctx, `INSERT INTO im_feedback_config
(tenant_id,categories,max_length,attachment_policy,allow_contact,diagnostics_notice,created_at,updated_at)
VALUES(?,?,2000,?,1,'',?,?)
ON DUPLICATE KEY UPDATE tenant_id=VALUES(tenant_id)`,
s.tenant(), `["bug","suggestion","complaint","other"]`, `{"max_files":5,"purpose":"feedback"}`, now, now)
if err != nil {
return nil, err
}
result.FeedbackConfigs, _ = res.RowsAffected()
if err = tx.Commit(); err != nil {
return nil, err
}
return result, nil
}