Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: utility property links #26

Merged
merged 1 commit into from
Nov 6, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,10 @@ frappe.ui.form.on("Meter Reading Item", {
method: "utility_billing.utility_billing.doctype.meter_reading.meter_reading.get_previous_invoice_reading",
args: {
item_code: row.item_code,
customer: frm.doc.customer,
},
callback: function (r) {
row.previous_reading = r.message[1] || 0;
row.previous_reading = r.message || 0;
frm.refresh_field("items");
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ def create_sales_order(meter_reading):
"selling_price_list": meter_reading.price_list,
}
)
utility_property = frappe.get_value("Customer", meter_reading.customer, "utility_property")
if utility_property:
sales_order.utility_property = utility_property

for rate in meter_reading.rates:
rate_dict = rate.as_dict()
Expand All @@ -52,8 +55,7 @@ def create_sales_order(meter_reading):


for i in meter_reading.items:
_, prev_reading = get_previous_invoice_reading(i.item_code)
prev_consumption = get_previous_consumption(i.item_code)
prev_reading = get_previous_invoice_reading(i.item_code, meter_reading.customer)
sales_order.append(
"meter_readings",
{
Expand All @@ -74,34 +76,20 @@ def create_sales_order(meter_reading):

return sales_order


@frappe.whitelist()
def get_previous_consumption(item_code):
"""Fetch the sum of previous readings for the specified meter number sharing the same parent."""
parent, _ = get_previous_invoice_reading(item_code)
meter_reading = DocType("Sales Invoice Meter Reading")
previous_consumption = (
frappe.qb.from_(meter_reading)
.where(meter_reading.parent == parent)
.select(Sum(meter_reading.current_reading - meter_reading.previous_reading))
).run()
return previous_consumption[0][0] if previous_consumption else 0


@frappe.whitelist()
def get_previous_invoice_reading(item_code):
"""Fetch the previous reading and its parent for the specified meter number."""
previous_reading = frappe.get_all(
"Sales Invoice Meter Reading",
filters={"item_code": item_code},
fields=["current_reading", "creation", "parent"],
order_by="creation desc",
limit_page_length=1,
)
if previous_reading:
return previous_reading[0].parent, previous_reading[0].current_reading
else:
return "None", 0
def get_previous_invoice_reading(item_code, customer):
"""Fetch the last submitted invoice's current reading for the specified item and customer."""

latest_invoice = frappe.get_value("Sales Invoice", filters={"customer": customer, "docstatus": 1},
fieldname="name", order_by="creation desc")

if not latest_invoice:
return 0

previous_reading = frappe.get_value("Sales Invoice Meter Reading", filters={"parent": latest_invoice, "item_code": item_code},
fieldname="current_reading", order_by="creation desc")

return previous_reading or 0


@frappe.whitelist()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,64 @@
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"title"
"title",
"lft",
"rgt",
"is_group",
"old_parent",
"parent_utility_category"
],
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title",
"unique": 1
},
{
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
"label": "Left",
"no_copy": 1,
"read_only": 1
},
{
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
"label": "Right",
"no_copy": 1,
"read_only": 1
},
{
"fieldname": "is_group",
"fieldtype": "Check",
"label": "Is Group"
},
{
"fieldname": "old_parent",
"fieldtype": "Link",
"label": "Old Parent",
"options": "Utility Category"
},
{
"fieldname": "parent_utility_category",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Parent Utility Category",
"options": "Utility Category"
}
],
"index_web_pages_for_search": 1,
"is_tree": 1,
"links": [],
"modified": "2024-11-06 16:06:42.742911",
"modified": "2024-11-06 16:40:59.588124",
"modified_by": "Administrator",
"module": "Utility Billing",
"name": "Utility Category",
"naming_rule": "By fieldname",
"nsm_parent_field": "parent_utility_category",
"owner": "Administrator",
"permissions": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,26 @@ frappe.ui.form.on("Utility Service Request", {
}
},

property: function (frm) {
if (frm.doc.property) {
frappe.call({
method: "frappe.client.get_value",
args: {
doctype: "Utility Property",
fieldname: "territory",
filters: {
name: frm.doc.property,
},
},
callback: function (r) {
if (r.message && r.message.territory) {
frm.set_value("territory", r.message.territory);
}
},
});
}
},

