Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 82 additions & 4 deletions propms/property_management_solution/doctype/lease/lease.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ frappe.ui.form.on('Lease', {
});
},
refresh: function(frm) {
frm.trigger("custom_set_intro");

cur_frm.add_custom_button(__("Make Invoice Schedule"), function() {
make_lease_invoice_schedule(cur_frm);
});
}, __("Actions"));
cur_frm.add_custom_button(__("Generate Pending Invoice"), function() {
generate_pending_invoice();
});
}, __("Actions"));
cur_frm.add_custom_button(__("Make Invoice Schedule for all Lease"), function() {
getAllLease(cur_frm);
});
}, __("Actions"));

// Add custom buttons for Accounts Receivable and Accounting Ledger
if (!frm.doc.__islocal) {
Expand All @@ -62,6 +64,39 @@ frappe.ui.form.on('Lease', {
},
__("View")
);

// Add "Renew Lease" custom button
if (
["Active", "Expired"].includes(frm.doc.lease_status) &&
(frappe.user.has_role("Property Manager") ||
frappe.user.has_role("System Manager"))
) {
frm.add_custom_button(
__("Renew Lease"),
function () {
frappe.confirm(__("Are you sure you want to renew this lease?"), function () {
frappe.call({
method: "propms.property_management_solution.doctype.lease.lease.initiate_lease_renewal",
args: {
source_lease_name: frm.doc.name,
},
freeze: true,
freeze_message: __("Initiating Lease Renewal..."),
callback: function (r) {
if (r.message) {
frappe.show_alert({
message: __("Lease renewal draft created successfully: {0}", [r.message]),
indicator: "green",
});
frappe.set_route("Form", "Lease", r.message);
}
},
});
});
},
__("Actions")
);
}
}
},
skip_end_date: function(frm) {
Expand Down Expand Up @@ -111,7 +146,50 @@ frappe.ui.form.on('Lease', {
}
});
}
}
},

custom_set_intro: function (frm) {
// Show intro banner if this is a renewal lease
if (frm.doc.renewed_from) {
frappe.db
.get_value("Lease", frm.doc.name, ["renewal_initiated_by", "creation"])
.then((r) => {
if (r.message) {
let d = r.message;
let created_on = moment(d.creation).format("DD-MM-YYYY hh:mm A");

frm.set_intro(
__("This lease is a renewal of {0}, initiated by {1} on {2}.", [
`<a href="/app/lease/${frm.doc.renewed_from}"><b>${frm.doc.renewed_from}</b></a>`,
`<b>${d.renewal_initiated_by || __("Unknown")}</b>`,
`<b>${created_on}</b>`,
]),
"blue"
);
}
});
}

// Show intro banner if this lease has already been renewed
frappe.db
.get_value("Lease", { renewed_from: frm.doc.name }, ["name", "renewal_initiated_by", "creation"])
.then((r) => {
if (r && r.message && r.message.name) {
let d = r.message;

let creation_time = moment(d.creation).format("DD-MM-YYYY hh:mm A");

frm.set_intro(
__("This lease has been renewed: {0} by {1} on {2}.", [
`<a href="/app/lease/${d.name}"><b>${d.name}</b></a>`,
`<b>${d.renewal_initiated_by || ""}</b>`,
`<b>${creation_time}</b>`,
]),
"green"
);
}
});
},
});

var make_lease_invoice_schedule = function(frm){
Expand Down
32 changes: 31 additions & 1 deletion propms/property_management_solution/doctype/lease/lease.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@
"witness_2",
"witness_1",
"section_break_36",
"amended_from"
"amended_from",
"lease_renewal_details_section",
"renewed_from",
"column_break_renewal",
"renewal_initiated_by"
],
"fields": [
{
Expand Down Expand Up @@ -325,6 +329,32 @@
"fieldname": "skip_end_date",
"fieldtype": "Check",
"label": "Skip End Date"
},
{
"fieldname": "lease_renewal_details_section",
"fieldtype": "Section Break",
"label": "Lease Renewal Details",
"collapsible": 1
},
{
"fieldname": "renewed_from",
"fieldtype": "Link",
"label": "Renewed From",
"options": "Lease",
"read_only": 1,
"no_copy": 1
},
{
"fieldname": "column_break_renewal",
"fieldtype": "Column Break"
},
{
"fieldname": "renewal_initiated_by",
"fieldtype": "Link",
"label": "Renewal Initiated By",
"options": "User",
"read_only": 1,
"no_copy": 1
}
],
"links": [],
Expand Down
59 changes: 59 additions & 0 deletions propms/property_management_solution/doctype/lease/lease.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,3 +506,62 @@ def make_lease_invoice_schedule(leasedoc):
except Exception as e:
frappe.msgprint("Exception error! Check app error log.")
app_error_log(frappe.session.user, str(e))


@frappe.whitelist()
def initiate_lease_renewal(source_lease_name):
# 1. Permission checks
if not any(r in frappe.get_roles() for r in ["Property Manager", "System Manager"]):
frappe.throw(_("You are not authorized to renew leases. Only Property Managers and System Managers can perform this action."), frappe.PermissionError)

# 2. Fetch source document
source_doc = frappe.get_doc("Lease", source_lease_name)

# 3. Status checks
if source_doc.lease_status not in ["Active", "Expired"]:
frappe.throw(_("Lease {0} is not eligible for renewal. Status must be Active or Expired.").format(source_lease_name), frappe.ValidationError)

# 4. Duplicate renewal check (ignoring terminated or aborted renewals)
duplicate_exists = frappe.db.exists("Lease", {
"renewed_from": source_lease_name,
"lease_status": ["not in", ["Not Materialized", "Terminated"]]
})
if duplicate_exists:
frappe.throw(_("A renewal lease already exists for this lease: {0}").format(duplicate_exists), frappe.ValidationError)

# 5. Clone Lease using standard frappe.copy_doc
new_lease = frappe.copy_doc(source_doc)
new_lease.set("lease_invoice_schedule", []) # Clear old invoice schedules

# Set renewal reference fields
new_lease.renewed_from = source_lease_name
new_lease.lease_status = "Renewal to Previous Lease"
new_lease.renewal_initiated_by = frappe.session.user

# Calculate dates
if source_doc.end_date:
new_lease.start_date = add_days(source_doc.end_date, 1)
if source_doc.start_date:
duration_days = (getdate(source_doc.end_date) - getdate(source_doc.start_date)).days
new_lease.end_date = add_days(new_lease.start_date, duration_days)
else:
new_lease.start_date = today()

# Update valid_from date for items
for item in new_lease.lease_item:
item.valid_from = new_lease.start_date

# Insert and save the new Lease as draft
new_lease.insert(ignore_permissions=True)

# Post a message/comment to the old lease with initiator and link details
comment_text = _("Lease renewal draft <a href='/app/Form/Lease/{0}'><b>{0}</b></a> has been initiated by <b>{1}</b> on <b>{2}</b>.").format(
new_lease.name,
frappe.session.user,
frappe.utils.formatdate(today())
)
source_doc.add_comment(text=comment_text)

return new_lease.name


Loading