@netoalmanca/advpl-sensei 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/agents/changelog-generator.md +63 -0
  2. package/agents/code-generator.md +215 -0
  3. package/agents/code-reviewer.md +145 -0
  4. package/agents/debugger.md +83 -0
  5. package/agents/doc-generator.md +67 -0
  6. package/agents/docs-reference.md +86 -0
  7. package/agents/migrator.md +84 -0
  8. package/agents/process-consultant.md +97 -0
  9. package/agents/refactorer.md +75 -0
  10. package/agents/sx-configurator.md +67 -0
  11. package/commands/changelog.md +66 -0
  12. package/commands/diagnose.md +67 -0
  13. package/commands/docs.md +81 -0
  14. package/commands/document.md +67 -0
  15. package/commands/explain.md +60 -0
  16. package/commands/generate.md +111 -0
  17. package/commands/migrate.md +81 -0
  18. package/commands/process.md +111 -0
  19. package/commands/refactor.md +65 -0
  20. package/commands/review.md +60 -0
  21. package/commands/sxgen.md +98 -0
  22. package/commands/test.md +103 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +143 -0
  26. package/dist/index.js.map +1 -0
  27. package/package.json +30 -0
  28. package/skills/advpl-code-generation/SKILL.md +163 -0
  29. package/skills/advpl-code-generation/patterns-fwformbrowse.md +485 -0
  30. package/skills/advpl-code-generation/patterns-jobs.md +519 -0
  31. package/skills/advpl-code-generation/patterns-mvc.md +765 -0
  32. package/skills/advpl-code-generation/patterns-pontos-entrada.md +708 -0
  33. package/skills/advpl-code-generation/patterns-rest.md +974 -0
  34. package/skills/advpl-code-generation/patterns-soap.md +639 -0
  35. package/skills/advpl-code-generation/patterns-treport.md +481 -0
  36. package/skills/advpl-code-generation/patterns-workflow.md +779 -0
  37. package/skills/advpl-code-generation/templates-classes.md +1096 -0
  38. package/skills/advpl-code-review/SKILL.md +72 -0
  39. package/skills/advpl-code-review/rules-best-practices.md +444 -0
  40. package/skills/advpl-code-review/rules-modernization.md +290 -0
  41. package/skills/advpl-code-review/rules-performance.md +333 -0
  42. package/skills/advpl-code-review/rules-security.md +302 -0
  43. package/skills/advpl-debugging/SKILL.md +265 -0
  44. package/skills/advpl-debugging/common-errors.md +1124 -0
  45. package/skills/advpl-debugging/performance-tips.md +768 -0
  46. package/skills/advpl-refactoring/SKILL.md +139 -0
  47. package/skills/advpl-to-tlpp-migration/SKILL.md +293 -0
  48. package/skills/advpl-to-tlpp-migration/migration-checklist.md +122 -0
  49. package/skills/advpl-to-tlpp-migration/migration-rules.md +265 -0
  50. package/skills/changelog-patterns/SKILL.md +99 -0
  51. package/skills/code-explanation/SKILL.md +66 -0
  52. package/skills/documentation-patterns/SKILL.md +172 -0
  53. package/skills/embedded-sql/SKILL.md +379 -0
  54. package/skills/probat-testing/SKILL.md +226 -0
  55. package/skills/probat-testing/patterns-unit-tests.md +614 -0
  56. package/skills/protheus-business/SKILL.md +92 -0
  57. package/skills/protheus-business/modulo-compras.md +780 -0
  58. package/skills/protheus-business/modulo-contabilidade.md +874 -0
  59. package/skills/protheus-business/modulo-estoque.md +876 -0
  60. package/skills/protheus-business/modulo-faturamento.md +800 -0
  61. package/skills/protheus-business/modulo-financeiro.md +1015 -0
  62. package/skills/protheus-business/modulo-fiscal.md +749 -0
  63. package/skills/protheus-business/modulo-manutencao.md +848 -0
  64. package/skills/protheus-business/modulo-pcp.md +743 -0
  65. package/skills/protheus-reference/SKILL.md +119 -0
  66. package/skills/protheus-reference/native-functions.md +7029 -0
  67. package/skills/protheus-reference/rest-api-reference.md +1758 -0
  68. package/skills/protheus-reference/restricted-functions.md +265 -0
  69. package/skills/protheus-reference/sx-dictionary.md +854 -0
  70. package/skills/sx-configuration/SKILL.md +184 -0