tc_name: function (frm) {
if (!frm.doc.tc_name) {
frm.set_value("terms", "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"date",
"customer_group",
"territory",
"property",
"column_break_wxld",
"company",
"tax_id",
Expand All @@ -36,10 +37,9 @@
"connection_size",
"pipes_typedistance",
"column_break_bfhu",
"east_cordinates",
"water_network",
"column_break_omtp",
"south_cordinates",
"location",
"address_and_contacts_tab",
"section_break_ywar",
"address_html",
Expand Down Expand Up @@ -229,16 +229,6 @@
"fieldtype": "Data",
"label": "Water Network"
},
{
"fieldname": "east_cordinates",
"fieldtype": "Data",
"label": "East Cordinates"
},
{
"fieldname": "south_cordinates",
"fieldtype": "Data",
"label": "South Cordinates"
},
{
"fieldname": "pipes_typedistance",
"fieldtype": "Data",
Expand Down Expand Up @@ -418,12 +408,24 @@
"fieldname": "date_posted",
"fieldtype": "Date",
"label": "Posted by Date"
},
{
"fieldname": "property",
"fieldtype": "Link",
"label": "Property",
"options": "Utility Property"
},
{
"fieldname": "location",
"fieldtype": "Link",
"label": "Location",
"options": "Location"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-10-24 13:50:18.316001",
"modified": "2024-11-06 16:42:41.258215",
"modified_by": "Administrator",
"module": "Utility Billing",
"name": "Utility Service Request",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def create_customer(doc):
customer_doc.nrc_or_passport_no = doc.nrcpassport_no
customer_doc.company = doc.company
customer_doc.insert()
customer_doc.utility_property = doc.property

frappe.db.set_value(
"Utility Service Request", doc.name, "customer", customer_doc.name
Expand Down Expand Up @@ -82,6 +83,7 @@ def create_sales_order(doc, customer_doc):
sales_order_doc = frappe.new_doc("Sales Order")
sales_order_doc.customer = customer_doc.name
sales_order_doc.utility_service_request = doc.name
sales_order_doc.utility_property = doc.property
sales_order_doc.transaction_date = frappe.utils.nowdate()
sales_order_doc.delivery_date = add_months(sales_order_doc.transaction_date, 1)

Expand Down Expand Up @@ -113,13 +115,12 @@ def create_site_survey(docname):
issue_doc.subject = f"Site Survey for {docname} ({doc.customer_name})"
issue_doc.description = (
f"Site survey created for Utility Service Request: {docname}, Customer name: {doc.customer_name}.\n"
f"{request_type_description}"
f"{' ' + request_type_description if request_type_description else ''}",
)
issue_doc.utility_service_request = docname
issue_doc.issue_type = doc.request_type

issue_doc.insert()
doc.save()

return {"issue": issue_doc.name}

Expand Down
54 changes: 25 additions & 29 deletions utility_billing/utility_billing/overrides/server/sales_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,36 @@
import frappe
from erpnext.controllers.taxes_and_totals import calculate_taxes_and_totals
from erpnext.controllers.accounts_controller import AccountsController
from frappe.model.mapper import get_mapped_doc


def before_validate(doc: Document, method: str) -> None:
"""Intercepts submit event for document"""
AccountsController.append_taxes_from_item_tax_template(doc)
calculate_taxes_and_totals(doc)
unique_sales_orders = {item.sales_order for item in doc.items if item.sales_order}
for sales_order in unique_sales_orders:
map_sales_order_meter_readings_to_invoice(sales_order, doc, True)
if not doc.taxes:
AccountsController.append_taxes_from_item_tax_template(doc)
calculate_taxes_and_totals(doc)
unique_sales_orders = {
item.sales_order
for item in frappe.get_all(
"Sales Invoice Item",
filters={"parent": doc.name, "sales_order": ["is", "set"]},
fields=["sales_order"]
)
}

for sales_order in unique_sales_orders:
map_sales_order_meter_readings_to_invoice(sales_order, doc)


def map_sales_order_meter_readings_to_invoice(source_name, target_doc, ignore_permissions):
"""Map Sales Order to Sales Invoice, including meter readings."""
return get_mapped_doc(
"Sales Order",
source_name,
{
"Sales Order": {
"doctype": "Sales Invoice",
"field_map": {
"party_account_currency": "party_account_currency",
"payment_terms_template": "payment_terms_template",
},
"field_no_map": ["payment_terms_template"],
"validation": {"docstatus": ["=", 1]},
},
"Sales Order Meter Reading": {
"doctype": "Sales Invoice Meter Reading",
"add_if_empty": True,
}
},
target_doc,
ignore_permissions=ignore_permissions,
)
def map_sales_order_meter_readings_to_invoice(sales_order_name, target_doc):
"""Map all fields from Sales Order Meter Reading to Sales Invoice Meter Reading."""
sales_order = frappe.get_doc("Sales Order", sales_order_name)
meter_readings = sales_order.get("meter_readings")
target_doc.set("meter_readings", [])
if sales_order.utility_property: target_doc.utility_property = sales_order.utility_property

for reading in meter_readings:
new_reading_data = reading.as_dict()
new_reading_data.pop("name", None)
new_reading = target_doc.append("meter_readings", new_reading_data)
new_reading.parent = target_doc.name

Loading