Protheus MVC Generator
Overview
Generate complete Protheus MVC screen implementations following the TOTVS framework patterns. Protheus MVC separates business rules (Model), visual presentation (View), and navigation/actions (Controller/Browse) using the FWFormModel, FWFormView, and FWFormBrowse framework classes. This skill generates the three mandatory functions (ModelDef, ViewDef, MenuDef) plus the Browse function that composes them.
When to Use
Use this skill when:
- Creating a new CRUD screen for a Protheus table
- Building a master-detail form (e.g., invoice header + items)
- Generating MVC boilerplate from a table alias
- Adding validations, triggers, and entry point hooks to MVC screens
- Migrating legacy AxCadastro/Mbrowse screens to MVC
MVC Architecture in Protheus
Core Components
┌─────────────────────────────────────────┐
│ Main Function (e.g., MYMOD01) │
│ ├── MenuDef() → Menu actions │
│ └── FWFormBrowse → Browse grid │
│ ├── ModelDef() → Business rules │
│ │ ├── FWFormStruct → Schema │
│ │ ├── FWFormFieldsModel (Form) │
│ │ ├── FWFormGridModel (Grid) │
│ │ └── Validations / Triggers │
│ └── ViewDef() → Visual layout │
│ ├── FWFormStruct → Schema │
│ ├── Form panels │
│ └── Grid panels │
└─────────────────────────────────────────┘
User Function Responsibilities
| Function | Purpose | Returns |
|---|---|---|
ModelDef() |
Defines the data model: fields, validations, relationships, triggers | FWFormModel object |
ViewDef() |
Defines the visual layout: panels, grids, field arrangement | FWFormView object |
MenuDef() |
Defines available actions: Include, Edit, Delete, View, Copy | Array of menu items |
| Main Function | Creates FWFormBrowse and activates the screen |
— |
Bundled Reference Files
This skill uses progressive disclosure. The SKILL.md body covers the architecture, generation workflow, the checklist, and troubleshooting. Detailed code templates and API references are in the references/ directory — read them on demand based on the scenario:
| Reference File | When to Read | Content |
|---|---|---|
| references/mvc-code-templates.md | Generating MVC code — Single Entity (Modelo 1) or Master-Detail (Modelo 3) templates, event handlers, validation/commit patterns | Full code templates for both MVC patterns, ModelDef/ViewDef/MenuDef boilerplate, validation handlers, commit handlers |
| references/mvc-api-reference.md | Customizing FWFormStruct, adjusting View layout (boxes, tabs), configuring MenuDef actions, or adding custom menu buttons | FWFormStruct parameters, structure customization (RemoveField, SetProperty, FWBuildFeature), HBox/VBox/Folder layout, action codes table, custom actions |
Also refer to references/sonarqube-rules-reference.md for the complete SonarQube rules reference shared across skills.
Generation Workflow
Step 1: Gather Requirements
Determine the generation pattern from the user's request:
| Scenario | MVC Pattern | Key Characteristic |
|---|---|---|
| Simple CRUD (single table) | Single Entity (Modelo 1) | AddFields only, no grid |
| Master-detail (header + items) | Master-Detail (Modelo 3) | AddFields + AddGrid + SetRelation |
| Legacy migration (AxCadastro/Mbrowse) | Depends on current structure | Analyze existing code to choose pattern |
Read the appropriate reference files based on the pattern identified:
- Code generation → read references/mvc-code-templates.md
- Structure customization or layout → read references/mvc-api-reference.md
Step 2: Generate Code
Using the selected template from the reference files, adapt it to the user's specific requirements:
- Replace table aliases (
ZZ1,ZZ2,ZZ3) with actual table aliases - Replace function/model IDs (
MYMOD01,MYMOD01M) with actual routine names - Add/remove fields, validations, and triggers as needed
- Adjust View layout proportions and structure
Step 3: Validate Against Checklist
Run through the MVC Generation Checklist below to verify completeness.
MVC Generation Checklist
Model (ModelDef)
-
FWFormStruct(1, "XXX")loaded for each table - Fields removed/customized as needed
- Model created with
MPFormModel():New("UNIQUE_ID") -
AddFieldscalled for form sections -
AddGridcalled for grid sections (master-detail) - Relationship defined with
SetRelationfor grids - Model and sub-model descriptions set
-
SetPrimaryKey({})called - Validation handlers registered (
SetVldActive,SetCommit) - Grid line validation registered (
SetVldLine)
View (ViewDef)
- Model loaded with
FWLoadModel("ROUTINE_NAME") -
FWFormStruct(2, "XXX")loaded for each table -
FWFormView():New()created - Model set with
SetModel(oModel) -
AddFieldand/orAddGridcalled for each visual section - Layout boxes created (
CreateHorizontalBox,CreateVerticalBox) - Views assigned to boxes with
SetOwnerView - Screen proportions make sense (header vs. detail)
MenuDef
- Standard CRUD operations included (1-5)
- Custom actions added if needed
- Menu item names match
VIEWDEF.ROUTINE_NAME
General
-
#include "fwmvcdef.ch"present -
#include "totvs.ch"present - Browse function creates
FWFormBrowseand sets alias - Legends added to browse if the table has status fields
- Validation messages use
Help()function -
FWFormCommit(oModel)called in commit handler for standard persistence - Custom tables registered in SX2/SX3 data dictionary before use
SonarQube Compliance
-
FWFormCommit(oModel)is used for persistence — never override theFormCommitmethod directly; useFWModelEventto intercept commit behavior - No UI calls (
MsgAlert,MsgYesNo,Aviso,Help,Pergunte,ParamBox) inside commit/validation handlers that execute within a transaction - Error handling uses
Try-Catch, notErrorBlock - Logging via
FWLogMsg(), notConOut() - No
IIF()in expressions — useIf/Else/EndIf - Includes in lowercase (e.g.,
#include "totvs.ch") -
GetMV()/ExistBlock()results cached before loops (especially in grid validations) - No direct access to SX3 via
DbSelectArea— useFWFormStruct()orFWSX3Util()
Refer to references/sonarqube-rules-reference.md for the complete SonarQube rules reference.
Troubleshooting
- "Field not found in SX3": The field referenced in
FWFormStructmust exist in the data dictionary (SX3). RunCFGX023()or use SIGACFG to register missing fields. - ModelDef/ViewDef mismatch: Every field ID added to
FWFormModelmust have a corresponding entry inFWFormView. Verify that model and view structures reference the same field set. - Grid rows not saving: Ensure
FWFormCommit(oModel)is called in the commit block. For master-detail, the grid model must be added withAddGrid()and linked viaSetOwner(). - Browse shows no records: Verify
FWFormBrowse():SetAlias()points to the correct table alias and that the table is accessible from the current branch/company. - Validation not triggering: Field-level validators must be registered in SX3 (X3_VALID) or via
SetFieldAction()on the model. Check that the trigger field ID matches exactly.