Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/frappe/erpnext into deve…
Browse files Browse the repository at this point in the history
…lop-ritvik-customer-ter-not-rqd
  • Loading branch information
deepeshgarg007 committed Oct 9, 2023
2 parents 77f94e2 + 788df14 commit 62b4e3c
Show file tree
Hide file tree
Showing 111 changed files with 903 additions and 1,114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ def test_bank_clearance_with_loan(self):
from lending.loan_management.doctype.loan.test_loan import (
create_loan,
create_loan_accounts,
create_loan_type,
create_loan_product,
create_repayment_entry,
make_loan_disbursement_entry,
)

def create_loan_masters():
create_loan_type(
create_loan_product(
"Clearance Loan",
2000000,
13.5,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,11 @@ frappe.ui.form.on("Bank Statement Import", {

export_errored_rows(frm) {
open_url_post(
"/api/method/frappe.core.doctype.data_import.data_import.download_errored_template",
"/api/method/erpnext.accounts.doctype.bank_statement_import.bank_statement_import.download_errored_template",
{
data_import_name: frm.doc.name,
}
},
true
);
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ def add_vouchers():
def create_loan_and_repayment():
from lending.loan_management.doctype.loan.test_loan import (
create_loan,
create_loan_type,
create_loan_product,
create_repayment_entry,
make_loan_disbursement_entry,
)
Expand All @@ -420,7 +420,7 @@ def create_loan_and_repayment():

from erpnext.setup.doctype.employee.test_employee import make_employee

create_loan_type(
create_loan_product(
"Personal Loan",
500000,
8.4,
Expand All @@ -441,7 +441,7 @@ def create_loan_and_repayment():
"applicant_type": "Employee",
"company": "_Test Company",
"applicant": applicant,
"loan_type": "Personal Loan",
"loan_product": "Personal Loan",
"loan_amount": 5000,
"repayment_method": "Repay Fixed Amount per Period",
"monthly_repayment_amount": 500,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"disabled",
"service_provider",
"api_endpoint",
"access_key",
"url",
"column_break_3",
"help",
Expand Down Expand Up @@ -84,12 +85,18 @@
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disabled"
},
{
"depends_on": "eval:doc.service_provider == 'exchangerate.host';",
"fieldname": "access_key",
"fieldtype": "Data",
"label": "Access Key"
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-01-09 12:19:03.955906",
"modified": "2023-10-04 15:30:25.333860",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Currency Exchange Settings",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,21 @@ def validate(self):

def set_parameters_and_result(self):
if self.service_provider == "exchangerate.host":

if not self.access_key:
frappe.throw(
_("Access Key is required for Service Provider: {0}").format(
frappe.bold(self.service_provider)
)
)

self.set("result_key", [])
self.set("req_params", [])

self.api_endpoint = "https://api.exchangerate.host/convert"
self.append("result_key", {"key": "result"})
self.append("req_params", {"key": "access_key", "value": self.access_key})
self.append("req_params", {"key": "amount", "value": "1"})
self.append("req_params", {"key": "date", "value": "{transaction_date}"})
self.append("req_params", {"key": "from", "value": "{from_currency}"})
self.append("req_params", {"key": "to", "value": "{to_currency}"})
Expand Down
10 changes: 9 additions & 1 deletion erpnext/accounts/doctype/journal_entry/journal_entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,15 @@ frappe.ui.form.on("Journal Entry", {

erpnext.accounts.unreconcile_payments.add_unreconcile_btn(frm);
},

before_save: function(frm) {
if ((frm.doc.docstatus == 0) && (!frm.doc.is_system_generated)) {
let payment_entry_references = frm.doc.accounts.filter(elem => (elem.reference_type == "Payment Entry"));
if (payment_entry_references.length > 0) {
let rows = payment_entry_references.map(x => "#"+x.idx);
frappe.throw(__("Rows: {0} have 'Payment Entry' as reference_type. This should not be set manually.", [frappe.utils.comma_and(rows)]));
}
}
},
make_inter_company_journal_entry: function(frm) {
var d = new frappe.ui.Dialog({
title: __("Select Company"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ def validate(self):


def get_report_pdf(doc, consolidated=True):
statement_dict = get_statement_dict(doc)
if not bool(statement_dict):
return False
elif consolidated:
delimiter = '<div style="page-break-before: always;"></div>' if doc.include_break else ""
result = delimiter.join(list(statement_dict.values()))
return get_pdf(result, {"orientation": doc.orientation})
else:
for customer, statement_html in statement_dict.items():
statement_dict[customer] = get_pdf(statement_html, {"orientation": doc.orientation})
return statement_dict


def get_statement_dict(doc, get_statement_dict=False):
statement_dict = {}
ageing = ""

Expand Down Expand Up @@ -78,18 +92,11 @@ def get_report_pdf(doc, consolidated=True):
if not res:
continue

statement_dict[entry.customer] = get_html(doc, filters, entry, col, res, ageing)
statement_dict[entry.customer] = (
[res, ageing] if get_statement_dict else get_html(doc, filters, entry, col, res, ageing)
)

if not bool(statement_dict):
return False
elif consolidated:
delimiter = '<div style="page-break-before: always;"></div>' if doc.include_break else ""
result = delimiter.join(list(statement_dict.values()))
return get_pdf(result, {"orientation": doc.orientation})
else:
for customer, statement_html in statement_dict.items():
statement_dict[customer] = get_pdf(statement_html, {"orientation": doc.orientation})
return statement_dict
return statement_dict


def set_ageing(doc, entry):
Expand All @@ -102,7 +109,8 @@ def set_ageing(doc, entry):
"range2": 60,
"range3": 90,
"range4": 120,
"customer": entry.customer,
"party_type": "Customer",
"party": [entry.customer],
}
)
col1, ageing = get_ageing(ageing_filters)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,107 @@
import unittest

import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, getdate, today

from erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts import (
get_statement_dict,
send_emails,
)
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin


class TestProcessStatementOfAccounts(unittest.TestCase):
class TestProcessStatementOfAccounts(AccountsTestMixin, FrappeTestCase):
def setUp(self):
self.create_company()
self.create_customer()
self.create_customer(customer_name="Other Customer")
self.clear_old_entries()
self.si = create_sales_invoice()
self.process_soa = create_process_soa()
create_sales_invoice(customer="Other Customer")

def test_process_soa_for_gl(self):
"""Tests the utils for Statement of Accounts(General Ledger)"""
process_soa = create_process_soa(
name="_Test Process SOA for GL",
customers=[{"customer": "_Test Customer"}, {"customer": "Other Customer"}],
)
statement_dict = get_statement_dict(process_soa, get_statement_dict=True)

# Checks if the statements are filtered based on the Customer
self.assertIn("Other Customer", statement_dict)
self.assertIn("_Test Customer", statement_dict)

# Checks if the correct number of receivable entries exist
# 3 rows for opening and closing and 1 row for SI
receivable_entries = statement_dict["_Test Customer"][0]
self.assertEqual(len(receivable_entries), 4)

# Checks the amount for the receivable entry
self.assertEqual(receivable_entries[1].voucher_no, self.si.name)
self.assertEqual(receivable_entries[1].balance, 100)

def test_process_soa_for_ar(self):
"""Tests the utils for Statement of Accounts(Accounts Receivable)"""
process_soa = create_process_soa(name="_Test Process SOA for AR", report="Accounts Receivable")
statement_dict = get_statement_dict(process_soa, get_statement_dict=True)

# Checks if the statements are filtered based on the Customer
self.assertNotIn("Other Customer", statement_dict)
self.assertIn("_Test Customer", statement_dict)

# Checks if the correct number of receivable entries exist
receivable_entries = statement_dict["_Test Customer"][0]
self.assertEqual(len(receivable_entries), 1)

# Checks the amount for the receivable entry
self.assertEqual(receivable_entries[0].voucher_no, self.si.name)
self.assertEqual(receivable_entries[0].total_due, 100)

# Checks the ageing summary for AR
ageing_summary = statement_dict["_Test Customer"][1][0]
expected_summary = frappe._dict(
range1=100,
range2=0,
range3=0,
range4=0,
range5=0,
)
self.check_ageing_summary(ageing_summary, expected_summary)

def test_auto_email_for_process_soa_ar(self):
send_emails(self.process_soa.name, from_scheduler=True)
self.process_soa.load_from_db()
self.assertEqual(self.process_soa.posting_date, getdate(add_days(today(), 7)))
process_soa = create_process_soa(
name="_Test Process SOA", enable_auto_email=1, report="Accounts Receivable"
)
send_emails(process_soa.name, from_scheduler=True)
process_soa.load_from_db()
self.assertEqual(process_soa.posting_date, getdate(add_days(today(), 7)))

def check_ageing_summary(self, ageing, expected_ageing):
for age_range in expected_ageing:
self.assertEqual(expected_ageing[age_range], ageing.get(age_range))

def tearDown(self):
frappe.delete_doc_if_exists("Process Statement Of Accounts", "Test Process SOA")
frappe.db.rollback()


def create_process_soa():
frappe.delete_doc_if_exists("Process Statement Of Accounts", "Test Process SOA")
def create_process_soa(**args):
args = frappe._dict(args)
frappe.delete_doc_if_exists("Process Statement Of Accounts", args.name)
process_soa = frappe.new_doc("Process Statement Of Accounts")
soa_dict = {
"name": "Test Process SOA",
"company": "_Test Company",
}
soa_dict = frappe._dict(
name=args.name,
company=args.company or "_Test Company",
customers=args.customers or [{"customer": "_Test Customer"}],
enable_auto_email=1 if args.enable_auto_email else 0,
frequency=args.frequency or "Weekly",
report=args.report or "General Ledger",
from_date=args.from_date or getdate(today()),
to_date=args.to_date or getdate(today()),
posting_date=args.posting_date or getdate(today()),
include_ageing=1,
)
process_soa.update(soa_dict)
process_soa.set("customers", [{"customer": "_Test Customer"}])
process_soa.enable_auto_email = 1
process_soa.frequency = "Weekly"
process_soa.report = "Accounts Receivable"
process_soa.save()
return process_soa
6 changes: 6 additions & 0 deletions erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,12 @@ cur_frm.set_query("expense_account", "items", function(doc) {
}
});

cur_frm.set_query("wip_composite_asset", "items", function() {
return {
filters: {'is_composite_asset': 1, 'docstatus': 0 }
}
});

cur_frm.cscript.expense_account = function(doc, cdt, cdn){
var d = locals[cdt][cdn];
if(d.idx == 1 && d.expense_account){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"manufacturer_part_no",
"accounting",
"expense_account",
"wip_composite_asset",
"col_break5",
"is_fixed_asset",
"asset_location",
Expand Down Expand Up @@ -903,12 +904,18 @@
"no_copy": 1,
"options": "Serial and Batch Bundle",
"print_hide": 1
},
{
"fieldname": "wip_composite_asset",
"fieldtype": "Link",
"label": "WIP Composite Asset",
"options": "Asset"
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2023-07-26 12:54:53.178156",
"modified": "2023-10-03 21:01:01.824892",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,11 @@ def get_party_total(self, args):

# Add all amount columns
for k in list(self.party_total[d.party]):
if k not in ["currency", "sales_person"]:

self.party_total[d.party][k] += d.get(k, 0.0)
if isinstance(self.party_total[d.party][k], float):
self.party_total[d.party][k] += d.get(k) or 0.0

# set territory, customer_group, sales person etc
self.set_party_details(d)
self.party_total[d.party].update({"party_type": d.party_type})

def init_party_total(self, row):
self.party_total.setdefault(
Expand All @@ -124,6 +122,7 @@ def init_party_total(self, row):
"total_due": 0.0,
"future_amount": 0.0,
"sales_person": [],
"party_type": row.party_type,
}
),
)
Expand All @@ -133,13 +132,12 @@ def set_party_details(self, row):

for key in ("territory", "customer_group", "supplier_group"):
if row.get(key):
self.party_total[row.party][key] = row.get(key)

self.party_total[row.party][key] = row.get(key, "")
if row.sales_person:
self.party_total[row.party].sales_person.append(row.sales_person)
self.party_total[row.party].sales_person.append(row.get("sales_person", ""))

if self.filters.sales_partner:
self.party_total[row.party]["default_sales_partner"] = row.get("default_sales_partner")
self.party_total[row.party]["default_sales_partner"] = row.get("default_sales_partner", "")

def get_columns(self):
self.columns = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"to_fiscal_year": data.fiscal_year
};

if(data.based_on == 'cost_center'){
if(data.based_on == 'Cost Center'){
frappe.route_options["cost_center"] = data.account
} else {
frappe.route_options["project"] = data.account
Expand Down
Loading

0 comments on commit 62b4e3c

Please sign in to comment.