@@ -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 |