Merge pull request #38942 from s-aga-r/FIX-38151-2
fix(ux): make PR and PI Item rate field readonly based on `Maintain Same Rate`
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json
index c4492be..09912e9 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.json
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json
@@ -23,6 +23,7 @@
"against_voucher_type",
"against_voucher",
"voucher_type",
+ "voucher_subtype",
"voucher_no",
"voucher_detail_no",
"project",
@@ -138,19 +139,19 @@
"options": "DocType"
},
{
- "fieldname": "against",
- "fieldtype": "Text",
- "in_filter": 1,
- "label": "Against",
- "oldfieldname": "against",
- "oldfieldtype": "Text"
+ "fieldname": "against",
+ "fieldtype": "Text",
+ "in_filter": 1,
+ "label": "Against",
+ "oldfieldname": "against",
+ "oldfieldtype": "Text"
},
{
- "fieldname": "against_link",
- "fieldtype": "Dynamic Link",
- "in_filter": 1,
- "label": "Against",
- "options": "against_type"
+ "fieldname": "against_link",
+ "fieldtype": "Dynamic Link",
+ "in_filter": 1,
+ "label": "Against",
+ "options": "against_type"
},
{
"fieldname": "against_voucher_type",
@@ -294,13 +295,18 @@
"fieldtype": "Currency",
"label": "Credit Amount in Transaction Currency",
"options": "transaction_currency"
+ },
+ {
+ "fieldname": "voucher_subtype",
+ "fieldtype": "Small Text",
+ "label": "Voucher Subtype"
}
],
"icon": "fa fa-list",
"idx": 1,
"in_create": 1,
"links": [],
- "modified": "2023-11-08 12:20:23.031733",
+ "modified": "2023-12-18 15:38:14.006208",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index f7dd29a..139f526 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -39,6 +39,8 @@
account: DF.Link | None
account_currency: DF.Link | None
against: DF.Text | None
+ against_link: DF.DynamicLink | None
+ against_type: DF.Link | None
against_voucher: DF.DynamicLink | None
against_voucher_type: DF.Link | None
company: DF.Link | None
@@ -66,6 +68,7 @@
transaction_exchange_rate: DF.Float
voucher_detail_no: DF.Data | None
voucher_no: DF.DynamicLink | None
+ voucher_subtype: DF.SmallText | None
voucher_type: DF.Link | None
# end: auto-generated types
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index b45ff60..4054dca 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -200,7 +200,7 @@
"""
select
name as gl_entry, posting_date, account, party_type, party,
- voucher_type, voucher_no, {dimension_fields}
+ voucher_type, voucher_subtype, voucher_no, {dimension_fields}
cost_center, project, {transaction_currency_fields}
against_voucher_type, against_voucher, account_currency,
against_link, against, is_opening, creation {select_fields}
@@ -610,6 +610,12 @@
columns += [
{"label": _("Voucher Type"), "fieldname": "voucher_type", "width": 120},
{
+ "label": _("Voucher Subtype"),
+ "fieldname": "voucher_subtype",
+ "fieldtype": "Data",
+ "width": 180,
+ },
+ {
"label": _("Voucher No"),
"fieldname": "voucher_no",
"fieldtype": "Dynamic Link",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index d88424b..febad18 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -874,6 +874,7 @@
"project": self.get("project"),
"post_net_value": args.get("post_net_value"),
"voucher_detail_no": args.get("voucher_detail_no"),
+ "voucher_subtype": self.get_voucher_subtype(),
}
)
@@ -929,6 +930,25 @@
return gl_dict
+ def get_voucher_subtype(self):
+ voucher_subtypes = {
+ "Journal Entry": "voucher_type",
+ "Payment Entry": "payment_type",
+ "Stock Entry": "stock_entry_type",
+ "Asset Capitalization": "entry_type",
+ }
+ if self.doctype in voucher_subtypes:
+ return self.get(voucher_subtypes[self.doctype])
+ elif self.doctype == "Purchase Receipt" and self.is_return:
+ return "Purchase Return"
+ elif self.doctype == "Delivery Note" and self.is_return:
+ return "Sales Return"
+ elif (self.doctype == "Sales Invoice" and self.is_return) or self.doctype == "Purchase Invoice":
+ return "Credit Note"
+ elif (self.doctype == "Purchase Invoice" and self.is_return) or self.doctype == "Sales Invoice":
+ return "Debit Note"
+ return self.doctype
+
def get_value_in_transaction_currency(self, account_currency, args, field):
if account_currency == self.get("currency"):
return args.get(field + "_in_account_currency")
diff --git a/erpnext/public/js/utils/sales_common.js b/erpnext/public/js/utils/sales_common.js
index 084cca7..b92b02e 100644
--- a/erpnext/public/js/utils/sales_common.js
+++ b/erpnext/public/js/utils/sales_common.js
@@ -184,6 +184,12 @@
refresh_field("incentives",row.name,row.parentfield);
}
+ warehouse(doc, cdt, cdn) {
+ if (doc.docstatus === 0 && doc.is_return && !doc.return_against) {
+ frappe.model.set_value(cdt, cdn, "incoming_rate", 0.0);
+ }
+ }
+
toggle_editable_price_list_rate() {
var df = frappe.meta.get_docfield(this.frm.doc.doctype + " Item", "price_list_rate", this.frm.doc.name);
var editable_price_list_rate = cint(frappe.defaults.get_default("editable_price_list_rate"));
diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
index 24650fd..7e03ac3 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
+++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
@@ -9,7 +9,7 @@
from frappe.query_builder.functions import Sum
from frappe.utils import cint, flt
-from erpnext.stock.utils import get_or_make_bin
+from erpnext.stock.utils import get_or_make_bin, get_stock_balance
class StockReservationEntry(Document):
@@ -151,7 +151,7 @@
"""Validates `Reserved Qty` when `Reservation Based On` is `Qty`."""
if self.reservation_based_on == "Qty":
- self.validate_with_max_reserved_qty(self.reserved_qty)
+ self.validate_with_allowed_qty(self.reserved_qty)
def auto_reserve_serial_and_batch(self, based_on: str = None) -> None:
"""Auto pick Serial and Batch Nos to reserve when `Reservation Based On` is `Serial and Batch`."""
@@ -324,7 +324,7 @@
frappe.throw(msg)
# Should be called after validating Serial and Batch Nos.
- self.validate_with_max_reserved_qty(qty_to_be_reserved)
+ self.validate_with_allowed_qty(qty_to_be_reserved)
self.db_set("reserved_qty", qty_to_be_reserved)
def update_reserved_qty_in_voucher(
@@ -429,7 +429,7 @@
msg = _("Stock Reservation Entry cannot be updated as it has been delivered.")
frappe.throw(msg)
- def validate_with_max_reserved_qty(self, qty_to_be_reserved: float) -> None:
+ def validate_with_allowed_qty(self, qty_to_be_reserved: float) -> None:
"""Validates `Reserved Qty` with `Max Reserved Qty`."""
self.db_set(
@@ -448,12 +448,12 @@
)
voucher_delivered_qty = flt(delivered_qty) * flt(conversion_factor)
- max_reserved_qty = min(
+ allowed_qty = min(
self.available_qty, (self.voucher_qty - voucher_delivered_qty - total_reserved_qty)
)
- if max_reserved_qty <= 0 and self.voucher_type == "Sales Order":
- msg = _("Item {0} is already delivered for Sales Order {1}.").format(
+ if self.get("_action") != "submit" and self.voucher_type == "Sales Order" and allowed_qty <= 0:
+ msg = _("Item {0} is already reserved/delivered against Sales Order {1}.").format(
frappe.bold(self.item_code), frappe.bold(self.voucher_no)
)
@@ -463,19 +463,33 @@
else:
frappe.throw(msg)
- if qty_to_be_reserved > max_reserved_qty:
+ if qty_to_be_reserved > allowed_qty:
+ actual_qty = get_stock_balance(self.item_code, self.warehouse)
msg = """
- Cannot reserve more than Max Reserved Qty {0} {1}.<br /><br />
- The <b>Max Reserved Qty</b> is calculated as follows:<br />
+ Cannot reserve more than Allowed Qty {0} {1} for Item {2} against {3} {4}.<br /><br />
+ The <b>Allowed Qty</b> is calculated as follows:<br />
<ul>
- <li><b>Available Qty To Reserve</b> = (Actual Stock Qty - Reserved Stock Qty)</li>
- <li><b>Voucher Qty</b> = Voucher Item Qty</li>
- <li><b>Delivered Qty</b> = Qty delivered against the Voucher Item</li>
- <li><b>Total Reserved Qty</b> = Qty reserved against the Voucher Item</li>
- <li><b>Max Reserved Qty</b> = Minimum of (Available Qty To Reserve, (Voucher Qty - Delivered Qty - Total Reserved Qty))</li>
+ <li>Actual Qty [Available Qty at Warehouse] = {5}</li>
+ <li>Reserved Stock [Ignore current SRE] = {6}</li>
+ <li>Available Qty To Reserve [Actual Qty - Reserved Stock] = {7}</li>
+ <li>Voucher Qty [Voucher Item Qty] = {8}</li>
+ <li>Delivered Qty [Qty delivered against the Voucher Item] = {9}</li>
+ <li>Total Reserved Qty [Qty reserved against the Voucher Item] = {10}</li>
+ <li>Allowed Qty [Minimum of (Available Qty To Reserve, (Voucher Qty - Delivered Qty - Total Reserved Qty))] = {11}</li>
</ul>
""".format(
- frappe.bold(max_reserved_qty), self.stock_uom
+ frappe.bold(allowed_qty),
+ self.stock_uom,
+ frappe.bold(self.item_code),
+ self.voucher_type,
+ frappe.bold(self.voucher_no),
+ actual_qty,
+ actual_qty - self.available_qty,
+ self.available_qty,
+ self.voucher_qty,
+ voucher_delivered_qty,
+ total_reserved_qty,
+ allowed_qty,
)
frappe.throw(msg)
@@ -509,7 +523,6 @@
"""Returns `Available Qty to Reserve (Actual Qty - Reserved Qty)` for Item, Warehouse and Batch combination."""
from erpnext.stock.doctype.batch.batch import get_batch_qty
- from erpnext.stock.utils import get_stock_balance
if batch_no:
return get_batch_qty(
diff --git a/erpnext/stock/report/reserved_stock/reserved_stock.js b/erpnext/stock/report/reserved_stock/reserved_stock.js
index 6872741..2b075e2 100644
--- a/erpnext/stock/report/reserved_stock/reserved_stock.js
+++ b/erpnext/stock/report/reserved_stock/reserved_stock.js
@@ -149,34 +149,36 @@
formatter: (value, row, column, data, default_formatter) => {
value = default_formatter(value, row, column, data);
- if (column.fieldname == "status") {
- switch (data.status) {
- case "Partially Reserved":
- value = "<span style='color:orange'>" + value + "</span>";
- break;
- case "Reserved":
- value = "<span style='color:blue'>" + value + "</span>";
- break;
- case "Partially Delivered":
- value = "<span style='color:purple'>" + value + "</span>";
- break;
- case "Delivered":
- value = "<span style='color:green'>" + value + "</span>";
- break;
+ if (data) {
+ if (column.fieldname == "status") {
+ switch (data.status) {
+ case "Partially Reserved":
+ value = "<span style='color:orange'>" + value + "</span>";
+ break;
+ case "Reserved":
+ value = "<span style='color:blue'>" + value + "</span>";
+ break;
+ case "Partially Delivered":
+ value = "<span style='color:purple'>" + value + "</span>";
+ break;
+ case "Delivered":
+ value = "<span style='color:green'>" + value + "</span>";
+ break;
+ }
}
- }
- else if (column.fieldname == "delivered_qty") {
- if (data.delivered_qty > 0) {
- if (data.reserved_qty > data.delivered_qty) {
- value = "<span style='color:blue'>" + value + "</span>";
+ else if (column.fieldname == "delivered_qty") {
+ if (data.delivered_qty > 0) {
+ if (data.reserved_qty > data.delivered_qty) {
+ value = "<span style='color:blue'>" + value + "</span>";
+ }
+ else {
+ value = "<span style='color:green'>" + value + "</span>";
+ }
}
else {
- value = "<span style='color:green'>" + value + "</span>";
+ value = "<span style='color:red'>" + value + "</span>";
}
}
- else {
- value = "<span style='color:red'>" + value + "</span>";
- }
}
return value;
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index 2745d4d..d05d0d9 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -103,6 +103,7 @@
Actual Qty {0} / Waiting Qty {1},Tatsächliche Menge {0} / Wartezeit {1},
Actual Qty: Quantity available in the warehouse.,Tatsächliche Menge: Menge verfügbar im Lager.,
Actual qty in stock,Tatsächliche Menge auf Lager,
+Actual Time (in Hours via Time Sheet), IST Zeit (in Stunden aus Zeiterfassung),
Actual type tax cannot be included in Item rate in row {0},Tatsächliche Steuerart kann nicht im Artikelpreis in Zeile {0} beinhaltet sein,
Add,Hinzufügen,
Add / Edit Prices,Preise hinzufügen / bearbeiten,