* feat: add Bankgirot LB-fil support for salary payments and tax payments - Implemented `generateBgLb` for salary batch payments, producing opening, payment, and closing records. - Added tests for `generateBgLb` to ensure correct record generation and validation. - Created `generateBankgiroPaymentBgLb` for single tax payments to Skatteverket, including validation and formatting. - Added tests for `generateBankgiroPaymentBgLb` to verify record structure and data integrity. - Introduced `generateSkattekontoOcr` for generating valid OCR references for Skattekonto payments, with tests for various input formats. - Updated database schema to track payment file formats and timestamps for salary runs and AGI declarations. - Created a new table for logging salary payslip deliveries to ensure compliance with audit requirements. * feat: add write permission check and company ID validation for payment file generation * feat: add write permission check for salary payment file generation
73 lines
2.8 KiB
SQL
73 lines
2.8 KiB
SQL
-- Salary payslip delivery log.
|
|
--
|
|
-- Per BFL 7 kap.: delivery confirmation of lönespecifikationer must be
|
|
-- retained as part of the audit trail. The send route currently calls Resend
|
|
-- and returns the count, but doesn't persist a per-employee record — so we
|
|
-- can't answer "did Anna receive her March payslip?" months later.
|
|
--
|
|
-- This table stores one row per (salary_run, employee, attempt) with the
|
|
-- Resend message_id (if known) so a follow-up webhook can update status to
|
|
-- delivered/bounced/complained.
|
|
|
|
CREATE TABLE IF NOT EXISTS public.salary_payslip_deliveries (
|
|
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
company_id uuid NOT NULL REFERENCES public.companies(id) ON DELETE CASCADE,
|
|
salary_run_id uuid NOT NULL REFERENCES public.salary_runs(id) ON DELETE CASCADE,
|
|
employee_id uuid NOT NULL REFERENCES public.employees(id) ON DELETE RESTRICT,
|
|
user_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
|
|
email_address text NOT NULL,
|
|
status text NOT NULL DEFAULT 'sent'
|
|
CHECK (status IN ('sent', 'delivered', 'bounced', 'complained', 'failed', 'skipped')),
|
|
|
|
-- Resend (or other provider) tracking
|
|
provider text NOT NULL DEFAULT 'resend',
|
|
provider_message_id text,
|
|
provider_event jsonb,
|
|
|
|
error_message text,
|
|
|
|
sent_at timestamptz NOT NULL DEFAULT now(),
|
|
delivered_at timestamptz,
|
|
bounced_at timestamptz,
|
|
complained_at timestamptz,
|
|
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
ALTER TABLE public.salary_payslip_deliveries ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "salary_payslip_deliveries_select"
|
|
ON public.salary_payslip_deliveries
|
|
FOR SELECT
|
|
USING (company_id IN (SELECT public.user_company_ids()));
|
|
|
|
CREATE POLICY "salary_payslip_deliveries_insert"
|
|
ON public.salary_payslip_deliveries
|
|
FOR INSERT
|
|
WITH CHECK (company_id IN (SELECT public.user_company_ids()));
|
|
|
|
CREATE POLICY "salary_payslip_deliveries_update"
|
|
ON public.salary_payslip_deliveries
|
|
FOR UPDATE
|
|
USING (company_id IN (SELECT public.user_company_ids()));
|
|
|
|
-- No DELETE policy — BFL 7 kap. requires retention of delivery records.
|
|
|
|
CREATE INDEX idx_payslip_deliveries_run
|
|
ON public.salary_payslip_deliveries (salary_run_id);
|
|
|
|
CREATE INDEX idx_payslip_deliveries_company
|
|
ON public.salary_payslip_deliveries (company_id);
|
|
|
|
CREATE INDEX idx_payslip_deliveries_provider_msg
|
|
ON public.salary_payslip_deliveries (provider_message_id)
|
|
WHERE provider_message_id IS NOT NULL;
|
|
|
|
CREATE TRIGGER salary_payslip_deliveries_updated_at
|
|
BEFORE UPDATE ON public.salary_payslip_deliveries
|
|
FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
|
|
|
|
NOTIFY pgrst, 'reload schema';
|