AgentSkillsCN

frappe-development

针对Frappe框架应用的设计模式与决策方法,包括DocType、控制器、客户端与服务器脚本、工作流,以及ERPNext风格的自定义开发。

SKILL.md
--- frontmatter
name: frappe-development
description: Patterns and decision-making for Frappe Framework apps including DocTypes, controllers, client and server scripts, workflows, and ERPNext-style customisation.
allowed-tools: Read, Write, Edit, Glob, Grep

Frappe Development Patterns

Opinionated guidance for building maintainable Frappe or ERPNext apps, with a focus on e-health systems.


How to Use This Skill

Use this whenever:

  • The project is built on Frappe Framework or ERPNext.
  • The user mentions DocTypes, Bench, sites or apps, or ERPNext Healthcare.
  • You are modelling business entities as DocTypes instead of ORM models.

Combine this with:

  • python-patterns for general Python decisions.
  • database-design for physical database concerns such as indexes and performance.
  • healthcare-compliance when PHI or clinical workflows are involved.

1. Frappe Architecture in 60 Seconds

  • Sites: contain databases and configuration for each tenant.
  • Apps: Python packages that define DocTypes, pages, reports, and logic.
  • DocTypes: metadata that defines database tables, forms, permissions, and controllers.
  • Desk: the authenticated back-office UI, with List, Form, Report, Dashboard, and Workspace.
  • Website: public pages, web forms, and portals, usually Jinja-based.
  • Bench: CLI that manages sites, apps, migrations, and workers.

Design principle: DocType-first – model your domain as DocTypes, then attach logic via controllers and hooks.


2. DocType-Based Data Modelling

When modelling an entity such as patient, appointment, or encounter:

  • Use Link fields for relations instead of manual foreign keys.
  • Prefer child tables for repeating structures such as vitals, diagnoses, or procedures.
  • Use Select with controlled vocabularies for status, priority, and triage levels.
  • Avoid large free-text fields when structured data is needed for analytics.
  • Mark sensitive DocTypes to track changes or views for auditability.

For healthcare:

  • Keep core DocTypes small and focused, for example Patient versus Encounter versus MedicalRecord.
  • Avoid mixing administrative and clinical data in the same DocType.

3. Controllers, Hooks, and Services

Each DocType normally has a Python controller at:

  • doctype/<doctype>/<doctype>.py

Guidelines:

  • Put validation and invariants in controller methods such as validate, before_save, and on_submit.
  • Keep controllers thin by delegating to service modules, for example my_app/api/encounter.py.
  • Register domain events in hooks.py using doc_events, scheduler_events, and whitelisted API methods.

Example decisions:

  • Use DocType controller methods for lifecycle-related logic such as enforcing required links or status transitions.
  • Use service modules for cross-DocType workflows such as encounter to orders to billing.
  • Avoid business logic in random utility modules or client scripts.

4. Client Scripts versus Server Scripts

Client Scripts, written in JavaScript and executed in Desk:

  • Use for small UX tweaks, dynamic field behaviour, and validation that improves user feedback.
  • Never rely on them for security or permission enforcement.

Server Scripts, written in Python and executed on the backend:

  • Use cautiously for on-the-fly customisation in production when editing the app is not possible.
  • Prefer first-class app code such as controllers, services, and tests for long-term maintainability.

Rules:

  • Any rule that protects data integrity or implements compliance must exist in server-side app code.
  • Treat Client Scripts as progressive enhancement, not the source of truth.

5. Workflows, Permissions, and Healthcare Roles

Frappe Workflows:

  • Use workflow states and transitions for long-running processes, for example the lab test lifecycle.
  • Map each state to allowed actions for specific roles, for example technician can submit result, doctor can verify.

Permission system:

  • Start with the DocType permissions matrix per role and per action.
  • Refine with User Permissions and Sharing for record-level control.
  • Avoid duplicating permission checks in every function; centralise where possible.

Healthcare-specific hints:

  • Define clear roles such as Receptionist, Nurse, Physician, Lab Tech, Billing, Administrator.
  • Ensure that views for PHI-heavy DocTypes respect least-privilege principles.
  • Enable standard audit fields and change tracking on all clinical DocTypes.

6. Patterns for E-Health Apps

