82 lines
4.2 KiB
SQL
82 lines
4.2 KiB
SQL
CREATE TABLE staff_employees (
|
|
id VARCHAR(26) PRIMARY KEY CHECK (id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
tenant_id VARCHAR(26) NOT NULL CHECK (tenant_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
core_user_id VARCHAR(26) CHECK (core_user_id IS NULL OR core_user_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
personnel_number TEXT NOT NULL,
|
|
display_name TEXT NOT NULL,
|
|
position TEXT NOT NULL DEFAULT '',
|
|
gender TEXT NOT NULL DEFAULT '' CHECK (gender IN ('', 'male', 'female')),
|
|
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'blocked', 'dismissed')),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE (tenant_id, id),
|
|
UNIQUE (tenant_id, personnel_number),
|
|
UNIQUE (tenant_id, core_user_id)
|
|
);
|
|
|
|
CREATE TABLE staff_attendance_events (
|
|
id VARCHAR(26) PRIMARY KEY CHECK (id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
tenant_id VARCHAR(26) NOT NULL CHECK (tenant_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
employee_id VARCHAR(26) NOT NULL,
|
|
event_type TEXT NOT NULL CHECK (event_type IN ('check_in', 'check_out')),
|
|
source TEXT NOT NULL CHECK (source IN ('terminal', 'mobile_app', 'manual_entry', 'web_portal')),
|
|
source_event_id TEXT NOT NULL,
|
|
occurred_at TIMESTAMPTZ NOT NULL,
|
|
received_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
device_id VARCHAR(26) CHECK (device_id IS NULL OR device_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
status TEXT NOT NULL DEFAULT 'accepted' CHECK (status IN ('accepted', 'rejected', 'review_required')),
|
|
actor_id VARCHAR(26) NOT NULL CHECK (actor_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
correlation_id VARCHAR(26) NOT NULL CHECK (correlation_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE (tenant_id, source, source_event_id),
|
|
FOREIGN KEY (tenant_id, employee_id) REFERENCES staff_employees(tenant_id, id)
|
|
);
|
|
CREATE INDEX staff_attendance_employee_time_idx
|
|
ON staff_attendance_events (tenant_id, employee_id, occurred_at DESC);
|
|
|
|
CREATE TABLE staff_timesheet_entries (
|
|
id VARCHAR(26) PRIMARY KEY CHECK (id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
tenant_id VARCHAR(26) NOT NULL CHECK (tenant_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
employee_id VARCHAR(26) NOT NULL,
|
|
work_date DATE NOT NULL,
|
|
minutes_worked INTEGER NOT NULL DEFAULT 0 CHECK (minutes_worked BETWEEN 0 AND 1440),
|
|
status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'submitted', 'approved', 'rejected')),
|
|
note TEXT NOT NULL DEFAULT '',
|
|
revision INTEGER NOT NULL DEFAULT 1 CHECK (revision > 0),
|
|
updated_by VARCHAR(26) NOT NULL CHECK (updated_by ~ '^[0-9A-HJKMNP-TV-Z]{26}$'),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE (tenant_id, employee_id, work_date),
|
|
FOREIGN KEY (tenant_id, employee_id) REFERENCES staff_employees(tenant_id, id)
|
|
);
|
|
CREATE INDEX staff_timesheet_period_idx
|
|
ON staff_timesheet_entries (tenant_id, work_date, employee_id);
|
|
|
|
ALTER TABLE staff_employees ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE staff_employees FORCE ROW LEVEL SECURITY;
|
|
CREATE POLICY staff_employees_tenant_isolation ON staff_employees
|
|
USING (tenant_id = current_setting('app.tenant_id', true))
|
|
WITH CHECK (tenant_id = current_setting('app.tenant_id', true));
|
|
|
|
ALTER TABLE staff_attendance_events ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE staff_attendance_events FORCE ROW LEVEL SECURITY;
|
|
CREATE POLICY staff_attendance_events_tenant_isolation ON staff_attendance_events
|
|
USING (tenant_id = current_setting('app.tenant_id', true))
|
|
WITH CHECK (
|
|
tenant_id = current_setting('app.tenant_id', true)
|
|
AND actor_id = current_setting('app.user_id', true)
|
|
);
|
|
|
|
ALTER TABLE staff_timesheet_entries ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE staff_timesheet_entries FORCE ROW LEVEL SECURITY;
|
|
CREATE POLICY staff_timesheet_entries_tenant_isolation ON staff_timesheet_entries
|
|
USING (tenant_id = current_setting('app.tenant_id', true))
|
|
WITH CHECK (
|
|
tenant_id = current_setting('app.tenant_id', true)
|
|
AND updated_by = current_setting('app.user_id', true)
|
|
);
|
|
|
|
GRANT SELECT, INSERT, UPDATE ON staff_employees TO krona_staff_app;
|
|
GRANT SELECT, INSERT ON staff_attendance_events TO krona_staff_app;
|
|
REVOKE UPDATE, DELETE, TRUNCATE ON staff_attendance_events FROM krona_staff_app;
|
|
GRANT SELECT, INSERT, UPDATE ON staff_timesheet_entries TO krona_staff_app;
|