Skip to content

Commit

Permalink
feat: allow to edit Stock Quantity in the Sales and Purchase Transact…
Browse files Browse the repository at this point in the history
…ions (#36600)

feat: allow to edit Stock Quantity in the Sales and Purchase transactions
  • Loading branch information
rohitwaghchaure authored Sep 20, 2023
1 parent e6199dc commit dd4769e
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 7 deletions.
9 changes: 9 additions & 0 deletions erpnext/controllers/buying_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,10 @@ def validate_for_subcontracting(self):
item.bom = None

def set_qty_as_per_stock_uom(self):
allow_to_edit_stock_qty = frappe.db.get_single_value(
"Stock Settings", "allow_to_edit_stock_uom_qty_for_purchase"
)

for d in self.get("items"):
if d.meta.get_field("stock_qty"):
# Check if item code is present
Expand All @@ -432,6 +436,11 @@ def set_qty_as_per_stock_uom(self):
d.conversion_factor, d.precision("conversion_factor")
)

if allow_to_edit_stock_qty:
d.stock_qty = flt(d.stock_qty, d.precision("stock_qty"))
if d.get("received_stock_qty"):
d.received_stock_qty = flt(d.received_stock_qty, d.precision("received_stock_qty"))

def validate_purchase_return(self):
for d in self.get("items"):
if self.is_return and flt(d.rejected_qty) != 0:
Expand Down
6 changes: 6 additions & 0 deletions erpnext/controllers/selling_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,17 @@ def validate_max_discount(self):
frappe.throw(_("Maximum discount for Item {0} is {1}%").format(d.item_code, discount))

def set_qty_as_per_stock_uom(self):
allow_to_edit_stock_qty = frappe.db.get_single_value(
"Stock Settings", "allow_to_edit_stock_uom_qty_for_sales"
)

for d in self.get("items"):
if d.meta.get_field("stock_qty"):
if not d.conversion_factor:
frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx))
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
if allow_to_edit_stock_qty:
d.stock_qty = flt(d.stock_qty, d.precision("stock_qty"))

This comment has been minimized.

Copy link
@TurkerTunali

TurkerTunali Jan 16, 2024

Contributor

Here setting the d.stock_qty doesn't make sense because we've already erased the manually entered value in line 205 as
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)

These lines should be:

if not allow_to_edit_stock_qty:
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
else:
d.stock_qty = flt(d.stock_qty, d.precision("stock_qty"))


def validate_selling_price(self):
def throw_message(idx, item_name, rate, ref_rate_field):
Expand Down
1 change: 1 addition & 0 deletions erpnext/public/js/controllers/buying.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ erpnext.buying = {
erpnext.buying.BuyingController = class BuyingController extends erpnext.TransactionController {
setup() {
super.setup();
this.toggle_enable_for_stock_uom("allow_to_edit_stock_uom_qty_for_purchase");
this.frm.email_field = "contact_email";
}

Expand Down
18 changes: 18 additions & 0 deletions erpnext/public/js/controllers/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,14 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
}

}

toggle_enable_for_stock_uom(field) {
frappe.db.get_single_value('Stock Settings', field)
.then(value => {
this.frm.fields_dict["items"].grid.toggle_enable("stock_qty", value);
});
}

onload() {
var me = this;

Expand Down Expand Up @@ -1191,6 +1199,16 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
]);
}

stock_qty(doc, cdt, cdn) {
let item = frappe.get_doc(cdt, cdn);
item.conversion_factor = 1.0;
if (item.stock_qty) {
item.conversion_factor = flt(item.stock_qty) / flt(item.qty);
}

refresh_field("conversion_factor", item.name, item.parentfield);
}