When building Frappe-based healthcare systems:

  • Reuse ERPNext Healthcare DocTypes when licensing and scope allow; extend via Custom Fields and Custom Scripts.
  • For greenfield apps, start from core DocTypes such as Patient, Encounter, Appointment, Prescription, LabTest, Invoice.
  • Keep integration boundaries clean: design FHIR-facing resources that map one-to-one or many-to-one with DocTypes.
  • Use background jobs for heavy tasks such as bulk data migration, document generation, and external synchronisation.
  • Write automated tests for critical workflows including registration, encounter, prescription, and billing.

Always design with clinical safety, traceability, and operator ergonomics in mind, not only developer convenience.


7. ERPNext Healthcare Module Reference

When building on top of the existing ERPNext Healthcare module (rather than greenfield), these are the standard DocTypes you inherit and extend.

Core Healthcare DocTypes (ERPNext Healthcare)

DocTypePurposeKey Fields
PatientMaster patient recordpatient_name, sex, dob, blood_group, mobile, email, uid (national ID), status, territory
Patient AppointmentScheduled visitpatient, practitioner, appointment_type, appointment_date, appointment_time, department, status, duration
Patient EncounterClinical visit notepatient, practitioner, encounter_date, symptoms (child table), diagnosis (child table), drug_prescription (child table), lab_test_prescription (child table)
Vital SignsStructured vitalspatient, signs_date, temperature, pulse, respiratory_rate, bp_systolic, bp_diastolic, bmi, height, weight, oxygen_saturation
Lab TestDiagnostic testpatient, practitioner, lab_test_name, template, result_date, normal_test_items (child table), descriptive_test_items (child table), status
Lab Test TemplateTest definitionlab_test_name, lab_test_group, lab_test_template_type, normal_test_templates (child table), descriptive_test_templates (child table)
Clinical ProcedureProcedurespatient, practitioner, procedure_template, start_date, status, consume_stock
Clinical Procedure TemplateProcedure definitiontemplate, medical_department, description, rate
Prescription DosageDosage presetsdosage, dosage_strength (child table)
Healthcare PractitionerClinician recordpractitioner_name, department, designation, op_consulting_charge, employee (link)
Healthcare Service UnitFacility rooms/bedsservice_unit_type, warehouse, company, is_group, parent_healthcare_service_unit
Medical Code StandardCoding systemmedical_code_standard (ICD-10, SNOMED, LOINC)
Medical CodeIndividual codemedical_code, code, description
Therapy TypeRehab/therapytherapy_type, default_duration, rate, exercises (child table)
Therapy PlanTreatment planpatient, start_date, therapy_plan_details (child table)
Inpatient RecordAdmission recordpatient, admitted_datetime, discharge_datetime, primary_practitioner, admission_service_unit

Extending Healthcare DocTypes with Custom Fields

When you need to add fields to standard Healthcare DocTypes without forking the module:

  • Use Custom Fields via Setup > Customize > Custom Field or programmatically in your app's fixtures.
  • Use fixtures in hooks.py to export and version-control Custom Fields:
python
# hooks.py
fixtures = [
    {
        "dt": "Custom Field",
        "filters": [["module", "=", "My EHealth"]]
    }
]
  • Use Custom Scripts (Client Script DocType) for UI-side behaviour on standard forms.
  • Use doc_events in hooks.py to attach server logic to standard Healthcare DocTypes without modifying their controllers:
python
doc_events = {
    "Patient Encounter": {
        "validate": "my_ehealth.overrides.encounter.custom_validate",
        "on_submit": "my_ehealth.overrides.encounter.on_submit"
    }
}

Naming Conventions in Healthcare

DocTypeDefault NamingOverride
PatientPAT-.#####Naming Series or field-based
Patient AppointmentHLC-APP-.YYYY.-.#####Naming Series
Patient EncounterHLC-ENC-.YYYY.-.#####Naming Series
Lab TestHLC-LAB-.YYYY.-.#####Naming Series
Vital SignsHLC-VIT-.YYYY.-.#####Naming Series

Common Extension Patterns

  • Add insurance fields to Patient via Custom Fields (insurance_provider, policy_number, expiry_date).
  • Add triage_level Select field to Patient Encounter for emergency department workflows.
  • Create custom child tables for structured data not covered by standard DocTypes (e.g., Allergy child table on Patient).
  • Override print formats for prescriptions, lab reports, and discharge summaries using custom Jinja templates.
  • Add Workflow states to Patient Encounter for multi-step approval (Draft → In Progress → Completed → Billed).