@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.
- package/agents/changelog-generator.md +63 -0
- package/agents/code-generator.md +215 -0
- package/agents/code-reviewer.md +145 -0
- package/agents/debugger.md +83 -0
- package/agents/doc-generator.md +67 -0
- package/agents/docs-reference.md +86 -0
- package/agents/migrator.md +84 -0
- package/agents/process-consultant.md +97 -0
- package/agents/refactorer.md +75 -0
- package/agents/sx-configurator.md +67 -0
- package/commands/changelog.md +66 -0
- package/commands/diagnose.md +67 -0
- package/commands/docs.md +81 -0
- package/commands/document.md +67 -0
- package/commands/explain.md +60 -0
- package/commands/generate.md +111 -0
- package/commands/migrate.md +81 -0
- package/commands/process.md +111 -0
- package/commands/refactor.md +65 -0
- package/commands/review.md +60 -0
- package/commands/sxgen.md +98 -0
- package/commands/test.md +103 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -0
- package/package.json +30 -0
- package/skills/advpl-code-generation/SKILL.md +163 -0
- package/skills/advpl-code-generation/patterns-fwformbrowse.md +485 -0
- package/skills/advpl-code-generation/patterns-jobs.md +519 -0
- package/skills/advpl-code-generation/patterns-mvc.md +765 -0
- package/skills/advpl-code-generation/patterns-pontos-entrada.md +708 -0
- package/skills/advpl-code-generation/patterns-rest.md +974 -0
- package/skills/advpl-code-generation/patterns-soap.md +639 -0
- package/skills/advpl-code-generation/patterns-treport.md +481 -0
- package/skills/advpl-code-generation/patterns-workflow.md +779 -0
- package/skills/advpl-code-generation/templates-classes.md +1096 -0
- package/skills/advpl-code-review/SKILL.md +72 -0
- package/skills/advpl-code-review/rules-best-practices.md +444 -0
- package/skills/advpl-code-review/rules-modernization.md +290 -0
- package/skills/advpl-code-review/rules-performance.md +333 -0
- package/skills/advpl-code-review/rules-security.md +302 -0
- package/skills/advpl-debugging/SKILL.md +265 -0
- package/skills/advpl-debugging/common-errors.md +1124 -0
- package/skills/advpl-debugging/performance-tips.md +768 -0
- package/skills/advpl-refactoring/SKILL.md +139 -0
- package/skills/advpl-to-tlpp-migration/SKILL.md +293 -0
- package/skills/advpl-to-tlpp-migration/migration-checklist.md +122 -0
- package/skills/advpl-to-tlpp-migration/migration-rules.md +265 -0
- package/skills/changelog-patterns/SKILL.md +99 -0
- package/skills/code-explanation/SKILL.md +66 -0
- package/skills/documentation-patterns/SKILL.md +172 -0
- package/skills/embedded-sql/SKILL.md +379 -0
- package/skills/probat-testing/SKILL.md +226 -0
- package/skills/probat-testing/patterns-unit-tests.md +614 -0
- package/skills/protheus-business/SKILL.md +92 -0
- package/skills/protheus-business/modulo-compras.md +780 -0
- package/skills/protheus-business/modulo-contabilidade.md +874 -0
- package/skills/protheus-business/modulo-estoque.md +876 -0
- package/skills/protheus-business/modulo-faturamento.md +800 -0
- package/skills/protheus-business/modulo-financeiro.md +1015 -0
- package/skills/protheus-business/modulo-fiscal.md +749 -0
- package/skills/protheus-business/modulo-manutencao.md +848 -0
- package/skills/protheus-business/modulo-pcp.md +743 -0
- package/skills/protheus-reference/SKILL.md +119 -0
- package/skills/protheus-reference/native-functions.md +7029 -0
- package/skills/protheus-reference/rest-api-reference.md +1758 -0
- package/skills/protheus-reference/restricted-functions.md +265 -0
- package/skills/protheus-reference/sx-dictionary.md +854 -0
- 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.
|