make charts non-standard

This commit is contained in:
meichthys 2025-09-07 03:46:02 +00:00
commit ec21b71152
132 changed files with 4313 additions and 0 deletions

21
.editorconfig Normal file
View File

@ -0,0 +1,21 @@
# Root editor config file
root = true
# Common settings
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
# python, js indentation settings
[{*.py,*.js,*.vue,*.css,*.scss,*.html}]
indent_style = tab
indent_size = 4
max_line_length = 99
# JSON files - mostly doctype schema files
[{*.json}]
insert_final_newline = false
indent_style = space
indent_size = 2

124
.eslintrc Normal file
View File

@ -0,0 +1,124 @@
{
"env": {
"browser": true,
"node": true,
"es2022": true
},
"parserOptions": {
"sourceType": "module"
},
"extends": "eslint:recommended",
"rules": {
"indent": "off",
"brace-style": "off",
"no-mixed-spaces-and-tabs": "off",
"no-useless-escape": "off",
"space-unary-ops": ["error", { "words": true }],
"linebreak-style": "off",
"quotes": ["off"],
"semi": "off",
"camelcase": "off",
"no-unused-vars": "off",
"no-console": ["warn"],
"no-extra-boolean-cast": ["off"],
"no-control-regex": ["off"],
},
"root": true,
"globals": {
"frappe": true,
"Vue": true,
"SetVueGlobals": true,
"__": true,
"repl": true,
"Class": true,
"locals": true,
"cint": true,
"cstr": true,
"cur_frm": true,
"cur_dialog": true,
"cur_page": true,
"cur_list": true,
"cur_tree": true,
"msg_dialog": true,
"is_null": true,
"in_list": true,
"has_common": true,
"posthog": true,
"has_words": true,
"validate_email": true,
"open_web_template_values_editor": true,
"validate_name": true,
"validate_phone": true,
"validate_url": true,
"get_number_format": true,
"format_number": true,
"format_currency": true,
"comment_when": true,
"open_url_post": true,
"toTitle": true,
"lstrip": true,
"rstrip": true,
"strip": true,
"strip_html": true,
"replace_all": true,
"flt": true,
"precision": true,
"CREATE": true,
"AMEND": true,
"CANCEL": true,
"copy_dict": true,
"get_number_format_info": true,
"strip_number_groups": true,
"print_table": true,
"Layout": true,
"web_form_settings": true,
"$c": true,
"$a": true,
"$i": true,
"$bg": true,
"$y": true,
"$c_obj": true,
"refresh_many": true,
"refresh_field": true,
"toggle_field": true,
"get_field_obj": true,
"get_query_params": true,
"unhide_field": true,
"hide_field": true,
"set_field_options": true,
"getCookie": true,
"getCookies": true,
"get_url_arg": true,
"md5": true,
"$": true,
"jQuery": true,
"moment": true,
"hljs": true,
"Awesomplete": true,
"Sortable": true,
"Showdown": true,
"Taggle": true,
"Gantt": true,
"Slick": true,
"Webcam": true,
"PhotoSwipe": true,
"PhotoSwipeUI_Default": true,
"io": true,
"JsBarcode": true,
"L": true,
"Chart": true,
"DataTable": true,
"Cypress": true,
"cy": true,
"it": true,
"describe": true,
"expect": true,
"context": true,
"before": true,
"beforeEach": true,
"after": true,
"qz": true,
"localforage": true,
"extend_cscript": true
}
}

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
.DS_Store
*.pyc
*.egg-info
*.swp
tags
node_modules
__pycache__
/.continue
/.vscode

69
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,69 @@
exclude: 'node_modules|.git'
default_stages: [pre-commit]
fail_fast: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
files: "church.*"
exclude: ".*json$|.*txt$|.*csv|.*md|.*svg"
- id: check-merge-conflict
- id: check-ast
- id: check-json
- id: check-toml
- id: check-yaml
- id: debug-statements
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.1
hooks:
- id: ruff
name: "Run ruff import sorter"
args: ["--select=I", "--fix"]
- id: ruff
name: "Run ruff linter"
- id: ruff-format
name: "Run ruff formatter"
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
hooks:
- id: prettier
types_or: [javascript, vue, scss]
# Ignore any files that might contain jinja / bundles
exclude: |
(?x)^(
church/public/dist/.*|
.*node_modules.*|
.*boilerplate.*|
church/templates/includes/.*|
church/public/js/lib/.*
)$
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.44.0
hooks:
- id: eslint
types_or: [javascript]
args: ['--quiet']
# Ignore any files that might contain jinja / bundles
exclude: |
(?x)^(
church/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*|
church/templates/includes/.*|
church/public/js/lib/.*
)$
ci:
autoupdate_schedule: weekly
skip: []
submodules: false

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"python.autoComplete.extraPaths": [
"${workspaceFolder}/../frappe"
],
}

91
README.md Normal file
View File

