diff --git a/propms/auto_custom.py b/propms/auto_custom.py index 045aa198..c6ee786a 100755 --- a/propms/auto_custom.py +++ b/propms/auto_custom.py @@ -428,7 +428,7 @@ def makeInvoiceSchedule( doctype="Lease Invoice Schedule", parent=name, parentfield="lease_invoice_schedule", - parenttype="lease", + parenttype="Lease", date_to_invoice=date_to_invoice, schedule_start_date=date, lease_item=item, diff --git a/propms/lease_invoice.py b/propms/lease_invoice.py index 25cddea0..4253ab46 100755 --- a/propms/lease_invoice.py +++ b/propms/lease_invoice.py @@ -100,6 +100,8 @@ def makeInvoice( doc.submit() return doc + except frappe.ValidationError: + raise except Exception as e: app_error_log(frappe.session.user, str(e)) @@ -147,7 +149,6 @@ def leaseInvoiceAutoCreate(): "invoice_number", "sales_order_number", "parent", - "parent", "invoice_item_group", "lease_item", "paid_by", @@ -260,6 +261,8 @@ def leaseInvoiceAutoCreate(): prev_currency = invoice_item.currency row_num += 1 # increment by 1 # Create the last invoice + if not invoice_item: + return res = makeInvoice( invoice_item.date_to_invoice, invoice_item.paid_by, @@ -285,6 +288,7 @@ def leaseInvoiceAutoCreate(): frappe.msgprint(_("Lease Invoice generated with number: {0}").format(res.name)) except Exception as e: + frappe.log_error(frappe.get_traceback(), "Lease Invoice Auto Create failed") app_error_log(frappe.session.user, str(e)) diff --git a/propms/lease_invoice_schedule.py b/propms/lease_invoice_schedule.py index ff353334..e22feadd 100644 --- a/propms/lease_invoice_schedule.py +++ b/propms/lease_invoice_schedule.py @@ -38,7 +38,7 @@ def make_lease_invoice_schedule(): # Only check start_date, ignore end_date for inclusion ) ) - lease_names = [row[0] for row in frappe.db.sql(query.get_sql())] + lease_names = [row[0] for row in query.run()] for lease_name in lease_names: try: @@ -145,8 +145,8 @@ def make_lease_invoice_schedule(): # Move to first day of next period invoice_date = add_days(invoice_period_end, 1) - frappe.msgprint(_(f"Completed invoice schedule for Lease: {lease.name}")) + frappe.msgprint(_("Completed invoice schedule for Lease: {0}").format(lease.name)) except Exception as e: - frappe.msgprint(_(f"Error in {lease_name}. Check app error log.")) + frappe.msgprint(_("Error in {0}. Check app error log.").format(lease_name)) app_error_log(frappe.session.user, f"{lease_name}: {str(e)}") diff --git a/propms/property_management_solution/doctype/daily_checklist/daily_checklist.json b/propms/property_management_solution/doctype/daily_checklist/daily_checklist.json index 4589628b..ce2c479e 100755 --- a/propms/property_management_solution/doctype/daily_checklist/daily_checklist.json +++ b/propms/property_management_solution/doctype/daily_checklist/daily_checklist.json @@ -221,7 +221,7 @@ "collapsible": 0, "columns": 0, "fieldname": "naming_series", - "fieldtype": "Data", + "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -229,7 +229,8 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "naming_series", + "label": "Naming Series", + "options": "DC-.YYYY.-", "length": 0, "no_copy": 0, "permlevel": 0, @@ -239,9 +240,9 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 0, + "reqd": 1, "search_index": 0, - "set_only_once": 0, + "set_only_once": 1, "translatable": 0, "unique": 0 } @@ -257,7 +258,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-12-24 19:42:26.306039", + "modified": "2026-08-27 12:00:00.000000", "modified_by": "Administrator", "module": "Property Management Solution", "name": "Daily Checklist", diff --git a/propms/property_management_solution/doctype/lease/lease.py b/propms/property_management_solution/doctype/lease/lease.py index d30a777d..112b3327 100755 --- a/propms/property_management_solution/doctype/lease/lease.py +++ b/propms/property_management_solution/doctype/lease/lease.py @@ -45,6 +45,7 @@ def on_submit(self): app_error_log(frappe.session.user, str(e)) def validate(self): + self.set_lease_status() self.validate_days_to_invoice_in_advance() try: properties = self.get_all_properties() @@ -119,7 +120,28 @@ def validate(self): raise except Exception as e: app_error_log(frappe.session.user, str(e)) - self.set_lease_status() + + def validate_days_to_invoice_in_advance(self): + """Prevent changing 'Days to Invoice in Advance' once invoices have been generated.""" + if not self.is_new() and self.has_value_changed("days_to_invoice_in_advance"): + has_generated_invoices = any( + row.invoice_number or row.sales_order_number for row in (self.lease_invoice_schedule or []) + ) + if not has_generated_invoices: + has_generated_invoices = frappe.db.exists( + "Lease Invoice Schedule", + { + "parent": self.name, + "invoice_number": ["is", "set"], + }, + ) + if has_generated_invoices: + frappe.throw( + _( + "Cannot change 'Days to Invoice in Advance' after invoices have been generated for this Lease." + ), + title=_("Field Read Only"), + ) def validate_days_to_invoice_in_advance(self): """Prevent changing 'Days to Invoice in Advance' once invoices have been generated.""" @@ -153,7 +175,7 @@ def set_lease_status(self): All other statuses are considered manual and are not overwritten. """ - if self.lease_status not in get_system_controlled_statuses(): + if self.lease_status and self.lease_status not in get_system_controlled_statuses(): return status = get_status_for_lease(self) diff --git a/propms/property_management_solution/doctype/outsourcing_attendance/outsourcing_attendance.json b/propms/property_management_solution/doctype/outsourcing_attendance/outsourcing_attendance.json index f287e327..1fe4a122 100755 --- a/propms/property_management_solution/doctype/outsourcing_attendance/outsourcing_attendance.json +++ b/propms/property_management_solution/doctype/outsourcing_attendance/outsourcing_attendance.json @@ -154,27 +154,28 @@ "collapsible": 0, "columns": 0, "fieldname": "naming_series", - "fieldtype": "Data", - "hidden": 1, + "fieldtype": "Select", + "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "naming_series", + "label": "Naming Series", + "options": "OA-.YYYY.-", "length": 0, "no_copy": 0, "permlevel": 0, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, - "read_only": 1, + "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 0, + "reqd": 1, "search_index": 0, - "set_only_once": 0, + "set_only_once": 1, "translatable": 0, "unique": 0 }, @@ -222,7 +223,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-01-16 15:54:32.839686", + "modified": "2026-08-27 12:00:00.000000", "modified_by": "Administrator", "module": "Property Management Solution", "name": "Outsourcing Attendance", diff --git a/propms/property_management_solution/doctype/property/property_tree.js b/propms/property_management_solution/doctype/property/property_tree.js index 4c9d00a7..3cca0ee2 100644 --- a/propms/property_management_solution/doctype/property/property_tree.js +++ b/propms/property_management_solution/doctype/property/property_tree.js @@ -14,7 +14,7 @@ frappe.treeview_settings["Property"] = { ], fields: [ - { fieldtype: "Data", fieldname: "property_name", label: __("New Property Name"), reqd: true }, + { fieldtype: "Data", fieldname: "name1", label: __("New Property Name"), reqd: true }, { fieldtype: "Check", fieldname: "is_group", diff --git a/propms/property_management_solution/doctype/security_attendance/security_attendance.json b/propms/property_management_solution/doctype/security_attendance/security_attendance.json index 53824fae..5c6dc794 100755 --- a/propms/property_management_solution/doctype/security_attendance/security_attendance.json +++ b/propms/property_management_solution/doctype/security_attendance/security_attendance.json @@ -43,15 +43,18 @@ }, { "fieldname": "naming_series", - "fieldtype": "Data", - "label": "naming_series", + "fieldtype": "Select", + "hidden": 0, + "label": "Naming Series", + "options": "SA-.YYYY.-", "print_hide": 1, - "read_only": 1 + "reqd": 1, + "set_only_once": 1 } ], "icon": "octicon octicon-clippy", "is_submittable": 1, - "modified": "2019-12-05 16:49:29.347921", + "modified": "2026-08-27 12:00:00.000000", "modified_by": "Administrator", "module": "Property Management Solution", "name": "Security Attendance", @@ -99,4 +102,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} \ No newline at end of file +} diff --git a/propms/property_management_solution/issue.js b/propms/property_management_solution/issue.js index ab9154e6..d8897489 100644 --- a/propms/property_management_solution/issue.js +++ b/propms/property_management_solution/issue.js @@ -1,246 +1,246 @@ -frappe.ui.form.on('Issue', { - validate: (frm) => { - // frm.trigger("make_row_readonly"); - if (!frm.doc.materials_required) { - return - } - let to_update = []; - frm.doc.materials_required.forEach((item, idx) => { - var sle_qty = 0 - frappe.call({ - method: "propms.issue_hook.get_stock_availability", - args: { - item_code: item.item, - company: frm.doc.company, - is_pos: item.is_pos - }, - async: false, - callback: function (r) { - if (r.message) { - sle_qty = r.message; - } - } - }); - if (item.material_status === "Bill" || item.material_status === "Self Consumption" && frm.doc.status === "Closed") { - if (sle_qty < item.quantity) { - frappe.throw(__(`Existing stock quantity of item ${item.item} is ${sle_qty} not enough`)) - return - } - let child = frm.add_child("materials_billed"); - child.item = item.item; - child.quantity = item.quantity; - child.uom = item.uom; - child.rate = item.rate; - child.amount = item.amount; - child.is_pos = item.is_pos; - child.material_status = item.material_status; - } - else { - to_update.push(item); - } - }); - frm.clear_table("materials_required"); - refresh_field("materials_required"); - to_update.forEach(item => { - let child = frm.add_child("materials_required"); - child.item = item.item; - child.quantity = item.quantity; - child.uom = item.uom; - child.rate = item.rate; - child.amount = item.amount; - child.is_pos = item.is_pos; - child.material_status = item.material_status; - refresh_field("materials_required"); - }); - refresh_field("materials_required"); - - if (!frm.doc.materials_billed) { - return - } - const sort_list = []; - frm.doc.materials_billed.forEach((item, idx) => { - let item_inv_no = Number.MAX_SAFE_INTEGER; - let item_inv_ser = ""; - if (item.sales_invoice) { - item_inv_no = +item.sales_invoice.slice(9).replace("-", ""); - item_inv_ser = item.sales_invoice.slice(0, 8); - } - sort_list.push({ - idx: idx, - no: item_inv_no, - ser: item_inv_ser, - pos: item.is_pos, - name: item.name - }); - }); - const sorted_list = sort_list.sort((a, b) => a.no - b.no); - const pos_list = []; - const not_list = []; - sorted_list.forEach(i => { - if (i.pos) { pos_list.push(i) } - else { not_list.push(i) } - }); - const new_sorted = [].concat(pos_list, not_list); - new_sorted.forEach((i, idx) => { - const row = locals["Issue Materials Billed"][i.name]; - row.idx = idx + 1; - }); - refresh_field("materials_billed"); - }, - - refresh: (frm) => { - frm.trigger("make_pos_readonly"); - }, - - onload: (frm) => { - frm.trigger("make_pos_readonly"); - }, - - make_pos_readonly: (frm) => { - if (!frm.doc.materials_required) { - return; - } - let child = frm.doc.materials_required; - child.forEach(function (e) { - $("[data-idx='" + e.idx + "']").find('.btn-open-row').css("pointer-events", "none"); - if (e.material_status === "Self Consumption") { - $("[data-idx='" + e.idx + "']").find('[data-fieldname = is_pos]').css("pointer-events", "none"); - } - else { - $("[data-idx='" + e.idx + "']").find('[data-fieldname = is_pos]').css("pointer-events", "auto"); - } - }); - refresh_field("materials_required"); - }, - - setup: function (frm) { - frm.set_query('person_in_charge', function () { - return { - filters: { - 'department': ['like', 'Maintenance - %'] - } - } - }); - frm.set_query('sub_contractor_contact', function () { - return { - filters: { - 'supplier_group': 'Sub-Contractor' - } - } - }); - frappe.call({ - method: "propms.issue_hook.get_items_group", - async: false, - callback: function (r) { - if (r.message) { - let maintenance_item_group = r.message; - frm.fields_dict["materials_required"].grid.get_field("item").get_query = function (doc, cdt, cdn) { - return { - filters: [ - ["Item", "item_group", "in", maintenance_item_group], - - ] - } - } - } - } - }); - }, - property_name: function (frm, cdt, cdn) { - // frappe.msgprint(__("Testing")) - frappe.model.set_value(cdt, cdn, 'customer', ''); - if (frm.doc.property_name) { - frappe.call({ - method: 'frappe.client.get_value', - args: { - doctype: 'Property', - fieldname: 'status', - filters: { - name: frm.doc.property_name - }, - }, - async: false, - callback: function (r, rt) { - if (r.message) { - if (r.message.status.toLowerCase() == 'on lease' || r.message.status.toLowerCase() == 'off lease in 3 months') { - frappe.call({ - method: 'frappe.client.get_value', - args: { - doctype: 'Lease', - fieldname: ['name', 'customer'], - filters: { - property: frm.doc.property_name, - start_date: ["<=", frappe.datetime.nowdate()], - end_date: [">=", frappe.datetime.nowdate()] - }, - }, - async: false, - callback: function (r, rt) { - if (r.message) { - frm.set_value("customer", r.message.customer); - refresh_field("customer") - } - } - }); - } else { - frappe.db.get_value("Property", frm.doc.property_name, "unit_owner", (r) => { - frm.set_value("customer", r.unit_owner); - }); - } - } - } - }); - } - }, -}); - -frappe.ui.form.on("Issue Materials Detail", "quantity", function (frm, cdt, cdn) { - var item_row = locals[cdt][cdn]; - item_row.amount = item_row.rate * item_row.quantity; - refresh_field("materials_required"); -}); - - -frappe.ui.form.on("Issue Materials Detail", "rate", function (frm, cdt, cdn) { - var item_row = locals[cdt][cdn]; - item_row.amount = item_row.rate * item_row.quantity; - refresh_field("materials_required"); -}); - - -frappe.ui.form.on("Issue Materials Detail", "material_status", function (frm, cdt, cdn) { - var item_row = locals[cdt][cdn]; - var is_pos = $("[data-idx='" + item_row.idx + "']").find('[data-fieldname = is_pos]') - - if (item_row.material_status === "Self Consumption") { - is_pos.css("pointer-events", "none"); - item_row.is_pos = 0; - - } else { - is_pos.css("pointer-events", "auto"); - } - refresh_field("materials_required"); -}); - - -frappe.ui.form.on("Issue Materials Detail", "item", function (frm, cdt, cdn) { - var item_row = locals[cdt][cdn]; - if (!item_row.item) { - return; - } - frappe.call({ - method: "propms.issue_hook.get_item_rate", - args: { - item: item_row.item, - customer: frm.doc.customer, - }, - async: false, - callback: function (r) { - if (r.message) { - item_row.rate = r.message; - item_row.amount = item_row.rate * item_row.quantity; - refresh_field("materials_required"); - } - } - }); -}); +frappe.ui.form.on('Issue', { + validate: (frm) => { + // frm.trigger("make_row_readonly"); + if (!frm.doc.materials_required) { + return + } + let to_update = []; + frm.doc.materials_required.forEach((item, idx) => { + var sle_qty = 0 + frappe.call({ + method: "propms.issue_hook.get_stock_availability", + args: { + item_code: item.item, + company: frm.doc.company, + is_pos: item.is_pos + }, + async: false, + callback: function (r) { + if (r.message) { + sle_qty = r.message; + } + } + }); + if (item.material_status === "Bill" || item.material_status === "Self Consumption" && frm.doc.status === "Closed") { + if (sle_qty < item.quantity) { + frappe.throw(__("Existing stock quantity of item {0} is {1}, which is not enough", [item.item, sle_qty])) + return + } + let child = frm.add_child("materials_billed"); + child.item = item.item; + child.quantity = item.quantity; + child.uom = item.uom; + child.rate = item.rate; + child.amount = item.amount; + child.is_pos = item.is_pos; + child.material_status = item.material_status; + } + else { + to_update.push(item); + } + }); + frm.clear_table("materials_required"); + refresh_field("materials_required"); + to_update.forEach(item => { + let child = frm.add_child("materials_required"); + child.item = item.item; + child.quantity = item.quantity; + child.uom = item.uom; + child.rate = item.rate; + child.amount = item.amount; + child.is_pos = item.is_pos; + child.material_status = item.material_status; + refresh_field("materials_required"); + }); + refresh_field("materials_required"); + + if (!frm.doc.materials_billed) { + return + } + const sort_list = []; + frm.doc.materials_billed.forEach((item, idx) => { + let item_inv_no = Number.MAX_SAFE_INTEGER; + let item_inv_ser = ""; + if (item.sales_invoice) { + item_inv_no = +item.sales_invoice.slice(9).replace("-", ""); + item_inv_ser = item.sales_invoice.slice(0, 8); + } + sort_list.push({ + idx: idx, + no: item_inv_no, + ser: item_inv_ser, + pos: item.is_pos, + name: item.name + }); + }); + const sorted_list = sort_list.sort((a, b) => a.no - b.no); + const pos_list = []; + const not_list = []; + sorted_list.forEach(i => { + if (i.pos) { pos_list.push(i) } + else { not_list.push(i) } + }); + const new_sorted = [].concat(pos_list, not_list); + new_sorted.forEach((i, idx) => { + const row = locals["Issue Materials Billed"][i.name]; + row.idx = idx + 1; + }); + refresh_field("materials_billed"); + }, + + refresh: (frm) => { + frm.trigger("make_pos_readonly"); + }, + + onload: (frm) => { + frm.trigger("make_pos_readonly"); + }, + + make_pos_readonly: (frm) => { + if (!frm.doc.materials_required) { + return; + } + let child = frm.doc.materials_required; + child.forEach(function (e) { + $("[data-idx='" + e.idx + "']").find('.btn-open-row').css("pointer-events", "none"); + if (e.material_status === "Self Consumption") { + $("[data-idx='" + e.idx + "']").find('[data-fieldname = is_pos]').css("pointer-events", "none"); + } + else { + $("[data-idx='" + e.idx + "']").find('[data-fieldname = is_pos]').css("pointer-events", "auto"); + } + }); + refresh_field("materials_required"); + }, + + setup: function (frm) { + frm.set_query('person_in_charge', function () { + return { + filters: { + 'department': ['like', 'Maintenance - %'] + } + } + }); + frm.set_query('sub_contractor_contact', function () { + return { + filters: { + 'supplier_group': 'Sub-Contractor' + } + } + }); + frappe.call({ + method: "propms.issue_hook.get_items_group", + async: false, + callback: function (r) { + if (r.message) { + let maintenance_item_group = r.message; + frm.fields_dict["materials_required"].grid.get_field("item").get_query = function (doc, cdt, cdn) { + return { + filters: [ + ["Item", "item_group", "in", maintenance_item_group], + + ] + } + } + } + } + }); + }, + property_name: function (frm, cdt, cdn) { + // frappe.msgprint(__("Testing")) + frappe.model.set_value(cdt, cdn, 'customer', ''); + if (frm.doc.property_name) { + frappe.call({ + method: 'frappe.client.get_value', + args: { + doctype: 'Property', + fieldname: 'status', + filters: { + name: frm.doc.property_name + }, + }, + async: false, + callback: function (r, rt) { + if (r.message) { + if (r.message.status.toLowerCase() == 'on lease' || r.message.status.toLowerCase() == 'off lease in 3 months') { + frappe.call({ + method: 'frappe.client.get_value', + args: { + doctype: 'Lease', + fieldname: ['name', 'customer'], + filters: { + property: frm.doc.property_name, + start_date: ["<=", frappe.datetime.nowdate()], + end_date: [">=", frappe.datetime.nowdate()] + }, + }, + async: false, + callback: function (r, rt) { + if (r.message) { + frm.set_value("customer", r.message.customer); + refresh_field("customer") + } + } + }); + } else { + frappe.db.get_value("Property", frm.doc.property_name, "unit_owner", (r) => { + frm.set_value("customer", r.unit_owner); + }); + } + } + } + }); + } + }, +}); + +frappe.ui.form.on("Issue Materials Detail", "quantity", function (frm, cdt, cdn) { + var item_row = locals[cdt][cdn]; + item_row.amount = item_row.rate * item_row.quantity; + refresh_field("materials_required"); +}); + + +frappe.ui.form.on("Issue Materials Detail", "rate", function (frm, cdt, cdn) { + var item_row = locals[cdt][cdn]; + item_row.amount = item_row.rate * item_row.quantity; + refresh_field("materials_required"); +}); + + +frappe.ui.form.on("Issue Materials Detail", "material_status", function (frm, cdt, cdn) { + var item_row = locals[cdt][cdn]; + var is_pos = $("[data-idx='" + item_row.idx + "']").find('[data-fieldname = is_pos]') + + if (item_row.material_status === "Self Consumption") { + is_pos.css("pointer-events", "none"); + item_row.is_pos = 0; + + } else { + is_pos.css("pointer-events", "auto"); + } + refresh_field("materials_required"); +}); + + +frappe.ui.form.on("Issue Materials Detail", "item", function (frm, cdt, cdn) { + var item_row = locals[cdt][cdn]; + if (!item_row.item) { + return; + } + frappe.call({ + method: "propms.issue_hook.get_item_rate", + args: { + item: item_row.item, + customer: frm.doc.customer, + }, + async: false, + callback: function (r) { + if (r.message) { + item_row.rate = r.message; + item_row.amount = item_row.rate * item_row.quantity; + refresh_field("materials_required"); + } + } + }); +}); diff --git a/propms/property_management_solution/report/invoice_details/other_methods.py b/propms/property_management_solution/report/invoice_details/other_methods.py index b5ab9611..76f181c7 100644 --- a/propms/property_management_solution/report/invoice_details/other_methods.py +++ b/propms/property_management_solution/report/invoice_details/other_methods.py @@ -183,11 +183,13 @@ def months_array(): def get_rate(invoice_name, filters): - filters_value = " and item_code= '" + filters.get("rental") + "' " + item_code = filters.get("rental") if filters.get("maintenance"): - filters_value = "and item_code = 'Service Charge - " + filters.get("rental").split()[0] + "'" - query = """ SELECT rate FROM `tabSales Invoice Item` WHERE {} {}""".format( - "parent = '" + invoice_name + "' ", filters_value - ) + item_code = "Service Charge - " + filters.get("rental").split()[0] - return frappe.db.sql(query, as_dict=True)[0].rate if len(frappe.db.sql(query, as_dict=True)) > 0 else "" + rows = frappe.db.sql( + """SELECT rate FROM `tabSales Invoice Item` WHERE parent = %(parent)s AND item_code = %(item_code)s""", + {"parent": invoice_name, "item_code": item_code}, + as_dict=True, + ) + return rows[0].rate if rows else "" diff --git a/propms/property_management_solution/report/mis_income_break_up/other_methods.py b/propms/property_management_solution/report/mis_income_break_up/other_methods.py index f45ced49..7b5e6309 100644 --- a/propms/property_management_solution/report/mis_income_break_up/other_methods.py +++ b/propms/property_management_solution/report/mis_income_break_up/other_methods.py @@ -34,6 +34,8 @@ def get_rentals(filters): return_data.append(tax) return_data.append(net_rent) for i in sum_monthly: + if i == "income": + continue tax[i] = float(sum_monthly[i]) * 0.10 net_rent[i] = sum_monthly[i] - tax[i] return return_data diff --git a/propms/property_management_solution/report/rent_invoices_details/rent_invoices_details.py b/propms/property_management_solution/report/rent_invoices_details/rent_invoices_details.py index 182a5fc7..7016d7f6 100644 --- a/propms/property_management_solution/report/rent_invoices_details/rent_invoices_details.py +++ b/propms/property_management_solution/report/rent_invoices_details/rent_invoices_details.py @@ -28,10 +28,12 @@ def execute(filters=None): def get_data(filters): rows = [] - _from_date = "'{from_date}'".format(from_date=filters["from_date"]) - _to_date = "'{to_date}'".format(to_date=filters["to_date"]) - _company = "'{company}'".format(company=filters["company"]) _items_grupe = filters.get("type_name") + values = { + "company": filters["company"], + "from_date": filters["from_date"], + "to_date": filters["to_date"], + } float_precision = cint(frappe.db.get_default("float_precision")) or 2 if filters.get("company"): default_currency = get_company_currency(filters["company"]) @@ -41,9 +43,10 @@ def get_data(filters): conditions = "" if not filters.get("extand"): - conditions = f"AND DATE(posting_date) BETWEEN {_from_date} AND {_to_date}" + conditions = "AND DATE(posting_date) BETWEEN %(from_date)s AND %(to_date)s" - query = f""" + query = ( + """ SELECT name as invoice_id, customer, @@ -57,16 +60,19 @@ def get_data(filters): `tabSales Invoice` WHERE docstatus = 1 - AND company = {_company} + AND company = %(company)s AND lease != "" AND from_date != "" AND to_date != "" AND is_return != 1 - {conditions} + """ + + conditions + + """ ORDER BY lease DESC, posting_date DESC """ + ) - sales_invoices = frappe.db.sql(query, as_dict=True) + sales_invoices = frappe.db.sql(query, values, as_dict=True) for invoice in sales_invoices: _items_rwos = [] @@ -83,9 +89,7 @@ def get_data(filters): # for key,value in months_obj.items(): # invoice[key] = value - invoice_id = "'{invoice_id}'".format(invoice_id=invoice["invoice_id"]) - - query_items = f""" + query_items = """ SELECT item_code, base_net_amount as item_total, @@ -97,10 +101,10 @@ def get_data(filters): FROM `tabSales Invoice Item` WHERE - parent = {invoice_id} + parent = %(invoice_id)s """ - items = frappe.db.sql(query_items, as_dict=True) + items = frappe.db.sql(query_items, {"invoice_id": invoice["invoice_id"]}, as_dict=True) for item in items: item_group = frappe.db.get_value("Item", item["item_code"], "item_group") item["item_group"] = item_group diff --git a/propms/property_management_solution/report/rent_invoices_details_usd/rent_invoices_details_usd.py b/propms/property_management_solution/report/rent_invoices_details_usd/rent_invoices_details_usd.py index d3fef271..b3ae0c4f 100644 --- a/propms/property_management_solution/report/rent_invoices_details_usd/rent_invoices_details_usd.py +++ b/propms/property_management_solution/report/rent_invoices_details_usd/rent_invoices_details_usd.py @@ -30,10 +30,12 @@ def execute(filters=None): def get_data(filters): rows = [] - _from_date = "'{from_date}'".format(from_date=filters["from_date"]) - _to_date = "'{to_date}'".format(to_date=filters["to_date"]) - _company = "'{company}'".format(company=filters["company"]) _items_grupe = filters.get("type_name") + values = { + "company": filters["company"], + "from_date": filters["from_date"], + "to_date": filters["to_date"], + } float_precision = cint(frappe.db.get_default("float_precision")) or 2 if filters.get("company"): default_currency = get_company_currency(filters["company"]) @@ -43,9 +45,10 @@ def get_data(filters): conditions = "" if not filters.get("extand"): - conditions = f"AND DATE(posting_date) BETWEEN {_from_date} AND {_to_date}" + conditions = "AND DATE(posting_date) BETWEEN %(from_date)s AND %(to_date)s" - query = f""" + query = ( + """ SELECT name as invoice_id, customer, @@ -59,15 +62,18 @@ def get_data(filters): `tabSales Invoice` WHERE docstatus = 1 - AND company = {_company} + AND company = %(company)s AND lease != "" AND from_date != "" AND to_date != "" - {conditions} + """ + + conditions + + """ ORDER BY lease DESC, posting_date ASC """ + ) - sales_invoices = frappe.db.sql(query, as_dict=True) + sales_invoices = frappe.db.sql(query, values, as_dict=True) for invoice in sales_invoices: _items_rwos = [] @@ -78,9 +84,7 @@ def get_data(filters): invoice.exchange_rate = get_exchange_rate("USD", default_currency, invoice.posting_date) invoice.foreign_total = invoice.total / invoice.exchange_rate - invoice_id = "'{invoice_id}'".format(invoice_id=invoice["invoice_id"]) - - query_items = f""" + query_items = """ SELECT item_code, base_net_amount as item_total, @@ -92,10 +96,10 @@ def get_data(filters): FROM `tabSales Invoice Item` WHERE - parent = {invoice_id} + parent = %(invoice_id)s """ - items = frappe.db.sql(query_items, as_dict=True) + items = frappe.db.sql(query_items, {"invoice_id": invoice["invoice_id"]}, as_dict=True) for item in items: item_group = frappe.db.get_value("Item", item["item_code"], "item_group") item["item_group"] = item_group diff --git a/propms/property_management_solution/report/subscription_service_report/subscription_service_report.js b/propms/property_management_solution/report/subscription_service_report/subscription_service_report.js index fe7e5e6b..a4acbe02 100644 --- a/propms/property_management_solution/report/subscription_service_report/subscription_service_report.js +++ b/propms/property_management_solution/report/subscription_service_report/subscription_service_report.js @@ -1,30 +1,30 @@ -// Copyright (c) 2016, Aakvatech and contributors -// For license information, please see license.txt -/* eslint-disable */ - -frappe.query_reports["Subscription Service Report"] = { - "filters": [ - { - "fieldname":"service_type", - "label": __("Service Type"), - "fieldtype": "Link", - "options": "Item", - "default": "Gym services", - "reqd": 1 - get_query: () => { - return { - filters: { - 'item_group': "Services" - } - } - } - }, - { - "fieldname":"to_date", - "label": __("To Date"), - "fieldtype": "Date", - "default": frappe.datetime.get_today(), - "reqd": 1 - } - ] -} +// Copyright (c) 2016, Aakvatech and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Subscription Service Report"] = { + "filters": [ + { + "fieldname":"service_type", + "label": __("Service Type"), + "fieldtype": "Link", + "options": "Item", + "default": "Gym services", + "reqd": 1, + "get_query": () => { + return { + filters: { + 'item_group': "Services" + } + } + } + }, + { + "fieldname":"to_date", + "label": __("To Date"), + "fieldtype": "Date", + "default": frappe.datetime.get_today(), + "reqd": 1 + } + ] +} diff --git a/propms/property_management_solution/report/subscription_service_report/subscription_service_report.json b/propms/property_management_solution/report/subscription_service_report/subscription_service_report.json index 18725825..a56c8ced 100644 --- a/propms/property_management_solution/report/subscription_service_report/subscription_service_report.json +++ b/propms/property_management_solution/report/subscription_service_report/subscription_service_report.json @@ -7,13 +7,13 @@ "doctype": "Report", "idx": 0, "is_standard": "Yes", - "modified": "2020-04-27 13:53:51.035254", + "modified": "2026-08-27 12:00:00.000000", "modified_by": "Administrator", "module": "Property Management Solution", "name": "Subscription Service Report", "owner": "Administrator", "prepared_report": 0, - "query": "SELECT si.name, \r\n si.customer,\r\n\t from_date,\r\n\t to_date\r\nFROM `tabSales Invoice` si LEFT JOIN `tabSales Invoice Item` sii on si.name = sii.parent\r\nWHERE si.from_date IS NOT NULL \r\nAND si.to_date IS NOT NULL \r\nAND sii.item_group = 'Services'\r\nAND si.item_name = %(service_type)s;", + "query": "SELECT si.name, \r\n si.customer,\r\n\t from_date,\r\n\t to_date\r\nFROM `tabSales Invoice` si LEFT JOIN `tabSales Invoice Item` sii on si.name = sii.parent\r\nWHERE si.from_date IS NOT NULL \r\nAND si.to_date IS NOT NULL \r\nAND sii.item_group = 'Services'\r\nAND sii.item_name = %(service_type)s;", "ref_doctype": "Sales Invoice", "report_name": "Subscription Service Report", "report_type": "Query Report", @@ -25,4 +25,4 @@ "role": "Accounts User" } ] -} \ No newline at end of file +} diff --git a/propms/property_management_solution/report/utility_invoices/other_methods.py b/propms/property_management_solution/report/utility_invoices/other_methods.py index 8b3fd06e..0f4bc26c 100644 --- a/propms/property_management_solution/report/utility_invoices/other_methods.py +++ b/propms/property_management_solution/report/utility_invoices/other_methods.py @@ -177,10 +177,9 @@ def months_array(): def get_rate(invoice_name): - filters_value = "and item_code = 'Utility Charges'" - query = """ SELECT rate FROM `tabSales Invoice Item` WHERE {} {}""".format( - "parent = '" + invoice_name + "' ", filters_value + rows = frappe.db.sql( + """SELECT rate FROM `tabSales Invoice Item` WHERE parent = %(parent)s AND item_code = 'Utility Charges'""", + {"parent": invoice_name}, + as_dict=True, ) - print(query) - - return frappe.db.sql(query, as_dict=True)[0].rate if len(frappe.db.sql(query, as_dict=True)) > 0 else "" + return rows[0].rate if rows else ""