mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-29 09:54:47 +00:00
Release v15.41.2 (#44037)
* fix: improved the conditions for determining voucher subtypes (cherry picked from commit00eee16190) * fix: patch (cherry picked from commitd76cc21086) # Conflicts: # erpnext/patches.txt * test: test voucher subtype for sales invoice (cherry picked from commitad6cc352f1) * chore: resolve conflict * fix: NoneType while updating ordered_qty in SO for removed items (cherry picked from commit442cdd7ce4) * refactor: add "margin_type" and "margin_rate_or_amount" to no copy (cherry picked from commit70f090c1ec) * fix: item not set in the batch quick entry form (backport #44028) (#44031) fix: item not set in the batch quick entry form (#44028) (cherry picked from commit0399ccc51e) Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com> * fix: calculate percentage received and delivered considering over-receipt and over-delivery (backport #43870) (#44030) fix: calculate percentage received and delivered considering over-receipt and over-delivery (#43870) (cherry picked from commitadba1168c1) Co-authored-by: Nabin Hait <nabinhait@gmail.com> * fix: sort by ascending to get the first period closing voucher (backport #44029) (#44035) fix: sort by ascending to get the first period closing voucher (#44029) (cherry picked from commit42dcdcde1a) Co-authored-by: Venkatesh <47534423+venkat102@users.noreply.github.com> --------- Co-authored-by: ljain112 <ljain112@gmail.com> Co-authored-by: Smit Vora <smitvora203@gmail.com> Co-authored-by: ruthra kumar <ruthra@erpnext.com> Co-authored-by: bhaveshkumar.j <bhaveshkumar.j@sritindia.com> Co-authored-by: Ravindu Nethmina <117300601+NethminaHiker360@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com> Co-authored-by: Venkatesh <47534423+venkat102@users.noreply.github.com>
This commit is contained in:
@@ -417,7 +417,7 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
"Period Closing Voucher",
|
"Period Closing Voucher",
|
||||||
{"company": self.company, "docstatus": 1},
|
{"company": self.company, "docstatus": 1},
|
||||||
"name",
|
"name",
|
||||||
order_by="period_end_date",
|
order_by="period_end_date asc",
|
||||||
)
|
)
|
||||||
|
|
||||||
if not first_pcv or first_pcv == self.name:
|
if not first_pcv or first_pcv == self.name:
|
||||||
|
|||||||
@@ -4005,6 +4005,25 @@ class TestSalesInvoice(FrappeTestCase):
|
|||||||
si.submit()
|
si.submit()
|
||||||
self.assertEqual(si.remarks, f"Against Customer Order Test PO dated {format_date(nowdate())}")
|
self.assertEqual(si.remarks, f"Against Customer Order Test PO dated {format_date(nowdate())}")
|
||||||
|
|
||||||
|
def test_gl_voucher_subtype(self):
|
||||||
|
si = create_sales_invoice()
|
||||||
|
gl_entries = frappe.get_all(
|
||||||
|
"GL Entry",
|
||||||
|
filters={"voucher_type": "Sales Invoice", "voucher_no": si.name},
|
||||||
|
pluck="voucher_subtype",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertTrue(all([x == "Sales Invoice" for x in gl_entries]))
|
||||||
|
|
||||||
|
si = create_sales_invoice(is_return=1, qty=-1)
|
||||||
|
gl_entries = frappe.get_all(
|
||||||
|
"GL Entry",
|
||||||
|
filters={"voucher_type": "Sales Invoice", "voucher_no": si.name},
|
||||||
|
pluck="voucher_subtype",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertTrue(all([x == "Credit Note" for x in gl_entries]))
|
||||||
|
|
||||||
|
|
||||||
def set_advance_flag(company, flag, default_account):
|
def set_advance_flag(company, flag, default_account):
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ class PurchaseOrder(BuyingController):
|
|||||||
def update_receiving_percentage(self):
|
def update_receiving_percentage(self):
|
||||||
total_qty, received_qty = 0.0, 0.0
|
total_qty, received_qty = 0.0, 0.0
|
||||||
for item in self.items:
|
for item in self.items:
|
||||||
received_qty += item.received_qty
|
received_qty += min(item.received_qty, item.qty)
|
||||||
total_qty += item.qty
|
total_qty += item.qty
|
||||||
if total_qty:
|
if total_qty:
|
||||||
self.db_set("per_received", flt(received_qty / total_qty) * 100, update_modified=False)
|
self.db_set("per_received", flt(received_qty / total_qty) * 100, update_modified=False)
|
||||||
@@ -625,9 +625,11 @@ class PurchaseOrder(BuyingController):
|
|||||||
if not self.is_against_so():
|
if not self.is_against_so():
|
||||||
return
|
return
|
||||||
for item in removed_items:
|
for item in removed_items:
|
||||||
prev_ordered_qty = frappe.get_cached_value(
|
prev_ordered_qty = (
|
||||||
"Sales Order Item", item.get("sales_order_item"), "ordered_qty"
|
frappe.get_cached_value("Sales Order Item", item.get("sales_order_item"), "ordered_qty")
|
||||||
|
or 0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
"Sales Order Item", item.get("sales_order_item"), "ordered_qty", prev_ordered_qty - item.qty
|
"Sales Order Item", item.get("sales_order_item"), "ordered_qty", prev_ordered_qty - item.qty
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1096,9 +1096,11 @@ class AccountsController(TransactionBase):
|
|||||||
return "Purchase Return"
|
return "Purchase Return"
|
||||||
elif self.doctype == "Delivery Note" and self.is_return:
|
elif self.doctype == "Delivery Note" and self.is_return:
|
||||||
return "Sales Return"
|
return "Sales Return"
|
||||||
elif (self.doctype == "Sales Invoice" and self.is_return) or self.doctype == "Purchase Invoice":
|
elif self.doctype == "Sales Invoice" and self.is_return:
|
||||||
return "Credit Note"
|
return "Credit Note"
|
||||||
elif (self.doctype == "Purchase Invoice" and self.is_return) or self.doctype == "Sales Invoice":
|
elif self.doctype == "Sales Invoice" and self.is_debit_note:
|
||||||
|
return "Debit Note"
|
||||||
|
elif self.doctype == "Purchase Invoice" and self.is_return:
|
||||||
return "Debit Note"
|
return "Debit Note"
|
||||||
|
|
||||||
return self.doctype
|
return self.doctype
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ erpnext.patches.v15_0.update_asset_value_for_manual_depr_entries
|
|||||||
erpnext.patches.v15_0.update_gpa_and_ndb_for_assdeprsch
|
erpnext.patches.v15_0.update_gpa_and_ndb_for_assdeprsch
|
||||||
erpnext.patches.v14_0.create_accounting_dimensions_for_closing_balance
|
erpnext.patches.v14_0.create_accounting_dimensions_for_closing_balance
|
||||||
erpnext.patches.v14_0.set_period_start_end_date_in_pcv
|
erpnext.patches.v14_0.set_period_start_end_date_in_pcv
|
||||||
erpnext.patches.v14_0.update_closing_balances #29-10-2024
|
erpnext.patches.v14_0.update_closing_balances #08-11-2024
|
||||||
execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
|
execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
|
||||||
erpnext.patches.v14_0.update_reference_type_in_journal_entry_accounts
|
erpnext.patches.v14_0.update_reference_type_in_journal_entry_accounts
|
||||||
erpnext.patches.v14_0.update_subscription_details
|
erpnext.patches.v14_0.update_subscription_details
|
||||||
@@ -381,3 +381,4 @@ erpnext.patches.v15_0.set_standard_stock_entry_type
|
|||||||
erpnext.patches.v15_0.link_purchase_item_to_asset_doc
|
erpnext.patches.v15_0.link_purchase_item_to_asset_doc
|
||||||
erpnext.patches.v14_0.update_currency_exchange_settings_for_frankfurter
|
erpnext.patches.v14_0.update_currency_exchange_settings_for_frankfurter
|
||||||
erpnext.patches.v15_0.update_task_assignee_email_field_in_asset_maintenance_log
|
erpnext.patches.v15_0.update_task_assignee_email_field_in_asset_maintenance_log
|
||||||
|
erpnext.patches.v15_0.update_sub_voucher_type_in_gl_entries
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
update_purchase_invoices()
|
||||||
|
update_sales_invoices()
|
||||||
|
update_sales_debit_notes()
|
||||||
|
|
||||||
|
|
||||||
|
def update_purchase_invoices():
|
||||||
|
invoices = frappe.get_all(
|
||||||
|
"Purchase Invoice",
|
||||||
|
filters={"docstatus": 1, "is_return": 0},
|
||||||
|
pluck="name",
|
||||||
|
)
|
||||||
|
|
||||||
|
if not invoices:
|
||||||
|
return
|
||||||
|
|
||||||
|
update_gl_entry(doctype="Purchase Invoice", invoices=invoices, value="Purchase Invoice")
|
||||||
|
|
||||||
|
|
||||||
|
def update_sales_invoices():
|
||||||
|
invoices = frappe.get_all(
|
||||||
|
"Sales Invoice",
|
||||||
|
filters={"docstatus": 1, "is_return": 0, "is_debit_note": 0},
|
||||||
|
pluck="name",
|
||||||
|
)
|
||||||
|
if not invoices:
|
||||||
|
return
|
||||||
|
|
||||||
|
update_gl_entry(doctype="Sales Invoice", invoices=invoices, value="Sales Invoice")
|
||||||
|
|
||||||
|
|
||||||
|
def update_sales_debit_notes():
|
||||||
|
invoices = frappe.get_all(
|
||||||
|
"Sales Invoice",
|
||||||
|
filters={"docstatus": 1, "is_debit_note": 1},
|
||||||
|
pluck="name",
|
||||||
|
)
|
||||||
|
|
||||||
|
if not invoices:
|
||||||
|
return
|
||||||
|
|
||||||
|
update_gl_entry(doctype="Sales Invoice", invoices=invoices, value="Debit Note")
|
||||||
|
|
||||||
|
|
||||||
|
def update_gl_entry(doctype, invoices, value):
|
||||||
|
gl_entry = frappe.qb.DocType("GL Entry")
|
||||||
|
(
|
||||||
|
frappe.qb.update(gl_entry)
|
||||||
|
.set("voucher_subtype", value)
|
||||||
|
.where(gl_entry.voucher_subtype.isnotnull())
|
||||||
|
.where(gl_entry.voucher_no.isin(invoices))
|
||||||
|
.where(gl_entry.voucher_type == doctype)
|
||||||
|
.run()
|
||||||
|
)
|
||||||
@@ -289,28 +289,6 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.frm.fields_dict['items'].grid.get_field('serial_and_batch_bundle')) {
|
|
||||||
let sbb_field = this.frm.get_docfield('items', 'serial_and_batch_bundle');
|
|
||||||
if (sbb_field) {
|
|
||||||
sbb_field.get_route_options_for_new_doc = (row) => {
|
|
||||||
return {
|
|
||||||
'item_code': row.doc.item_code,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.frm.fields_dict['items'].grid.get_field('batch_no')) {
|
|
||||||
let batch_no_field = this.frm.get_docfield('items', 'batch_no');
|
|
||||||
if (batch_no_field) {
|
|
||||||
batch_no_field.get_route_options_for_new_doc = function(row) {
|
|
||||||
return {
|
|
||||||
'item': row.doc.item_code
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is_return() {
|
is_return() {
|
||||||
@@ -409,6 +387,35 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
|||||||
this.setup_quality_inspection();
|
this.setup_quality_inspection();
|
||||||
this.validate_has_items();
|
this.validate_has_items();
|
||||||
erpnext.utils.view_serial_batch_nos(this.frm);
|
erpnext.utils.view_serial_batch_nos(this.frm);
|
||||||
|
this.set_route_options_for_new_doc();
|
||||||
|
}
|
||||||
|
|
||||||
|
set_route_options_for_new_doc() {
|
||||||
|
// While creating the batch from the link field, copy item from line item to batch form
|
||||||
|
|
||||||
|
if(this.frm.fields_dict['items'].grid.get_field('batch_no')) {
|
||||||
|
let batch_no_field = this.frm.get_docfield('items', 'batch_no');
|
||||||
|
if (batch_no_field) {
|
||||||
|
batch_no_field.get_route_options_for_new_doc = function(row) {
|
||||||
|
return {
|
||||||
|
'item': row.doc.item_code
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// While creating the SABB from the link field, copy item, doctype from line item to SABB form
|
||||||
|
if(this.frm.fields_dict['items'].grid.get_field('serial_and_batch_bundle')) {
|
||||||
|
let sbb_field = this.frm.get_docfield('items', 'serial_and_batch_bundle');
|
||||||
|
if (sbb_field) {
|
||||||
|
sbb_field.get_route_options_for_new_doc = (row) => {
|
||||||
|
return {
|
||||||
|
"item_code": row.doc.item_code,
|
||||||
|
"voucher_type": this.frm.doc.doctype,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_barcode() {
|
scan_barcode() {
|
||||||
|
|||||||
@@ -584,7 +584,7 @@ class SalesOrder(SellingController):
|
|||||||
item_delivered_qty = item_delivered_qty[0][0] if item_delivered_qty else 0
|
item_delivered_qty = item_delivered_qty[0][0] if item_delivered_qty else 0
|
||||||
item.db_set("delivered_qty", flt(item_delivered_qty), update_modified=False)
|
item.db_set("delivered_qty", flt(item_delivered_qty), update_modified=False)
|
||||||
|
|
||||||
delivered_qty += item.delivered_qty
|
delivered_qty += min(item.delivered_qty, item.qty)
|
||||||
tot_qty += item.qty
|
tot_qty += item.qty
|
||||||
|
|
||||||
if tot_qty != 0:
|
if tot_qty != 0:
|
||||||
@@ -1347,6 +1347,8 @@ def make_purchase_order_for_default_supplier(source_name, selected_items=None, t
|
|||||||
"discount_percentage",
|
"discount_percentage",
|
||||||
"discount_amount",
|
"discount_amount",
|
||||||
"pricing_rules",
|
"pricing_rules",
|
||||||
|
"margin_type",
|
||||||
|
"margin_rate_or_amount",
|
||||||
],
|
],
|
||||||
"postprocess": update_item,
|
"postprocess": update_item,
|
||||||
"condition": lambda doc: doc.ordered_qty < doc.stock_qty
|
"condition": lambda doc: doc.ordered_qty < doc.stock_qty
|
||||||
|
|||||||
Reference in New Issue
Block a user