@ -0,0 +1,91 @@
> [!WARNING]
> This app is not ready for production. Large changes should be expected until a 1.0.0 version is released.
### ⛪ Church
A fully open-source church management app built on the [Frappe Framework](https://frappe.io/framework).
![onboarding screenshot](screenshots/Onboarding.png "Onboarding")
### ✨ Features
The following features have been implemented in this app (see the [🗺️ Roadmap](#🗺️-roadmap) below for future plans):
- `Church Person` tracking
- Define and track `Church Person Relation`ships
- Define `Church Person Relation Type`s
- Define & track `Church Person Role`s (i.e. board member, deacon, pastor, etc)
- `Church Family` tracking
- Track head of household (Set on `Church Person` record)
- Church module desk workspace with guided setup steps
- Event tracking
- Event types, details, basic attendance tracking & reporting
- Collection/donation tracking
- Donation entry with collection totals & split check support
- Bank reconciliation report
### 📥 Installation
To use this app, you must have a working Frappe environment. The easiest way to get a working Frappe environment is to use [Frappe Cloud](https://frappe.io/cloud). For a few dollars per month you can run an instance in the cloud. To self-host an instance on a home pc or server, you can use [frappe-manager](https://github.com/rtcamp/frappe-manager) to quickly setup a local frappe instance. Making a local instance of frappe accessible from outside of your network is currentlyl out of the scope of this project, but with some persistence and some technical expertise, it shouldn't be too difficult.
You can install this app using the [bench](https://github.com/frappe/bench) CLI:
```bash
cd $PATH_TO_YOUR_BENCH
bench get-app $URL_OF_THIS_REPO --branch develop
bench install-app church
```
After the above installation and a WebUI reload, you should see the `Church` app installed when you view `Help > About` in the [Frappe Desk](https://docs.frappe.io/framework/user/en/desk).
### 🗺️ Roadmap
Hopefully this roadmap will help avoid too much scope creep and provide a sense of where this project is headed. The items below are listed in order of current priority.
- Collection Improvements
- Make collections submittable(?)
- Add Onboarding Tours
- Add 'Tutorial' button to each doctype form
- Fund Tracking
- Update fund balance after collection submission
- Add standard church website pages:
- About Us
- Home/Welcome
- Missions
- Beliefs/Statement of Faith
- Calendar
- Contact Us
- Add portal for `Church Person`s
- Show tracked giving
- Show tracked attendance
- Allow updating attendance status(?)
- Ministry tracking
- Auto add spouse to `Church Person`s relationships
- Event templating/recurrence
- Templating via `Church Event Type` default values table(?)
### 🤝 Contributing
Contributions are very welcome! If you plan any large contributions, please let me know first so we can coordinate and make the chances of a merged pull-request more likely.
- Doctype Naming: I've generally been using a single fieldname for the doctype names when the records in the doctype have low chance of clashing. If there is a higher chance of clashing, I've been using multiple fields in the name along with a `{####}` auto increment. The number of digits in the auto-increment are just sane values that should never be exceeded. I then specify the Title Field in the View Settings, and check the `Show Title in LInk Fields` option. This mostly hides the autonumber name from the user and lets the user only see the not-so-confusing name specified in the `Title Field` (sometimes I create a custom field to concatenate values - since the `Title Field` cannot take multiple fields at once afaik.)
#### Pre-Commit
This app uses `pre-commit` for code formatting and linting. Please [install pre-commit](https://pre-commit.com/#installation) and enable it for this repository:
```bash
cd apps/church
pre-commit install
```
Pre-commit is configured to use the following tools for checking and formatting your code:
- ruff
- eslint
- prettier
- pyupgrade
### 🔑 License
MIT

1
church/__init__.py Normal file
View File

@ -0,0 +1 @@
__version__ = "0.0.1"

View File

View File

@ -0,0 +1,35 @@
{
"based_on": "creation",
"chart_name": "Church Collections",
"chart_type": "Sum",
"color": "#138a25",
"creation": "2025-09-06 21:24:53.622970",
"currency": "USD",
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Church Donation",
"dynamic_filters_json": "[]",
"filters_json": "[]",
"group_by_type": "Count",
"idx": 0,
"is_public": 0,
"is_standard": 1,
"last_synced_on": "2025-09-06 23:07:30.356897",
"modified": "2025-09-06 23:10:58.140613",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Collections",
"number_of_groups": 0,
"owner": "Administrator",
"parent_document_type": "Church Collection",
"roles": [],
"show_values_over_chart": 1,
"source": "",
"time_interval": "Weekly",
"timeseries": 1,
"timespan": "Last Year",
"type": "Bar",
"use_report_chart": 0,
"value_based_on": "amount",
"y_axis": []
}

View File

@ -0,0 +1,35 @@
{
"based_on": "creation",
"chart_name": "Church Members",
"chart_type": "Count",
"color": "#29CD42",
"creation": "2025-09-06 21:24:53.605400",
"currency": "",
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Church Person",
"dynamic_filters_json": "[]",
"filters_json": "[[\"Church Person\",\"is_member\",\"=\",1,false]]",
"group_by_type": "Count",
"idx": 0,
"is_public": 1,
"is_standard": 1,
"last_synced_on": "2025-08-28 01:07:15.891255",
"modified": "2025-09-06 23:11:58.440465",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Members",
"number_of_groups": 0,
"owner": "Administrator",
"parent_document_type": "",
"roles": [],
"show_values_over_chart": 0,
"source": "",
"time_interval": "Monthly",
"timeseries": 1,
"timespan": "Last Year",
"type": "Line",
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}

View File

@ -0,0 +1,35 @@
{
"based_on": "creation",
"chart_name": "Church Persons",
"chart_type": "Count",
"color": "#4463F0",
"creation": "2025-08-22 01:19:16.929858",
"currency": "",
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Church Person",
"dynamic_filters_json": "[]",
"filters_json": "[]",
"group_by_type": "Count",
"idx": 0,
"is_public": 1,
"is_standard": 1,
"last_synced_on": "2025-08-22 01:53:58.979008",
"modified": "2025-08-22 01:54:25.866369",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Persons",
"number_of_groups": 0,
"owner": "Administrator",
"parent_document_type": "",
"roles": [],
"show_values_over_chart": 0,
"source": "",
"time_interval": "Weekly",
"timeseries": 1,
"timespan": "Last Year",
"type": "Line",
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}

View File

@ -0,0 +1,35 @@
{
"based_on": "membership_date",
"chart_name": "New Church Members",
"chart_type": "Count",
"color": "#29CD42",
"creation": "2025-08-22 01:15:53.489892",
"currency": "",
"docstatus": 0,
"doctype": "Dashboard Chart",
"document_type": "Church Person",
"dynamic_filters_json": "[]",
"filters_json": "[[\"Church Person\",\"is_member\",\"=\",1,false]]",
"group_by_type": "Count",
"idx": 0,
"is_public": 1,
"is_standard": 1,
"last_synced_on": "2025-08-22 23:54:40.605920",
"modified": "2025-08-22 23:54:59.315764",
"modified_by": "Administrator",
"module": "Church",
"name": "New Church Members",
"number_of_groups": 0,
"owner": "Administrator",
"parent_document_type": "",
"roles": [],
"show_values_over_chart": 0,
"source": "",
"time_interval": "Monthly",
"timeseries": 1,
"timespan": "Last Year",
"type": "Bar",
"use_report_chart": 0,
"value_based_on": "",
"y_axis": []
}

View File

View File

@ -0,0 +1,38 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
// Add button to goto `Church Collection Bank Reconciliation` report
frappe.ui.form.on("Church Collection", {
refresh(frm) {
// Add 'Bank Reconciliation Report' button
frm.add_custom_button(__('Bank Reconciliation Report'), function () {
if (frm.is_new()) {
frappe.show_alert("Save the Collection first!")
return;
};
frm.refresh_field('date');
frappe.set_route("query-report", "Church Collection Bank Reconciliation", {
"parent_filter": frm.doc.date
});
frappe.query_report.load();
});
},
});
// Keep Collection `total_amount` up to date when amounts are changed/added
frappe.ui.form.on("Church Donation", "amount", update_collection_total);
// Keep Collection `total_amount` up to date when rows are removed from grid
frappe.ui.form.on("Church Donation", {
donations_remove: update_collection_total
});
// Update Collection `total_amount` with sum of donation amounts
function update_collection_total(frm) {
var total = 0;
frm.doc.donations.forEach(function (donation) {
total += donation.amount || 0;
});
frm.set_value("total_amount", total);
}

View File

@ -0,0 +1,88 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{date}",
"creation": "2025-09-02 00:47:02.825073",
"description": "A specific collection of `Church Donation`s that are generally from `Church Person`s and associated with a specific `Church Event`s.",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"date",
"event",
"column_break_ijpy",
"total_amount",
"section_break_izta",
"donations"
],
"fields": [
{
"description": "The `Church Event` associated with this collection.",
"fieldname": "event",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Event",
"options": "Church Event"
},
{
"default": "now",
"fieldname": "date",
"fieldtype": "Datetime",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Date",
"reqd": 1
},
{
"fieldname": "section_break_izta",
"fieldtype": "Section Break"
},
{
"description": "For 'anonymous' donations, enter the total amount and leave `Person` and `Check #` blank. To apply a single check to multiple funds, create another donation record with the same check number. The `Bank Reconciliation Report` will combine the separate donations together for easier reconciliation with bank statements.",
"fieldname": "donations",
"fieldtype": "Table",
"label": "Donations",
"options": "Church Donation",
"reqd": 1
},
{
"fieldname": "column_break_ijpy",
"fieldtype": "Column Break"
},
{
"fieldname": "total_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Total Amount",
"read_only": 1
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-09-04 23:45:50.511534",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Collection",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchCollection(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchCollection(FrappeTestCase):
pass

View File

@ -0,0 +1,89 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2025-09-02 00:57:15.831405",
"description": "A donation made to the church (Generally by `Church Person`s).",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"amount",
"payment_type",
"check_number",
"fund",
"person",
"notes"
],
"fields": [
{
"allow_in_quick_entry": 1,
"default": "Check",
"fieldname": "payment_type",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Payment Type",
"options": "Church Payment Type",
"reqd": 1
},
{
"allow_in_quick_entry": 1,
"default": "General",
"fieldname": "fund",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Fund",
"options": "Church Fund",
"reqd": 1
},
{
"allow_in_quick_entry": 1,
"description": "Leave blank for 'anonymous' donations.",
"fieldname": "person",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Person",
"mandatory_depends_on": "eval:doc.payment_type==\"Check\"",
"options": "Church Person"
},
{
"fieldname": "notes",
"fieldtype": "Data",
"label": "Notes"
},
{
"depends_on": "eval:doc.payment_type==\"Check\";",
"fieldname": "check_number",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Check #",
"mandatory_depends_on": "eval:doc.payment_type==\"Check\";",
"read_only_depends_on": "eval:doc.payment_type!=\"Check\""
},
{
"allow_in_quick_entry": 1,
"fieldname": "amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"reqd": 1
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2025-09-04 23:47:17.659104",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Donation",
"owner": "Administrator",
"permissions": [],
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchDonation(Document):
pass

View File

@ -0,0 +1,17 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
frappe.ui.form.on('Church Event', {
before_save(frm) {
// Update Attendance Total when saving
// Only include the number of 'Confirmed' and 'Assumed' attendees
var total_attendance = 0;
frm.doc.attendance.forEach(function (row) {
if (["Confirmed", "Assumed"].includes(row.attendance_type)) {
total_attendance += 1;
}
});
frm.set_value('attendance_total', total_attendance);
}
});

View File

@ -0,0 +1,146 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{start_date} ({type}) - {event_name}",
"creation": "2025-08-31 23:40:34.324092",
"description": "Any kind of church gathering. This includes regular services as well as one-off events.",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"event_name",
"all_day",
"start_date",
"start_time",
"end_date",
"end_time",
"column_break_bkje",
"attendance_total",
"type",
"address",
"description",
"section_break_dlpa",
"attendance"
],
"fields": [
{
"allow_in_quick_entry": 1,
"default": "0",
"fieldname": "all_day",
"fieldtype": "Check",
"label": "All-Day ?"
},
{
"fieldname": "column_break_bkje",
"fieldtype": "Column Break"
},
{
"allow_in_quick_entry": 1,
"fieldname": "event_name",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Name",
"reqd": 1
},
{
"allow_in_quick_entry": 1,
"fieldname": "type",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Type",
"options": "Church Event Type",
"reqd": 1
},
{
"fieldname": "address",
"fieldtype": "Link",
"label": "Address",
"options": "Address"
},
{
"fieldname": "description",
"fieldtype": "Small Text",
"label": "Description"
},
{
"allow_in_quick_entry": 1,
"default": "now",
"fieldname": "start_date",
"fieldtype": "Date",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Start Date",
"reqd": 1
},
{
"allow_in_quick_entry": 1,
"depends_on": "eval:!doc.all_day",
"fieldname": "start_time",
"fieldtype": "Time",
"label": "Start Time",
"mandatory_depends_on": "eval:!doc.all_day"
},
{
"allow_in_quick_entry": 1,
"fieldname": "end_date",
"fieldtype": "Date",
"label": "End Date"
},
{
"allow_in_quick_entry": 1,
"depends_on": "eval:!doc.all_day",
"fieldname": "end_time",
"fieldtype": "Time",
"label": "End Time"
},
{
"fieldname": "section_break_dlpa",
"fieldtype": "Section Break"
},
{
"description": "'Church Person's who attended this event.",
"fieldname": "attendance",
"fieldtype": "Table",
"label": "Attendance",
"options": "Church Event Attendance"
},
{
"description": "Includes `Confirmed`, `Assumed` attendance.",
"fieldname": "attendance_total",
"fieldtype": "Int",
"label": "Attendance Total",
"read_only": 1
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-09-04 23:44:35.780823",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Event",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1,
"track_views": 1
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchEvent(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchEvent(FrappeTestCase):
pass

View File

@ -0,0 +1,49 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2025-09-01 00:29:32.386192",
"description": "'Church Person's who attended a 'Church Event'",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"person",
"attendance_type"
],
"fields": [
{
"allow_in_quick_entry": 1,
"fieldname": "person",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Person",
"options": "Church Person",
"reqd": 1
},
{
"default": "Confirmed",
"fieldname": "attendance_type",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Attendance Type",
"options": "Church Event Attendance Type",
"reqd": 1
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2025-09-04 23:59:03.690831",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Event Attendance",
"owner": "Administrator",
"permissions": [],
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchEventAttendance(Document):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Church Event Attendance Type", {
// refresh(frm) {
// },
// });

View File

@ -0,0 +1,58 @@
{
"actions": [],
"autoname": "format:{type}",
"creation": "2025-09-01 00:33:34.102307",
"description": "Type of `Church Event Attendance` (i.e. Confirmed, Assumed, Unknown, Absent etc.)",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"type",
"description"
],
"fields": [
{
"allow_in_quick_entry": 1,
"fieldname": "type",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Type of Attendance",
"reqd": 1,
"unique": 1
},
{
"allow_in_quick_entry": 1,
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Description"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-09-05 00:00:05.160645",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Event Attendance Type",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchEventAttendanceType(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchEventAttendanceType(FrappeTestCase):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Church Event Type", {
// refresh(frm) {
// },
// });

View File

@ -0,0 +1,59 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{type}",
"creation": "2025-08-31 23:41:14.325452",
"description": "Types of church events (i.e Sunday services, community events, private events, etc)",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"type",
"description"
],
"fields": [
{
"allow_in_quick_entry": 1,
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Description"
},
{
"allow_in_quick_entry": 1,
"fieldname": "type",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Type of Event",
"reqd": 1,
"unique": 1
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-09-04 23:59:26.837133",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Event Type",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchEventType(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchEventType(FrappeTestCase):
pass

View File

@ -0,0 +1,6 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
frappe.ui.form.on("Church Family", {
});

View File

@ -0,0 +1,89 @@
{
"actions": [],
"allow_import": 1,
"autoname": "format:{family_name} - {####}",
"creation": "2025-08-22 00:15:20.425153",
"description": "A family of people ('Church Person's) that are considered to be part of the same household. One 'Church Person' can be set to be the Head of Household for a family. ",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"family_name",
"head_of_household",
"column_break_pmch",
"home_address",
"photo"
],
"fields": [
{
"fieldname": "column_break_pmch",
"fieldtype": "Column Break"
},
{
"fieldname": "home_address",
"fieldtype": "Link",
"label": "Home Address",
"options": "Address"
},
{
"allow_in_quick_entry": 1,
"fieldname": "family_name",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Name",
"reqd": 1,
"unique": 1
},
{
"allow_in_quick_entry": 1,
"fieldname": "head_of_household",
"fieldtype": "Link",
"in_standard_filter": 1,
"is_virtual": 1,
"label": "Head of Household",
"options": "Church Person"
},
{
"fieldname": "photo",
"fieldtype": "Attach Image",
"label": "Photo"
}
],
"grid_page_length": 50,
"image_field": "photo",
"index_web_pages_for_search": 1,
"links": [
{
"link_doctype": "Church Person",
"link_fieldname": "family"
}
],
"modified": "2025-09-04 23:59:50.816837",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Family",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"show_title_field_in_link": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"title_field": "family_name",
"track_changes": 1
}

View File

@ -0,0 +1,23 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class ChurchFamily(Document):
pass
@property
def head_of_household(self):
# To ensure we don't have multiple people returned here,
# After saving a 'Church Person', we uncheck `head_of_household`
# for any other 'Church Person's that are part of the same family
doc_dict = frappe.get_list(
doctype="Church Person",
filters=[["family", "=", self.name], ["is_head_of_household", "=", True]],
)
if not doc_dict:
return
doc_dict[0]["doctype"] = "Church Person"
return frappe.get_doc(doc_dict[0]).name

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchFamily(FrappeTestCase):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Church Fund", {
// refresh(frm) {
// },
// });

View File

@ -0,0 +1,76 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{fund}",
"creation": "2025-09-02 01:11:30.383380",
"description": "Financial funds of the church (i.e. General, Trust, etc).",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"fund",
"description",
"column_break_ojjy",
"start_date",
"end_date"
],
"fields": [
{
"fieldname": "fund",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Name",
"reqd": 1
},
{
"allow_in_quick_entry": 1,
"fieldname": "description",
"fieldtype": "Small Text",
"label": "Description"
},
{
"fieldname": "column_break_ojjy",
"fieldtype": "Column Break"
},
{
"allow_in_quick_entry": 1,
"fieldname": "start_date",
"fieldtype": "Date",
"label": "Start Date"
},
{
"allow_in_quick_entry": 1,
"fieldname": "end_date",
"fieldtype": "Date",
"label": "End Date"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-09-04 23:56:21.592680",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Fund",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchFund(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchFund(FrappeTestCase):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Church Member Status Type", {
// refresh(frm) {
// },
// });

View File

@ -0,0 +1,66 @@
{
"actions": [],
"autoname": "field:status",
"creation": "2025-08-25 22:44:34.512827",
"description": "Status type of the `Church Member` as defined by the church.",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"status",
"color",
"description"
],
"fields": [
{
"allow_in_quick_entry": 1,
"fieldname": "status",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Status",
"reqd": 1,
"unique": 1
},
{
"allow_in_quick_entry": 1,
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Description"
},
{
"fieldname": "color",
"fieldtype": "Color",
"in_list_view": 1,
"label": "Color"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-09-05 00:01:44.911284",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Member Status Type",
"naming_rule": "By fieldname",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"title_field": "status"
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchMemberStatusType(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchMemberStatusType(FrappeTestCase):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Church Payment Type", {
// refresh(frm) {
// },
// });

View File

@ -0,0 +1,58 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{type}",
"creation": "2025-09-02 01:03:03.764617",
"description": "The type of payment used for `Church Donation`s (i.e. Cash, Check, etc)",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"type",
"description"
],
"fields": [
{
"allow_in_quick_entry": 1,
"fieldname": "type",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Type of Payment",
"reqd": 1
},
{
"allow_in_quick_entry": 1,
"fieldname": "description",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Description"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-09-04 23:56:57.935045",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Payment Type",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchPaymentType(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchPaymentType(FrappeTestCase):
pass

View File

@ -0,0 +1,25 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
frappe.ui.form.on("Church Person", {
refresh(frm) {
// Add 'New Family From Person' button
frm.add_custom_button(__('New Family From Person'), function () {
frm.call("new_family_from_person")
});
// Add 'Church Person Tour' button
frm.add_custom_button(__('Tutorial'), function () {
frm.tour.init("Church Person").then(() => frm.tour.start());
});
},
before_save(frm) {
// Call ensure_single_head_of_household
frm.call("ensure_single_head_of_household");
},
after_save(frm) {
frm.call("update_is_current_role")
},
});

View File

@ -0,0 +1,290 @@
{
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "format:{first_name} {last_name} - {#####}",
"creation": "2025-08-21 01:19:39.714186",
"description": "A person that has interacted with the church in some way (i.e. attendee, member, visitor, etc).",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"personal_information_section",
"first_name",
"last_name",
"full_name",
"column_break_agva",
"photo",
"birthday",
"alergies",
"church_records_section",
"is_member",
"membership_date",
"membership_status",
"column_break_lvwv",
"is_baptized",
"baptism_date",
"section_break_osjz",
"church_roles",
"contact_information_tab",
"contact_information_section",
"home_address",
"mailing_address",
"column_break_vzrz",
"primary_phone",
"email",
"family_tab",
"column_break_gwhd",
"family",
"is_head_of_household",
"is_married",
"anniversary",
"spouse",
"column_break_fkwj",
"table_relations",
"notes_tab",
"notes"
],
"fields": [
{
"allow_in_quick_entry": 1,
"fieldname": "first_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "First Name",
"reqd": 1
},
{
"allow_in_quick_entry": 1,
"fieldname": "last_name",
"fieldtype": "Data",
"in_standard_filter": 1,
"label": "Last Name"
},
{
"fieldname": "full_name",
"fieldtype": "Data",
"label": "Full Name",
"read_only": 1
},
{
"fieldname": "column_break_gwhd",
"fieldtype": "Column Break"
},
{
"allow_in_quick_entry": 1,
"default": "0",
"description": "Is this person a church member?",
"fieldname": "is_member",
"fieldtype": "Check",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Is Member"
},
{
"allow_in_quick_entry": 1,
"default": "Today",
"depends_on": "eval:doc.is_member",
"description": "When did the person become a member?",
"fieldname": "membership_date",
"fieldtype": "Date",
"label": "Membership Date",
"mandatory_depends_on": "eval:doc.is_member"
},
{
"fieldname": "birthday",
"fieldtype": "Date",
"label": "Birthday"
},
{
"fieldname": "personal_information_section",
"fieldtype": "Section Break",
"label": "Personal Information"
},
{
"fieldname": "contact_information_section",
"fieldtype": "Section Break"
},
{
"fieldname": "home_address",
"fieldtype": "Link",
"label": "Home Address",
"options": "Address"
},
{
"fieldname": "mailing_address",
"fieldtype": "Link",
"label": "Mailing Address",
"options": "Address"
},
{
"fieldname": "column_break_vzrz",
"fieldtype": "Column Break"
},
{
"fieldname": "primary_phone",
"fieldtype": "Phone",
"label": "Primary Phone"
},
{
"fieldname": "email",
"fieldtype": "Data",
"label": "Email"
},
{
"allow_in_quick_entry": 1,
"fieldname": "family",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Family",
"options": "Church Family",
"search_index": 1
},
{
"allow_in_quick_entry": 1,
"default": "0",
"depends_on": "eval:doc.family;",
"description": "Is this person 'Head of Household\" for their Family?",
"fieldname": "is_head_of_household",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Is Head of Household"
},
{
"allow_in_quick_entry": 1,
"description": "Note: Relations are not automatically reciprocal. (i.e. If you are editing 'Mark' and add 'Jane' as 'Sister', Jane's record will not automatically be updated to show 'Mark' as 'Brother'. ",
"fieldname": "table_relations",
"fieldtype": "Table",
"label": "Notable Relationships",
"options": "Church Person Relation"
},
{
"fieldname": "photo",
"fieldtype": "Attach Image",
"label": "Photo"
},
{
"fieldname": "contact_information_tab",
"fieldtype": "Tab Break",
"label": "Contact Information"
},
{
"fieldname": "alergies",
"fieldtype": "Data",
"label": "Alergies"
},
{
"fieldname": "church_records_section",
"fieldtype": "Section Break",
"label": "Church Records"
},
{
"fieldname": "column_break_lvwv",
"fieldtype": "Column Break"
},
{
"allow_in_quick_entry": 1,
"depends_on": "eval:doc.is_member",
"fieldname": "membership_status",
"fieldtype": "Link",
"label": "Membership Status",
"mandatory_depends_on": "eval:doc.is_member",
"options": "Church Member Status Type"
},
{
"default": "0",
"fieldname": "is_baptized",
"fieldtype": "Check",
"label": "Is Baptized"
},
{
"depends_on": "eval:doc.is_baptized",
"fieldname": "baptism_date",
"fieldtype": "Date",
"label": "Baptism Date"
},
{
"fieldname": "church_roles",
"fieldtype": "Table",
"label": "Church Roles",
"options": "Church Role"
},
{
"fieldname": "section_break_osjz",
"fieldtype": "Section Break"
},
{
"fieldname": "column_break_agva",
"fieldtype": "Column Break"
},
{
"fieldname": "family_tab",
"fieldtype": "Tab Break",
"label": "Family"
},
{
"default": "0",
"fieldname": "is_married",
"fieldtype": "Check",
"label": "Is Married"
},
{
"depends_on": "eval:doc.is_married;",
"fieldname": "anniversary",
"fieldtype": "Date",
"label": "Anniversary"
},
{
"depends_on": "eval:doc.is_married;",
"fieldname": "spouse",
"fieldtype": "Link",
"label": "Spouse",
"options": "Church Person"
},
{
"fieldname": "column_break_fkwj",
"fieldtype": "Column Break"
},
{
"fieldname": "notes_tab",
"fieldtype": "Tab Break",
"label": "Notes"
},
{
"fieldname": "notes",
"fieldtype": "Text Editor",
"label": "Notes"
}
],
"grid_page_length": 50,
"image_field": "photo",
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-09-06 01:12:17.688813",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Person",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"show_title_field_in_link": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"title_field": "full_name",
"track_changes": 1
}

View File

@ -0,0 +1,60 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
from datetime import datetime
import frappe
from frappe.model.document import Document
class ChurchPerson(Document):
def before_save(self):
# We set this here since virtual fields do not work with
# View Settings -> Title Field as of 2025-08-26
self.full_name = f"{self.first_name} {self.last_name}"
@frappe.whitelist()
def new_family_from_person(self):
doc = frappe.new_doc("Church Family")
doc.family_name = self.last_name
doc.save()
self.set("family", doc)
self.save()
self.reload()
frappe.msgprint(f"New family created: {doc.family_name}")
@frappe.whitelist()
def ensure_single_head_of_household(self):
if self.is_head_of_household:
old_heads_of_household = frappe.db.get_all(
doctype="Church Person",
filters=[
["family", "=", self.family],
["is_head_of_household", "=", True],
["name", "!=", self.name],
],
)
if old_heads_of_household:
for head in old_heads_of_household:
head_doc = frappe.get_doc("Church Person", head["name"])
# ToDo: It may be good to display a message that we are
# changing these documents. For some reason frappe.msgprint
# seems to only return an empty message here:
# frappe.msgprint(
# f"A Head of Household for '{self.family}' was already set.\n"
# f"{head_doc.name} was removed from being Head of Household for '{self.family}'"
# )
head_doc.is_head_of_household = False
head_doc.save()
@frappe.whitelist()
def update_is_current_role(self):
for role in self.church_roles:
if (
frappe.utils.get_datetime(role.start_date)
< datetime.now()
< frappe.utils.get_datetime(role.end_date)
) or (not role.end_date and frappe.utils.get_datetime(role.start_date) < datetime.now()):
role.is_current_role = 1
else:
role.is_current_role = 0

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchPerson(FrappeTestCase):
pass

View File

@ -0,0 +1,53 @@
{
"actions": [],
"creation": "2025-08-25 20:53:56.079617",
"description": "Relationship between two `Church Person`s",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"section_break_mhmq",
"church_person",
"relation_type"
],
"fields": [
{
"fieldname": "section_break_mhmq",
"fieldtype": "Section Break"
},
{
"allow_in_quick_entry": 1,
"fieldname": "relation_type",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Relation Type",
"options": "Church Person Relation Type",
"reqd": 1
},
{
"allow_in_quick_entry": 1,
"fieldname": "church_person",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Church Person",
"options": "Church Person",
"reqd": 1
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2025-09-05 00:00:45.544253",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Person Relation",
"owner": "Administrator",
"permissions": [],
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchPersonRelation(Document):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Church Person Relation Type", {
// refresh(frm) {
// },
// });

View File

@ -0,0 +1,59 @@
{
"actions": [],
"allow_import": 1,
"autoname": "format:{relation_type}",
"creation": "2025-08-25 21:30:15.393857",
"description": "The type of relationship between two `Church Person`s",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"relation_type",
"description"
],
"fields": [
{
"allow_in_quick_entry": 1,
"fieldname": "relation_type",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Relation Type",
"reqd": 1,
"unique": 1
},
{
"allow_in_quick_entry": 1,
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Description"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-08-26 01:47:22.322018",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Person Relation Type",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"row_format": "Dynamic",
"sort_field": "relation_type",
"sort_order": "ASC",
"states": []
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchPersonRelationType(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchPersonRelationType(FrappeTestCase):
pass

View File

@ -0,0 +1,7 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Church Role", {
// });

View File

@ -0,0 +1,74 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{role} - {#####}",
"creation": "2025-08-26 22:42:20.029649",
"description": "`Church Person` roles in the church.",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"role",
"start_date",
"end_date",
"is_current_role",
"notes"
],
"fields": [
{
"fieldname": "role",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Role",
"options": "Church Role Type",
"reqd": 1
},
{
"fieldname": "notes",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Notes"
},
{
"default": "Today",
"fieldname": "start_date",
"fieldtype": "Date",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Start Date",
"reqd": 1
},
{
"fieldname": "end_date",
"fieldtype": "Date",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "End Date"
},
{
"default": "0",
"fieldname": "is_current_role",
"fieldtype": "Check",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Is Current Role?"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2025-09-06 01:56:17.457466",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Role",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"row_format": "Dynamic",
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
class ChurchRole(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchRole(FrappeTestCase):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2025, meichthys and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Church Role Type", {
// refresh(frm) {
// },
// });

View File

@ -0,0 +1,59 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:{role} - {#####}",
"creation": "2025-08-26 22:57:29.102805",
"description": "Types of roles that `Church Person`s can fill in the church.",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"role",
"description"
],
"fields": [
{
"description": "The name of the role or position that a `Church Person` can fulfill.",
"fieldname": "role",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Role",
"reqd": 1
},
{
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Description"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-09-05 00:01:13.708323",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Role Type",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"row_format": "Dynamic",
"show_title_field_in_link": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"title_field": "role"
}

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class ChurchRoleType(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2025, meichthys and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestChurchRoleType(FrappeTestCase):
pass

View File

@ -0,0 +1,32 @@
{
"allow_roles": [
{
"role": "Administrator"
}
],
"creation": "2025-09-01 01:22:49.239262",
"docstatus": 0,
"doctype": "Module Onboarding",
"documentation_url": "https://github.com/meichthys/church",
"idx": 0,
"is_complete": 0,
"modified": "2025-09-03 00:16:21.639005",
"modified_by": "Administrator",
"module": "Church",
"name": "Church",
"owner": "Administrator",
"steps": [
{
"step": "Church Person"
},
{
"step": "Church Family"
},
{
"step": "Church Event"
}
],
"subtitle": "People, Families, Events, Ministries, and more...",
"success_message": "Your Church is setup! \ud83c\udf89 May God grow your ministry \ud83d\ude4f",
"title": "\u26ea Let's Set Up Your Church."
}

View File

@ -0,0 +1,19 @@
{
"action": "Create Entry",
"creation": "2025-09-01 01:22:18.857151",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
"modified": "2025-09-01 01:22:18.857151",
"modified_by": "Administrator",
"name": "Church Event",
"owner": "Administrator",
"reference_document": "Church Event",
"show_form_tour": 0,
"show_full_form": 0,
"title": "Add upcoming church events.",
"validate_action": 1
}

View File

@ -0,0 +1,19 @@
{
"action": "Create Entry",
"creation": "2025-09-01 01:21:35.262713",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
"modified": "2025-09-01 01:21:35.262713",
"modified_by": "Administrator",
"name": "Church Family",
"owner": "Administrator",
"reference_document": "Church Family",
"show_form_tour": 0,
"show_full_form": 0,
"title": "Add families that are represented in your church.",
"validate_action": 1
}

View File

@ -0,0 +1,21 @@
{
"action": "Create Entry",
"action_label": "",
"creation": "2025-09-01 01:20:15.914066",
"description": "",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
"modified": "2025-09-01 01:28:40.000011",
"modified_by": "Administrator",
"name": "Church Person",
"owner": "Administrator",
"reference_document": "Church Person",
"show_form_tour": 0,
"show_full_form": 0,
"title": "Add people that attend your church.",
"validate_action": 1
}

View File

View File

@ -0,0 +1,29 @@
{
"add_total_row": 0,
"add_translate_data": 0,
"columns": [],
"creation": "2025-09-05 01:10:20.185556",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"json": "{\"filters\":[[\"Church Event Attendance\",\"person\",\"is\",\"set\",false],[\"Church Event Attendance\",\"attendance_type\",\"in\",[\"Confirmed\",\"Assumed\"],false]],\"fields\":[[\"person\",\"Church Event Attendance\"],[\"event_name\",\"Church Event\"],[\"type\",\"Church Event\"],[\"attendance_type\",\"Church Event Attendance\"],[\"name\",\"Church Event\"]],\"order_by\":\"`tabChurch Event`.`modified` desc\",\"page_length\":20,\"column_widths\":{\"Church Event Attendance:person\":120,\"event_name\":120,\"type\":182,\"Church Event Attendance:attendance_type\":120,\"name\":361},\"group_by\":null}",
"letterhead": null,
"modified": "2025-09-05 01:17:07.937298",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Attendance",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Church Event",
"report_name": "Church Attendance",
"report_type": "Report Builder",
"roles": [
{
"role": "System Manager"
}
],
"timeout": 0
}

View File

@ -0,0 +1,39 @@
{
"add_total_row": 1,
"add_translate_data": 0,
"columns": [],
"creation": "2025-09-03 23:14:16.871681",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [
{
"default": "",
"fieldname": "parent_filter",
"fieldtype": "Link",
"label": "Collections",
"mandatory": 1,
"options": "Church Collection",
"wildcard_filter": 0
}
],
"idx": 2,
"is_standard": "Yes",
"letterhead": null,
"modified": "2025-09-05 01:07:50.717361",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Collection Bank Reconciliation",
"owner": "Administrator",
"prepared_report": 0,
"query": "SELECT\n parent as \"Collection\", \n fund as \"Fund\", \n person as \"Person\", \n payment_type as \"Payment Type\", \n check_number as \"Check #\", \n sum(amount) as \"Amount\", \n notes as \"Notes\"\nFROM `tabChurch Donation`\nWHERE parent = %(parent_filter)s\nGROUP By check_number;",
"ref_doctype": "Church Collection",
"report_name": "Church Collection Bank Reconciliation",
"report_type": "Query Report",
"roles": [
{
"role": "System Manager"
}
],
"timeout": 0
}

View File

@ -0,0 +1,29 @@
{
"add_total_row": 0,
"add_translate_data": 0,
"columns": [],
"creation": "2025-09-05 01:00:11.506737",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"json": "{\"filters\":[],\"fields\":[[\"name\",\"Church Collection\"],[\"event\",\"Church Collection\"],[\"fund\",\"Church Donation\"],[\"person\",\"Church Donation\"],[\"payment_type\",\"Church Donation\"],[\"check_number\",\"Church Donation\"],[\"amount\",\"Church Donation\"]],\"order_by\":\"`tabChurch Collection`.`modified` desc\",\"page_length\":20,\"column_widths\":{\"name\":120,\"event\":120,\"Church Donation:fund\":120,\"Church Donation:person\":120,\"Church Donation:payment_type\":120,\"Church Donation:check_number\":120,\"Church Donation:amount\":120},\"group_by\":null}",
"letterhead": null,
"modified": "2025-09-05 01:05:48.956751",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Donations",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Church Collection",
"report_name": "Church Donations",
"report_type": "Report Builder",
"roles": [
{
"role": "System Manager"
}
],
"timeout": 0
}

View File

@ -0,0 +1,29 @@
{
"add_total_row": 0,
"add_translate_data": 0,
"columns": [],
"creation": "2025-09-05 00:50:20.107973",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"json": "{\"filters\":[[\"Church Collection\",\"date\",\"Timespan\",\"this year\",false]],\"fields\":[[\"person\",\"Church Donation\"],[\"_aggregate_column\",\"Church Donation\"]],\"order_by\":\"`tabChurch Collection`.`modified` desc\",\"add_totals_row\":true,\"page_length\":20,\"column_widths\":{\"Church Donation:person\":120,\"_aggregate_column\":200},\"group_by\":{\"group_by\":\"`tabChurch Donation`.`person`\",\"aggregate_function\":\"sum\",\"aggregate_on\":\"`tabChurch Donation`.`amount`\"}}",
"letterhead": null,
"modified": "2025-09-05 00:58:49.724689",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Donations by Person",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Church Collection",
"report_name": "Church Donations by Person",
"report_type": "Report Builder",
"roles": [
{
"role": "System Manager"
}
],
"timeout": 0
}

View File

@ -0,0 +1,29 @@
{
"add_total_row": 1,
"add_translate_data": 0,
"columns": [],
"creation": "2025-09-04 22:57:32.654687",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"letterhead": null,
"modified": "2025-09-04 23:21:32.192099",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Event Attendance",
"owner": "Administrator",
"prepared_report": 0,
"query": "SELECT parent as Event, count(person) as `Attendance Count`\nFROM `tabChurch Event Attendance`\nWHERE attendance_type in (\"Assumed\", \"Confirmed\")\nGROUP BY parent;\n",
"ref_doctype": "Church Event",
"report_name": "Church Event Attendance",
"report_type": "Query Report",
"roles": [
{
"role": "System Manager"
}
],
"timeout": 0
}

View File

@ -0,0 +1,48 @@
{
"add_total_row": 1,
"add_translate_data": 0,
"columns": [],
"creation": "2025-09-04 22:27:48.193996",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [
{
"default": "",
"fieldname": "start",
"fieldtype": "Date",
"label": "Start Date",
"mandatory": 1,
"wildcard_filter": 0
},
{
"default": "Today",
"fieldname": "end",
"fieldtype": "Date",
"label": "End Date",
"mandatory": 1,
"wildcard_filter": 0
}
],
"idx": 0,
"is_standard": "Yes",
"json": "{\"columns\":[{\"label\":\"Type\",\"fieldname\":\"type\",\"id\":\"type\",\"name\":\"Type\",\"width\":null,\"editable\":false,\"compareValue\":null},{\"label\":\"Count\",\"fieldname\":\"count\",\"id\":\"count\",\"name\":\"Count\",\"width\":null,\"editable\":false,\"compareValue\":null}],\"filters\":{\"start\":\"2025-06-01\",\"end\":\"2025-09-04\"}}",
"letterhead": null,
"modified": "2025-09-04 22:55:47.816751",
"modified_by": "Administrator",
"module": "Church",
"name": "Church Event Count by Type",
"owner": "Administrator",
"prepared_report": 0,
"query": "SELECT type as Type, count(name) as Counts\nFROM `tabChurch Event`\nWHERE (start_date IS NULL OR end_date IS NULL OR date(start_date) BETWEEN %(start)s AND %(end)s)\nGROUP BY type;",
"ref_doctype": "Church Event",
"reference_report": "Church Events by Type",
"report_name": "Church Event Count by Type",
"report_type": "Query Report",
"roles": [
{
"role": "System Manager"
}
],
"timeout": 0
}

Some files were not shown because too many files have changed in this diff Show More