Skip to content

Commit

Permalink
chore: release v15 (#42024)
Browse files Browse the repository at this point in the history
* fix(Sales Order): only show permitted actions

(cherry picked from commit c29d955)

* fix(Delivery Note): only show permitted actions

(cherry picked from commit 418bdc1)

* fix: do not show zero balance stock items in stock balance report (backport #41958) (#41961)

fix: do not show zero balance stock in stock balance

(cherry picked from commit 7f7b363)

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>

* fix: add string for translation (backport #41903) (#41963)

fix: add string for translation (#41903)

fix: add string for translation
(cherry picked from commit f28c692)

Co-authored-by: mahsem <137205921+mahsem@users.noreply.github.com>

* refactor: remove use of can_create for Payment Request (#41647)

(cherry picked from commit 47bc569)

* fix: move condition for shipment

* fix: incorrect discount on other item

When discount is applied on other item, don't update `discount_amount`
as the amount is calculated for current item

(cherry picked from commit 654764e)

* fix: incorrect against_account upon reposting

(cherry picked from commit 20c4098)

* fix: decimal issue in pick list (backport #41972) (#41982)

fix: decimal issue in pick list (#41972)

(cherry picked from commit 21adc7b)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* refactor: renamed number of depreciations booked to opening booked de… (#41515)

* refactor: renamed number of depreciations booked to opening booked depreciations

* feat: introduced new field for showing total number of booked depreciations

* fix: reload asset when creating asset depreciation

* chore: added nosemgrep for security checks

* feat: default account head for operating cost (backport #41985) (#41987)

* feat: default account head for operating cost (#41985)

(cherry picked from commit fd7666a)

# Conflicts:
#	erpnext/manufacturing/doctype/bom/bom.py
#	erpnext/setup/doctype/company/company.json

* chore: fix conflicts

* chore: fix conflicts

* chore: fix conflicts

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* perf: dont run queries unnecessarily, improved filters (#41993)

* perf: dont run queries unnecessarily, improved filters

* perf: dont run query if `in` filter is empty

(cherry picked from commit ac6d85a)

* chore: remove validation on payment entry

(cherry picked from commit e774003)

* refactor: convert amount to base currency for advances

(cherry picked from commit c9ede1f)

* refactor: for advances uses the party account in references table

(cherry picked from commit 7dce6e0)

* refactor(test): simpler create_account helper method

(cherry picked from commit 475e0dd)

* test: exc gain/loss booking on advances under asset/liability

(cherry picked from commit 827d67d)

* test: advance against purchase invoice

(cherry picked from commit 90c8482)

* refactor: validation to force accounts to be on same currency

(cherry picked from commit 0f0b4d8)

* refactor: validation in customer group

(cherry picked from commit 4f9a228)

* refactor: validation in Supplier Group

(cherry picked from commit 107b614)

* refactor: better error messages

(cherry picked from commit 83ff94b)

* chore: fix test data

(cherry picked from commit 07d5944)

* chore: remove dead code

(cherry picked from commit 7e318c0)

* fix(test): incorrect field for customer default billing currency

(cherry picked from commit c696d13)

* refactor(test): enfore use of customer/supplier master

While using advance accounts in foreign currency, always use
Customer/Supplier master to maintain them

(cherry picked from commit 64e6388)

* refactor(test): make and use a different party for subscription

(cherry picked from commit 3fabf4a)

* fix: pricing rule with and without 'apply multiple' and priority

Either all of the pricing rules identified for an item should have
'apply multiple' enabled. If not, Priority is applied and only the
highest priority is applied

(cherry picked from commit 5e875b2)

* test: priority takes effect on with and without apply multiple

(cherry picked from commit efebc36)

* feat: accounting dimension filters in gp report

(cherry picked from commit d165638)

* feat(gp): group by cost center

(cherry picked from commit e26bc17)

* fix: Wrong Delete Batch on Purchase Receipt (backport #42007) (#42012)

fix: Wrong Delete Batch on Purchase Receipt (#42007)

(cherry picked from commit d50487c)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* fix: incorrect Difference Amount (backport #42008) (#42013)

fix: incorrect Difference Amount (#42008)

(cherry picked from commit 7d91c6c)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* fix: valuation rate for the legacy batches (backport #42011) (#42020)

fix: valuation rate for the legacy batches (#42011)

(cherry picked from commit 9ab333d)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* fix: timeout while cancelling LCV (backport #42030) (backport #42031) (#42032)

fix: timeout while cancelling LCV (backport #42030) (#42031)

fix: timeout while cancelling LCV (#42030)

fix: timeout while canelling LCV
(cherry picked from commit 21bf7fd)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
(cherry picked from commit 2e76b9f)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

* fix: Stock Reservation Entry was not getting created (backport #42033) (#42035)

fix: Stock Reservation Entry was not getting created (#42033)

(cherry picked from commit 1a9899b)

Co-authored-by: Poorvi-R-Bhat <poorvi.r.bhat@gmail.com>

* fix: manufacturing date issue in the batch (backport #42034) (#42037)

* fix: manufacturing date issue in the batch (#42034)

(cherry picked from commit eca3e02)

# Conflicts:
#	erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py

* chore: fix conflicts

---------

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>

* fix: fixed asset value in Fixed Asset Register (backport #41930) (#42027)

fix: fixed asset value in Fixed Asset Register (#41930)

(cherry picked from commit 1c643a0)

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>

* feat: Turkish Chart Of Accounts (backport #41756) (#42028)

* feat: Create Turkish Chart Of Accounts

(cherry picked from commit 5c8ea86)

* feat: Create Turkish Chart Of Accounts

(cherry picked from commit b401ba2)

---------

Co-authored-by: fzozyurt <fzozyurt@outlook.com>

* perf: code optimization to handle large asset creation (backport #42018) (#42025)

perf: code optimization to handle large asset creation (#42018)

(cherry picked from commit 5738d93)

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>

* fix: incorrect time period in asset depreciation schedule (backport #41805) (#42043)

fix: incorrect time period in asset depreciation schedule (#41805)

* fix(wip): depreciation calculation for existing asset

* fix(wip): added validation for incorrect depreciation period

* fix: depreciation schedule time period issue for existing asset

* chore: run pre-commit checks and apply fixes

* style: apply formatting changes

* style: made some necessary changes

* chore: modified test

(cherry picked from commit 625f16d)

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>

* chore: patch to enable total number of booked depreciations field (backport #41940) (#42042)

* chore: patch to enable total number of booked depreciations field (#41940)

* chore: patch to enable total number of booked depreciations field

* fix: conflict resolved

* refactor: replaced fb_row.db_set with set_value

(cherry picked from commit 5fdd1d3)

# Conflicts:
#	erpnext/patches.txt

* fix: resolved conflicts

* fix: removed unmerged patches

---------

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>

* fix: lead status filter (backport #41816) (#42046)

fix: lead status filter (#41816)

(cherry picked from commit 8ae2b8f)

Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>

* fix: unhide serial no field (backport #42045) (#42047)

* fix: unhide serial no field (#42045)

(cherry picked from commit 80c6981)

# Conflicts:
#	erpnext/assets/doctype/asset_capitalization_stock_item/asset_capitalization_stock_item.json

* fix: resolved conflicts

---------

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>

---------

Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
Co-authored-by: mahsem <137205921+mahsem@users.noreply.github.com>
Co-authored-by: ruthra kumar <ruthra@erpnext.com>
Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>
Co-authored-by: Sagar Vora <sagar@resilient.tech>
Co-authored-by: Dany Robert <danyrt@wahni.com>
Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
Co-authored-by: Poorvi-R-Bhat <poorvi.r.bhat@gmail.com>
Co-authored-by: fzozyurt <fzozyurt@outlook.com>
Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com>
  • Loading branch information
13 people committed Jun 26, 2024
1 parent e99ef57 commit b7eabc3
Show file tree
Hide file tree
Showing 57 changed files with 2,629 additions and 854 deletions.

This file was deleted.

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions erpnext/accounts/doctype/journal_entry/journal_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ def on_submit(self):
self.update_asset_value()
self.update_inter_company_jv()
self.update_invoice_discounting()
self.update_booked_depreciation()

def on_update_after_submit(self):
if hasattr(self, "repost_required"):
Expand Down Expand Up @@ -225,6 +226,7 @@ def on_cancel(self):
self.unlink_inter_company_jv()
self.unlink_asset_adjustment_entry()
self.update_invoice_discounting()
self.update_booked_depreciation(1)

def get_title(self):
return self.pay_to_recd_from or self.accounts[0].account
Expand Down Expand Up @@ -439,6 +441,25 @@ def _validate_invoice_discounting_status(inv_disc, id_status, expected_status, r
if status:
inv_disc_doc.set_status(status=status)

def update_booked_depreciation(self, cancel=0):
for d in self.get("accounts"):
if (
self.voucher_type == "Depreciation Entry"
and d.reference_type == "Asset"
and d.reference_name
and frappe.get_cached_value("Account", d.account, "root_type") == "Expense"
and d.debit
):
asset = frappe.get_doc("Asset", d.reference_name)
for fb_row in asset.get("finance_books"):
if fb_row.finance_book == self.finance_book:
if cancel:
fb_row.total_number_of_booked_depreciations -= 1
else:
fb_row.total_number_of_booked_depreciations += 1
fb_row.db_update()
break

def unlink_advance_entry_reference(self):
for d in self.get("accounts"):
if d.is_advance == "Yes" and d.reference_type in ("Sales Invoice", "Purchase Invoice"):
Expand Down
21 changes: 2 additions & 19 deletions erpnext/accounts/doctype/payment_entry/payment_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ def validate(self):
self.setup_party_account_field()
self.set_missing_values()
self.set_liability_account()
self.validate_advance_account_currency()
self.set_missing_ref_details(force=True)
self.validate_payment_type()
self.validate_party_details()
Expand Down Expand Up @@ -163,22 +162,6 @@ def set_liability_account(self):
alert=True,
)

def validate_advance_account_currency(self):
if self.book_advance_payments_in_separate_party_account is True:
company_currency = frappe.get_cached_value("Company", self.company, "default_currency")
if self.payment_type == "Receive" and self.paid_from_account_currency != company_currency:
frappe.throw(
_("Booking advances in foreign currency account: {0} ({1}) is not yet supported.").format(
frappe.bold(self.paid_from), frappe.bold(self.paid_from_account_currency)
)
)
if self.payment_type == "Pay" and self.paid_to_account_currency != company_currency:
frappe.throw(
_("Booking advances in foreign currency account: {0} ({1}) is not yet supported.").format(
frappe.bold(self.paid_to), frappe.bold(self.paid_to_account_currency)
)
)

def on_cancel(self):
self.ignore_linked_doctypes = (
"GL Entry",
Expand Down Expand Up @@ -1266,7 +1249,7 @@ def add_advance_gl_for_reference(self, gl_entries, invoice):

dr_or_cr, account = self.get_dr_and_account_for_advances(invoice)
args_dict["account"] = account
args_dict[dr_or_cr] = invoice.allocated_amount
args_dict[dr_or_cr] = self.calculate_base_allocated_amount_for_reference(invoice)
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
args_dict.update(
{
Expand All @@ -1285,7 +1268,7 @@ def add_advance_gl_for_reference(self, gl_entries, invoice):
args_dict[dr_or_cr + "_in_account_currency"] = 0
dr_or_cr = "debit" if dr_or_cr == "credit" else "credit"
args_dict["account"] = self.party_account
args_dict[dr_or_cr] = invoice.allocated_amount
args_dict[dr_or_cr] = self.calculate_base_allocated_amount_for_reference(invoice)
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
args_dict.update(
{
Expand Down
62 changes: 62 additions & 0 deletions erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,68 @@ def test_priority_of_multiple_pricing_rules(self):
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 1")
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 2")

def test_pricing_rules_with_and_without_apply_multiple(self):
item = make_item("PR Item 99")

test_records = [
{
"doctype": "Pricing Rule",
"title": "_Test discount on item group",
"name": "_Test discount on item group",
"apply_on": "Item Group",
"item_groups": [
{
"item_group": "Products",
}
],
"selling": 1,
"price_or_product_discount": "Price",
"rate_or_discount": "Discount Percentage",
"discount_percentage": 60,
"has_priority": 1,
"company": "_Test Company",
"apply_multiple_pricing_rules": True,
},
{
"doctype": "Pricing Rule",
"title": "_Test fixed rate on item code",
"name": "_Test fixed rate on item code",
"apply_on": "Item Code",
"items": [
{
"item_code": item.name,
}
],
"selling": 1,
"price_or_product_discount": "Price",
"rate_or_discount": "Rate",
"rate": 25,
"has_priority": 1,
"company": "_Test Company",
"apply_multiple_pricing_rules": False,
},
]

for item_group_priority, item_code_priority in [(2, 4), (4, 2)]:
item_group_rule = frappe.get_doc(test_records[0].copy())
item_group_rule.priority = item_group_priority
item_group_rule.insert()

item_code_rule = frappe.get_doc(test_records[1].copy())
item_code_rule.priority = item_code_priority
item_code_rule.insert()

si = create_sales_invoice(qty=5, customer="_Test Customer 1", item=item.name, do_not_submit=True)
si.save()
self.assertEqual(len(si.pricing_rules), 1)
# Item Code rule should've applied as it has higher priority
expected_rule = item_group_rule if item_group_priority > item_code_priority else item_code_rule
self.assertEqual(si.pricing_rules[0].pricing_rule, expected_rule.name)

si.delete()
item_group_rule.delete()
item_code_rule.delete()


test_dependencies = ["Campaign"]

Expand Down
9 changes: 3 additions & 6 deletions erpnext/accounts/doctype/pricing_rule/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,9 @@ def _get_pricing_rules(apply_on, args, values):


def apply_multiple_pricing_rules(pricing_rules):
apply_multiple_rule = [
d.apply_multiple_pricing_rules for d in pricing_rules if d.apply_multiple_pricing_rules
]

if not apply_multiple_rule:
return False
for d in pricing_rules:
if not d.apply_multiple_pricing_rules:
return False

return True

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -593,14 +593,18 @@ def validate_expense_account(self):
for item in self.get("items"):
validate_account_head(item.idx, item.expense_account, self.company, "Expense")

def set_against_expense_account(self):
def set_against_expense_account(self, force=False):
against_accounts = []
for item in self.get("items"):
if item.expense_account and (item.expense_account not in against_accounts):
against_accounts.append(item.expense_account)

self.against_expense_account = ",".join(against_accounts)

def force_set_against_expense_account(self):
self.set_against_expense_account()
frappe.db.set_value(self.doctype, self.name, "against_expense_account", self.against_expense_account)

def po_required(self):
if frappe.db.get_value("Buying Settings", None, "po_required") == "Yes":
if frappe.get_value(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ def start_repost(account_repost_doc=str) -> None:
doc.make_gl_entries_on_cancel()

doc.docstatus = 1
if doc.doctype == "Sales Invoice":
doc.force_set_against_income_account()
else:
doc.force_set_against_expense_account()
doc.make_gl_entries()

elif doc.doctype in ["Payment Entry", "Journal Entry", "Expense Claim"]:
Expand Down
4 changes: 4 additions & 0 deletions erpnext/accounts/doctype/sales_invoice/sales_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,10 @@ def set_against_income_account(self):
against_acc.append(d.income_account)
self.against_income_account = ",".join(against_acc)

def force_set_against_income_account(self):
self.set_against_income_account()
frappe.db.set_value(self.doctype, self.name, "against_income_account", self.against_income_account)

def add_remarks(self):
if not self.remarks:
if self.po_no and self.po_date:
Expand Down
10 changes: 8 additions & 2 deletions erpnext/accounts/doctype/subscription/test_subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ def test_subscription_recovery(self):
start_date="2021-01-01",
submit_invoice=0,
generate_new_invoices_past_due_date=1,
party="_Test Subscription Customer",
party="_Test Subscription Customer John Doe",
)

# create invoices for the first two moths
Expand Down Expand Up @@ -565,10 +565,16 @@ def create_parties():
if not frappe.db.exists("Customer", "_Test Subscription Customer"):
customer = frappe.new_doc("Customer")
customer.customer_name = "_Test Subscription Customer"
customer.billing_currency = "USD"
customer.default_currency = "USD"
customer.append("accounts", {"company": "_Test Company", "account": "_Test Receivable USD - _TC"})
customer.insert()

if not frappe.db.exists("Customer", "_Test Subscription Customer John Doe"):
customer = frappe.new_doc("Customer")
customer.customer_name = "_Test Subscription Customer John Doe"
customer.append("accounts", {"company": "_Test Company", "account": "_Test Receivable - _TC"})
customer.insert()


def reset_settings():
settings = frappe.get_single("Subscription Settings")
Expand Down
24 changes: 23 additions & 1 deletion erpnext/accounts/report/gross_profit/gross_profit.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ frappe.query_reports["Gross Profit"] = {
label: __("Group By"),
fieldtype: "Select",
options:
"Invoice\nItem Code\nItem Group\nBrand\nWarehouse\nCustomer\nCustomer Group\nTerritory\nSales Person\nProject\nMonthly\nPayment Term",
"Invoice\nItem Code\nItem Group\nBrand\nWarehouse\nCustomer\nCustomer Group\nTerritory\nSales Person\nProject\nCost Center\nMonthly\nPayment Term",
default: "Invoice",
},
{
Expand All @@ -63,6 +63,26 @@ frappe.query_reports["Gross Profit"] = {
};
},
},
{
fieldname: "cost_center",
label: __("Cost Center"),
fieldtype: "MultiSelectList",
get_data: function (txt) {
return frappe.db.get_link_options("Cost Center", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
},
{
fieldname: "project",
label: __("Project"),
fieldtype: "MultiSelectList",
get_data: function (txt) {
return frappe.db.get_link_options("Project", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
},
],
tree: true,
name_field: "parent",
Expand All @@ -85,3 +105,5 @@ frappe.query_reports["Gross Profit"] = {
return value;
},
};

erpnext.utils.add_dimensions("Gross Profit", 15);
46 changes: 45 additions & 1 deletion erpnext/accounts/report/gross_profit/gross_profit.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
from frappe.query_builder import Order
from frappe.utils import cint, flt, formatdate

from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_accounting_dimensions,
get_dimension_with_children,
)
from erpnext.accounts.report.financial_statements import get_cost_centers_with_children
from erpnext.controllers.queries import get_match_cond
from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition
from erpnext.stock.utils import get_incoming_rate
Expand Down Expand Up @@ -120,6 +125,13 @@ def execute(filters=None):
"gross_profit_percent",
],
"project": ["project", "base_amount", "buying_amount", "gross_profit", "gross_profit_percent"],
"cost_center": [
"cost_center",
"base_amount",
"buying_amount",
"gross_profit",
"gross_profit_percent",
],
"territory": [
"territory",
"base_amount",
Expand Down Expand Up @@ -299,7 +311,14 @@ def get_columns(group_wise_columns, filters):
"fieldname": "project",
"fieldtype": "Link",
"options": "Project",
"width": 100,
"width": 140,
},
"cost_center": {
"label": _("Cost Center"),
"fieldname": "cost_center",
"fieldtype": "Link",
"options": "Cost Center",
"width": 140,
},
"sales_person": {
"label": _("Sales Person"),
Expand Down Expand Up @@ -787,6 +806,31 @@ def load_invoice_items(self):
if self.filters.get("item_code"):
conditions += " and `tabSales Invoice Item`.item_code = %(item_code)s"

if self.filters.get("cost_center"):
self.filters.cost_center = frappe.parse_json(self.filters.get("cost_center"))
self.filters.cost_center = get_cost_centers_with_children(self.filters.cost_center)
conditions += " and `tabSales Invoice Item`.cost_center in %(cost_center)s"

if self.filters.get("project"):
self.filters.project = frappe.parse_json(self.filters.get("project"))
conditions += " and `tabSales Invoice Item`.project in %(project)s"

accounting_dimensions = get_accounting_dimensions(as_list=False)
if accounting_dimensions:
for dimension in accounting_dimensions:
if self.filters.get(dimension.fieldname):
if frappe.get_cached_value("DocType", dimension.document_type, "is_tree"):
self.filters[dimension.fieldname] = get_dimension_with_children(
dimension.document_type, self.filters.get(dimension.fieldname)
)
conditions += (
f" and `tabSales Invoice Item`.{dimension.fieldname} in %({dimension.fieldname})s"
)
else:
conditions += (
f" and `tabSales Invoice Item`.{dimension.fieldname} in %({dimension.fieldname})s"
)

if self.filters.get("warehouse"):
warehouse_details = frappe.db.get_value(
"Warehouse", self.filters.get("warehouse"), ["lft", "rgt"], as_dict=1
Expand Down
Loading

0 comments on commit b7eabc3

Please sign in to comment.