Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport jphlions-staging] Bump to v13.17.0 (#524) #551

Merged
merged 3 commits into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions erpnext/accounts/deferred_revenue.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,12 +376,13 @@ def make_gl_entries(doc, credit_account, debit_account, against,
frappe.db.commit()
except Exception as e:
if frappe.flags.in_test:
traceback = frappe.get_traceback()
frappe.log_error(title=_('Error while processing deferred accounting for Invoice {0}').format(doc.name), message=traceback)
raise e
else:
frappe.db.rollback()
traceback = frappe.get_traceback()
frappe.log_error(message=traceback)

frappe.log_error(title=_('Error while processing deferred accounting for Invoice {0}').format(doc.name), message=traceback)
frappe.flags.deferred_accounting_error = True

def send_mail(deferred_process):
Expand Down Expand Up @@ -448,10 +449,12 @@ def book_revenue_via_journal_entry(doc, credit_account, debit_account, against,

if submit:
journal_entry.submit()

frappe.db.commit()
except Exception:
frappe.db.rollback()
traceback = frappe.get_traceback()
frappe.log_error(message=traceback)
frappe.log_error(title=_('Error while processing deferred accounting for Invoice {0}').format(doc.name), message=traceback)

frappe.flags.deferred_accounting_error = True

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from frappe.model.document import Document
from frappe.utils import cint

from erpnext.stock.utils import check_pending_reposting


class AccountsSettings(Document):
def on_update(self):
Expand All @@ -26,6 +28,7 @@ def validate(self):
self.validate_stale_days()
self.enable_payment_schedule_in_print()
self.toggle_discount_accounting_fields()
self.validate_pending_reposts()

def validate_stale_days(self):
if not self.allow_stale and cint(self.stale_days) <= 0:
Expand Down Expand Up @@ -57,3 +60,8 @@ def toggle_discount_accounting_fields(self):
make_property_setter(doctype, "additional_discount_account", "mandatory_depends_on", "", "Code", validate_fields_for_doctype=False)

make_property_setter("Item", "default_discount_account", "hidden", not(enable_discount_accounting), "Check", validate_fields_for_doctype=False)


def validate_pending_reposts(self):
if self.acc_frozen_upto:
check_pending_reposting(self.acc_frozen_upto)
3 changes: 3 additions & 0 deletions erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ def validate(self):
self.set_status()
self.validate_purchase_receipt_if_update_stock()
validate_inter_company_party(self.doctype, self.supplier, self.company, self.inter_company_invoice_reference)
self.reset_default_field_value("set_warehouse", "items", "warehouse")
self.reset_default_field_value("rejected_warehouse", "items", "rejected_warehouse")
self.reset_default_field_value("set_from_warehouse", "items", "from_warehouse")

def validate_release_date(self):
if self.release_date and getdate(nowdate()) >= getdate(self.release_date):
Expand Down
2 changes: 2 additions & 0 deletions erpnext/accounts/doctype/sales_invoice/sales_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ def validate(self):
if self.redeem_loyalty_points and self.loyalty_program and self.loyalty_points and not self.is_consolidated:
validate_loyalty_points(self, self.loyalty_points)

self.reset_default_field_value("set_warehouse", "items", "warehouse")

def validate_fixed_asset(self):
for d in self.get("items"):
if d.is_fixed_asset and d.meta.get_field("asset") and d.asset:
Expand Down
68 changes: 63 additions & 5 deletions erpnext/accounts/report/accounts_receivable/accounts_receivable.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,11 @@ def init_voucher_balance(self):
invoiced = 0.0,
paid = 0.0,
credit_note = 0.0,
outstanding = 0.0
outstanding = 0.0,
invoiced_in_account_currency = 0.0,
paid_in_account_currency = 0.0,
credit_note_in_account_currency = 0.0,
outstanding_in_account_currency = 0.0
)
self.get_invoices(gle)

Expand Down Expand Up @@ -151,21 +155,28 @@ def update_voucher_balance(self, gle):
# gle_balance will be the total "debit - credit" for receivable type reports and
# and vice-versa for payable type reports
gle_balance = self.get_gle_balance(gle)
gle_balance_in_account_currency = self.get_gle_balance_in_account_currency(gle)

if gle_balance > 0:
if gle.voucher_type in ('Journal Entry', 'Payment Entry') and gle.against_voucher:
# debit against sales / purchase invoice
row.paid -= gle_balance
row.paid_in_account_currency -= gle_balance_in_account_currency
else:
# invoice
row.invoiced += gle_balance
row.invoiced_in_account_currency += gle_balance_in_account_currency
else:
# payment or credit note for receivables
if self.is_invoice(gle):
# stand alone debit / credit note
row.credit_note -= gle_balance
row.credit_note_in_account_currency -= gle_balance_in_account_currency
else:
# advance / unlinked payment or other adjustment
row.paid -= gle_balance
row.paid_in_account_currency -= gle_balance_in_account_currency

if gle.cost_center:
row.cost_center = str(gle.cost_center)

Expand Down Expand Up @@ -217,8 +228,46 @@ def build_data(self):
# as we can use this to filter out invoices without outstanding
for key, row in self.voucher_balance.items():
row.outstanding = flt(row.invoiced - row.paid - row.credit_note, self.currency_precision)
row.outstanding_in_account_currency = flt(row.invoiced_in_account_currency - row.paid_in_account_currency - \
row.credit_note_in_account_currency, self.currency_precision)
row.invoice_grand_total = row.invoiced
if abs(row.outstanding) > 1.0/10 ** self.currency_precision:

if frappe.get_hooks('accounts_receivable_usd_column') and row.outstanding != 0.0:
if row['voucher_type'] == "Payment Entry":
currency_field = "paid_to_account_currency"
fields_to_get = ["paid_to_account_currency", "source_exchange_rate", "posting_date"]
elif row['voucher_type'] == "Journal Entry":
currency_field = "currency"
fields_to_get = ["posting_date"]
else:
currency_field = "currency"
fields_to_get = ["currency", "conversion_rate", "posting_date"]

vourcher_data = frappe.db.get_values(row['voucher_type'], row['voucher_no'], fields_to_get, as_dict=1)[0]

if row['voucher_type'] == "Journal Entry":
vourcher_data[currency_field] = "ARS"
elif row['voucher_type'] == "Payment Entry":
vourcher_data["conversion_rate"] = vourcher_data['source_exchange_rate']

if vourcher_data.get('conversion_rate') and vourcher_data.get('conversion_rate') != 1:
row.outstanding_original_currency = flt((row.outstanding / vourcher_data['conversion_rate']), self.currency_precision)
else:
if row['voucher_type'] == "Purchase Invoice":
exchange_type = "for_buying"
elif row['voucher_type'] == "Sales Invoice":
exchange_type = "for_selling"
elif row['voucher_type'] in ["Payment Entry", "Journal Entry"]:
if self.party_type == "Customer":
exchange_type = "for_selling"
else:
exchange_type = "for_buying"

conversion_rate = get_exchange_rate("USD", vourcher_data[currency_field], nowdate(), exchange_type)
row.outstanding_original_currency = flt((row.outstanding / conversion_rate), self.currency_precision)

if (abs(row.outstanding) > 1.0/10 ** self.currency_precision) and \
(abs(row.outstanding_in_account_currency) > 1.0/10 ** self.currency_precision):
# non-zero oustanding, we must consider this row

if self.is_invoice(row) and self.filters.based_on_payment_terms:
Expand Down Expand Up @@ -584,21 +633,23 @@ def get_gl_entries(self):
else:
select_fields = "debit, credit"

doc_currency_fields = "debit_in_account_currency, credit_in_account_currency"

remarks = ", remarks" if self.filters.get("show_remarks") else ""

self.gl_entries = frappe.db.sql("""
select
name, posting_date, account, party_type, party, voucher_type, voucher_no, cost_center,
against_voucher_type, against_voucher, account_currency, {0} {remarks}
against_voucher_type, against_voucher, account_currency, {0}, {1} {remarks}
from
`tabGL Entry`
where
docstatus < 2
and is_cancelled = 0
and party_type=%s
and (party is not null and party != '')
{1} {2} {3}"""
.format(select_fields, date_condition, conditions, order_by, remarks=remarks), values, as_dict=True)
{2} {3} {4}"""
.format(select_fields, doc_currency_fields, date_condition, conditions, order_by, remarks=remarks), values, as_dict=True)

def get_sales_invoices_or_customers_based_on_sales_person(self):
if self.filters.get("sales_person"):
Expand Down Expand Up @@ -719,6 +770,13 @@ def get_gle_balance(self, gle):
# get the balance of the GL (debit - credit) or reverse balance based on report type
return gle.get(self.dr_or_cr) - self.get_reverse_balance(gle)

def get_gle_balance_in_account_currency(self, gle):
# get the balance of the GL (debit - credit) or reverse balance based on report type
return gle.get(self.dr_or_cr + '_in_account_currency') - self.get_reverse_balance_in_account_currency(gle)

def get_reverse_balance_in_account_currency(self, gle):
return gle.get('debit_in_account_currency' if self.dr_or_cr=='credit' else 'credit_in_account_currency')

def get_reverse_balance(self, gle):
# get "credit" balance if report type is "debit" and vice versa
return gle.get('debit' if self.dr_or_cr=='credit' else 'credit')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"label": __("Include Default Book Entries"),
"fieldtype": "Check",
"default": 1
},
{
"fieldname": "show_zero_values",
"label": __("Show zero values"),
"fieldtype": "Check"
}
],
"formatter": function(value, row, column, data, default_formatter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
get_cash_flow_accounts,
)
from erpnext.accounts.report.cash_flow.cash_flow import get_report_summary as get_cash_flow_summary
from erpnext.accounts.report.financial_statements import get_fiscal_year_data, sort_accounts
from erpnext.accounts.report.financial_statements import (
filter_out_zero_value_rows,
get_fiscal_year_data,
sort_accounts,
)
from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import (
get_chart_data as get_pl_chart_data,
)
Expand Down Expand Up @@ -264,7 +268,7 @@ def get_columns(companies, filters):
return columns

def get_data(companies, root_type, balance_must_be, fiscal_year, filters=None, ignore_closing_entries=False):
accounts, accounts_by_name = get_account_heads(root_type,
accounts, accounts_by_name, parent_children_map = get_account_heads(root_type,
companies, filters)

if not accounts: return []
Expand Down Expand Up @@ -293,6 +297,8 @@ def get_data(companies, root_type, balance_must_be, fiscal_year, filters=None, i

out = prepare_data(accounts, start_date, end_date, balance_must_be, companies, company_currency, filters)

out = filter_out_zero_value_rows(out, parent_children_map, show_zero_values=filters.get("show_zero_values"))

if out:
add_total_row(out, root_type, balance_must_be, companies, company_currency)

Expand Down Expand Up @@ -369,7 +375,7 @@ def get_account_heads(root_type, companies, filters):

accounts, accounts_by_name, parent_children_map = filter_accounts(accounts)

return accounts, accounts_by_name
return accounts, accounts_by_name, parent_children_map

def update_parent_account_names(accounts):
"""Update parent_account_name in accounts list.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map):
posting_date = entry.posting_date
voucher_type = entry.voucher_type

if not tax_withholding_category:
tax_withholding_category = supplier_map.get(supplier, {}).get('tax_withholding_category')
rate = tax_rate_map.get(tax_withholding_category)

if entry.account in tds_accounts:
tds_deducted += (entry.credit - entry.debit)

total_amount_credited += (entry.credit - entry.debit)

if rate and tds_deducted:
if tds_deducted:
row = {
'pan' if frappe.db.has_column('Supplier', 'pan') else 'tax_id': supplier_map.get(supplier).pan,
'supplier': supplier_map.get(supplier).name
Expand All @@ -68,7 +72,7 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map):

def get_supplier_pan_map():
supplier_map = frappe._dict()
suppliers = frappe.db.get_all('Supplier', fields=['name', 'pan', 'supplier_type', 'supplier_name'])
suppliers = frappe.db.get_all('Supplier', fields=['name', 'pan', 'supplier_type', 'supplier_name', 'tax_withholding_category'])

for d in suppliers:
supplier_map[d.name] = d
Expand Down
49 changes: 38 additions & 11 deletions erpnext/assets/doctype/asset/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,8 @@ def make_depreciation_schedule(self, date_of_sale):
start = self.clear_depreciation_schedule()

# value_after_depreciation - current Asset value
if d.value_after_depreciation:
value_after_depreciation = (flt(d.value_after_depreciation) -
flt(self.opening_accumulated_depreciation))
if self.docstatus == 1 and d.value_after_depreciation:
value_after_depreciation = flt(d.value_after_depreciation)
else:
value_after_depreciation = (flt(self.gross_purchase_amount) -
flt(self.opening_accumulated_depreciation))
Expand Down Expand Up @@ -242,7 +241,7 @@ def make_depreciation_schedule(self, date_of_sale):
break

# For first row
if has_pro_rata and n==0:
if has_pro_rata and not self.opening_accumulated_depreciation and n==0:
depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount,
self.available_for_use_date, d.depreciation_start_date)

