186 lines
4.7 KiB
PL/PgSQL
186 lines
4.7 KiB
PL/PgSQL
BEGIN;
|
|
|
|
-- Enable direct/manual sales orders (e.g. market booth daily capture).
|
|
-- Direct orders are identifiable by order_source=direct and external_ref prefix DIR-.
|
|
|
|
ALTER TABLE sales_order
|
|
ADD COLUMN IF NOT EXISTS order_source TEXT NOT NULL DEFAULT 'wix';
|
|
|
|
ALTER TABLE sales_order
|
|
ALTER COLUMN party_id DROP NOT NULL;
|
|
|
|
UPDATE sales_order
|
|
SET order_source = 'wix'
|
|
WHERE order_source IS NULL;
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1
|
|
FROM pg_constraint
|
|
WHERE conname = 'chk_sales_order_source'
|
|
) THEN
|
|
ALTER TABLE sales_order
|
|
ADD CONSTRAINT chk_sales_order_source
|
|
CHECK (order_source IN ('wix', 'direct'));
|
|
END IF;
|
|
END;
|
|
$$;
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1
|
|
FROM pg_constraint
|
|
WHERE conname = 'chk_sales_order_direct_ref_prefix'
|
|
) THEN
|
|
ALTER TABLE sales_order
|
|
ADD CONSTRAINT chk_sales_order_direct_ref_prefix
|
|
CHECK (order_source <> 'direct' OR external_ref LIKE 'DIR-%');
|
|
END IF;
|
|
END;
|
|
$$;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_sales_order_source ON sales_order(order_source);
|
|
|
|
CREATE SEQUENCE IF NOT EXISTS seq_sales_order_direct_ref;
|
|
|
|
CREATE OR REPLACE FUNCTION fn_next_direct_sales_order_ref(
|
|
p_order_date DATE DEFAULT CURRENT_DATE
|
|
) RETURNS TEXT
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
v_seq BIGINT;
|
|
BEGIN
|
|
v_seq := nextval('seq_sales_order_direct_ref');
|
|
RETURN format(
|
|
'DIR-%s-%s',
|
|
to_char(p_order_date, 'YYYYMMDD'),
|
|
lpad(v_seq::TEXT, 5, '0')
|
|
);
|
|
END;
|
|
$$;
|
|
|
|
CREATE OR REPLACE FUNCTION fn_sales_order_assign_direct_ref()
|
|
RETURNS TRIGGER
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
IF NEW.order_source = 'direct' AND (NEW.external_ref IS NULL OR btrim(NEW.external_ref) = '') THEN
|
|
NEW.external_ref := fn_next_direct_sales_order_ref(COALESCE(NEW.order_date::DATE, CURRENT_DATE));
|
|
END IF;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
DROP TRIGGER IF EXISTS trg_sales_order_assign_direct_ref ON sales_order;
|
|
|
|
CREATE TRIGGER trg_sales_order_assign_direct_ref
|
|
BEFORE INSERT OR UPDATE OF order_source, external_ref, order_date ON sales_order
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION fn_sales_order_assign_direct_ref();
|
|
|
|
CREATE OR REPLACE FUNCTION fn_enqueue_sales_order_events()
|
|
RETURNS TRIGGER
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
v_event_key TEXT;
|
|
BEGIN
|
|
IF TG_OP = 'INSERT' THEN
|
|
v_event_key := format('order.imported:%s', NEW.external_ref);
|
|
PERFORM fn_enqueue_event(
|
|
'order.imported',
|
|
v_event_key,
|
|
'sales_order',
|
|
NEW.id::TEXT,
|
|
jsonb_build_object(
|
|
'orderId', NEW.id,
|
|
'externalRef', NEW.external_ref,
|
|
'orderSource', NEW.order_source,
|
|
'orderStatus', NEW.order_status,
|
|
'paymentStatus', NEW.payment_status,
|
|
'occurredAt', NOW()
|
|
)
|
|
);
|
|
ELSIF TG_OP = 'UPDATE' THEN
|
|
IF OLD.order_status IS DISTINCT FROM NEW.order_status AND NEW.order_status = 'cancelled' THEN
|
|
v_event_key := format('order.cancelled.full:%s:%s', NEW.external_ref, COALESCE(NEW.cancelled_at, NOW()));
|
|
PERFORM fn_enqueue_event(
|
|
'order.cancelled.full',
|
|
v_event_key,
|
|
'sales_order',
|
|
NEW.id::TEXT,
|
|
jsonb_build_object(
|
|
'orderId', NEW.id,
|
|
'externalRef', NEW.external_ref,
|
|
'orderSource', NEW.order_source,
|
|
'orderStatus', NEW.order_status,
|
|
'cancelledAt', COALESCE(NEW.cancelled_at, NOW()),
|
|
'cancelledReason', NEW.cancelled_reason
|
|
)
|
|
);
|
|
END IF;
|
|
END IF;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
CREATE OR REPLACE FUNCTION fn_enqueue_partial_cancel_events()
|
|
RETURNS TRIGGER
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
v_order_id BIGINT;
|
|
v_external_ref TEXT;
|
|
v_order_source TEXT;
|
|
v_event_key TEXT;
|
|
BEGIN
|
|
IF NEW.line_status = 'partially_cancelled' AND OLD.line_status IS DISTINCT FROM NEW.line_status THEN
|
|
SELECT so.id, so.external_ref, so.order_source
|
|
INTO v_order_id, v_external_ref, v_order_source
|
|
FROM sales_order so
|
|
WHERE so.id = NEW.sales_order_id;
|
|
|
|
v_event_key := format('order.cancelled.partial:%s:%s:%s', v_external_ref, NEW.id, NEW.qty_cancelled);
|
|
|
|
PERFORM fn_enqueue_event(
|
|
'order.cancelled.partial',
|
|
v_event_key,
|
|
'sales_order_line',
|
|
NEW.id::TEXT,
|
|
jsonb_build_object(
|
|
'orderId', v_order_id,
|
|
'externalRef', v_external_ref,
|
|
'orderSource', v_order_source,
|
|
'lineId', NEW.id,
|
|
'lineNo', NEW.line_no,
|
|
'qty', NEW.qty,
|
|
'qtyCancelled', NEW.qty_cancelled,
|
|
'lineStatus', NEW.line_status,
|
|
'occurredAt', NOW()
|
|
)
|
|
);
|
|
END IF;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
-- Payment methods used by direct/manual sales mask.
|
|
INSERT INTO payment_method (code, label)
|
|
VALUES
|
|
('cash', 'Barzahlung'),
|
|
('paypal', 'PayPal')
|
|
ON CONFLICT (code) DO NOTHING;
|
|
|
|
UPDATE payment_method
|
|
SET label = 'Ueberweisung', updated_at = NOW()
|
|
WHERE code = 'bank_transfer'
|
|
AND label <> 'Ueberweisung';
|
|
|
|
COMMIT;
|