@fayz-ai/db 0.30.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- 225_a_task_can_be_a_call — the one task list carries calls and knows what
|
|
3
|
+
-- record it is about.
|
|
4
|
+
--
|
|
5
|
+
-- The feira campaign's touch 3 wrote 105 calls as CRM activities, out of the
|
|
6
|
+
-- tasks drawer, and the CRM grew its own list over them: two places for the
|
|
7
|
+
-- same to-do (11-03). `tasks` stays the single store, with what a call needs:
|
|
8
|
+
--
|
|
9
|
+
-- * `kind` — 'todo' (the default, what the drawer always had) or 'call';
|
|
10
|
+
-- * `subject_type` / `subject_id` — the record it is about ('crm.deal', <id>),
|
|
11
|
+
-- so the deal shows its open tasks and a done call lands on its timeline;
|
|
12
|
+
-- * `phones` — [{ "label", "number" }], the numbers to try, in order;
|
|
13
|
+
-- * `outcome` — what happened when it was done ('connected', 'no_answer',
|
|
14
|
+
-- 'left_message', 'scheduled', 'replied'), the vocabulary of CRM activities.
|
|
15
|
+
--
|
|
16
|
+
-- Idempotent and replay-safe.
|
|
17
|
+
-- ============================================================================
|
|
18
|
+
|
|
19
|
+
ALTER TABLE public.tasks ADD COLUMN IF NOT EXISTS kind text NOT NULL DEFAULT 'todo';
|
|
20
|
+
ALTER TABLE public.tasks ADD COLUMN IF NOT EXISTS subject_type text;
|
|
21
|
+
ALTER TABLE public.tasks ADD COLUMN IF NOT EXISTS subject_id uuid;
|
|
22
|
+
ALTER TABLE public.tasks ADD COLUMN IF NOT EXISTS phones jsonb NOT NULL DEFAULT '[]'::jsonb;
|
|
23
|
+
ALTER TABLE public.tasks ADD COLUMN IF NOT EXISTS outcome text;
|
|
24
|
+
|
|
25
|
+
DO $$
|
|
26
|
+
BEGIN
|
|
27
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'tasks_kind_check') THEN
|
|
28
|
+
ALTER TABLE public.tasks ADD CONSTRAINT tasks_kind_check CHECK (kind IN ('todo', 'call'));
|
|
29
|
+
END IF;
|
|
30
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'tasks_outcome_check') THEN
|
|
31
|
+
ALTER TABLE public.tasks ADD CONSTRAINT tasks_outcome_check
|
|
32
|
+
CHECK (outcome IS NULL OR outcome IN ('connected', 'no_answer', 'left_message', 'replied', 'scheduled'));
|
|
33
|
+
END IF;
|
|
34
|
+
END $$;
|
|
35
|
+
|
|
36
|
+
CREATE INDEX IF NOT EXISTS tasks_subject_idx ON public.tasks (tenant_id, subject_type, subject_id);
|
|
37
|
+
CREATE INDEX IF NOT EXISTS tasks_open_assignee_idx ON public.tasks (tenant_id, assigned_to_id, due_date)
|
|
38
|
+
WHERE status IN ('todo', 'in_progress');
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- 225 — stock can go below zero when the house says so
|
|
3
|
+
--
|
|
4
|
+
-- stock_apply refused any on_hand below zero. A house that sells before it
|
|
5
|
+
-- produces (Artorius, with no production module yet) switches «Permitir estoque
|
|
6
|
+
-- negativo» on in Configurações › Estoque, so a sale of a product it does not
|
|
7
|
+
-- have yet is recorded, and the negative balance tells it what to produce.
|
|
8
|
+
--
|
|
9
|
+
-- The core does not read the inventory's settings. The inventory, which does,
|
|
10
|
+
-- marks its own transaction with `fayz.stock_allow_negative = on` before it
|
|
11
|
+
-- calls stock_apply (plugin-inventory 037); only then is a negative on_hand
|
|
12
|
+
-- accepted. Every other caller is refused as before.
|
|
13
|
+
--
|
|
14
|
+
-- Idempotent and replay-safe: CREATE OR REPLACE, same signature.
|
|
15
|
+
-- ============================================================================
|
|
16
|
+
|
|
17
|
+
CREATE OR REPLACE FUNCTION public.stock_apply(p_tenant uuid, p_variant uuid, p_unit uuid, p_on_hand numeric DEFAULT 0, p_reserved numeric DEFAULT 0, p_source text DEFAULT 'inventory'::text)
|
|
18
|
+
RETURNS jsonb
|
|
19
|
+
LANGUAGE plpgsql
|
|
20
|
+
SECURITY DEFINER
|
|
21
|
+
SET search_path TO ''
|
|
22
|
+
AS $function$
|
|
23
|
+
DECLARE
|
|
24
|
+
v_on_hand numeric;
|
|
25
|
+
v_reserved numeric;
|
|
26
|
+
BEGIN
|
|
27
|
+
IF p_tenant IS NULL OR p_variant IS NULL THEN
|
|
28
|
+
RAISE EXCEPTION 'stock_apply: tenant and variant are required' USING ERRCODE = '22023';
|
|
29
|
+
END IF;
|
|
30
|
+
|
|
31
|
+
INSERT INTO public.stock_balances (tenant_id, variant_id, unit_id, on_hand, reserved, updated_by)
|
|
32
|
+
VALUES (p_tenant, p_variant, p_unit, coalesce(p_on_hand, 0), greatest(coalesce(p_reserved, 0), 0), p_source)
|
|
33
|
+
ON CONFLICT (tenant_id, variant_id, coalesce(unit_id, '00000000-0000-0000-0000-000000000000'::uuid)) DO UPDATE
|
|
34
|
+
SET on_hand = public.stock_balances.on_hand + coalesce(p_on_hand, 0),
|
|
35
|
+
reserved = greatest(public.stock_balances.reserved + coalesce(p_reserved, 0), 0),
|
|
36
|
+
updated_at = now(),
|
|
37
|
+
updated_by = p_source
|
|
38
|
+
RETURNING on_hand, reserved INTO v_on_hand, v_reserved;
|
|
39
|
+
|
|
40
|
+
-- Below zero is a data question, not a rounding one: the caller that asked for
|
|
41
|
+
-- it is the one that has to answer — unless the inventory, following the
|
|
42
|
+
-- house's «estoque negativo» switch, said it may (225).
|
|
43
|
+
IF v_on_hand < 0 AND coalesce(current_setting('fayz.stock_allow_negative', true), 'off') <> 'on' THEN
|
|
44
|
+
RAISE EXCEPTION 'stock_apply: % would take variant % below zero (%)', p_source, p_variant, v_on_hand
|
|
45
|
+
USING ERRCODE = '23514';
|
|
46
|
+
END IF;
|
|
47
|
+
|
|
48
|
+
RETURN jsonb_build_object('on_hand', v_on_hand, 'reserved', v_reserved, 'available', v_on_hand - v_reserved);
|
|
49
|
+
END $function$;
|
package/package.json
CHANGED