@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,481 @@
1
+ # Protheus TReport Patterns
2
+
3
+ Complete reference for implementing reports using the TReport framework in TOTVS Protheus.
4
+
5
+ ---
6
+
7
+ ## 1. Overview
8
+
9
+ The TReport framework is the standard report engine in TOTVS Protheus. It replaces legacy functions like `SetPrint`, `SetDefault`, `RptStatus`, and `Cabec`. TReport allows users to customize report output (font, color, line style, header, footer) and supports PDF, print, and spreadsheet output.
10
+
11
+ Key classes:
12
+ - **TReport**: The report container. Manages pages, orientation, font, and print dialog.
13
+ - **TRSection**: A data section (layout) that holds cells, breaks, and totalizers. Can contain sub-sections for master-detail reports.
14
+ - **TRCell**: A print cell (column) belonging to a section. Defines what data is printed and its formatting.
15
+ - **TRBreak**: Defines break rules for grouping data, triggering subtotals.
16
+ - **TRFunction**: A totalizer attached to a break or section. Supports SUM, COUNT, MAX, MIN, AVERAGE, ONPRINT, TIMESUM, TIMEAVERAGE.
17
+
18
+ Required includes:
19
+ ```advpl
20
+ #Include "TOTVS.CH"
21
+ ```
22
+
23
+ ---
24
+
25
+ ## 2. TReport - Report Container
26
+
27
+ ### 2.1 Constructor
28
+
29
+ ```advpl
30
+ oReport := TReport():New(cName, cTitle, cPergunte, bAction, cDescription, lLandscape)
31
+ ```
32
+
33
+ | Parameter | Type | Description |
34
+ |-----------|------|-------------|
35
+ | `cName` | Character | Report internal name |
36
+ | `cTitle` | Character | Report title displayed in header |
37
+ | `cPergunte` | Character | Pergunte group code (SX1) for filtering. Use `Nil` if using ParamBox |
38
+ | `bAction` | Block | Code block executed for printing: `{|oReport| PrintFunction(oReport)}` |
39
+ | `cDescription` | Character | Report description |
40
+ | `lLandscape` | Logical | `.T.` for landscape, `.F.` for portrait (optional) |
41
+
42
+ ### 2.2 Key Methods
43
+
44
+ | Method | Description |
45
+ |--------|-------------|
46
+ | `SetTitle(cTitle)` | Sets the report title |
47
+ | `SetLandscape()` | Sets page orientation to landscape |
48
+ | `SetPortrait()` | Sets page orientation to portrait |
49
+ | `SetTotalInLine(lInLine)` | `.T.` prints totalizers in line, `.F.` in column |
50
+ | `SetLineHeight(nHeight)` | Sets the line height in printing |
51
+ | `PrintDialog()` | Opens the print configuration dialog |
52
+ | `Print()` | Prints without showing dialog |
53
+
54
+ ### 2.3 Key Properties
55
+
56
+ | Property | Type | Description |
57
+ |----------|------|-------------|
58
+ | `nFontBody` | Numeric | Font size for the report body |
59
+ | `lParamPage` | Logical | `.T.` shows parameter page, `.F.` hides it |
60
+ | `oPage` | Object | Page object for paper configuration |
61
+
62
+ ---
63
+
64
+ ## 3. TRSection - Data Section
65
+
66
+ ### 3.1 Constructor
67
+
68
+ ```advpl
69
+ oSection := TRSection():New(oReport, cName, aAliases, nOrder, cTitle, lLandscape, lDisable)
70
+ ```
71
+
72
+ | Parameter | Type | Description |
73
+ |-----------|------|-------------|
74
+ | `oReport` | Object | Parent TReport or TRSection object |
75
+ | `cName` | Character | Section name |
76
+ | `aAliases` | Array | Array of alias names used by this section, e.g. `{"SB1"}` or `{"QRY_REP"}` |
77
+ | `nOrder` | Numeric | Index order for positioning (optional) |
78
+ | `cTitle` | Character | Section title (optional) |
79
+ | `lLandscape` | Logical | `.T.` for landscape (optional) |
80
+ | `lDisable` | Logical | `.T.` to create disabled (optional) |
81
+
82
+ ### 3.2 Key Methods
83
+
84
+ | Method | Description |
85
+ |--------|-------------|
86
+ | `SetQuery(cAlias, cQuery, lChangeQuery, aParam, aTCFields)` | Defines a SQL query for data source |
87
+ | `SetFilter(cFilter, cIndexKey, cOrdem, cAlias, nIdxOrder)` | Sets a filter on the section table |
88
+ | `SetTotalInLine(lInLine)` | Sets totalizer display mode for this section |
89
+ | `Print()` | Prints the section |
90
+ | `PrintLine()` | Prints a single data line |
91
+ | `Cell(cName)` | Returns the TRCell object for the given field name |
92
+
93
+ ### 3.3 Detail Sections (Master-Detail)
94
+
95
+ A section can contain sub-sections for master-detail reports:
96
+
97
+ ```advpl
98
+ // Master section
99
+ oSecMaster := TRSection():New(oReport, "Master", {"SB1"})
100
+
101
+ // Detail section (child of master)
102
+ oSecDetail := TRSection():New(oSecMaster, "Detail", {"SD1"})
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 4. TRCell - Column Definition
108
+
109
+ ### 4.1 Constructor
110
+
111
+ ```advpl
112
+ TRCell():New(oSection, cName, cAlias, cTitle, cPicture, nSize, lPixel, bBlock, cAlign, lLineBreak, cHeaderAlign, lCellBreak, nColSpace, lAutoSize, nClrBack, nClrFore, lBold)
113
+ ```
114
+
115
+ | Parameter | Type | Description |
116
+ |-----------|------|-------------|
117
+ | `oSection` | Object | Parent TRSection object |
118
+ | `cName` | Character | Field name (from SX3 or query alias) |
119
+ | `cAlias` | Character | Table/query alias reference |
120
+ | `cTitle` | Character | Column header title |
121
+ | `cPicture` | Character | Display format mask (optional) |
122
+ | `nSize` | Numeric | Column width |
123
+ | `lPixel` | Logical | `.T.` if size is in pixels (optional) |
124
+ | `bBlock` | Block | Custom print code block (optional) |
125
+ | `cAlign` | Character | Text alignment: `"LEFT"`, `"CENTER"`, `"RIGHT"` (optional) |
126
+ | `lLineBreak` | Logical | Line break after cell (optional) |
127
+ | `cHeaderAlign` | Character | Header alignment (optional) |
128
+ | `lCellBreak` | Logical | Cell break (optional) |
129
+ | `nColSpace` | Numeric | Column spacing (optional) |
130
+ | `lAutoSize` | Logical | Auto-size column (optional) |
131
+ | `nClrBack` | Numeric | Background color (optional) |
132
+ | `nClrFore` | Numeric | Foreground color (optional) |
133
+ | `lBold` | Logical | `.T.` for bold text (optional) |
134
+
135
+ ---
136
+
137
+ ## 5. TRBreak - Section Break
138
+
139
+ ### 5.1 Constructor
140
+
141
+ ```advpl
142
+ oBreak := TRBreak():New(oSection, uBreak, uTitle, lTotalInLine, cName, lPageBreak)
143
+ ```
144
+
145
+ | Parameter | Type | Description |
146
+ |-----------|------|-------------|
147
+ | `oSection` | Object | Parent TRSection object |
148
+ | `uBreak` | Object/Block | Cell object or code block for break rule |
149
+ | `uTitle` | Block/Character | Break title or code block returning title |
150
+ | `lTotalInLine` | Logical | `.T.` totalizers in line, `.F.` in column |
151
+ | `cName` | Character | Break name (optional) |
152
+ | `lPageBreak` | Logical | `.T.` forces page break on group change (optional) |
153
+
154
+ ---
155
+
156
+ ## 6. TRFunction - Totalizers
157
+
158
+ ### 6.1 Constructor
159
+
160
+ ```advpl
161
+ TRFunction():New(oCell, cId, cFunction, oBreak, cTitle, cPicture, cFormula, lEndSection, lEndReport, lEndPage)
162
+ ```
163
+
164
+ | Parameter | Type | Description |
165
+ |-----------|------|-------------|
166
+ | `oCell` | Object | TRCell object to totalize |
167
+ | `cId` | Character | Totalizer identifier (optional) |
168
+ | `cFunction` | Character | Aggregate function type (see table below) |
169
+ | `oBreak` | Object | TRBreak object (optional, Nil for section/report total) |
170
+ | `cTitle` | Character | Totalizer title (optional) |
171
+ | `cPicture` | Character | Display format mask (optional) |
172
+ | `cFormula` | Character | Custom formula expression (optional) |
173
+ | `lEndSection` | Logical | Print at end of section (optional) |
174
+ | `lEndReport` | Logical | Print at end of report (optional) |
175
+ | `lEndPage` | Logical | Print at end of page (optional) |
176
+
177
+ ### 6.2 Aggregate Function Types
178
+
179
+ | Function | Description |
180
+ |----------|-------------|
181
+ | `"SUM"` | Sum of values |
182
+ | `"COUNT"` | Count of records |
183
+ | `"MAX"` | Maximum value |
184
+ | `"MIN"` | Minimum value |
185
+ | `"AVERAGE"` | Average value |
186
+ | `"ONPRINT"` | Current value at print time |
187
+ | `"TIMESUM"` | Sum of hours |
188
+ | `"TIMEAVERAGE"` | Average of hours |
189
+
190
+ ---
191
+
192
+ ## 7. Filtering - Pergunte and ParamBox
193
+
194
+ ### 7.1 Using Pergunte (SX1)
195
+
196
+ The traditional approach uses the `Pergunte` group registered in SX1. The report constructor receives the group code as the third parameter.
197
+
198
+ ```advpl
199
+ oReport := TReport():New("REL001", "Relatorio de Produtos", "REL001", {|oReport| fPrint(oReport)})
200
+ ```
201
+
202
+ ### 7.2 Using ParamBox
203
+
204
+ For custom parameters without SX1 registration, use `ParamBox` before creating the report:
205
+
206
+ ```advpl
207
+ User Function MyReport()
208
+ Local aPergs := {}
209
+ Local oReport := Nil
210
+ Local cProdDe := Space(TamSX3("B1_COD")[1])
211
+ Local cProdAte := StrTran(cProdDe, " ", "Z")
212
+ Local cTipoDe := Space(TamSX3("B1_TIPO")[1])
213
+ Local cTipoAte := StrTran(cTipoDe, " ", "Z")
214
+ Local nOrdem := 1
215
+
216
+ // Define parameters
217
+ aAdd(aPergs, {1, "Produto De", cProdDe, "", ".T.", "SB1", ".T.", 80, .F.})
218
+ aAdd(aPergs, {1, "Produto Ate", cProdAte, "", ".T.", "SB1", ".T.", 80, .T.})
219
+ aAdd(aPergs, {1, "Tipo De", cTipoDe, "", ".T.", "02", ".T.", 40, .F.})
220
+ aAdd(aPergs, {1, "Tipo Ate", cTipoAte, "", ".T.", "02", ".T.", 40, .T.})
221
+ aAdd(aPergs, {2, "Ordenar por", nOrdem, {"1=Codigo", "2=Descricao"}, 100, ".T.", .T.})
222
+
223
+ If ParamBox(aPergs, "Informe os parametros", , , , , , , , , .F., .F.)
224
+ oReport := fReportDef()
225
+ oReport:PrintDialog()
226
+ EndIf
227
+
228
+ Return Nil
229
+ ```
230
+
231
+ ---
232
+
233
+ ## 8. MenuDef for Reports
234
+
235
+ Reports are typically registered in the Protheus menu with `ADD OPTION`:
236
+
237
+ ```advpl
238
+ Static Function MenuDef()
239
+ Local aRotina := {}
240
+
241
+ ADD OPTION aRotina TITLE "Imprimir" ACTION "U_MyReport" OPERATION 2 ACCESS 0
242
+
243
+ Return aRotina
244
+ ```
245
+
246
+ ---
247
+
248
+ ## 9. Complete Example - Product Report by Group
249
+
250
+ This example creates a report listing products grouped by type, with count totalizer per group.
251
+
252
+ ```advpl
253
+ #Include "TOTVS.CH"
254
+
255
+ /*/{Protheus.doc} zRelProd
256
+ Relatorio de Produtos por Grupo com TReport
257
+ @type User Function
258
+ @author Autor
259
+ @since 01/01/2026
260
+ @version 1.0
261
+ /*/
262
+ User Function zRelProd()
263
+ Local aArea := GetArea()
264
+ Local aPergs := {}
265
+ Local oReport := Nil
266
+ Local cProdDe := Space(TamSX3("B1_COD")[1])
267
+ Local cProdAte := StrTran(cProdDe, " ", "Z")
268
+ Local cTipoDe := Space(TamSX3("B1_TIPO")[1])
269
+ Local cTipoAte := StrTran(cTipoDe, " ", "Z")
270
+
271
+ // Parametros de filtro
272
+ aAdd(aPergs, {1, "Produto De", cProdDe, "", ".T.", "SB1", ".T.", 80, .F.})
273
+ aAdd(aPergs, {1, "Produto Ate", cProdAte, "", ".T.", "SB1", ".T.", 80, .T.})
274
+ aAdd(aPergs, {1, "Tipo De", cTipoDe, "", ".T.", "02", ".T.", 40, .F.})
275
+ aAdd(aPergs, {1, "Tipo Ate", cTipoAte, "", ".T.", "02", ".T.", 40, .T.})
276
+
277
+ If ParamBox(aPergs, "Informe os parametros", , , , , , , , , .F., .F.)
278
+ oReport := fReportDef()
279
+ oReport:PrintDialog()
280
+ EndIf
281
+
282
+ RestArea(aArea)
283
+
284
+ Return Nil
285
+
286
+ // =============================================================
287
+ // Report Definition
288
+ // =============================================================
289
+ Static Function fReportDef()
290
+ Local oReport := Nil
291
+ Local oSection := Nil
292
+ Local oBreak := Nil
293
+
294
+ // Cria o relatorio
295
+ oReport := TReport():New("zRelProd", "Relatorio de Produtos por Grupo", Nil, ;
296
+ {|oReport| fRepPrint(oReport)})
297
+ oReport:SetTotalInLine(.F.)
298
+ oReport:SetPortrait()
299
+ oReport:SetLineHeight(50)
300
+ oReport:nFontBody := 10
301
+ oReport:lParamPage := .F.
302
+
303
+ // Secao de dados
304
+ oSection := TRSection():New(oReport, "Produtos", {"QRY_REP"})
305
+ oSection:SetTotalInLine(.F.)
306
+
307
+ // Colunas do relatorio
308
+ TRCell():New(oSection, "B1_COD", "QRY_REP", "Codigo", /*cPicture*/, 15, /*lPixel*/, /*bBlock*/, "LEFT", /*lLineBreak*/, "LEFT")
309
+ TRCell():New(oSection, "B1_DESC", "QRY_REP", "Descricao", /*cPicture*/, 30, /*lPixel*/, /*bBlock*/, "LEFT", /*lLineBreak*/, "LEFT")
310
+ TRCell():New(oSection, "B1_TIPO", "QRY_REP", "Tipo", /*cPicture*/, 05, /*lPixel*/, /*bBlock*/, "LEFT", /*lLineBreak*/, "LEFT")
311
+ TRCell():New(oSection, "B1_UM", "QRY_REP", "Un. Med.", /*cPicture*/, 05, /*lPixel*/, /*bBlock*/, "LEFT", /*lLineBreak*/, "LEFT")
312
+ TRCell():New(oSection, "B1_PRV1", "QRY_REP", "Preco", "@E 999,999.99", 12, /*lPixel*/, /*bBlock*/, "RIGHT", /*lLineBreak*/, "RIGHT")
313
+
314
+ // Quebra por tipo de produto
315
+ oBreak := TRBreak():New(oSection, oSection:Cell("B1_TIPO"), ;
316
+ {|| "Total do Tipo: " + AllTrim((oSection:Cell("B1_TIPO")):cBuffer)}, .F.)
317
+
318
+ // Totalizador: contagem de produtos por quebra
319
+ TRFunction():New(oSection:Cell("B1_COD"), Nil, "COUNT", oBreak, "Qtd Produtos", "@E 999,999,999")
320
+
321
+ // Totalizador: soma de precos no final do relatorio
322
+ TRFunction():New(oSection:Cell("B1_PRV1"), Nil, "SUM", Nil, "Total Geral", "@E 999,999,999.99", Nil, .F., .T.)
323
+
324
+ Return oReport
325
+
326
+ // =============================================================
327
+ // Print Logic
328
+ // =============================================================
329
+ Static Function fRepPrint(oReport)
330
+ Local cQuery := ""
331
+ Local cAlias := GetNextAlias()
332
+ Local oSection := oReport:Section(1)
333
+
334
+ // Monta query com filtros do ParamBox
335
+ cQuery := "SELECT B1_COD, B1_DESC, B1_TIPO, B1_UM, B1_PRV1 "
336
+ cQuery += "FROM " + RetSqlName("SB1") + " SB1 "
337
+ cQuery += "WHERE SB1.D_E_L_E_T_ = ' ' "
338
+ cQuery += "AND B1_FILIAL = '" + xFilial("SB1") + "' "
339
+ cQuery += "AND B1_COD >= '" + MV_PAR01 + "' "
340
+ cQuery += "AND B1_COD <= '" + MV_PAR02 + "' "
341
+ cQuery += "AND B1_TIPO >= '" + MV_PAR03 + "' "
342
+ cQuery += "AND B1_TIPO <= '" + MV_PAR04 + "' "
343
+ cQuery += "ORDER BY B1_TIPO, B1_COD "
344
+
345
+ TCQuery cQuery New Alias (cAlias)
346
+
347
+ // Configura a secao para usar o alias da query
348
+ oSection:BeginQuery()
349
+
350
+ While !(cAlias)->(Eof())
351
+ oSection:PrintLine()
352
+ (cAlias)->(DbSkip())
353
+ EndWh
354
+
355
+ oSection:EndQuery()
356
+
357
+ (cAlias)->(DbCloseArea())
358
+
359
+ Return Nil
360
+ ```
361
+
362
+ ---
363
+
364
+ ## 10. Using SetQuery for Automatic Processing
365
+
366
+ Instead of manually iterating records, you can use `SetQuery` to let TReport handle the data loop automatically:
367
+
368
+ ```advpl
369
+ Static Function fReportDef()
370
+ Local oReport := Nil
371
+ Local oSection := Nil
372
+ Local cQuery := ""
373
+
374
+ oReport := TReport():New("zRelAuto", "Relatorio Automatico", Nil, ;
375
+ {|oReport| oReport:Section(1):Print()})
376
+ oReport:SetTotalInLine(.F.)
377
+ oReport:SetPortrait()
378
+
379
+ // Secao com query automatica
380
+ oSection := TRSection():New(oReport, "Produtos", {"TMP"})
381
+
382
+ cQuery := "SELECT B1_COD, B1_DESC, B1_TIPO, B1_UM, B1_PRV1 "
383
+ cQuery += "FROM " + RetSqlName("SB1") + " SB1 "
384
+ cQuery += "WHERE SB1.D_E_L_E_T_ = ' ' "
385
+ cQuery += "AND B1_FILIAL = '" + xFilial("SB1") + "' "
386
+ cQuery += "ORDER BY B1_TIPO, B1_COD "
387
+
388
+ oSection:SetQuery("TMP", cQuery)
389
+
390
+ // Colunas
391
+ TRCell():New(oSection, "B1_COD", "TMP", "Codigo", /*cPicture*/, 15, /*lPixel*/, /*bBlock*/, "LEFT")
392
+ TRCell():New(oSection, "B1_DESC", "TMP", "Descricao", /*cPicture*/, 30, /*lPixel*/, /*bBlock*/, "LEFT")
393
+ TRCell():New(oSection, "B1_TIPO", "TMP", "Tipo", /*cPicture*/, 05, /*lPixel*/, /*bBlock*/, "LEFT")
394
+ TRCell():New(oSection, "B1_UM", "TMP", "Un. Med.", /*cPicture*/, 05, /*lPixel*/, /*bBlock*/, "LEFT")
395
+ TRCell():New(oSection, "B1_PRV1", "TMP", "Preco", "@E 999,999.99", 12, /*lPixel*/, /*bBlock*/, "RIGHT")
396
+
397
+ Return oReport
398
+ ```
399
+
400
+ ---
401
+
402
+ ## 11. Master-Detail Report
403
+
404
+ Example of a report with two related sections (order header + order items):
405
+
406
+ ```advpl
407
+ Static Function fReportDef()
408
+ Local oReport := Nil
409
+ Local oSecMaster := Nil
410
+ Local oSecDetail := Nil
411
+
412
+ oReport := TReport():New("zRelMD", "Pedidos e Itens", Nil, ;
413
+ {|oReport| fRepPrintMD(oReport)})
414
+ oReport:SetLandscape()
415
+ oReport:SetTotalInLine(.F.)
416
+
417
+ // Secao master (cabecalho do pedido)
418
+ oSecMaster := TRSection():New(oReport, "Pedidos", {"SC7"})
419
+
420
+ TRCell():New(oSecMaster, "C7_NUM", "SC7", "Numero", /*cPicture*/, 10, /*lPixel*/, /*bBlock*/, "LEFT")
421
+ TRCell():New(oSecMaster, "C7_EMISSAO","SC7", "Emissao", /*cPicture*/, 10, /*lPixel*/, /*bBlock*/, "LEFT")
422
+ TRCell():New(oSecMaster, "C7_FORNECE","SC7", "Fornecedor", /*cPicture*/, 10, /*lPixel*/, /*bBlock*/, "LEFT")
423
+
424
+ // Secao detail (itens do pedido) - filha da master
425
+ oSecDetail := TRSection():New(oSecMaster, "Itens", {"SC7"})
426
+
427
+ TRCell():New(oSecDetail, "C7_ITEM", "SC7", "Item", /*cPicture*/, 05, /*lPixel*/, /*bBlock*/, "LEFT")
428
+ TRCell():New(oSecDetail, "C7_PRODUTO","SC7", "Produto", /*cPicture*/, 15, /*lPixel*/, /*bBlock*/, "LEFT")
429
+ TRCell():New(oSecDetail, "C7_QUANT", "SC7", "Quantidade", "@E 999,999.99", 10, /*lPixel*/, /*bBlock*/, "RIGHT")
430
+ TRCell():New(oSecDetail, "C7_PRECO", "SC7", "Preco Unit", "@E 999,999.99", 12, /*lPixel*/, /*bBlock*/, "RIGHT")
431
+ TRCell():New(oSecDetail, "C7_TOTAL", "SC7", "Total", "@E 999,999.99", 12, /*lPixel*/, /*bBlock*/, "RIGHT")
432
+
433
+ // Totalizador no final da secao detail
434
+ TRFunction():New(oSecDetail:Cell("C7_TOTAL"), Nil, "SUM", Nil, "Total Pedido", "@E 999,999,999.99")
435
+
436
+ Return oReport
437
+ ```
438
+
439
+ ---
440
+
441
+ ## 12. Common Patterns
442
+
443
+ ### 12.1 Custom Cell with Code Block
444
+
445
+ Use a code block to format or compute cell values at print time:
446
+
447
+ ```advpl
448
+ // Celula com codigo customizado
449
+ TRCell():New(oSection, "SITUACAO", "QRY_REP", "Situacao", /*cPicture*/, 15, /*lPixel*/, ;
450
+ {|| IIf(QRY_REP->B1_MSBLQL == "1", "Bloqueado", "Ativo")}, "LEFT")
451
+ ```
452
+
453
+ ### 12.2 Landscape Configuration
454
+
455
+ ```advpl
456
+ oReport := TReport():New("zRelLand", "Relatorio Paisagem", Nil, ;
457
+ {|oReport| fPrint(oReport)})
458
+ oReport:SetLandscape()
459
+ oReport:oPage:SetPaperSize(9) // A4
460
+ ```
461
+
462
+ ### 12.3 Multiple Breaks and Totalizers
463
+
464
+ ```advpl
465
+ // Quebra por grupo
466
+ oBreak1 := TRBreak():New(oSection, oSection:Cell("B1_GRUPO"), ;
467
+ {|| "Grupo: " + AllTrim((oSection:Cell("B1_GRUPO")):cBuffer)}, .F.)
468
+
469
+ // Quebra por tipo dentro do grupo
470
+ oBreak2 := TRBreak():New(oSection, oSection:Cell("B1_TIPO"), ;
471
+ {|| "Tipo: " + AllTrim((oSection:Cell("B1_TIPO")):cBuffer)}, .F.)
472
+
473
+ // Totalizadores por quebra
474
+ TRFunction():New(oSection:Cell("B1_PRV1"), Nil, "SUM", oBreak1, "Total Grupo", "@E 999,999.99")
475
+ TRFunction():New(oSection:Cell("B1_PRV1"), Nil, "AVERAGE", oBreak1, "Media Grupo", "@E 999,999.99")
476
+ TRFunction():New(oSection:Cell("B1_COD"), Nil, "COUNT", oBreak2, "Qtd por Tipo", "@E 999,999")
477
+
478
+ // Totalizador geral (sem break, no final do relatorio)
479
+ TRFunction():New(oSection:Cell("B1_PRV1"), Nil, "SUM", Nil, "Total Geral", "@E 999,999,999.99", Nil, .F., .T.)
480
+ TRFunction():New(oSection:Cell("B1_COD"), Nil, "COUNT", Nil, "Total Registros", "@E 999,999", Nil, .F., .T.)
481
+ ```