Expand All @@ -255,7 +254,7 @@ def make_depreciation_schedule(self, date_of_sale):
if not self.flags.increase_in_asset_life:
# In case of increase_in_asset_life, the self.to_date is already set on asset_repair submission
self.to_date = add_months(self.available_for_use_date,
n * cint(d.frequency_of_depreciation))
(n + self.number_of_depreciations_booked) * cint(d.frequency_of_depreciation))

depreciation_amount, days, months = self.get_pro_rata_amt(d,
depreciation_amount, schedule_date, self.to_date)
Expand Down Expand Up @@ -351,7 +350,12 @@ def get_from_date(self, finance_book):
# if it returns True, depreciation_amount will not be equal for the first and last rows
def check_is_pro_rata(self, row):
has_pro_rata = False
days = date_diff(row.depreciation_start_date, self.available_for_use_date) + 1

# if not existing asset, from_date = available_for_use_date
# otherwise, if number_of_depreciations_booked = 2, available_for_use_date = 01/01/2020 and frequency_of_depreciation = 12
# from_date = 01/01/2022
from_date = self.get_modified_available_for_use_date(row)
days = date_diff(row.depreciation_start_date, from_date) + 1

# if frequency_of_depreciation is 12 months, total_days = 365
total_days = get_total_days(row.depreciation_start_date, row.frequency_of_depreciation)
Expand All @@ -361,6 +365,9 @@ def check_is_pro_rata(self, row):

