feat(format): default output to dist/examples house style
CI / Test (push) Successful in 1m12s
CI / Build (push) Successful in 30s

Align the formatter defaults and layout with the hand-formatted reference
procedures in dist/examples so a clean `pgtidy fmt` produces the house style.

config.Default():
- align_param_types: false (no type-column alignment in param lists)
- plpgsql_declare_align_type / plpgsql_declare_align_eq: true

Formatter:
- routine header: leading-comma params at column 0, first param at one
  indent, RETURNS/LANGUAGE/volatility/SECURITY each indented one level
- %type / %rowtype printed tight (isPctTypeBoundary)
- DECLARE = / := / DEFAULT column padded only to the widest declaration
  that carries an assignment
- WHERE continuations in body UPDATE/DELETE: AND/OR aligned with WHERE
- EXCEPTION aligned to its enclosing BEGIN; column-0 comment continuations
  kept flush-left

Safety gate:
- SemanticallyEqual tolerates CRLF vs LF inside string literals (normNL);
  the formatter re-emits all layout with st.Newline, so a \r\n inside a
  multi-line string literal is normalisation, not a code change. This was
  why action_init and event_exec_func previously refused to format.

Corpus:
- add the four CRLF reference files as idempotence/safety fixtures
- regenerate test_a and test_mm_proc goldens

