@@ -0,0 +1,6 @@ | |||
.DS_Store | |||
*.pyc | |||
*.egg-info | |||
*.swp | |||
tags | |||
property_management/docs/current |
@@ -0,0 +1,18 @@ | |||
include MANIFEST.in | |||
include requirements.txt | |||
include *.json | |||
include *.md | |||
include *.py | |||
include *.txt | |||
recursive-include property_management *.css | |||
recursive-include property_management *.csv | |||
recursive-include property_management *.html | |||
recursive-include property_management *.ico | |||
recursive-include property_management *.js | |||
recursive-include property_management *.json | |||
recursive-include property_management *.md | |||
recursive-include property_management *.png | |||
recursive-include property_management *.py | |||
recursive-include property_management *.svg | |||
recursive-include property_management *.txt | |||
recursive-exclude property_management *.pyc |
@@ -0,0 +1,7 @@ | |||
## Property Management | |||
Property Management | |||
#### License | |||
MIT |
@@ -0,0 +1 @@ | |||
License: MIT |
@@ -0,0 +1,5 @@ | |||
# -*- coding: utf-8 -*- | |||
from __future__ import unicode_literals | |||
__version__ = '0.0.1' | |||
@@ -0,0 +1,76 @@ | |||
import frappe | |||
import json | |||
@frappe.whitelist() | |||
def change_contract_status(doc, status): | |||
""" | |||
Validates if property already on rent between the from and to dates | |||
""" | |||
doc = json.loads(doc) | |||
if status == "Hold": | |||
doc = frappe.get_doc("Property Contract", doc["name"]) | |||
doc.status = status | |||
doc.save() | |||
unit_doc = frappe.get_doc("Unit", doc.unit) | |||
unit_doc.status = "Vacant" | |||
unit_doc.save() | |||
return | |||
# Get Property Contaract if from date is between new from and new to date | |||
filters = { | |||
"rent_start_date": ["between", [doc["rent_start_date"], doc["rent_end_date"]]], | |||
"docstatus": 1, | |||
"unit_name": doc["unit_name"], | |||
"status": ["!=", "Hold"] | |||
} | |||
property_contract = frappe.get_list("Property Contract", | |||
fields = ["name"], | |||
filters = filters) | |||
if len(property_contract)> 0: | |||
frappe.throw(f"This property unit already contain a contract <a href='#Form/Property%20Contract/{property_contract[0].name}'>{property_contract[0].name}</a> that not ended yet.") | |||
# Get Property Contaract if to date is between new from and new to date | |||
filters = { | |||
"rent_end_date": ["between", [doc["rent_start_date"], doc["rent_end_date"]]], | |||
"docstatus": 1, | |||
"unit_name": doc["unit_name"], | |||
"status": ["!=", "Hold"] | |||
} | |||
property_contract = frappe.get_list("Property Contract", | |||
fields = ["name"], | |||
filters = filters) | |||
if len(property_contract)> 0: | |||
frappe.throw(f"This property unit already contain a contract <a href='#Form/Property%20Contract/{property_contract[0].name}'>{property_contract[0].name}</a> that not ended yet.") | |||
# Get Property Contaract if from date is after new from date and to date is before new to date | |||
filters = { | |||
"rent_start_date": ["<=", doc["rent_start_date"]], | |||
"rent_end_date": [">=", doc["rent_end_date"]], | |||
"docstatus": 1, | |||
"unit_name": doc["unit_name"], | |||
"status": ["!=", "Hold"] | |||
} | |||
property_contract = frappe.get_list("Property Contract", | |||
fields = ["name"], | |||
filters = filters) | |||
if len(property_contract)> 0: | |||
frappe.throw(f"This property unit already contain a contract <a href='#Form/Property%20Contract/{property_contract[0].name}'>{property_contract[0].name}</a> that not ended yet.") | |||
doc = frappe.get_doc("Property Contract", doc["name"]) | |||
doc.status = status | |||
doc.save() | |||
unit_doc = frappe.get_doc("Unit", doc.unit_name) | |||
unit_doc.status = "Leased" | |||
unit_doc.save() |
@@ -0,0 +1,24 @@ | |||
import frappe | |||
@frappe.whitelist() | |||
def get_tiles_data(): | |||
''' | |||
function will use to get property dashboard's tiles data | |||
''' | |||
properties = frappe.db.count("Property") | |||
units = frappe.db.count("Unit") | |||
sold_units = frappe.db.count("Unit", {"status": "Sold"}) | |||
rented_units = frappe.db.count("Unit", {"status": "Rented"}) | |||
available_units = frappe.db.count("Unit", {"status": "Available"}) | |||
data = { | |||
"total_property": properties, | |||
"total_unit": units, | |||
"total_sold_unit": sold_units, | |||
"total_rented_unit": rented_units, | |||
"total_available_unit": available_units, | |||
} | |||
return data |
@@ -0,0 +1,14 @@ | |||
# -*- coding: utf-8 -*- | |||
from __future__ import unicode_literals | |||
from frappe import _ | |||
def get_data(): | |||
return [ | |||
{ | |||
"module_name": "Property Management", | |||
"color": "grey", | |||
"icon": "octicon octicon-file-directory", | |||
"type": "module", | |||
"label": _("Property Management") | |||
} | |||
] |
@@ -0,0 +1,11 @@ | |||
""" | |||
Configuration for docs | |||
""" | |||
# source_link = "https://github.com/[org_name]/property_management" | |||
# docs_base_url = "https://[org_name].github.io/property_management" | |||
# headline = "App that does everything" | |||
# sub_heading = "Yes, you got that right the first time, everything" | |||
def get_context(context): | |||
context.brand_html = "Property Management" |
@@ -0,0 +1,141 @@ | |||
from __future__ import unicode_literals | |||
from frappe import _ | |||
def get_data(): | |||
return [ | |||
{ | |||
"label": _("Services"), | |||
"items": [ | |||
{ | |||
"type": "doctype", | |||
"name": "Maintenance Ticket", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Property Contract", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Reservations", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Auction", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Auction Free Card", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Real Estate Offer", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Real Estate Order", | |||
"onboard": 1 | |||
} | |||
] | |||
}, | |||
{ | |||
"label": _("Setup"), | |||
"items": [ | |||
{ | |||
"type": "doctype", | |||
"name": "Unit", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Property", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Unit Type", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Property Type", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Unit Activity", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Opening Phase", | |||
"onboard": 1 | |||
}, | |||
] | |||
}, | |||
{ | |||
"label": _("People"), | |||
"items": [ | |||
{ | |||
"type": "doctype", | |||
"name": "User", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "doctype", | |||
"name": "Customer", | |||
"onboard": 1 | |||
} | |||
] | |||
}, | |||
{ | |||
"label": _("Reports"), | |||
"items": [ | |||
{ | |||
"type": "report", | |||
"is_query_report": True, | |||
"name": "Rent Roll", | |||
"doctype": "Property Contract", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "report", | |||
"is_query_report": True, | |||
"name": "Service Charge Roll", | |||
"doctype": "Property Contract", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "report", | |||
"is_query_report": True, | |||
"name": "Sold Unit", | |||
"doctype": "Unit", | |||
"onboard": 1 | |||
}, | |||
{ | |||
"type": "report", | |||
"is_query_report": True, | |||
"name": "Property Management Revenue", | |||
"doctype": "Property Contract", | |||
"onboard": 1 | |||
} | |||
] | |||
}, | |||
{ | |||
"label": _("Dashboards"), | |||
"items": [ | |||
{ | |||
"type": "page", | |||
"name": "property-dashboard", | |||
"label": _("Property Dashboard"), | |||
"onboard": 1 | |||
} | |||
] | |||
}, | |||
] |
@@ -0,0 +1,25 @@ | |||
import frappe | |||
def submit(doc, method): | |||
if hasattr(doc, 'property') and doc.property: | |||
prop = frappe.get_doc('Property', doc.property) | |||
prop.customer = doc.customer | |||
prop.customer_name = doc.customer_name | |||
prop.save() | |||
if hasattr(doc, 'unit') and doc.unit: | |||
unit = frappe.get_doc('Unit', doc.unit) | |||
unit.customer = doc.customer | |||
unit.customer_name = doc.customer_name | |||
unit.save() | |||
def cancel(doc, method): | |||
if hasattr(doc, 'property') and doc.property: | |||
prop = frappe.get_doc('Property', doc.property) | |||
prop.customer = None | |||
prop.customer_name = None | |||
prop.save() | |||
if hasattr(doc, 'unit') and doc.unit: | |||
unit = frappe.get_doc('Unit', doc.unit) | |||
unit.customer = None | |||
unit.customer_name = None | |||
unit.save() |
@@ -0,0 +1,30 @@ | |||
[ | |||
{ | |||
"dimension_defaults": [], | |||
"disabled": 0, | |||
"docstatus": 0, | |||
"doctype": "Accounting Dimension", | |||
"document_type": "Unit", | |||
"fieldname": "unit", | |||
"label": "Unit", | |||
"modified": "2021-02-01 15:29:00.082653", | |||
"name": "Unit", | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null | |||
}, | |||
{ | |||
"dimension_defaults": [], | |||
"disabled": 0, | |||
"docstatus": 0, | |||
"doctype": "Accounting Dimension", | |||
"document_type": "Property", | |||
"fieldname": "property", | |||
"label": "Property", | |||
"modified": "2021-02-01 15:29:09.706024", | |||
"name": "Property", | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null | |||
} | |||
] |
@@ -0,0 +1,462 @@ | |||
[ | |||
{ | |||
"allow_in_quick_entry": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"collapsible_depends_on": null, | |||
"columns": 0, | |||
"default": null, | |||
"depends_on": "eval:doc.customer_type == \"Company\"", | |||
"description": null, | |||
"docstatus": 0, | |||
"doctype": "Custom Field", | |||
"dt": "Customer", | |||
"fetch_from": null, | |||
"fetch_if_empty": 0, | |||
"fieldname": "company_name_en", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"insert_after": "customer_name", | |||
"label": "Company Name en", | |||
"length": 0, | |||
"modified": "2021-04-12 01:00:41.963015", | |||
"name": "Customer-company_name_en", | |||
"no_copy": 0, | |||
"options": null, | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"print_width": null, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"translatable": 0, | |||
"unique": 0, | |||
"width": null | |||
}, | |||
{ | |||
"allow_in_quick_entry": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"collapsible_depends_on": null, | |||
"columns": 0, | |||
"default": null, | |||
"depends_on": null, | |||
"description": null, | |||
"docstatus": 0, | |||
"doctype": "Custom Field", | |||
"dt": "Lead", | |||
"fetch_from": null, | |||
"fetch_if_empty": 0, | |||
"fieldname": "sales_persons", | |||
"fieldtype": "Link", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"insert_after": "email_id", | |||
"label": "Sales Persons", | |||
"length": 0, | |||
"modified": "2021-10-24 01:56:12.828482", | |||
"name": "Lead-sales_persons", | |||
"no_copy": 0, | |||
"options": "Sales Person", | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"print_width": null, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"translatable": 0, | |||
"unique": 0, | |||
"width": null | |||
}, | |||
{ | |||
"allow_in_quick_entry": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"collapsible_depends_on": null, | |||
"columns": 0, | |||
"default": null, | |||
"depends_on": null, | |||
"description": null, | |||
"docstatus": 0, | |||
"doctype": "Custom Field", | |||
"dt": "Customer", | |||
"fetch_from": null, | |||
"fetch_if_empty": 0, | |||
"fieldname": "customer_documents", | |||
"fieldtype": "Section Break", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"insert_after": "disabled", | |||
"label": "Customer Documents", | |||
"length": 0, | |||
"modified": "2021-12-28 00:44:27.424715", | |||
"name": "Customer-customer_documents", | |||
"no_copy": 0, | |||
"options": null, | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"print_width": null, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"translatable": 0, | |||
"unique": 0, | |||
"width": null | |||
}, | |||
{ | |||
"allow_in_quick_entry": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"collapsible_depends_on": null, | |||
"columns": 0, | |||
"default": null, | |||
"depends_on": null, | |||
"description": null, | |||
"docstatus": 0, | |||
"doctype": "Custom Field", | |||
"dt": "Sales Invoice", | |||
"fetch_from": null, | |||
"fetch_if_empty": 0, | |||
"fieldname": "property_contract", | |||
"fieldtype": "Link", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"insert_after": "project", | |||
"label": "Property Contract", | |||
"length": 0, | |||
"modified": "2021-06-18 02:01:44.898355", | |||
"name": "Sales Invoice-property_contract", | |||
"no_copy": 0, | |||
"options": "Property Contract", | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"print_width": null, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"translatable": 0, | |||
"unique": 0, | |||
"width": null | |||
}, | |||
{ | |||
"allow_in_quick_entry": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"collapsible_depends_on": null, | |||
"columns": 0, | |||
"default": null, | |||
"depends_on": null, | |||
"description": null, | |||
"docstatus": 0, | |||
"doctype": "Custom Field", | |||
"dt": "Customer", | |||
"fetch_from": null, | |||
"fetch_if_empty": 0, | |||
"fieldname": "documents", | |||
"fieldtype": "Table", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"insert_after": "customer_documents", | |||
"label": "Documents", | |||
"length": 0, | |||
"modified": "2021-12-28 00:44:27.946523", | |||
"name": "Customer-documents", | |||
"no_copy": 0, | |||
"options": "Document", | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"print_width": null, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"translatable": 0, | |||
"unique": 0, | |||
"width": null | |||
}, | |||
{ | |||
"allow_in_quick_entry": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"collapsible_depends_on": null, | |||
"columns": 0, | |||
"default": null, | |||
"depends_on": null, | |||
"description": null, | |||
"docstatus": 0, | |||
"doctype": "Custom Field", | |||
"dt": "Journal Entry", | |||
"fetch_from": null, | |||
"fetch_if_empty": 0, | |||
"fieldname": "accounting_dimensions", | |||
"fieldtype": "Section Break", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"insert_after": "select_print_heading", | |||
"label": "Accounting Dimensions", | |||
"length": 0, | |||
"modified": "2021-02-01 17:24:28.183421", | |||
"name": "Journal Entry-accounting_dimensions", | |||
"no_copy": 0, | |||
"options": null, | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"print_width": null, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"translatable": 0, | |||
"unique": 0, | |||
"width": null | |||
}, | |||
{ | |||
"allow_in_quick_entry": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"collapsible_depends_on": null, | |||
"columns": 0, | |||
"default": null, | |||
"depends_on": null, | |||
"description": null, | |||
"docstatus": 0, | |||
"doctype": "Custom Field", | |||
"dt": "Journal Entry", | |||
"fetch_from": null, | |||
"fetch_if_empty": 0, | |||
"fieldname": "unit", | |||
"fieldtype": "Link", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"insert_after": "accounting_dimensions", | |||
"label": "Unit", | |||
"length": 0, | |||
"modified": "2021-02-01 17:24:28.342902", | |||
"name": "Journal Entry-unit", | |||
"no_copy": 0, | |||
"options": "Unit", | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"print_width": null, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"translatable": 0, | |||
"unique": 0, | |||
"width": null | |||
}, | |||
{ | |||
"allow_in_quick_entry": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"collapsible_depends_on": null, | |||
"columns": 0, | |||
"default": null, | |||
"depends_on": null, | |||
"description": null, | |||
"docstatus": 0, | |||
"doctype": "Custom Field", | |||
"dt": "Journal Entry", | |||
"fetch_from": null, | |||
"fetch_if_empty": 0, | |||
"fieldname": "property", | |||
"fieldtype": "Link", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"insert_after": "unit", | |||
"label": "Property", | |||
"length": 0, | |||
"modified": "2021-02-01 17:24:28.545797", | |||
"name": "Journal Entry-property", | |||
"no_copy": 0, | |||
"options": "Property", | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"print_width": null, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"translatable": 0, | |||
"unique": 0, | |||
"width": null | |||
}, | |||
{ | |||
"allow_in_quick_entry": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"collapsible_depends_on": null, | |||
"columns": 0, | |||
"default": null, | |||
"depends_on": null, | |||
"description": null, | |||
"docstatus": 0, | |||
"doctype": "Custom Field", | |||
"dt": "Journal Entry", | |||
"fetch_from": null, | |||
"fetch_if_empty": 0, | |||
"fieldname": "column_break_45", | |||
"fieldtype": "Column Break", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"insert_after": "property", | |||
"label": "", | |||
"length": 0, | |||
"modified": "2021-02-01 17:24:28.796911", | |||
"name": "Journal Entry-column_break_45", | |||
"no_copy": 0, | |||
"options": "", | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"print_width": null, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"translatable": 0, | |||
"unique": 0, | |||
"width": null | |||
}, | |||
{ | |||
"allow_in_quick_entry": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"collapsible_depends_on": null, | |||
"columns": 0, | |||
"default": null, | |||
"depends_on": null, | |||
"description": null, | |||
"docstatus": 0, | |||
"doctype": "Custom Field", | |||
"dt": "Journal Entry", | |||
"fetch_from": null, | |||
"fetch_if_empty": 0, | |||
"fieldname": "cost_center", | |||
"fieldtype": "Link", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"insert_after": "column_break_45", | |||
"label": "Cost Center", | |||
"length": 0, | |||
"modified": "2021-02-01 17:24:28.955064", | |||
"name": "Journal Entry-cost_center", | |||
"no_copy": 0, | |||
"options": "Cost Center", | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"print_width": null, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"translatable": 0, | |||
"unique": 0, | |||
"width": null | |||
} | |||
] |
@@ -0,0 +1,18 @@ | |||
[ | |||
{ | |||
"default_value": null, | |||
"doc_type": "Customer", | |||
"docstatus": 0, | |||
"doctype": "Property Setter", | |||
"doctype_or_field": "DocField", | |||
"field_name": "customer_name", | |||
"modified": "2021-04-12 01:03:25.733494", | |||
"name": "Customer-customer_name-label", | |||
"parent": null, | |||
"parentfield": null, | |||
"parenttype": null, | |||
"property": "label", | |||
"property_type": "Data", | |||
"value": "Legal Name" | |||
} | |||
] |
@@ -0,0 +1,161 @@ | |||
# -*- coding: utf-8 -*- | |||
from __future__ import unicode_literals | |||
from . import __version__ as app_version | |||
app_name = "muezzin" | |||
app_title = "Muezzin" | |||
app_publisher = "Havenir Solutions" | |||
app_description = "Property Management App for Muezzin" | |||
app_icon = "octicon octicon-file-directory" | |||
app_color = "grey" | |||
app_email = "info@havenir.com" | |||
app_license = "MIT" | |||
# Includes in <head> | |||
# ------------------ | |||
# include js, css files in header of desk.html | |||
app_include_css = "/assets/css/muezzin.css" | |||
# app_include_js = "/assets/muezzin/js/muezzin.js" | |||
# include js, css files in header of web template | |||
# web_include_css = "/assets/muezzin/css/muezzin.css" | |||
# web_include_js = "/assets/muezzin/js/muezzin.js" | |||
# include js in page | |||
# page_js = {"page" : "public/js/file.js"} | |||
# include js in doctype views | |||
doctype_js = { | |||
"Payment Entry": "public/js/payment_entry.js" | |||
} | |||
# doctype_list_js = {"doctype" : "public/js/doctype_list.js"} | |||
# doctype_tree_js = {"doctype" : "public/js/doctype_tree.js"} | |||
# doctype_calendar_js = {"doctype" : "public/js/doctype_calendar.js"} | |||
# Home Pages | |||
# ---------- | |||
# application home page (will override Website Settings) | |||
# home_page = "login" | |||
# website user home page (by Role) | |||
# role_home_page = { | |||
# "Role": "home_page" | |||
# } | |||
# Website user home page (by function) | |||
# get_website_user_home_page = "muezzin.utils.get_home_page" | |||
# Generators | |||
# ---------- | |||
# automatically create page for each record of this doctype | |||
# website_generators = ["Web Page"] | |||
# Installation | |||
# ------------ | |||
# before_install = "muezzin.install.before_install" | |||
# after_install = "muezzin.install.after_install" | |||
# Desk Notifications | |||
# ------------------ | |||
# See frappe.core.notifications.get_notification_config | |||
# notification_config = "muezzin.notifications.get_notification_config" | |||
# Permissions | |||
# ----------- | |||
# Permissions evaluated in scripted ways | |||
# permission_query_conditions = { | |||
# "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions", | |||
# } | |||
# | |||
# has_permission = { | |||
# "Event": "frappe.desk.doctype.event.event.has_permission", | |||
# } | |||
# Document Events | |||
# --------------- | |||
# Hook on document methods and events | |||
doc_events = { | |||
"Sales Invoice": { | |||
"on_submit": "muezzin.events.sales_invoice.submit", | |||
"on_cancel": "muezzin.events.sales_invoice.cancel" | |||
} | |||
} | |||
# Scheduled Tasks | |||
# --------------- | |||
scheduler_events = { | |||
# "all": [ | |||
# "muezzin.tasks.all" | |||
# ], | |||
"daily": [ | |||
# "muezzin.property_management.doctype.property_contract.property_contract.create_sales_invoice", | |||
"muezzin.property_management.doctype.property_contract.property_contract.update_unit_status" | |||
], | |||
"hourly": [ | |||
"muezzin.property_management.doctype.property_contract.property_contract.update_unit_status_basd_on_reservation" | |||
], | |||
# "weekly": [ | |||
# "muezzin.tasks.weekly" | |||
# ] | |||
# "monthly": [ | |||
# "muezzin.tasks.monthly" | |||
# ] | |||
} | |||
# Testing | |||
# ------- | |||
# before_tests = "muezzin.install.before_tests" | |||
# Overriding Methods | |||
# ------------------------------ | |||
# | |||
# override_whitelisted_methods = { | |||
# "frappe.desk.doctype.event.event.get_events": "muezzin.event.get_events" | |||
# } | |||
# | |||
# each overriding function accepts a `data` argument; | |||
# generated from the base implementation of the doctype dashboard, | |||
# along with any modifications made in other Frappe apps | |||
# override_doctype_dashboards = { | |||
# "Task": "muezzin.task.get_dashboard_data" | |||
# } | |||
fixtures = [{ | |||
"dt": "Custom Field", | |||
"filters": [["name", "in", [ | |||
'Journal Entry-accounting_dimensions', | |||
'Journal Entry-unit', | |||
'Journal Entry-property', | |||
'Journal Entry-column_break_45', | |||
'Journal Entry-cost_center', | |||
'Customer-company_name_en', | |||
'Sales Invoice-property_contract', | |||
'Lead-sales_persons', | |||
'Customer-documents', | |||
'Customer-customer_documents' | |||
]]] | |||
}, | |||
{ | |||
"dt": "Property Setter", | |||
"filters": [["name", "in", [ | |||
'Customer-customer_name-l abel', | |||
]]] | |||
}, | |||
{ | |||
"dt": "Accounting Dimension", | |||
"filters": [["name", "in", [ | |||
'Property', | |||
'Unit' | |||
]]] | |||
} | |||
] |
@@ -0,0 +1 @@ | |||
Property Management |
@@ -0,0 +1,31 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Auction', { | |||
refresh: function(frm) { | |||
frm.set_query('property', () => { | |||
return { | |||
filters: { | |||
property_type: frm.doc.property_type | |||
} | |||
} | |||
}) | |||
}, | |||
property_type: function(frm) { | |||
frm.doc.property = null; | |||
frm.refresh_field('property'); | |||
}, | |||
property: function(frm) { | |||
if (frm.doc.property) { | |||
frappe.db.get_value('Property', frm.doc.property, 'property_type') | |||
.then( r=> { | |||
if (r.message) { | |||
frm.doc.property_type = r.message.property_type; | |||
frm.refresh_field('property_type'); | |||
} | |||
}) | |||
} | |||
} | |||
}); |
@@ -0,0 +1,118 @@ | |||
{ | |||
"autoname": "format:{auction_subject}-{###}", | |||
"creation": "2021-02-22 18:46:54.748490", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"auction_subject", | |||
"property_type", | |||
"property", | |||
"unit", | |||
"attach_a_file", | |||
"column_break_4", | |||
"date", | |||
"number_of_pieces", | |||
"auction_type", | |||
"court", | |||
"amended_from" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "auction_subject", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Auction Subject", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "property_type", | |||
"fieldtype": "Link", | |||
"label": "Property Type", | |||
"options": "Property Type" | |||
}, | |||
{ | |||
"fieldname": "property", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Property", | |||
"options": "Property", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "column_break_4", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"default": "Now", | |||
"fieldname": "date", | |||
"fieldtype": "Date", | |||
"label": "Date" | |||
}, | |||
{ | |||
"fieldname": "number_of_pieces", | |||
"fieldtype": "Int", | |||
"in_list_view": 1, | |||
"label": "Number of Pieces", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "auction_type", | |||
"fieldtype": "Select", | |||
"label": "Auction Type", | |||
"options": "Ministry of Justice\nIndividual" | |||
}, | |||
{ | |||
"fieldname": "court", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Court", | |||
"options": "Court", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "amended_from", | |||
"fieldtype": "Link", | |||
"label": "Amended From", | |||
"no_copy": 1, | |||
"options": "Auction", | |||
"print_hide": 1, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "attach_a_file", | |||
"fieldtype": "Attach", | |||
"label": "Attach a File" | |||
}, | |||
{ | |||
"fieldname": "unit", | |||
"fieldtype": "Table MultiSelect", | |||
"label": "Unit", | |||
"options": "Auction Unit", | |||
"reqd": 1 | |||
} | |||
], | |||
"is_submittable": 1, | |||
"modified": "2021-02-25 11:58:26.923370", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Auction", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"share": 1, | |||
"write": 1 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class Auction(Document): | |||
pass |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestAuction(unittest.TestCase): | |||
pass |
@@ -0,0 +1,37 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Auction Free Card', { | |||
refresh: function(frm) { | |||
frm.set_query('units', () => { | |||
if (frm.doc.auction) { | |||
return { | |||
query: 'muezzin.property_management.doctype.auction_free_card.auction_free_card.get_unit', | |||
filters: { | |||
'parent': frm.doc.auction | |||
} | |||
} | |||
} else { | |||
return { | |||
filters: { | |||
"parent": 'Empty' | |||
} | |||
} | |||
} | |||
}) | |||
}, | |||
auction: function(frm) { | |||
if(frm.doc.auction) { | |||
frm.call('set_unit') | |||
.then( r => { | |||
refresh_field('units'); | |||
}) | |||
} else { | |||
frm.doc.units = []; | |||
frm.doc.property_type = null; | |||
frm.doc.property = null; | |||
frm.refresh_fields('units', 'property', 'property_type'); | |||
} | |||
} | |||
}); |
@@ -0,0 +1,190 @@ | |||
{ | |||
"autoname": "format:AFC-{auction}-{###}", | |||
"creation": "2021-02-23 14:11:09.113084", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"auction", | |||
"property", | |||
"customer", | |||
"column_break_4", | |||
"units", | |||
"property_type", | |||
"mobile_number", | |||
"national_id", | |||
"section_break_9", | |||
"bank", | |||
"check_number", | |||
"check_value", | |||
"vat_on_commission", | |||
"quest_value", | |||
"total_quest", | |||
"column_break_16", | |||
"opening_price", | |||
"plan", | |||
"notes", | |||
"tax_on_property", | |||
"attach_files", | |||
"amended_from" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "auction", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Auction", | |||
"options": "Auction", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fetch_from": "auction.property", | |||
"fieldname": "property", | |||
"fieldtype": "Data", | |||
"label": "Property", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "mobile_number", | |||
"fieldtype": "Data", | |||
"label": "Mobile Number" | |||
}, | |||
{ | |||
"fieldname": "column_break_4", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fetch_from": "auction.property_type", | |||
"fieldname": "property_type", | |||
"fieldtype": "Data", | |||
"label": "Property Type", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "units", | |||
"fieldtype": "Table MultiSelect", | |||
"label": "Units", | |||
"options": "Auction Unit", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "customer", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Customer", | |||
"options": "Customer", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "national_id", | |||
"fieldtype": "Data", | |||
"label": "National Id" | |||
}, | |||
{ | |||
"fieldname": "section_break_9", | |||
"fieldtype": "Section Break" | |||
}, | |||
{ | |||
"fieldname": "bank", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Bank", | |||
"options": "Bank", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "check_number", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Check Number", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "check_value", | |||
"fieldtype": "Float", | |||
"label": "Check Value", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "vat_on_commission", | |||
"fieldtype": "Float", | |||
"label": "Vat On Commission", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "total_quest", | |||
"fieldtype": "Float", | |||
"label": "Total Quest", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "tax_on_property", | |||
"fieldtype": "Check", | |||
"label": "Tax on Property" | |||
}, | |||
{ | |||
"fieldname": "column_break_16", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "opening_price", | |||
"fieldtype": "Float", | |||
"label": "Opening Price" | |||
}, | |||
{ | |||
"fieldname": "quest_value", | |||
"fieldtype": "Float", | |||
"label": "Quest Value", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "plan", | |||
"fieldtype": "Data", | |||
"label": "Plan", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "notes", | |||
"fieldtype": "Data", | |||
"label": "Notes" | |||
}, | |||
{ | |||
"fieldname": "attach_files", | |||
"fieldtype": "Attach", | |||
"label": "Attach Files" | |||
}, | |||
{ | |||
"fieldname": "amended_from", | |||
"fieldtype": "Link", | |||
"label": "Amended From", | |||
"no_copy": 1, | |||
"options": "Auction Free Card", | |||
"print_hide": 1, | |||
"read_only": 1 | |||
} | |||
], | |||
"is_submittable": 1, | |||
"modified": "2021-02-25 11:57:24.514506", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Auction Free Card", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"share": 1, | |||
"write": 1 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,24 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.model.document import Document | |||
class AuctionFreeCard(Document): | |||
def set_unit(self): | |||
result = frappe.db.get_list('Auction Unit', {'parent': self.auction}, 'unit') | |||
for row in result: | |||
self.append('units', { | |||
'unit': row.unit | |||
}) | |||
@frappe.whitelist() | |||
def get_unit(doctype, txt, searchfield, start, page_len, filters): | |||
return frappe.db.sql("""select unit | |||
from `tabAuction Unit` | |||
where | |||
parent = {auction}""" | |||
.format(auction = frappe.db.escape(filters.get("auction")) | |||
)) |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestAuctionFreeCard(unittest.TestCase): | |||
pass |
@@ -0,0 +1,29 @@ | |||
{ | |||
"creation": "2021-02-24 18:10:02.718182", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"unit" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "unit", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Unit", | |||
"options": "Unit" | |||
} | |||
], | |||
"istable": 1, | |||
"modified": "2021-02-24 18:35:03.788544", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Auction Unit", | |||
"owner": "Administrator", | |||
"permissions": [], | |||
"quick_entry": 1, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class AuctionUnit(Document): | |||
pass |
@@ -0,0 +1,43 @@ | |||
{ | |||
"creation": "2021-02-02 12:45:10.043925", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"date", | |||
"annual_raise_type", | |||
"annual_raise_amount" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "date", | |||
"fieldtype": "Date", | |||
"in_list_view": 1, | |||
"label": "Date" | |||
}, | |||
{ | |||
"fieldname": "annual_raise_type", | |||
"fieldtype": "Select", | |||
"in_list_view": 1, | |||
"label": "Annual Raise Type", | |||
"options": "\nAmount\nPercentage" | |||
}, | |||
{ | |||
"fieldname": "annual_raise_amount", | |||
"fieldtype": "Int", | |||
"in_list_view": 1, | |||
"label": "Annual Raise Amount" | |||
} | |||
], | |||
"istable": 1, | |||
"modified": "2021-06-30 03:36:03.351219", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Contract Annual Raise", | |||
"owner": "Administrator", | |||
"permissions": [], | |||
"quick_entry": 1, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class ContractAnnualRaise(Document): | |||
pass |
@@ -0,0 +1,92 @@ | |||
{ | |||
"creation": "2021-02-02 13:38:41.441710", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"date", | |||
"amount", | |||
"reason", | |||
"invoice", | |||
"create_invoice", | |||
"discount_applied", | |||
"discount_refrence", | |||
"remarks" | |||
], | |||
"fields": [ | |||
{ | |||
"columns": 1, | |||
"fieldname": "date", | |||
"fieldtype": "Date", | |||
"in_list_view": 1, | |||
"label": "Date", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"allow_on_submit": 1, | |||
"columns": 1, | |||
"fieldname": "amount", | |||
"fieldtype": "Currency", | |||
"in_list_view": 1, | |||
"label": "Amount", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"columns": 2, | |||
"fieldname": "reason", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Reason" | |||
}, | |||
{ | |||
"columns": 2, | |||
"fieldname": "invoice", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Invoice", | |||
"options": "Sales Invoice", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"allow_on_submit": 1, | |||
"columns": 1, | |||
"fieldname": "create_invoice", | |||
"fieldtype": "Button", | |||
"in_list_view": 1, | |||
"label": "Create Invoice" | |||
}, | |||
{ | |||
"columns": 2, | |||
"fieldname": "remarks", | |||
"fieldtype": "Small Text", | |||
"in_list_view": 1, | |||
"label": "Remarks" | |||
}, | |||
{ | |||
"columns": 1, | |||
"default": "0", | |||
"fieldname": "discount_applied", | |||
"fieldtype": "Check", | |||
"in_list_view": 1, | |||
"label": "Discount Applied", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "discount_refrence", | |||
"fieldtype": "Data", | |||
"label": "Discount Refrence", | |||
"read_only": 1 | |||
} | |||
], | |||
"istable": 1, | |||
"modified": "2021-12-25 18:08:34.469555", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Contract Payments", | |||
"owner": "Administrator", | |||
"permissions": [], | |||
"quick_entry": 1, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class ContractPayments(Document): | |||
pass |
@@ -0,0 +1,8 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Court', { | |||
// refresh: function(frm) { | |||
// } | |||
}); |
@@ -0,0 +1,52 @@ | |||
{ | |||
"autoname": "field:court_name", | |||
"creation": "2021-02-22 18:46:46.022348", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"court_name", | |||
"amended_from" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "court_name", | |||
"fieldtype": "Data", | |||
"label": "Court Name", | |||
"unique": 1 | |||
}, | |||
{ | |||
"fieldname": "amended_from", | |||
"fieldtype": "Link", | |||
"label": "Amended From", | |||
"no_copy": 1, | |||
"options": "Court", | |||
"print_hide": 1, | |||
"read_only": 1 | |||
} | |||
], | |||
"is_submittable": 1, | |||
"modified": "2021-02-22 18:46:46.022348", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Court", | |||
"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, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class Court(Document): | |||
pass |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestCourt(unittest.TestCase): | |||
pass |
@@ -0,0 +1,39 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Discount Request', { | |||
refresh: function (frm) { | |||
get_brand_names(frm) | |||
}, | |||
onload: function (frm) { | |||
get_brand_names(frm) | |||
}, | |||
customer: function (frm) { | |||
get_brand_names(frm) | |||
frm.set_query('property_contract', function (doc) { | |||
return { | |||
filters: { | |||
renter: frm.doc.customer, | |||
docstatus: 1 | |||
} | |||
} | |||
}); | |||
} | |||
}); | |||
let get_brand_names = function (frm) { | |||
if (frm.doc.customer) { | |||
frappe.call({ | |||
method: "get_brand_names", | |||
doc: frm.doc, | |||
callback: function (data) { | |||
if (data.message) { | |||
let options = data.message; | |||
let options_new = options.join("\n"); | |||
frm.set_df_property('brand_name', 'options', options_new); | |||
} | |||
} | |||
}) | |||
} | |||
} |
@@ -0,0 +1,153 @@ | |||
{ | |||
"autoname": "format:{property_contract}-{YYYY}-{#####}", | |||
"creation": "2021-12-25 15:32:33.360291", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"customer", | |||
"customer_name", | |||
"brand_name", | |||
"column_break_4", | |||
"start_date", | |||
"end_date", | |||
"section_break_7", | |||
"property_contract", | |||
"unit_name", | |||
"column_break_10", | |||
"apply_discount_on", | |||
"discount_type", | |||
"percentage", | |||
"amount", | |||
"section_break_14", | |||
"description", | |||
"amended_from" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "customer", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Customer", | |||
"options": "Customer", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fetch_from": "customer.customer_name", | |||
"fieldname": "customer_name", | |||
"fieldtype": "Read Only", | |||
"label": "Customer Name" | |||
}, | |||
{ | |||
"fieldname": "brand_name", | |||
"fieldtype": "Select", | |||
"label": "Tenant Brand Name" | |||
}, | |||
{ | |||
"fieldname": "column_break_4", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "start_date", | |||
"fieldtype": "Date", | |||
"label": "Start Date", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "end_date", | |||
"fieldtype": "Date", | |||
"label": "End Date", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "section_break_7", | |||
"fieldtype": "Section Break" | |||
}, | |||
{ | |||
"fieldname": "property_contract", | |||
"fieldtype": "Link", | |||
"label": "Property Contract", | |||
"options": "Property Contract" | |||
}, | |||
{ | |||
"fetch_from": "property_contract.unit", | |||
"fieldname": "unit_name", | |||
"fieldtype": "Link", | |||
"label": "Unit Name", | |||
"options": "Unit", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "amended_from", | |||
"fieldtype": "Link", | |||
"label": "Amended From", | |||
"no_copy": 1, | |||
"options": "Discount Request", | |||
"print_hide": 1, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "column_break_10", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "discount_type", | |||
"fieldtype": "Select", | |||
"label": "Discount Type", | |||
"options": "\nPercentage\nAmount" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.discount_type=='Percentage'", | |||
"fieldname": "percentage", | |||
"fieldtype": "Percent", | |||
"label": "Percentage" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.discount_type=='Amount'", | |||
"fieldname": "amount", | |||
"fieldtype": "Currency", | |||
"label": "Amount" | |||
}, | |||
{ | |||
"fieldname": "section_break_14", | |||
"fieldtype": "Section Break" | |||
}, | |||
{ | |||
"fieldname": "description", | |||
"fieldtype": "Small Text", | |||
"label": "Description" | |||
}, | |||
{ | |||
"fieldname": "apply_discount_on", | |||
"fieldtype": "Select", | |||
"label": "Apply Discount On", | |||
"options": "\nRent\nServices Charges\nAll", | |||
"reqd": 1 | |||
} | |||
], | |||
"is_submittable": 1, | |||
"modified": "2021-12-25 16:28:30.028665", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Discount Request", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"share": 1, | |||
"write": 1 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1, | |||
"track_seen": 1, | |||
"track_views": 1 | |||
} |
@@ -0,0 +1,52 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.model.document import Document | |||
from frappe.utils import flt | |||
class DiscountRequest(Document): | |||
def on_submit(self): | |||
self.add_remove_discount(type='Add') | |||
def on_cancel(self): | |||
self.add_remove_discount(type='Remove') | |||
def get_brand_names(self): | |||
list_items = [] | |||
brands = frappe.get_all("Tenant Brand Name", filters={"parent": self.customer}, fields=['tenant_brand_name'], | |||
order_by="tenant_brand_name") | |||
if brands: | |||
for item in brands: | |||
list_items.append(item["tenant_brand_name"]) | |||
return list_items | |||
def add_remove_discount(self, type): | |||
filters = {"parent": self.property_contract, "date": ["between", [self.start_date, self.end_date]], | |||
"invoice": ["=", '']} | |||
if self.apply_discount_on != "All": | |||
filters['reason'] = self.apply_discount_on | |||
payments = frappe.db.get_all("Contract Payments", filters=filters, order_by="date") | |||
for row in payments: | |||
doc = frappe.get_doc("Contract Payments", row["name"]) | |||
if type == 'Add': | |||
doc.amount -= ( | |||
((flt(self.percentage) / 100) * flt(doc.amount)) if self.discount_type == 'Percentage' else flt( | |||
self.amount)) | |||
doc.remarks = ' تم تطبيق خصم على هذا الشهريقيمة <br>' + str((((flt(self.percentage) / 100) * flt( | |||
doc.amount)) if self.discount_type == 'Percentage' else flt(self.amount))) + "<br>" + str(self.name) | |||
doc.discount_applied = 1 | |||
doc.discount_refrence = self.name | |||
else: | |||
doc.amount = (( (flt(doc.amount) * 100) / flt(100 - flt(self.percentage)) ) if self.discount_type == 'Percentage' else (flt(self.amount)+flt(doc.amount))) | |||
doc.remarks = '' | |||
doc.discount_applied = 0 | |||
doc.discount_refrence = '' | |||
doc.flags.ignore_validate_update_after_submit = True | |||
doc.save() | |||
frappe.db.commit() |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestDiscountRequest(unittest.TestCase): | |||
pass |
@@ -0,0 +1,60 @@ | |||
{ | |||
"creation": "2021-12-28 00:43:37.531121", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"title", | |||
"document_type", | |||
"attach", | |||
"start_date", | |||
"end_date" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "title", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Title", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "document_type", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Document Type", | |||
"options": "Document Type", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "attach", | |||
"fieldtype": "Attach", | |||
"in_list_view": 1, | |||
"label": "Attach", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "start_date", | |||
"fieldtype": "Date", | |||
"in_list_view": 1, | |||
"label": "Start Date" | |||
}, | |||
{ | |||
"fieldname": "end_date", | |||
"fieldtype": "Date", | |||
"in_list_view": 1, | |||
"label": "End Date" | |||
} | |||
], | |||
"istable": 1, | |||
"modified": "2021-12-28 00:45:09.880101", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Document", | |||
"owner": "Administrator", | |||
"permissions": [], | |||
"quick_entry": 1, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class Document(Document): | |||
pass |
@@ -0,0 +1,8 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Document Type', { | |||
// refresh: function(frm) { | |||
// } | |||
}); |
@@ -0,0 +1,43 @@ | |||
{ | |||
"autoname": "field:type", | |||
"creation": "2021-12-28 00:40:08.546784", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"type" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "type", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Type", | |||
"reqd": 1, | |||
"unique": 1 | |||
} | |||
], | |||
"modified": "2021-12-28 00:40:14.109297", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Document Type", | |||
"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, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class DocumentType(Document): | |||
pass |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestDocumentType(unittest.TestCase): | |||
pass |
@@ -0,0 +1,47 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Maintenance Ticket', { | |||
refresh: function(frm) { | |||
queries(frm); | |||
}, | |||
onload_post_render(frm) { | |||
set_location(frm); | |||
}, | |||
property(frm) { | |||
if (frm.doc.property) { | |||
// setTimeout(set_location(frm), 500); | |||
} else { | |||
frm.doc.unit = null; | |||
frm.doc.property_location = null; | |||
frm.doc.latitude = null; | |||
frm.doc.longitude = null; | |||
frm.refresh_fields(['unit', 'property_location', 'latitude', 'longitude']); | |||
} | |||
}, | |||
property_location(frm) { | |||
set_location(frm); | |||
} | |||
}); | |||
function queries(frm) { | |||
frm.set_query('unit', () => { | |||
return { | |||
filters: { | |||
property: frm.doc.property | |||
} | |||
} | |||
}) | |||
} | |||
// function set_location(frm) { | |||
// if (!frm.doc.property_location && frm.doc.latitude && frm.doc.longitude) { | |||
// frm.fields_dict.property_location.map.setView([frm.doc.latitude, frm.doc.longitude], 13); | |||
// } | |||
// else { | |||
// frm.doc.latitude = frm.fields_dict.property_location.map.getCenter()['lat']; | |||
// frm.doc.longitude = frm.fields_dict.property_location.map.getCenter()['lng']; | |||
// } | |||
// } |
@@ -0,0 +1,173 @@ | |||
{ | |||
"autoname": "naming_series:", | |||
"creation": "2021-01-15 17:58:51.656150", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"naming_series", | |||
"property", | |||
"unit", | |||
"category", | |||
"property_location", | |||
"column_break_5", | |||
"client", | |||
"mobile_number", | |||
"service_provider", | |||
"section_break_11", | |||
"notes", | |||
"section_break_13", | |||
"latitude", | |||
"responsible_user", | |||
"column_break_15", | |||
"longitude", | |||
"send_sms_alert_to_responsible_user", | |||
"section_break_18", | |||
"location", | |||
"amended_from" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "naming_series", | |||
"fieldtype": "Data", | |||
"label": "Serial Number", | |||
"options": "MT-" | |||
}, | |||
{ | |||
"fieldname": "property", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Property", | |||
"options": "Property", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "category", | |||
"fieldtype": "Select", | |||
"label": "Category", | |||
"options": "Electrical Maintenance\nWater Maintenance\nA / C Maintenance\nElevators\nCleaning\nOther" | |||
}, | |||
{ | |||
"fieldname": "mobile_number", | |||
"fieldtype": "Data", | |||
"label": "Mobile Number" | |||
}, | |||
{ | |||
"fieldname": "column_break_5", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "service_provider", | |||
"fieldtype": "Link", | |||
"label": "Service Provider", | |||
"options": "Supplier" | |||
}, | |||
{ | |||
"fieldname": "client", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Client", | |||
"options": "Customer", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fetch_from": "property.property_location", | |||
"fieldname": "property_location", | |||
"fieldtype": "Data", | |||
"label": "Property Location", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "notes", | |||
"fieldtype": "Small Text", | |||
"label": "Notes" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "send_sms_alert_to_responsible_user", | |||
"fieldtype": "Check", | |||
"label": "Send SMS Alert to Responsible User" | |||
}, | |||
{ | |||
"fetch_from": "property.latitude", | |||
"fieldname": "latitude", | |||
"fieldtype": "Data", | |||
"label": "Latitude", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "column_break_15", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "responsible_user", | |||
"fieldtype": "Link", | |||
"label": "Responsible User", | |||
"options": "User" | |||
}, | |||
{ | |||
"fetch_from": "property.longitude", | |||
"fieldname": "longitude", | |||
"fieldtype": "Data", | |||
"label": "Longitude", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "section_break_18", | |||
"fieldtype": "Section Break" | |||
}, | |||
{ | |||
"fieldname": "location", | |||
"fieldtype": "Geolocation", | |||
"label": "Location" | |||
}, | |||
{ | |||
"fieldname": "amended_from", | |||
"fieldtype": "Link", | |||
"label": "Amended From", | |||
"no_copy": 1, | |||
"options": "Maintenance Ticket", | |||
"print_hide": 1, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "unit", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Unit", | |||
"options": "Unit", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "section_break_11", | |||
"fieldtype": "Section Break" | |||
}, | |||
{ | |||
"fieldname": "section_break_13", | |||
"fieldtype": "Section Break" | |||
} | |||
], | |||
"is_submittable": 1, | |||
"modified": "2021-01-18 12:35:14.883674", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Maintenance Ticket", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"share": 1, | |||
"write": 1 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class MaintenanceTicket(Document): | |||
pass |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestMaintenanceTicket(unittest.TestCase): | |||
pass |
@@ -0,0 +1,8 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Opening Phase', { | |||
// refresh: function(frm) { | |||
// } | |||
}); |
@@ -0,0 +1,43 @@ | |||
{ | |||
"autoname": "field:phase_name", | |||
"creation": "2021-04-12 01:36:49.755823", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"phase_name" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "phase_name", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Phase Name", | |||
"reqd": 1, | |||
"unique": 1 | |||
} | |||
], | |||
"modified": "2021-04-12 01:36:58.923784", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Opening Phase", | |||
"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, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class OpeningPhase(Document): | |||
pass |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestOpeningPhase(unittest.TestCase): | |||
pass |
@@ -0,0 +1,58 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Property', { | |||
refresh: function(frm) { | |||
if (!frm.is_dirty()) { | |||
create_custom_buttons(frm); | |||
} | |||
} | |||
}); | |||
const create_custom_buttons = function(frm) { | |||
frm.add_custom_button(__('Journal Entry'), () => { | |||
let doc = frm.doc | |||
frappe.run_serially([ | |||
() => frappe.new_doc('Journal Entry'), | |||
() => { | |||
cur_frm.doc.cost_center = doc.cost_center; | |||
cur_frm.doc.property = doc.name; | |||
cur_frm.refresh(); | |||
} | |||
]); | |||
}, __('Create')); | |||
frm.add_custom_button(__('Sales Invoice'), () => { | |||
let doc = frm.doc | |||
frappe.run_serially([ | |||
() => frappe.new_doc('Sales Invoice'), | |||
() => { | |||
cur_frm.doc.cost_center = doc.cost_center; | |||
cur_frm.doc.property = doc.name; | |||
cur_frm.refresh(); | |||
} | |||
]); | |||
}, __('Create')); | |||
frm.add_custom_button(__('Payment Entry'), () => { | |||
let doc = frm.doc | |||
frappe.run_serially([ | |||
() => frappe.new_doc('Payment Entry'), | |||
() => { | |||
cur_frm.doc.cost_center = doc.cost_center; | |||
cur_frm.doc.property = doc.name; | |||
if (doc.customer) { | |||
cur_frm.doc.party_type = 'Customer'; | |||
cur_frm.doc.party = doc.customer; | |||
cur_frm.doc.party_name = doc.customer_name; | |||
} | |||
if (doc.supplier) { | |||
cur_frm.doc.party_type = 'Supplier'; | |||
cur_frm.doc.party = doc.supplier; | |||
cur_frm.doc.party_name = doc.supplier_name; | |||
} | |||
cur_frm.refresh(); | |||
} | |||
]); | |||
}, __('Create')); | |||
} |
@@ -0,0 +1,499 @@ | |||
{ | |||
"autoname": "field:property_name", | |||
"creation": "2021-01-15 17:09:32.926540", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"customer", | |||
"customer_name", | |||
"column_break_2", | |||
"supplier", | |||
"supplier_name", | |||
"basic_information_section", | |||
"property_name", | |||
"property_type", | |||
"property_code_or_plate", | |||
"property_number", | |||
"property_management_commission", | |||
"subject_to_vat", | |||
"property_location", | |||
"about_him", | |||
"column_break_9", | |||
"property_address", | |||
"area_of_property", | |||
"construction_year", | |||
"status", | |||
"governorate", | |||
"city", | |||
"contact", | |||
"type_of_commission_for_property_management", | |||
"calculated_as_a_percentage", | |||
"accounting_dimensions_section", | |||
"cost_center", | |||
"property_data_section", | |||
"property_owner", | |||
"property_owner_company", | |||
"property_owner_supplier", | |||
"property_owner_customer", | |||
"instrument_number", | |||
"land__real_estate_number", | |||
"bank", | |||
"column_break_21", | |||
"instrument_history", | |||
"instrument_case", | |||
"instrument_image_section", | |||
"attach_instrument_image", | |||
"property_evaluation_data_section", | |||
"real_estate_evaluation", | |||
"amount_of_evaluation", | |||
"purchasing_price", | |||
"column_break_30", | |||
"date_of_evaluation", | |||
"resident_agency", | |||
"date_of_purchase", | |||
"picture_of_property_section", | |||
"attach_property_image", | |||
"additional_data_section", | |||
"number_of_elevators", | |||
"national_address", | |||
"number_of_positions", | |||
"real_estate_facilities", | |||
"electricity_account_number", | |||
"cleanliness_for_common_entrance", | |||
"column_break_43", | |||
"number_of_floors", | |||
"flat_construction", | |||
"property_features", | |||
"water_account_number", | |||
"architecture_guard_data_section", | |||
"building_guard_name", | |||
"architecture_guard_identity", | |||
"column_break_51", | |||
"building_guards_mobile_number", | |||
"adding_units_to_property_section", | |||
"units", | |||
"location_on_the_map_section", | |||
"latitude", | |||
"amended_from" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "basic_information_section", | |||
"fieldtype": "Section Break", | |||
"label": "Basic Information" | |||
}, | |||
{ | |||
"fieldname": "property_name", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Property Name", | |||
"no_copy": 1, | |||
"reqd": 1, | |||
"unique": 1 | |||
}, | |||
{ | |||
"fieldname": "property_type", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Property Type", | |||
"options": "Property Type", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "governorate", | |||
"fieldtype": "Link", | |||
"label": "Governorate", | |||
"options": "Territory" | |||
}, | |||
{ | |||
"fieldname": "property_management_commission", | |||
"fieldtype": "Data", | |||
"label": "Property Management Commission" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "subject_to_vat", | |||
"fieldtype": "Check", | |||
"label": "Subject to VAT" | |||
}, | |||
{ | |||
"fieldname": "about_him", | |||
"fieldtype": "Small Text", | |||
"label": "About Him" | |||
}, | |||
{ | |||
"fieldname": "column_break_9", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "property_address", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Property Address", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "area_of_property", | |||
"fieldtype": "Data", | |||
"label": "Area of Property" | |||
}, | |||
{ | |||
"fieldname": "construction_year", | |||
"fieldtype": "Data", | |||
"label": "Construction Year" | |||
}, | |||
{ | |||
"fieldname": "city", | |||
"fieldtype": "Link", | |||
"label": "City", | |||
"options": "Territory" | |||
}, | |||
{ | |||
"fieldname": "type_of_commission_for_property_management", | |||
"fieldtype": "Select", | |||
"label": "Type of Commission for Property Management", | |||
"options": "With Payments Made\nAnnual\nMid Term\nQuarterly" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "calculated_as_a_percentage", | |||
"fieldtype": "Check", | |||
"label": "Calculated as a Percentage" | |||
}, | |||
{ | |||
"fieldname": "property_data_section", | |||
"fieldtype": "Section Break", | |||
"label": "Property Data" | |||
}, | |||
{ | |||
"fieldname": "instrument_number", | |||
"fieldtype": "Data", | |||
"label": "Instrument Number" | |||
}, | |||
{ | |||
"fieldname": "land__real_estate_number", | |||
"fieldtype": "Data", | |||
"label": "Land / Real Estate Number" | |||
}, | |||
{ | |||
"fieldname": "bank", | |||
"fieldtype": "Link", | |||
"label": "Bank", | |||
"options": "Bank" | |||
}, | |||
{ | |||
"fieldname": "column_break_21", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "instrument_history", | |||
"fieldtype": "Date", | |||
"label": "Instrument History" | |||
}, | |||
{ | |||
"fieldname": "instrument_case", | |||
"fieldtype": "Select", | |||
"label": "Instrument Case", | |||
"options": "Mortgaged\nNot Mortgaged" | |||
}, | |||
{ | |||
"fieldname": "instrument_image_section", | |||
"fieldtype": "Section Break", | |||
"label": "Instrument Image" | |||
}, | |||
{ | |||
"fieldname": "property_evaluation_data_section", | |||
"fieldtype": "Section Break", | |||
"label": "Property Evaluation Data" | |||
}, | |||
{ | |||
"fieldname": "real_estate_evaluation", | |||
"fieldtype": "Data", | |||
"label": "Real Estate Evaluation" | |||
}, | |||
{ | |||
"fieldname": "amount_of_evaluation", | |||
"fieldtype": "Data", | |||
"label": "Amount of Evaluation" | |||
}, | |||
{ | |||
"fieldname": "purchasing_price", | |||
"fieldtype": "Float", | |||
"label": "Purchasing Price" | |||
}, | |||
{ | |||
"fieldname": "column_break_30", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "date_of_evaluation", | |||
"fieldtype": "Date", | |||
"label": "Date of Evaluation" | |||
}, | |||
{ | |||
"fieldname": "resident_agency", | |||
"fieldtype": "Data", | |||
"label": "Resident Agency" | |||
}, | |||
{ | |||
"fieldname": "date_of_purchase", | |||
"fieldtype": "Date", | |||
"label": "Date of Purchase" | |||
}, | |||
{ | |||
"fieldname": "picture_of_property_section", | |||
"fieldtype": "Section Break", | |||
"label": "Picture of Property" | |||
}, | |||
{ | |||
"fieldname": "additional_data_section", | |||
"fieldtype": "Section Break", | |||
"label": "Additional Data" | |||
}, | |||
{ | |||
"fieldname": "number_of_elevators", | |||
"fieldtype": "Int", | |||
"label": "Number of Elevators" | |||
}, | |||
{ | |||
"fieldname": "national_address", | |||
"fieldtype": "Data", | |||
"label": "National Address" | |||
}, | |||
{ | |||
"fieldname": "number_of_positions", | |||
"fieldtype": "Int", | |||
"label": "Number of Positions" | |||
}, | |||
{ | |||
"fieldname": "real_estate_facilities", | |||
"fieldtype": "Small Text", | |||
"label": "Real Estate Facilities" | |||
}, | |||
{ | |||
"fieldname": "electricity_account_number", | |||
"fieldtype": "Data", | |||
"label": "Electricity Account Number" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "cleanliness_for_common_entrance", | |||
"fieldtype": "Check", | |||
"label": "Cleanliness for Common Entrance" | |||
}, | |||
{ | |||
"fieldname": "column_break_43", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "number_of_floors", | |||
"fieldtype": "Int", | |||
"label": "Number of Floors" | |||
}, | |||
{ | |||
"fieldname": "flat_construction", | |||
"fieldtype": "Data", | |||
"label": "Flat Construction" | |||
}, | |||
{ | |||
"fieldname": "property_features", | |||
"fieldtype": "Small Text", | |||
"label": "Property Features" | |||
}, | |||
{ | |||
"fieldname": "water_account_number", | |||
"fieldtype": "Data", | |||
"label": "Water Account Number" | |||
}, | |||
{ | |||
"fieldname": "architecture_guard_data_section", | |||
"fieldtype": "Section Break", | |||
"label": "Architecture Guard Data" | |||
}, | |||
{ | |||
"fieldname": "building_guard_name", | |||
"fieldtype": "Data", | |||
"label": "Building Guard Name" | |||
}, | |||
{ | |||
"fieldname": "architecture_guard_identity", | |||
"fieldtype": "Data", | |||
"label": "Architecture Guard Identity" | |||
}, | |||
{ | |||
"fieldname": "column_break_51", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "building_guards_mobile_number", | |||
"fieldtype": "Data", | |||
"label": "Building Guard's Mobile Number" | |||
}, | |||
{ | |||
"fieldname": "adding_units_to_property_section", | |||
"fieldtype": "Section Break", | |||
"label": "Adding Units to Property" | |||
}, | |||
{ | |||
"fieldname": "units", | |||
"fieldtype": "Table", | |||
"label": "Units", | |||
"options": "Property Unit Detail" | |||
}, | |||
{ | |||
"fieldname": "location_on_the_map_section", | |||
"fieldtype": "Section Break", | |||
"label": "Location on the map" | |||
}, | |||
{ | |||
"fieldname": "amended_from", | |||
"fieldtype": "Link", | |||
"label": "Amended From", | |||
"no_copy": 1, | |||
"options": "Property", | |||
"print_hide": 1, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "attach_instrument_image", | |||
"fieldtype": "Attach Image", | |||
"label": "Image" | |||
}, | |||
{ | |||
"fieldname": "attach_property_image", | |||
"fieldtype": "Attach Image", | |||
"label": "Image" | |||
}, | |||
{ | |||
"fieldname": "contact", | |||
"fieldtype": "Link", | |||
"label": "Contact", | |||
"options": "Contact" | |||
}, | |||
{ | |||
"fieldname": "latitude", | |||
"fieldtype": "Data", | |||
"label": "Latitude" | |||
}, | |||
{ | |||
"fieldname": "property_location", | |||
"fieldtype": "Select", | |||
"label": "Property Location", | |||
"options": "Arkan Extention\nArkan Existing" | |||
}, | |||
{ | |||
"fieldname": "status", | |||
"fieldtype": "Select", | |||
"label": "Status", | |||
"options": "Available\nRented\nSold" | |||
}, | |||
{ | |||
"collapsible": 1, | |||
"fieldname": "accounting_dimensions_section", | |||
"fieldtype": "Section Break", | |||
"label": "Accounting Dimensions" | |||
}, | |||
{ | |||
"fieldname": "cost_center", | |||
"fieldtype": "Link", | |||
"label": "Cost Center", | |||
"options": "Cost Center" | |||
}, | |||
{ | |||
"fieldname": "customer", | |||
"fieldtype": "Link", | |||
"label": "Customer", | |||
"no_copy": 1, | |||
"options": "Customer", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "column_break_2", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "supplier", | |||
"fieldtype": "Link", | |||
"label": "Supplier", | |||
"no_copy": 1, | |||
"options": "Supplier", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "property_code_or_plate", | |||
"fieldtype": "Int", | |||
"label": "Property Code / Plate" | |||
}, | |||
{ | |||
"fieldname": "property_number", | |||
"fieldtype": "Int", | |||
"label": "Property Number" | |||
}, | |||
{ | |||
"fieldname": "customer_name", | |||
"fieldtype": "Data", | |||
"label": "Customer Name", | |||
"no_copy": 1, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "supplier_name", | |||
"fieldtype": "Data", | |||
"label": "Supplier Name", | |||
"no_copy": 1, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "property_owner", | |||
"fieldtype": "Select", | |||
"in_list_view": 1, | |||
"label": "Property Owner", | |||
"options": "\nCompany\nSupplier\nCustomer", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"depends_on": "eval:doc.property_owner=='Company'", | |||
"fieldname": "property_owner_company", | |||
"fieldtype": "Link", | |||
"label": "Property Owner Company", | |||
"options": "Company" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.property_owner=='Supplier'", | |||
"fieldname": "property_owner_supplier", | |||
"fieldtype": "Link", | |||
"label": "Property Owner Supplier", | |||
"options": "Supplier" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.property_owner=='Customer'", | |||
"fieldname": "property_owner_customer", | |||
"fieldtype": "Link", | |||
"label": "Property Owner Customer", | |||
"options": "Customer" | |||
} | |||
], | |||
"modified": "2021-03-01 16:41:28.607988", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Property", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"share": 1, | |||
"write": 1 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class Property(Document): | |||
pass |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestProperty(unittest.TestCase): | |||
pass |
@@ -0,0 +1,545 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe import _ | |||
import datetime | |||
# from datetime import datetime, timedelta | |||
import dateutil | |||
import calendar | |||
from calendar import weekday, monthrange | |||
from collections import Counter | |||
from dateutil.relativedelta import relativedelta | |||
from dateutil.rrule import rrule, MONTHLY, YEARLY | |||
from frappe.model.document import Document | |||
from frappe.utils import flt, date_diff, getdate, cint, nowdate,get_datetime | |||
class PropertyContract(Document): | |||
def validate(self): | |||
if self.is_new(): | |||
self.add_payment() | |||
# self.add_contract_annual_raise() | |||
def before_submit(self): | |||
""" | |||
Validates if property already on rent between the from and to dates | |||
""" | |||
# Get Property Contaract if from date is between new from and new to date | |||
filters = { | |||
"rent_start_date": ["between", [self.rent_start_date, self.rent_end_date]], | |||
"docstatus": 1, | |||
"unit": self.unit, | |||
"status": ["!=", "Hold"] | |||
} | |||
property_contract = frappe.get_list("Property Contract", | |||
fields = ["name"], | |||
filters = filters) | |||
if len(property_contract)> 0: | |||
frappe.throw(f"This property unit already contain a contract <a href='#Form/Property%20Contract/{property_contract[0].name}'>{property_contract[0].name}</a> that not ended yet.") | |||
# Get Property Contaract if to date is between new from and new to date | |||
filters = { | |||
"rent_end_date": ["between", [self.rent_start_date, self.rent_end_date]], | |||
"docstatus": 1, | |||
"unit": self.unit, | |||
"status": ["!=", "Hold"] | |||
} | |||
property_contract = frappe.get_list("Property Contract", | |||
fields = ["name"], | |||
filters = filters) | |||
if len(property_contract)> 0: | |||
frappe.throw(f"This property unit already contain a contract <a href='#Form/Property%20Contract/{property_contract[0].name}'>{property_contract[0].name}</a> that not ended yet.") | |||
# Get Property Contaract if from date is after new from date and to date is before new to date | |||
filters = { | |||
"rent_start_date": ["<=", self.rent_start_date], | |||
"rent_end_date": [">=", self.rent_end_date], | |||
"docstatus": 1, | |||
"unit": self.unit, | |||
"status": ["!=", "Hold"] | |||
} | |||
property_contract = frappe.get_list("Property Contract", | |||
fields = ["name"], | |||
filters = filters) | |||
if len(property_contract)> 0: | |||
frappe.throw(f"This property unit already contain a contract <a href='#Form/Property%20Contract/{property_contract[0].name}'>{property_contract[0].name}</a> that not ended yet.") | |||
diff_days = date_diff(self.rent_end_date,getdate()) | |||
if flt(diff_days) > 0: | |||
frappe.db.set_value("Unit", self.unit, "status", "Leased") | |||
def add_contract_annual_raise(self): | |||
self.contract_annual_raise = [] | |||
start_date = datetime.datetime.strptime(self.rent_start_date, "%Y-%m-%d") | |||
duration = self.duration - 1 if self.duration > 1 else self.duration | |||
month = dateutil.relativedelta.relativedelta(months=duration) | |||
end_date = start_date + month | |||
for row in rrule(YEARLY, dtstart=start_date, until=end_date): | |||
self.append('contract_annual_raise', { | |||
'date': row.date(), | |||
'amount': 0, | |||
}) | |||
def add_payment(self): | |||
self.payments = [] | |||
start_date = datetime.datetime.strptime(self.rent_start_date, "%Y-%m-%d") | |||
duration = self.duration - 1 if self.duration > 1 else self.duration | |||
month = dateutil.relativedelta.relativedelta(months=duration) | |||
end_date = start_date + month | |||
if not self.annual_raise_start_date: | |||
duration_to_add = 13 - start_date.month | |||
months = dateutil.relativedelta.relativedelta(months = duration_to_add) | |||
self.annual_raise_start_date = start_date + months | |||
self.annual_raise_start_date = self.annual_raise_start_date.strftime('%Y-%m-%d') | |||
annual_raise_start_date = datetime.datetime.strptime(str(self.annual_raise_start_date), "%Y-%m-%d") | |||
service_charge_start_date = datetime.datetime.strptime(str(self.service_charge_start_date), "%Y-%m-%d") | |||
frequency = 0 | |||
if self.type == 'Customized c': | |||
if self.payments_scheduling: | |||
frequency = self.payments_scheduling | |||
else: | |||
if self.type == 'Monthly': | |||
frequency = 1 | |||
if self.type == 'Quarterly': | |||
frequency = 4 | |||
if self.type == 'Half Yearly': | |||
frequency = 6 | |||
if self.type == 'Annually': | |||
frequency = 12 | |||
annual_raise_amount = self.annual_raise_amount | |||
rent = (self.total_rent_per_month if not self.split_indoor_from_outdoor_rent else self.indoor_rent_month) | |||
year = annual_raise_start_date.year | |||
service_year = start_date.year | |||
service_charge =0.0 | |||
if self.split_indoor_from_outdoor_service: | |||
service_charge = self.service_charge_per_month or 0 | |||
else: | |||
service_charge = self.total_services_rent or 0 | |||
flag=1 | |||
service_charge_frequency = 1 | |||
if self.service_charges_type == 'Annually': | |||
service_charge_frequency = 12 | |||
if flt(service_charge) > 0 : | |||
for row in rrule(MONTHLY, interval=service_charge_frequency, dtstart=start_date, until=end_date): | |||
if (self.service_raise_type == "Annual Regular"): | |||
if row.month == service_charge_start_date.month and row.year >= service_charge_start_date.year: | |||
# if row.year >service_year: | |||
service_year=row.year | |||
if self.annual_service_charges == "Percentage": | |||
service_charge += service_charge / 100 * int((self.amount if self.amount else "0")) | |||
else: | |||
service_charge += int(self.amount) | |||
if (self.service_raise_type == "Annual Irregular"): | |||
ourdoor_service_dict = {} | |||
for sub_row in self.service_raise_details: | |||
date = datetime.datetime.strptime(sub_row.date, "%Y-%m-%d") | |||
date = date.strftime("%d-%m-%Y") | |||
ourdoor_service_dict[date] = f'{sub_row.annual_raise_type}_{sub_row.annual_raise_amount}' | |||
month = '{:02d}'.format(row.month) | |||
day = '{:02d}'.format(row.day) | |||
fieldname = f'{day}-{month}-{row.year}' | |||
if fieldname in ourdoor_service_dict and ourdoor_service_dict[fieldname]: | |||
splitted_field = ourdoor_service_dict[fieldname].split("_") | |||
annual_raise_type = splitted_field[0] | |||
annual_raise_amount = splitted_field[1] | |||
# print("===================>" + str(annual_raise_amount)) | |||
if annual_raise_type == "Percentage": | |||
service_charge += service_charge / 100 * int(annual_raise_amount) | |||
else: | |||
service_charge += int(annual_raise_amount) | |||
self.append('payments', { | |||
'date': row.date(), | |||
'amount': service_charge or 0, | |||
'reason':'Services Charges'+("" if not self.split_indoor_from_outdoor_service else " - InDoor") | |||
}) | |||
if self.split_indoor_from_outdoor_service: | |||
service_charge = self.outdoor_service_charge_per_month | |||
year = service_charge_start_date.year | |||
service_year = start_date.year | |||
if service_charge > 0: | |||
for row in rrule(MONTHLY, interval=service_charge_frequency, dtstart=start_date, until=end_date): | |||
if (self.service_raise_type == "Annual Regular"): | |||
if row.month == service_charge_start_date.month and row.year >= service_charge_start_date.year: | |||
# if row.year > service_year: | |||
service_year = row.year | |||
if self.annual_service_charges == "Percentage": | |||
service_charge += service_charge / 100 * int(self.amount) | |||
else: | |||
service_charge += int(self.amount) | |||
if (self.service_raise_type == "Annual Irregular"): | |||
ourdoor_service_dict = {} | |||
for sub_row in self.service_raise_details: | |||
date = datetime.datetime.strptime(sub_row.date, "%Y-%m-%d") | |||
date = date.strftime("%d-%m-%Y") | |||
ourdoor_service_dict[date] = f'{sub_row.annual_raise_type}_{sub_row.annual_raise_amount}' | |||
month = '{:02d}'.format(row.month) | |||
day = '{:02d}'.format(row.day) | |||
fieldname = f'{day}-{month}-{row.year}' | |||
if fieldname in ourdoor_service_dict and ourdoor_service_dict[fieldname]: | |||
splitted_field = ourdoor_service_dict[fieldname].split("_") | |||
annual_raise_type = splitted_field[0] | |||
annual_raise_amount = splitted_field[1] | |||
# print("===================>" + str(annual_raise_amount)) | |||
if annual_raise_type == "Percentage": | |||
service_charge += service_charge / 100 * int(annual_raise_amount) | |||
else: | |||
service_charge += int(annual_raise_amount) | |||
self.append('payments', { | |||
'date': row.date(), | |||
'amount': service_charge or 0, | |||
'reason': 'Services Charges'+" - " +"OutDoor" | |||
}) | |||
for row in rrule(MONTHLY, interval=frequency, dtstart=start_date, until=end_date): | |||
if(self.annual_raise == "Annual Regular"): | |||
if row.year >= annual_raise_start_date.year: | |||
#if row.month >= annual_raise_start_date.month or row.year > annual_raise_start_date.year: | |||
if row.month == annual_raise_start_date.month and row.year >= annual_raise_start_date.year: | |||
if row.year > year : | |||
year=row.year | |||
flag=1 | |||
if flag == 1: | |||
if self.annual_raise_type == "Percentage": | |||
rent += rent / 100 * int(annual_raise_amount) | |||
else: | |||
rent += int(annual_raise_amount) | |||
flag = 0 | |||
if(self.annual_raise == "Annual Irregular"): | |||
contract_dict = {} | |||
for sub_row in self.contract_annual_raise: | |||
date = datetime.datetime.strptime(sub_row.date, "%Y-%m-%d") | |||
date = date.strftime("%d-%m-%Y") | |||
contract_dict[date] = f'{sub_row.annual_raise_type}_{sub_row.annual_raise_amount}' | |||
month = '{:02d}'.format(row.month) | |||
day = '{:02d}'.format(row.day) | |||
fieldname = f'{day}-{month}-{row.year}' | |||
if fieldname in contract_dict and contract_dict[fieldname]: | |||
splitted_field = contract_dict[fieldname].split("_") | |||
annual_raise_type = splitted_field[0] | |||
annual_raise_amount = splitted_field[1] | |||
# print("===================>" + str(annual_raise_amount)) | |||
if annual_raise_type == "Percentage": | |||
rent += rent / 100 * int(annual_raise_amount) | |||
else: | |||
rent += int(annual_raise_amount) | |||
self.append('payments', { | |||
'date': row.date(), | |||
'amount': rent or 0, | |||
'reason':'Rent'+(' - indoor' if self.split_indoor_from_outdoor_rent else '') | |||
}) | |||
if self.split_indoor_from_outdoor_rent: | |||
flag = 1 | |||
rent = self.outdoor_rent_month | |||
if rent > 0: | |||
for row in rrule(MONTHLY, interval=frequency, dtstart=start_date, until=end_date): | |||
if (self.annual_raise == "Annual Regular"): | |||
if row.year >= annual_raise_start_date.year: | |||
#if row.month >= annual_raise_start_date.month or row.year > annual_raise_start_date.year: | |||
if row.month == annual_raise_start_date.month and row.year >= annual_raise_start_date.year: | |||
if row.year > year: | |||
year = row.year | |||
flag = 1 | |||
if flag == 1: | |||
if self.annual_raise_type == "Percentage": | |||
rent += rent / 100 * int(annual_raise_amount) | |||
else: | |||
rent += int(annual_raise_amount) | |||
flag = 0 | |||
if (self.annual_raise == "Annual Irregular"): | |||
contract_dict = {} | |||
for sub_row in self.contract_annual_raise: | |||
date = datetime.datetime.strptime(sub_row.date, "%Y-%m-%d") | |||
date = date.strftime("%d-%m-%Y") | |||
contract_dict[date] = f'{sub_row.annual_raise_type}_{sub_row.annual_raise_amount}' | |||
month = '{:02d}'.format(row.month) | |||
day = '{:02d}'.format(row.day) | |||
fieldname = f'{day}-{month}-{row.year}' | |||
if fieldname in contract_dict and contract_dict[fieldname]: | |||
splitted_field = contract_dict[fieldname].split("_") | |||
annual_raise_type = splitted_field[0] | |||
annual_raise_amount = splitted_field[1] | |||
if annual_raise_type == "Percentage": | |||
rent += rent / 100 * int(annual_raise_amount) | |||
else: | |||
rent += int(annual_raise_amount) | |||
self.append('payments', { | |||
'date': row.date(), | |||
'amount': rent or 0, | |||
'reason': 'Rent' + ' - outdoor' | |||
}) | |||
if not self.is_new(): | |||
self.save() | |||
def on_cancel(self): | |||
frappe.db.set_value("Unit", self.unit, "status", "Vacant") | |||
def create_row_invoice(self,rowid): | |||
create_sales_invoice(self.name,rowid) | |||
def get_brand_names(self): | |||
list_items = [] | |||
brands = frappe.get_all("Tenant Brand Name", filters={"parent": self.renter}, fields=['tenant_brand_name'], order_by="tenant_brand_name") | |||
if brands: | |||
for item in brands: | |||
list_items.append(item["tenant_brand_name"]) | |||
return list_items | |||
def update_duration(self): | |||
duration = self.get_dates_diff(self.rent_start_date,self.rent_end_date) | |||
# frappe.msgprint(str(duration)) | |||
duration_months = (cint(duration["years"]) * 12) + cint(duration["months"]) + (1 if cint(duration["days"]) > 0 or getdate(self.rent_end_date).day == 1 else 0) | |||
# frappe.msgprint(str(duration_months)) | |||
self.duration = duration_months | |||
return duration_months | |||
def get_dates_diff(self,a, b): | |||
a = getdate(a) | |||
b = getdate(b) | |||
diff_dict = {} | |||
# a = datetime(a.year, a.month, a.day) | |||
# b = datetime(b.year, b.month, b.day) | |||
delta = dateutil.relativedelta.relativedelta(b, a) | |||
diff_dict["years"] = delta.years | |||
diff_dict["months"] = delta.months | |||
diff_dict["days"] = delta.days | |||
return diff_dict | |||
def create_sales_invoice(docname="",rowid=""): | |||
print("Starting Creation..........") | |||
condiction = "" | |||
if docname and rowid: | |||
row_doc = frappe.get_doc("Contract Payments",rowid) | |||
condiction = " and C.parent = '%s' " % docname | |||
# condiction += " and C.`name` = '%s' " % rowid | |||
condiction += " and C.date = '%s' " % row_doc.date | |||
invoices = frappe.db.sql(""" | |||
select *,P.`name` contract_name,C.date invoice_date,C.amount row_amount | |||
from `tabProperty Contract` P | |||
inner JOIN | |||
`tabContract Payments` C | |||
on P.`name` = C.parent | |||
-- and CURRENT_DATE() >= C.date | |||
and P.rent_item is not NULL | |||
and P.service_item is not NULL | |||
-- and P.docstatus = 1 | |||
and C.invoice is Null | |||
and C.amount > 0 | |||
{0} | |||
order by date | |||
""".format(condiction),as_dict=True,debug=True) | |||
if invoices: | |||
# for invoice in invoices: | |||
# s_name = create_sales_invoices(invoice) | |||
# print(str(s_name.name)+" Invoice Created.") | |||
s_name = create_sales_invoices(invoices) | |||
print("Finished.") | |||
def create_sales_invoices(invoices): | |||
# frappe.throw(str(args)) | |||
default_company = frappe.db.get_default("Company") | |||
si = frappe.new_doc("Sales Invoice") | |||
if isinstance(invoices,list): | |||
args = frappe._dict(invoices[0]) | |||
else: | |||
args = frappe._dict(invoices) | |||
invoice_date = args.date or nowdate() | |||
si.posting_date = invoice_date | |||
debit_to = frappe.db.get_value("Company", default_company, 'default_receivable_account') | |||
if debit_to: | |||
si.debit_to = debit_to # Default Receivable Account | |||
else: | |||
frappe.throw(_("Please set Default Receivable Account in Company " + default_company)) | |||
si.set_posting_time = 1 | |||
si.postint_date = args.invoice_date | |||
si.due_date = args.invoice_date | |||
si.customer = args.renter | |||
si.tax_id = frappe.db.get_value("Customer",args.renter,"tax_id") | |||
si.debit_to = debit_to | |||
print(str(si.postint_date)+"================================================="+str(si.due_date)) | |||
#Accounting Dimensions | |||
si.property = args.property_name | |||
si.unit = args.unit | |||
si.property_contract = args.contract_name | |||
invoice_curerncy = frappe.db.get_value('Customer', args.renter, "default_currency") or frappe.get_cached_value('Company', default_company, "default_currency") | |||
si.currency=invoice_curerncy | |||
conversion_rate = 1 | |||
if invoice_curerncy !="EGP": | |||
conversion_rate = get_conversion_rate(invoice_curerncy,invoice_date) | |||
if conversion_rate == 0: | |||
message = _("Please Insert Currency Exchange for day {0}".format(invoice_date)) | |||
frappe.throw(frappe.bold(message)) | |||
si.conversion_rate = conversion_rate | |||
tax_list = [] | |||
old_template = "" | |||
for item in invoices: | |||
default_income_account = None | |||
item_income_account = frappe.db.get_value("Item Default", {"parent":(item.rent_item if item.reason =="Rent" else item.service_item)}, 'income_account') | |||
company_default_income_account = frappe.db.get_value("Company", default_company, 'default_income_account') | |||
if item_income_account: | |||
default_income_account = item_income_account | |||
elif company_default_income_account: | |||
default_income_account = company_default_income_account | |||
else: | |||
frappe.throw(_("Please set Default Income Account in Company " + default_company)) | |||
cost_center = frappe.db.get_value("Company", default_company, 'cost_center') | |||
if not cost_center: | |||
frappe.throw(_("Please set Default Cost Center in Company " + default_company)) | |||
tax_template_name = "" | |||
if item.reason =="Services Charges" and item.service_sales_taxes_and_charges_template: | |||
tax_template_name = item.service_sales_taxes_and_charges_template | |||
elif item.reason =="Rent" and item.rent_sales_taxes_and_charges_template: | |||
tax_template_name = item.rent_sales_taxes_and_charges_template | |||
si.append("items", { | |||
"item_code": (item.rent_item if item.reason =="Rent" else item.service_item) , | |||
"item_name": (item.rent_item_name if item.reason =="Rent" else item.service_item), | |||
"qty": 1, | |||
"item_tax_template": (tax_template_name if tax_template_name else "") , | |||
"rate": item.row_amount , | |||
"uom": item.uom or "Unit", | |||
"stock_uom": item.uom or "Unit", | |||
"income_account": default_income_account,# Default Income Account | |||
"cost_center": cost_center , | |||
"conversion_factor": 1, | |||
"description" : item.reason+" for contract "+ str(item.contract_name) | |||
}) | |||
if tax_template_name: | |||
if old_template=="": | |||
old_template = tax_template_name | |||
tax_data = frappe.db.sql(""" | |||
select * | |||
from `tabItem Tax Template Detail` | |||
where parent='{tax_template_name}' | |||
""".format(tax_template_name=tax_template_name),as_dict=True,debug=False) | |||
if tax_data: | |||
tax_data = tax_data[0] | |||
if old_template == tax_template_name: | |||
tax_list = [] | |||
tax_list.append({ | |||
"charge_type":"On Net Total", | |||
"account_head":tax_data["tax_type"], | |||
"description":tax_data["parent"], | |||
"rate": 0 , #tax_data["tax_rate"], | |||
"tax_amount":flt(tax_data["tax_rate"]) * flt(item.row_amount), | |||
"total":(flt(tax_data["tax_rate"]) * flt(item.row_amount)) + flt(item.row_amount), | |||
"base_tax_amount":flt(tax_data["tax_rate"]) * flt(item.row_amount), | |||
"base_total":(flt(tax_data["tax_rate"]) * flt(item.row_amount)) + flt(item.row_amount) | |||
}) | |||
for item in tax_list: | |||
si.append("taxes",item) | |||
Sinv_ID = None | |||
try: | |||
Sinv_ID = si.insert(ignore_mandatory = True) | |||
for row in invoices: | |||
frappe.db.sql("""update `tabContract Payments` set invoice = '{0}' where `name` = '{1}' """.format(Sinv_ID.name,row.name),debug=True) | |||
return Sinv_ID | |||
except Exception as e: | |||
print("Error......"+str(e)) | |||
frappe.throw(_(e)) | |||
def get_conversion_rate(invoice_curerncy,invoice_date): | |||
conversion_rate = 0 | |||
exchange_rate = frappe.db.sql(""" | |||
select exchange_rate | |||
from `tabCurrency Exchange` | |||
where from_currency ='{invoice_curerncy}' | |||
and to_currency='EGP' | |||
and date ='{invoice_date}' | |||
""".format(invoice_curerncy=invoice_curerncy,invoice_date=invoice_date),as_dict=True) | |||
if exchange_rate: | |||
conversion_rate = exchange_rate[0]["exchange_rate"] | |||
return conversion_rate | |||
def update_unit_status(): | |||
units = frappe.db.get_list("Property Contract",filters={"docstatus":1,"rent_end_date":getdate()},fields=["unit"]) | |||
if units: | |||
for unit in units: | |||
frappe.db.set_value("Unit", unit["unit"], "status", "Vacant") | |||
def update_unit_status_basd_on_reservation(): | |||
print("==========================starting============================") | |||
units = frappe.db.get_list("Reservations",filters={"docstatus":1,"reservation_end":["<",get_datetime()]},fields=["unit"]) | |||
if units: | |||
for unit in units: | |||
frappe.db.set_value("Unit", unit["unit"], "status", "Vacant") | |||
print("==========================Finished============================") |
@@ -0,0 +1,351 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Property Contract', { | |||
onload: function (frm) { | |||
get_brand_names(frm) | |||
}, | |||
generate_payment_scheduale: function (frm) { | |||
frm.doc.payment = [] | |||
frappe.call({ | |||
method: 'add_payment', | |||
doc: frm.doc, | |||
callback: function (res) { | |||
frappe.show_alert('Generated Successfully') | |||
cur_frm.reload_doc() | |||
} | |||
}) | |||
}, | |||
renter: function (frm) { | |||
get_brand_names(frm) | |||
}, | |||
refresh: function (frm) { | |||
get_brand_names(frm) | |||
frm.set_query('property_name', () => { | |||
return { | |||
filters: { | |||
property_type: frm.doc.property_type | |||
} | |||
} | |||
}) | |||
frm.set_query('unit', () => { | |||
return { | |||
filters: { | |||
unit_type: frm.doc.unit_type, | |||
property: frm.doc.property_name | |||
} | |||
} | |||
}) | |||
frm.set_query('rent_item', () => { | |||
return { | |||
filters: { | |||
is_sales_item: 1 | |||
} | |||
} | |||
}) | |||
frm.set_query('service_item', () => { | |||
return { | |||
filters: { | |||
is_sales_item: 1 | |||
} | |||
} | |||
}) | |||
frm.clear_custom_buttons() | |||
if (frm.doc.docstatus == 0 && !frm.is_new()) { | |||
frm.add_custom_button(__("Generate Payment Scheduale"), function () { | |||
frm.trigger('generate_payment_scheduale'); | |||
}); | |||
} | |||
if (frm.doc.docstatus == 1 && frm.doc.status != "Hold") { | |||
frm.add_custom_button("Hold Contract", () => { | |||
frappe.call({ | |||
method: "muezzin.api.property_contract.change_contract_status", | |||
args: { | |||
doc: frm.doc, | |||
status: "Hold" | |||
}, | |||
callback: () => { | |||
frm.reload_doc(); | |||
} | |||
}) | |||
}) | |||
} | |||
if (frm.doc.docstatus == 1 && frm.doc.status == "Hold") { | |||
frm.add_custom_button("Release Contract", () => { | |||
frappe.call({ | |||
method: "muezzin.api.property_contract.change_contract_status", | |||
args: { | |||
doc: frm.doc, | |||
status: "Active" | |||
}, | |||
callback: () => { | |||
frm.reload_doc(); | |||
} | |||
}) | |||
}) | |||
} | |||
}, | |||
rent_start_date: function (frm) { | |||
update_duration(frm) | |||
// if (frm.doc.docstatus == 0 && !frm.is_new()) { | |||
// frm.trigger('generate_payment_scheduale'); | |||
// } | |||
}, | |||
rent_end_date: function (frm) { | |||
update_duration(frm) | |||
// if (frm.doc.docstatus == 0 && !frm.is_new()) { | |||
// frm.trigger('generate_payment_scheduale'); | |||
// } | |||
}, | |||
// annual_raise_start_date: function (frm) { | |||
// if (frm.doc.docstatus == 0 && !frm.is_new()) { | |||
// frm.trigger('generate_payment_scheduale'); | |||
// } | |||
// }, | |||
// service_charge_start_date: function (frm) { | |||
// if (frm.doc.docstatus == 0 && !frm.is_new()) { | |||
// frm.trigger('generate_payment_scheduale'); | |||
// } | |||
// }, | |||
property_type: function (frm) { | |||
frm.doc.property_name = null; | |||
frm.refresh_field('property_name'); | |||
}, | |||
unit_type: function (frm) { | |||
frm.doc.property_name = null; | |||
frm.refresh_field('unit'); | |||
}, | |||
// duration: function(frm) { | |||
// update_payment(frm); | |||
// update_annual_raise_amount(frm); | |||
// }, | |||
// type: function(frm) { | |||
// update_payment(frm); | |||
// }, | |||
// payments_scheduling: function(frm) { | |||
// update_payment(frm); | |||
// }, | |||
unit: function (frm) { | |||
update_total_unit_area(frm); | |||
}, | |||
service_indoor_area: function (frm) { | |||
update_service_charge_per_month(frm); | |||
}, | |||
service_charge_sqm: function (frm) { | |||
update_service_charge_per_month(frm); | |||
}, | |||
outdoor_service_charge_per_month: function (frm) { | |||
update_total_services_rent(frm) | |||
update_total_rent(frm); | |||
// update_total_rent_month(frm); | |||
update_total_services_rent(frm) | |||
update_outdoor_service_charge_sqm(frm); | |||
}, | |||
service_outdoor_area: function (frm) { | |||
// update_outdoor_service_charge_sqm(frm); | |||
}, | |||
outdoor_service_charge_sqm: function (frm) { | |||
update_outdoor_service_charge_sqm(frm); | |||
}, | |||
indoor_area: function (frm) { | |||
update_indoor_rent_month(frm); | |||
}, | |||
rent_per_sqm: function (frm) { | |||
update_indoor_rent_month(frm); | |||
}, | |||
indoor_rent_month: function (frm) { | |||
update_total_rent_month(frm); | |||
}, | |||
// outdoor_service_charge_per_month: function(frm) { | |||
// update_total_rent_month(frm); | |||
// }, | |||
outdoor_area: function (frm) { | |||
update_outdoor_rent_month(frm); | |||
}, | |||
outdoor_rent_sqm: function (frm) { | |||
update_outdoor_rent_month(frm); | |||
}, | |||
outdoor_rent_month: function (frm) { | |||
update_total_rent_month(frm); | |||
}, | |||
total_rent_per_month: function (frm) { | |||
update_total_rent(frm); | |||
}, | |||
service_charge_per_month: function (frm) { | |||
update_total_services_rent(frm) | |||
update_total_rent(frm); | |||
}, | |||
total_rent: function (frm) { | |||
if (frm.doc.total_rent) { | |||
frm.set_value('annualized_rent', frm.doc.total_rent * 12); | |||
} | |||
} | |||
}); | |||
frappe.ui.form.on('Contract Payments', { | |||
create_invoice: function (frm, cdt, cdn) { | |||
var row = locals[cdt][cdn]; | |||
if (!row.invoice) { | |||
frm.call({ | |||
method: 'create_row_invoice', | |||
doc: frm.doc, | |||
args: {rowid: cdn}, | |||
callback: function (res) { | |||
frm.reload_doc(); | |||
} | |||
}) | |||
} else { | |||
frappe.throw(__('Invoice Already Created..')) | |||
} | |||
} | |||
}) | |||
const update_payment = function (frm) { | |||
if (!frm.doc.rent_start_date) { | |||
frm.doc.duration = null; | |||
frm.refresh_field('duration'); | |||
frappe.msgprint('Enter Rent Start Date.') | |||
} else { | |||
if (frm.doc.type && frm.doc.duration) { | |||
frm.call('add_payment'); | |||
frm.refresh_field('payments'); | |||
} else { | |||
frm.doc.payments = []; | |||
frm.refresh_field('payments'); | |||
} | |||
} | |||
} | |||
const update_annual_raise_amount = function (frm) { | |||
if (!frm.doc.rent_start_date) { | |||
frm.doc.duration = null; | |||
frm.refresh_field('duration'); | |||
frappe.msgprint('Enter Rent Start Date.') | |||
} else { | |||
if (frm.doc.annual_raise === 'Annual Irregular' && frm.doc.duration) { | |||
frm.call('add_contract_annual_raise'); | |||
frm.refresh_field('contract_annual_raise'); | |||
} else { | |||
frm.doc.contract_annual_raise = []; | |||
frm.refresh_field('contract_annual_raise'); | |||
} | |||
} | |||
} | |||
// const update_service_charge = function(frm) { | |||
// if(frm.doc.gla && frm.doc.service_charge_sqm) { | |||
// frm.set_value('service_charge_per_month', frm.doc.gla * frm.doc.service_charge_sqm) | |||
// } | |||
// } | |||
const update_total_rent_month = function (frm) { | |||
if (frm.doc.indoor_rent_month >= 0 && frm.doc.outdoor_rent_month >= 0) { | |||
frm.set_value('total_rent_per_month', flt(frm.doc.indoor_rent_month) + flt(frm.doc.outdoor_rent_month) + flt(frm.doc.outdoor_service_charge_per_month)); | |||
} | |||
} | |||
const update_total_rent = function (frm) { | |||
if (frm.doc.total_rent_per_month >= 0 && frm.doc.service_charge_per_month >= 0) { | |||
frm.set_value('total_rent', flt(frm.doc.total_rent_per_month) + flt(frm.doc.service_charge_per_month) + flt(frm.doc.outdoor_service_charge_per_month)); | |||
} | |||
} | |||
const update_outdoor_rent_month = function (frm) { | |||
// if (frm.doc.outdoor_area && frm.doc.outdoor_rent_sqm) { | |||
frm.set_value('outdoor_rent_month', frm.doc.outdoor_area * frm.doc.outdoor_rent_sqm); | |||
// } | |||
} | |||
const update_indoor_rent_month = function (frm) { | |||
if (frm.doc.indoor_area && frm.doc.rent_per_sqm) { | |||
frm.set_value('indoor_rent_month', frm.doc.indoor_area * frm.doc.rent_per_sqm); | |||
} | |||
} | |||
const update_total_unit_area = function (frm) { | |||
// if (frm.doc.gla && frm.doc.service_charge_sqm) { | |||
frm.set_value('gla', frm.doc.outdoor_area + frm.doc.indoor_area); | |||
refresh_field('gla') | |||
// } | |||
} | |||
const update_service_charge_per_month = function (frm) { | |||
// if (frm.doc.gla && frm.doc.service_charge_sqm) { | |||
frm.set_value('service_charge_per_month', frm.doc.service_indoor_area * frm.doc.service_charge_sqm); | |||
// } | |||
} | |||
const update_total_services_rent = function (frm) { | |||
frm.set_value('total_services_rent', flt(frm.doc.outdoor_service_charge_per_month) + flt(frm.doc.service_charge_per_month)); | |||
} | |||
const update_outdoor_service_charge_sqm = function (frm) { | |||
// if (frm.doc.outdoor_service_charge_sqm && frm.doc.service_outdoor_area) { | |||
// frm.set_value('outdoor_service_charge_sqm',0) | |||
// frm.set_value('outdoor_rent_sqm',0) | |||
frm.set_value('outdoor_service_charge_per_month', frm.doc.outdoor_service_charge_sqm * frm.doc.service_outdoor_area); | |||
// refresh_field('outdoor_rent_sqm') | |||
// refresh_field('outdoor_service_charge_per_month') | |||
// } | |||
} | |||
const update_duration = function (frm) { | |||
if (frm.doc.rent_start_date && frm.doc.rent_end_date) { | |||
// let duration = get_time_diff(frm.doc.rent_end_date, frm.doc.rent_start_date) | |||
// frm.set_value('duration', duration) | |||
frappe.call({ | |||
method:'update_duration', | |||
doc:frm.doc, | |||
callback:function(r){ | |||
if(r.message){ | |||
frm.set_value('duration', r.message) | |||
refresh_field('duration') | |||
} | |||
} | |||
}) | |||
} | |||
} | |||
const get_time_diff = (end, start) => { | |||
const end_datetime = new Date(end) | |||
const start_datetime = new Date(start) | |||
const time_diff = end_datetime - start_datetime | |||
const months = time_diff / 2592000000 | |||
return Math.round(months) | |||
} | |||
let get_brand_names = function (frm) { | |||
if (frm.doc.renter) { | |||
frappe.call({ | |||
method: "muezzin.property_management.doctype.property_contract.property_contract.get_brand_names", | |||
args: { | |||
renter:frm.doc.renter | |||
}, | |||
callback: function (data) { | |||
if (data.message) { | |||
let options = data.message; | |||
let options_new = options.join("\n"); | |||
frm.set_df_property('brand_name', 'options', options_new); | |||
} | |||
} | |||
}) | |||
} | |||
} |
@@ -0,0 +1,745 @@ | |||
{ | |||
"autoname": "field:lease", | |||
"creation": "2021-02-02 11:52:23.747179", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"main_data_section", | |||
"lease", | |||
"status", | |||
"date_type", | |||
"opening_date", | |||
"rent_start_date", | |||
"renter", | |||
"brand_name", | |||
"tenant_name_currency", | |||
"is_vat_applied", | |||
"column_break_7", | |||
"writing_date", | |||
"script", | |||
"rent_end_date", | |||
"migration_migrate_to_accounts", | |||
"grace_period_day", | |||
"revenue_sharing", | |||
"insurance_policy", | |||
"choose_units_section", | |||
"property_type", | |||
"unit_type", | |||
"column_break_14", | |||
"property_name", | |||
"unit", | |||
"items_section", | |||
"rent_item", | |||
"rent_item_name", | |||
"rent_sales_taxes_and_charges_template", | |||
"column_break_22", | |||
"service_item", | |||
"service_item_name", | |||
"service_sales_taxes_and_charges_template", | |||
"rent_details_section", | |||
"indoor_area", | |||
"rent_per_sqm", | |||
"indoor_rent_month", | |||
"column_break_24", | |||
"service_indoor_area", | |||
"service_charge_sqm", | |||
"service_charge_per_month", | |||
"section_break_28", | |||
"outdoor_area", | |||
"outdoor_rent_sqm", | |||
"outdoor_rent_month", | |||
"column_break_32", | |||
"service_outdoor_area", | |||
"outdoor_service_charge_sqm", | |||
"outdoor_service_charge_per_month", | |||
"totals_section", | |||
"total_rent_per_month", | |||
"total_rent", | |||
"annualized_rent", | |||
"column_break_25", | |||
"gla", | |||
"total_services_rent", | |||
"lease_sent", | |||
"lease_signed", | |||
"split_indoor_from_outdoor_rent", | |||
"split_indoor_from_outdoor_service", | |||
"payments_scheduling_section", | |||
"duration", | |||
"payments_scheduling", | |||
"annual_raise_start_date", | |||
"annual_raise_type", | |||
"column_break_19", | |||
"type", | |||
"annual_raise", | |||
"annual_raise_amount", | |||
"section_break_50", | |||
"contract_annual_raise", | |||
"section_break_23", | |||
"service_raise_type", | |||
"service_raise_details", | |||
"annual_service_charges", | |||
"amount", | |||
"column_break_48", | |||
"service_charges_type", | |||
"service_charge_start_date", | |||
"section_break_25", | |||
"payments", | |||
"expenses_section", | |||
"maintenance_services_payment", | |||
"water_payment", | |||
"clining", | |||
"owner_management", | |||
"electricity_payment", | |||
"lease_payment", | |||
"column_break_29", | |||
"ms_type", | |||
"w_type", | |||
"c_type", | |||
"om_type", | |||
"e_type", | |||
"insurance_payment", | |||
"column_break_36", | |||
"ms_service", | |||
"w_service", | |||
"c_service", | |||
"om_service", | |||
"e_service", | |||
"marketing_fees", | |||
"amended_from" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "main_data_section", | |||
"fieldtype": "Section Break", | |||
"label": "Main Data" | |||
}, | |||
{ | |||
"fieldname": "lease", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Lease", | |||
"reqd": 1, | |||
"unique": 1 | |||
}, | |||
{ | |||
"fieldname": "date_type", | |||
"fieldtype": "Select", | |||
"in_list_view": 1, | |||
"label": "Date Type", | |||
"options": "Hijri\nGregorian", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "rent_start_date", | |||
"fieldtype": "Date", | |||
"in_list_view": 1, | |||
"label": "Rent start date", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "renter", | |||
"fieldtype": "Link", | |||
"label": "Legal Tenant Name", | |||
"options": "Customer" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "is_vat_applied", | |||
"fieldtype": "Check", | |||
"label": "Is Vat Applied" | |||
}, | |||
{ | |||
"fieldname": "column_break_7", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "writing_date", | |||
"fieldtype": "Date", | |||
"in_list_view": 1, | |||
"label": "Writing Date", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "migration_migrate_to_accounts", | |||
"fieldtype": "Check", | |||
"label": "Migration (Migrate to Accounts)" | |||
}, | |||
{ | |||
"fieldname": "script", | |||
"fieldtype": "Link", | |||
"label": "Script", | |||
"options": "Script" | |||
}, | |||
{ | |||
"fieldname": "grace_period_day", | |||
"fieldtype": "Data", | |||
"label": "Grace period (day)" | |||
}, | |||
{ | |||
"fieldname": "choose_units_section", | |||
"fieldtype": "Section Break", | |||
"label": "Choose Units" | |||
}, | |||
{ | |||
"fieldname": "property_type", | |||
"fieldtype": "Link", | |||
"label": "Property Type", | |||
"options": "Property Type" | |||
}, | |||
{ | |||
"fieldname": "column_break_14", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "property_name", | |||
"fieldtype": "Link", | |||
"label": "Property Name", | |||
"options": "Property", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "payments_scheduling_section", | |||
"fieldtype": "Section Break", | |||
"label": "Payments Scheduling" | |||
}, | |||
{ | |||
"fieldname": "duration", | |||
"fieldtype": "Int", | |||
"label": "Duration", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "annual_raise", | |||
"fieldtype": "Select", | |||
"label": "Annual raise", | |||
"options": "\nAnnual Regular\nAnnual Irregular" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.service_raise_type=='Annual Regular'", | |||
"fieldname": "column_break_19", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "type", | |||
"fieldtype": "Select", | |||
"label": "Type", | |||
"options": "Monthly\nQuarterly\nHalf Yearly\nAnnually\nCustomized c" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.type=='Customized c'", | |||
"description": "Ex: 3, means new payment every 3 months among lease duration", | |||
"fieldname": "payments_scheduling", | |||
"fieldtype": "Int", | |||
"label": "Payments Scheduling" | |||
}, | |||
{ | |||
"fieldname": "expenses_section", | |||
"fieldtype": "Section Break", | |||
"label": "Expenses" | |||
}, | |||
{ | |||
"fieldname": "lease_payment", | |||
"fieldtype": "Currency", | |||
"label": "Lease Payment", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "maintenance_services_payment", | |||
"fieldtype": "Currency", | |||
"label": "Maintenance Services Payment", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "water_payment", | |||
"fieldtype": "Currency", | |||
"label": "Water Payment", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "clining", | |||
"fieldtype": "Currency", | |||
"label": "Clining", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "owner_management", | |||
"fieldtype": "Currency", | |||
"label": "Owner Management", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "electricity_payment", | |||
"fieldtype": "Currency", | |||
"label": "Electricity Payment", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "column_break_29", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "insurance_payment", | |||
"fieldtype": "Currency", | |||
"label": "Insurance Payment", | |||
"options": "Currency" | |||
}, | |||
{ | |||
"fieldname": "ms_type", | |||
"fieldtype": "Select", | |||
"label": "Type", | |||
"options": "Annually\nWith Payments\nMonthly\nJust Once" | |||
}, | |||
{ | |||
"fieldname": "w_type", | |||
"fieldtype": "Select", | |||
"label": "Type", | |||
"options": "Annually\nWith Payments\nMonthly\nJust Once" | |||
}, | |||
{ | |||
"fieldname": "c_type", | |||
"fieldtype": "Select", | |||
"label": "Type", | |||
"options": "Annually\nWith Payments\nMonthly\nJust Once" | |||
}, | |||
{ | |||
"fieldname": "om_type", | |||
"fieldtype": "Select", | |||
"label": "Type", | |||
"options": "Annually\nWith Payments\nMonthly\nJust Once" | |||
}, | |||
{ | |||
"fieldname": "e_type", | |||
"fieldtype": "Select", | |||
"label": "Type", | |||
"options": "Annually\nWith Payments\nMonthly\nJust Once" | |||
}, | |||
{ | |||
"fieldname": "column_break_36", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "ms_service", | |||
"fieldtype": "Select", | |||
"label": "Service Provider", | |||
"options": "\nSarabi\nMaqawal\nMisry" | |||
}, | |||
{ | |||
"fieldname": "w_service", | |||
"fieldtype": "Select", | |||
"label": "Service Provider", | |||
"options": "\nSarabi\nMaqawal\nMisry" | |||
}, | |||
{ | |||
"fieldname": "c_service", | |||
"fieldtype": "Select", | |||
"label": "Service Provider", | |||
"options": "\nSarabi\nMaqawal\nMisry" | |||
}, | |||
{ | |||
"fieldname": "om_service", | |||
"fieldtype": "Select", | |||
"label": "Service Provider", | |||
"options": "\nSarabi\nMaqawal\nMisry" | |||
}, | |||
{ | |||
"fieldname": "e_service", | |||
"fieldtype": "Select", | |||
"label": "Service Provider", | |||
"options": "\nSarabi\nMaqawal\nMisry" | |||
}, | |||
{ | |||
"fieldname": "amended_from", | |||
"fieldtype": "Link", | |||
"label": "Amended From", | |||
"no_copy": 1, | |||
"options": "Property Contract", | |||
"print_hide": 1, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"depends_on": "eval:doc.annual_raise=='Annual Regular';", | |||
"fieldname": "annual_raise_amount", | |||
"fieldtype": "Data", | |||
"label": "Annual Raise Amount" | |||
}, | |||
{ | |||
"collapsible": 1, | |||
"fieldname": "section_break_23", | |||
"fieldtype": "Section Break", | |||
"label": "SERVICE CHARGES" | |||
}, | |||
{ | |||
"fieldname": "contract_annual_raise", | |||
"fieldtype": "Table", | |||
"label": "Annual Raise Details", | |||
"options": "Contract Annual Raise" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.duration>0;", | |||
"fieldname": "section_break_25", | |||
"fieldtype": "Section Break" | |||
}, | |||
{ | |||
"allow_on_submit": 1, | |||
"fieldname": "payments", | |||
"fieldtype": "Table", | |||
"label": "Payments", | |||
"options": "Contract Payments" | |||
}, | |||
{ | |||
"fieldname": "rent_details_section", | |||
"fieldtype": "Section Break", | |||
"label": "Rent Details" | |||
}, | |||
{ | |||
"fieldname": "rent_per_sqm", | |||
"fieldtype": "Currency", | |||
"label": "Rent (Per sqm)", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "outdoor_rent_sqm", | |||
"fieldtype": "Currency", | |||
"label": "Outdoor Rent (sqm)", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "total_rent_per_month", | |||
"fieldtype": "Currency", | |||
"label": "Total Rent per Month", | |||
"options": "tenant_name_currency", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "service_charge_sqm", | |||
"fieldtype": "Currency", | |||
"label": "Service Charge sqm", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "service_charge_per_month", | |||
"fieldtype": "Currency", | |||
"label": "Service Charge per Month", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "total_rent", | |||
"fieldtype": "Currency", | |||
"label": "Total Rent", | |||
"options": "tenant_name_currency", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "annualized_rent", | |||
"fieldtype": "Currency", | |||
"label": "Annualized Rent", | |||
"options": "tenant_name_currency", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "lease_sent", | |||
"fieldtype": "Check", | |||
"label": "Lease Sent" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "lease_signed", | |||
"fieldtype": "Check", | |||
"label": "Lease Signed" | |||
}, | |||
{ | |||
"fieldname": "column_break_22", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "marketing_fees", | |||
"fieldtype": "Currency", | |||
"label": "Marketing Fees", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "rent_end_date", | |||
"fieldtype": "Date", | |||
"label": "Rent End Date", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "indoor_rent_month", | |||
"fieldtype": "Currency", | |||
"label": "Indoor Rent (LE/Month)", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "outdoor_rent_month", | |||
"fieldtype": "Currency", | |||
"label": "Outdoor Rent (LE/Month)", | |||
"options": "tenant_name_currency" | |||
}, | |||
{ | |||
"fieldname": "unit_type", | |||
"fieldtype": "Link", | |||
"label": "Unit Type", | |||
"options": "Unit Type" | |||
}, | |||
{ | |||
"fetch_from": "unit.unit_area", | |||
"fieldname": "indoor_area", | |||
"fieldtype": "Float", | |||
"label": "Indoor Area", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fetch_from": "unit.outdoor_area", | |||
"fieldname": "outdoor_area", | |||
"fieldtype": "Float", | |||
"label": "Outdoor Area", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "gla", | |||
"fieldtype": "Float", | |||
"label": "GLA", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"depends_on": "eval:doc.annual_raise=='Annual Regular';", | |||
"fieldname": "annual_raise_type", | |||
"fieldtype": "Select", | |||
"label": "Annual Raise Type", | |||
"options": "\nAmount\nPercentage" | |||
}, | |||
{ | |||
"allow_on_submit": 1, | |||
"fieldname": "status", | |||
"fieldtype": "Select", | |||
"label": "Status", | |||
"options": "\nActive\nHold", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"depends_on": "eval:doc.annual_raise !='Annual Irregular'", | |||
"fieldname": "annual_raise_start_date", | |||
"fieldtype": "Date", | |||
"label": "Annual Raise Start Date" | |||
}, | |||
{ | |||
"fieldname": "service_charges_type", | |||
"fieldtype": "Select", | |||
"label": "Type", | |||
"options": "Monthly\nAnnually" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.service_raise_type=='Annual Regular'", | |||
"fieldname": "annual_service_charges", | |||
"fieldtype": "Select", | |||
"label": "Annual Raise Type", | |||
"options": "Percentage\nAmount" | |||
}, | |||
{ | |||
"fieldname": "column_break_48", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.service_raise_type=='Annual Regular'", | |||
"fieldname": "amount", | |||
"fieldtype": "Float", | |||
"label": "Amount" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.annual_raise=='Annual Irregular'", | |||
"fieldname": "section_break_50", | |||
"fieldtype": "Section Break" | |||
}, | |||
{ | |||
"fieldname": "unit", | |||
"fieldtype": "Link", | |||
"label": "Unit Name", | |||
"options": "Unit", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "split_indoor_from_outdoor_rent", | |||
"fieldtype": "Check", | |||
"label": "Split Indoor from Outdoor Rent" | |||
}, | |||
{ | |||
"fieldname": "column_break_24", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "section_break_28", | |||
"fieldtype": "Section Break" | |||
}, | |||
{ | |||
"fetch_from": "unit.outdoor_area", | |||
"fieldname": "service_outdoor_area", | |||
"fieldtype": "Float", | |||
"label": "Service Outdoor Area ", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "outdoor_service_charge_sqm", | |||
"fieldtype": "Float", | |||
"label": "Outdoor Service Charge SQM" | |||
}, | |||
{ | |||
"fieldname": "outdoor_service_charge_per_month", | |||
"fieldtype": "Float", | |||
"label": "Outdoor Service Charge per Month" | |||
}, | |||
{ | |||
"fieldname": "totals_section", | |||
"fieldtype": "Section Break", | |||
"label": "Totals" | |||
}, | |||
{ | |||
"fieldname": "column_break_32", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "split_indoor_from_outdoor_service", | |||
"fieldtype": "Check", | |||
"label": " Split Indoor from Outdoor Service" | |||
}, | |||
{ | |||
"fieldname": "total_services_rent", | |||
"fieldtype": "Currency", | |||
"label": "Total Services Rent", | |||
"options": "tenant_name_currency", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "items_section", | |||
"fieldtype": "Section Break", | |||
"label": "Items" | |||
}, | |||
{ | |||
"fieldname": "rent_item", | |||
"fieldtype": "Link", | |||
"label": "Rent Item", | |||
"options": "Item", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "service_item", | |||
"fieldtype": "Link", | |||
"label": "Service Item", | |||
"options": "Item", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "column_break_25", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fetch_from": "rent_item.item_name", | |||
"fieldname": "rent_item_name", | |||
"fieldtype": "Read Only", | |||
"label": "Rent Item Name" | |||
}, | |||
{ | |||
"fetch_from": "service_item.item_name", | |||
"fieldname": "service_item_name", | |||
"fieldtype": "Read Only", | |||
"label": "Service Item Name" | |||
}, | |||
{ | |||
"fetch_from": "unit.unit_area", | |||
"fieldname": "service_indoor_area", | |||
"fieldtype": "Float", | |||
"label": "Service Indoor Area ", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"default": "Today", | |||
"depends_on": "eval:doc.service_raise_type=='Annual Regular'", | |||
"fieldname": "service_charge_start_date", | |||
"fieldtype": "Date", | |||
"label": "Service Charge Start Date", | |||
"options": "Today" | |||
}, | |||
{ | |||
"fieldname": "service_raise_type", | |||
"fieldtype": "Select", | |||
"label": "Service Raise Type", | |||
"options": "\nAnnual Regular\nAnnual Irregular" | |||
}, | |||
{ | |||
"depends_on": "eval:doc.service_raise_type=='Annual Irregular'", | |||
"fieldname": "service_raise_details", | |||
"fieldtype": "Table", | |||
"label": "Service Raise Details", | |||
"options": "Contract Annual Raise" | |||
}, | |||
{ | |||
"default": "Today", | |||
"fieldname": "opening_date", | |||
"fieldtype": "Date", | |||
"label": "Opening date" | |||
}, | |||
{ | |||
"fieldname": "revenue_sharing", | |||
"fieldtype": "Data", | |||
"label": "Revenue sharing" | |||
}, | |||
{ | |||
"fieldname": "insurance_policy", | |||
"fieldtype": "Data", | |||
"label": "Insurance policy" | |||
}, | |||
{ | |||
"fieldname": "rent_sales_taxes_and_charges_template", | |||
"fieldtype": "Link", | |||
"label": "Rent Sales Taxes and Charges Template", | |||
"options": "Sales Taxes and Charges Template" | |||
}, | |||
{ | |||
"fieldname": "service_sales_taxes_and_charges_template", | |||
"fieldtype": "Link", | |||
"label": "Service Sales Taxes and Charges Template", | |||
"options": "Sales Taxes and Charges Template" | |||
}, | |||
{ | |||
"fieldname": "brand_name", | |||
"fieldtype": "Select", | |||
"label": "Tenant Brand Name" | |||
}, | |||
{ | |||
"default": "EGP", | |||
"fetch_from": "renter.default_currency", | |||
"fetch_if_empty": 1, | |||
"fieldname": "tenant_name_currency", | |||
"fieldtype": "Link", | |||
"label": "Tenant Name Currency", | |||
"options": "Currency" | |||
} | |||
], | |||
"is_submittable": 1, | |||
"modified": "2021-12-25 01:52:49.738569", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Property Contract", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"share": 1, | |||
"write": 1 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,545 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe import _ | |||
import datetime | |||
# from datetime import datetime, timedelta | |||
import dateutil | |||
import calendar | |||
from calendar import weekday, monthrange | |||
from collections import Counter | |||
from dateutil.relativedelta import relativedelta | |||
from dateutil.rrule import rrule, MONTHLY, YEARLY | |||
from frappe.model.document import Document | |||
from frappe.utils import flt, date_diff, getdate, cint, nowdate | |||
class PropertyContract(Document): | |||
def validate(self): | |||
if self.is_new(): | |||
self.add_payment() | |||
# self.add_contract_annual_raise() | |||
def before_submit(self): | |||
""" | |||
Validates if property already on rent between the from and to dates | |||
""" | |||
# Get Property Contaract if from date is between new from and new to date | |||
filters = { | |||
"rent_start_date": ["between", [self.rent_start_date, self.rent_end_date]], | |||
"docstatus": 1, | |||
"unit": self.unit, | |||
"status": ["!=", "Hold"] | |||
} | |||
property_contract = frappe.get_list("Property Contract", | |||
fields=["name"], | |||
filters=filters) | |||
if len(property_contract) > 0: | |||
frappe.throw( | |||
f"This property unit already contain a contract <a href='#Form/Property%20Contract/{property_contract[0].name}'>{property_contract[0].name}</a> that not ended yet.") | |||
# Get Property Contaract if to date is between new from and new to date | |||
filters = { | |||
"rent_end_date": ["between", [self.rent_start_date, self.rent_end_date]], | |||
"docstatus": 1, | |||
"unit": self.unit, | |||
"status": ["!=", "Hold"] | |||
} | |||
property_contract = frappe.get_list("Property Contract", | |||
fields=["name"], | |||
filters=filters) | |||
if len(property_contract) > 0: | |||
frappe.throw( | |||
f"This property unit already contain a contract <a href='#Form/Property%20Contract/{property_contract[0].name}'>{property_contract[0].name}</a> that not ended yet.") | |||
# Get Property Contaract if from date is after new from date and to date is before new to date | |||
filters = { | |||
"rent_start_date": ["<=", self.rent_start_date], | |||
"rent_end_date": [">=", self.rent_end_date], | |||
"docstatus": 1, | |||
"unit": self.unit, | |||
"status": ["!=", "Hold"] | |||
} | |||
property_contract = frappe.get_list("Property Contract", | |||
fields=["name"], | |||
filters=filters) | |||
if len(property_contract) > 0: | |||
frappe.throw( | |||
f"This property unit already contain a contract <a href='#Form/Property%20Contract/{property_contract[0].name}'>{property_contract[0].name}</a> that not ended yet.") | |||
diff_days = date_diff(self.rent_end_date, getdate()) | |||
if flt(diff_days) > 0: | |||
frappe.db.set_value("Unit", self.unit, "status", "Leased") | |||
@frappe.whitelist() | |||
def add_contract_annual_raise(self): | |||
self.contract_annual_raise = [] | |||
start_date = datetime.datetime.strptime(self.rent_start_date, "%Y-%m-%d") | |||
duration = self.duration - 1 if self.duration > 1 else self.duration | |||
month = dateutil.relativedelta.relativedelta(months=duration) | |||
end_date = start_date + month | |||
for row in rrule(YEARLY, dtstart=start_date, until=end_date): | |||
self.append('contract_annual_raise', { | |||
'date': row.date(), | |||
'amount': 0, | |||
}) | |||
@frappe.whitelist() | |||
def add_payment(self): | |||
self.payments = [] | |||
start_date = datetime.datetime.strptime(self.rent_start_date, "%Y-%m-%d") | |||
duration = self.duration - 1 if self.duration > 1 else self.duration | |||
month = dateutil.relativedelta.relativedelta(months=duration) | |||
end_date = start_date + month | |||
if not self.annual_raise_start_date: | |||
duration_to_add = 13 - start_date.month | |||
months = dateutil.relativedelta.relativedelta(months=duration_to_add) | |||
self.annual_raise_start_date = start_date + months | |||
self.annual_raise_start_date = self.annual_raise_start_date.strftime('%Y-%m-%d') | |||
annual_raise_start_date = datetime.datetime.strptime(str(self.annual_raise_start_date), "%Y-%m-%d") | |||
service_charge_start_date = datetime.datetime.strptime(str(self.service_charge_start_date), "%Y-%m-%d") | |||
frequency = 0 | |||
if self.type == 'Customized c': | |||
if self.payments_scheduling: | |||
frequency = self.payments_scheduling | |||
else: | |||
if self.type == 'Monthly': | |||
frequency = 1 | |||
if self.type == 'Quarterly': | |||
frequency = 4 | |||
if self.type == 'Half Yearly': | |||
frequency = 6 | |||
if self.type == 'Annually': | |||
frequency = 12 | |||
annual_raise_amount = self.annual_raise_amount | |||
rent = (self.total_rent_per_month if not self.split_indoor_from_outdoor_rent else self.indoor_rent_month) | |||
year = annual_raise_start_date.year | |||
service_year = start_date.year | |||
service_charge = 0.0 | |||
if self.split_indoor_from_outdoor_service: | |||
service_charge = self.service_charge_per_month or 0 | |||
else: | |||
service_charge = self.total_services_rent or 0 | |||
flag = 1 | |||
service_charge_frequency = 1 | |||
if self.service_charges_type == 'Annually': | |||
service_charge_frequency = 12 | |||
if flt(service_charge) > 0: | |||
for row in rrule(MONTHLY, interval=service_charge_frequency, dtstart=start_date, until=end_date): | |||
if (self.service_raise_type == "Annual Regular"): | |||
if row.month == service_charge_start_date.month and row.year >= service_charge_start_date.year: | |||
# if row.year >service_year: | |||
service_year = row.year | |||
if self.annual_service_charges == "Percentage": | |||
service_charge += service_charge / 100 * int((self.amount if self.amount else "0")) | |||
else: | |||
service_charge += int(self.amount) | |||
if (self.service_raise_type == "Annual Irregular"): | |||
ourdoor_service_dict = {} | |||
for sub_row in self.service_raise_details: | |||
date = datetime.datetime.strptime(sub_row.date, "%Y-%m-%d") | |||
date = date.strftime("%d-%m-%Y") | |||
ourdoor_service_dict[date] = f'{sub_row.annual_raise_type}_{sub_row.annual_raise_amount}' | |||
month = '{:02d}'.format(row.month) | |||
day = '{:02d}'.format(row.day) | |||
fieldname = f'{day}-{month}-{row.year}' | |||
if fieldname in ourdoor_service_dict and ourdoor_service_dict[fieldname]: | |||
splitted_field = ourdoor_service_dict[fieldname].split("_") | |||
annual_raise_type = splitted_field[0] | |||
annual_raise_amount = splitted_field[1] | |||
# print("===================>" + str(annual_raise_amount)) | |||
if annual_raise_type == "Percentage": | |||
service_charge += service_charge / 100 * int(annual_raise_amount) | |||
else: | |||
service_charge += int(annual_raise_amount) | |||
self.append('payments', { | |||
'date': row.date(), | |||
'amount': service_charge or 0, | |||
'reason': 'Services Charges' + ("" if not self.split_indoor_from_outdoor_service else " - InDoor") | |||
}) | |||
if self.split_indoor_from_outdoor_service: | |||
service_charge = self.outdoor_service_charge_per_month | |||
year = service_charge_start_date.year | |||
service_year = start_date.year | |||
if service_charge > 0: | |||
for row in rrule(MONTHLY, interval=service_charge_frequency, dtstart=start_date, until=end_date): | |||
if (self.service_raise_type == "Annual Regular"): | |||
if row.month == service_charge_start_date.month and row.year >= service_charge_start_date.year: | |||
# if row.year > service_year: | |||
service_year = row.year | |||
if self.annual_service_charges == "Percentage": | |||
service_charge += service_charge / 100 * int(self.amount) | |||
else: | |||
service_charge += int(self.amount) | |||
if (self.service_raise_type == "Annual Irregular"): | |||
ourdoor_service_dict = {} | |||
for sub_row in self.service_raise_details: | |||
date = datetime.datetime.strptime(sub_row.date, "%Y-%m-%d") | |||
date = date.strftime("%d-%m-%Y") | |||
ourdoor_service_dict[date] = f'{sub_row.annual_raise_type}_{sub_row.annual_raise_amount}' | |||
month = '{:02d}'.format(row.month) | |||
day = '{:02d}'.format(row.day) | |||
fieldname = f'{day}-{month}-{row.year}' | |||
if fieldname in ourdoor_service_dict and ourdoor_service_dict[fieldname]: | |||
splitted_field = ourdoor_service_dict[fieldname].split("_") | |||
annual_raise_type = splitted_field[0] | |||
annual_raise_amount = splitted_field[1] | |||
# print("===================>" + str(annual_raise_amount)) | |||
if annual_raise_type == "Percentage": | |||
service_charge += service_charge / 100 * int(annual_raise_amount) | |||
else: | |||
service_charge += int(annual_raise_amount) | |||
self.append('payments', { | |||
'date': row.date(), | |||
'amount': service_charge or 0, | |||
'reason': 'Services Charges' + " - " + "OutDoor" | |||
}) | |||
for row in rrule(MONTHLY, interval=frequency, dtstart=start_date, until=end_date): | |||
if (self.annual_raise == "Annual Regular"): | |||
if row.year >= annual_raise_start_date.year: | |||
# if row.month >= annual_raise_start_date.month or row.year > annual_raise_start_date.year: | |||
if row.month == annual_raise_start_date.month and row.year >= annual_raise_start_date.year: | |||
if row.year > year: | |||
year = row.year | |||
flag = 1 | |||
if flag == 1: | |||
if self.annual_raise_type == "Percentage": | |||
rent += rent / 100 * int(annual_raise_amount) | |||
else: | |||
rent += int(annual_raise_amount) | |||
flag = 0 | |||
if (self.annual_raise == "Annual Irregular"): | |||
contract_dict = {} | |||
for sub_row in self.contract_annual_raise: | |||
date = datetime.datetime.strptime(sub_row.date, "%Y-%m-%d") | |||
date = date.strftime("%d-%m-%Y") | |||
contract_dict[date] = f'{sub_row.annual_raise_type}_{sub_row.annual_raise_amount}' | |||
month = '{:02d}'.format(row.month) | |||
day = '{:02d}'.format(row.day) | |||
fieldname = f'{day}-{month}-{row.year}' | |||
if fieldname in contract_dict and contract_dict[fieldname]: | |||
splitted_field = contract_dict[fieldname].split("_") | |||
annual_raise_type = splitted_field[0] | |||
annual_raise_amount = splitted_field[1] | |||
# print("===================>" + str(annual_raise_amount)) | |||
if annual_raise_type == "Percentage": | |||
rent += rent / 100 * int(annual_raise_amount) | |||
else: | |||
rent += int(annual_raise_amount) | |||
self.append('payments', { | |||
'date': row.date(), | |||
'amount': rent or 0, | |||
'reason': 'Rent' + (' - indoor' if self.split_indoor_from_outdoor_rent else '') | |||
}) | |||
if self.split_indoor_from_outdoor_rent: | |||
flag = 1 | |||
rent = self.outdoor_rent_month | |||
if rent > 0: | |||
for row in rrule(MONTHLY, interval=frequency, dtstart=start_date, until=end_date): | |||
if (self.annual_raise == "Annual Regular"): | |||
if row.year >= annual_raise_start_date.year: | |||
# if row.month >= annual_raise_start_date.month or row.year > annual_raise_start_date.year: | |||
if row.month == annual_raise_start_date.month and row.year >= annual_raise_start_date.year: | |||
if row.year > year: | |||
year = row.year | |||
flag = 1 | |||
if flag == 1: | |||
if self.annual_raise_type == "Percentage": | |||
rent += rent / 100 * int(annual_raise_amount) | |||
else: | |||
rent += int(annual_raise_amount) | |||
flag = 0 | |||
if (self.annual_raise == "Annual Irregular"): | |||
contract_dict = {} | |||
for sub_row in self.contract_annual_raise: | |||
date = datetime.datetime.strptime(sub_row.date, "%Y-%m-%d") | |||
date = date.strftime("%d-%m-%Y") | |||
contract_dict[date] = f'{sub_row.annual_raise_type}_{sub_row.annual_raise_amount}' | |||
month = '{:02d}'.format(row.month) | |||
day = '{:02d}'.format(row.day) | |||
fieldname = f'{day}-{month}-{row.year}' | |||
if fieldname in contract_dict and contract_dict[fieldname]: | |||
splitted_field = contract_dict[fieldname].split("_") | |||
annual_raise_type = splitted_field[0] | |||
annual_raise_amount = splitted_field[1] | |||
if annual_raise_type == "Percentage": | |||
rent += rent / 100 * int(annual_raise_amount) | |||
else: | |||
rent += int(annual_raise_amount) | |||
self.append('payments', { | |||
'date': row.date(), | |||
'amount': rent or 0, | |||
'reason': 'Rent' + ' - outdoor' | |||
}) | |||
if not self.is_new(): | |||
self.save() | |||
def on_cancel(self): | |||
frappe.db.set_value("Unit", self.unit, "status", "Vacant") | |||
@frappe.whitelist() | |||
def create_row_invoice(self, rowid): | |||
create_sales_invoice(self.name, rowid) | |||
def get_brand_names(self): | |||
list_items = [] | |||
brands = frappe.get_all("Tenant Brand Name", filters={"parent": self.renter}, fields=['tenant_brand_name'], | |||
order_by="tenant_brand_name") | |||
if brands: | |||
for item in brands: | |||
list_items.append(item["tenant_brand_name"]) | |||
return list_items | |||
@frappe.whitelist() | |||
def update_duration(self): | |||
duration = self.get_dates_diff(self.rent_start_date, self.rent_end_date) | |||
# frappe.msgprint(str(duration)) | |||
duration_months = (cint(duration["years"]) * 12) + cint(duration["months"]) + ( | |||
1 if cint(duration["days"]) > 0 or getdate(self.rent_end_date).day == 1 else 0) | |||
# frappe.msgprint(str(duration_months)) | |||
self.duration = duration_months | |||
return duration_months | |||
def get_dates_diff(self, a, b): | |||
a = getdate(a) | |||
b = getdate(b) | |||
diff_dict = {} | |||
# a = datetime(a.year, a.month, a.day) | |||
# b = datetime(b.year, b.month, b.day) | |||
delta = dateutil.relativedelta.relativedelta(b, a) | |||
diff_dict["years"] = delta.years | |||
diff_dict["months"] = delta.months | |||
diff_dict["days"] = delta.days | |||
return diff_dict | |||
def create_sales_invoice(docname="", rowid=""): | |||
print("Starting Creation..........") | |||
condiction = "" | |||
if docname and rowid: | |||
row_doc = frappe.get_doc("Contract Payments", rowid) | |||
#condiction = " and P.`name` = '%s' " % docname | |||
condiction += " and C.`name` = '%s' " % rowid | |||
condiction += " and C.date = '%s' " % row_doc.date | |||
invoices = frappe.db.sql(""" | |||
select *,P.`name` contract_name,C.date invoice_date | |||
from `tabProperty Contract` P | |||
inner JOIN | |||
`tabContract Payments` C | |||
on P.`name` = C.parent | |||
-- and CURRENT_DATE() >= C.date | |||
and P.rent_item is not NULL | |||
and P.service_item is not NULL | |||
-- and P.docstatus = 1 | |||
and C.invoice is Null | |||
and C.amount > 0 | |||
{0} | |||
order by date | |||
""".format(condiction), as_dict=True, debug=True) | |||
# return | |||
if invoices: | |||
for invoice in invoices: | |||
s_name = create_sales_invoices(invoice) | |||
print(str(s_name.name) + " Invoice Created.") | |||
print("Finished.") | |||
def create_sales_invoices(args): | |||
# frappe.throw(str(args)) | |||
default_company = frappe.db.get_default("Company") | |||
si = frappe.new_doc("Sales Invoice") | |||
args = frappe._dict(args) | |||
si.posting_date = args.date or nowdate() | |||
invoice_date = args.date or nowdate() | |||
debit_to = frappe.db.get_value("Company", default_company, 'default_receivable_account') | |||
if debit_to: | |||
si.debit_to = debit_to # Default Receivable Account | |||
else: | |||
frappe.throw(_("Please set Default Receivable Account in Company " + default_company)) | |||
si.set_posting_time = 1 | |||
si.postint_date = args.invoice_date | |||
si.due_date = args.invoice_date | |||
si.customer = args.renter | |||
si.tax_id = frappe.db.get_value("Customer", args.renter, "tax_id") | |||
si.debit_to = debit_to | |||
print(str(si.postint_date) + "=================================================" + str(si.due_date)) | |||
# Accounting Dimensions | |||
si.property = args.property_name | |||
si.unit = args.unit | |||
si.property_contract = args.contract_name | |||
invoice_curerncy = frappe.get_cached_value('Customer', args.renter, "default_currency") or frappe.get_cached_value( | |||
'Company', default_company, "default_currency") | |||
si.currency = invoice_curerncy | |||
conversion_rate = 1 | |||
if invoice_curerncy != "EGP": | |||
conversion_rate = get_conversion_rate(invoice_curerncy,invoice_date) | |||
if conversion_rate == 0: | |||
message = _("Please Insert Currency Exchange for day {0}".format(invoice_date)) | |||
frappe.throw(frappe.bold(message)) | |||
si.conversion_rate = conversion_rate | |||
default_income_account = None | |||
item_income_account = frappe.db.get_value("Item Default", { | |||
"parent": (args.rent_item if args.reason == "Rent" else args.service_item)}, 'income_account') | |||
company_default_income_account = frappe.db.get_value("Company", default_company, 'default_income_account') | |||
if item_income_account: | |||
default_income_account = item_income_account | |||
elif company_default_income_account: | |||
default_income_account = company_default_income_account | |||
else: | |||
frappe.throw(_("Please set Default Income Account in Company " + default_company)) | |||
cost_center = frappe.db.get_value("Company", default_company, 'cost_center') | |||
if not cost_center: | |||
frappe.throw(_("Please set Default Cost Center in Company " + default_company)) | |||
si.append("items", { | |||
"item_code": (args.rent_item if args.reason == "Rent" else args.service_item), | |||
"item_name": (args.rent_item_name if args.reason == "Rent" else args.service_item), | |||
"qty": 1, | |||
"rate": args.amount, | |||
"uom": args.uom or "Unit", | |||
"stock_uom": args.uom or "Unit", | |||
"income_account": default_income_account, # Default Income Account | |||
"cost_center": cost_center, | |||
"conversion_factor": 1, | |||
"description": args.reason + " for contract " + str(args.contract_name) | |||
}) | |||
tax_template_name = "" | |||
if args.reason == "Services Charges" and args.service_sales_taxes_and_charges_template: | |||
tax_template_name = args.service_sales_taxes_and_charges_template | |||
elif args.reason == "Rent" and args.rent_sales_taxes_and_charges_template: | |||
tax_template_name = args.rent_sales_taxes_and_charges_template | |||
if tax_template_name: | |||
tax_data = frappe.db.sql(""" | |||
select T.`name` taxes_and_charges,S.charge_type,S.description,S.rate,S.account_head | |||
from `tabSales Taxes and Charges Template` T | |||
INNER JOIN | |||
`tabSales Taxes and Charges` S | |||
on T.`name` = S.parent | |||
and S.parenttype='Sales Taxes and Charges Template' | |||
and T.`name`='{tax_template_name}' | |||
""".format(tax_template_name=tax_template_name), as_dict=True, debug=False) | |||
# frappe.throw(str(args.service_sales_taxes_and_charges_template)) | |||
if tax_data: | |||
tax_data = tax_data[0] | |||
si.taxes_and_charges = tax_data["taxes_and_charges"] | |||
si.append("taxes", { | |||
"charge_type": tax_data["charge_type"], | |||
"account_head": tax_data["account_head"], | |||
"description": tax_data["description"], | |||
"rate": tax_data["rate"], | |||
"tax_amount": flt(tax_data["rate"]) * flt(si.net_total), | |||
"total": (flt(tax_data["rate"]) * flt(si.net_total)) + flt(si.net_total), | |||
"base_tax_amount": flt(tax_data["rate"]) * flt(si.net_total), | |||
"base_total": (flt(tax_data["rate"]) * flt(si.net_total)) + flt(si.net_total) | |||
}) | |||
Sinv_ID = None | |||
try: | |||
Sinv_ID = si.insert(ignore_mandatory=True) | |||
frappe.db.sql("""update `tabContract Payments` set invoice = '{0}' where `name` = '{1}' """.format(Sinv_ID.name, | |||
args.name), | |||
debug=True) | |||
return Sinv_ID | |||
except Exception as e: | |||
print("Error......" + str(e)) | |||
frappe.throw(_(e)) | |||
def get_conversion_rate(invoice_curerncy,invoice_date): | |||
conversion_rate = 0 | |||
exchange_rate = frappe.db.sql(""" | |||
select exchange_rate | |||
from `tabCurrency Exchange` | |||
where from_currency ='{invoice_curerncy}' | |||
and to_currency='EGP' | |||
-- and date ='{invoice_date}' | |||
ORDER BY date desc | |||
limit 1 | |||
""".format(invoice_curerncy=invoice_curerncy,invoice_date=invoice_date),as_dict=True) | |||
if exchange_rate: | |||
conversion_rate = exchange_rate[0]["exchange_rate"] | |||
return conversion_rate | |||
def update_unit_status(): | |||
units = frappe.db.get_list("Property Contract", filters={"docstatus": 1, "rent_end_date": getdate()}, | |||
fields=["unit"]) | |||
if units: | |||
for unit in units: | |||
frappe.db.set_value("Unit", unit["unit"], "status", "Vacant") | |||
@frappe.whitelist() | |||
def get_brand_names(renter): | |||
list_items = [] | |||
brands = frappe.get_all("Tenant Brand Name", filters={"parent": renter}, fields=['tenant_brand_name'], | |||
order_by="tenant_brand_name") | |||
if brands: | |||
for item in brands: | |||
list_items.append(item["tenant_brand_name"]) | |||
return list_items |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestPropertyContract(unittest.TestCase): | |||
pass |
@@ -0,0 +1,8 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Property Type', { | |||
// refresh: function(frm) { | |||
// } | |||
}); |
@@ -0,0 +1,41 @@ | |||
{ | |||
"autoname": "field:type", | |||
"creation": "2021-01-15 16:58:13.694397", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"type" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "type", | |||
"fieldtype": "Data", | |||
"label": "Type", | |||
"unique": 1 | |||
} | |||
], | |||
"modified": "2021-01-15 18:13:28.102488", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Property Type", | |||
"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, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class PropertyType(Document): | |||
pass |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestPropertyType(unittest.TestCase): | |||
pass |
@@ -0,0 +1,36 @@ | |||
{ | |||
"creation": "2021-01-15 18:18:54.805424", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"unit_type", | |||
"unit_number" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "unit_type", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Unit Type", | |||
"options": "Unit Type" | |||
}, | |||
{ | |||
"fieldname": "unit_number", | |||
"fieldtype": "Int", | |||
"in_list_view": 1, | |||
"label": "Unit Number" | |||
} | |||
], | |||
"istable": 1, | |||
"modified": "2021-01-15 18:22:32.111757", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Property Unit Detail", | |||
"owner": "Administrator", | |||
"permissions": [], | |||
"quick_entry": 1, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class PropertyUnitDetail(Document): | |||
pass |
@@ -0,0 +1,8 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Real Estate Offer', { | |||
// refresh: function(frm) { | |||
// } | |||
}); |
@@ -0,0 +1,273 @@ | |||
{ | |||
"autoname": "format:{title}-{####}", | |||
"creation": "2021-02-23 13:30:21.537656", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"title", | |||
"details", | |||
"basic_information_section", | |||
"owner", | |||
"property_type", | |||
"age", | |||
"city", | |||
"street", | |||
"postal_box", | |||
"number_of_air_conditioners", | |||
"the_role", | |||
"owner_type", | |||
"instrument_history", | |||
"width_rating", | |||
"column_break_15", | |||
"plate_number", | |||
"property", | |||
"display_type", | |||
"is_subject_to_installment", | |||
"neighborhood", | |||
"space", | |||
"the_national_email", | |||
"air_conditioner_type", | |||
"the_number_of_windows", | |||
"instrument_number", | |||
"case", | |||
"financial_information_section", | |||
"price", | |||
"limit", | |||
"income", | |||
"column_break_31", | |||
"price_type", | |||
"price_of_one_meter", | |||
"total_price", | |||
"mortgaged", | |||
"amended_from", | |||
"section_break_37", | |||
"location" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "title", | |||
"fieldtype": "Data", | |||
"label": "Title" | |||
}, | |||
{ | |||
"fieldname": "details", | |||
"fieldtype": "Small Text", | |||
"label": "Details" | |||
}, | |||
{ | |||
"fieldname": "basic_information_section", | |||
"fieldtype": "Section Break", | |||
"label": "Basic Information" | |||
}, | |||
{ | |||
"fieldname": "owner", | |||
"fieldtype": "Link", | |||
"label": "Owner", | |||
"options": "Customer" | |||
}, | |||
{ | |||
"fieldname": "property_type", | |||
"fieldtype": "Link", | |||
"label": "Property Type", | |||
"options": "Property Type" | |||
}, | |||
{ | |||
"fieldname": "age", | |||
"fieldtype": "Int", | |||
"label": "Age" | |||
}, | |||
{ | |||
"fieldname": "city", | |||
"fieldtype": "Data", | |||
"label": "City" | |||
}, | |||
{ | |||
"fieldname": "street", | |||
"fieldtype": "Data", | |||
"label": "Street" | |||
}, | |||
{ | |||
"fieldname": "postal_box", | |||
"fieldtype": "Data", | |||
"label": "Postal Box" | |||
}, | |||
{ | |||
"fieldname": "number_of_air_conditioners", | |||
"fieldtype": "Data", | |||
"label": "Number of Air Conditioners" | |||
}, | |||
{ | |||
"fieldname": "the_role", | |||
"fieldtype": "Data", | |||
"label": "The Role" | |||
}, | |||
{ | |||
"fieldname": "owner_type", | |||
"fieldtype": "Select", | |||
"label": "Owner type", | |||
"options": "Owner\nMediator\nAgent\nReal Estate Office" | |||
}, | |||
{ | |||
"fieldname": "instrument_history", | |||
"fieldtype": "Date", | |||
"label": "Instrument history" | |||
}, | |||
{ | |||
"fieldname": "width_rating", | |||
"fieldtype": "Data", | |||
"label": "Width Rating", | |||
"options": "Commercial\nResidential\nAgricultural\nIndustrial\nTourist" | |||
}, | |||
{ | |||
"fieldname": "column_break_15", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "plate_number", | |||
"fieldtype": "Data", | |||
"label": "Plate Number" | |||
}, | |||
{ | |||
"fieldname": "property", | |||
"fieldtype": "Link", | |||
"label": "Property", | |||
"options": "Property" | |||
}, | |||
{ | |||
"fieldname": "display_type", | |||
"fieldtype": "Select", | |||
"label": "Display Type", | |||
"options": "For Rent\nFor Sale\nInvestment" | |||
}, | |||
{ | |||
"fieldname": "is_subject_to_installment", | |||
"fieldtype": "Data", | |||
"label": "Is Subject to Installment" | |||
}, | |||
{ | |||
"fieldname": "neighborhood", | |||
"fieldtype": "Select", | |||
"label": "Neighborhood" | |||
}, | |||
{ | |||
"fieldname": "space", | |||
"fieldtype": "Data", | |||
"label": "Space" | |||
}, | |||
{ | |||
"fieldname": "the_national_email", | |||
"fieldtype": "Data", | |||
"label": "The National Email" | |||
}, | |||
{ | |||
"fieldname": "air_conditioner_type", | |||
"fieldtype": "Data", | |||
"label": "Air Conditioner Type" | |||
}, | |||
{ | |||
"fieldname": "the_number_of_windows", | |||
"fieldtype": "Data", | |||
"label": "The Number of Windows" | |||
}, | |||
{ | |||
"fieldname": "instrument_number", | |||
"fieldtype": "Data", | |||
"label": "Instrument Number" | |||
}, | |||
{ | |||
"fieldname": "case", | |||
"fieldtype": "Select", | |||
"label": "Case", | |||
"options": "Effective\nClosed" | |||
}, | |||
{ | |||
"fieldname": "financial_information_section", | |||
"fieldtype": "Section Break", | |||
"label": "Financial Information" | |||
}, | |||
{ | |||
"fieldname": "price", | |||
"fieldtype": "Currency", | |||
"label": "Price", | |||
"options": "Currency" | |||
}, | |||
{ | |||
"fieldname": "limit", | |||
"fieldtype": "Data", | |||
"label": "Limit" | |||
}, | |||
{ | |||
"fieldname": "income", | |||
"fieldtype": "Float", | |||
"label": "Income" | |||
}, | |||
{ | |||
"fieldname": "column_break_31", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "price_type", | |||
"fieldtype": "Select", | |||
"label": "Price Type", | |||
"options": "Fixed\nVariable" | |||
}, | |||
{ | |||
"fieldname": "price_of_one_meter", | |||
"fieldtype": "Float", | |||
"label": "Price of One Meter" | |||
}, | |||
{ | |||
"fieldname": "total_price", | |||
"fieldtype": "Float", | |||
"label": "Total Price" | |||
}, | |||
{ | |||
"fieldname": "mortgaged", | |||
"fieldtype": "Select", | |||
"label": "Mortgaged", | |||
"options": "\nReal Estate Bank\nA Commercial Bank\nInstallment Company" | |||
}, | |||
{ | |||
"fieldname": "amended_from", | |||
"fieldtype": "Link", | |||
"label": "Amended From", | |||
"no_copy": 1, | |||
"options": "Real Estate Offer", | |||
"print_hide": 1, | |||
"read_only": 1 | |||
}, | |||
{ | |||
"fieldname": "section_break_37", | |||
"fieldtype": "Section Break" | |||
}, | |||
{ | |||
"fieldname": "location", | |||
"fieldtype": "Geolocation", | |||
"label": "Location" | |||
} | |||
], | |||
"is_submittable": 1, | |||
"modified": "2021-02-25 11:58:56.669609", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Real Estate Offer", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"share": 1, | |||
"write": 1 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class RealEstateOffer(Document): | |||
pass |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestRealEstateOffer(unittest.TestCase): | |||
pass |
@@ -0,0 +1,8 @@ | |||
// Copyright (c) 2021, Havenir Solutions and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('Real Estate Order', { | |||
// refresh: function(frm) { | |||
// } | |||
}); |
@@ -0,0 +1,275 @@ | |||
{ | |||
"creation": "2021-02-23 13:45:20.505685", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"address_of_request", | |||
"details", | |||
"section_break_3", | |||
"customer", | |||
"type_of_request", | |||
"property_type", | |||
"price", | |||
"case", | |||
"column_break_9", | |||
"age", | |||
"city", | |||
"neighborhood", | |||
"street", | |||
"postal_box", | |||
"additional_details_section", | |||
"number_of_rooms", | |||
"role_number", | |||
"number_of_laundries", | |||
"space", | |||
"direction", | |||
"security", | |||
"central_air_conditioning", | |||
"elevator", | |||
"swimming_pool", | |||
"laundry_room", | |||
"column_break_26", | |||
"number_of_toilets", | |||
"number_of_halls", | |||
"finishing_type", | |||
"flooring", | |||
"architecture", | |||
"kitchen", | |||
"car_parking", | |||
"driver_room", | |||
"working_room", | |||
"amended_from" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "address_of_request", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Address of Request", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "details", | |||
"fieldtype": "Small Text", | |||
"in_list_view": 1, | |||
"label": "Details", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "section_break_3", | |||
"fieldtype": "Section Break" | |||
}, | |||
{ | |||
"fieldname": "customer", | |||
"fieldtype": "Link", | |||
"in_list_view": 1, | |||
"label": "Customer", | |||
"options": "Customer", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "type_of_request", | |||
"fieldtype": "Select", | |||
"in_list_view": 1, | |||
"label": "Type of Request", | |||
"options": "For Rent\nFor Sale", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "property_type", | |||
"fieldtype": "Link", | |||
"label": "Property Type", | |||
"options": "Property Type", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "price", | |||
"fieldtype": "Currency", | |||
"label": "Price", | |||
"options": "Currency", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "case", | |||
"fieldtype": "Select", | |||
"label": "Case", | |||
"options": "Effective\nClosed", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"fieldname": "column_break_9", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "age", | |||
"fieldtype": "Int", | |||
"label": "Age" | |||
}, | |||
{ | |||
"fieldname": "city", | |||
"fieldtype": "Data", | |||
"label": "City" | |||
}, | |||
{ | |||
"fieldname": "neighborhood", | |||
"fieldtype": "Data", | |||
"label": "Neighborhood" | |||
}, | |||
{ | |||
"fieldname": "street", | |||
"fieldtype": "Data", | |||
"label": "Street" | |||
}, | |||
{ | |||
"fieldname": "postal_box", | |||
"fieldtype": "Data", | |||
"label": "Postal Box" | |||
}, | |||
{ | |||
"fieldname": "additional_details_section", | |||
"fieldtype": "Section Break", | |||
"label": "Additional Details" | |||
}, | |||
{ | |||
"fieldname": "number_of_rooms", | |||
"fieldtype": "Data", | |||
"label": "Number of Rooms" | |||
}, | |||
{ | |||
"fieldname": "role_number", | |||
"fieldtype": "Data", | |||
"label": "Role number" | |||
}, | |||
{ | |||
"fieldname": "number_of_laundries", | |||
"fieldtype": "Data", | |||
"label": "Number of Laundries" | |||
}, | |||
{ | |||
"fieldname": "space", | |||
"fieldtype": "Data", | |||
"label": "Space" | |||
}, | |||
{ | |||
"fieldname": "direction", | |||
"fieldtype": "Data", | |||
"label": "Direction" | |||
}, | |||
{ | |||
"fieldname": "security", | |||
"fieldtype": "Data", | |||
"label": "Security" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "central_air_conditioning", | |||
"fieldtype": "Check", | |||
"label": "Central Air Conditioning" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "elevator", | |||
"fieldtype": "Check", | |||
"label": "Elevator" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "swimming_pool", | |||
"fieldtype": "Check", | |||
"label": "Swimming Pool" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "laundry_room", | |||
"fieldtype": "Check", | |||
"label": "Laundry Room" | |||
}, | |||
{ | |||
"fieldname": "column_break_26", | |||
"fieldtype": "Column Break" | |||
}, | |||
{ | |||
"fieldname": "number_of_toilets", | |||
"fieldtype": "Data", | |||
"label": "Number of Toilets" | |||
}, | |||
{ | |||
"fieldname": "number_of_halls", | |||
"fieldtype": "Data", | |||
"label": "Number of Halls" | |||
}, | |||
{ | |||
"fieldname": "finishing_type", | |||
"fieldtype": "Select", | |||
"label": "Finishing Type", | |||
"options": "Deluxe\nNormal\nSuper\nProfessional" | |||
}, | |||
{ | |||
"fieldname": "flooring", | |||
"fieldtype": "Data", | |||
"label": "Flooring" | |||
}, | |||
{ | |||
"fieldname": "architecture", | |||
"fieldtype": "Data", | |||
"label": "Architecture" | |||
}, | |||
{ | |||
"fieldname": "kitchen", | |||
"fieldtype": "Select", | |||
"label": "Kitchen", | |||
"options": "Open\nEnvelope" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "car_parking", | |||
"fieldtype": "Check", | |||
"label": "Car Parking" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "driver_room", | |||
"fieldtype": "Check", | |||
"label": "Driver Room" | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "working_room", | |||
"fieldtype": "Check", | |||
"label": "Working Room" | |||
}, | |||
{ | |||
"fieldname": "amended_from", | |||
"fieldtype": "Link", | |||
"label": "Amended From", | |||
"no_copy": 1, | |||
"options": "Real Estate Order", | |||
"print_hide": 1, | |||
"read_only": 1 | |||
} | |||
], | |||
"is_submittable": 1, | |||
"modified": "2021-02-25 12:00:30.216679", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Real Estate Order", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
"create": 1, | |||
"delete": 1, | |||
"email": 1, | |||
"export": 1, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"share": 1, | |||
"write": 1 | |||
} | |||
], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class RealEstateOrder(Document): | |||
pass |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
import unittest | |||
class TestRealEstateOrder(unittest.TestCase): | |||
pass |
@@ -0,0 +1,82 @@ | |||
{ | |||
"creation": "2021-10-23 15:09:39.197026", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"payment_date", | |||
"principal_amount", | |||
"interest_amount", | |||
"total_payment", | |||
"balance_amount", | |||
"paid" | |||
], | |||
"fields": [ | |||
{ | |||
"allow_on_submit": 1, | |||
"columns": 2, | |||
"fieldname": "payment_date", | |||
"fieldtype": "Date", | |||
"in_list_view": 1, | |||
"label": "Payment Date" | |||
}, | |||
{ | |||
"columns": 2, | |||
"fieldname": "principal_amount", | |||
"fieldtype": "Currency", | |||
"in_list_view": 1, | |||
"label": "Principal Amount", | |||
"no_copy": 1, | |||
"options": "Company:company:default_currency", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"columns": 2, | |||
"fieldname": "interest_amount", | |||
"fieldtype": "Currency", | |||
"in_list_view": 1, | |||
"label": "Interest Amount", | |||
"no_copy": 1, | |||
"options": "Company:company:default_currency", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"columns": 2, | |||
"fieldname": "total_payment", | |||
"fieldtype": "Currency", | |||
"in_list_view": 1, | |||
"label": "Total Payment", | |||
"options": "Company:company:default_currency", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"columns": 2, | |||
"fieldname": "balance_amount", | |||
"fieldtype": "Currency", | |||
"in_list_view": 1, | |||
"label": "Balance Amount", | |||
"no_copy": 1, | |||
"options": "Company:company:default_currency", | |||
"read_only": 1 | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "paid", | |||
"fieldtype": "Check", | |||
"in_list_view": 1, | |||
"label": "Paid", | |||
"read_only": 1 | |||
} | |||
], | |||
"istable": 1, | |||
"modified": "2021-10-24 02:20:34.154918", | |||
"modified_by": "Administrator", | |||
"module": "Property Management", | |||
"name": "Reservation Repayment Schedule", | |||
"owner": "Administrator", | |||
"permissions": [], | |||
"quick_entry": 1, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2021, Havenir Solutions and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
# import frappe | |||
from frappe.model.document import Document | |||
class ReservationRepaymentSchedule(Document): | |||
pass |