return has_pro_rata

def get_modified_available_for_use_date(self, row):
return add_months(self.available_for_use_date, (self.number_of_depreciations_booked * row.frequency_of_depreciation))

def validate_asset_finance_books(self, row):
if flt(row.expected_value_after_useful_life) >= flt(self.gross_purchase_amount):
frappe.throw(_("Row {0}: Expected Value After Useful Life must be less than Gross Purchase Amount")
Expand Down Expand Up @@ -397,7 +404,29 @@ def validate_asset_finance_books(self, row):
frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Available-for-use Date")
.format(row.idx))

def set_accumulated_depreciation(self, date_of_sale=None, ignore_booked_entry = False):
# to ensure that final accumulated depreciation amount is accurate
def get_adjusted_depreciation_amount(self, depreciation_amount_without_pro_rata, depreciation_amount_for_last_row, finance_book):
if not self.opening_accumulated_depreciation:
depreciation_amount_for_first_row = self.get_depreciation_amount_for_first_row(finance_book)

if depreciation_amount_for_first_row + depreciation_amount_for_last_row != depreciation_amount_without_pro_rata:
depreciation_amount_for_last_row = depreciation_amount_without_pro_rata - depreciation_amount_for_first_row

return depreciation_amount_for_last_row

def get_depreciation_amount_for_first_row(self, finance_book):
if self.has_only_one_finance_book():
return self.schedules[0].depreciation_amount
else:
for schedule in self.schedules:
if schedule.finance_book == finance_book:
return schedule.depreciation_amount