FOR...LOOP body indentation keeps the existing +1 convention (LOOP aligned
with FOR); the dist/examples use +2, so loop-body regions differ by
whitespace only.
This commit is contained in:
Hein
2026-09-10 14:54:20 +02:00
parent 94d776e3de
commit 83b215fd25
17 changed files with 3740 additions and 147 deletions
+2
View File
@@ -165,3 +165,5 @@ dist
temp/* temp/*
dist/* dist/*
# Local build of the CLI binary
/pgtidy
+6
View File
@@ -68,6 +68,12 @@ testdata/corpus/ — real-world .pgsql procedures used as the safety/idempoten
not just a test assertion (`pkg/format/format_test.go`); it is enforced at runtime so a not just a test assertion (`pkg/format/format_test.go`); it is enforced at runtime so a
formatter bug can never silently drop or alter code. formatter bug can never silently drop or alter code.
**Line endings**: the formatter re-emits all layout with `st.Newline` (default `\n`), so a
CRLF input file is normalised to LF on write. This includes `\r\n` that sits *inside* a
multi-line string literal — a line-ending change there is layout normalisation, not a change
of code content, so `SemanticallyEqual` compares string tokens modulo `\r\n` ↔ `\n`
(`normNL` in `pkg/format/safety.go`). Set `newline: "\r\n"` in `.pgtidy.yaml` to keep CRLF.
## Commands ## Commands
```bash ```bash
+3 -3
View File
@@ -47,14 +47,14 @@ insert_collapse_values: true # Fold multiple VALUES rows onto fewer lines
# --- Routines (functions / procedures) --- # --- Routines (functions / procedures) ---
align_param_types: true # Pad param names so type column aligns across all params align_param_types: false # Pad param names so type column aligns across all params
routine_as_wrap: true # Newline before AS $$ (false = keep AS on same line) routine_as_wrap: true # Newline before AS $$ (false = keep AS on same line)
# --- PL/pgSQL body --- # --- PL/pgSQL body ---
plpgsql_max_blank_lines: 1 # Max consecutive blank lines in body plpgsql_max_blank_lines: 1 # Max consecutive blank lines in body
plpgsql_declare_align_type: false # Align type column in DECLARE block plpgsql_declare_align_type: true # Align type column in DECLARE block
plpgsql_declare_align_eq: false # Align := / = in DECLARE block plpgsql_declare_align_eq: true # Align := / = in DECLARE block (padded to the widest assigned declaration)
plpgsql_if_then_newline: true # THEN on its own line (false = same line as condition) plpgsql_if_then_newline: true # THEN on its own line (false = same line as condition)
plpgsql_loop_collapse: true # Collapse empty loop bodies to one line plpgsql_loop_collapse: true # Collapse empty loop bodies to one line
+3 -3
View File
@@ -128,7 +128,7 @@ DataGrip enum conventions used below:
| DataGrip key | PgTidy key | Default | Notes | | DataGrip key | PgTidy key | Default | Notes |
|---|---|---|---| |---|---|---|---|
| `ROUTINE_ARG_COMMA` | uses `commas` | `leading` | same setting as query lists | | `ROUTINE_ARG_COMMA` | uses `commas` | `leading` | same setting as query lists |
| `ROUTINE_ARG_ALIGN_TYPES` | `align_param_types` | `true` | align type column in param list | | `ROUTINE_ARG_ALIGN_TYPES` | `align_param_types` | `false` | align type column in param list |
| `ROUTINE_AS_WRAP` | `routine_as_wrap` | `true` | newline before `AS $$` | | `ROUTINE_AS_WRAP` | `routine_as_wrap` | `true` | newline before `AS $$` |
### PL/pgSQL body ### PL/pgSQL body
@@ -136,8 +136,8 @@ DataGrip enum conventions used below:
| DataGrip key | PgTidy key | Default | Notes | | DataGrip key | PgTidy key | Default | Notes |
|---|---|---|---| |---|---|---|---|
| `IMP_COMMON_KEEP_BLANK_LINES_IN_CODE` | `plpgsql_max_blank_lines` | `1` | max consecutive blank lines in body | | `IMP_COMMON_KEEP_BLANK_LINES_IN_CODE` | `plpgsql_max_blank_lines` | `1` | max consecutive blank lines in body |
| `IMP_DECLARE_ALIGN_TYPE` | `plpgsql_declare_align_type` | `false` | align type column in DECLARE block | | `IMP_DECLARE_ALIGN_TYPE` | `plpgsql_declare_align_type` | `true` | align type column in DECLARE block |
| `IMP_DECLARE_ALIGN_EQ` | `plpgsql_declare_align_eq` | `false` | align `:=` / `=` in DECLARE block | | `IMP_DECLARE_ALIGN_EQ` | `plpgsql_declare_align_eq` | `true` | align `:=` / `=` in DECLARE block |
| `IMP_IF_THEN_WRAP_THEN` | `plpgsql_if_then_newline` | `true` | THEN on its own line | | `IMP_IF_THEN_WRAP_THEN` | `plpgsql_if_then_newline` | `true` | THEN on its own line |
| `IMP_LOOP_COLLAPSE` | `plpgsql_loop_collapse` | `true` | collapse empty loop bodies | | `IMP_LOOP_COLLAPSE` | `plpgsql_loop_collapse` | `true` | collapse empty loop bodies |
+4 -2
View File
@@ -213,7 +213,7 @@ as a proxy (new_line for content, inline for single-arg subexpressions).
### ✅ Formatter — routine param alignment (`pkg/format/format.go`) ### ✅ Formatter — routine param alignment (`pkg/format/format.go`)
- `align_param_types`: `alignParamTypes()` pads param names so type columns align; default `true`. - `align_param_types`: `alignParamTypes()` pads param names so type columns align; default `false` (house style: no type-column alignment in param lists).
- `routine_as_wrap`: when `false`, AS stays on the same line as the last option clause. - `routine_as_wrap`: when `false`, AS stays on the same line as the last option clause.
- Golden file `testdata/corpus/test_a.pgsql` updated to reflect aligned params. - Golden file `testdata/corpus/test_a.pgsql` updated to reflect aligned params.
@@ -221,7 +221,9 @@ as a proxy (new_line for content, inline for single-arg subexpressions).
- `plpgsql_max_blank_lines`: blank-line runs capped at the configured limit; default `1`. - `plpgsql_max_blank_lines`: blank-line runs capped at the configured limit; default `1`.
- `plpgsql_declare_align_type` + `plpgsql_declare_align_eq`: two-pass declare formatter - `plpgsql_declare_align_type` + `plpgsql_declare_align_eq`: two-pass declare formatter
measures name/type widths then pads for alignment; `writeDeclareAligned` helper. measures name/type widths then pads for alignment; `writeDeclareAligned` helper. Both
default `true` (house style). The `=` column is padded only to the widest type among
declarations that actually carry an assignment, so a lone `x text = '…';` stays tight.
- `plpgsql_if_then_newline`: when `false`, `joinThenToCondition` merges THEN onto the - `plpgsql_if_then_newline`: when `false`, `joinThenToCondition` merges THEN onto the
preceding condition line. preceding condition line.
- `plpgsql_loop_collapse`: `tryCollapseLoop` detects empty FOR/WHILE loop bodies and - `plpgsql_loop_collapse`: `tryCollapseLoop` detects empty FOR/WHILE loop bodies and
+3 -3
View File
@@ -130,12 +130,12 @@ func Default() Style {
InsertCollapseValues: true, InsertCollapseValues: true,
AlignParamTypes: true, AlignParamTypes: false,
RoutineAsWrap: true, RoutineAsWrap: true,
PlpgsqlMaxBlankLines: 1, PlpgsqlMaxBlankLines: 1,
PlpgsqlDeclareAlignType: false, PlpgsqlDeclareAlignType: true,
PlpgsqlDeclareAlignEq: false, PlpgsqlDeclareAlignEq: true,
PlpgsqlIfThenNewline: true, PlpgsqlIfThenNewline: true,
PlpgsqlLoopCollapse: true, PlpgsqlLoopCollapse: true,
+48 -6
View File
@@ -177,7 +177,10 @@ func formatDeclareVars(b *strings.Builder, toks []cst.Tok, st config.Style) {
if nw > nameColW { if nw > nameColW {
nameColW = nw nameColW = nw
} }
if tw > typeColW { // typeColW drives the '='/':='/DEFAULT column (align_eq only), so
// only declarations that actually carry an assignment participate —
// a bare "name type;" must not widen it.
if tw > typeColW && declHasAssignment(body) {
typeColW = tw typeColW = tw
} }
} }
@@ -207,7 +210,7 @@ func formatDeclareVars(b *strings.Builder, toks []cst.Tok, st config.Style) {
writeDeclareAligned(b, body, st, nameColW, typeColW) writeDeclareAligned(b, body, st, nameColW, typeColW)
} else { } else {
for j, t := range body { for j, t := range body {
if j > 0 && needSpace(body[j-1].Tok, t.Tok) { if j > 0 && needSpace(body[j-1].Tok, t.Tok) && !isPctTypeBoundary(body, j) {
b.WriteByte(' ') b.WriteByte(' ')
} }
b.WriteString(caseText(t.Tok, st)) b.WriteString(caseText(t.Tok, st))
@@ -220,6 +223,32 @@ func formatDeclareVars(b *strings.Builder, toks []cst.Tok, st config.Style) {
} }
} }
// declHasAssignment reports whether a DECLARE variable body (name type … ) has
// a default assignment ( := / = / DEFAULT ) at paren depth 0.
func declHasAssignment(body []cst.Tok) bool {
depth := 0
for _, t := range body {
switch t.Tok.Kind {
case lexer.LParen, lexer.LBracket:
depth++
case lexer.RParen, lexer.RBracket:
if depth > 0 {
depth--
}
}
if depth != 0 {
continue
}
if t.Tok.Kind == lexer.Operator && (t.Tok.Text == ":=" || t.Tok.Text == "=") {
return true
}
if t.Tok.Kind == lexer.Ident && lowerASCII(t.Tok.Text) == "default" {
return true
}
}
return false
}
// declareNameTypeWidth returns the rendered width of the name and type portions // declareNameTypeWidth returns the rendered width of the name and type portions
// of a DECLARE variable declaration (without the default assignment). // of a DECLARE variable declaration (without the default assignment).
// Format is: [name type [:= default]] or [name type [DEFAULT default]]. // Format is: [name type [:= default]] or [name type [DEFAULT default]].
@@ -256,7 +285,7 @@ func declareNameTypeWidth(body []cst.Tok, st config.Style) (nameW, typeW int) {
} }
var tb strings.Builder var tb strings.Builder
for j, t := range typeTokens { for j, t := range typeTokens {
if j > 0 && needSpace(typeTokens[j-1].Tok, t.Tok) { if j > 0 && needSpace(typeTokens[j-1].Tok, t.Tok) && !isPctTypeBoundary(typeTokens, j) {
tb.WriteByte(' ') tb.WriteByte(' ')
} }
tb.WriteString(caseText(t.Tok, st)) tb.WriteString(caseText(t.Tok, st))
@@ -315,7 +344,7 @@ func writeDeclareAligned(b *strings.Builder, body []cst.Tok, st config.Style, na
var typeStr strings.Builder var typeStr strings.Builder
for j, t := range typeTokens { for j, t := range typeTokens {
if j > 0 && needSpace(typeTokens[j-1].Tok, t.Tok) { if j > 0 && needSpace(typeTokens[j-1].Tok, t.Tok) && !isPctTypeBoundary(typeTokens, j) {
typeStr.WriteByte(' ') typeStr.WriteByte(' ')
} }
typeStr.WriteString(caseText(t.Tok, st)) typeStr.WriteString(caseText(t.Tok, st))
@@ -429,8 +458,13 @@ func formatBodyStatements(text string, st config.Style) string {
} }
case "exception": case "exception":
inException = true inException = true
// EXCEPTION belongs to its nearest enclosing BEGIN, so align it one
// level in from the current block body (col 0 for the outermost).
effectiveDepth = blockDepth - 1
if effectiveDepth < 0 {
effectiveDepth = 0 effectiveDepth = 0
} }
}
baseIndent := strings.Repeat(st.Indent, effectiveDepth) baseIndent := strings.Repeat(st.Indent, effectiveDepth)
@@ -589,7 +623,13 @@ func formatBodyStmtLines(lines []bline, baseIndent string, st config.Style) []st
for i, ll := range lines { for i, ll := range lines {
text := ll.text text := ll.text
indent := baseIndent indent := baseIndent
if i > 0 && ll.indent != "" && !isStandaloneBodyKeyword(ll.text, "then", "else", "elsif", "elseif") { switch {
case i > 0 && ll.indent == "" && len(significantBodyTokens(text)) == 0:
// A column-0 comment line trailing a multi-line (commented-out)
// statement is a continuation the author left flush-left — keep it
// there rather than re-indenting it to block depth.
indent = ""
case i > 0 && ll.indent != "" && !isStandaloneBodyKeyword(ll.text, "then", "else", "elsif", "elseif"):
indent = ll.indent indent = ll.indent
} }
out = append(out, indent+text) out = append(out, indent+text)
@@ -639,7 +679,9 @@ func reindentBodyDML(lines []bline, baseIndent string, st config.Style) []string
continue continue
} }
if lineDepth == 0 && (kw == "and" || kw == "or") { if lineDepth == 0 && (kw == "and" || kw == "or") {
out = append(out, baseIndent+st.Indent+strings.TrimSpace(text)) // House style: AND/OR line up with the WHERE keyword; the first
// predicate is indented two levels under it.
out = append(out, baseIndent+strings.TrimSpace(text))
afterWhere = false afterWhere = false
updateBodyParenDepth(text, &parenDepth) updateBodyParenDepth(text, &parenDepth)
continue continue
+1 -1
View File
@@ -462,7 +462,7 @@ func dmlInline(toks []cst.Tok, st config.Style) string {
} }
var b strings.Builder var b strings.Builder
for i, t := range toks { for i, t := range toks {
if i > 0 && needSpace(toks[i-1].Tok, t.Tok) { if i > 0 && needSpace(toks[i-1].Tok, t.Tok) && !isPctTypeBoundary(toks, i) {
b.WriteByte(' ') b.WriteByte(' ')
} }
// Space after comma in calls: func(a, b) vs func(a,b). // Space after comma in calls: func(a, b) vs func(a,b).
+31 -5
View File
@@ -147,8 +147,9 @@ func (p *printer) writeCreateFunction(cf *cst.CreateFunction) {
paramTexts = alignParamTypes(paramTexts) paramTexts = alignParamTypes(paramTexts)
} }
first := p.st.Indent + " " // align item text one column past the comma // House style: first parameter indented one level; leading-comma
cont := p.st.Indent // continuation lines carry the comma at column 0 followed by one space.
first := p.st.Indent
for i, text := range paramTexts { for i, text := range paramTexts {
param := cf.Params[i] param := cf.Params[i]
p.nl() p.nl()
@@ -159,8 +160,7 @@ func (p *printer) writeCreateFunction(cf *cst.CreateFunction) {
p.b.WriteString(",") p.b.WriteString(",")
} }
} else { } else {
p.b.WriteString(cont) p.b.WriteString(", ")
p.b.WriteString(",")
p.b.WriteString(text) p.b.WriteString(text)
} }
// Emit trailing inline comment from the separator (e.g. --description after param). // Emit trailing inline comment from the separator (e.g. --description after param).
@@ -179,6 +179,7 @@ func (p *printer) writeCreateFunction(cf *cst.CreateFunction) {
for _, clause := range cf.Options { for _, clause := range cf.Options {
p.nl() p.nl()
p.b.WriteString(p.st.Indent)
p.b.WriteString(p.inline(clause)) p.b.WriteString(p.inline(clause))
} }
if cf.As != nil { if cf.As != nil {
@@ -218,7 +219,7 @@ func (p *printer) inline(toks []cst.Tok) string {
} }
var b strings.Builder var b strings.Builder
for i, t := range toks { for i, t := range toks {
if i > 0 && needSpace(toks[i-1].Tok, t.Tok) { if i > 0 && needSpace(toks[i-1].Tok, t.Tok) && !isPctTypeBoundary(toks, i) {
b.WriteByte(' ') b.WriteByte(' ')
} }
var prev lexer.Token var prev lexer.Token
@@ -254,6 +255,31 @@ func (p *printer) trailingComments(lead cst.Trivia) {
// tightOps are operators printed without surrounding spaces. // tightOps are operators printed without surrounding spaces.
var tightOps = map[string]bool{"::": true, ":": true, "->": true, "->>": true} var tightOps = map[string]bool{"::": true, ":": true, "->": true, "->>": true}
// isPctTypeBoundary reports whether the gap between toks[i-1] and toks[i] sits
// inside a %TYPE / %ROWTYPE modifier (e.g. core.tbl%rowtype), which is printed
// tight like "::" rather than as the modulo operator.
func isPctTypeBoundary(toks []cst.Tok, i int) bool {
if i <= 0 || i >= len(toks) {
return false
}
isPct := func(t lexer.Token) bool { return t.Kind == lexer.Operator && t.Text == "%" }
isTypeWord := func(t lexer.Token) bool {
if t.Kind != lexer.Ident {
return false
}
l := lowerASCII(t.Text)
return l == "type" || l == "rowtype"
}
prev, cur := toks[i-1].Tok, toks[i].Tok
if isPct(prev) && isTypeWord(cur) {
return true // space after %
}
if isPct(cur) && i+1 < len(toks) && isTypeWord(toks[i+1].Tok) {
return true // space before %
}
return false
}
// parenKws are keywords that always take a space before '(' because they // parenKws are keywords that always take a space before '(' because they
// introduce a subquery or a bracketed clause, not a function-call argument list. // introduce a subquery or a bracketed clause, not a function-call argument list.
var parenKws = map[string]bool{ var parenKws = map[string]bool{
+7 -7
View File
@@ -24,12 +24,12 @@ func TestFormatHeaderGolden(t *testing.T) {
want := "--select * from dropall('resolvespec_login');\n" + want := "--select * from dropall('resolvespec_login');\n" +
"CREATE OR REPLACE FUNCTION resolvespec_login(\n" + "CREATE OR REPLACE FUNCTION resolvespec_login(\n" +
" INOUT p_data jsonb\n" + " INOUT p_data jsonb\n" +
" ,OUT p_success boolean\n" + ", OUT p_success boolean\n" +
" ,OUT p_error text\n" + ", OUT p_error text\n" +
")\n" + ")\n" +
"LANGUAGE plpgsql\n" + " LANGUAGE plpgsql\n" +
"VOLATILE\n" + " VOLATILE\n" +
"SECURITY DEFINER\n" + " SECURITY DEFINER\n" +
"AS\n" + "AS\n" +
"$$\nbegin end;\n$$;\n" "$$\nbegin end;\n$$;\n"
@@ -130,8 +130,8 @@ func TestFormatIssue1PLpgSQLIndenting(t *testing.T) {
want := "CREATE FUNCTION f(\n" + want := "CREATE FUNCTION f(\n" +
")\n" + ")\n" +
"RETURNS void\n" + " RETURNS void\n" +
"LANGUAGE plpgsql\n" + " LANGUAGE plpgsql\n" +
"AS\n" + "AS\n" +
"$$\n" + "$$\n" +
"DECLARE\n" + "DECLARE\n" +
+12
View File
@@ -32,6 +32,14 @@ func SemanticallyEqual(a, b string) bool {
if !strings.EqualFold(ta[i].Text, tb[i].Text) { if !strings.EqualFold(ta[i].Text, tb[i].Text) {
return false return false
} }
case lexer.String, lexer.EscapeString, lexer.BitString, lexer.HexString, lexer.UnicodeString:
// A CRLF vs LF difference inside a multi-line string literal is a
// line-ending normalisation, not a change of code content — the
// formatter always re-emits layout with st.Newline. Compare the
// literal modulo \r\n ↔ \n.
if normNL(ta[i].Text) != normNL(tb[i].Text) {
return false
}
case lexer.DollarString: case lexer.DollarString:
_, innerA, _, okA := splitDollarQuote(ta[i].Text) _, innerA, _, okA := splitDollarQuote(ta[i].Text)
_, innerB, _, okB := splitDollarQuote(tb[i].Text) _, innerB, _, okB := splitDollarQuote(tb[i].Text)
@@ -47,6 +55,10 @@ func SemanticallyEqual(a, b string) bool {
return true return true
} }
// normNL collapses CRLF to LF so string literals compare independent of the
// source file's line-ending convention.
func normNL(s string) string { return strings.ReplaceAll(s, "\r\n", "\n") }
// significantTokens lexes src and returns its tokens excluding EOF and trivia // significantTokens lexes src and returns its tokens excluding EOF and trivia
// (whitespace/comments). // (whitespace/comments).
func significantTokens(src string) []lexer.Token { func significantTokens(src string) []lexer.Token {
+797
View File
@@ -0,0 +1,797 @@
--select * from dropall('action_init','core');
CREATE OR REPLACE FUNCTION core.action_init(
p_table text
, p_rid integer
, INOUT p_parms jsonb default json_build_object()
, OUT p_retval integer
, OUT p_errmsg text
)
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
AS
$$
DECLARE
--Error Handling--
m_funcname text = 'core.action_init';
m_errmsg text;
m_errcontext text;
m_errdetail text;
m_errhint text;
m_errstate text;
m_retval integer;
--Error Handling--
--r_workflow core.workflowitem%rowtype;
r_tasklist core.tasklist%rowtype;
r_taskitem core.taskitem%rowtype;
r_taskitem_prev core.taskitem%rowtype;
r_taskitem_parent core.taskitem%rowtype;
r_mastertaskitem core.mastertaskitem%rowtype;
r_mastertaskitemevent core.mastertaskitemevent%rowtype;
r_taskitemevent core.taskitemevent%rowtype;
r_taskitemevent_parent core.taskitemevent%rowtype;
m_rid_hub_user integer;
m_rid_hub_payload integer;
m_temp_rid integer;
m_temp_rid_list integer[];
j_results jsonb;
BEGIN
p_retval = 0;
p_errmsg = '';
m_rid_hub_user = _bv(core.f_get_user_hub_rid(), (
select hub.rid_hub
from core.hub
where hub.hubtype = 'program'
limit 1
));
m_rid_hub_payload = _try_integers(p_parms ->> 'rid_hub', p_parms ->> 'rid_hub_payload');
if nv(p_rid) = 0
then
raise 'Invalid or no p_rid';
end if;
---select * from meta.table_prefix t where t.tablename = 'mastertaskitemevent'
if p_table::citext in ('taskitemevent', 'tiv')
then
raise exception 'Action Init is not allowed on task item events. Please use the mastertaskitemevent or taskitem as entry point.';
elsif p_table::citext in ('mastertaskitemevent', 'mtev')
then
select *
from core.mastertaskitemevent mtev
where mtev.rid_mastertaskitemevent = p_rid
into r_mastertaskitemevent;
if r_mastertaskitemevent.inactive > 0
then
raise exception 'The template task item event is inactive. rid_mastertaskitemevent = %',r_mastertaskitemevent.rid_mastertaskitemevent;
end if;
select ttie.*
from core.taskitemevent ttie
where ttie.rid_taskitemevent = _try_integer(p_parms ->> 'parent_rid_taskitemevent', 0)
into r_taskitemevent_parent;
-- try to get the given task item
select *
from core.taskitem ti
where
ti.rid_taskitem = _try_integer(p_parms ->> 'rid_taskitem', -1)
and ti.rid_mastertaskitem = r_mastertaskitemevent.rid_mastertaskitem
into r_taskitem;
if _try_integer(p_parms ->> 'parent_rid_taskitem', 0) > 0
then
select *
from core.taskitem ti
where ti.rid_taskitem = _try_integer(p_parms ->> 'parent_rid_taskitem', 0)
into r_taskitem_parent;
end if;
select *
from core.tasklist tl
where tl.rid_tasklist = r_taskitem.rid_tasklist
into r_tasklist;
-- perform log_event(m_funcname,format(E'Action Init via %s=%s Item:%s(%s rid_taskitem:%s[%s] < %s %s[%s]) Event:%s(%s[%s],parent_rid_taskitemevent:%s[%s])
-- p_parms:%s',p_table,p_rid
-- , r_mastertaskitem.description, r_mastertaskitem.rid_mastertaskitem,r_taskitem.rid_taskitem
-- ,r_taskitem.status, r_taskitem_parent.description
-- ,r_taskitem_parent.rid_taskitem,r_taskitem_parent.status
-- , r_mastertaskitemevent.description,r_mastertaskitemevent.status, r_mastertaskitemevent.rid_mastertaskitemevent
-- , r_taskitemevent_parent.rid_taskitemevent, r_taskitemevent_parent.status
-- , p_parms),bt_enum('eventlog','local notice'));
-- raise 'p_rid=%=% r_taskitem.status =% r_taskitem_parent.status=%,% r_mastertaskitemevent.status=% pps=%'
-- ,p_table,p_rid, r_taskitem.status,r_taskitem_parent.description,r_taskitem_parent.status, r_mastertaskitemevent.status
-- ,(select ti.status
-- from core.taskitem ti
-- where ti.rid_taskitem = r_taskitem_parent.rid_taskitem_parentaction);
-- if r_mastertaskitemevent.status = core._enumi('eventstatus','complete')
-- and r_taskitem_parent.rid_taskitem > 0
-- and exists (
-- select 1
-- from core.taskitem ti
-- where ti.rid_taskitem = r_taskitem_parent.rid_taskitem_parentaction
-- and ti.status in (core._enumi('eventstatus','complete')
-- ,core._enumi('eventstatus','error')
-- ,core._enumi('eventstatus','retry'))
-- )
-- then
-- r_taskitem = null;
--
-- end if;
--If there is no action, try getting the same open one of this type for this hub
if nv(r_taskitem.rid_taskitem) = 0
then
--Create item linked to task for this hub if not found
select r.p_retval, r.p_errmsg, r.p_a_rid_taskitem, r.p_parameters
from core.taskitem_get_or_prime(_jsonb_object_cat(
_jsonb_object_cat(r_taskitem_parent.jsonvalue
, jsonb_build_object('AOP', null, 'controls', null, 'rid_taskitem', null, 'message', null, 'subject', null,
'alerttype', null)
)
, p_parms
, jsonb_build_object(
'rid_mastertaskitem', r_mastertaskitemevent.rid_mastertaskitem
, 'rid_mastertaskitemevent', r_mastertaskitemevent.rid_mastertaskitemevent
, 'parent_rid_taskitemevent', r_taskitemevent_parent.rid_taskitemevent
, 'parent_rid_taskitem', _bv(r_taskitem_parent.rid_taskitem
, _try_integer(p_parms ->> 'parent_rid_taskitem', 0)
)
, 'rid_tasklist_prev', _try_integers(p_parms ->> 'rid_tasklist_prev', p_parms ->> 'rid_tasklist'
, r_tasklist.rid_tasklist::text, r_taskitem.rid_tasklist::text)
, 'rid_taskitem_parentaction', p_parms -> 'rid_taskitem_parentaction'
--,'rid_tasklist', r_tasklist.rid_tasklist
)
)) r
into m_retval,m_errmsg,m_temp_rid_list,j_results;
if m_retval > 0
then
raise exception '%',m_errmsg using hint = 'in taskitem_get_or_prime 2';
end if;
else
m_temp_rid_list = array [r_taskitem.rid_taskitem]::integer[];
end if;
p_parms = jsonb_build_object();
for m_temp_rid in (
select u.n
from unnest(m_temp_rid_list) u(n)
)
loop
select *
from core.taskitem ti
where ti.rid_taskitem = m_temp_rid
into r_taskitem;
select *
from core.tasklist tl
where tl.rid_tasklist = r_taskitem.rid_tasklist
into r_tasklist;
if nv(r_tasklist.rid_tasklist) = 0
then
select *
from core.tasklist tl
where
tl.rid_tasklist = r_taskitem.rid_tasklist
or nv(r_taskitem.rid_tasklist) = 0
and
(tl.rid_hub = m_rid_hub_payload
or tl.rid_hub = r_taskitem_parent.rid_hub
)
and tl.rid_mastertask in (
select mti.rid_mastertask
from core.mastertaskitem mti
where
mti.rid_mastertaskitem = r_mastertaskitemevent.rid_mastertaskitem
and coalesce(mti.inactive, 0) = 0
)
order by tl.rid_tasklist desc
limit 1
into r_tasklist;
end if;
select tie.*
from core.taskitemevent tie
where
tie.rid_taskitem = r_taskitem.rid_taskitem
and tie.rid_mastertaskitemevent = r_mastertaskitemevent.rid_mastertaskitemevent
--and tie.status = r_mastertaskitemevent.status
order by tie.rid_taskitemevent desc
limit 1
into r_taskitemevent;
perform log_event(m_funcname, format(E'__Processing task item %s(%s, status=%s) for event %s(%s) status=%s'
, r_taskitem.description, r_taskitem.rid_taskitem, r_taskitem.status
, r_taskitemevent.description, r_mastertaskitemevent.rid_mastertaskitemevent, r_taskitemevent.status
), bt_enum('eventlog', 'local notice'));
if nv(r_taskitem.status) in (4, 5, 6, 11) --11 Resolved
and r_mastertaskitemevent.status is distinct from r_taskitem.status
and existS (
select 1
from core.taskitemevent e
where
e.rid_taskitem = r_taskitem.rid_taskitem
and e.status = r_taskitem.status
)
--Or errors to errors
-- or nv(r_taskitem.status) in (10, 11)
-- and nv(r_taskitemevent.status) in (1, 2, 11, 10)
-- and not exists (
-- select 1
-- from core.taskitem ti2
-- where ti2.rid_parenttaskitem = r_taskitem.rid_taskitem
-- and ti2.status in (1,2,10,11)
-- )
-- )
-- and nv(r_mastertaskitem.jsonvalue->'AOP'->>'errorcode') = ''
or p_parms ->> 'new_task' in ('1', 'true')
then
select r.p_retval, r.p_errmsg, r.p_a_rid_taskitem, r.p_parameters
from core.taskitem_get_or_prime(_jsonb_object_cat(
_jsonb_object_cat(r_taskitem.jsonvalue, jsonb_build_object('AOP', null, 'controls', null)),
p_parms
, jsonb_build_object(
'rid_mastertaskitem', r_mastertaskitemevent.rid_mastertaskitem
, 'rid_mastertaskitemevent', r_mastertaskitemevent.rid_mastertaskitemevent
, 'parent_rid_taskitemevent', r_taskitemevent.rid_taskitemevent
, 'rid_tasklist', r_tasklist.rid_tasklist
, 'parent_rid_taskitem'
, _bv(r_taskitem.rid_taskitem
, _try_integer(p_parms ->> 'parent_rid_taskitem', 0)
, r_taskitem_parent.rid_taskitem)
, 'new_item', false
, 'status', 1
, 'rid_tasklist_prev', _try_integers(p_parms ->> 'rid_tasklist_prev', p_parms ->> 'rid_tasklist',
r_taskitem.rid_tasklist::text)
, 'rid_taskitem_parentaction', p_parms -> 'rid_taskitem_parentaction'
)
)) r
into m_retval,m_errmsg,m_temp_rid_list,j_results;
if m_retval > 0
then
raise exception '%',m_errmsg using hint = 'in taskitem_get_or_prime 2';
end if;
--raise notice 'Re-evaluated task item % for event % m_temp_rid_list=%',r_taskitem.rid_taskitem,r_mastertaskitemevent.rid_mastertaskitemevent, m_temp_rid_list;
if array_length(m_temp_rid_list, 1) > 1
and r_taskitem.rid_taskitem <> any (m_temp_rid_list)
or (p_parms ->> 'new_task' in ('1', 'true')
and r_taskitem.status in (4, 11)
)
then
perform log_event(m_funcname, format(E'*.* Fired event %s(%s) for completed action : %s New Actions: %s'
, r_mastertaskitemevent.description, r_mastertaskitemevent.rid_mastertaskitemevent, r_taskitem.description
, m_temp_rid_list), bt_enum('eventlog', 'debug'));
r_taskitem_prev = r_taskitem;
select ti.rid_taskitem
from core.taskitem ti
where
ti.rid_taskitem = any (m_temp_rid_list)
and ti.rid_mastertaskitem = r_taskitem.rid_mastertaskitem
into r_taskitem;
select *
from core.mastertaskitem mti
where mti.rid_mastertaskitem = r_taskitem.rid_mastertaskitem
into r_mastertaskitem;
r_taskitemevent = null;
-- else
--
-- perform log_event(m_funcname,format(E'Cannot fire event (Already Done,Cancelled,Error) (%s,%s,%s), on %s(%s) status = %s'
-- ,r_mastertaskitemevent.description
-- ,r_mastertaskitemevent.rid_mastertaskitemevent
-- ,r_mastertaskitemevent.status
-- ,r_taskitem.rid_taskitem
-- ,r_taskitem.description
-- ,r_taskitem.status
-- ),bt_enum('eventlog','debug'));
--
-- continue;
end if;
end if;
---Allow firing events again.
if nv(r_taskitemevent.rid_taskitemevent) > 0
then
-- if nv(r_taskitemevent.retval) < 2
-- then
perform log_event(m_funcname, format(E'**Updating event %s(%s) for action : %s'
, r_mastertaskitemevent.description, r_mastertaskitemevent.rid_mastertaskitemevent, r_taskitem.description
), bt_enum('eventlog', 'debug'));
--SET session_replication_role = DEFAULT;
update core.taskitemevent u
set
retval = 0
, createddatetime = now()
, jsonvalue = _jsonb_object_cat(u.jsonvalue, p_parms -> '_event_jsonvalue',
jsonb_build_object('rid_mastertaskitem_complete', case
when
_try_integer(
r_taskitemevent_parent.jsonvalue ->>
'rid_mastertaskitem_complete',
0) <>
r_mastertaskitemevent.rid_mastertaskitem
then r_taskitemevent_parent.jsonvalue ->> 'rid_mastertaskitem_complete'
else null
end
))
where u.rid_taskitemevent = r_taskitemevent.rid_taskitemevent
returning u.*
into r_taskitemevent;
select r.p_retval, r.p_errmsg
from core.event_created(r_taskitemevent.rid_taskitemevent) r
into m_retval,m_errmsg;
if m_retval > 0
then
raise exception '%',m_errmsg;
end if;
update core.taskitemevent u
set
jsonvalue = _jsonb_object_cat(u.jsonvalue, jsonb_build_object('rid_taskitemevent_retries',
_jsonb_object_cat(u.jsonvalue ->
'rid_taskitemevent_retries',
jsonb_build_array(r_taskitemevent.rid_taskitemevent))))
where u.rid_taskitemevent = r_taskitemevent_parent.rid_taskitemevent;
-- end if;
else
--SET session_replication_role = DEFAULT;
insert
into core.taskitemevent( createddatetime
, description
, guid
, rid_mastertaskitemevent
, rid_taskitem
, duedatetime
, errmsg
, escalated
, outcome
, status
, jsonvalue)
select now()
, format('%s %s', evt.description, nv((
select count(1)
from core.taskitemevent ev2
where
ev2.rid_taskitem = r_taskitem.rid_taskitem
and ev2.rid_mastertaskitemevent = r_mastertaskitemevent.rid_mastertaskitemevent
)) + 1
)
, newid()
, r_mastertaskitemevent.rid_mastertaskitemevent
, r_taskitem.rid_taskitem
, (
select eri.p_timestamp
from core.interval_fetch('mastertaskitemevent', r_mastertaskitemevent.rid_mastertaskitemevent
, r_taskitem.rid_hub, 'duedatetime',
jsonb_build_object('rid_taskitem', r_taskitem.rid_taskitem)) eri
limit 1
)
, null
, _try_integer(p_parms ->> 'escalated', 0)
, evt.outcome
, evt.status
, _jsonb_object_cat(p_parms -> '_event_jsonvalue', case
when nv(r_taskitem.rid_taskitem) = 0
then jsonb_build_object('rid_hub', m_rid_hub_payload)
else jsonb_build_object()
end
, jsonb_build_object('parent_rid_taskitem',
_try_integer(p_parms ->> 'parent_rid_taskitem', r_taskitem.rid_taskitem)
, 'parent_rid_taskitemevent', r_taskitemevent_parent.rid_taskitemevent
, 'rid_mastertaskitem_complete', case
when _try_integer(
r_taskitemevent_parent.jsonvalue ->>
'rid_mastertaskitem_complete', 0) <>
evt.rid_mastertaskitem
then r_taskitemevent_parent.jsonvalue ->> 'rid_mastertaskitem_complete'
else null
end)
)
from core.mastertaskitemevent evt
where evt.rid_mastertaskitemevent = r_mastertaskitemevent.rid_mastertaskitemevent
returning taskitemevent.*
into r_taskitemevent;
if r_taskitemevent.rid_taskitemevent > 0
then
perform log_event(m_funcname, format(E'**Created event %s(%s) for action : %s'
, r_mastertaskitemevent.description, r_mastertaskitemevent.rid_mastertaskitemevent, r_taskitem.description
), bt_enum('eventlog', 'debug'));
update core.taskitemevent u
set
jsonvalue = _jsonb_object_cat(u.jsonvalue, jsonb_build_object('rid_taskitemevent_spawned',
_jsonb_object_cat(u.jsonvalue ->
'rid_taskitemevent_spawned',
jsonb_build_array(r_taskitemevent.rid_taskitemevent))))
where u.rid_taskitemevent = r_taskitemevent_parent.rid_taskitemevent;
end if;
end if;
/*
if nv(r_taskitemevent.rid_taskitemevent) > 0
then
-- if nv(r_taskitemevent.retval) < 2
-- then
perform log_event(m_funcname,format(E'Updating event %s(%s) for action : %s'
,r_mastertaskitemevent.description,r_mastertaskitemevent.rid_mastertaskitemevent, r_taskitem.description
),bt_enum('eventlog','debug'));
perform meta.add_transaction_event(txid_current(), 'core.action_init'
,replace(replace(replace(replace(replace($CC$
DO $ICC$
DECLARE
m_retval integer;
m_errmsg text;
r_taskitemevent core.taskitemevent%rowtype;
r_taskitemevent_parent core.taskitemevent%rowtype;
r_mastertaskitemevent core.mastertaskitemevent%rowtype;
BEGIN
select *
from core.taskitemevent tie
where tie.rid_taskitemevent = [rid_taskitemevent]
into r_taskitemevent;
select *
from core.taskitemevent tie
where tie.rid_taskitemevent = [rid_taskitemevent_parent]
into r_taskitemevent_parent;
select *
from core.mastertaskitemevent t
where t.rid_mastertaskitemevent = [rid_mastertaskitemevent]
into r_mastertaskitemevent;
update core.taskitemevent u
set
retval = 0
, createddatetime = now()
, jsonvalue = _jsonb_object_cat(u.jsonvalue,$JJA$[event_json_value]$JJA$::jsonb, jsonb_build_object('rid_mastertaskitem_complete', case
when
_try_integer(
r_taskitemevent_parent.jsonvalue ->>
'rid_mastertaskitem_complete',
0) <>
r_mastertaskitemevent.rid_mastertaskitem
then r_taskitemevent_parent.jsonvalue ->> 'rid_mastertaskitem_complete'
else null
end
))
where u.rid_taskitemevent = r_taskitemevent.rid_taskitemevent
returning u.*
into r_taskitemevent;
select r.p_retval,r.p_errmsg
from core.event_created(r_taskitemevent.rid_taskitemevent) r
into m_retval,m_errmsg;
if m_retval > 0
then
raise exception '%',m_errmsg;
end if;
update core.taskitemevent u
set
jsonvalue = _jsonb_object_cat(u.jsonvalue, jsonb_build_object('rid_taskitemevent_retries',
_jsonb_object_cat(u.jsonvalue -> 'rid_taskitemevent_retries',
jsonb_build_array(r_taskitemevent.rid_taskitemevent))))
where u.rid_taskitemevent = r_taskitemevent_parent.rid_taskitemevent;
END;
$ICC$;
$CC$,'[rid_taskitemevent_parent]', nv(r_taskitemevent_parent.rid_taskitemevent)::text)
,'[rid_taskitemevent]', nv(r_taskitemevent.rid_taskitemevent)::text)
,'[rid_mastertaskitemevent]', nv(r_mastertaskitemevent.rid_mastertaskitemevent)::text)
,'[rid_taskitem]', nv(r_taskitem.rid_taskitem)::text)
,'[event_json_value]' ,coalesce((p_parms->'_event_jsonvalue')::text,'{}'))
)
,30, format('action_init_%s',r_taskitemevent.rid_taskitemevent);
SET session_replication_role = DEFAULT;
*/
-------------------------------------------__Recursive Rules__---------------------------------------------------
-- --activate rule
-- if r_taskitemevent_parent.rid_taskitemevent > 0
-- and r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_activate' is not null
-- and _try_integer(r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_activate',-1) > 0
-- and not exists (
-- select 1
-- from core.taskitem ti
-- where ti.rid_mastertaskitem = _try_integer(r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_activate',-1)
-- and ti.rid_hub = m_rid_hub_payload
-- )
-- then
-- if _try_integer(r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_activate',-1) <> r_taskitem.rid_mastertaskitem
-- and _try_integer(r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_activate',-1) <> nv(r_mastertaskitem.rid_parentmastertaskitem)
-- then
-- insert into core.taskitemevent(rid_taskitem,rid_mastertaskitemevent,description,status,createddatetime,guid,jsonvalue)
-- select r_taskitem.rid_taskitem
-- , mtev.rid_mastertaskitemevent
-- , mtev.description
-- , mtev.status
-- , now()
-- , newid()
-- , _jsonb_object_cat(mtev.jsonvalue,p_parms->'_event_jsonvalue', jsonb_build_object('rid_mastertaskitem_activate',r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_activate', 'simulated', true
-- , 'parent_rid_taskitem',_try_integer(p_parms ->> 'parent_rid_taskitem',0)
-- ))
-- from core.mastertaskitemevent mtev
-- where mtev.rid_mastertaskitem = r_taskitem.rid_mastertaskitem
-- and coalesce(mtev.inactive,0) = 0
-- and mtev.status = 2
-- and not exists (
-- select 1
-- from core.taskitemevent tie
-- where tie.rid_taskitem = r_taskitem.rid_taskitem
-- and tie.rid_mastertaskitemevent = mtev.rid_mastertaskitemevent
-- )
-- ;
-- elseif _try_integer(r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_activate',-1) = r_taskitem.rid_mastertaskitem
-- then
-- --We reached the target taskitem, so we can mark it activate
-- insert into core.taskitemevent(rid_taskitem,rid_mastertaskitemevent,description,status,createddatetime,guid,jsonvalue)
-- select r_taskitem.rid_taskitem
-- , mtev.rid_mastertaskitemevent
-- , mtev.description
-- , mtev.status
-- , now()
-- , newid()
-- , _jsonb_object_cat( mtev.jsonvalue,p_parms->'_event_jsonvalue',jsonb_build_object('parent_rid_taskitem',_try_integer(p_parms ->> 'parent_rid_taskitem',0)))
-- from core.mastertaskitemevent mtev
-- where mtev.rid_mastertaskitem = r_taskitem.rid_mastertaskitem
-- and coalesce(mtev.inactive,0) = 0
-- and mtev.status = 2
-- and not exists (
-- select 1
-- from core.taskitemevent tie
-- where tie.rid_taskitem = r_taskitem.rid_taskitem
-- and tie.rid_mastertaskitemevent = mtev.rid_mastertaskitemevent
-- )
-- ;
-- end if;
--
-- end if;
--
-- --complete rule
-- if r_taskitemevent_parent.rid_taskitemevent > 0
-- and r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_complete' is not null
-- and _try_integer(r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_complete',-1) > 0
-- and not exists (
-- select 1
-- from core.taskitem ti
-- where ti.rid_mastertaskitem = _try_integer(r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_complete',-1)
-- and ti.rid_hub = m_rid_hub_payload
-- )
-- then
-- if _try_integer(r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_complete',-1) <> r_taskitem.rid_mastertaskitem
-- and _try_integer(r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_complete',-1) <> nv(r_mastertaskitem.rid_parentmastertaskitem)
-- then
-- insert into core.taskitemevent(rid_taskitem,rid_mastertaskitemevent,description,status,createddatetime,guid,jsonvalue)
-- select r_taskitem.rid_taskitem
-- , mtev.rid_mastertaskitemevent
-- , mtev.description
-- , mtev.status
-- , now()
-- , newid()
-- , _jsonb_object_cat(mtev.jsonvalue,p_parms->'_event_jsonvalue', jsonb_build_object('rid_mastertaskitem_complete',r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_complete', 'simulated', true, 'parent_rid_taskitem',_try_integer(p_parms ->> 'parent_rid_taskitem',0)))
-- from core.mastertaskitemevent mtev
-- where mtev.rid_mastertaskitem = r_taskitem.rid_mastertaskitem
-- and coalesce(mtev.inactive,0) = 0
-- and mtev.status = 4
-- and not exists (
-- select 1
-- from core.taskitemevent tie
-- where tie.rid_taskitem = r_taskitem.rid_taskitem
-- and tie.rid_mastertaskitemevent = mtev.rid_mastertaskitemevent
-- )
-- ;
-- elseif _try_integer(r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_complete',-1) = r_taskitem.rid_mastertaskitem
-- then
-- --We reached the target taskitem, so we can mark it activate
-- insert into core.taskitemevent(rid_taskitem,rid_mastertaskitemevent,description,status,createddatetime,guid,jsonvalue)
-- select r_taskitem.rid_taskitem
-- , mtev.rid_mastertaskitemevent
-- , mtev.description
-- , mtev.status
-- , now()
-- , newid()
-- , _jsonb_object_cat(mtev.jsonvalue,p_parms->'_event_jsonvalue',jsonb_build_object('parent_rid_taskitem',_try_integer(p_parms ->> 'parent_rid_taskitem',0)))
-- from core.mastertaskitemevent mtev
-- where mtev.rid_mastertaskitem = r_taskitem.rid_mastertaskitem
-- and coalesce(mtev.inactive,0) = 0
-- and mtev.status = 2
-- and not exists (
-- select 1
-- from core.taskitemevent tie
-- where tie.rid_taskitem = r_taskitem.rid_taskitem
-- and tie.rid_mastertaskitemevent = mtev.rid_mastertaskitemevent
-- )
-- ;
-- end if;
-- end if;
p_parms := _jsonb_object_cat(p_parms, to_jsonb(r_taskitemevent));
end loop;
-- perform log_event(m_funcname
-- ,format('Post event insert: rid_taskitemevent=%s rid_mastertaskitem_complete=%s rid_mastertaskitem=%s'
-- ,r_taskitemevent_parent.rid_taskitemevent
-- ,r_taskitemevent_parent.jsonvalue->>'rid_mastertaskitem_complete'
-- ,r_taskitem.rid_mastertaskitem
-- ),bt_enum('eventlog','local notice'));
elsif p_table::citext in ('taskitem', 'wfl')
then
select ti.*
from core.taskitem ti
where ti.rid_taskitem = p_rid
into r_taskitem;
select ti.*
from core.mastertaskitem ti
where ti.rid_mastertaskitem = r_taskitem.rid_mastertaskitem
into r_mastertaskitem;
select tl.*
from core.tasklist tl
where tl.rid_tasklist = r_taskitem.rid_tasklist
into r_tasklist;
--Create item linked to task for this hub if not found
perform log_event(m_funcname, format(E'Action Init via %s=%s Item:%s(%s rid_taskitem:%s)
p_parms:%s', p_table, p_rid
, r_mastertaskitem.description, r_mastertaskitem.rid_mastertaskitem, r_taskitem.rid_taskitem
, p_parms), bt_enum('eventlog', 'local notice'));
select r.p_retval, r.p_errmsg, r.p_a_rid_taskitem
from core.taskitem_get_or_prime(_jsonb_object_cat(
jsonb_build_object('rid_tasklist', r_tasklist.rid_tasklist
, 'rid_mastertaskitemevent',
r_mastertaskitemevent.rid_mastertaskitemevent
, 'rid_taskitem_parentaction', p_parms -> 'rid_taskitem_parentaction'
), to_jsonb(r_taskitem), p_parms)) r
into m_retval,m_errmsg,m_temp_rid_list;
if m_retval > 0
then
raise exception '%',m_errmsg using hint = 'in taskitem_get_or_prime 3';
end if;
if array_length(m_temp_rid_list, 1) > 1
then
select array_agg(to_jsonb(ti))
from core.taskitem ti
where ti.rid_taskitem = any (m_temp_rid_list)
into p_parms;
else
m_temp_rid = m_temp_rid_list[1];
select *
from core.taskitem ti
where ti.rid_taskitem = m_temp_rid
into r_taskitem;
p_parms = to_jsonb(r_taskitem);
end if;
elsif p_table::citext in ('mastertaskitem', 'mal')
then
select ti.*
from core.mastertaskitem ti
where ti.rid_mastertaskitem = p_rid
into r_mastertaskitem;
if r_mastertaskitem.inactive > 0
then
raise exception 'The template task item is inactive. rid_mastertaskitem = %',r_mastertaskitem.rid_mastertaskitem;
end if;
perform log_event(m_funcname, format(E'Action Init via %s=%s Item:%s(%s)
p_parms:%s', p_table, p_rid
, r_mastertaskitem.description, r_mastertaskitem.rid_mastertaskitem
, p_parms), bt_enum('eventlog', 'local notice'));
select r.p_retval, r.p_errmsg, r.p_a_rid_taskitem
from core.taskitem_get_or_prime(_jsonb_object_cat(to_jsonb(r_mastertaskitem)
, p_parms
, jsonb_build_object('rid_mastertaskitemevent', r_mastertaskitemevent.rid_mastertaskitemevent
, 'rid_taskitem_parentaction',
p_parms -> 'rid_taskitem_parentaction'
))
) r
into m_retval,m_errmsg,m_temp_rid_list;
if m_retval > 0
then
raise exception '%',m_errmsg using hint = 'in taskitem_get_or_prime 4';
end if;
if array_length(m_temp_rid_list, 1) > 1
then
select array_agg(to_jsonb(ti))
from core.taskitem ti
where ti.rid_taskitem = any (m_temp_rid_list)
into p_parms;
else
m_temp_rid = m_temp_rid_list[1];
select *
from core.taskitem ti
where ti.rid_taskitem = m_temp_rid
into r_taskitem;
p_parms = to_jsonb(r_taskitem);
end if;
end if;
if nv(r_taskitem.rid_mastertaskitem) = 0
then
raise warning 'No template for the task item. rid_mastertaskitem = %',r_taskitem.rid_mastertaskitem;
end if;
EXCEPTION
WHEN others THEN
GET STACKED DIAGNOSTICS
m_errmsg = MESSAGE_TEXT
,m_errcontext = PG_EXCEPTION_CONTEXT
,m_errdetail = PG_EXCEPTION_DETAIL
,m_errhint = PG_EXCEPTION_HINT
,m_errstate = RETURNED_SQLSTATE;
p_errmsg := format('%s table:%s rid:%s',
get_err_msg(m_funcname, m_errmsg, m_errcontext, m_errdetail, m_errhint, m_errstate), p_table,
p_rid);
p_retval = 1;
END;
$$;
+988
View File
@@ -0,0 +1,988 @@
--select * from dropall('event_exec_func','core');
CREATE OR REPLACE FUNCTION core.event_exec_func(
p_event_parameters jsonb
, p_item_parameters jsonb
, OUT p_retval integer
, OUT p_errorcode text
, OUT p_errmsg text
, OUT p_output jsonb
)
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
AS
$$
DECLARE
--Error Handling--
m_funcname text = 'core.event_exec_func';
m_errmsg text;
m_errcode text;
m_errcontext text;
m_errdetail text;
m_errhint text;
m_errstate text;
m_retval integer;
--Error Handling--
r_taskitem core.taskitem%rowtype;
r_taskitem_parent core.taskitem%rowtype;
r_mastertaskitem core.mastertaskitem%rowtype;
r_taskitemevent core.taskitemevent%rowtype;
m_rid integer;
j_output jsonb;
j_all_parms jsonb;
j_controls jsonb;
j_tmp jsonb;
m_exec_funcname citext;
m_exec_schema citext;
m_sql citext;
r_lp record;
r_hub core.hub%rowtype;
a_async_procs citext[];
a_broker_procs citext[];
a_noerror_procs citext[];
BEGIN
j_controls = jsonb_build_array();
p_retval = 0;
p_errmsg = '';
m_exec_schema = 'public';
a_async_procs = array ['']; --hsync_upload_clienttohyphen
a_broker_procs = array ['']; --hsync_upload_clienttohyphen
a_noerror_procs = array ['ui_clientscenario_commit'];
-- if p_event_parameters -> 'AFN_RID_ACTIONFUNCTION_CODE' is null
-- then
-- p_retval = 1;
-- p_errmsg = '[ECR0001] No AFN_RID_ACTIONFUNCTION_CODE inside the AOP pack.';
--
-- select m.v[1]
-- from regexp_matches(p_errmsg, '\[([^\]]+)\]','ig') m(v)
-- where length(m.v[1]) between 2 and 10
-- order by m.v[1]
-- into p_errorcode;
--
-- return;
-- end if;
select *
from core.taskitemevent tie
where tie.rid_taskitemevent = _try_integer(p_item_parameters ->> 'rid_taskitemevent', 0)
into r_taskitemevent;
select *
from core.taskitem ti
where ti.rid_taskitem = _try_integer(p_item_parameters ->> 'rid_taskitem', r_taskitemevent.rid_taskitem)
into r_taskitem;
select *
from core.mastertaskitem mti
where
mti.rid_mastertaskitem = _try_integer(p_item_parameters ->> 'rid_mastertaskitem', 0)
or r_taskitem.rid_mastertaskitem > 0 and mti.rid_mastertaskitem = r_taskitem.rid_mastertaskitem
order by mti.rid_mastertaskitem desc
limit 1
into r_mastertaskitem;
m_exec_funcname = r_mastertaskitem.functionname_code;
if m_exec_funcname ilike '%.%'
then
m_exec_schema = split_part(m_exec_funcname, '.', 1);
m_exec_funcname = split_part(m_exec_funcname, '.', 2);
end if;
if nv(m_exec_funcname) = ''
then
perform log_event(m_funcname, format(
E'No function to execute for MasterTaskItem %s (rid_mastertaskitem=%s) and TaskItem %s (rid_taskitem=%s)',
r_mastertaskitem.description, r_mastertaskitem.rid_mastertaskitem, r_taskitem.description,
r_taskitem.rid_taskitem), bt_enum('eventlog', 'local notice'));
return;
end if;
-- if m_exec_funcname ilike '%payment%plan%'
-- then
-- raise exception 'Payment Plan Test Error % [RTY0001]', m_exec_funcname;
-- end if;
j_all_parms = _jsonb_object_cat(r_taskitem.jsonvalue,
j_all_parms
, (
select jsonb_object_agg(k, p_event_parameters -> k)
from jsonb_object_keys(p_event_parameters) keys(k)
where jsonb_typeof(p_event_parameters -> keys.k) not in ('object', 'array', 'null')
), (
select jsonb_object_agg(k, p_item_parameters -> k)
from jsonb_object_keys(p_item_parameters) keys(k)
where jsonb_typeof(p_item_parameters -> keys.k) not in ('object', 'array', 'null')
)
);
if r_taskitem.rid_taskitem > 0 and r_taskitem.rid_taskitem_parentaction > 0
then
select ti.*
from core.taskitem ti
where ti.rid_taskitem = r_taskitem.rid_taskitem_parentaction
into r_taskitem_parent;
end if;
select af.jsonvalue -> 'controls'
from core.actionfunction af
where
(
af.functionname = m_exec_funcname
or af.functionname = r_mastertaskitem.functionname_code
)
and af.fntype = 'pgsql-function'::citext
into j_controls;
if jsonb_typeof(p_item_parameters -> 'AOP' -> 'jsonvalue' -> 'controls_code') = 'array'
then
j_controls = _jsonb_object_cat(j_controls, p_item_parameters -> 'AOP' -> 'jsonvalue' -> 'controls');
end if;
if jsonb_typeof(p_event_parameters -> 'jsonvalue' -> 'controls_code') = 'array'
then
j_controls = _jsonb_object_cat(j_controls, p_event_parameters -> 'jsonvalue' -> 'controls');
end if;
if jsonb_typeof(j_all_parms -> 'controls_code') = 'array'
then
j_controls = _jsonb_object_cat(j_controls, j_all_parms -> 'controls_code');
end if;
if jsonb_typeof(r_mastertaskitem.jsonvalue -> 'controls_code') = 'array'
then
j_controls = _jsonb_object_cat(j_controls, r_mastertaskitem.jsonvalue -> 'controls_code');
end if;
raise notice 'Controls: %', j_controls::text;
j_all_parms = _jsonb_object_cat(j_all_parms,
(
select jsonb_object_agg(ctr.j ->> 'name'
, case
when nv(j_all_parms ->> (ctr.j ->> 'name')) = ''
then ctr.j -> 'props' ->> 'value'
else j_all_parms ->> (ctr.j ->> 'name')
end
order by i
)
from jsonb_array_elements(j_controls) with ordinality ctr(j, i)
where nv(ctr.j -> 'props' ->> 'value') <> ''
)
);
if nv(j_all_parms ->> 'rid_hub_user') = ''
then
j_all_parms = _jsonb_object_cat(j_all_parms, jsonb_build_object(
'rid_hub_user', _bv(core.f_get_user_hub_rid(), (
select hub.rid_hub
from core.hub
where hub.hubtype = 'program'
limit 1
)),
'login', f_getuser()
));
end if;
if nv(j_all_parms ->> 'login') = ''
then
j_all_parms = _jsonb_object_cat(j_all_parms, jsonb_build_object(
'login', f_getuser()
));
end if;
if _try_integer(j_all_parms ->> 'rid_hub', 0) > 0
then
select *
from core.hub
where rid_hub = _try_integer(j_all_parms ->> 'rid_hub', 0)
into r_hub;
if r_hub.hubtype in ('client', 'lead')
then
j_all_parms = _jsonb_object_cat(j_all_parms, (
select jsonb_build_object(
'rid_adproclient', cli.rid_adproclient
, 'rid_client', cli.rid_adproclient
)
from t_adproclient cli
where cli.rid_hub = r_hub.rid_hub
limit 1
));
elsif r_hub.hubtype in ('trader')
then
j_all_parms = _jsonb_object_cat(j_all_parms, (
select jsonb_build_object(
'rid_trader', tdr.rid_trader
, 'rid_adprocreditor', tdr.rid_trader
)
from t_trader tdr
where tdr.rid_hub = r_hub.rid_hub
limit 1
));
end if;
end if;
j_all_parms = _jsonb_object_cat(j_all_parms, jsonb_build_object('AOP', null));
-- perform log_event(m_funcname, format('p_event_parameters=%s p_item_parameters=%s j_all_parms=%s', p_event_parameters::text,
-- p_item_parameters::text, j_all_parms::text), bt_enum('eventlog', 'local notice'));
if (
select 1
from core.actionfunction af
where
(
af.functionname = m_exec_funcname
or af.functionname = r_mastertaskitem.functionname_code
)
and af.fntype = 'pgsql-function'::citext
)
then
if m_exec_funcname = 'event_nextaction'
then
select r.p_retval, r.p_errmsg, r.p_data
from core.event_nextaction(j_all_parms) r
into m_retval,m_errmsg, j_output;
if m_retval > 0
then
p_retval = m_retval;
p_errmsg = m_errmsg;
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
return;
end if;
elsif m_exec_funcname in ('event_pre_error_check')
then
select r.p_retval, r.p_errmsg, r.p_errorcode, r.p_parms
from core.event_pre_error_check(_jsonb_object_cat(j_all_parms, jsonb_build_object(
'rid_taskitem', r_taskitem.rid_taskitem
, 'rid_tasklist', r_taskitem.rid_tasklist
, 'rid_mastertaskitem', r_mastertaskitem.rid_mastertaskitem
))) r
into p_retval,p_errmsg, p_errorcode, p_output;
return;
elsif m_exec_funcname = 'ui_maint_commitem'
then
select r.p_retval, r.p_errmsg, r.p_options
from core.ui_maint_commitem(_jsonb_object_cat(
r_taskitem.jsonvalue
, r_taskitemevent.jsonvalue
, jsonb_build_object(
'rid_taskitem', r_taskitem.rid_taskitem,
'rid_mastertaskitem', r_taskitem.rid_mastertaskitem,
'rid_hub_user', j_all_parms ->> 'rid_hub_user',
'rid_hub_payload', _try_integers(j_all_parms ->> 'rid_hub', j_all_parms ->> 'rid_hub_payload')
)
)) r
into m_retval,m_errmsg, j_output;
if m_retval > 0
then
p_retval = m_retval;
p_errmsg = m_errmsg;
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
return;
end if;
elsif m_exec_funcname = 'ui_modify_paymentplan'
then
select r.p_retval, r.p_errmsg, r.p_data
from ui_modify_paymentplan(j_all_parms) r
into m_retval,m_errmsg, j_output;
if m_retval > 0
then
p_retval = m_retval;
p_errmsg = m_errmsg;
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
return;
end if;
elsif m_exec_funcname in ('f_checkforreapprove_client')
then
select f_checkforreapprove_client(cli.rid_adproclient)
from t_adproclient cli
where cli.rid_hub = r_taskitem.rid_hub
into m_retval;
if m_retval > 0
then
p_retval = 1;
p_errmsg = 'Re-approval is required for this client and it needs to be uploaded to the PDA.';
p_errorcode = 'CLIAPRV1';
p_output = jsonb_build_object('message', p_errmsg, 'actionstatus', 'error',
'errorcode', p_errorcode
, 'alerttype', 'error'
, 'in_modal', true
);
return;
else
p_retval = 0;
p_errmsg = '';
p_errorcode = '';
p_output = jsonb_build_object('actionstatus', 'success', 'delete_after', true);
return;
end if;
elsif m_exec_funcname in ('c_checkforreapprove')
then
select c_checkforreapprove(cli.rid_adproclient)
from t_adproclient cli
where cli.rid_hub = r_taskitem.rid_hub
into m_retval;
if m_retval > 0
then
p_retval = 1;
p_errmsg = 'Re-approval is required for this client`s payment plan and it needs to be uploaded to the PDA.';
p_errorcode = 'CLIAPRV2';
p_output = jsonb_build_object('message', p_errmsg, 'actionstatus', 'error', 'errorcode'
, p_errorcode
, 'alerttype', 'error'
, 'in_modal', true);
return;
else
p_retval = 0;
p_errmsg = '';
p_errorcode = '';
p_output = jsonb_build_object('actionstatus', 'success', 'delete_after', true);
return;
end if;
elsif m_exec_funcname in ('action_init_hublinks')
then
select r.p_retval, r.p_errmsg
from core.action_init_hublinks(_jsonb_object_cat(p_item_parameters, jsonb_build_object(
'rid_taskitem', r_taskitem.rid_taskitem,
'rid_mastertaskitem', r_taskitem.rid_mastertaskitem,
'rid_hub_user', j_all_parms ->> 'rid_hub_user',
'event_status', r_taskitemevent.status,
'parent_rid_taskitemevent', r_taskitemevent.rid_taskitemevent,
'calling_function', m_funcname
))) r
into m_retval, m_errmsg;
if m_retval > 0
then
p_retval = m_retval;
p_errmsg = m_errmsg;
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
return;
end if;
elsif m_exec_funcname in ('ui_clientscenario_commit')
then
if coalesce(_try_integers(j_all_parms ->> 'rid_clientscenario', j_all_parms ->> 'p_rid_clientscenario'), 0) = 0
then
select s.rid_clientscenario
from clientscenario s
inner join t_adproclient c on c.rid_adproclient = s.rid_adproclient
and c.rid_hub = r_taskitem.rid_hub
where s.status in (1, 2)
order by s.status, s.rid_clientscenario desc
limit 1
into m_rid;
if nv(m_rid) = 0 and r_taskitem.rid_hub_link > 0
then
--Falback to link parent client when tasklink is for client.
select s.rid_clientscenario
from core.hub_link h
inner join t_adproclient c on c.rid_hub = h.rid_hub_parent
and h.parent_hubtype = 'client'
inner join clientscenario s on s.rid_adproclient = c.rid_adproclient
and s.status in (1, 2)
where h.rid_hub_link = r_taskitem.rid_hub_link
order by s.status, s.rid_clientscenario desc
limit 1
into m_rid;
end if;
j_all_parms = _jsonb_object_cat(j_all_parms, jsonb_build_object(
'rid_clientscenario', m_rid
));
end if;
select r.p_retval, r.p_errmsg
from public.ui_clientscenario_commit(_try_integers(j_all_parms ->> 'rid_clientscenario'
, j_all_parms ->> 'p_rid_clientscenario', null)
, null
, _jsonb_object_cat(p_item_parameters, jsonb_build_object(
'rid_taskitem', r_taskitem.rid_taskitem,
'rid_hub', r_taskitem.rid_hub,
'rid_mastertaskitem', r_taskitem.rid_mastertaskitem,
'rid_hub_user', j_all_parms ->> 'rid_hub_user',
'event_status', r_taskitemevent.status,
'parent_rid_taskitemevent', r_taskitemevent.rid_taskitemevent,
'calling_function', m_funcname
))) r
into m_retval, m_errmsg;
if p_event_parameters ->> 'no_error' in ('1', 'true') or p_item_parameters ->> 'no_error' in ('1', 'true')
then
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
return;
end if;
if m_retval > 0
then
p_retval = m_retval;
p_errmsg = m_errmsg;
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
return;
end if;
elsif exists (
select ns.nspname, pro.*
from pg_proc pro
inner join pg_namespace ns on ns.oid = pro.pronamespace
and ns.nspname not in ('postgres', 'pg_catalog')
and ns.nspname = m_exec_schema
where pro.proname = m_exec_funcname
)
and m_exec_funcname in
('clfrm_builderrorlist', 'upl_builduploaderrors', 'clfrm_propcalc_errlist', 'ui_clientscenarion_errorlist')
then
raise notice 'Running %',m_exec_funcname;
p_retval = 0;
p_errmsg = '';
m_errdetail = '';
SET session_replication_role = DEFAULT;
if not exists (
select cli.rid_adproclient
from t_adproclient cli
where cli.rid_hub = r_taskitem.rid_hub
)
then
p_retval = 1;
p_errmsg = 'No client found for the hub.';
return;
end if;
with
cli as (
select cli.rid_adproclient
from t_adproclient cli
where cli.rid_hub = r_taskitem.rid_hub
)
, src as (
select o.errordescription as errordescription
, o.errorcode as errorcode
, o.error_priority as priority
, o.errortype
from clfrm_builderrorlist((
select cli.rid_adproclient
from cli
limit 1
), 0, 0) o
where m_exec_funcname in ('clfrm_builderrorlist')
union
select o.errordescription as errordescription
, o.errorcode as errorcode
, o.error_priority as priority
, o.errortype
from clfrm_builderrorlist((
select cli.rid_adproclient
from cli
limit 1
), 0, 1) o
where m_exec_funcname in ('clfrm_builderrorlist')
union
select o.errordescription as errordescription, o.errorcode as errorcode, 1 as priority, 'error' as errortype
from clfrm_propcalc_errlist((
select cli.rid_adproclient
from cli
limit 1
)) o
where m_exec_funcname = 'm_exec_funcname'
union
select o.errdescription as errordescription
, o.errorcode as errorcode
, o.severity as priority
, o.errtype as errortype
from upl_builduploaderrors((
select cli.rid_adproclient
from cli
limit 1
)
, _bv(j_all_parms ->> 'p_approve_mode', j_all_parms ->> 'approve_mode', j_all_parms ->> 'mode', 'normal')) o
where
m_exec_funcname in ('upl_builduploaderrors')
union
select elm.j ->> 'errordescription' as errordescription
, elm.j ->> 'errorcode' as errorcode
, _try_integer(elm.j ->> 'priority', 1) as priority
, _bv(elm.j ->> 'errortype', 'error') as errortype
from ui_clientscenarion_errorlist((
select sc.rid_clientscenario
from cli
inner join clientscenario sc on sc.rid_adproclient = cli.rid_adproclient
and sc.status = 1
order by sc.rid_clientscenario desc
limit 1
)) o
cross join jsonb_array_elements(case
when jsonb_typeof(o.p_data) = 'object' then jsonb_build_array(o.p_data)
when jsonb_typeof(o.p_data) = 'array' then o.p_data
else jsonb_build_array()
end) elm(j)
where m_exec_funcname in ('ui_clientscenarion_errorlist')
order by priority
)
, composed as (
select
-- src.errorcode
-- , src.errordescription
-- , src.priority as errorpriority
-- , src.errortype
row_number() over (partition by src.errorcode, src.errordescription order by src.priority desc) as rn
, evt2.rid_mastertaskitemevent as rid_mastertaskitemevent
, mti.rid_mastertaskitem as rid_mastertaskitem
, ti.rid_taskitem as rid_taskitem
, core.f_get_user_hub_rid() as rid_hub_user
, jsonb_build_object(
'errordescription', src.errordescription
, 'errorcode', src.errorcode
, 'errortype', src.errortype
, 'errorpriority', src.priority
) as jsonvalue
from src
--Get the main linked event
left outer join core.mastertaskitemevent ev1 on ev1.rid_mastertaskitem = r_taskitem.rid_mastertaskitem
and nv(ev1.errorcode) <> ''
and (
ev1.errorcode = src.errorcode
or ev1.errorcode in (
select m.interface_code
from core.error_code_map(jsonb_build_object('filter_code', src.errorcode)) m
where nv(m.interface_code) <> ''
)
)
left outer join core.mastertaskitemeventreaction er1
on er1.rid_mastertaskitemevent = ev1.rid_mastertaskitemevent
-- Fallback to the global event list
left outer join core.mastertaskitemevent evt2 on (
evt2.rid_mastertaskitemevent =
er1.rid_mastertaskitemevent_target
or evt2.status in (2)
and nv(evt2.errorcode) <> ''
and (
evt2.errorcode = src.errorcode
or evt2.errorcode in (
select m.interface_code
from core.error_code_map(jsonb_build_object('filter_code', src.errorcode)) m
where nv(m.interface_code) <> ''
)
)
)
and nv(evt2.inactive) = 0
left outer join core.mastertaskitem mti on mti.rid_mastertaskitem = evt2.rid_mastertaskitem
left outer join core.taskitem ti on ti.rid_mastertaskitem = mti.rid_mastertaskitem
and ti.rid_hub = r_taskitem.rid_hub
and nv(ti.rid_hub_link) = nv(r_taskitem.rid_hub_link)
and ti.status in (1, 2, 3)
)
select jsonb_agg(_jsonb_object_cat(to_jsonb(mti), to_jsonb(ti), jsonb_strip_nulls(to_jsonb(c))))
filter ( where c.rn = 1 )
, count(1)
from composed c
left outer join core.mastertaskitem mti on mti.rid_mastertaskitem = c.rid_mastertaskitem
left outer join core.taskitem ti on ti.rid_taskitem = c.rid_taskitem
into j_tmp, m_retval;
if m_retval > 0
then
-- update core.taskitem u
-- set jsonvalue = jsonb_build_object('errorlist', j_tmp)
-- where u.rid_taskitem = r_taskitem.rid_taskitem;
p_output =
jsonb_build_object('actionstatus', 'error', 'errorcode', 'ERRLIST', 'errorlist', j_tmp, 'delete_caller',
true);
else
p_output =
jsonb_build_object('message', null, 'actionstatus', 'success', 'errorcode', null, 'delete_after', true,
'errorlist', null);
end if;
perform log_event(m_funcname, format(E'List Function (%s) Results Code=%s Error=%s.
MasterTaskItem:%s \n p_output:%s \nm_errdetail:%s'
, m_exec_funcname
, p_errorcode
, p_errmsg
, r_mastertaskitem.description
, p_output
, m_errdetail
)
, bt_enum('eventlog', 'local error'));
return;
--m_retval =0;
elsif exists (
select ns.nspname, pro.*
from pg_proc pro
inner join pg_namespace ns on ns.oid = pro.pronamespace
and ns.nspname not in ('postgres', 'pg_catalog')
and ns.nspname = m_exec_schema
where pro.proname = m_exec_funcname
)
then
with
args as (
select ns.nspname
, pro.proname
, t.typname
, i.i
, pro.proargnames[i - 1] as argname
, pro.proargmodes[i - 1] as mode
, CASE
WHEN pro.proargdefaults IS NOT NULL
AND i.i - 1 > (pro.pronargs - pro.pronargdefaults)
THEN split_part(
pg_get_expr(pro.proargdefaults, 0),
',',
i.i - 1 - (pro.pronargs - pro.pronargdefaults)
)::text
ELSE NULL::text
END as default_value
, row_number() over (order by i.i) as number
--,pro.*
from pg_proc pro
inner join pg_namespace ns on ns.oid = pro.pronamespace
and ns.nspname not in ('postgres', 'pg_catalog')
JOIN LATERAL generate_subscripts(pro.proallargtypes, 1) AS i ON true
JOIN pg_type t ON t.oid = pro.proallargtypes[i - 1]
where
pro.proname = m_exec_funcname
and ns.nspname = m_exec_schema
--pro.proname in ('hsync_upload_clienttohyphen')
AND (pro.proargmodes IS NULL OR pro.proargmodes[i - 1] in ('i', 'b'))
)
, argval as (
select args.*
--, _bv(j_all_parms ->> args.argname,args.default_value) as argvalue
, case
when nv(j_all_parms ->> args.argname) in ('', '0', 'null')
and args.argname ilike 'p_%' and
nv(j_all_parms ->> replace(args.argname, 'p_', '')) not in ('', '0', 'null')
then j_all_parms ->> replace(args.argname, 'p_', '')
when nv(j_all_parms ->> args.argname) <> '' then j_all_parms ->> args.argname
when args.argname ilike 'p_%' and nv(j_all_parms ->> replace(args.argname, 'p_', '')) <> ''
then j_all_parms ->> replace(args.argname, 'p_', '')
when args.argname ilike 'p_login%' and j_all_parms ->> 'login' is not null
then j_all_parms ->> 'login'
when args.argname ilike 'p_user%' and j_all_parms ->> 'login' is not null
then j_all_parms ->> 'login'
when nv(args.default_value) <> '' then args.default_value
else null::text
end as argvalue
from args
)
select (
select string_agg(format('%s::%s', case
when a.typname ilike '%int%' then a.argvalue
else quote_literal(a.argvalue)
end, a.typname), ', ') as args
from argval a
)
, (
select count(1)
from argval a
where a.argvalue is null
)
, (
select format('[ECR0002] Cannot execute function %s. The following arguments are missing: %s (Defaults: %s) ',
m_exec_funcname, string_agg(a.argname, ','), string_agg(a.default_value, ','))
from argval a
where a.argvalue is null
)
into m_sql,m_retval, m_errmsg, m_errcode;
raise notice 'Function % executed with arguments: %', m_exec_funcname, m_sql;
if m_retval > 0
then
p_retval = 1;
p_errmsg = m_errmsg;
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
perform log_event(m_funcname, format(
E'Error on Function (%s) Code=%s Error=%s. MasterTaskItem:%s \n SQL:%s \n j_all_parms:%s \n Controls: %s'
, m_exec_funcname
, p_errorcode
, p_errmsg
, r_mastertaskitem.description
, m_sql
, substr((j_all_parms || jsonb_build_object('AOP', null))::text, 1, 100000)
, j_controls::text
)
, bt_enum('eventlog', 'local error'));
return;
end if;
m_sql = format('select to_jsonb(r) as val from %s.%s(%s) r ;', m_exec_schema, m_exec_funcname, m_sql);
perform log_event(m_funcname, format('Executing Function (%s) with SQL: %s', m_exec_funcname, m_sql),
bt_enum('eventlog', 'local notice'));
if m_exec_funcname::citext = any (a_broker_procs)
then
select r.p_retval, r.p_errmsg
from agent_job_add(format('exec %s', m_sql)
, get_agent_freequeue(3)
, format('%s(taskitemevent=%s)', m_exec_funcname, r_taskitemevent.rid_taskitemevent)
, 15
) r
into m_retval,m_errmsg;
elsif m_exec_funcname::citext = any (a_async_procs)
then
select _bv(j.val -> 'val', j.val)
from autoexec_query(m_sql, jsonb_build_object()) j(val)
into j_output;
else
execute m_sql into j_output;
end if;
p_output = j_output;
if p_event_parameters ->> 'no_error' in ('1', 'true') or p_item_parameters ->> 'no_error' in ('1', 'true')
then
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
perform log_event(m_funcname, format('Error(!) on Function (%s) Code=%s Error=%s. MasterTaskItem:%s Response:%s'
, m_exec_funcname
, p_errorcode
, p_errmsg
, r_mastertaskitem.description
, substr(j_output::text, 1, 10000)
)
, bt_enum('eventlog', 'local error'));
return;
end if;
if jsonb_typeof(j_output) in ('number', 'boolean', 'string')
then
perform log_event(m_funcname,
format('Function (%s) returned scalar value: %s', m_exec_funcname, j_output::text),
bt_enum('eventlog', 'debug'));
if j_all_parms -> 'p_output' is not null
and (j_all_parms ->> 'p_output')::citext is distinct from j_output::citext
then
p_retval = 1;
p_errmsg =
'Output value does not match expected value. Expected: ' || j_all_parms ->> 'p_output' || ' Actual: ' ||
j_output::text;
return;
end if;
end if;
if _try_integer(j_output ->> 'p_retval', 0) > 0
and m_exec_funcname::citext <> all (a_noerror_procs)
then
p_retval = _try_integer(j_output ->> 'p_retval', 0);
p_errmsg = format('%s', j_output ->> 'p_errmsg');
p_errorcode = _bv(j_output ->> 'p_error_code', j_output ->> 'p_errorcode', '');
perform log_event(m_funcname, format('Error on Function (%s) Code=%s Error=%s. MasterTaskItem:%s Response:%s'
, m_exec_funcname
, p_errorcode
, p_errmsg
, r_mastertaskitem.description
, substr(j_output::text, 1, 10000)
)
, bt_enum('eventlog', 'local error'));
if nv(p_errorcode) = ''
then
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
if nv(p_errorcode) = ''
then
p_errorcode = 'ECR0003';
end if;
end if;
return;
end if;
else
perform log_event(m_funcname, format('Function (%s) not defined for this event (%s).',
p_event_parameters -> 'AFN_RID_ACTIONFUNCTION_CODE' ->> 'functionname'
, r_mastertaskitem.description)
, bt_enum('eventlog', 'local error'));
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
return;
end if;
else
raise notice 'Type not supported: %', p_event_parameters -> 'AFN_RID_ACTIONFUNCTION_CODE' ->> 'fntype';
end if;
--select * from core.actionfunction
if nv(p_errorcode) = '' and nv(p_errmsg) <> ''
then
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
if nv(p_errorcode) = ''
then
p_errorcode = 'PRCERR';
end if;
end if;
EXCEPTION
WHEN others THEN
GET STACKED DIAGNOSTICS
m_errmsg = MESSAGE_TEXT
,m_errcontext = PG_EXCEPTION_CONTEXT
,m_errdetail = PG_EXCEPTION_DETAIL
,m_errhint = PG_EXCEPTION_HINT
,m_errstate = RETURNED_SQLSTATE;
p_errmsg := get_err_msg(m_funcname, m_errmsg, m_errcontext, m_errdetail, m_errhint, m_errstate);
p_retval = 1;
if nv(p_errorcode) = '' and nv(p_errmsg) <> ''
then
select m.v[1]
from regexp_matches(p_errmsg, '\[([^\]]+)\]', 'ig') m(v)
where length(m.v[1]) between 2 and 10
order by m.v[1]
into p_errorcode;
if nv(p_errorcode) = ''
then
p_errorcode = 'PRCERR';
end if;
end if;
END;
$$;
--Tests
/*
select (regexp_matches('[ECR0001] No AFN inside the AOP pack.', '\[([^\]]+)\]'))[1]
, (regexp_matches('[21] No AFN inside the AOP pack. [45345]', '\[([^\]]+)\]'))[1]
, (regexp_matches('A Test', '\[([^\]]+)\]'))[1]
*/
/*
select *
from core.taskitemevent e
where e.rid_taskitem = 26344
limit
;*/
/*
select *
from core.event_exec_func((
select _jsonb_object_cat( to_jsonb(e)
,jsonb_build_object('AFN_RID_ACTIONFUNCTION_CODE',to_jsonb(af)))
from core.taskitemevent e
inner join core.taskitem ti on ti.rid_taskitem = e.rid_taskitem
inner join core.actionoption ao on ao.guid = ti.jsonvalue -> 'AOP' ->> 'guid'
inner join core.actionfunction af on af.rid_actionfunction = ao.rid_actionfunction_code
where e.rid_taskitem = 26344
),(select _jsonb_object_cat( to_jsonb(e)
,jsonb_build_object('AFN_RID_ACTIONFUNCTION_CODE',to_jsonb(af)))
from core.taskitem e
inner join core.mastertaskitem mti
on mti.rid_mastertaskitem = e.rid_mastertaskitem
inner join core.actionoption ao on ao.guid = e.jsonvalue -> 'AOP' ->> 'guid'
inner join core.actionfunction af on af.rid_actionfunction = ao.rid_actionfunction_code
where e.rid_taskitem = 26344
))
selecT * from v_eventlog
select * from core.taskitem ti
order by ti.rid_taskitem desc
*/
File diff suppressed because it is too large Load Diff
+613
View File
@@ -0,0 +1,613 @@
--select * from dropall('ui_action_event','core');
CREATE OR REPLACE FUNCTION core.ui_action_event(
p_payload INOUT jsonb
, OUT p_retval integer
, OUT p_errmsg text
)
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
AS
$$
DECLARE
--Error Handling--
m_funcname text = 'core.ui_action_event';
m_errmsg text;
m_errcontext text;
m_errdetail text;
m_errhint text;
m_errstate text;
m_retval integer;
--Error Handling--
m_rid_hub integer;
m_rid_hub_link integer;
m_rid_hub_user integer;
m_temp_rid integer;
m_final_rid_taskitem integer;
m_temp_rid_list integer[];
m_status integer;
m_outcome integer;
r_mastertaskitemevent core.mastertaskitemevent%rowtype;
r_taskitem core.taskitem%rowtype;
r_taskitemevent core.taskitemevent%rowtype;
r_mastertaskitem core.mastertaskitem%rowtype;
r_mastertask core.mastertask%rowtype;
r_lp record;
m_check_error boolean := false;
m_cancel boolean := false;
j_result jsonb;
j_obj jsonb;
m_tm timestamp ;
BEGIN
m_tm = clock_timestamp();
p_retval = 0;
p_errmsg = '';
j_result = jsonb_build_array();
m_rid_hub = _try_integer(p_payload ->> 'rid_hub', 0);
m_rid_hub_user = _try_integer(p_payload ->> 'rid_hub_user', core.f_get_user_hub_rid());
m_status = _try_integer(p_payload ->> 'status', 0);
m_outcome = _try_integer(p_payload ->> 'outcome', 0);
m_check_error = (p_payload ->> 'check_error')::citext in ('1', 'true');
m_cancel = (p_payload ->> 'cancel')::citext in ('1', 'true');
select *
from core.mastertaskitemevent mte
where mte.rid_mastertaskitemevent = _try_integer(p_payload ->> 'rid_mastertaskitemevent', 0)
into r_mastertaskitemevent;
select mti.*
from core.mastertaskitem mti
where
mti.rid_mastertaskitem = _try_integer(p_payload ->> 'rid_mastertaskitem', 0)
and _try_integer(p_payload ->> 'rid_mastertaskitem', 0) > 0
or mti.rid_mastertaskitem = r_mastertaskitemevent.rid_mastertaskitem
into r_mastertaskitem;
select mt.*
from core.mastertask mt
where
mt.rid_mastertask = _try_integer(p_payload ->> 'rid_mastertask', 0)
and _try_integer(p_payload ->> 'rid_mastertask', 0) > 0
or mt.rid_mastertask = r_mastertaskitem.rid_mastertask
into r_mastertask;
select *
from core.taskitem ti
where ti.rid_taskitem = _try_integer(p_payload ->> 'rid_taskitem', 0)
into r_taskitem;
if r_taskitem.rid_taskitem > 0
then
perform set_config('session.rid_taskitem', r_taskitem.rid_taskitem::text, false);
end if;
if nv(r_mastertaskitem.rid_mastertaskitem) = 0
then
if r_taskitem.rid_taskitem > 0
then
select *
from core.mastertaskitem mti
where mti.rid_mastertaskitem = r_taskitem.rid_mastertaskitem
into r_mastertaskitem;
elsif r_mastertask.rid_mastertask > 0
then
select *
from core.mastertaskitem mti
where
mti.rid_mastertask = r_mastertask.rid_mastertask
and coalesce(mti.inactive, 0) = 0
and coalesce(mti.rid_parentmastertaskitem, 0) = 0
order by mti.seqno nulls first, mti.rid_mastertaskitem
limit 1
into r_mastertaskitem;
end if;
end if;
if nv(r_mastertaskitemevent.rid_mastertaskitemevent) = 0
then
if r_mastertaskitem.rid_mastertaskitem > 0
then
select *
from core.mastertaskitemevent mte
where
mte.rid_mastertaskitem = r_mastertaskitem.rid_mastertaskitem
and coalesce(mte.inactive, 0) = 0
and mte.status in (1, 2)
order by mte.status desc, mte.seqno nulls first, mte.rid_mastertaskitemevent
limit 1
into r_mastertaskitemevent;
end if;
end if;
---Check error handler
if m_check_error
then
if nv(r_mastertaskitemevent.status) <> 13
then
select evt.*
from core.mastertaskitemevent evt
where
evt.rid_mastertaskitem = r_mastertaskitem.rid_mastertaskitem
and evt.status = 13
order by evt.seqno desc, evt.rid_mastertaskitemevent desc
into r_mastertaskitemevent;
end if;
--perform log_event(m_funcname,format('Init check error for rid_mastertaskitem:%s hub:%s ',r_mastertaskitemevent.rid_mastertaskitem,m_rid_hub),bt_enum('eventlog','local notice'));
if r_mastertaskitemevent.rid_mastertaskitemevent > 0
then
select r.p_retval, r.p_errmsg, r.p_parms
from core.action_init('mastertaskitemevent', r_mastertaskitemevent.rid_mastertaskitemevent
, _jsonb_object_cat(p_payload,
jsonb_build_object('check_error', true, 'rid_hub', m_rid_hub, 'createmode', 'existing'))
) r
into m_retval,m_errmsg, p_payload;
if m_retval > 0
then
p_retval = m_retval;
p_errmsg = m_errmsg;
return;
end if;
else
p_retval = 0;
p_errmsg = 'Error check enabled but no error event found for mastertaskitem.';
end if;
return;
end if;
---Check cancel handler
if m_cancel
then
if nv(r_mastertaskitemevent.status) <> 6
then
select evt.*
from core.mastertaskitemevent evt
where
evt.rid_mastertaskitem = r_mastertaskitem.rid_mastertaskitem
and evt.status = 6
order by evt.seqno desc, evt.rid_mastertaskitemevent desc
into r_mastertaskitemevent;
end if;
perform log_event(m_funcname,
format('Init cancel for rid_mastertaskitem:%s hub:%s ', r_mastertaskitemevent.rid_mastertaskitem,
m_rid_hub), bt_enum('eventlog', 'local notice'));
if r_mastertaskitemevent.rid_mastertaskitemevent > 0
then
select r.p_retval, r.p_errmsg, r.p_parms
from core.action_init('mastertaskitemevent', r_mastertaskitemevent.rid_mastertaskitemevent
, _jsonb_object_cat(p_payload,
jsonb_build_object('cancel', true, 'rid_hub', m_rid_hub, 'createmode', 'existing'))
) r
into m_retval,m_errmsg, p_payload;
if m_retval > 0
then
p_retval = m_retval;
p_errmsg = m_errmsg;
return;
end if;
else
p_retval = 0;
p_errmsg = 'cancel called but no cancel event found for mastertaskitem.';
end if;
return;
end if;
if nv(m_rid_hub) = 0 and r_taskitem.rid_taskitem > 0 and r_taskitem.rid_hub > 0
then
m_rid_hub = r_taskitem.rid_hub;
end if;
--perform log_event(m_funcname,format('Init %s(%s) m_rid_hub: %s p_payload: %s',r_taskitem.description,r_taskitem.rid_taskitem,m_rid_hub,p_payload::text),bt_enum('eventlog','local notice'));
if nv(m_rid_hub) = 0
then
p_errmsg := 'Missing required parameter: rid_hub';
p_retval = 1;
return;
end if;
if nv(r_mastertaskitemevent.rid_mastertaskitemevent) = 0
then
p_errmsg := 'Missing required parameter: rid_mastertaskitemevent';
p_retval = 1;
return;
end if;
perform log_event(m_funcname,
format(E'Init rid_mastertaskitemevent %s for rid_mastertaskitem:%s hub:%s \np_payload:%s',
r_mastertaskitemevent.rid_mastertaskitemevent, r_mastertaskitem.rid_mastertaskitem,
m_rid_hub, p_payload), bt_enum('eventlog', 'local notice'));
select r.p_retval, r.p_errmsg, r.p_a_rid_taskitem
from core.taskitem_get_or_prime(_jsonb_object_cat(p_payload, jsonb_build_object(
'parent_rid_taskitem', case
when r_taskitem.rid_taskitem = _try_integer(p_payload ->> 'parent_rid_taskitem', 0)
then r_taskitem.rid_taskitem_parentaction
else _try_integer(p_payload ->> 'parent_rid_taskitem',
r_taskitem.rid_taskitem_parentaction)
end
, 'rid_mastertaskitem', r_mastertaskitem.rid_mastertaskitem
, 'rid_mastertaskitemevent', r_mastertaskitemevent.rid_mastertaskitemevent
, 'status', r_mastertaskitemevent.status
, 'create_mode', p_payload ->> 'create_mode'
--,'create_mode','new'
))) r
into m_retval,m_errmsg,m_temp_rid_list;
if m_retval > 0
then
raise 'Error initializing taskitem %',m_errmsg;
end if;
for m_temp_rid in select * from unnest(m_temp_rid_list)
loop
select *
from core.taskitem ti
where ti.rid_taskitem = m_temp_rid
into r_taskitem;
if nv(r_taskitem.rid_taskitem) = 0
then
p_retval = 1;
p_errmsg = format('Task item not created or found. %s', m_temp_rid);
return;
end if;
select tie.*
from core.taskitemevent tie
where
tie.rid_mastertaskitemevent = r_mastertaskitemevent.rid_mastertaskitemevent
and tie.rid_taskitem = r_taskitem.rid_taskitem
into r_taskitemevent;
--raise exception 'Show me the error: % %',r_taskitemevent.rid_taskitemevent, r_taskitemevent.rid_taskitem;
--raise notice 'New/Update r_taskitemevent? %',r_taskitemevent;
-- if r_taskitem.rid_taskitem > 0
-- and p_payload->'jsonvalue'->>'errorcode' is not null
-- then
-- update core.taskitem u
-- set jsonvalue = _jsonb_object_cat(u.jsonvalue, jsonb_build_object(
-- 'errorcode', _bv(p_payload->'jsonvalue'->>'errorcode',u.jsonvalue->>'errorcode')
-- ,'errormessage',_bv( p_payload->'jsonvalue'->>'errormessage',u.jsonvalue->>'errormessage')
-- ,'alerttype', _bv(p_payload->'jsonvalue'->>'alerttype',u.jsonvalue->>'alerttype')
-- ))
-- where u.rid_taskitem = r_taskitem.rid_taskitem;
--
-- end if;
if r_taskitemevent.rid_taskitemevent > 0
then
update core.taskitemevent u
set
retval = 0
, errmsg = null
, jsonvalue = _jsonb_object_cat(u.jsonvalue, (
select mte.jsonvalue
from core.mastertaskitemevent mte
where mte.rid_mastertaskitemevent = u.rid_mastertaskitemevent
limit 1
), p_payload -> 'jsonvalue')
where u.rid_taskitemevent = r_taskitemevent.rid_taskitemevent;
select r.p_retval, r.p_errmsg
from core.event_created(r_taskitemevent.rid_taskitemevent
, jsonb_build_object('operation', 'UPDATE')) r
into m_retval,m_errmsg;
if m_retval > 0
then
raise '%',m_errmsg;
end if;
select e.*
from core.taskitemevent e
where e.rid_taskitemevent = r_taskitemevent.rid_taskitemevent
into r_taskitemevent;
if length(r_taskitemevent.errmsg) > 0
then
p_retval = 1;
p_errmsg = r_taskitemevent.errmsg;
end if;
else
insert
into core.taskitemevent( createddatetime, description, rid_mastertaskitemevent, rid_taskitem, status
--, duedatetime
--, escalated
, jsonvalue, outcome, rid_hub_user, retval)
select now()
, r_mastertaskitemevent.description
, r_mastertaskitemevent.rid_mastertaskitemevent
, r_taskitem.rid_taskitem
, _bv(r_mastertaskitemevent.status, m_status)
, _jsonb_object_cat((
select mte.jsonvalue
from core.mastertaskitemevent mte
where mte.rid_mastertaskitemevent = r_mastertaskitemevent.rid_mastertaskitemevent
limit 1
), p_payload -> 'jsonvalue')
, m_outcome
, m_rid_hub_user
, 0
where
not exists (
select 1
from core.taskitemevent tie
where
tie.rid_mastertaskitemevent = r_mastertaskitemevent.rid_mastertaskitemevent
and tie.rid_taskitem = r_taskitem.rid_taskitem
)
returning taskitemevent.*
into r_taskitemevent;
-- select r.p_retval,r.p_errmsg
-- from core.event_created(r_taskitemevent.rid_taskitemevent
-- ,jsonb_build_object('operation','UPDATE')) r
-- into m_retval,m_errmsg;
--
-- if m_retval > 0
-- then
-- raise '%',m_errmsg;
-- end if;
select e.*
from core.taskitemevent e
where e.rid_taskitemevent = r_taskitemevent.rid_taskitemevent
into r_taskitemevent;
if length(r_taskitemevent.errmsg) > 1
then
p_retval = 1;
p_errmsg = r_taskitemevent.errmsg;
end if;
end if;
with
recursive
tasklist_events as (
select ti.rid_taskitem
, 1 as level
, coalesce(ti.seqno, 0) as seqno
, ti.status
from core.taskitem ti
inner join core.mastertaskitem mti on mti.rid_mastertaskitem = ti.rid_mastertaskitem
where
(ti.rid_tasklist = r_taskitem.rid_tasklist
or ti.rid_tasklist in (
select tl.rid_tasklist_parent
from core.tasklistlink tl
where tl.rid_tasklist_child = r_taskitem.rid_tasklist
union
select tl.rid_tasklist_child
from core.tasklistlink tl
where tl.rid_tasklist_parent = r_taskitem.rid_tasklist
)
)
-- and mti.rid_mastertaskitem in (
-- select ev2.rid_mastertaskitem
-- from core.mastertaskitemeventreaction er
-- inner join core.mastertaskitemevent ev2 on ev2.rid_mastertaskitemevent = er.rid_mastertaskitemevent_target
-- where er.rid_mastertaskitemevent = r_taskitemevent.rid_mastertaskitemevent
-- )
union
select ti.rid_taskitem
, te.level + 1
, coalesce(ti.seqno, 0) as seqno
, ti.status
from core.taskitem ti
inner join tasklist_events te on te.rid_taskitem = ti.rid_parenttaskitem
)
select e.rid_taskitem
from tasklist_events e
where nv(e.status) in (2, 10)
order by e.level desc, e.status desc, e.seqno desc
limit 1
into m_final_rid_taskitem;
j_obj = _jsonb_object_cat(to_jsonb(r_taskitemevent), jsonb_build_object(
'jsonvalue', _jsonb_object_cat(r_taskitemevent.jsonvalue, jsonb_build_object(
'rid_tasklist', r_taskitem.rid_tasklist,
'rid_tasklist_event', (
select jsonb_agg(distinct ti.rid_tasklist)
from core.mastertaskitemeventreaction er
inner join core.mastertaskitemevent mtiet
on mtiet.rid_mastertaskitemevent = er.rid_mastertaskitemevent_target
inner join core.taskitem ti on ti.rid_mastertaskitem = mtiet.rid_mastertaskitem
and ti.rid_hub = r_taskitem.rid_hub
and ti.rid_tasklist = r_taskitem.rid_tasklist
where er.rid_mastertaskitemevent = r_taskitemevent.rid_mastertaskitemevent
)
, 'rid_tasklist_next', (
select jsonb_agg(distinct tl.rid_tasklist)
from core.taskitem ti
inner join core.mastertaskitem mti on mti.rid_mastertaskitem = ti.rid_mastertaskitem
inner join core.mastertask mtj on mti.guid = mti.jsonvalue ->> 'guid_mastertask_next'
inner join core.tasklist tl on tl.rid_mastertask = mtj.rid_mastertask
and tl.rid_hub = r_taskitem.rid_hub
where ti.rid_taskitem = r_taskitemevent.rid_taskitem
)
, 'select_taskitem_guid', (
select ti.guid
from core.taskitem ti
where
(m_final_rid_taskitem > 0
and ti.rid_taskitem = m_final_rid_taskitem
or nv(m_final_rid_taskitem) = 0
and ti.rid_tasklist = r_taskitem.rid_tasklist
)
order by
case
when ti.status in (10) then 2
when ti.status in (0, 1, 2) then 1
else 99
end
, ti.status desc, ti.seqno desc
limit 1
)
, 'openactions', (
select count(ti.rid_taskitem) filter ( where
coalesce(ti.status, 0) in (
core._enumi('eventstatus', 'todo'), core._enumi('eventstatus', 'planned')
)
)
from core.taskitem ti
where
ti.rid_tasklist in (
select r_taskitem.rid_tasklist
union
select tl.rid_tasklist_child
from core.tasklistlink tl
where tl.rid_tasklist_parent = r_taskitem.rid_tasklist
union
select tl.rid_tasklist_parent
from core.tasklistlink tl
where tl.rid_tasklist_child = r_taskitem.rid_tasklist
)
and nv(ti.subitem) = 0
and coalesce(ti.status, 0) <> coalesce(core._enumi('eventstatus', 'Canceled'), 0)
)
))
, 'WFL', to_jsonb(r_taskitem)));
j_obj = _jsonb_object_cat(j_obj
, jsonb_build_object('jsonvalue'
, _jsonb_object_cat(
j_obj -> 'jsonvalue'
, jsonb_build_object('complete'
, (j_obj -> 'jsonvalue' ->> 'rid_tasklist_event' is null
and j_obj -> 'jsonvalue' ->> 'rid_tasklist_next' is null
and _try_integer(j_obj -> 'jsonvalue' ->> 'openactions', 0) = 0
and nv(r_taskitemevent.jsonvalue ->> 'errorcode') not ilike 'E%'
)
)
)
)
);
j_result = j_result || j_obj;
if m_final_rid_taskitem > 0 and m_final_rid_taskitem is distinct from r_taskitem.rid_taskitem
then
j_obj = _jsonb_object_cat(to_jsonb(ev), jsonb_build_object(
'jsonvalue', jsonb_build_object(
'rid_tasklist', ti.rid_tasklist
, 'select_taskitem_guid', (
select ti.guid
from core.taskitem ti
where
(m_final_rid_taskitem > 0
and ti.rid_taskitem = m_final_rid_taskitem
or nv(m_final_rid_taskitem) = 0
and ti.rid_tasklist = r_taskitem.rid_tasklist
)
order by case when ti.status in (0, 1, 2) then 1 else 99 end, ti.status desc, ti.seqno desc
limit 1
)
, 'openactions', (
select count(ti.rid_taskitem) filter ( where
coalesce(ti.status, 0) in (
core._enumi('eventstatus', 'todo'), core._enumi('eventstatus', 'planned')
)
)
from core.taskitem ti
where
ti.rid_tasklist = r_taskitem.rid_tasklist
and nv(ti.subitem) = 0
and coalesce(ti.status, 0) <> coalesce(core._enumi('eventstatus', 'Canceled'), 0)
limit 1
)
)
, 'WFL', to_jsonb(ti)
)
)
from core.taskitem ti
inner join lateral (
select *
from core.taskitemevent ev
where
ev.rid_taskitem = ti.rid_taskitem
and ev.status in (2, 4)
order by ev.status desc
limit 1
) ev on ev.rid_taskitem = ti.rid_taskitem
where ti.rid_taskitem = m_final_rid_taskitem;
j_result = j_result || j_obj;
end if;
end loop;
--perform log_event(m_funcname,format('Result j_result: %s',j_result),bt_enum('eventlog','local notice'));
p_payload = j_result;
EXCEPTION
WHEN others THEN
GET STACKED DIAGNOSTICS
m_errmsg = MESSAGE_TEXT
,m_errcontext = PG_EXCEPTION_CONTEXT
,m_errdetail = PG_EXCEPTION_DETAIL
,m_errhint = PG_EXCEPTION_HINT
,m_errstate = RETURNED_SQLSTATE;
p_errmsg := get_err_msg(m_funcname, m_errmsg, m_errcontext, m_errdetail, m_errhint, m_errstate);
p_retval = 1;
perform log_event(m_funcname, format('Benchmark Err %s Items: %s', array_length(m_temp_rid_list, 1),
(clock_timestamp() - m_tm)::interval::text),
bt_enum('eventlog', 'local notice'));
END;
$$;
/*
select * from core.ui_action_event(jsonb_build_object('check_error',true
,'rid_mastertaskitem',(
select mti.rid_mastertaskitem from core.mastertaskitem mti
where mti.guid = '7a7348ec-7db6-4f13-bca7-c7840de1d22c'
),'rid_hub',20405))
;
select * from core.ui_action_event(jsonb_build_object('check_error',true
,'rid_mastertaskitem',(
select mti.rid_mastertaskitem from core.mastertaskitem mti
where mti.guid = '7a7348ec-7db6-4f13-bca7-c7840de1d22c'
),'rid_hub',20405))
;
select * from v_eventlog
selecT * from core.taskitem ti
order by ti.rid_taskitem desc
select mti.rid_mastertask,mti.rid_mastertaskitem, mti.description, mti.guid from core.mastertaskitem mti order by mti.rid_mastertaskitem desc;
*/
--select cli.rid_hub from t_adproclient cli where cli.clientid = '92092101980891'
+5 -5
View File
@@ -1,12 +1,12 @@
--select * from dropall('resolvespec_login'); --select * from dropall('resolvespec_login');
CREATE OR REPLACE FUNCTION resolvespec_login( CREATE OR REPLACE FUNCTION resolvespec_login(
INOUT p_data jsonb INOUT p_data jsonb
,OUT p_success boolean , OUT p_success boolean
,OUT p_error text , OUT p_error text
) )
LANGUAGE plpgsql LANGUAGE plpgsql
VOLATILE VOLATILE
SECURITY DEFINER SECURITY DEFINER
AS AS
$$ $$
DECLARE DECLARE
+33 -33
View File
@@ -1,17 +1,17 @@
CREATE OR REPLACE FUNCTION mm_proc( CREATE OR REPLACE FUNCTION mm_proc(
p_doctype text --File Types: html, docx, text, allfieldvalues p_doctype text --File Types: html, docx, text, allfieldvalues
,p_commtype text --Merge Data Type: e.g. SMS,Email,All (Will be passed through to menu/taglist funct) , p_commtype text --Merge Data Type: e.g. SMS,Email,All (Will be passed through to menu/taglist funct)
,p_template bytea --Source/Template file to be merge , p_template bytea --Source/Template file to be merge
,p_data_prefix text --Table prefix for data source. e.g. tcli (client) , sta (standard letters) , p_data_prefix text --Table prefix for data source. e.g. tcli (client) , sta (standard letters)
,p_data_rid integer --rid for given table prefix , p_data_rid integer --rid for given table prefix
,p_filterdata json = NULL --Advanced filter data. , p_filterdata json = NULL --Advanced filter data.
,OUT p_doc bytea --Merged document output , OUT p_doc bytea --Merged document output
,OUT p_docguid text --optional guid to store document guid from tempfile table. (For disk reading) , OUT p_docguid text --optional guid to store document guid from tempfile table. (For disk reading)
,OUT p_retval integer , OUT p_retval integer
,OUT p_errmsg text , OUT p_errmsg text
) )
LANGUAGE plpgsql LANGUAGE plpgsql
VOLATILE VOLATILE
AS AS
$$ $$
DECLARE DECLARE
@@ -98,17 +98,17 @@ BEGIN
m_user = f_getuser(); m_user = f_getuser();
-- if p_doctype ilike '%plain%' and f_iscompressed(p_template) in ('none') -- if p_doctype ilike '%plain%' and f_iscompressed(p_template) in ('none')
-- and byteatotext(p_template) not ilike '%'|| G_TAG_S || '%' || G_TAG_E || '%' -- and byteatotext(p_template) not ilike '%'|| G_TAG_S || '%' || G_TAG_E || '%'
-- then -- then
-- raise warning 'No tags to merge in plain template.'; -- raise warning 'No tags to merge in plain template.';
-- p_doc = p_template; -- p_doc = p_template;
-- return; -- return;
-- end if; -- end if;
-- perform log_event(m_funcname,format('INIT _ type=%s commtype=%s p_data_prefix=%s p_data_rid=%s Template:%s' -- perform log_event(m_funcname,format('INIT _ type=%s commtype=%s p_data_prefix=%s p_data_rid=%s Template:%s'
-- ,p_doctype, p_commtype,p_data_prefix,p_data_rid -- ,p_doctype, p_commtype,p_data_prefix,p_data_rid
-- ,case when octet_length(p_template) < 100 then byteatotext(p_template) else octet_length(p_template)::text end -- ,case when octet_length(p_template) < 100 then byteatotext(p_template) else octet_length(p_template)::text end
-- ),bt_enum('eventlog','local notice')); -- ),bt_enum('eventlog','local notice'));
if p_data_prefix::citext = 'com' if p_data_prefix::citext = 'com'
then then
@@ -168,7 +168,7 @@ BEGIN
into r_doc; into r_doc;
-- perform log_event(m_funcname,format('init = p_doctype = %s p_data_prefix = %s p_data_rid = %s p_template[size] = %s' -- perform log_event(m_funcname,format('init = p_doctype = %s p_data_prefix = %s p_data_rid = %s p_template[size] = %s'
-- ,p_doctype,p_data_prefix,p_data_rid,octet_length(p_template)),bt_enum('eventlog','local notice')); -- ,p_doctype,p_data_prefix,p_data_rid,octet_length(p_template)),bt_enum('eventlog','local notice'));
if p_doctype = 'allfieldvalues' if p_doctype = 'allfieldvalues'
then then
@@ -291,7 +291,7 @@ BEGIN
from src d ; from src d ;
--CREATE INDEX "idx_tmp_merge_init_src_type" ON tmp_merge_init_src USING btree (merge_type); --CREATE INDEX "idx_tmp_merge_init_src_type" ON tmp_merge_init_src USING btree (merge_type);
--CREATE INDEX "idx_tmp_merge_init_src_tag" ON tmp_merge_init_src USING btree (mergetag); --CREATE INDEX "idx_tmp_merge_init_src_tag" ON tmp_merge_init_src USING btree (mergetag);
--HTML field types has a special meaning in the frontend. We treat them as normal fields. --HTML field types has a special meaning in the frontend. We treat them as normal fields.
update tmp_merge_init_src u update tmp_merge_init_src u
@@ -513,8 +513,8 @@ BEGIN
) )
then then
-- perform log_event(m_funcname,format('NO TAGS p_doctype=%s p_commtype=%s p_data_prefix=%s p_data_rid=%s' -- perform log_event(m_funcname,format('NO TAGS p_doctype=%s p_commtype=%s p_data_prefix=%s p_data_rid=%s'
-- ,p_doctype, p_commtype,p_data_prefix,p_data_rid),bt_enum('eventlog','local notice')); -- ,p_doctype, p_commtype,p_data_prefix,p_data_rid),bt_enum('eventlog','local notice'));
-- --
p_doc = p_template; p_doc = p_template;
return; return;
@@ -553,7 +553,7 @@ BEGIN
where tat.description ilike 'Form 16 (%' where tat.description ilike 'Form 16 (%'
), 'TCLI',1000016) r ), 'TCLI',1000016) r
*/ */
/* /*
drop table if exists debug_merge_init_src; drop table if exists debug_merge_init_src;
create table debug_merge_init_src as create table debug_merge_init_src as
@@ -1130,10 +1130,10 @@ BEGIN
) )
loop loop
-- perform log_event(m_funcname,format(' Tables %s=%s src=%s rn=%s' ,p_data_prefix,p_data_rid -- perform log_event(m_funcname,format(' Tables %s=%s src=%s rn=%s' ,p_data_prefix,p_data_rid
-- ,r_lp_t.source,r_lp_t.rn -- ,r_lp_t.source,r_lp_t.rn
-- ),bt_enum('eventlog','local notice') -- ),bt_enum('eventlog','local notice')
-- --,(select jsonb_agg(row_to_json(f)::jsonb) from tmp_merge_init_fields f)::text -- --,(select jsonb_agg(row_to_json(f)::jsonb) from tmp_merge_init_fields f)::text
-- ); -- );
if r_lp_t.table_name = any(a_inner_selected) and nv(r_lp_t.table_name ) <> '' if r_lp_t.table_name = any(a_inner_selected) and nv(r_lp_t.table_name ) <> ''
then then
@@ -1385,10 +1385,10 @@ BEGIN
end if; end if;
-- perform log_event(m_funcname,format('Complex Tables %s=%s m_json_full_complex=%s' ,p_data_prefix,p_data_rid -- perform log_event(m_funcname,format('Complex Tables %s=%s m_json_full_complex=%s' ,p_data_prefix,p_data_rid
-- ,m_json_full_complex::text -- ,m_json_full_complex::text
-- ),bt_enum('eventlog','local notice') -- ),bt_enum('eventlog','local notice')
-- --,(select jsonb_agg(row_to_json(f)::jsonb) from tmp_merge_init_fields f)::text -- --,(select jsonb_agg(row_to_json(f)::jsonb) from tmp_merge_init_fields f)::text
-- ); -- );
m_execfilter = ''; m_execfilter = '';
m_execstr = ''; m_execstr = '';