calculate_stock_uom_rate(doc, cdt, cdn) {
let item = frappe.get_doc(cdt, cdn);
item.stock_uom_rate = flt(item.rate)/flt(item.conversion_factor);
Expand Down
1 change: 1 addition & 0 deletions erpnext/public/js/utils/sales_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ erpnext.sales_common = {
erpnext.selling.SellingController = class SellingController extends erpnext.TransactionController {
setup() {
super.setup();
this.toggle_enable_for_stock_uom("allow_to_edit_stock_uom_qty_for_sales");
this.frm.email_field = "contact_email";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
"sample_quantity",
"tracking_section",
"received_stock_qty",
"stock_qty",
"col_break_tracking_section",
"stock_qty",
"returned_qty",
"rate_and_amount",
"price_list_rate",
Expand Down Expand Up @@ -858,7 +858,8 @@
},
{
"fieldname": "tracking_section",
"fieldtype": "Section Break"
"fieldtype": "Section Break",
"label": "Qty as Per Stock UOM"
},
{
"fieldname": "col_break_tracking_section",
Expand Down Expand Up @@ -1060,7 +1061,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2023-07-26 12:55:15.234477",
"modified": "2023-08-11 16:16:16.504549",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",
Expand Down
29 changes: 25 additions & 4 deletions erpnext/stock/doctype/stock_settings/stock_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
"auto_insert_price_list_rate_if_missing",
"column_break_12",
"update_existing_price_list_rate",
"conversion_factor_section",
"allow_to_edit_stock_uom_qty_for_sales",
"column_break_lznj",
"allow_to_edit_stock_uom_qty_for_purchase",
"stock_validations_tab",
"section_break_9",
"over_delivery_receipt_allowance",
Expand Down Expand Up @@ -357,10 +361,6 @@
"fieldtype": "Check",
"label": "Allow Partial Reservation"
},
{
"fieldname": "section_break_plhx",
"fieldtype": "Section Break"
},
{
"fieldname": "column_break_mhzc",
"fieldtype": "Column Break"
Expand Down Expand Up @@ -400,6 +400,27 @@
"fieldname": "auto_reserve_stock_for_sales_order",
"fieldtype": "Check",
"label": "Auto Reserve Stock for Sales Order"
},
{
"fieldname": "conversion_factor_section",
"fieldtype": "Section Break",
"label": "Stock UOM Quantity"
},
{
"fieldname": "column_break_lznj",
"fieldtype": "Column Break"
},
{
"default": "0",
"fieldname": "allow_to_edit_stock_uom_qty_for_sales",
"fieldtype": "Check",
"label": "Allow to Edit Stock UOM Qty for Sales Documents"
},
{
"default": "0",
"fieldname": "allow_to_edit_stock_uom_qty_for_purchase",
"fieldtype": "Check",
"label": "Allow to Edit Stock UOM Qty for Purchase Documents"
}
],
"icon": "icon-cog",
Expand Down
52 changes: 52 additions & 0 deletions erpnext/stock/doctype/stock_settings/stock_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ def validate(self):
self.validate_clean_description_html()
self.validate_pending_reposts()
self.validate_stock_reservation()
self.change_precision_for_for_sales()
self.change_precision_for_purchase()

def validate_warehouses(self):
warehouse_fields = ["default_warehouse", "sample_retention_warehouse"]
Expand Down Expand Up @@ -167,6 +169,56 @@ def validate_stock_reservation(self):
def on_update(self):
self.toggle_warehouse_field_for_inter_warehouse_transfer()

def change_precision_for_for_sales(self):
doc_before_save = self.get_doc_before_save()
if doc_before_save and (
doc_before_save.allow_to_edit_stock_uom_qty_for_sales
== self.allow_to_edit_stock_uom_qty_for_sales
):
return

if self.allow_to_edit_stock_uom_qty_for_sales:
doctypes = ["Sales Order Item", "Sales Invoice Item", "Delivery Note Item", "Quotation Item"]
self.make_property_setter_for_precision(doctypes)

def change_precision_for_purchase(self):
doc_before_save = self.get_doc_before_save()
if doc_before_save and (
doc_before_save.allow_to_edit_stock_uom_qty_for_purchase
== self.allow_to_edit_stock_uom_qty_for_purchase
):
return

if self.allow_to_edit_stock_uom_qty_for_purchase:
doctypes = [
"Purchase Order Item",
"Purchase Receipt Item",
"Purchase Invoice Item",
"Request for Quotation Item",
"Supplier Quotation Item",
"Material Request Item",
]
self.make_property_setter_for_precision(doctypes)

@staticmethod
def make_property_setter_for_precision(doctypes):
for doctype in doctypes:
if property_name := frappe.db.exists(
"Property Setter",
{"doc_type": doctype, "field_name": "conversion_factor", "property": "precision"},
):
frappe.db.set_value("Property Setter", property_name, "value", 9)
continue

make_property_setter(
doctype,
"conversion_factor",
"precision",
9,
"Float",
validate_fields_for_doctype=False,
)

def toggle_warehouse_field_for_inter_warehouse_transfer(self):
make_property_setter(
"Sales Invoice Item",
Expand Down

0 comments on commit dd4769e

Please sign in to comment.