Skip to content

Commit

Permalink
Merge pull request #35 from navariltd/service-request
Browse files Browse the repository at this point in the history
Service request
  • Loading branch information
muruthigitau authored Nov 29, 2024
2 parents 8a44654 + cf5f40a commit 1bd9f51
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ frappe.ui.form.on("Meter Reading", {
},
};
};

update_meter_number_query(frm);
},

customer: function (frm) {
Expand All @@ -37,6 +39,7 @@ frappe.ui.form.on("Meter Reading", {
},
});
}
update_meter_number_query(frm);
},

items_add: function (frm) {
Expand Down Expand Up @@ -109,6 +112,7 @@ frappe.ui.form.on("Meter Reading Item", {
},
});
}
update_meter_number_query(frm);
},
meter_number: function (frm, cdt, cdn) {
const row = locals[cdt][cdn];
Expand All @@ -118,6 +122,38 @@ frappe.ui.form.on("Meter Reading Item", {
},
});

function update_meter_number_query(frm) {
frappe.db
.get_list("Warranty Claim", {
filters: { status: "Closed", customer: frm.doc.customer },
fields: ["serial_no"],
})
.then((warrantyClaims) => {
const closedWarrantySerials = warrantyClaims.map((claim) => claim.serial_no);

frm.fields_dict["items"].grid.get_field("meter_number").get_query = function () {
return {
filters: {
status: "Active",
name: ["in", closedWarrantySerials],
},
};
};

frm.doc.items.forEach((row) => {
if (!row.meter_number && closedWarrantySerials.length === 1) {
frappe.model.set_value(
row.doctype,
row.name,
"meter_number",
closedWarrantySerials[0]
);
}
});
frm.refresh_field("items");
});
}

