Jump to content

Repo SharedConcepts

From Game in the Brain Wiki
Revision as of 16:33, 9 March 2026 by Ocjustin260223 (talk | contribs) ("Repo analysis: comfac-hrms and comfac-webshop (14 pages)")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Repo_SharedConcepts — Patterns Across Projects

This page documents patterns and concepts that appear across multiple repositories in the ComFac ecosystem.

Frappe Framework Patterns

DocType: The Core Abstraction

A DocType is Frappe's fundamental building block. It combines:

  • Database table — Schema definition
  • Form UI — Layout and fields
  • Permissions — Access control
  • Workflow — States and transitions
  • Controller — Python class for business logic

Key insight: Editing a DocType JSON changes the database schema. Editing the Python controller changes behavior.

DocType File Locations

``` app_name/ └── app_name/

   └── doctype/
       └── doctype_name/
           ├── doctype_name.json      # Schema (fields, permissions)
           ├── doctype_name.py        # Controller (validations, methods)
           ├── doctype_name_list.js   # List view customization
           ├── doctype_name_calendar.js  # Calendar view
           └── test_doctype_name.py   # Unit tests

```

hooks.py: The Wiring Diagram

Every Frappe app has a hooks.py that registers:

Hook Type Purpose Example
doc_events React to document changes Send email when Order submitted
scheduler_events Background jobs Daily report generation
override_doctype_class Replace core behavior Custom Employee validation
doctype_js Client-side scripts Form field visibility
website_generators Public pages Product pages

Request Flow in Frappe

``` HTTP Request

Frappe Router

Permission Check

Controller Method (whitelisted)

Document Load/Save (if DocType)

Database (MariaDB)

Response (JSON/HTML) ```

Common Database Operations

Operation Code Use When
Get single doc frappe.get_doc("Doctype", "name") You need the full object with methods
Query multiple frappe.get_all("Doctype", filters={}) Read-only list, respects permissions
Raw SQL frappe.db.sql("SELECT ...") Complex queries (avoid if possible)
Single value frappe.db.get_value("Doctype", "name", "field") Just need one field

Extension Patterns

The Override Pattern

Instead of modifying core code, create an override:

```python

  1. In your app: my_app/overrides/employee.py

from erpnext.setup.doctype.employee.employee import Employee

class CustomEmployee(Employee):

   def validate(self):
       super().validate()  # Call original
       # Add your custom validation
       if self.date_of_birth and self.date_of_birth > today():
           frappe.throw("Date of birth cannot be in the future")

```

Register in hooks.py: ```python override_doctype_class = {

   "Employee": "my_app.overrides.employee.CustomEmployee"

} ```

The Event Hook Pattern

Add behavior without changing the original class:

```python

  1. hooks.py

doc_events = {

   "Sales Order": {
       "on_submit": "my_app.hooks.send_notification_email"
   }

}

  1. my_app/hooks.py

def send_notification_email(doc, method=None):

   frappe.sendmail(
       recipients=[doc.contact_email],
       subject=f"Order {doc.name} confirmed!",
       message="..."
   )

```

Custom Fields Pattern

Add fields without forking the DocType:

Method Best For Persistence
Desk UI (Customize Form) Quick additions Database only
Fixtures Version controlled Exportable JSON
Patch Data migration One-time setup

Python Patterns

Imports You Will See Everywhere

```python import frappe # The framework from frappe import _ # Translation function from frappe.utils import today, getdate, flt, cint # Utilities ```

The frappe.throw Pattern

```python if not self.customer:

   frappe.throw(_("Customer is required"), title=_("Missing Field"))

```

Always use _("...") for translatable strings.

Naming Conventions

Element Convention Example
DocType names Title Case "Leave Application"
Field names snake_case "employee_name"
Python files snake_case "leave_application.py"
Class names PascalCase class LeaveApplication

Git-Mediawiki Workflow

How This Wiki Works

  1. Content is written as .wiki files (MediaWiki wikitext)
  2. Files are stored in a git repository (wiki-gi7b-org/)
  3. git push syncs to live MediaWiki at wiki.gi7b.org

File Naming

Wiki Page File Path
PageName PageName.wiki
Namespace:Page Namespace/Page.wiki
Page/Subpage Page/Subpage.wiki

Commit Convention

```bash

  1. After completing a repo analysis

git add Repo/AppName/ git commit -m "Repo:AppName — full structural analysis (6 pages)" git push

  1. After updating index

git add Repo_Index.wiki Repo_SharedConcepts.wiki git commit -m "Repo:Index + SharedConcepts — updated after AppName analysis" git push ```

Reading Dependencies

requirements.txt / pyproject.toml

When you see a dependency, ask:

  1. Is it a Frappe app? (frappe, erpnext, payments)
    • These extend the framework
  2. Is it a Python library? (requests, pandas)
    • These provide specific functionality
  3. Is it for development? (pytest, black)
    • These are dev-only, not runtime

package.json (Node.js)

  • Dependencies — Required at runtime
  • devDependencies — Build/test only
  • Look for frappe-ui — Frappe's Vue component library

Development Workflow

Typical Edit Cycle

  1. Understand — Read relevant wiki page
  2. Locate — Find the file to edit (use DirectoryMap)
  3. Edit — Make minimal changes
  4. Test — Run bench start, check browser
  5. Migrate — If DocType changed: bench migrate
  6. Build — If JS/CSS changed: bench build
  7. Commit — Git commit with clear message

Common bench Commands

Command When to Use
bench start Start development server
bench migrate Sync DocTypes, run patches
bench build Compile frontend assets
bench --site [site] install-app [app] Install app on site
bench --site [site] console Interactive Python shell
bench --site [site] mariadb Direct database access

Quick Decision Guide

"I want to add a field to a form"

  1. Is it a core field? → Edit DocType JSON
  2. Is it custom/temporary? → Use Customize Form (Desk UI)
  3. Needs to be version controlled? → Use fixtures

"I want to change validation logic"

  1. For standard DocTypes → Override class in overrides/
  2. For custom DocTypes → Edit the DocType's .py controller
  3. For cross-cutting concerns → Use doc_events hook

"I want to run code on a schedule"

  1. Add to scheduler_events in hooks.py
  2. Choose frequency: all, hourly, daily, weekly, monthly

"I want to add a web page"

  1. Public page → Create in www/
  2. Auto-generated per record → Use website_generators
  3. API endpoint → Use @frappe.whitelist()

Resources