def has_only_one_finance_book(self):
if len(self.finance_books) == 1:
return True

def set_accumulated_depreciation(self, date_of_sale=None, date_of_return=None, ignore_booked_entry = False):
straight_line_idx = [d.idx for d in self.get("schedules") if d.depreciation_method == 'Straight Line']
finance_books = []

Expand Down Expand Up @@ -828,13 +857,11 @@ def get_total_days(date, frequency):

@erpnext.allow_regional
def get_depreciation_amount(asset, depreciable_value, row):
depreciation_left = flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked)

if row.depreciation_method in ("Straight Line", "Manual"):
# if the Depreciation Schedule is being prepared for the first time
if not asset.flags.increase_in_asset_life:
depreciation_amount = (flt(row.value_after_depreciation) -
flt(row.expected_value_after_useful_life)) / depreciation_left
depreciation_amount = (flt(asset.gross_purchase_amount) -
flt(row.expected_value_after_useful_life)) / flt(row.total_number_of_depreciations)

# if the Depreciation Schedule is being modified after Asset Repair
else:
Expand Down
4 changes: 4 additions & 0 deletions erpnext/assets/doctype/asset_repair/asset_repair.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ frappe.ui.form.on('Asset Repair', {
if (frm.doc.repair_status == "Completed") {
frm.set_value('completion_date', frappe.datetime.now_datetime());
}
},

stock_items_on_form_rendered() {
erpnext.setup_serial_or_batch_no();
}
});

Expand Down
Loading