@@ -0,0 +1,854 @@
1
+ # Protheus Data Dictionary (SX Tables)
2
+
3
+ > **Important**: Direct access to SX dictionary tables (e.g., `DbSelectArea("SX3")`, `DbSeek()`) is deprecated and blocked by TOTVS SonarQube rules. Use the recommended framework classes instead: `FWSX1Util`, `FWSX2Util`, `FWSX3Util`, `FWSX6Util`, `FWSIXUtil`, `FWGetSX5()`, and `FwPutSX5()`.
4
+
5
+ Reference for the TOTVS Protheus data dictionary tables. These metadata tables define the structure of all business tables, fields, indexes, triggers, and parameters in the ERP system.
6
+
7
+ ---
8
+
9
+ ## SX1 - Perguntas (Report Parameters)
10
+
11
+ SX1 stores the parameter questions used in reports, processing routines, and other programs that invoke the `Pergunte()` function. Each group of questions is identified by a group code (`X1_GRUPO`), and each question within the group has an order number (`X1_ORDEM`). When the user runs a report, the system reads SX1 to build the parameter dialog, and the answers are stored in the public variables `mv_par01` through `mv_par06` (and beyond, depending on the number of questions).
12
+
13
+ ### Key Fields
14
+
15
+ | Field Name | Type | Size | Description |
16
+ |------------|------|------|-------------|
17
+ | X1_GRUPO | C | 6 | Question group identifier (e.g., "AFR010") |
18
+ | X1_ORDEM | C | 2 | Order/sequence of the question within the group ("01", "02", ...) |
19
+ | X1_PERGUNT | C | 60 | Question text displayed in Portuguese |
20
+ | X1_PERSPA | C | 60 | Question text in Spanish |
21
+ | X1_PERENG | C | 60 | Question text in English |
22
+ | X1_TIPO | C | 1 | Answer type: "C" (Character), "N" (Numeric), "D" (Date), "L" (Logical) |
23
+ | X1_TAMANHO | N | 3 | Size of the answer field |
24
+ | X1_GSC | C | 1 | Get, Select, or Combo: "G" (text input), "S" (spinner/range), "C" (combo box) |
25
+ | X1_DEF01 | C | 70 | Default value / combo option 1 (Portuguese) |
26
+ | X1_DEF02 | C | 70 | Default value / combo option 2 (Portuguese) |
27
+ | X1_DEF03 | C | 70 | Default value / combo option 3 (Portuguese) |
28
+ | X1_DEF04 | C | 70 | Default value / combo option 4 (Spanish) |
29
+ | X1_DEF05 | C | 70 | Default value / combo option 5 (English) |
30
+ | X1_CNT01 | C | 70 | Current content of the answer (Portuguese) |
31
+ | X1_CNT02 | C | 70 | Current content of the answer (Spanish) |
32
+ | X1_CNT03 | C | 70 | Current content of the answer (English) |
33
+ | X1_VAR01 | C | 10 | Variable name that will receive the answer (mv_par01, etc.) |
34
+ | X1_VAR02 | C | 10 | Variable name (Spanish) |
35
+ | X1_VAR03 | C | 10 | Variable name (English) |
36
+ | X1_VALID | C | 120 | Validation expression for the answer |
37
+ | X1_F3 | C | 6 | F3 lookup code (references SXB) |
38
+ | X1_GRPSEC | C | 2 | Security group |
39
+ | X1_PESSION | C | 1 | Persistent: "S" (Yes) or "N" (No) - whether to remember the last answer |
40
+
41
+ ### Programmatic Access
42
+
43
+ #### Recommended Approach
44
+
45
+ ```advpl
46
+ // FWSX1Util - Recommended class for SX1 operations
47
+ Local oSX1 := FWSX1Util():New()
48
+ oSX1:AddGroup("MR0001")
49
+ oSX1:SearchGroup()
50
+ Local aPergunte := oSX1:GetGroup("MR0001")
51
+
52
+ // Check if a question group exists
53
+ Local lExists := FWSX1Util():ExistPergunte("MR0001")
54
+
55
+ // Check if a specific item exists in the group
56
+ Local lItem := FWSX1Util():ExistItem("MR0001", "De cliente?")
57
+
58
+ // Using Pergunte() to open the parameter dialog (standard approach for reports)
59
+ User Function MyReport()
60
+
61
+ // Pergunte() opens the parameter dialog for group "MR0001"
62
+ // Returns .T. if user confirmed, .F. if cancelled
63
+ If !Pergunte("MR0001", .T.)
64
+ Return
65
+ EndIf
66
+
67
+ // After Pergunte(), answers are in mv_par01..mv_parNN
68
+ Local cCodDe := mv_par01 // e.g., "From" customer code
69
+ Local cCodAte := mv_par02 // e.g., "To" customer code
70
+ Local dDtDe := mv_par03 // e.g., "From" date
71
+ Local dDtAte := mv_par04 // e.g., "To" date
72
+ Local nOpcao := mv_par05 // e.g., combo selection (1, 2, or 3)
73
+
74
+ // Use parameters in the report logic
75
+ DbSelectArea("SA1")
76
+ DbSetOrder(1)
77
+ DbSeek(xFilial("SA1") + cCodDe)
78
+
79
+ While !Eof() .And. SA1->A1_COD <= cCodAte
80
+ // Process records...
81
+ DbSkip()
82
+ EndDo
83
+
84
+ Return
85
+ ```
86
+
87
+ #### Legacy Approach (deprecated)
88
+
89
+ > **Warning**: Direct access to SX tables via `DbSelectArea()` / `DbSeek()` is blocked by TOTVS SonarQube. Use `FWSX1Util` instead.
90
+
91
+ ```advpl
92
+ // Reading SX1 directly to check what questions exist in a group
93
+ // DEPRECATED - Use FWSX1Util():GetGroup() instead
94
+ User Function ListQuestions(cGroup)
95
+ Local aArea := GetArea()
96
+
97
+ DbSelectArea("SX1")
98
+ DbSetOrder(1)
99
+ DbSeek(cGroup)
100
+
101
+ While !Eof() .And. SX1->X1_GRUPO == cGroup
102
+ ConOut("Question " + SX1->X1_ORDEM + ": " + AllTrim(SX1->X1_PERGUNT))
103
+ ConOut(" Type: " + SX1->X1_TIPO + " | Size: " + cValToChar(SX1->X1_TAMANHO))
104
+ DbSkip()
105
+ EndDo
106
+
107
+ RestArea(aArea)
108
+ Return
109
+ ```
110
+
111
+ ### Common Use Cases
112
+
113
+ - **Report parameters**: Every standard report uses `Pergunte()` with an SX1 group to let users filter data by date range, code range, branch, etc.
114
+ - **Custom processing routines**: Define questions for batch jobs so users can specify parameters before execution.
115
+ - **Querying existing parameters**: Read SX1 to discover what parameters a given report/routine expects, useful when automating via Job Scheduler.
116
+
117
+ ---
118
+
119
+ ## SX2 - Tabelas (Table Definitions)
120
+
121
+ SX2 is the master table registry. It contains one record for every table (alias) available in the Protheus environment. Each record maps a two or three-character alias (e.g., "SA1", "SC5", "ZA1") to its physical file name, description, path, and sharing mode. When registering a custom table, a new record must be added to SX2.
122
+
123
+ ### Key Fields
124
+
125
+ | Field Name | Type | Size | Description |
126
+ |------------|------|------|-------------|
127
+ | X2_CHAVE | C | 3 | Table alias (e.g., "SA1", "SC5", "ZA1") |
128
+ | X2_PATH | C | 60 | Relative path where the data file is stored |
129
+ | X2_ARQUIVO | C | 10 | Physical file name (e.g., "SA1990" for company 99, branch 0) |
130
+ | X2_NOME | C | 30 | Table description in Portuguese (e.g., "Clientes") |
131
+ | X2_NOMESPA | C | 30 | Table description in Spanish |
132
+ | X2_NOMEENG | C | 30 | Table description in English |
133
+ | X2_UESSION | C | 1 | Exclusive mode: "C" (Compartilhado/Shared) or "E" (Exclusivo/Exclusive) |
134
+ | X2_MODO | C | 1 | Sharing mode: "C" (Compartilhado) or "E" (Exclusivo) |
135
+ | X2_TTS | C | 1 | Enable TTS (Transaction Tracking System): "S" or "N" |
136
+ | X2_ROTINA | C | 20 | Associated routine name |
137
+ | X2_PESSION | C | 1 | Persistent connection |
138
+
139
+ ### Programmatic Access
140
+
141
+ #### Recommended Approach
142
+
143
+ ```advpl
144
+ // FWSX2Util - Recommended class for SX2 operations
145
+
146
+ // Get physical file name for a table
147
+ Local cFile := FWSX2Util():GetFile("SA1")
148
+
149
+ // Get path of the table
150
+ Local cPath := FWSX2Util():GetPath("SA1")
151
+
152
+ // Get table description
153
+ Local cName := FWSX2Util():GetX2Name("SA1") // Returns "Clientes"
154
+
155
+ // Get the module that owns the table
156
+ Local nModule := FWSX2Util():GetX2Module("SA1")
157
+
158
+ // Check if a table exists (positions on SX2)
159
+ Local lExists := FWSX2Util():SeekX2File("SA1990")
160
+
161
+ // Return specific fields from SX2
162
+ Local aData := FWSX2Util():GetSX2Data("SA1", {"X2_UNICO"}, .F.)
163
+
164
+ // Opening a table by its alias (standard Protheus pattern)
165
+ DbSelectArea("SA1") // Internally looks up SX2 to find the physical file
166
+ DbSetOrder(1) // Set to the first SIX index
167
+ ```
168
+
169
+ #### Legacy Approach (deprecated)
170
+
171
+ > **Warning**: Direct access to SX tables via `DbSelectArea()` / `DbSeek()` is blocked by TOTVS SonarQube. Use `FWSX2Util` instead.
172
+
173
+ ```advpl
174
+ // Check if a table alias exists in SX2
175
+ // DEPRECATED - Use FWSX2Util():SeekX2File() instead
176
+ User Function TableExists(cAlias)
177
+ Local lExists := .F.
178
+ Local aArea := GetArea()
179
+
180
+ DbSelectArea("SX2")
181
+ DbSetOrder(1)
182
+ lExists := DbSeek(cAlias)
183
+
184
+ RestArea(aArea)
185
+ Return lExists
186
+
187
+ // List all custom tables (aliases starting with "Z")
188
+ // DEPRECATED - Use FWSX2Util methods instead
189
+ User Function ListCustomTables()
190
+ Local aArea := GetArea()
191
+
192
+ DbSelectArea("SX2")
193
+ DbSetOrder(1)
194
+ DbSeek("Z")
195
+
196
+ While !Eof() .And. Left(SX2->X2_CHAVE, 1) == "Z"
197
+ ConOut("Alias: " + SX2->X2_CHAVE + ;
198
+ " | File: " + AllTrim(SX2->X2_ARQUIVO) + ;
199
+ " | Desc: " + AllTrim(SX2->X2_NOME))
200
+ DbSkip()
201
+ EndDo
202
+
203
+ RestArea(aArea)
204
+ Return
205
+ ```
206
+
207
+ ### Common Use Cases
208
+
209
+ - **Registering custom tables**: Before adding custom fields (SX3) or indexes (SIX), the table alias must exist in SX2.
210
+ - **Validating table existence**: Before attempting `DbSelectArea()`, check SX2 to confirm the alias is registered.
211
+ - **Environment documentation**: Query SX2 to generate a catalog of all tables in a Protheus environment, useful for audits and migrations.
212
+
213
+ ---
214
+
215
+ ## SX3 - Campos (Field Definitions)
216
+
217
+ SX3 is the field dictionary. It defines every field in every table registered in SX2, including data type, size, title, validation rules, picture format, browse visibility, mandatory flag, trigger references, and more. This is the most heavily referenced SX table, as it drives how fields are displayed in screens, validated on input, and stored in the database.
218
+
219
+ ### Key Fields
220
+
221
+ | Field Name | Type | Size | Description |
222
+ |------------|------|------|-------------|
223
+ | X3_ARQUIVO | C | 10 | Table alias the field belongs to (e.g., "SA1") |
224
+ | X3_CAMPO | C | 10 | Field name (e.g., "A1_COD", "A1_NOME") |
225
+ | X3_TIPO | C | 1 | Data type: "C" (Char), "N" (Numeric), "D" (Date), "L" (Logical), "M" (Memo) |
226
+ | X3_TAMANHO | N | 3 | Field size |
227
+ | X3_DECIMAL | N | 2 | Number of decimal places (for numeric fields) |
228
+ | X3_TITULO | C | 19 | Field title (Portuguese) displayed in screens |
229
+ | X3_TITSPA | C | 19 | Field title (Spanish) |
230
+ | X3_TITENG | C | 19 | Field title (English) |
231
+ | X3_DESCRIC | C | 55 | Field description (Portuguese) |
232
+ | X3_DESCSPA | C | 55 | Field description (Spanish) |
233
+ | X3_DESCENG | C | 55 | Field description (English) |
234
+ | X3_PICTURE | C | 30 | Display picture/mask (e.g., "@E 999,999.99", "@!") |
235
+ | X3_VALID | C | 120 | Validation expression executed on field exit |
236
+ | X3_USADO | C | 1 | Usage flag - whether the field is active |
237
+ | X3_OBRIGAT | C | 1 | Mandatory field: "S" (Yes) or "N" (No) |
238
+ | X3_BROWSE | C | 1 | Visible in browse grid: "S" (Yes) or "N" (No) |
239
+ | X3_VISUAL | C | 1 | Visibility in screens: "A" (Alter), "V" (Visualize only), blank (always editable) |
240
+ | X3_CONTEXT | C | 1 | Context: "R" (Real), "V" (Virtual) |
241
+ | X3_CBOX | C | 40 | Combo box options (e.g., "1=Active;2=Inactive;3=Blocked") |
242
+ | X3_WHEN | C | 120 | WHEN condition - controls when the field is editable |
243
+ | X3_ESSION | C | 1 | Field level |
244
+ | X3_VLDUSER | C | 120 | User validation expression |
245
+ | X3_PROPRI | C | 1 | Proprietary/module owner |
246
+ | X3_F3 | C | 6 | F3 lookup table code (references SXB) |
247
+ | X3_TRIGGER | C | 1 | Has trigger: "S" (Yes) or "N" (No) |
248
+ | X3_FOLDER | C | 20 | Tab/folder where the field appears in the form |
249
+ | X3_RELACAO | C | 120 | Initial value expression (executed on field initialization) |
250
+ | X3_RESERV | C | 20 | Reserved field |
251
+ | X3_GRPSEC | C | 3 | Security group |
252
+
253
+ ### Programmatic Access
254
+
255
+ #### Recommended Approach
256
+
257
+ ```advpl
258
+ // FWSX3Util - Recommended class for SX3 operations
259
+
260
+ // Get field description
261
+ Local cDesc := FWSX3Util():GetDescription("A1_COD")
262
+
263
+ // Get field type
264
+ Local cType := FWSX3Util():GetFieldType("A1_COD")
265
+
266
+ // Get complete field structure (name, type, size, decimals, picture)
267
+ Local aStruct := FWSX3Util():GetFieldStruct("A1_COD")
268
+
269
+ // List all fields for a table
270
+ Local aFields := FWSX3Util():GetAllFields("SA1", .T.) // .T. includes virtual fields
271
+
272
+ // Get structure of all fields for an alias
273
+ Local aStruct := FWSX3Util():GetListFieldsStruct("SA1", .T., .F.)
274
+
275
+ // Check if a field exists
276
+ Local lExists := FWSX3Util():SeekX3File("A1_COD")
277
+
278
+ // Using GetSX3Cache to get field properties efficiently (also valid)
279
+ Local cType := GetSX3Cache("A1_COD", "X3_TIPO") // Returns "C"
280
+ Local nSize := GetSX3Cache("A1_COD", "X3_TAMANHO") // Returns field size
281
+ Local cPict := GetSX3Cache("A1_COD", "X3_PICTURE") // Returns picture mask
282
+ ```
283
+
284
+ #### Legacy Approach (deprecated)
285
+
286
+ > **Warning**: Direct access to SX tables via `DbSelectArea()` / `DbSeek()` is blocked by TOTVS SonarQube. Use `FWSX3Util` instead.
287
+
288
+ ```advpl
289
+ // Read field properties from SX3
290
+ // DEPRECATED - Use FWSX3Util():GetFieldStruct() instead
291
+ User Function GetFieldInfo(cField)
292
+ Local aArea := GetArea()
293
+
294
+ DbSelectArea("SX3")
295
+ DbSetOrder(2) // Index by field name (X3_CAMPO)
296
+ If DbSeek(cField)
297
+ ConOut("Field: " + AllTrim(SX3->X3_CAMPO))
298
+ ConOut("Table: " + AllTrim(SX3->X3_ARQUIVO))
299
+ ConOut("Type: " + SX3->X3_TIPO)
300
+ ConOut("Size: " + cValToChar(SX3->X3_TAMANHO))
301
+ ConOut("Dec: " + cValToChar(SX3->X3_DECIMAL))
302
+ ConOut("Title: " + AllTrim(SX3->X3_TITULO))
303
+ ConOut("Mand: " + SX3->X3_OBRIGAT)
304
+ ConOut("Valid: " + AllTrim(SX3->X3_VALID))
305
+ ConOut("Picture: " + AllTrim(SX3->X3_PICTURE))
306
+ Else
307
+ ConOut("Field " + cField + " not found in SX3")
308
+ EndIf
309
+
310
+ RestArea(aArea)
311
+ Return
312
+
313
+ // List all fields for a given table
314
+ // DEPRECATED - Use FWSX3Util():GetAllFields() instead
315
+ User Function ListTableFields(cAlias)
316
+ Local aArea := GetArea()
317
+
318
+ DbSelectArea("SX3")
319
+ DbSetOrder(1) // Index by X3_ARQUIVO + X3_CAMPO
320
+ DbSeek(cAlias)
321
+
322
+ While !Eof() .And. AllTrim(SX3->X3_ARQUIVO) == cAlias
323
+ ConOut(PadR(SX3->X3_CAMPO, 10) + " | " + ;
324
+ SX3->X3_TIPO + " | " + ;
325
+ Str(SX3->X3_TAMANHO, 3) + " | " + ;
326
+ AllTrim(SX3->X3_TITULO))
327
+ DbSkip()
328
+ EndDo
329
+
330
+ RestArea(aArea)
331
+ Return
332
+ ```
333
+
334
+ ### Common Use Cases
335
+
336
+ - **Dynamic screen building**: Protheus reads SX3 at runtime to build Enchoice/MVC form layouts, including field order, titles, mandatory flags, and validations.
337
+ - **Custom field validation**: The `X3_VALID` and `X3_VLDUSER` expressions are evaluated every time a field loses focus; they can call ADVPL User Functions.
338
+ - **Field metadata queries**: Programmatically discover field type, size, and picture to build dynamic queries, exports, or integration mappings.
339
+
340
+ ---
341
+
342
+ ## SX5 - Tabelas Genericas (Generic Lookup Tables)
343
+
344
+ SX5 stores generic code-description pairs grouped by a two-character table identifier. These are used as domain value lists for combo boxes, validations, and general lookups throughout the system. For example, table "13" might store states/provinces, and table "01" might store payment conditions codes.
345
+
346
+ ### Key Fields
347
+
348
+ | Field Name | Type | Size | Description |
349
+ |------------|------|------|-------------|
350
+ | X5_FILIAL | C | 8 | Branch code (xFilial("SX5")) |
351
+ | X5_TABELA | C | 2 | Table identifier code (e.g., "13", "01", "AB") |
352
+ | X5_CHAVE | C | 6 | Key/code value within the table |
353
+ | X5_DESCRI | C | 40 | Description in Portuguese |
354
+ | X5_DESCSPA | C | 40 | Description in Spanish |
355
+ | X5_DESCENG | C | 40 | Description in English |
356
+
357
+ ### Programmatic Access
358
+
359
+ #### Recommended Approach
360
+
361
+ ```advpl
362
+ // FWGetSX5 / FwPutSX5 - Recommended functions for SX5 operations
363
+
364
+ // Get all records from a generic table
365
+ Local aContent := FWGetSX5("13") // Returns array with all records from table "13"
366
+ // aContent[n][1] = Branch, [2] = Table, [3] = Key, [4] = Description
367
+
368
+ // Get a specific record
369
+ Local aContent := FWGetSX5("13", "SP") // Returns only key "SP" from table "13"
370
+
371
+ // Get with a specific language
372
+ Local aContent := FWGetSX5("13", , "en") // Description in English
373
+
374
+ // Write to SX5
375
+ FwPutSX5(, "ZZ", "001", "Descricao PT", "Description EN", "Descripcion ES")
376
+
377
+ // Using the standard function X5Descri() (also valid for quick lookups)
378
+ Local cDesc := X5Descri("13", "001") // Returns description for table 13, key 001
379
+ ```
380
+
381
+ #### Legacy Approach (deprecated)
382
+
383
+ > **Warning**: Direct access to SX tables via `DbSelectArea()` / `DbSeek()` is blocked by TOTVS SonarQube. Use `FWGetSX5()` and `FwPutSX5()` instead.
384
+
385
+ ```advpl
386
+ // Read a description from a generic table
387
+ // DEPRECATED - Use FWGetSX5() instead
388
+ User Function GetSX5Desc(cTabela, cChave)
389
+ Local cDesc := ""
390
+ Local aArea := GetArea()
391
+
392
+ DbSelectArea("SX5")
393
+ DbSetOrder(1) // X5_FILIAL + X5_TABELA + X5_CHAVE
394
+ If DbSeek(xFilial("SX5") + cTabela + cChave)
395
+ cDesc := AllTrim(SX5->X5_DESCRI)
396
+ EndIf
397
+
398
+ RestArea(aArea)
399
+ Return cDesc
400
+
401
+ // List all entries in a specific generic table
402
+ // DEPRECATED - Use FWGetSX5() instead
403
+ User Function ListSX5Table(cTabela)
404
+ Local aArea := GetArea()
405
+
406
+ DbSelectArea("SX5")
407
+ DbSetOrder(1)
408
+ DbSeek(xFilial("SX5") + cTabela)
409
+
410
+ While !Eof() .And. SX5->X5_FILIAL == xFilial("SX5") .And. SX5->X5_TABELA == cTabela
411
+ ConOut("Key: " + AllTrim(SX5->X5_CHAVE) + ;
412
+ " | Desc: " + AllTrim(SX5->X5_DESCRI))
413
+ DbSkip()
414
+ EndDo
415
+
416
+ RestArea(aArea)
417
+ Return
418
+ ```
419
+
420
+ ### Common Use Cases
421
+
422
+ - **Combo box values**: Fields with `X3_CBOX` often reference SX5 tables to populate dropdown options.
423
+ - **Domain validation**: Validate that a user-entered code exists in a specific generic table before saving.
424
+ - **Localization**: Each entry has descriptions in three languages (Portuguese, Spanish, English), supporting multi-language environments.
425
+
426
+ ---
427
+
428
+ ## SX6 - Parametros (System Parameters MV_*)
429
+
430
+ SX6 stores all system parameters (also called MV parameters) that control the behavior of Protheus modules. Parameter names follow the convention `MV_*` (e.g., `MV_ESTADO`, `MV_MOEDA1`, `MV_CUESSION`). These parameters are read using `GetMV()`, `SuperGetMV()`, or `GetNewPar()` and written using `PutMV()`.
431
+
432
+ ### Key Fields
433
+
434
+ | Field Name | Type | Size | Description |
435
+ |------------|------|------|-------------|
436
+ | X6_FIL | C | 8 | Branch code (blank = all branches, or specific branch) |
437
+ | X6_VAR | C | 10 | Parameter name (e.g., "MV_ESTADO", "MV_1DUP") |
438
+ | X6_TIPO | C | 1 | Value type: "C" (Char), "N" (Numeric), "D" (Date), "L" (Logical) |
439
+ | X6_CONTEUD | C | 250 | Parameter value (stored as character regardless of type) |
440
+ | X6_DESCRIC | C | 60 | Description in Portuguese |
441
+ | X6_DESCSPA | C | 60 | Description in Spanish |
442
+ | X6_DESCENG | C | 60 | Description in English |
443
+ | X6_PROPRI | C | 1 | Proprietary module flag |
444
+
445
+ ### Programmatic Access
446
+
447
+ #### Recommended Approach
448
+
449
+ ```advpl
450
+ // SuperGetMV - Recommended way to read parameters (with default value fallback)
451
+ // SuperGetMV(cParam, lHelp, cDefault)
452
+ Local cEstado := SuperGetMV("MV_ESTADO", .F., "SP")
453
+ Local nMoeda := SuperGetMV("MV_MOEDA1", .F., 1)
454
+
455
+ // GetNewPar - Alternative with default value
456
+ Local cEstado := GetNewPar("MV_ESTADO", "SP")
457
+
458
+ // GetMV - Older approach (still valid but SuperGetMV is preferred)
459
+ Local cEstado := GetMV("MV_ESTADO")
460
+
461
+ // Writing/updating a parameter value
462
+ PutMV("MV_ESTADO", "RJ") // Changes the state parameter to "RJ"
463
+
464
+ // Example: Check if a feature is enabled
465
+ If SuperGetMV("MV_USARFT", .F., "N") == "S"
466
+ // Feature is enabled
467
+ EndIf
468
+
469
+ // FWSX6Util - For existence checks and replication operations
470
+ // Check if a parameter exists
471
+ Local lExists := FWSX6Util():ExistsParam("MV_ESTADO")
472
+
473
+ // Replicate parameter to specific branches
474
+ Local lOk := FWSX6Util():ReplicateParam("MV_ESTADO", {"01","02"})
475
+
476
+ // Replicate to all branches
477
+ Local lOk := FWSX6Util():ReplicateParam("MV_ESTADO", "*")
478
+
479
+ // Get parameter data in JSON format
480
+ Local cJson := FWSX6Util():GetParamData("MV_ESTADO", "99")
481
+ ```
482
+
483
+ #### Legacy Approach (deprecated)
484
+
485
+ > **Warning**: Direct access to SX tables via `DbSelectArea()` / `DbSeek()` is blocked by TOTVS SonarQube. Use `SuperGetMV()`, `PutMV()`, and `FWSX6Util` instead.
486
+
487
+ ```advpl
488
+ // Reading SX6 directly (bulk queries)
489
+ // DEPRECATED - Use FWSX6Util methods instead
490
+ User Function ListMVParams(cPrefix)
491
+ Local aArea := GetArea()
492
+
493
+ DbSelectArea("SX6")
494
+ DbSetOrder(1) // X6_FIL + X6_VAR
495
+ DbSeek(xFilial("SX6") + cPrefix)
496
+
497
+ While !Eof() .And. Left(AllTrim(SX6->X6_VAR), Len(cPrefix)) == cPrefix
498
+ ConOut("Param: " + AllTrim(SX6->X6_VAR) + ;
499
+ " | Type: " + SX6->X6_TIPO + ;
500
+ " | Value: " + AllTrim(SX6->X6_CONTEUD) + ;
501
+ " | Desc: " + AllTrim(SX6->X6_DESCRIC))
502
+ DbSkip()
503
+ EndDo
504
+
505
+ RestArea(aArea)
506
+ Return
507
+ ```
508
+
509
+ ### Common Use Cases
510
+
511
+ - **System configuration**: MV parameters control virtually every configurable behavior in Protheus -- tax rates, default values, feature toggles, paths, etc.
512
+ - **Branch-specific settings**: A parameter can have different values per branch (X6_FIL), allowing multi-branch environments to behave differently.
513
+ - **Feature flags**: Many customizations use custom MV parameters (e.g., `MV_XMYFEAT`) as feature toggles, checked with `SuperGetMV()` and a safe default.
514
+
515
+ ---
516
+
517
+ ## SX7 - Gatilhos (Field Triggers)
518
+
519
+ SX7 defines automatic field triggers. A trigger fires when a source field changes value, evaluating an expression and writing the result into a target field. Triggers are used to auto-fill related fields -- for example, when the user enters a customer code, a trigger can automatically fill the customer name, address, and tax ID.
520
+
521
+ > **Note**: SX7 is less commonly accessed programmatically. Triggers are typically managed through the Configurador module (SIGACFG). There is no dedicated TOTVS framework class for SX7 operations.
522
+
523
+ ### Key Fields
524
+
525
+ | Field Name | Type | Size | Description |
526
+ |------------|------|------|-------------|
527
+ | X7_CAMPO | C | 10 | Source field name that fires the trigger (e.g., "A1_COD") |
528
+ | X7_SEQUENC | C | 3 | Trigger sequence number (for multiple triggers on the same field) |
529
+ | X7_REGRA | C | 120 | Expression to evaluate (the value to fill in the target field) |
530
+ | X7_CDOMIN | C | 10 | Target/destination field that receives the result |
531
+ | X7_TIPO | C | 1 | Trigger type: "P" (Primary - only on new records), "E" (Foreign key lookup), "X" (execute always) |
532
+ | X7_SEEK | C | 120 | Seek expression used to position the lookup table |
533
+ | X7_ALIAS | C | 10 | Alias of the lookup table to seek in |
534
+ | X7_ORDEM | C | 2 | Index order to use in the lookup table |
535
+ | X7_CONDIC | C | 120 | Condition expression: trigger only fires if this evaluates to .T. |
536
+ | X7_PROPRI | C | 1 | Proprietary module flag |
537
+
538
+ ### Programmatic Access
539
+
540
+ ```advpl
541
+ // List all triggers for a specific source field
542
+ User Function ListTriggers(cField)
543
+ Local aArea := GetArea()
544
+
545
+ DbSelectArea("SX7")
546
+ DbSetOrder(1) // X7_CAMPO + X7_SEQUENC
547
+ DbSeek(cField)
548
+
549
+ While !Eof() .And. AllTrim(SX7->X7_CAMPO) == cField
550
+ ConOut("Trigger #" + SX7->X7_SEQUENC)
551
+ ConOut(" Source: " + AllTrim(SX7->X7_CAMPO))
552
+ ConOut(" Target: " + AllTrim(SX7->X7_CDOMIN))
553
+ ConOut(" Rule: " + AllTrim(SX7->X7_REGRA))
554
+ ConOut(" Condition: " + AllTrim(SX7->X7_CONDIC))
555
+ ConOut(" Type: " + SX7->X7_TIPO)
556
+ ConOut(" Alias: " + AllTrim(SX7->X7_ALIAS))
557
+ ConOut(" Order: " + SX7->X7_ORDEM)
558
+ DbSkip()
559
+ EndDo
560
+
561
+ RestArea(aArea)
562
+ Return
563
+
564
+ // Example: A trigger that fills customer name when customer code is entered
565
+ // This would be configured in SX7 as:
566
+ // X7_CAMPO = "C5_CLIENTE" (source: order customer code)
567
+ // X7_ALIAS = "SA1" (lookup: customer table)
568
+ // X7_ORDEM = "01" (index: A1_FILIAL + A1_COD + A1_LOJA)
569
+ // X7_SEEK = xFilial("SA1") + M->C5_CLIENTE + M->C5_LOJACLI
570
+ // X7_REGRA = "SA1->A1_NOME" (expression: customer name)
571
+ // X7_CDOMIN = "C5_NOMECLI" (target: order customer name field)
572
+ // X7_CONDIC = "" (no condition, always fires)
573
+ // X7_TIPO = "E" (foreign key trigger)
574
+ ```
575
+
576
+ ### Common Use Cases
577
+
578
+ - **Auto-fill related fields**: When a foreign key field is entered (e.g., customer code), triggers automatically populate denormalized fields (name, address, CNPJ).
579
+ - **Calculated fields**: Triggers can compute values, such as total = quantity * unit price, and write the result to a target field.
580
+ - **Conditional logic**: The `X7_CONDIC` expression allows triggers to fire only under certain conditions, such as only for specific product types.
581
+
582
+ ---
583
+
584
+ ## SX9 - Relacionamentos (Table Relationships)
585
+
586
+ SX9 defines relationships between tables, similar to foreign key constraints in relational databases. These relationships are used by the system for referential integrity checks, automatic joins in queries, and documentation of the data model.
587
+
588
+ > **Note**: SX9 is less commonly accessed programmatically. Relationships are typically managed through the Configurador module (SIGACFG). There is no dedicated TOTVS framework class for SX9 operations.
589
+
590
+ ### Key Fields
591
+
592
+ | Field Name | Type | Size | Description |
593
+ |------------|------|------|-------------|
594
+ | X9_DOM | C | 10 | Domain/parent table alias (e.g., "SA1") |
595
+ | X9_CDOM | C | 10 | Key field in the domain/parent table |
596
+ | X9_EXPDOM | C | 120 | Expression for the domain side of the relationship |
597
+ | X9_EXP | C | 120 | Expression for the related/child side of the relationship |
598
+ | X9_CONDSQL | C | 200 | SQL condition expression for the relationship |
599
+ | X9_PROPRI | C | 1 | Proprietary module flag |
600
+
601
+ ### Programmatic Access
602
+
603
+ ```advpl
604
+ // List relationships for a specific table
605
+ User Function ListRelationships(cAlias)
606
+ Local aArea := GetArea()
607
+
608
+ DbSelectArea("SX9")
609
+ DbSetOrder(1)
610
+ DbSeek(cAlias)
611
+
612
+ While !Eof() .And. AllTrim(SX9->X9_DOM) == cAlias
613
+ ConOut("Parent Table: " + AllTrim(SX9->X9_DOM))
614
+ ConOut(" Parent Key: " + AllTrim(SX9->X9_CDOM))
615
+ ConOut(" Parent Expr: " + AllTrim(SX9->X9_EXPDOM))
616
+ ConOut(" Related Expr: " + AllTrim(SX9->X9_EXP))
617
+ ConOut(" SQL Cond: " + AllTrim(SX9->X9_CONDSQL))
618
+ DbSkip()
619
+ EndDo
620
+
621
+ RestArea(aArea)
622
+ Return
623
+
624
+ // Example: Check if SA1 (Customers) has relationships defined
625
+ // SA1 -> SE1 (Receivables): A customer generates receivable titles
626
+ // SA1 -> SC5 (Sales Orders): A customer has sales orders
627
+ User Function CheckCustomerRels()
628
+ Local aArea := GetArea()
629
+
630
+ DbSelectArea("SX9")
631
+ DbSetOrder(1)
632
+ DbSeek("SA1")
633
+
634
+ While !Eof() .And. AllTrim(SX9->X9_DOM) == "SA1"
635
+ ConOut("SA1 -> " + AllTrim(SX9->X9_EXP))
636
+ DbSkip()
637
+ EndDo
638
+
639
+ RestArea(aArea)
640
+ Return
641
+ ```
642
+
643
+ ### Common Use Cases
644
+
645
+ - **Referential integrity**: The system can check SX9 before allowing a record deletion to verify no dependent records exist in related tables.
646
+ - **Automatic joins**: Some query builders and report tools use SX9 relationships to suggest or auto-generate joins between tables.
647
+ - **Data model documentation**: SX9 serves as a living data model diagram, documenting how tables relate to each other.
648
+
649
+ ---
650
+
651
+ ## SXB - Consultas Padrao (Standard Queries / F3 Lookups)
652
+
653
+ SXB defines the standard queries (Consultas Padrao) used for F3 lookups. When a user presses F3 on a field, the system reads SXB to determine which table to query, which columns to display, how to search, and how to return the selected value. Each query is identified by an alias/code and can have multiple configuration rows (column definitions, search criteria, etc.).
654
+
655
+ > **Note**: SXB is less commonly accessed programmatically. Standard queries are typically managed through the Configurador module (SIGACFG). There is no dedicated TOTVS framework class for SXB operations.
656
+
657
+ ### Key Fields
658
+
659
+ | Field Name | Type | Size | Description |
660
+ |------------|------|------|-------------|
661
+ | XB_ALIAS | C | 6 | Query identifier code (referenced by X3_F3 in SX3) |
662
+ | XB_TIPO | C | 1 | Row type: "1" (header), "2" (column detail), "3" (return field), "4" (filter), "5" (search order) |
663
+ | XB_DESCRI | C | 40 | Description of the query (for type "1") or column title (for type "2") |
664
+ | XB_COLUNA | C | 10 | Field/column name to display |
665
+ | XB_SEEK | C | 120 | Seek expression used for search |
666
+ | XB_SHOWPESQ | C | 1 | Show in search dialog: "S" (Yes) or "N" (No) |
667
+ | XB_LINPOS | C | 4 | Line position / display order |
668
+ | XB_CONTEM | C | 60 | Content / return expression |
669
+ | XB_ESSION | C | 1 | Return type |
670
+
671
+ ### Programmatic Access
672
+
673
+ ```advpl
674
+ // List the configuration of a standard query
675
+ User Function ListSXBQuery(cQueryAlias)
676
+ Local aArea := GetArea()
677
+
678
+ DbSelectArea("SXB")
679
+ DbSetOrder(1) // XB_ALIAS + XB_TIPO + XB_LINPOS
680
+ DbSeek(cQueryAlias)
681
+
682
+ While !Eof() .And. AllTrim(SXB->XB_ALIAS) == cQueryAlias
683
+ Do Case
684
+ Case SXB->XB_TIPO == "1"
685
+ ConOut("== Query: " + AllTrim(SXB->XB_DESCRI) + " ==")
686
+ Case SXB->XB_TIPO == "2"
687
+ ConOut(" Column: " + AllTrim(SXB->XB_COLUNA) + ;
688
+ " | Title: " + AllTrim(SXB->XB_DESCRI))
689
+ Case SXB->XB_TIPO == "3"
690
+ ConOut(" Return: " + AllTrim(SXB->XB_CONTEM))
691
+ Case SXB->XB_TIPO == "4"
692
+ ConOut(" Filter: " + AllTrim(SXB->XB_SEEK))
693
+ Case SXB->XB_TIPO == "5"
694
+ ConOut(" Search Order: " + AllTrim(SXB->XB_DESCRI))
695
+ EndCase
696
+ DbSkip()
697
+ EndDo
698
+
699
+ RestArea(aArea)
700
+ Return
701
+
702
+ // The F3 lookup is invoked in the UI when a field's X3_F3 references an SXB alias.
703
+ // Example: Field A1_COD might have X3_F3 = "SA1" which triggers a customer lookup.
704
+ // This is configured in SX3, not in code:
705
+ // X3_CAMPO = "C5_CLIENTE"
706
+ // X3_F3 = "SA1" -> When user presses F3, opens the SA1 standard query
707
+ ```
708
+
709
+ ### Common Use Cases
710
+
711
+ - **F3 field lookups**: The primary purpose -- when a user presses F3 on a field, SXB defines what data is shown and what value is returned.
712
+ - **Custom lookup dialogs**: Create custom SXB entries for specialized search screens that display specific columns and filters.
713
+ - **Reusable query definitions**: Multiple fields across different tables can reference the same SXB query code, providing a consistent lookup experience.
714
+
715
+ ---
716
+
717
+ ## SIX - Indices (Index Definitions)
718
+
719
+ SIX stores the index definitions for all tables in the system. Each record defines one index order for a table, including the key expression (which fields compose the index), a description, and a nickname. Indexes are critical for performance -- `DbSetOrder()` references these entries to position the database cursor on the correct index before seeking.
720
+
721
+ ### Key Fields
722
+
723
+ | Field Name | Type | Size | Description |
724
+ |------------|------|------|-------------|
725
+ | INDICE | C | 3 | Table alias (e.g., "SA1", "SC5") |
726
+ | ORDEM | C | 2 | Index order number ("1", "2", "3", ...) |
727
+ | CHAVE | C | 120 | Key expression (e.g., "A1_FILIAL+A1_COD+A1_LOJA") |
728
+ | DESCRICAO | C | 60 | Index description in Portuguese |
729
+ | DESCSPA | C | 60 | Index description in Spanish |
730
+ | DESCENG | C | 60 | Index description in English |
731
+ | SHOWPESQ | C | 1 | Show in search dialog: "S" (Yes) or "N" (No) |
732
+ | NICKNAME | C | 15 | Index nickname for reference |
733
+ | F3 | C | 6 | Associated F3 lookup code |
734
+ | PROPRI | C | 1 | Proprietary module flag |
735
+
736
+ ### Programmatic Access
737
+
738
+ #### Recommended Approach
739
+
740
+ ```advpl
741
+ // FWSIXUtil - Recommended class for SIX operations
742
+
743
+ // Check if an index exists by order number
744
+ Local lExists := FWSIXUtil():ExistIndex("SA1", "1")
745
+
746
+ // Check if an index exists by nickname
747
+ Local lExists := FWSIXUtil():ExistIndex("SE1", "TITPAI", .T.)
748
+
749
+ // Get all indexes for a table
750
+ Local aIndexes := FWSIXUtil():GetAliasIndexes("SA1")
751
+ // Returns: {{field1, field2}, {field1, field2, field3}}
752
+
753
+ // Using indexes in practice:
754
+ // DbSetOrder() sets the active index by its order number from SIX
755
+ DbSelectArea("SA1")
756
+ DbSetOrder(1) // Order 1: A1_FILIAL + A1_COD + A1_LOJA
757
+ DbSeek(xFilial("SA1") + "000001" + "01") // Seek customer 000001, store 01
758
+
759
+ DbSetOrder(3) // Order 3: A1_FILIAL + A1_CGC (CNPJ/CPF index)
760
+ DbSeek(xFilial("SA1") + "12345678000199") // Seek by CNPJ
761
+ ```
762
+
763
+ #### Legacy Approach (deprecated)
764
+
765
+ > **Warning**: Direct access to SX tables via `DbSelectArea()` / `DbSeek()` is blocked by TOTVS SonarQube. Use `FWSIXUtil` instead.
766
+
767
+ ```advpl
768
+ // List all indexes for a table
769
+ // DEPRECATED - Use FWSIXUtil():GetAliasIndexes() instead
770
+ User Function ListIndexes(cAlias)
771
+ Local aArea := GetArea()
772
+
773
+ DbSelectArea("SIX")
774
+ DbSetOrder(1) // INDICE + ORDEM
775
+ DbSeek(cAlias)
776
+
777
+ While !Eof() .And. AllTrim(SIX->INDICE) == cAlias
778
+ ConOut("Index Order " + SIX->ORDEM + ": " + AllTrim(SIX->CHAVE))
779
+ ConOut(" Description: " + AllTrim(SIX->DESCRICAO))
780
+ ConOut(" Nickname: " + AllTrim(SIX->NICKNAME))
781
+ ConOut(" Show Search: " + SIX->SHOWPESQ)
782
+ DbSkip()
783
+ EndDo
784
+
785
+ RestArea(aArea)
786
+ Return
787
+
788
+ // Find which index order to use for a specific key pattern
789
+ // DEPRECATED - Use FWSIXUtil():ExistIndex() instead
790
+ User Function FindIndexByKey(cAlias, cKeyFragment)
791
+ Local cOrder := ""
792
+ Local aArea := GetArea()
793
+
794
+ DbSelectArea("SIX")
795
+ DbSetOrder(1)
796
+ DbSeek(cAlias)
797
+
798
+ While !Eof() .And. AllTrim(SIX->INDICE) == cAlias
799
+ If cKeyFragment $ AllTrim(SIX->CHAVE)
800
+ cOrder := SIX->ORDEM
801
+ ConOut("Found index order " + cOrder + ": " + AllTrim(SIX->CHAVE))
802
+ Exit
803
+ EndIf
804
+ DbSkip()
805
+ EndDo
806
+
807
+ RestArea(aArea)
808
+ Return cOrder
809
+ ```
810
+
811
+ ### Common Use Cases
812
+
813
+ - **Setting the correct index for seeks**: Before calling `DbSeek()`, use `DbSetOrder()` with the index order from SIX that matches the fields you want to search by.
814
+ - **Custom table indexes**: When creating custom tables, register appropriate indexes in SIX to ensure efficient data access.
815
+ - **Performance analysis**: Review SIX to determine if proper indexes exist for frequently-used queries and add missing ones to improve performance.
816
+
817
+ ---
818
+
819
+ ## Cross-Reference: How SX Tables Work Together
820
+
821
+ The SX tables form an interconnected metadata system. Understanding how they relate helps when creating or modifying Protheus customizations:
822
+
823
+ ```
824
+ SX2 (Table) ──────┬──> SX3 (Fields for this table)
825
+ │ │
826
+ │ ├──> X3_F3 ──> SXB (F3 lookup definition)
827
+ │ │
828
+ │ ├──> X3_TRIGGER ──> SX7 (Field triggers)
829
+ │ │
830
+ │ ├──> X3_CBOX ──> SX5 (Combo box domain values)
831
+ │ │
832
+ │ └──> X3_VALID ──> Validation expressions
833
+
834
+ ├──> SIX (Indexes for this table)
835
+
836
+ ├──> SX9 (Relationships to other tables)
837
+
838
+ └──> SX1 (Report parameters referencing this table)
839
+
840
+ SX6 (MV Parameters) ──> System-wide configuration values
841
+ ```
842
+
843
+ ### Typical Workflow: Registering a Custom Table
844
+
845
+ When creating a new custom table (e.g., "ZA1") in Protheus, the following SX entries are needed:
846
+
847
+ 1. **SX2**: Register the table alias "ZA1" with its description and physical file name
848
+ 2. **SX3**: Define every field (ZA1_FILIAL, ZA1_COD, ZA1_DESC, etc.) with types, sizes, validations, and titles
849
+ 3. **SIX**: Create at least one index (e.g., Order 1: ZA1_FILIAL + ZA1_COD)
850
+ 4. **SX7** (optional): Define triggers for auto-fill behavior
851
+ 5. **SXB** (optional): Create a standard query so other fields can use F3 to look up ZA1 records
852
+ 6. **SX9** (optional): Define relationships to other tables
853
+
854
+ This is typically done through the **Configurador** module (SIGACFG), but can also be done programmatically or via the UPDDISTR update process.