function fetch_previous_reading(frm, row) {
if (row.item_code && frm.doc.customer) {
frappe.call({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@

class MeterReading(Document):
def validate(self):
for item in self.items:
self.validate_item_readings(item)
create_meter_reading_rates(self, self.price_list, self.date)

def on_submit(self):
settings = frappe.get_single("Utility Billing Settings")
if not self.rates or len(self.rates) == 0:
frappe.throw(
frappe._("Cannot submit Meter Reading. No rates available.")
)
existing_sales_order = frappe.db.exists(
{
"doctype": "Sales Order Meter Reading",
Expand All @@ -31,6 +37,31 @@ def on_submit(self):
sales_order = create_sales_order(self)
sales_order.submit()

def validate_item_readings(self, item):
"""Validate readings for each item."""
if item.current_reading is None:
frappe.throw(
frappe._(
f"Current reading is required for item: {item.item_code}"
)
)

previous_reading = get_previous_invoice_reading(
item_code=item.item_code,
customer=self.customer,
meter_number=item.meter_number
)
item.previous_reading = previous_reading

item.consumption = item.current_reading - previous_reading

if item.consumption < 0:
frappe.throw(
frappe._(
f"Current reading cannot be lower than the previous reading for item: {item.item_code}"
)
)


def create_sales_order(meter_reading):
"""Create a Sales Order based on the Meter Reading."""
Expand Down Expand Up @@ -116,3 +147,24 @@ def get_customer_details(customer):
)

return customer_doc.as_dict()


@frappe.whitelist()
def get_serial_numbers_from_warranty_claims(customer):
"""
Fetch serial numbers from closed Warranty Claims for the given customer and item.
"""
serial_numbers = frappe.get_all(
"Warranty Claim",
filters={
"customer": customer,
"status": "Closed",
},
fields=["serial_no"],
)
serial_list = []
for claim in serial_numbers:
if claim.get("serial_no"):
serial_list.extend(claim["serial_no"].split("\n"))

return list(set(serial_list))
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"sales_order_creation_state",
"sales_invoice_creation_state",
"column_break_moce",
"stock_entry_creation_state",
"individual_invoices_for_multiple_sales_orders"
],
"fields": [
Expand All @@ -34,12 +35,19 @@
"fieldtype": "Select",
"label": "Sales Invoice Creation State",
"options": "Draft\nSubmitted"
},
{
"default": "Draft",
"fieldname": "stock_entry_creation_state",
"fieldtype": "Select",
"label": "Stock Entry Creation State",
"options": "Draft\nSubmitted"
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2024-11-16 19:13:25.929144",
"modified": "2024-11-28 16:53:04.866577",
"modified_by": "Administrator",
"module": "Utility Billing",
"name": "Utility Billing Settings",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,26 @@ frappe.ui.form.on("Utility Service Request", {
};
};

let closedWarrantySerials = [];

frappe.db
.get_list("Warranty Claim", {
filters: { status: "Closed" },
fields: ["serial_no"],
})
.then((warrantyClaims) => {
closedWarrantySerials = warrantyClaims.map((claim) => claim.serial_no);
});

frm.fields_dict["items"].grid.get_field("meter_number").get_query = function () {
return {
filters: {
status: "Active",
name: ["not in", closedWarrantySerials],
},
};
};

frm.set_query("customer_group", function () {
return {
filters: {
Expand Down Expand Up @@ -113,6 +133,11 @@ frappe.ui.form.on("Utility Service Request", {
});

frappe.ui.form.on("Utility Service Request Item", {
form_render: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
handle_item_code(frm, cdt, cdn, row.item_code);
},

items_add: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
let delivery_date = frm.doc.delivery_date || frappe.datetime.nowdate();
Expand All @@ -126,44 +151,7 @@ frappe.ui.form.on("Utility Service Request Item", {

item_code: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
if (row.item_code) {
frappe.call({
method: "utility_billing.utility_billing.doctype.utility_service_request.utility_service_request.get_item_details",
args: {
item_code: row.item_code,
price_list: frm.doc.price_list,
},
callback: function (r) {
if (r.message) {
let item = r.message;
frappe.model.set_value(cdt, cdn, {
item_name: item.item_name,
uom: item.uom,
rate: item.rate,
warehouse: item.warehouse,
description: item.description,
qty: 1,
conversion_factor: item.conversion_factor,
brand: item.brand,
item_group: item.item_group,
stock_uom: item.stock_uom,
bom_no: item.bom_no,
weight_per_unit: item.weight_per_unit,
weight_uom: item.weight_uom,
item_tax_template: item.item_tax_template,
warehouse: item.default_warehouse,
});

let amount = flt(item.rate) * flt(row.qty || 1);
frappe.model.set_value(cdt, cdn, {
rate: item.rate,
amount: amount,
base_price_list_rate: item.rate,
});
}
},
});
}
handle_item_code(frm, cdt, cdn, row.item_code, true);
},

rate: function (frm, cdt, cdn) {
Expand All @@ -181,6 +169,64 @@ frappe.ui.form.on("Utility Service Request Item", {
},
});

function handle_item_code(frm, cdt, cdn, item_code, update_fields = false) {
if (item_code) {
frappe.call({
method: "utility_billing.utility_billing.doctype.utility_service_request.utility_service_request.get_item_details",
args: {
item_code: item_code,
price_list: frm.doc.price_list,
},
callback: function (r) {
if (r.message) {
let item = r.message;
if (update_fields) {
update_item_fields(frm, cdt, cdn, item);
}
toggle_meter_number(frm, cdt, cdn, item.item_group === "Meter");
}
},
});
} else {
toggle_meter_number(frm, cdt, cdn, false);
}
}

function update_item_fields(frm, cdt, cdn, item) {
frappe.model.set_value(cdt, cdn, {
item_name: item.item_name,
uom: item.uom,
rate: item.rate,
warehouse: item.warehouse,
description: item.description,
qty: 1,
conversion_factor: item.conversion_factor,
brand: item.brand,
item_group: item.item_group,
stock_uom: item.stock_uom,
bom_no: item.bom_no,
weight_per_unit: item.weight_per_unit,
weight_uom: item.weight_uom,
item_tax_template: item.item_tax_template,
warehouse: item.default_warehouse,
});

let amount = flt(item.rate) * flt(frm.doc.qty || 1);
frappe.model.set_value(cdt, cdn, {
rate: item.rate,
amount: amount,
base_price_list_rate: item.rate,
});
}

function toggle_meter_number(frm, cdt, cdn, show) {
frm.fields_dict["items"].grid.toggle_display("meter_number", show, cdt, cdn);
if (!show) {
frappe.model.set_value(cdt, cdn, "meter_number", null);
}
frm.fields_dict["items"].grid.toggle_reqd("warehouse", show, cdt, cdn);
}

function calculate_amount(frm, cdt, cdn) {
let row = locals[cdt][cdn];
let amount = flt(row.rate) * flt(row.qty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ def create_customer_and_sales_order(docname):
customer_doc = create_customer(doc)
link_contact_and_address_to_customer(customer_doc, doc)
sales_order_doc = create_sales_order(doc, customer_doc)
create_stock_entry_for_meter_issue(docname)
for item in doc.items:
if item.item_group == "Meter" and item.meter_number:
create_warranty_claim(customer_doc, item.meter_number, item.item_code)

return {"sales_order": sales_order_doc.name}

Expand Down Expand Up @@ -214,4 +218,44 @@ def get_item_details(item_code, price_list=None):
@frappe.whitelist()
def bom_new_version(bom):
bom = frappe.get_doc("BOM", bom)
return frappe.copy_doc(bom)
return frappe.copy_doc(bom)


def create_warranty_claim(customer_doc, serial_number, item_code):
warranty_claim = frappe.new_doc("Warranty Claim")
warranty_claim.customer = customer_doc.name
warranty_claim.complaint = customer_doc.name
warranty_claim.serial_no = serial_number
warranty_claim.item_code = item_code
warranty_claim.complaint_date = nowdate()
warranty_claim.status = "Closed"
warranty_claim.save()
return warranty_claim


@frappe.whitelist()
def create_stock_entry_for_meter_issue(docname):
doc = frappe.get_doc("Utility Service Request", docname)

auto_submit_stock_entry = frappe.db.get_single_value("Utility Billing Settings", "stock_entry_creation_state")

stock_entry = frappe.new_doc("Stock Entry")
stock_entry.stock_entry_type = "Material Issue"

for item in doc.items:
if item.item_group == "Meter" and item.meter_number:
stock_entry_item = item.as_dict()
stock_entry_item.update({
"serial_no": item.meter_number,
"use_serial_batch_fields": 1,
"s_warehouse": item.warehouse,
})
stock_entry.append("items", stock_entry_item)

if stock_entry.items:
stock_entry.save()

if auto_submit_stock_entry == "Submitted":
stock_entry.submit()

return {"stock_entry": stock_entry.name}
Loading

0 comments on commit 1bd9f51

Please sign in to comment.