forlogic-core 2.5.1 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,210 @@
1
+ /*
2
+ Infraestrutura compartilhada do fluxo de importação (staging).
3
+ Executar UMA ÚNICA VEZ por base, antes das procedures validate_*.
4
+ */
5
+
6
+ USE [qualiex_common]
7
+ GO
8
+
9
+ IF NOT EXISTS (SELECT 1 FROM [dbo].[imports_types] WHERE [id] = N'5')
10
+ BEGIN
11
+ INSERT INTO [dbo].[imports_types] ([id], [name])
12
+ VALUES (N'5', N'Staging')
13
+ END
14
+ GO
15
+
16
+ IF SCHEMA_ID('import') IS NULL
17
+ EXEC('CREATE SCHEMA import')
18
+ GO
19
+
20
+ IF OBJECT_ID(N'import.batches', N'U') IS NULL
21
+ BEGIN
22
+ CREATE TABLE import.batches
23
+ (
24
+ id UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWSEQUENTIALID(),
25
+ entity_name VARCHAR(100) NOT NULL,
26
+ status VARCHAR(30) NOT NULL DEFAULT 'PENDING',
27
+ total_rows INT NULL,
28
+ valid_rows INT NULL,
29
+ error_rows INT NULL,
30
+ created_at DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
31
+ started_at DATETIME2 NULL,
32
+ finished_at DATETIME2 NULL,
33
+
34
+ CONSTRAINT chk_import_batches_status
35
+ CHECK
36
+ (
37
+ status IN
38
+ (
39
+ 'PENDING',
40
+ 'PROCESSING',
41
+ 'PROCESSED',
42
+ 'PROCESSED_WITH_ERRORS',
43
+ 'FAILED'
44
+ )
45
+ )
46
+ )
47
+ END
48
+ GO
49
+
50
+ IF OBJECT_ID(N'import.errors', N'U') IS NULL
51
+ BEGIN
52
+ CREATE TABLE import.errors
53
+ (
54
+ id INT IDENTITY PRIMARY KEY,
55
+ id_batch UNIQUEIDENTIFIER NOT NULL,
56
+ row_num INT NOT NULL,
57
+ error_msg NVARCHAR(2000) NOT NULL,
58
+ created_at DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
59
+ )
60
+
61
+ ALTER TABLE import.errors
62
+ ADD CONSTRAINT FK_import_errors_batch
63
+ FOREIGN KEY (id_batch) REFERENCES import.batches(id)
64
+ END
65
+ GO
66
+
67
+ CREATE OR ALTER PROCEDURE import.process_batch
68
+ (
69
+ @id_batch UNIQUEIDENTIFIER,
70
+ @tablename SYSNAME
71
+ )
72
+ AS
73
+ BEGIN
74
+
75
+ SET NOCOUNT ON;
76
+ SET XACT_ABORT ON;
77
+
78
+ DECLARE
79
+ @sql NVARCHAR(MAX),
80
+ @lock_result INT,
81
+ @validation_procedure SYSNAME,
82
+ @staging_table SYSNAME,
83
+ @total INT,
84
+ @errors INT;
85
+
86
+ -- DEFINIÇÕES DINÂMICAS
87
+ SET @validation_procedure = 'validate_' + @tablename;
88
+ SET @staging_table = @tablename + '_staging';
89
+
90
+ IF NOT EXISTS
91
+ (
92
+ SELECT 1
93
+ FROM sys.procedures
94
+ WHERE name = @validation_procedure
95
+ AND schema_id = SCHEMA_ID('import')
96
+ )
97
+ THROW 50003, 'Procedure de validação não encontrada.', 1;
98
+
99
+
100
+ BEGIN TRY
101
+
102
+ -- LOCK DE CONCORRÊNCIA
103
+ EXEC @lock_result = sp_getapplock
104
+ @Resource = @id_batch,
105
+ @LockMode = 'Exclusive',
106
+ @LockOwner = 'Session',
107
+ @LockTimeout = 10000;
108
+
109
+ IF @lock_result < 0
110
+ THROW 50001, 'Não foi possível obter lock do batch.', 1;
111
+
112
+
113
+ -- MARCAR PROCESSANDO
114
+ UPDATE import.batches WITH (UPDLOCK, ROWLOCK)
115
+ SET
116
+ status = 'PROCESSING',
117
+ started_at = SYSUTCDATETIME()
118
+ WHERE id = @id_batch
119
+ AND status = 'PENDING';
120
+
121
+ IF @@ROWCOUNT = 0
122
+ THROW 50002, 'Batch inválido ou não está PENDING.', 1;
123
+
124
+
125
+ BEGIN TRAN;
126
+
127
+
128
+ -- LIMPAR ERROS
129
+ DELETE FROM import.errors WHERE id_batch = @id_batch;
130
+
131
+ -- EXECUTAR VALIDAÇÃO
132
+ SET @sql =
133
+ 'EXEC [import].'
134
+ + QUOTENAME(@validation_procedure)
135
+ + ' @id_batch=@id_batch';
136
+
137
+ EXEC sp_executesql
138
+ @sql,
139
+ N'@id_batch UNIQUEIDENTIFIER',
140
+ @id_batch;
141
+
142
+
143
+ -- CONTAR TOTAL DE LINHAS
144
+ SET @sql =
145
+ '
146
+ SELECT
147
+ @total_out = COUNT(*)
148
+ FROM [import].' + QUOTENAME(@staging_table) + '
149
+ WHERE id_batch = @id_batch
150
+ ';
151
+
152
+ EXEC sp_executesql
153
+ @sql,
154
+ N'@id_batch UNIQUEIDENTIFIER, @total_out INT OUTPUT',
155
+ @id_batch,
156
+ @total OUTPUT;
157
+
158
+
159
+ -- CONTAR LINHAS COM ERRO
160
+ SELECT
161
+ @errors = COUNT(DISTINCT row_num)
162
+ FROM import.errors
163
+ WHERE id_batch = @id_batch;
164
+
165
+
166
+ -- FINALIZAR BATCH
167
+ UPDATE import.batches
168
+ SET
169
+ total_rows = @total,
170
+ error_rows = @errors,
171
+ valid_rows = @total - @errors,
172
+
173
+ status =
174
+ CASE
175
+ WHEN @errors > 0
176
+ THEN 'PROCESSED_WITH_ERRORS'
177
+ ELSE 'PROCESSED'
178
+ END,
179
+
180
+ finished_at = SYSUTCDATETIME()
181
+ WHERE id = @id_batch;
182
+
183
+ COMMIT;
184
+
185
+ EXEC sp_releaseapplock
186
+ @Resource = @id_batch,
187
+ @LockOwner = 'Session';
188
+
189
+ END TRY
190
+ BEGIN CATCH
191
+
192
+ IF @@TRANCOUNT > 0
193
+ ROLLBACK;
194
+
195
+ UPDATE import.batches
196
+ SET
197
+ status = 'FAILED',
198
+ finished_at = SYSUTCDATETIME()
199
+ WHERE id = @id_batch;
200
+
201
+ EXEC sp_releaseapplock
202
+ @Resource = @id_batch,
203
+ @LockOwner = 'Session';
204
+
205
+ THROW;
206
+
207
+ END CATCH
208
+
209
+ END
210
+ GO
@@ -0,0 +1,209 @@
1
+ -- =============================================================
2
+ -- Procedures de importação — Fornecedores | Parâmetros | Critérios
3
+ -- Banco: qualiex_common (SQL Server)
4
+ -- Dispatch dinâmico: import.process_batch resolve pelo table_name
5
+ -- (@tablename = 'criteria').
6
+ --
7
+ -- Colunas esperadas no CSV (ordem do template):
8
+ -- 1) Título -> title (obrigatório)
9
+ -- 2) Etapa de seleção -> selection_stage (Sim/Não)
10
+ -- 3) Etapa de aquisição -> acquisition_stage (Sim/Não)
11
+ -- 4) Tipo de resposta -> id_answer_type (obrigatório, int)
12
+ -- 5) Critério -> type (obrigatório, 1 Mérito / 2 Demérito)
13
+ -- 6) Valor do demérito -> demerit_value (decimal, aceita vírgula)
14
+ -- 7) Critério obrigatório -> required (Sim/Não)
15
+ -- 8) Ocorrências -> is_occurrences (Sim/Não)
16
+ -- 9) Como avaliar -> how_to_evaluate (opcional)
17
+ -- 10) Situação -> is_active (Ativo/Inativo, default Ativo)
18
+ -- 11) Emissor -> id_creation_user (obrigatório, lookup users)
19
+ --
20
+ -- id_company é resolvido pelo backend a partir do contexto da unidade.
21
+ --
22
+ -- Nota de collation:
23
+ -- Colunas texto/ID usam Latin1_General_CS_AS explicitamente para
24
+ -- evitar conflito de collation com a base de produção.
25
+ -- =============================================================
26
+
27
+ USE [qualiex_common]
28
+ GO
29
+
30
+ IF EXISTS (SELECT * FROM sys.objects
31
+ WHERE object_id = OBJECT_ID(N'[import].[criteria_staging]')
32
+ AND type IN (N'U'))
33
+ DROP TABLE [import].[criteria_staging]
34
+ GO
35
+
36
+ CREATE TABLE [import].[criteria_staging](
37
+ [id_batch] [uniqueidentifier] NOT NULL,
38
+ [row_num] [int] NOT NULL,
39
+ [title] [varchar](500) COLLATE Latin1_General_CS_AS NOT NULL,
40
+ [selection_stage] [varchar](20) COLLATE Latin1_General_CS_AS NULL,
41
+ [acquisition_stage] [varchar](20) COLLATE Latin1_General_CS_AS NULL,
42
+ [id_answer_type] [int] NULL,
43
+ [how_to_evaluate] [nvarchar](max) COLLATE Latin1_General_CS_AS NULL,
44
+ [required] [varchar](20) COLLATE Latin1_General_CS_AS NULL,
45
+ [type] [int] NULL,
46
+ [demerit_value] [varchar](20) COLLATE Latin1_General_CS_AS NULL,
47
+ [is_active] [varchar](20) COLLATE Latin1_General_CS_AS NULL,
48
+ [is_occurrences] [varchar](20) COLLATE Latin1_General_CS_AS NULL,
49
+ [id_creation_user] [char](8) COLLATE Latin1_General_CS_AS NOT NULL,
50
+ [id_company] [char](8) COLLATE Latin1_General_CS_AS NOT NULL,
51
+ CONSTRAINT [pk_criteria_staging] PRIMARY KEY CLUSTERED
52
+ (
53
+ [id_batch] ASC,
54
+ [row_num] ASC
55
+ ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
56
+ ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON,
57
+ OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
58
+ ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
59
+ GO
60
+
61
+ USE [qualiex_common]
62
+ GO
63
+
64
+ CREATE OR ALTER PROCEDURE [import].[validate_criteria]
65
+ @id_batch UNIQUEIDENTIFIER
66
+ AS
67
+ BEGIN
68
+ SET NOCOUNT ON;
69
+
70
+ -- Validação 1: Título duplicado dentro do próprio lote
71
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
72
+ SELECT @id_batch, sub.row_num, 'Título duplicado no arquivo'
73
+ FROM (
74
+ SELECT *, COUNT(*) OVER (PARTITION BY title) AS cnt
75
+ FROM import.criteria_staging WITH (NOLOCK)
76
+ WHERE id_batch = @id_batch
77
+ ) sub
78
+ WHERE sub.cnt > 1;
79
+
80
+ -- Validação 2: Título já existente na produção (mesma unidade)
81
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
82
+ SELECT @id_batch, cs.row_num, 'Critério já existe na base para esta unidade'
83
+ FROM import.criteria_staging cs WITH (NOLOCK)
84
+ INNER JOIN suppliers.criteria c WITH (NOLOCK)
85
+ ON c.title COLLATE Latin1_General_CS_AS = cs.title
86
+ AND c.removed = 0
87
+ AND c.id_company COLLATE Latin1_General_CS_AS = cs.id_company
88
+ WHERE cs.id_batch = @id_batch;
89
+
90
+ -- Validação 3: Validação de Situação (Ativo / Inativo)
91
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
92
+ SELECT @id_batch, cs.row_num, 'Situação inválida (selecione Ativo ou Inativo na planilha)'
93
+ FROM import.criteria_staging cs WITH (NOLOCK)
94
+ WHERE cs.id_batch = @id_batch
95
+ AND ISNULL(cs.is_active, '') NOT IN ('Ativo', 'Inativo', '');
96
+
97
+ -- Validação 4: Validação de booleanos genéricos (Sim / Não)
98
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
99
+ SELECT @id_batch, cs.row_num, 'Valor inválido para campos de Sim/Não (Certifique-se de escolher Sim ou Não na planilha)'
100
+ FROM import.criteria_staging cs WITH (NOLOCK)
101
+ WHERE cs.id_batch = @id_batch
102
+ AND (
103
+ ISNULL(cs.selection_stage, '') NOT IN ('Sim', 'Não', '')
104
+ OR ISNULL(cs.acquisition_stage, '') NOT IN ('Sim', 'Não', '')
105
+ OR ISNULL(cs.required, '') NOT IN ('Sim', 'Não', '')
106
+ OR ISNULL(cs.is_occurrences, '') NOT IN ('Sim', 'Não', '')
107
+ );
108
+
109
+ -- Validação 5: Validação de número Decimal (demerit_value)
110
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
111
+ SELECT @id_batch, cs.row_num, 'Valor de demérito inválido. Insira um número válido.'
112
+ FROM import.criteria_staging cs WITH (NOLOCK)
113
+ WHERE cs.id_batch = @id_batch
114
+ AND cs.demerit_value IS NOT NULL
115
+ AND TRY_CAST(REPLACE(cs.demerit_value, ',', '.') AS DECIMAL(6,2)) IS NULL;
116
+
117
+ -- INSERÇÃO DOS DADOS VÁLIDOS
118
+ INSERT INTO suppliers.criteria
119
+ (
120
+ id_company,
121
+ title,
122
+ selection_stage,
123
+ acquisition_stage,
124
+ id_answer_type,
125
+ how_to_evaluate,
126
+ how_to_evaluate_text,
127
+ required,
128
+ id_creation_user,
129
+ id_last_modified_user,
130
+ creation_date,
131
+ last_modified,
132
+ is_active,
133
+ removed,
134
+ type,
135
+ demerit_value,
136
+ is_occurrences
137
+ )
138
+ SELECT
139
+ cs.id_company,
140
+ cs.title,
141
+
142
+ CASE WHEN cs.selection_stage = 'Sim' THEN 1 ELSE 0 END AS selection_stage,
143
+ CASE WHEN cs.acquisition_stage = 'Sim' THEN 1 ELSE 0 END AS acquisition_stage,
144
+
145
+ ISNULL(cs.id_answer_type, 0) AS id_answer_type,
146
+
147
+ NULLIF(cs.how_to_evaluate, '') AS how_to_evaluate,
148
+ NULLIF(cs.how_to_evaluate, '') AS how_to_evaluate_text,
149
+
150
+ CASE WHEN cs.required = 'Sim' THEN 1 ELSE 0 END AS required,
151
+
152
+ cs.id_creation_user,
153
+ cs.id_creation_user AS id_last_modified_user,
154
+ SYSDATETIMEOFFSET() AS creation_date,
155
+ SYSDATETIMEOFFSET() AS last_modified,
156
+
157
+ CASE WHEN cs.is_active = 'Inativo' THEN 0 ELSE 1 END AS is_active,
158
+ 0 AS removed,
159
+
160
+ ISNULL(cs.type, 0) AS type,
161
+ ISNULL(TRY_CAST(REPLACE(cs.demerit_value, ',', '.') AS DECIMAL(6,2)), 0.00) AS demerit_value,
162
+
163
+ CASE WHEN cs.is_occurrences = 'Sim' THEN 1 ELSE 0 END AS is_occurrences
164
+
165
+ FROM import.criteria_staging cs WITH (NOLOCK)
166
+ WHERE cs.id_batch = @id_batch
167
+ AND NOT EXISTS (
168
+ SELECT 1
169
+ FROM import.errors e
170
+ WHERE e.id_batch = cs.id_batch
171
+ AND e.row_num = cs.row_num
172
+ );
173
+
174
+ END
175
+ GO
176
+
177
+ USE [qualiex_common]
178
+ GO
179
+
180
+ CREATE OR ALTER PROCEDURE [import].[get_errors_criteria]
181
+ (
182
+ @id_batch UNIQUEIDENTIFIER
183
+ )
184
+ AS
185
+ BEGIN
186
+ SET NOCOUNT ON;
187
+
188
+ SELECT
189
+ STRING_AGG(
190
+ CAST(e.error_msg AS NVARCHAR(MAX)),
191
+ '; '
192
+ ) WITHIN GROUP (ORDER BY e.error_msg) AS error_msg,
193
+
194
+ e.row_num,
195
+ cs.title,
196
+ cs.id_creation_user
197
+
198
+ FROM import.errors e WITH (NOLOCK)
199
+ JOIN import.criteria_staging cs WITH (NOLOCK)
200
+ ON cs.row_num = e.row_num
201
+ AND cs.id_batch = e.id_batch
202
+ WHERE e.id_batch = @id_batch
203
+ GROUP BY
204
+ e.row_num,
205
+ cs.title,
206
+ cs.id_creation_user
207
+ ORDER BY e.row_num;
208
+ END
209
+ GO
@@ -0,0 +1,295 @@
1
+ use [qualiex_common]
2
+ go
3
+
4
+ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[import].[occurrences_staging]') AND type IN (N'U'))
5
+ DROP TABLE [import].[occurrences_staging]
6
+ GO
7
+
8
+ CREATE TABLE import.occurrences_staging
9
+ (
10
+ id_batch UNIQUEIDENTIFIER,
11
+ row_num INT NOT NULL,
12
+ code NVARCHAR(8) COLLATE Latin1_General_CS_AS NOT NULL,
13
+ name NVARCHAR(500) COLLATE Latin1_General_CS_AS NULL,
14
+ id_type CHAR(8) COLLATE Latin1_General_CS_AS NULL,
15
+ id_category CHAR(8) COLLATE Latin1_General_CS_AS NULL,
16
+ description NVARCHAR(MAX) COLLATE Latin1_General_CS_AS NULL,
17
+ id_creation_user CHAR(8) COLLATE Latin1_General_CS_AS NULL,
18
+ id_responsible CHAR(8) COLLATE Latin1_General_CS_AS NULL,
19
+ start_date DATETIMEOFFSET(7) NULL,
20
+ end_date DATETIMEOFFSET(7) NULL,
21
+ id_status INT NOT NULL,
22
+ id_company CHAR(8) COLLATE Latin1_General_CS_AS NOT NULL,
23
+ CONSTRAINT pk_occurrences_staging PRIMARY KEY CLUSTERED (id_batch, row_num)
24
+ )
25
+ GO
26
+
27
+ USE [qualiex_common]
28
+ GO
29
+
30
+ CREATE OR ALTER PROCEDURE import.validate_occurrences
31
+ @id_batch UNIQUEIDENTIFIER
32
+ AS
33
+ BEGIN
34
+ SET NOCOUNT ON;
35
+
36
+ -- VALIDAÇÃO 1: Duplicado dentro do próprio lote
37
+ INSERT INTO import.errors
38
+ (id_batch, row_num, error_msg)
39
+ SELECT @id_batch, sub.row_num, 'Código duplicado no arquivo'
40
+ FROM (
41
+ SELECT *, COUNT(*) OVER (PARTITION BY code) AS cnt
42
+ FROM import.occurrences_staging WITH (NOLOCK)
43
+ WHERE id_batch = @id_batch
44
+ ) sub
45
+ WHERE sub.cnt > 1;
46
+
47
+ -- VALIDAÇÃO 2: Código já existente na produção
48
+ INSERT INTO import.errors
49
+ (id_batch, row_num, error_msg)
50
+ SELECT @id_batch, os.row_num, 'Código já existe na base'
51
+ FROM import.occurrences_staging os WITH (NOLOCK)
52
+ INNER JOIN occurrences.occurrences o WITH (NOLOCK)
53
+ ON o.code COLLATE Latin1_General_CS_AS = os.code
54
+ AND o.id_company COLLATE Latin1_General_CS_AS = os.id_company
55
+ AND o.removed = 0
56
+ WHERE os.id_batch = @id_batch;
57
+
58
+ -- INSERÇÃO: Apenas registros válidos
59
+ INSERT INTO occurrences.occurrences
60
+ (
61
+ code,
62
+ name,
63
+ id_type,
64
+ id_category,
65
+ description,
66
+ id_creation_user,
67
+ id_responsible,
68
+ start_date,
69
+ end_date,
70
+ id_status,
71
+ id_company,
72
+ root_cause_identification_required,
73
+ checker_responsible_equals_in_occurrences,
74
+ creation_date,
75
+ last_modified,
76
+ removed
77
+ )
78
+ SELECT
79
+ os.code,
80
+ os.name,
81
+ os.id_type,
82
+ os.id_category,
83
+ os.description,
84
+ os.id_creation_user,
85
+ os.id_responsible,
86
+ os.start_date,
87
+ os.end_date,
88
+ os.id_status,
89
+ os.id_company,
90
+ 1,
91
+ 0,
92
+ SYSDATETIMEOFFSET(),
93
+ SYSDATETIMEOFFSET(),
94
+ 0
95
+ FROM import.occurrences_staging os WITH (NOLOCK)
96
+ WHERE os.id_batch = @id_batch
97
+ AND NOT EXISTS (
98
+ SELECT 1
99
+ FROM import.errors e
100
+ WHERE e.id_batch = os.id_batch
101
+ AND e.row_num = os.row_num
102
+ );
103
+
104
+ CREATE TABLE #occurrence_phases (
105
+ id UNIQUEIDENTIFIER,
106
+ id_company CHAR(8),
107
+ id_occurrence CHAR(8),
108
+ id_responsible CHAR(8),
109
+ start_date DATETIME2,
110
+ id_days_work INT,
111
+ days_evaluation INT,
112
+ days_causes_analysis INT,
113
+ days_action_plan_elaboration INT,
114
+ days_action_plan_execution INT,
115
+ days_effectiveness_check INT,
116
+ days_standardization INT
117
+ );
118
+
119
+ INSERT INTO #occurrence_phases (
120
+ id,
121
+ id_company,
122
+ id_occurrence,
123
+ id_responsible,
124
+ start_date,
125
+ id_days_work,
126
+ days_evaluation,
127
+ days_causes_analysis,
128
+ days_action_plan_elaboration,
129
+ days_action_plan_execution,
130
+ days_effectiveness_check,
131
+ days_standardization
132
+ )
133
+ SELECT
134
+ NEWID() AS id,
135
+ o.id_company,
136
+ o.id AS id_occurrence,
137
+ o.id_responsible,
138
+ COALESCE(o.start_date, o.creation_date) AS start_date,
139
+ c.id_days_work,
140
+ cat.days_evaluation,
141
+ cat.days_causes_analysis,
142
+ cat.days_action_plan_elaboration,
143
+ cat.days_action_plan_execution,
144
+ cat.days_effectiveness_check,
145
+ cat.days_standardization
146
+ FROM import.occurrences_staging os WITH (NOLOCK)
147
+ INNER JOIN occurrences.occurrences o WITH (NOLOCK)
148
+ ON o.id_company COLLATE Latin1_General_CS_AS = os.id_company
149
+ AND o.code COLLATE Latin1_General_CS_AS = os.code
150
+ AND o.removed = 0
151
+ INNER JOIN occurrences.configurations c WITH (NOLOCK)
152
+ ON c.id_company = o.id_company
153
+ INNER JOIN occurrences.categories cat WITH (NOLOCK)
154
+ ON cat.id = o.id_category
155
+ WHERE os.id_batch = @id_batch
156
+ AND o.id_category IS NOT NULL;
157
+
158
+ -- create a record table that will hold one row per phase, calculated sequentially
159
+ CREATE TABLE #phase_records (
160
+ id_company CHAR(8),
161
+ id_occurrence CHAR(8),
162
+ id_responsible CHAR(8),
163
+ phase_status INT,
164
+ phase_duration INT,
165
+ phase_end_date DATETIME2
166
+ );
167
+
168
+ -- evaluation
169
+ INSERT INTO #phase_records
170
+ SELECT
171
+ id_company,
172
+ id_occurrence,
173
+ id_responsible,
174
+ 2,
175
+ days_evaluation,
176
+ dbo.AddDays(days_evaluation, start_date, id_days_work, 0)
177
+ FROM #occurrence_phases;
178
+
179
+ -- cause analysis (cumulative)
180
+ INSERT INTO #phase_records
181
+ SELECT
182
+ id_company,
183
+ id_occurrence,
184
+ id_responsible,
185
+ 3,
186
+ days_causes_analysis,
187
+ dbo.AddDays(days_evaluation + days_causes_analysis, start_date, id_days_work, 0)
188
+ FROM #occurrence_phases;
189
+
190
+ -- action plan elaboration (cumulative)
191
+ INSERT INTO #phase_records
192
+ SELECT
193
+ id_company,
194
+ id_occurrence,
195
+ id_responsible,
196
+ 4,
197
+ days_action_plan_elaboration,
198
+ dbo.AddDays(days_evaluation + days_causes_analysis + days_action_plan_elaboration, start_date, id_days_work, 0)
199
+ FROM #occurrence_phases;
200
+
201
+ -- action plan execution (cumulative)
202
+ INSERT INTO #phase_records
203
+ SELECT
204
+ id_company,
205
+ id_occurrence,
206
+ id_responsible,
207
+ 5,
208
+ days_action_plan_execution,
209
+ dbo.AddDays(days_evaluation + days_causes_analysis + days_action_plan_elaboration + days_action_plan_execution, start_date, id_days_work, 0)
210
+ FROM #occurrence_phases;
211
+
212
+ -- effectiveness check (cumulative)
213
+ INSERT INTO #phase_records
214
+ SELECT
215
+ id_company,
216
+ id_occurrence,
217
+ id_responsible,
218
+ 6,
219
+ days_effectiveness_check,
220
+ dbo.AddDays(days_evaluation + days_causes_analysis + days_action_plan_elaboration + days_action_plan_execution + days_effectiveness_check, start_date, id_days_work, 0)
221
+ FROM #occurrence_phases;
222
+
223
+ -- standardization (cumulative)
224
+ INSERT INTO #phase_records
225
+ SELECT
226
+ id_company,
227
+ id_occurrence,
228
+ id_responsible,
229
+ 7,
230
+ days_standardization,
231
+ dbo.AddDays(days_evaluation + days_causes_analysis + days_action_plan_elaboration + days_action_plan_execution + days_effectiveness_check + days_standardization, start_date, id_days_work, 0)
232
+ FROM #occurrence_phases;
233
+
234
+ -- finally insert all records into production at once
235
+ INSERT INTO occurrences.phase_associations
236
+ (id_company, id_occurrence, id_responsible, id_status, duration_days, end_date)
237
+ SELECT
238
+ id_company,
239
+ id_occurrence,
240
+ id_responsible,
241
+ phase_status,
242
+ phase_duration,
243
+ phase_end_date
244
+ FROM #phase_records;
245
+
246
+ DROP TABLE #occurrence_phases;
247
+ DROP TABLE #phase_records;
248
+
249
+ END
250
+ GO
251
+
252
+ use [qualiex_common]
253
+ go
254
+
255
+ CREATE OR ALTER PROCEDURE import.get_errors_occurrences
256
+ (
257
+ @id_batch UNIQUEIDENTIFIER
258
+ )
259
+ AS
260
+ BEGIN
261
+ SET NOCOUNT ON;
262
+
263
+ SELECT
264
+ STRING_AGG(CAST(e.error_msg AS NVARCHAR(MAX)), '; ') WITHIN GROUP (ORDER BY e.error_msg) AS error_msg,
265
+ e.row_num,
266
+ os.code,
267
+ os.name,
268
+ os.id_type,
269
+ os.id_category,
270
+ os.description,
271
+ os.id_creation_user,
272
+ os.id_responsible,
273
+ os.start_date,
274
+ os.end_date,
275
+ os.id_status
276
+ FROM import.errors e WITH (NOLOCK)
277
+ JOIN import.occurrences_staging os WITH (NOLOCK)
278
+ ON os.row_num = e.row_num
279
+ AND os.id_batch = e.id_batch
280
+ WHERE e.id_batch = @id_batch
281
+ GROUP BY
282
+ e.row_num,
283
+ os.code,
284
+ os.name,
285
+ os.id_type,
286
+ os.id_category,
287
+ os.description,
288
+ os.id_creation_user,
289
+ os.id_responsible,
290
+ os.start_date,
291
+ os.end_date,
292
+ os.id_status
293
+ ORDER BY e.row_num;
294
+ END
295
+ GO