forlogic-core 2.4.11 → 2.4.13

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,200 @@
1
+ USE [qualiex_common]
2
+ GO
3
+
4
+ begin tran
5
+
6
+ IF EXISTS (SELECT * FROM sys.objects
7
+ WHERE object_id = OBJECT_ID(N'[import].[risks_groups_staging]')
8
+ AND type IN (N'U'))
9
+ DROP TABLE [import].[risks_groups_staging]
10
+ GO
11
+
12
+ CREATE TABLE [import].[risks_groups_staging](
13
+ [id_batch] [uniqueidentifier] NOT NULL,
14
+ [row_num] [int] NOT NULL,
15
+ [code] [nvarchar](10) NOT NULL,
16
+ [name] [nvarchar](200) NOT NULL,
17
+ [description] [nvarchar](max) NULL,
18
+ [is_active] [varchar](20) NULL,
19
+ [responsible_email] [varchar](150) NOT NULL,
20
+ [place_name] [nvarchar](200) NULL,
21
+ [rule_name] [nvarchar](200) NULL,
22
+ [id_creation_user] [char](8) NOT NULL,
23
+ [id_company] [char](8) NOT NULL,
24
+ CONSTRAINT [pk_risks_groups_staging] PRIMARY KEY CLUSTERED
25
+ (
26
+ [id_batch] ASC,
27
+ [row_num] ASC
28
+ ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
29
+ ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON,
30
+ OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
31
+ ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
32
+ GO
33
+
34
+ CREATE OR ALTER PROCEDURE [import].[validate_risks_groups]
35
+ @id_batch UNIQUEIDENTIFIER
36
+ AS
37
+ BEGIN
38
+ SET NOCOUNT ON;
39
+
40
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
41
+ SELECT @id_batch, s.row_num, 'Código duplicado no arquivo'
42
+ FROM (
43
+ SELECT *, COUNT(*) OVER (PARTITION BY code) AS cnt
44
+ FROM import.risks_groups_staging WITH (NOLOCK)
45
+ WHERE id_batch = @id_batch
46
+ AND NULLIF(RTRIM(LTRIM(code)), '') IS NOT NULL
47
+ ) s
48
+ WHERE s.cnt > 1;
49
+
50
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
51
+ SELECT @id_batch, s.row_num, 'Código de grupo já existe na base para esta unidade'
52
+ FROM import.risks_groups_staging s WITH (NOLOCK)
53
+ INNER JOIN risks.groups t WITH (NOLOCK)
54
+ ON t.code = s.code COLLATE Latin1_General_CS_AS
55
+ AND t.removed = 0
56
+ AND t.id_company = s.id_company COLLATE Latin1_General_CS_AS
57
+ WHERE s.id_batch = @id_batch;
58
+
59
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
60
+ SELECT @id_batch, s.row_num, 'Nome do grupo duplicado no arquivo'
61
+ FROM (
62
+ SELECT *, COUNT(*) OVER (PARTITION BY name) AS cnt
63
+ FROM import.risks_groups_staging WITH (NOLOCK)
64
+ WHERE id_batch = @id_batch
65
+ ) s
66
+ WHERE s.cnt > 1;
67
+
68
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
69
+ SELECT @id_batch, s.row_num, 'Nome do grupo já existe na base para esta unidade'
70
+ FROM import.risks_groups_staging s WITH (NOLOCK)
71
+ INNER JOIN risks.groups t WITH (NOLOCK)
72
+ ON t.name = s.name COLLATE Latin1_General_CS_AS
73
+ AND t.removed = 0
74
+ AND t.id_company = s.id_company COLLATE Latin1_General_CS_AS
75
+ WHERE s.id_batch = @id_batch;
76
+
77
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
78
+ SELECT @id_batch, s.row_num, 'Situação inválida (selecione Ativo ou Inativo na planilha)'
79
+ FROM import.risks_groups_staging s WITH (NOLOCK)
80
+ WHERE s.id_batch = @id_batch
81
+ AND ISNULL(s.is_active, '') COLLATE Latin1_General_CS_AS NOT IN ('Ativo', 'Inativo', '');
82
+
83
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
84
+ SELECT @id_batch, s.row_num, 'Usuário responsável não encontrado'
85
+ FROM import.risks_groups_staging s WITH (NOLOCK)
86
+ LEFT JOIN dbo.users u WITH (NOLOCK)
87
+ ON u.email = s.responsible_email COLLATE Latin1_General_CS_AS
88
+ AND u.removed = 0
89
+ WHERE s.id_batch = @id_batch
90
+ AND NULLIF(RTRIM(LTRIM(s.responsible_email)), '') IS NOT NULL
91
+ AND u.id IS NULL;
92
+
93
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
94
+ SELECT @id_batch, s.row_num, 'Local não encontrado ou inativo'
95
+ FROM import.risks_groups_staging s WITH (NOLOCK)
96
+ LEFT JOIN common.places p WITH (NOLOCK)
97
+ ON p.title = s.place_name COLLATE Latin1_General_CS_AS
98
+ AND p.id_company = s.id_company COLLATE Latin1_General_CS_AS
99
+ AND p.removed = 0
100
+ WHERE s.id_batch = @id_batch
101
+ AND NULLIF(RTRIM(LTRIM(s.place_name)), '') IS NOT NULL
102
+ AND p.id IS NULL;
103
+
104
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
105
+ SELECT @id_batch, s.row_num, 'Regra não encontrada ou inativa'
106
+ FROM import.risks_groups_staging s WITH (NOLOCK)
107
+ LEFT JOIN risks.rules r WITH (NOLOCK)
108
+ ON r.title = s.rule_name COLLATE Latin1_General_CS_AS
109
+ AND r.id_company = s.id_company COLLATE Latin1_General_CS_AS
110
+ AND r.removed = 0
111
+ WHERE s.id_batch = @id_batch
112
+ AND NULLIF(RTRIM(LTRIM(s.rule_name)), '') IS NOT NULL
113
+ AND r.id IS NULL;
114
+
115
+ INSERT INTO risks.groups
116
+ (
117
+ id_company,
118
+ code,
119
+ name,
120
+ description,
121
+ description_text,
122
+ is_active,
123
+ id_responsible_user,
124
+ id_place,
125
+ id_rule,
126
+ id_creation_user,
127
+ creation_date,
128
+ last_modified,
129
+ removed
130
+ )
131
+ SELECT
132
+ s.id_company,
133
+ LTRIM(RTRIM(s.code)) AS code,
134
+ s.name,
135
+ NULLIF(s.description, '') AS description,
136
+ NULLIF(s.description, '') AS description_text,
137
+ CASE
138
+ WHEN s.is_active COLLATE Latin1_General_CS_AS = 'Inativo' THEN 0
139
+ ELSE 1
140
+ END AS is_active,
141
+ u.id AS id_responsible_user,
142
+ p.id AS id_place,
143
+ r.id AS id_rule,
144
+ s.id_creation_user,
145
+ SYSDATETIMEOFFSET() AS creation_date,
146
+ SYSDATETIMEOFFSET() AS last_modified,
147
+ 0 AS removed
148
+ FROM import.risks_groups_staging s WITH (NOLOCK)
149
+ LEFT JOIN dbo.users u WITH (NOLOCK)
150
+ ON u.email = s.responsible_email COLLATE Latin1_General_CS_AS AND u.removed = 0
151
+ LEFT JOIN common.places p WITH (NOLOCK)
152
+ ON p.title = s.place_name COLLATE Latin1_General_CS_AS AND p.id_company = s.id_company AND p.removed = 0
153
+ LEFT JOIN risks.rules r WITH (NOLOCK)
154
+ ON r.title = s.rule_name COLLATE Latin1_General_CS_AS AND r.id_company = s.id_company AND r.removed = 0
155
+ WHERE s.id_batch = @id_batch
156
+ AND NOT EXISTS (
157
+ SELECT 1
158
+ FROM import.errors e
159
+ WHERE e.id_batch = s.id_batch
160
+ AND e.row_num = s.row_num
161
+ );
162
+
163
+ END
164
+ GO
165
+
166
+ CREATE OR ALTER PROCEDURE [import].[get_errors_risks_groups]
167
+ (
168
+ @id_batch UNIQUEIDENTIFIER
169
+ )
170
+ AS
171
+ BEGIN
172
+ SET NOCOUNT ON;
173
+
174
+ SELECT
175
+ STRING_AGG(
176
+ CAST(e.error_msg AS NVARCHAR(MAX)),
177
+ '; '
178
+ ) WITHIN GROUP (ORDER BY e.error_msg) AS error_msg,
179
+
180
+ e.row_num,
181
+ s.code,
182
+ s.name,
183
+ s.id_creation_user
184
+
185
+ FROM import.errors e WITH (NOLOCK)
186
+ JOIN import.risks_groups_staging s WITH (NOLOCK)
187
+ ON s.row_num = e.row_num
188
+ AND s.id_batch = e.id_batch
189
+ WHERE e.id_batch = @id_batch
190
+ GROUP BY
191
+ e.row_num,
192
+ s.code,
193
+ s.name,
194
+ s.id_creation_user
195
+ ORDER BY e.row_num;
196
+ END
197
+ GO
198
+
199
+ -- commit
200
+ -- rollback
@@ -0,0 +1,173 @@
1
+ -- =============================================================
2
+ -- Procedures de importação — Categorias de Fornecedores
3
+ -- Banco: qualiex_common (SQL Server)
4
+ -- Padrão: espelha import.validate_suppliers / import.get_errors_suppliers
5
+ -- Dispatch dinâmico: import.process_batch resolve pelo nome da tabela
6
+ -- (@tablename = 'suppliers_categories').
7
+ --
8
+ -- Decisões confirmadas com o backend:
9
+ -- 1) `id char(8)` é auto-gerado pelo SQL Server — não incluir no INSERT.
10
+ -- 2) `color` default oficial do produto: '#000000ff' (usado quando o CSV vier vazio).
11
+ -- 3) `creation_date` / `last_modified` são populados via SYSDATETIMEOFFSET()
12
+ -- diretamente no INSERT.
13
+ --
14
+ -- A tabela suppliers.categories NÃO possui coluna `code`.
15
+ -- O identificador de negócio para deduplicação é `title` (varchar 200, NOT NULL).
16
+ -- =============================================================
17
+
18
+ USE [qualiex_common]
19
+ GO
20
+
21
+ -- =============================================================
22
+ -- Cleanup — procedures antigas com nomenclatura errada (supplier_*)
23
+ -- =============================================================
24
+ IF OBJECT_ID('import.get_errors_supplier_categories', 'P') IS NOT NULL
25
+ DROP PROCEDURE import.get_errors_supplier_categories;
26
+ GO
27
+ IF OBJECT_ID('import.validate_supplier_categories', 'P') IS NOT NULL
28
+ DROP PROCEDURE import.validate_supplier_categories;
29
+ GO
30
+
31
+ -- =============================================================
32
+ -- Staging table — espelha padrão de import.suppliers_staging
33
+ -- Colunas alinhadas com common.imports_template_fields do template
34
+ -- "Fornecedores | Parâmetros | Categorias"
35
+ -- =============================================================
36
+ /****** Object: Table [import].[suppliers_categories_staging] ******/
37
+ IF EXISTS (SELECT * FROM sys.objects
38
+ WHERE object_id = OBJECT_ID(N'[import].[suppliers_categories_staging]')
39
+ AND type IN (N'U'))
40
+ DROP TABLE [import].[suppliers_categories_staging]
41
+ GO
42
+
43
+ SET ANSI_NULLS ON
44
+ GO
45
+ SET QUOTED_IDENTIFIER ON
46
+ GO
47
+
48
+ CREATE TABLE [import].[suppliers_categories_staging](
49
+ [id_batch] [uniqueidentifier] NOT NULL,
50
+ [row_num] [int] NOT NULL,
51
+ [title] [varchar](200) NOT NULL,
52
+ [description] [varchar](max) NULL,
53
+ [color] [varchar](9) NULL,
54
+ [icon] [varchar](100) NULL,
55
+ [id_form] [char](8) NULL,
56
+ [id_form_action_plans] [char](8) NULL,
57
+ [id_creation_user] [char](8) NOT NULL,
58
+ [id_company] [char](8) NOT NULL,
59
+ CONSTRAINT [pk_suppliers_categories_staging] PRIMARY KEY CLUSTERED
60
+ (
61
+ [id_batch] ASC,
62
+ [row_num] ASC
63
+ ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
64
+ ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON,
65
+ OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
66
+ ) ON [PRIMARY]
67
+ GO
68
+
69
+
70
+
71
+ CREATE OR ALTER PROCEDURE [import].[get_errors_suppliers_categories]
72
+ (
73
+ @id_batch UNIQUEIDENTIFIER
74
+ )
75
+ AS
76
+ BEGIN
77
+ SET NOCOUNT ON;
78
+
79
+ SELECT
80
+ STRING_AGG(
81
+ CAST(e.error_msg AS NVARCHAR(MAX)),
82
+ '; '
83
+ ) WITHIN GROUP (ORDER BY e.error_msg) AS error_msg,
84
+
85
+ e.row_num,
86
+
87
+ s.title,
88
+ s.id_creation_user
89
+
90
+ FROM import.errors e
91
+ JOIN import.suppliers_categories_staging s
92
+ ON s.row_num = e.row_num
93
+ AND s.id_batch = e.id_batch
94
+ WHERE e.id_batch = @id_batch
95
+ GROUP BY
96
+ e.row_num,
97
+ s.title,
98
+ s.id_creation_user
99
+ ORDER BY e.row_num;
100
+ END
101
+ GO
102
+
103
+
104
+ USE [qualiex_common]
105
+ GO
106
+
107
+ CREATE OR ALTER PROCEDURE [import].[validate_suppliers_categories]
108
+ @id_batch UNIQUEIDENTIFIER
109
+ AS
110
+ BEGIN
111
+ SET NOCOUNT ON;
112
+
113
+ -- VALIDAÇÃO 1: Título duplicado dentro do próprio lote
114
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
115
+ SELECT @id_batch, s.row_num, 'Título duplicado no arquivo'
116
+ FROM (
117
+ SELECT *, COUNT(*) OVER (PARTITION BY title) AS cnt
118
+ FROM import.suppliers_categories_staging WITH (NOLOCK)
119
+ WHERE id_batch = @id_batch
120
+ ) s
121
+ WHERE s.cnt > 1;
122
+
123
+ -- VALIDAÇÃO 2: Título já existente na produção (mesma unidade)
124
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
125
+ SELECT @id_batch, s.row_num, 'Título já existe na base'
126
+ FROM import.suppliers_categories_staging s WITH (NOLOCK)
127
+ INNER JOIN suppliers.categories t WITH (NOLOCK)
128
+ ON t.title = s.title COLLATE Latin1_General_CS_AS
129
+ AND t.removed = 0
130
+ AND t.id_company = s.id_company COLLATE Latin1_General_CS_AS
131
+ WHERE s.id_batch = @id_batch;
132
+
133
+ -- INSERÇÃO: apenas registros sem erro
134
+ INSERT INTO suppliers.categories
135
+ (
136
+ title,
137
+ description,
138
+ color,
139
+ icon,
140
+ id_form,
141
+ id_form_action_plans,
142
+ id_company,
143
+ is_active,
144
+ removed,
145
+ id_creation_user,
146
+ id_last_modified_user,
147
+ creation_date,
148
+ last_modified
149
+ )
150
+ SELECT
151
+ s.title,
152
+ NULLIF(s.description, '') AS description,
153
+ COALESCE(NULLIF(s.color, ''), '#000000ff') AS color,
154
+ NULLIF(s.icon, '') AS icon,
155
+ NULLIF(s.id_form, '') AS id_form,
156
+ NULLIF(s.id_form_action_plans, '') AS id_form_action_plans,
157
+ s.id_company,
158
+ 1 AS is_active,
159
+ 0 AS removed,
160
+ s.id_creation_user,
161
+ s.id_creation_user AS id_last_modified_user,
162
+ SYSDATETIMEOFFSET() AS creation_date,
163
+ SYSDATETIMEOFFSET() AS last_modified
164
+ FROM import.suppliers_categories_staging s WITH (NOLOCK)
165
+ WHERE s.id_batch = @id_batch
166
+ AND NOT EXISTS (
167
+ SELECT 1
168
+ FROM import.errors e
169
+ WHERE e.id_batch = s.id_batch
170
+ AND e.row_num = s.row_num
171
+ );
172
+ END
173
+ GO
@@ -0,0 +1,171 @@
1
+ -- =============================================================
2
+ -- Procedures de importação — Fornecedores (code + is_custom_supplier)
3
+ -- Banco: qualiex_common_15 (SQL Server)
4
+ --
5
+ -- Regras conforme suppliers.suppliers_configurations.is_custom_supplier:
6
+ --
7
+ -- is_custom = 0 (padrão do sistema)
8
+ -- code vazio → ERRO "Código obrigatório no padrão AA-NNNNN"
9
+ -- code fora padrão → ERRO "Código fora do padrão do sistema (AA-NNNNN)"
10
+ -- code no padrão → valida duplicidade (lote + base) e insere
11
+ --
12
+ -- is_custom = 1 (customizável)
13
+ -- code vazio → insere com code = NULL
14
+ -- code preenchido → valida duplicidade e insere livremente
15
+ --
16
+ -- Formato padrão do sistema: AA-NNNNN
17
+ -- AA = 2 dígitos (ano)
18
+ -- NNNNN = 5 dígitos (sequencial dentro do ano)
19
+ -- Ex.: 25-00001
20
+ --
21
+ -- Premissa: 1 unidade por lote (id_company constante no staging).
22
+ --
23
+ -- Nota de collation:
24
+ -- Colunas de ID (char(8)) na base de produção usam
25
+ -- `Latin1_General_CS_AS`, enquanto o staging herda o collation
26
+ -- padrão do banco (`Latin1_General_CI_AI`). Todas as comparações
27
+ -- de IDs recebem COLLATE Latin1_General_CS_AS explícito para
28
+ -- evitar "Cannot resolve the collation conflict".
29
+ -- =============================================================
30
+
31
+ USE [qualiex_common_15]
32
+ GO
33
+
34
+ SET ANSI_NULLS ON
35
+ GO
36
+ SET QUOTED_IDENTIFIER ON
37
+ GO
38
+
39
+ CREATE OR ALTER PROCEDURE [import].[validate_suppliers]
40
+ @id_batch UNIQUEIDENTIFIER
41
+ AS
42
+ BEGIN
43
+ SET NOCOUNT ON;
44
+
45
+ -- =========================================================
46
+ -- 0) Lê is_custom_supplier da unidade do lote
47
+ -- =========================================================
48
+ DECLARE @is_custom BIT = 0;
49
+
50
+ SELECT TOP 1 @is_custom = ISNULL(sc.is_custom_supplier, 0)
51
+ FROM import.suppliers_staging s WITH (NOLOCK)
52
+ INNER JOIN suppliers.suppliers_configurations sc WITH (NOLOCK)
53
+ ON sc.id_company = s.id_company COLLATE Latin1_General_CS_AS
54
+ AND sc.removed = 0
55
+ WHERE s.id_batch = @id_batch;
56
+
57
+ -- =========================================================
58
+ -- 1) VALIDAÇÃO DE FORMATO — apenas quando is_custom = 0
59
+ -- =========================================================
60
+ IF @is_custom = 0
61
+ BEGIN
62
+ -- 1.1) Código obrigatório
63
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
64
+ SELECT @id_batch, s.row_num, 'Código obrigatório no padrão AA-NNNNN'
65
+ FROM import.suppliers_staging s WITH (NOLOCK)
66
+ WHERE s.id_batch = @id_batch
67
+ AND ISNULL(s.code, '') = '';
68
+
69
+ -- 1.2) Código fora do padrão AA-NNNNN (2 dígitos, hífen, 5 dígitos)
70
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
71
+ SELECT @id_batch, s.row_num, 'Código fora do padrão do sistema (AA-NNNNN)'
72
+ FROM import.suppliers_staging s WITH (NOLOCK)
73
+ WHERE s.id_batch = @id_batch
74
+ AND s.code <> ''
75
+ AND (
76
+ LEN(s.code) <> 8
77
+ OR s.code NOT LIKE '[0-9][0-9]-[0-9][0-9][0-9][0-9][0-9]'
78
+ );
79
+ END
80
+
81
+ -- =========================================================
82
+ -- 2) VALIDAÇÃO DE DUPLICIDADE — para code preenchido
83
+ -- (aplica em ambos os modos)
84
+ -- =========================================================
85
+
86
+ -- 2.1) Duplicado dentro do próprio lote
87
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
88
+ SELECT @id_batch, s.row_num, 'Código duplicado no arquivo'
89
+ FROM (
90
+ SELECT *, COUNT(*) OVER (PARTITION BY code) AS cnt
91
+ FROM import.suppliers_staging WITH (NOLOCK)
92
+ WHERE id_batch = @id_batch
93
+ AND code <> ''
94
+ ) s
95
+ WHERE s.cnt > 1;
96
+
97
+ -- 2.2) Código já existente na produção (mesma unidade)
98
+ INSERT INTO import.errors (id_batch, row_num, error_msg)
99
+ SELECT @id_batch, s.row_num, 'Código já existe na base'
100
+ FROM import.suppliers_staging s WITH (NOLOCK)
101
+ INNER JOIN suppliers.suppliers t WITH (NOLOCK)
102
+ ON t.code = s.code COLLATE Latin1_General_CS_AS
103
+ AND t.removed = 0
104
+ AND t.id_company = s.id_company COLLATE Latin1_General_CS_AS
105
+ WHERE s.id_batch = @id_batch
106
+ AND s.code <> '';
107
+
108
+ -- =========================================================
109
+ -- 3) INSERÇÃO — apenas registros válidos
110
+ -- (code vazio entra como NULL — permitido só em is_custom = 1)
111
+ -- =========================================================
112
+ INSERT INTO suppliers.suppliers
113
+ (
114
+ code,
115
+ name,
116
+ id_type,
117
+ id_category,
118
+ e_document_type,
119
+ document_number,
120
+ corporate_name,
121
+ email,
122
+ website,
123
+ phone,
124
+ municipal_registration,
125
+ state_registration,
126
+ observations,
127
+ cep,
128
+ state,
129
+ city,
130
+ neighborhood,
131
+ address,
132
+ address_number,
133
+ complement,
134
+ id_creation_user,
135
+ id_company,
136
+ id_last_modified_user
137
+ )
138
+ SELECT
139
+ NULLIF(s.code, ''),
140
+ s.name,
141
+ s.id_type,
142
+ s.id_category,
143
+ s.e_document_type,
144
+ s.document_number,
145
+ s.corporate_name,
146
+ s.email,
147
+ s.website,
148
+ s.phone,
149
+ s.municipal_registration,
150
+ s.state_registration,
151
+ s.observations,
152
+ s.cep,
153
+ s.state,
154
+ s.city,
155
+ s.neighborhood,
156
+ s.address,
157
+ s.address_number,
158
+ s.complement,
159
+ s.id_creation_user,
160
+ s.id_company,
161
+ s.id_creation_user AS id_last_modified_user
162
+ FROM import.suppliers_staging s WITH (NOLOCK)
163
+ WHERE s.id_batch = @id_batch
164
+ AND NOT EXISTS (
165
+ SELECT 1
166
+ FROM import.errors e
167
+ WHERE e.id_batch = s.id_batch
168
+ AND e.row_num = s.row_num
169
+ );
170
+ END
171
+ GO