mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-06 21:59:13 +00:00
Merge branch 'develop' into common-party-acc
This commit is contained in:
@@ -9,19 +9,8 @@ import frappe
|
||||
import unittest
|
||||
|
||||
class TestFinanceBook(unittest.TestCase):
|
||||
def create_finance_book(self):
|
||||
if not frappe.db.exists("Finance Book", "_Test Finance Book"):
|
||||
finance_book = frappe.get_doc({
|
||||
"doctype": "Finance Book",
|
||||
"finance_book_name": "_Test Finance Book"
|
||||
}).insert()
|
||||
else:
|
||||
finance_book = frappe.get_doc("Finance Book", "_Test Finance Book")
|
||||
|
||||
return finance_book
|
||||
|
||||
def test_finance_book(self):
|
||||
finance_book = self.create_finance_book()
|
||||
finance_book = create_finance_book()
|
||||
|
||||
# create jv entry
|
||||
jv = make_journal_entry("_Test Bank - _TC",
|
||||
@@ -41,3 +30,14 @@ class TestFinanceBook(unittest.TestCase):
|
||||
|
||||
for gl_entry in gl_entries:
|
||||
self.assertEqual(gl_entry.finance_book, finance_book.name)
|
||||
|
||||
def create_finance_book():
|
||||
if not frappe.db.exists("Finance Book", "_Test Finance Book"):
|
||||
finance_book = frappe.get_doc({
|
||||
"doctype": "Finance Book",
|
||||
"finance_book_name": "_Test Finance Book"
|
||||
}).insert()
|
||||
else:
|
||||
finance_book = frappe.get_doc("Finance Book", "_Test Finance Book")
|
||||
|
||||
return finance_book
|
||||
@@ -533,8 +533,8 @@ frappe.ui.form.on('Payment Entry', {
|
||||
source_exchange_rate: function(frm) {
|
||||
if (frm.doc.paid_amount) {
|
||||
frm.set_value("base_paid_amount", flt(frm.doc.paid_amount) * flt(frm.doc.source_exchange_rate));
|
||||
if(!frm.set_paid_amount_based_on_received_amount &&
|
||||
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) {
|
||||
// target exchange rate should always be same as source if both account currencies is same
|
||||
if(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
|
||||
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
|
||||
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
|
||||
}
|
||||
|
||||
@@ -55,14 +55,17 @@ class PaymentEntry(AccountsController):
|
||||
self.validate_mandatory()
|
||||
self.validate_reference_documents()
|
||||
self.set_tax_withholding()
|
||||
self.apply_taxes()
|
||||
self.set_amounts()
|
||||
self.validate_amounts()
|
||||
self.apply_taxes()
|
||||
self.set_amounts_after_tax()
|
||||
self.clear_unallocated_reference_document_rows()
|
||||
self.validate_payment_against_negative_invoice()
|
||||
self.validate_transaction_reference()
|
||||
self.set_title()
|
||||
self.set_remarks()
|
||||
self.validate_duplicate_entry()
|
||||
self.validate_payment_type_with_outstanding()
|
||||
self.validate_allocated_amount()
|
||||
self.validate_paid_invoices()
|
||||
self.ensure_supplier_is_not_blocked()
|
||||
@@ -118,6 +121,11 @@ class PaymentEntry(AccountsController):
|
||||
if not self.get(field):
|
||||
self.set(field, bank_data.account)
|
||||
|
||||
def validate_payment_type_with_outstanding(self):
|
||||
total_outstanding = sum(d.allocated_amount for d in self.get('references'))
|
||||
if total_outstanding < 0 and self.party_type == 'Customer' and self.payment_type == 'Receive':
|
||||
frappe.throw(_("Cannot receive from customer against negative outstanding"), title=_("Incorrect Payment Type"))
|
||||
|
||||
def validate_allocated_amount(self):
|
||||
for d in self.get("references"):
|
||||
if (flt(d.allocated_amount))> 0:
|
||||
@@ -236,7 +244,9 @@ class PaymentEntry(AccountsController):
|
||||
self.company_currency, self.posting_date)
|
||||
|
||||
def set_target_exchange_rate(self, ref_doc=None):
|
||||
if self.paid_to and not self.target_exchange_rate:
|
||||
if self.paid_from_account_currency == self.paid_to_account_currency:
|
||||
self.target_exchange_rate = self.source_exchange_rate
|
||||
elif self.paid_to and not self.target_exchange_rate:
|
||||
if ref_doc:
|
||||
if self.paid_to_account_currency == ref_doc.currency:
|
||||
self.target_exchange_rate = ref_doc.get("exchange_rate")
|
||||
@@ -468,13 +478,22 @@ class PaymentEntry(AccountsController):
|
||||
def set_amounts(self):
|
||||
self.set_received_amount()
|
||||
self.set_amounts_in_company_currency()
|
||||
self.set_amounts_after_tax()
|
||||
self.set_total_allocated_amount()
|
||||
self.set_unallocated_amount()
|
||||
self.set_difference_amount()
|
||||
|
||||
def validate_amounts(self):
|
||||
self.validate_received_amount()
|
||||
|
||||
def validate_received_amount(self):
|
||||
if self.paid_from_account_currency == self.paid_to_account_currency:
|
||||
if self.paid_amount != self.received_amount:
|
||||
frappe.throw(_("Received Amount cannot be greater than Paid Amount"))
|
||||
|
||||
def set_received_amount(self):
|
||||
self.base_received_amount = self.base_paid_amount
|
||||
if self.paid_from_account_currency == self.paid_to_account_currency:
|
||||
self.received_amount = self.paid_amount
|
||||
|
||||
def set_amounts_after_tax(self):
|
||||
applicable_tax = 0
|
||||
|
||||
@@ -107,7 +107,7 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
|
||||
pe.reference_no = "1"
|
||||
pe.reference_date = "2016-01-01"
|
||||
pe.target_exchange_rate = 50
|
||||
pe.source_exchange_rate = 50
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
@@ -154,7 +154,7 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
|
||||
pe.reference_no = "1"
|
||||
pe.reference_date = "2016-01-01"
|
||||
pe.target_exchange_rate = 50
|
||||
pe.source_exchange_rate = 50
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
@@ -491,7 +491,7 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
|
||||
pe.reference_no = "1"
|
||||
pe.reference_date = "2016-01-01"
|
||||
pe.target_exchange_rate = 55
|
||||
pe.source_exchange_rate = 55
|
||||
|
||||
pe.append("deductions", {
|
||||
"account": "_Test Exchange Gain/Loss - _TC",
|
||||
|
||||
@@ -50,9 +50,13 @@ class PeriodClosingVoucher(AccountsController):
|
||||
.format(pce[0][0], self.posting_date))
|
||||
|
||||
def make_gl_entries(self):
|
||||
gl_entries = self.get_gl_entries()
|
||||
if gl_entries:
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries)
|
||||
|
||||
def get_gl_entries(self):
|
||||
gl_entries = []
|
||||
net_pl_balance = 0
|
||||
|
||||
pl_accounts = self.get_pl_balances()
|
||||
|
||||
for acc in pl_accounts:
|
||||
@@ -60,6 +64,7 @@ class PeriodClosingVoucher(AccountsController):
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": acc.account,
|
||||
"cost_center": acc.cost_center,
|
||||
"finance_book": acc.finance_book,
|
||||
"account_currency": acc.account_currency,
|
||||
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0,
|
||||
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0,
|
||||
@@ -67,35 +72,13 @@ class PeriodClosingVoucher(AccountsController):
|
||||
"credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0
|
||||
}, item=acc))
|
||||
|
||||
net_pl_balance += flt(acc.bal_in_company_currency)
|
||||
if gl_entries:
|
||||
gle_for_net_pl_bal = self.get_pnl_gl_entry(pl_accounts)
|
||||
gl_entries += gle_for_net_pl_bal
|
||||
|
||||
if net_pl_balance:
|
||||
if self.cost_center_wise_pnl:
|
||||
costcenter_wise_gl_entries = self.get_costcenter_wise_pnl_gl_entries(pl_accounts)
|
||||
gl_entries += costcenter_wise_gl_entries
|
||||
else:
|
||||
gl_entry = self.get_pnl_gl_entry(net_pl_balance)
|
||||
gl_entries.append(gl_entry)
|
||||
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries)
|
||||
|
||||
def get_pnl_gl_entry(self, net_pl_balance):
|
||||
cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
||||
gl_entry = self.get_gl_dict({
|
||||
"account": self.closing_account_head,
|
||||
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
||||
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
||||
"cost_center": cost_center
|
||||
})
|
||||
|
||||
self.update_default_dimensions(gl_entry)
|
||||
|
||||
return gl_entry
|
||||
|
||||
def get_costcenter_wise_pnl_gl_entries(self, pl_accounts):
|
||||
return gl_entries
|
||||
|
||||
def get_pnl_gl_entry(self, pl_accounts):
|
||||
company_cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
||||
gl_entries = []
|
||||
|
||||
@@ -104,6 +87,7 @@ class PeriodClosingVoucher(AccountsController):
|
||||
gl_entry = self.get_gl_dict({
|
||||
"account": self.closing_account_head,
|
||||
"cost_center": acc.cost_center or company_cost_center,
|
||||
"finance_book": acc.finance_book,
|
||||
"account_currency": acc.account_currency,
|
||||
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0,
|
||||
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0,
|
||||
@@ -130,7 +114,7 @@ class PeriodClosingVoucher(AccountsController):
|
||||
def get_pl_balances(self):
|
||||
"""Get balance for dimension-wise pl accounts"""
|
||||
|
||||
dimension_fields = ['t1.cost_center']
|
||||
dimension_fields = ['t1.cost_center', 't1.finance_book']
|
||||
|
||||
self.accounting_dimensions = get_accounting_dimensions()
|
||||
for dimension in self.accounting_dimensions:
|
||||
|
||||
@@ -8,6 +8,7 @@ import frappe
|
||||
from frappe.utils import flt, today
|
||||
from erpnext.accounts.utils import get_fiscal_year, now
|
||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
||||
from erpnext.accounts.doctype.finance_book.test_finance_book import create_finance_book
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
|
||||
class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
@@ -118,6 +119,58 @@ class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
|
||||
self.assertTrue(pcv_gle, expected_gle)
|
||||
|
||||
def test_period_closing_with_finance_book_entries(self):
|
||||
frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'")
|
||||
|
||||
company = create_company()
|
||||
surplus_account = create_account()
|
||||
cost_center = create_cost_center("Test Cost Center 1")
|
||||
|
||||
create_sales_invoice(
|
||||
company=company,
|
||||
income_account="Sales - TPC",
|
||||
expense_account="Cost of Goods Sold - TPC",
|
||||
cost_center=cost_center,
|
||||
rate=400,
|
||||
debit_to="Debtors - TPC"
|
||||
)
|
||||
jv = make_journal_entry(
|
||||
account1="Cash - TPC",
|
||||
account2="Sales - TPC",
|
||||
amount=400,
|
||||
cost_center=cost_center,
|
||||
posting_date=now()
|
||||
)
|
||||
jv.company = company
|
||||
jv.finance_book = create_finance_book().name
|
||||
jv.save()
|
||||
jv.submit()
|
||||
|
||||
pcv = frappe.get_doc({
|
||||
"transaction_date": today(),
|
||||
"posting_date": today(),
|
||||
"fiscal_year": get_fiscal_year(today())[0],
|
||||
"company": company,
|
||||
"closing_account_head": surplus_account,
|
||||
"remarks": "Test",
|
||||
"doctype": "Period Closing Voucher"
|
||||
})
|
||||
pcv.insert()
|
||||
pcv.submit()
|
||||
|
||||
expected_gle = (
|
||||
(surplus_account, 0.0, 400.0, ''),
|
||||
(surplus_account, 0.0, 400.0, jv.finance_book),
|
||||
('Sales - TPC', 400.0, 0.0, ''),
|
||||
('Sales - TPC', 400.0, 0.0, jv.finance_book)
|
||||
)
|
||||
|
||||
pcv_gle = frappe.db.sql("""
|
||||
select account, debit, credit, finance_book from `tabGL Entry` where voucher_no=%s
|
||||
""", (pcv.name))
|
||||
|
||||
self.assertTrue(pcv_gle, expected_gle)
|
||||
|
||||
def make_period_closing_voucher(self):
|
||||
pcv = frappe.get_doc({
|
||||
"doctype": "Period Closing Voucher",
|
||||
|
||||
@@ -85,9 +85,15 @@ class TestPOSClosingEntry(unittest.TestCase):
|
||||
|
||||
pcv_doc.load_from_db()
|
||||
pcv_doc.cancel()
|
||||
si_doc.load_from_db()
|
||||
|
||||
cancelled_invoice = frappe.db.get_value(
|
||||
'POS Invoice Merge Log', {'pos_closing_entry': pcv_doc.name},
|
||||
'consolidated_invoice'
|
||||
)
|
||||
docstatus = frappe.db.get_value("Sales Invoice", cancelled_invoice, 'docstatus')
|
||||
self.assertEqual(docstatus, 2)
|
||||
|
||||
pos_inv1.load_from_db()
|
||||
self.assertEqual(si_doc.docstatus, 2)
|
||||
self.assertEqual(pos_inv1.status, 'Paid')
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
|
||||
|
||||
onload(doc) {
|
||||
super.onload();
|
||||
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log'];
|
||||
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log', 'POS Closing Entry'];
|
||||
if(doc.__islocal && doc.is_pos && frappe.get_route_str() !== 'point-of-sale') {
|
||||
this.frm.script_manager.trigger("is_pos");
|
||||
this.frm.refresh_fields();
|
||||
@@ -111,16 +111,12 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
|
||||
}
|
||||
|
||||
write_off_outstanding_amount_automatically() {
|
||||
if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
|
||||
if (cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
|
||||
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
|
||||
// this will make outstanding amount 0
|
||||
this.frm.set_value("write_off_amount",
|
||||
flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount"))
|
||||
);
|
||||
this.frm.toggle_enable("write_off_amount", false);
|
||||
|
||||
} else {
|
||||
this.frm.toggle_enable("write_off_amount", true);
|
||||
}
|
||||
|
||||
this.calculate_outstanding_amount(false);
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
"loyalty_redemption_account",
|
||||
"loyalty_redemption_cost_center",
|
||||
"section_break_49",
|
||||
"coupon_code",
|
||||
"apply_discount_on",
|
||||
"base_discount_amount",
|
||||
"column_break_51",
|
||||
@@ -1183,7 +1184,8 @@
|
||||
"label": "Write Off Amount",
|
||||
"no_copy": 1,
|
||||
"options": "currency",
|
||||
"print_hide": 1
|
||||
"print_hide": 1,
|
||||
"read_only_depends_on": "eval: doc.write_off_outstanding_amount_automatically"
|
||||
},
|
||||
{
|
||||
"fieldname": "base_write_off_amount",
|
||||
@@ -1549,12 +1551,20 @@
|
||||
"no_copy": 1,
|
||||
"options": "Sales Invoice",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "coupon_code",
|
||||
"fieldname": "coupon_code",
|
||||
"fieldtype": "Link",
|
||||
"label": "Coupon Code",
|
||||
"options": "Coupon Code",
|
||||
"print_hide": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-file-text",
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-08-17 20:13:44.255437",
|
||||
"modified": "2021-08-18 16:13:52.080543",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Invoice",
|
||||
|
||||
@@ -44,6 +44,9 @@ class POSInvoice(SalesInvoice):
|
||||
self.validate_pos()
|
||||
self.validate_payment_amount()
|
||||
self.validate_loyalty_transaction()
|
||||
if self.coupon_code:
|
||||
from erpnext.accounts.doctype.pricing_rule.utils import validate_coupon_code
|
||||
validate_coupon_code(self.coupon_code)
|
||||
|
||||
def on_submit(self):
|
||||
# create the loyalty point ledger entry if the customer is enrolled in any loyalty program
|
||||
@@ -58,6 +61,10 @@ class POSInvoice(SalesInvoice):
|
||||
self.check_phone_payments()
|
||||
self.set_status(update=True)
|
||||
|
||||
if self.coupon_code:
|
||||
from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count
|
||||
update_coupon_code_count(self.coupon_code,'used')
|
||||
|
||||
def before_cancel(self):
|
||||
if self.consolidated_invoice and frappe.db.get_value('Sales Invoice', self.consolidated_invoice, 'docstatus') == 1:
|
||||
pos_closing_entry = frappe.get_all(
|
||||
@@ -84,6 +91,10 @@ class POSInvoice(SalesInvoice):
|
||||
against_psi_doc.delete_loyalty_point_entry()
|
||||
against_psi_doc.make_loyalty_point_entry()
|
||||
|
||||
if self.coupon_code:
|
||||
from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count
|
||||
update_coupon_code_count(self.coupon_code,'cancelled')
|
||||
|
||||
def check_phone_payments(self):
|
||||
for pay in self.payments:
|
||||
if pay.type == "Phone" and pay.amount >= 0:
|
||||
@@ -127,7 +138,7 @@ class POSInvoice(SalesInvoice):
|
||||
.format(item.idx, bold_delivered_serial_nos), title=_("Item Unavailable"))
|
||||
|
||||
def validate_stock_availablility(self):
|
||||
if self.is_return:
|
||||
if self.is_return or self.docstatus != 1:
|
||||
return
|
||||
|
||||
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
|
||||
|
||||
@@ -198,12 +198,19 @@ def apply_pricing_rule(args, doc=None):
|
||||
set_serial_nos_based_on_fifo = frappe.db.get_single_value("Stock Settings",
|
||||
"automatically_set_serial_nos_based_on_fifo")
|
||||
|
||||
item_code_list = tuple(item.get('item_code') for item in item_list)
|
||||
query_items = frappe.get_all('Item', fields=['item_code','has_serial_no'], filters=[['item_code','in',item_code_list]],as_list=1)
|
||||
serialized_items = dict()
|
||||
for item_code, val in query_items:
|
||||
serialized_items.setdefault(item_code, val)
|
||||
|
||||
for item in item_list:
|
||||
args_copy = copy.deepcopy(args)
|
||||
args_copy.update(item)
|
||||
data = get_pricing_rule_for_item(args_copy, item.get('price_list_rate'), doc=doc)
|
||||
out.append(data)
|
||||
if not item.get("serial_no") and set_serial_nos_based_on_fifo and not args.get('is_return'):
|
||||
|
||||
if serialized_items.get(item.get('item_code')) and not item.get("serial_no") and set_serial_nos_based_on_fifo and not args.get('is_return'):
|
||||
out[0].update(get_serial_no_for_item(args_copy))
|
||||
|
||||
return out
|
||||
|
||||
@@ -324,16 +324,12 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
|
||||
}
|
||||
|
||||
write_off_outstanding_amount_automatically() {
|
||||
if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
|
||||
if (cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
|
||||
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
|
||||
// this will make outstanding amount 0
|
||||
this.frm.set_value("write_off_amount",
|
||||
flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount"))
|
||||
);
|
||||
this.frm.toggle_enable("write_off_amount", false);
|
||||
|
||||
} else {
|
||||
this.frm.toggle_enable("write_off_amount", true);
|
||||
}
|
||||
|
||||
this.calculate_outstanding_amount(false);
|
||||
@@ -787,8 +783,6 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
|
||||
else hide_field(['c_form_applicable', 'c_form_no']);
|
||||
|
||||
frm.toggle_enable("write_off_amount", !!!cint(doc.write_off_outstanding_amount_automatically));
|
||||
|
||||
frm.refresh_fields();
|
||||
},
|
||||
|
||||
|
||||
@@ -1444,7 +1444,8 @@
|
||||
"label": "Write Off Amount",
|
||||
"no_copy": 1,
|
||||
"options": "currency",
|
||||
"print_hide": 1
|
||||
"print_hide": 1,
|
||||
"read_only_depends_on": "eval:doc.write_off_outstanding_amount_automatically"
|
||||
},
|
||||
{
|
||||
"fieldname": "base_write_off_amount",
|
||||
@@ -2014,7 +2015,7 @@
|
||||
"link_fieldname": "consolidated_invoice"
|
||||
}
|
||||
],
|
||||
"modified": "2021-08-17 20:16:12.737743",
|
||||
"modified": "2021-08-18 16:07:45.122570",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -26,6 +26,7 @@ from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
|
||||
from erpnext.stock.utils import get_incoming_rate
|
||||
from erpnext.accounts.utils import PaymentEntryUnlinkError
|
||||
|
||||
class TestSalesInvoice(unittest.TestCase):
|
||||
def make(self):
|
||||
@@ -136,7 +137,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
pe.paid_to_account_currency = si.currency
|
||||
pe.source_exchange_rate = 1
|
||||
pe.target_exchange_rate = 1
|
||||
pe.paid_amount = si.grand_total
|
||||
pe.paid_amount = si.outstanding_amount
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
@@ -145,6 +146,42 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
self.assertRaises(frappe.LinkExistsError, si.cancel)
|
||||
unlink_payment_on_cancel_of_invoice()
|
||||
|
||||
def test_payment_entry_unlink_against_standalone_credit_note(self):
|
||||
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
|
||||
si1 = create_sales_invoice(rate=1000)
|
||||
si2 = create_sales_invoice(rate=300)
|
||||
si3 = create_sales_invoice(qty=-1, rate=300, is_return=1)
|
||||
|
||||
|
||||
pe = get_payment_entry("Sales Invoice", si1.name, bank_account="_Test Bank - _TC")
|
||||
pe.append('references', {
|
||||
'reference_doctype': 'Sales Invoice',
|
||||
'reference_name': si2.name,
|
||||
'total_amount': si2.grand_total,
|
||||
'outstanding_amount': si2.outstanding_amount,
|
||||
'allocated_amount': si2.outstanding_amount
|
||||
})
|
||||
|
||||
pe.append('references', {
|
||||
'reference_doctype': 'Sales Invoice',
|
||||
'reference_name': si3.name,
|
||||
'total_amount': si3.grand_total,
|
||||
'outstanding_amount': si3.outstanding_amount,
|
||||
'allocated_amount': si3.outstanding_amount
|
||||
})
|
||||
|
||||
pe.reference_no = 'Test001'
|
||||
pe.reference_date = nowdate()
|
||||
pe.save()
|
||||
pe.submit()
|
||||
|
||||
si2.load_from_db()
|
||||
si2.cancel()
|
||||
|
||||
si1.load_from_db()
|
||||
self.assertRaises(PaymentEntryUnlinkError, si1.cancel)
|
||||
|
||||
|
||||
def test_sales_invoice_calculation_export_currency(self):
|
||||
si = frappe.copy_doc(test_records[2])
|
||||
si.currency = "USD"
|
||||
@@ -2014,7 +2051,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
data = get_ewb_data("Sales Invoice", [si.name])
|
||||
|
||||
self.assertEqual(data['version'], '1.0.1118')
|
||||
self.assertEqual(data['version'], '1.0.0421')
|
||||
self.assertEqual(data['billLists'][0]['fromGstin'], '27AAECE4835E1ZR')
|
||||
self.assertEqual(data['billLists'][0]['fromTrdName'], '_Test Company')
|
||||
self.assertEqual(data['billLists'][0]['toTrdName'], '_Test Customer')
|
||||
|
||||
@@ -101,7 +101,7 @@ def merge_similar_entries(gl_map, precision=None):
|
||||
|
||||
def check_if_in_list(gle, gl_map, dimensions=None):
|
||||
account_head_fieldnames = ['voucher_detail_no', 'party', 'against_voucher',
|
||||
'cost_center', 'against_voucher_type', 'party_type', 'project']
|
||||
'cost_center', 'against_voucher_type', 'party_type', 'project', 'finance_book']
|
||||
|
||||
if dimensions:
|
||||
account_head_fieldnames = account_head_fieldnames + dimensions
|
||||
|
||||
@@ -535,6 +535,8 @@ class ReceivablePayableReport(object):
|
||||
if getdate(entry_date) > getdate(self.filters.report_date):
|
||||
row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0
|
||||
|
||||
row.total_due = row.range1 + row.range2 + row.range3 + row.range4 + row.range5
|
||||
|
||||
def get_ageing_data(self, entry_date, row):
|
||||
# [0-30, 30-60, 60-90, 90-120, 120-above]
|
||||
row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0
|
||||
|
||||
@@ -82,6 +82,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
"range3": 0.0,
|
||||
"range4": 0.0,
|
||||
"range5": 0.0,
|
||||
"total_due": 0.0,
|
||||
"sales_person": []
|
||||
}))
|
||||
|
||||
@@ -135,3 +136,6 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
"{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]),
|
||||
"{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))]):
|
||||
self.add_column(label=label, fieldname='range' + str(i+1))
|
||||
|
||||
# Add column for total due amount
|
||||
self.add_column(label="Total Amount Due", fieldname='total_due')
|
||||
|
||||
@@ -210,10 +210,10 @@ def get_data(companies, root_type, balance_must_be, fiscal_year, filters=None, i
|
||||
company_currency = get_company_currency(filters)
|
||||
|
||||
if filters.filter_based_on == 'Fiscal Year':
|
||||
start_date = fiscal_year.year_start_date
|
||||
start_date = fiscal_year.year_start_date if filters.report != 'Balance Sheet' else None
|
||||
end_date = fiscal_year.year_end_date
|
||||
else:
|
||||
start_date = filters.period_start_date
|
||||
start_date = filters.period_start_date if filters.report != 'Balance Sheet' else None
|
||||
end_date = filters.period_end_date
|
||||
|
||||
gl_entries_by_account = {}
|
||||
|
||||
@@ -19,6 +19,7 @@ from erpnext.stock import get_warehouse_account_map
|
||||
|
||||
class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass
|
||||
class FiscalYearError(frappe.ValidationError): pass
|
||||
class PaymentEntryUnlinkError(frappe.ValidationError): pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_fiscal_year(date=None, fiscal_year=None, label="Date", verbose=1, company=None, as_dict=False):
|
||||
@@ -555,10 +556,16 @@ def remove_ref_doc_link_from_pe(ref_type, ref_no):
|
||||
and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no))
|
||||
|
||||
for pe in linked_pe:
|
||||
pe_doc = frappe.get_doc("Payment Entry", pe)
|
||||
pe_doc.set_total_allocated_amount()
|
||||
pe_doc.set_unallocated_amount()
|
||||
pe_doc.clear_unallocated_reference_document_rows()
|
||||
try:
|
||||
pe_doc = frappe.get_doc("Payment Entry", pe)
|
||||
pe_doc.set_amounts()
|
||||
pe_doc.clear_unallocated_reference_document_rows()
|
||||
pe_doc.validate_payment_type_with_outstanding()
|
||||
except Exception as e:
|
||||
msg = _("There were issues unlinking payment entry {0}.").format(pe_doc.name)
|
||||
msg += '<br>'
|
||||
msg += _("Please cancel payment entry manually first")
|
||||
frappe.throw(msg, exc=PaymentEntryUnlinkError, title=_("Payment Unlink Error"))
|
||||
|
||||
frappe.db.sql("""update `tabPayment Entry` set total_allocated_amount=%s,
|
||||
base_total_allocated_amount=%s, unallocated_amount=%s, modified=%s, modified_by=%s
|
||||
|
||||
Reference in New Issue
Block a user