Merge pull request #35609 from GursheenK/#34282-Record-advance-payment-as-a-liability
feat: Record Advance Payment as a liability
This commit is contained in:
commit
3df0c5e32f
@ -13,7 +13,7 @@ class TestFinanceBook(unittest.TestCase):
|
||||
finance_book = create_finance_book()
|
||||
|
||||
# create jv entry
|
||||
jv = make_journal_entry("_Test Bank - _TC", "_Test Receivable - _TC", 100, save=False)
|
||||
jv = make_journal_entry("_Test Bank - _TC", "Debtors - _TC", 100, save=False)
|
||||
|
||||
jv.accounts[1].update({"party_type": "Customer", "party": "_Test Customer"})
|
||||
|
||||
|
@ -43,7 +43,7 @@ class TestJournalEntry(unittest.TestCase):
|
||||
frappe.db.sql(
|
||||
"""select name from `tabJournal Entry Account`
|
||||
where account = %s and docstatus = 1 and parent = %s""",
|
||||
("_Test Receivable - _TC", test_voucher.name),
|
||||
("Debtors - _TC", test_voucher.name),
|
||||
)
|
||||
)
|
||||
|
||||
@ -273,7 +273,7 @@ class TestJournalEntry(unittest.TestCase):
|
||||
jv.submit()
|
||||
|
||||
# create jv in USD, but account currency in INR
|
||||
jv = make_journal_entry("_Test Bank - _TC", "_Test Receivable - _TC", 100, save=False)
|
||||
jv = make_journal_entry("_Test Bank - _TC", "Debtors - _TC", 100, save=False)
|
||||
|
||||
jv.accounts[1].update({"party_type": "Customer", "party": "_Test Customer USD"})
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
"doctype": "Journal Entry",
|
||||
"accounts": [
|
||||
{
|
||||
"account": "_Test Receivable - _TC",
|
||||
"account": "Debtors - _TC",
|
||||
"party_type": "Customer",
|
||||
"party": "_Test Customer",
|
||||
"credit_in_account_currency": 400.0,
|
||||
@ -70,7 +70,7 @@
|
||||
"doctype": "Journal Entry",
|
||||
"accounts": [
|
||||
{
|
||||
"account": "_Test Receivable - _TC",
|
||||
"account": "Debtors - _TC",
|
||||
"party_type": "Customer",
|
||||
"party": "_Test Customer",
|
||||
"credit_in_account_currency": 0.0,
|
||||
|
@ -6,7 +6,8 @@
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"company",
|
||||
"account"
|
||||
"account",
|
||||
"advance_account"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@ -22,14 +23,20 @@
|
||||
"fieldname": "account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Account",
|
||||
"label": "Default Account",
|
||||
"options": "Account"
|
||||
},
|
||||
{
|
||||
"fieldname": "advance_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Advance Account",
|
||||
"options": "Account"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2022-04-04 12:31:02.994197",
|
||||
"modified": "2023-06-06 14:15:42.053150",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Party Account",
|
||||
|
@ -319,6 +319,10 @@ frappe.ui.form.on('Payment Entry', {
|
||||
}
|
||||
},
|
||||
|
||||
company: function(frm){
|
||||
frm.trigger('party');
|
||||
},
|
||||
|
||||
party: function(frm) {
|
||||
if (frm.doc.contact_email || frm.doc.contact_person) {
|
||||
frm.set_value("contact_email", "");
|
||||
@ -733,7 +737,6 @@ frappe.ui.form.on('Payment Entry', {
|
||||
if(r.message) {
|
||||
var total_positive_outstanding = 0;
|
||||
var total_negative_outstanding = 0;
|
||||
|
||||
$.each(r.message, function(i, d) {
|
||||
var c = frm.add_child("references");
|
||||
c.reference_doctype = d.voucher_type;
|
||||
@ -744,6 +747,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
c.bill_no = d.bill_no;
|
||||
c.payment_term = d.payment_term;
|
||||
c.allocated_amount = d.allocated_amount;
|
||||
c.account = d.account;
|
||||
|
||||
if(!in_list(frm.events.get_order_doctypes(frm), d.voucher_type)) {
|
||||
if(flt(d.outstanding_amount) > 0)
|
||||
@ -1459,4 +1463,4 @@ frappe.ui.form.on('Payment Entry', {
|
||||
});
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
@ -19,6 +19,7 @@
|
||||
"party_type",
|
||||
"party",
|
||||
"party_name",
|
||||
"book_advance_payments_in_separate_party_account",
|
||||
"column_break_11",
|
||||
"bank_account",
|
||||
"party_bank_account",
|
||||
@ -735,12 +736,21 @@
|
||||
"fieldname": "get_outstanding_orders",
|
||||
"fieldtype": "Button",
|
||||
"label": "Get Outstanding Orders"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fetch_from": "company.book_advance_payments_in_separate_party_account",
|
||||
"fieldname": "book_advance_payments_in_separate_party_account",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Book Advance Payments in Separate Party Account",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2023-06-19 11:38:04.387219",
|
||||
"modified": "2023-06-23 18:07:38.023010",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Entry",
|
||||
|
@ -21,7 +21,11 @@ from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_ban
|
||||
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import (
|
||||
get_party_tax_withholding_details,
|
||||
)
|
||||
from erpnext.accounts.general_ledger import make_gl_entries, process_gl_map
|
||||
from erpnext.accounts.general_ledger import (
|
||||
make_gl_entries,
|
||||
make_reverse_gl_entries,
|
||||
process_gl_map,
|
||||
)
|
||||
from erpnext.accounts.party import get_party_account
|
||||
from erpnext.accounts.utils import get_account_currency, get_balance_on, get_outstanding_invoices
|
||||
from erpnext.controllers.accounts_controller import (
|
||||
@ -60,6 +64,7 @@ class PaymentEntry(AccountsController):
|
||||
def validate(self):
|
||||
self.setup_party_account_field()
|
||||
self.set_missing_values()
|
||||
self.set_liability_account()
|
||||
self.set_missing_ref_details()
|
||||
self.validate_payment_type()
|
||||
self.validate_party_details()
|
||||
@ -87,11 +92,45 @@ class PaymentEntry(AccountsController):
|
||||
if self.difference_amount:
|
||||
frappe.throw(_("Difference Amount must be zero"))
|
||||
self.make_gl_entries()
|
||||
self.make_advance_gl_entries()
|
||||
self.update_outstanding_amounts()
|
||||
self.update_advance_paid()
|
||||
self.update_payment_schedule()
|
||||
self.set_status()
|
||||
|
||||
def set_liability_account(self):
|
||||
if not self.book_advance_payments_in_separate_party_account:
|
||||
return
|
||||
|
||||
account_type = frappe.get_value(
|
||||
"Account", {"name": self.party_account, "company": self.company}, "account_type"
|
||||
)
|
||||
|
||||
if (account_type == "Payable" and self.party_type == "Customer") or (
|
||||
account_type == "Receivable" and self.party_type == "Supplier"
|
||||
):
|
||||
return
|
||||
|
||||
if self.unallocated_amount == 0:
|
||||
for d in self.references:
|
||||
if d.reference_doctype in ["Sales Order", "Purchase Order"]:
|
||||
break
|
||||
else:
|
||||
return
|
||||
|
||||
liability_account = get_party_account(
|
||||
self.party_type, self.party, self.company, include_advance=True
|
||||
)[1]
|
||||
|
||||
self.set(self.party_account_field, liability_account)
|
||||
|
||||
msg = "Book Advance Payments as Liability option is chosen. Paid From account changed from {0} to {1}.".format(
|
||||
frappe.bold(self.party_account),
|
||||
frappe.bold(liability_account),
|
||||
)
|
||||
|
||||
frappe.msgprint(_(msg), alert=True)
|
||||
|
||||
def on_cancel(self):
|
||||
self.ignore_linked_doctypes = (
|
||||
"GL Entry",
|
||||
@ -101,6 +140,7 @@ class PaymentEntry(AccountsController):
|
||||
"Repost Payment Ledger Items",
|
||||
)
|
||||
self.make_gl_entries(cancel=1)
|
||||
self.make_advance_gl_entries(cancel=1)
|
||||
self.update_outstanding_amounts()
|
||||
self.update_advance_paid()
|
||||
self.delink_advance_entry_references()
|
||||
@ -174,7 +214,8 @@ class PaymentEntry(AccountsController):
|
||||
"party_account": self.paid_from if self.payment_type == "Receive" else self.paid_to,
|
||||
"get_outstanding_invoices": True,
|
||||
"get_orders_to_be_billed": True,
|
||||
}
|
||||
},
|
||||
validate=True,
|
||||
)
|
||||
|
||||
# Group latest_references by (voucher_type, voucher_no)
|
||||
@ -379,7 +420,10 @@ class PaymentEntry(AccountsController):
|
||||
elif self.party_type == "Employee":
|
||||
ref_party_account = ref_doc.payable_account
|
||||
|
||||
if ref_party_account != self.party_account:
|
||||
if (
|
||||
ref_party_account != self.party_account
|
||||
and not self.book_advance_payments_in_separate_party_account
|
||||
):
|
||||
frappe.throw(
|
||||
_("{0} {1} is associated with {2}, but Party Account is {3}").format(
|
||||
d.reference_doctype, d.reference_name, ref_party_account, self.party_account
|
||||
@ -941,24 +985,27 @@ class PaymentEntry(AccountsController):
|
||||
cost_center = self.cost_center
|
||||
if d.reference_doctype == "Sales Invoice" and not cost_center:
|
||||
cost_center = frappe.db.get_value(d.reference_doctype, d.reference_name, "cost_center")
|
||||
|
||||
gle = party_gl_dict.copy()
|
||||
gle.update(
|
||||
{
|
||||
"against_voucher_type": d.reference_doctype,
|
||||
"against_voucher": d.reference_name,
|
||||
"cost_center": cost_center,
|
||||
}
|
||||
)
|
||||
|
||||
allocated_amount_in_company_currency = self.calculate_base_allocated_amount_for_reference(d)
|
||||
|
||||
if self.book_advance_payments_in_separate_party_account:
|
||||
against_voucher_type = "Payment Entry"
|
||||
against_voucher = self.name
|
||||
else:
|
||||
against_voucher_type = d.reference_doctype
|
||||
against_voucher = d.reference_name
|
||||
|
||||
gle.update(
|
||||
{
|
||||
dr_or_cr + "_in_account_currency": d.allocated_amount,
|
||||
dr_or_cr: allocated_amount_in_company_currency,
|
||||
dr_or_cr + "_in_account_currency": d.allocated_amount,
|
||||
"against_voucher_type": against_voucher_type,
|
||||
"against_voucher": against_voucher,
|
||||
"cost_center": cost_center,
|
||||
}
|
||||
)
|
||||
|
||||
gl_entries.append(gle)
|
||||
|
||||
if self.unallocated_amount:
|
||||
@ -966,7 +1013,6 @@ class PaymentEntry(AccountsController):
|
||||
base_unallocated_amount = self.unallocated_amount * exchange_rate
|
||||
|
||||
gle = party_gl_dict.copy()
|
||||
|
||||
gle.update(
|
||||
{
|
||||
dr_or_cr + "_in_account_currency": self.unallocated_amount,
|
||||
@ -976,6 +1022,80 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
gl_entries.append(gle)
|
||||
|
||||
def make_advance_gl_entries(self, against_voucher_type=None, against_voucher=None, cancel=0):
|
||||
if self.book_advance_payments_in_separate_party_account:
|
||||
gl_entries = []
|
||||
for d in self.get("references"):
|
||||
if d.reference_doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||
if not (against_voucher_type and against_voucher) or (
|
||||
d.reference_doctype == against_voucher_type and d.reference_name == against_voucher
|
||||
):
|
||||
self.make_invoice_liability_entry(gl_entries, d)
|
||||
|
||||
if cancel:
|
||||
for entry in gl_entries:
|
||||
frappe.db.set_value(
|
||||
"GL Entry",
|
||||
{
|
||||
"voucher_no": self.name,
|
||||
"voucher_type": self.doctype,
|
||||
"voucher_detail_no": entry.voucher_detail_no,
|
||||
"against_voucher_type": entry.against_voucher_type,
|
||||
"against_voucher": entry.against_voucher,
|
||||
},
|
||||
"is_cancelled",
|
||||
1,
|
||||
)
|
||||
|
||||
make_reverse_gl_entries(gl_entries=gl_entries, partial_cancel=True)
|
||||
else:
|
||||
make_gl_entries(gl_entries)
|
||||
|
||||
def make_invoice_liability_entry(self, gl_entries, invoice):
|
||||
args_dict = {
|
||||
"party_type": self.party_type,
|
||||
"party": self.party,
|
||||
"account_currency": self.party_account_currency,
|
||||
"cost_center": self.cost_center,
|
||||
"voucher_type": "Payment Entry",
|
||||
"voucher_no": self.name,
|
||||
"voucher_detail_no": invoice.name,
|
||||
}
|
||||
|
||||
dr_or_cr = "credit" if invoice.reference_doctype == "Sales Invoice" else "debit"
|
||||
args_dict["account"] = invoice.account
|
||||
args_dict[dr_or_cr] = invoice.allocated_amount
|
||||
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
|
||||
args_dict.update(
|
||||
{
|
||||
"against_voucher_type": invoice.reference_doctype,
|
||||
"against_voucher": invoice.reference_name,
|
||||
}
|
||||
)
|
||||
gle = self.get_gl_dict(
|
||||
args_dict,
|
||||
item=self,
|
||||
)
|
||||
gl_entries.append(gle)
|
||||
|
||||
args_dict[dr_or_cr] = 0
|
||||
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 + "_in_account_currency"] = invoice.allocated_amount
|
||||
args_dict.update(
|
||||
{
|
||||
"against_voucher_type": "Payment Entry",
|
||||
"against_voucher": self.name,
|
||||
}
|
||||
)
|
||||
gle = self.get_gl_dict(
|
||||
args_dict,
|
||||
item=self,
|
||||
)
|
||||
gl_entries.append(gle)
|
||||
|
||||
def add_bank_gl_entries(self, gl_entries):
|
||||
if self.payment_type in ("Pay", "Internal Transfer"):
|
||||
gl_entries.append(
|
||||
@ -1301,7 +1421,7 @@ def validate_inclusive_tax(tax, doc):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_outstanding_reference_documents(args):
|
||||
def get_outstanding_reference_documents(args, validate=False):
|
||||
if isinstance(args, str):
|
||||
args = json.loads(args)
|
||||
|
||||
@ -1365,7 +1485,7 @@ def get_outstanding_reference_documents(args):
|
||||
outstanding_invoices = get_outstanding_invoices(
|
||||
args.get("party_type"),
|
||||
args.get("party"),
|
||||
args.get("party_account"),
|
||||
get_party_account(args.get("party_type"), args.get("party"), args.get("company")),
|
||||
common_filter=common_filter,
|
||||
posting_date=posting_and_due_date,
|
||||
min_outstanding=args.get("outstanding_amt_greater_than"),
|
||||
@ -1421,13 +1541,14 @@ def get_outstanding_reference_documents(args):
|
||||
elif args.get("get_orders_to_be_billed"):
|
||||
ref_document_type = "orders"
|
||||
|
||||
frappe.msgprint(
|
||||
_(
|
||||
"No outstanding {0} found for the {1} {2} which qualify the filters you have specified."
|
||||
).format(
|
||||
ref_document_type, _(args.get("party_type")).lower(), frappe.bold(args.get("party"))
|
||||
if not validate:
|
||||
frappe.msgprint(
|
||||
_(
|
||||
"No outstanding {0} found for the {1} {2} which qualify the filters you have specified."
|
||||
).format(
|
||||
ref_document_type, _(args.get("party_type")).lower(), frappe.bold(args.get("party"))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
@ -1463,6 +1584,7 @@ def split_invoices_based_on_payment_terms(outstanding_invoices):
|
||||
"outstanding_amount": flt(d.outstanding_amount),
|
||||
"payment_amount": payment_term.payment_amount,
|
||||
"payment_term": payment_term.payment_term,
|
||||
"account": d.account,
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -1587,6 +1709,7 @@ def get_negative_outstanding_invoices(
|
||||
condition=None,
|
||||
):
|
||||
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
|
||||
account = "debit_to" if voucher_type == "Sales Invoice" else "credit_to"
|
||||
supplier_condition = ""
|
||||
if voucher_type == "Purchase Invoice":
|
||||
supplier_condition = "and (release_date is null or release_date <= CURRENT_DATE)"
|
||||
@ -1600,7 +1723,7 @@ def get_negative_outstanding_invoices(
|
||||
return frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
"{voucher_type}" as voucher_type, name as voucher_no,
|
||||
"{voucher_type}" as voucher_type, name as voucher_no, {account} as account,
|
||||
if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) as invoice_amount,
|
||||
outstanding_amount, posting_date,
|
||||
due_date, conversion_rate as exchange_rate
|
||||
@ -1623,6 +1746,7 @@ def get_negative_outstanding_invoices(
|
||||
"party_type": scrub(party_type),
|
||||
"party_account": "debit_to" if party_type == "Customer" else "credit_to",
|
||||
"cost_center": cost_center,
|
||||
"account": account,
|
||||
}
|
||||
),
|
||||
(party, party_account),
|
||||
@ -1637,7 +1761,6 @@ def get_party_details(company, party_type, party, date, cost_center=None):
|
||||
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
|
||||
|
||||
party_account = get_party_account(party_type, party, company)
|
||||
|
||||
account_currency = get_account_currency(party_account)
|
||||
account_balance = get_balance_on(party_account, date, cost_center=cost_center)
|
||||
_party_name = "title" if party_type == "Shareholder" else party_type.lower() + "_name"
|
||||
@ -1710,7 +1833,7 @@ def get_outstanding_on_journal_entry(name):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_reference_details(reference_doctype, reference_name, party_account_currency):
|
||||
total_amount = outstanding_amount = exchange_rate = None
|
||||
total_amount = outstanding_amount = exchange_rate = account = None
|
||||
|
||||
ref_doc = frappe.get_doc(reference_doctype, reference_name)
|
||||
company_currency = ref_doc.get("company_currency") or erpnext.get_company_currency(
|
||||
@ -1748,6 +1871,9 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
||||
|
||||
if reference_doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||
outstanding_amount = ref_doc.get("outstanding_amount")
|
||||
account = (
|
||||
ref_doc.get("debit_to") if reference_doctype == "Sales Invoice" else ref_doc.get("credit_to")
|
||||
)
|
||||
else:
|
||||
outstanding_amount = flt(total_amount) - flt(ref_doc.get("advance_paid"))
|
||||
|
||||
@ -1755,7 +1881,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
||||
# Get the exchange rate based on the posting date of the ref doc.
|
||||
exchange_rate = get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date)
|
||||
|
||||
return frappe._dict(
|
||||
res = frappe._dict(
|
||||
{
|
||||
"due_date": ref_doc.get("due_date"),
|
||||
"total_amount": flt(total_amount),
|
||||
@ -1764,6 +1890,9 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
||||
"bill_no": ref_doc.get("bill_no"),
|
||||
}
|
||||
)
|
||||
if account:
|
||||
res.update({"account": account})
|
||||
return res
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
@ -932,7 +932,7 @@ class TestPaymentEntry(FrappeTestCase):
|
||||
self.assertEqual(pe.cost_center, si.cost_center)
|
||||
self.assertEqual(flt(expected_account_balance), account_balance)
|
||||
self.assertEqual(flt(expected_party_balance), party_balance)
|
||||
self.assertEqual(flt(expected_party_account_balance), party_account_balance)
|
||||
self.assertEqual(flt(expected_party_account_balance, 2), flt(party_account_balance, 2))
|
||||
|
||||
def test_multi_currency_payment_entry_with_taxes(self):
|
||||
payment_entry = create_payment_entry(
|
||||
|
@ -15,7 +15,8 @@
|
||||
"outstanding_amount",
|
||||
"allocated_amount",
|
||||
"exchange_rate",
|
||||
"exchange_gain_loss"
|
||||
"exchange_gain_loss",
|
||||
"account"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@ -101,12 +102,18 @@
|
||||
"label": "Exchange Gain/Loss",
|
||||
"options": "Company:company:default_currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Account",
|
||||
"options": "Account"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2022-12-12 12:31:44.919895",
|
||||
"modified": "2023-06-08 07:40:38.487874",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Entry Reference",
|
||||
|
@ -13,6 +13,7 @@
|
||||
"party_type",
|
||||
"party",
|
||||
"due_date",
|
||||
"voucher_detail_no",
|
||||
"cost_center",
|
||||
"finance_book",
|
||||
"voucher_type",
|
||||
@ -142,12 +143,17 @@
|
||||
"fieldname": "remarks",
|
||||
"fieldtype": "Text",
|
||||
"label": "Remarks"
|
||||
},
|
||||
{
|
||||
"fieldname": "voucher_detail_no",
|
||||
"fieldtype": "Data",
|
||||
"label": "Voucher Detail No"
|
||||
}
|
||||
],
|
||||
"in_create": 1,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2022-08-22 15:32:56.629430",
|
||||
"modified": "2023-06-29 12:24:20.500632",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Ledger Entry",
|
||||
|
@ -29,6 +29,17 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
||||
};
|
||||
});
|
||||
|
||||
this.frm.set_query('default_advance_account', () => {
|
||||
return {
|
||||
filters: {
|
||||
"company": this.frm.doc.company,
|
||||
"is_group": 0,
|
||||
"account_type": this.frm.doc.party_type == 'Customer' ? "Receivable": "Payable",
|
||||
"root_type": this.frm.doc.party_type == 'Customer' ? "Liability": "Asset"
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
this.frm.set_query('bank_cash_account', () => {
|
||||
return {
|
||||
filters:[
|
||||
@ -128,19 +139,20 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
||||
this.frm.trigger("clear_child_tables");
|
||||
|
||||
if (!this.frm.doc.receivable_payable_account && this.frm.doc.party_type && this.frm.doc.party) {
|
||||
return frappe.call({
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.party.get_party_account",
|
||||
args: {
|
||||
company: this.frm.doc.company,
|
||||
party_type: this.frm.doc.party_type,
|
||||
party: this.frm.doc.party
|
||||
party: this.frm.doc.party,
|
||||
include_advance: 1
|
||||
},
|
||||
callback: (r) => {
|
||||
if (!r.exc && r.message) {
|
||||
this.frm.set_value("receivable_payable_account", r.message);
|
||||
this.frm.set_value("receivable_payable_account", r.message[0]);
|
||||
this.frm.set_value("default_advance_account", r.message[1]);
|
||||
}
|
||||
this.frm.refresh();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
"column_break_4",
|
||||
"party",
|
||||
"receivable_payable_account",
|
||||
"default_advance_account",
|
||||
"col_break1",
|
||||
"from_invoice_date",
|
||||
"from_payment_date",
|
||||
@ -185,13 +186,21 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Cost Center",
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.party",
|
||||
"fieldname": "default_advance_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Advance Account",
|
||||
"mandatory_depends_on": "doc.party_type",
|
||||
"options": "Account"
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
"icon": "icon-resize-horizontal",
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2022-04-29 15:37:10.246831",
|
||||
"modified": "2023-06-09 13:02:48.718362",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation",
|
||||
|
@ -55,12 +55,28 @@ class PaymentReconciliation(Document):
|
||||
self.add_payment_entries(non_reconciled_payments)
|
||||
|
||||
def get_payment_entries(self):
|
||||
if self.default_advance_account:
|
||||
party_account = [self.receivable_payable_account, self.default_advance_account]
|
||||
else:
|
||||
party_account = [self.receivable_payable_account]
|
||||
|
||||
order_doctype = "Sales Order" if self.party_type == "Customer" else "Purchase Order"
|
||||
condition = self.get_conditions(get_payments=True)
|
||||
condition = frappe._dict(
|
||||
{
|
||||
"company": self.get("company"),
|
||||
"get_payments": True,
|
||||
"cost_center": self.get("cost_center"),
|
||||
"from_payment_date": self.get("from_payment_date"),
|
||||
"to_payment_date": self.get("to_payment_date"),
|
||||
"maximum_payment_amount": self.get("maximum_payment_amount"),
|
||||
"minimum_payment_amount": self.get("minimum_payment_amount"),
|
||||
}
|
||||
)
|
||||
|
||||
payment_entries = get_advance_payment_entries(
|
||||
self.party_type,
|
||||
self.party,
|
||||
self.receivable_payable_account,
|
||||
party_account,
|
||||
order_doctype,
|
||||
against_all_orders=True,
|
||||
limit=self.payment_limit,
|
||||
|
@ -38,7 +38,7 @@ class TestProcessDeferredAccounting(unittest.TestCase):
|
||||
si.save()
|
||||
si.submit()
|
||||
|
||||
process_deferred_accounting = doc = frappe.get_doc(
|
||||
process_deferred_accounting = frappe.get_doc(
|
||||
dict(
|
||||
doctype="Process Deferred Accounting",
|
||||
posting_date="2019-01-01",
|
||||
@ -56,7 +56,7 @@ class TestProcessDeferredAccounting(unittest.TestCase):
|
||||
["Sales - _TC", 0.0, 33.85, "2019-01-31"],
|
||||
]
|
||||
|
||||
check_gl_entries(self, si.name, expected_gle, "2019-01-10")
|
||||
check_gl_entries(self, si.name, expected_gle, "2019-01-31")
|
||||
|
||||
def test_pda_submission_and_cancellation(self):
|
||||
pda = frappe.get_doc(
|
||||
|
@ -1088,6 +1088,7 @@
|
||||
"fieldtype": "Button",
|
||||
"label": "Get Advances Paid",
|
||||
"oldfieldtype": "Button",
|
||||
"options": "set_advances",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
|
@ -1664,6 +1664,63 @@ class TestPurchaseInvoice(unittest.TestCase, StockTestMixin):
|
||||
|
||||
self.assertTrue(return_pi.docstatus == 1)
|
||||
|
||||
def test_advance_entries_as_asset(self):
|
||||
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
|
||||
|
||||
account = create_account(
|
||||
parent_account="Current Assets - _TC",
|
||||
account_name="Advances Paid",
|
||||
company="_Test Company",
|
||||
account_type="Receivable",
|
||||
)
|
||||
|
||||
set_advance_flag(company="_Test Company", flag=1, default_account=account)
|
||||
|
||||
pe = create_payment_entry(
|
||||
company="_Test Company",
|
||||
payment_type="Pay",
|
||||
party_type="Supplier",
|
||||
party="_Test Supplier",
|
||||
paid_from="Cash - _TC",
|
||||
paid_to="Creditors - _TC",
|
||||
paid_amount=500,
|
||||
)
|
||||
pe.submit()
|
||||
|
||||
pi = make_purchase_invoice(
|
||||
company="_Test Company",
|
||||
customer="_Test Supplier",
|
||||
do_not_save=True,
|
||||
do_not_submit=True,
|
||||
rate=1000,
|
||||
price_list_rate=1000,
|
||||
qty=1,
|
||||
)
|
||||
pi.base_grand_total = 1000
|
||||
pi.grand_total = 1000
|
||||
pi.set_advances()
|
||||
for advance in pi.advances:
|
||||
advance.allocated_amount = 500 if advance.reference_name == pe.name else 0
|
||||
pi.save()
|
||||
pi.submit()
|
||||
|
||||
self.assertEqual(pi.advances[0].allocated_amount, 500)
|
||||
|
||||
# Check GL Entry against payment doctype
|
||||
expected_gle = [
|
||||
["Advances Paid - _TC", 0.0, 500, nowdate()],
|
||||
["Cash - _TC", 0.0, 500, nowdate()],
|
||||
["Creditors - _TC", 500, 0.0, nowdate()],
|
||||
["Creditors - _TC", 500, 0.0, nowdate()],
|
||||
]
|
||||
|
||||
check_gl_entries(self, pe.name, expected_gle, nowdate(), voucher_type="Payment Entry")
|
||||
|
||||
pi.load_from_db()
|
||||
self.assertEqual(pi.outstanding_amount, 500)
|
||||
|
||||
set_advance_flag(company="_Test Company", flag=0, default_account="")
|
||||
|
||||
def test_gl_entries_for_standalone_debit_note(self):
|
||||
make_purchase_invoice(qty=5, rate=500, update_stock=True)
|
||||
|
||||
@ -1680,16 +1737,32 @@ class TestPurchaseInvoice(unittest.TestCase, StockTestMixin):
|
||||
self.assertAlmostEqual(returned_inv.items[0].rate, rate)
|
||||
|
||||
|
||||
def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
|
||||
gl_entries = frappe.db.sql(
|
||||
"""select account, debit, credit, posting_date
|
||||
from `tabGL Entry`
|
||||
where voucher_type='Purchase Invoice' and voucher_no=%s and posting_date >= %s
|
||||
order by posting_date asc, account asc""",
|
||||
(voucher_no, posting_date),
|
||||
as_dict=1,
|
||||
def set_advance_flag(company, flag, default_account):
|
||||
frappe.db.set_value(
|
||||
"Company",
|
||||
company,
|
||||
{
|
||||
"book_advance_payments_in_separate_party_account": flag,
|
||||
"default_advance_paid_account": default_account,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def check_gl_entries(doc, voucher_no, expected_gle, posting_date, voucher_type="Purchase Invoice"):
|
||||
gl = frappe.qb.DocType("GL Entry")
|
||||
q = (
|
||||
frappe.qb.from_(gl)
|
||||
.select(gl.account, gl.debit, gl.credit, gl.posting_date)
|
||||
.where(
|
||||
(gl.voucher_type == voucher_type)
|
||||
& (gl.voucher_no == voucher_no)
|
||||
& (gl.posting_date >= posting_date)
|
||||
& (gl.is_cancelled == 0)
|
||||
)
|
||||
.orderby(gl.posting_date, gl.account, gl.creation)
|
||||
)
|
||||
gl_entries = q.run(as_dict=True)
|
||||
|
||||
for i, gle in enumerate(gl_entries):
|
||||
doc.assertEqual(expected_gle[i][0], gle.account)
|
||||
doc.assertEqual(expected_gle[i][1], gle.debit)
|
||||
|
@ -117,7 +117,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-09-26 15:47:28.167371",
|
||||
"modified": "2023-06-23 21:13:18.013816",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Advance",
|
||||
@ -125,5 +125,6 @@
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"customer": "_Test Customer",
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
"debit_to": "Debtors - _TC",
|
||||
"doctype": "Sales Invoice",
|
||||
"items": [
|
||||
{
|
||||
@ -78,7 +78,7 @@
|
||||
"currency": "INR",
|
||||
"customer": "_Test Customer",
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
"debit_to": "Debtors - _TC",
|
||||
"doctype": "Sales Invoice",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"items": [
|
||||
@ -137,7 +137,7 @@
|
||||
"currency": "INR",
|
||||
"customer": "_Test Customer",
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
"debit_to": "Debtors - _TC",
|
||||
"doctype": "Sales Invoice",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"items": [
|
||||
@ -265,7 +265,7 @@
|
||||
"currency": "INR",
|
||||
"customer": "_Test Customer",
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
"debit_to": "Debtors - _TC",
|
||||
"doctype": "Sales Invoice",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"items": [
|
||||
|
@ -6,7 +6,6 @@ import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.model.dynamic_links import get_dynamic_link_map
|
||||
from frappe.model.naming import make_autoname
|
||||
from frappe.tests.utils import change_settings
|
||||
from frappe.utils import add_days, flt, getdate, nowdate, today
|
||||
|
||||
@ -35,7 +34,6 @@ from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle
|
||||
get_serial_nos_from_bundle,
|
||||
make_serial_batch_bundle,
|
||||
)
|
||||
from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import (
|
||||
get_qty_after_transaction,
|
||||
make_stock_entry,
|
||||
@ -1726,7 +1724,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
# Party Account currency must be in USD, as there is existing GLE with USD
|
||||
si4 = create_sales_invoice(
|
||||
customer="_Test Customer USD",
|
||||
debit_to="_Test Receivable - _TC",
|
||||
debit_to="Debtors - _TC",
|
||||
currency="USD",
|
||||
conversion_rate=50,
|
||||
do_not_submit=True,
|
||||
@ -1739,7 +1737,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si3.cancel()
|
||||
si5 = create_sales_invoice(
|
||||
customer="_Test Customer USD",
|
||||
debit_to="_Test Receivable - _TC",
|
||||
debit_to="Debtors - _TC",
|
||||
currency="USD",
|
||||
conversion_rate=50,
|
||||
do_not_submit=True,
|
||||
@ -1818,7 +1816,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
"reference_date": nowdate(),
|
||||
"received_amount": 300,
|
||||
"paid_amount": 300,
|
||||
"paid_from": "_Test Receivable - _TC",
|
||||
"paid_from": "Debtors - _TC",
|
||||
"paid_to": "_Test Cash - _TC",
|
||||
}
|
||||
)
|
||||
@ -3252,9 +3250,10 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si.submit()
|
||||
|
||||
expected_gle = [
|
||||
["_Test Receivable USD - _TC", 7500.0, 500],
|
||||
["Exchange Gain/Loss - _TC", 500.0, 0.0],
|
||||
["Sales - _TC", 0.0, 7500.0],
|
||||
["_Test Exchange Gain/Loss - _TC", 500.0, 0.0, nowdate()],
|
||||
["_Test Receivable USD - _TC", 7500.0, 0.0, nowdate()],
|
||||
["_Test Receivable USD - _TC", 0.0, 500.0, nowdate()],
|
||||
["Sales - _TC", 0.0, 7500.0, nowdate()],
|
||||
]
|
||||
|
||||
check_gl_entries(self, si.name, expected_gle, nowdate())
|
||||
@ -3310,6 +3309,73 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
)
|
||||
self.assertRaises(frappe.ValidationError, si.submit)
|
||||
|
||||
def test_advance_entries_as_liability(self):
|
||||
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
|
||||
|
||||
account = create_account(
|
||||
parent_account="Current Liabilities - _TC",
|
||||
account_name="Advances Received",
|
||||
company="_Test Company",
|
||||
account_type="Receivable",
|
||||
)
|
||||
|
||||
set_advance_flag(company="_Test Company", flag=1, default_account=account)
|
||||
|
||||
pe = create_payment_entry(
|
||||
company="_Test Company",
|
||||
payment_type="Receive",
|
||||
party_type="Customer",
|
||||
party="_Test Customer",
|
||||
paid_from="Debtors - _TC",
|
||||
paid_to="Cash - _TC",
|
||||
paid_amount=1000,
|
||||
)
|
||||
pe.submit()
|
||||
|
||||
si = create_sales_invoice(
|
||||
company="_Test Company",
|
||||
customer="_Test Customer",
|
||||
do_not_save=True,
|
||||
do_not_submit=True,
|
||||
rate=500,
|
||||
price_list_rate=500,
|
||||
)
|
||||
si.base_grand_total = 500
|
||||
si.grand_total = 500
|
||||
si.set_advances()
|
||||
for advance in si.advances:
|
||||
advance.allocated_amount = 500 if advance.reference_name == pe.name else 0
|
||||
si.save()
|
||||
si.submit()
|
||||
|
||||
self.assertEqual(si.advances[0].allocated_amount, 500)
|
||||
|
||||
# Check GL Entry against payment doctype
|
||||
expected_gle = [
|
||||
["Advances Received - _TC", 500, 0.0, nowdate()],
|
||||
["Cash - _TC", 1000, 0.0, nowdate()],
|
||||
["Debtors - _TC", 0.0, 1000, nowdate()],
|
||||
["Debtors - _TC", 0.0, 500, nowdate()],
|
||||
]
|
||||
|
||||
check_gl_entries(self, pe.name, expected_gle, nowdate(), voucher_type="Payment Entry")
|
||||
|
||||
si.load_from_db()
|
||||
self.assertEqual(si.outstanding_amount, 0)
|
||||
|
||||
set_advance_flag(company="_Test Company", flag=0, default_account="")
|
||||
|
||||
|
||||
def set_advance_flag(company, flag, default_account):
|
||||
frappe.db.set_value(
|
||||
"Company",
|
||||
company,
|
||||
{
|
||||
"book_advance_payments_in_separate_party_account": flag,
|
||||
"default_advance_received_account": default_account,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def get_sales_invoice_for_e_invoice():
|
||||
si = make_sales_invoice_for_ewaybill()
|
||||
@ -3346,16 +3412,20 @@ def get_sales_invoice_for_e_invoice():
|
||||
return si
|
||||
|
||||
|
||||
def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
|
||||
gl_entries = frappe.db.sql(
|
||||
"""select account, debit, credit, posting_date
|
||||
from `tabGL Entry`
|
||||
where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s
|
||||
and is_cancelled = 0
|
||||
order by posting_date asc, account asc""",
|
||||
(voucher_no, posting_date),
|
||||
as_dict=1,
|
||||
def check_gl_entries(doc, voucher_no, expected_gle, posting_date, voucher_type="Sales Invoice"):
|
||||
gl = frappe.qb.DocType("GL Entry")
|
||||
q = (
|
||||
frappe.qb.from_(gl)
|
||||
.select(gl.account, gl.debit, gl.credit, gl.posting_date)
|
||||
.where(
|
||||
(gl.voucher_type == voucher_type)
|
||||
& (gl.voucher_no == voucher_no)
|
||||
& (gl.posting_date >= posting_date)
|
||||
& (gl.is_cancelled == 0)
|
||||
)
|
||||
.orderby(gl.posting_date, gl.account, gl.creation)
|
||||
)
|
||||
gl_entries = q.run(as_dict=True)
|
||||
|
||||
for i, gle in enumerate(gl_entries):
|
||||
doc.assertEqual(expected_gle[i][0], gle.account)
|
||||
|
@ -118,7 +118,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-09-26 15:47:46.911595",
|
||||
"modified": "2023-06-23 21:12:57.557731",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Advance",
|
||||
@ -126,5 +126,6 @@
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
@ -223,6 +223,7 @@ def check_if_in_list(gle, gl_map, dimensions=None):
|
||||
"party_type",
|
||||
"project",
|
||||
"finance_book",
|
||||
"voucher_no",
|
||||
]
|
||||
|
||||
if dimensions:
|
||||
@ -500,7 +501,12 @@ def get_round_off_account_and_cost_center(
|
||||
|
||||
|
||||
def make_reverse_gl_entries(
|
||||
gl_entries=None, voucher_type=None, voucher_no=None, adv_adj=False, update_outstanding="Yes"
|
||||
gl_entries=None,
|
||||
voucher_type=None,
|
||||
voucher_no=None,
|
||||
adv_adj=False,
|
||||
update_outstanding="Yes",
|
||||
partial_cancel=False,
|
||||
):
|
||||
"""
|
||||
Get original gl entries of the voucher
|
||||
@ -520,14 +526,19 @@ def make_reverse_gl_entries(
|
||||
|
||||
if gl_entries:
|
||||
create_payment_ledger_entry(
|
||||
gl_entries, cancel=1, adv_adj=adv_adj, update_outstanding=update_outstanding
|
||||
gl_entries,
|
||||
cancel=1,
|
||||
adv_adj=adv_adj,
|
||||
update_outstanding=update_outstanding,
|
||||
partial_cancel=partial_cancel,
|
||||
)
|
||||
validate_accounting_period(gl_entries)
|
||||
check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
|
||||
|
||||
is_opening = any(d.get("is_opening") == "Yes" for d in gl_entries)
|
||||
validate_against_pcv(is_opening, gl_entries[0]["posting_date"], gl_entries[0]["company"])
|
||||
set_as_cancel(gl_entries[0]["voucher_type"], gl_entries[0]["voucher_no"])
|
||||
if not partial_cancel:
|
||||
set_as_cancel(gl_entries[0]["voucher_type"], gl_entries[0]["voucher_no"])
|
||||
|
||||
for entry in gl_entries:
|
||||
new_gle = copy.deepcopy(entry)
|
||||
|
@ -367,7 +367,7 @@ def set_account_and_due_date(
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_account(party_type, party=None, company=None):
|
||||
def get_party_account(party_type, party=None, company=None, include_advance=False):
|
||||
"""Returns the account for the given `party`.
|
||||
Will first search in party (Customer / Supplier) record, if not found,
|
||||
will search in group (Customer Group / Supplier Group),
|
||||
@ -408,6 +408,40 @@ def get_party_account(party_type, party=None, company=None):
|
||||
if (account and account_currency != existing_gle_currency) or not account:
|
||||
account = get_party_gle_account(party_type, party, company)
|
||||
|
||||
if include_advance and party_type in ["Customer", "Supplier"]:
|
||||
advance_account = get_party_advance_account(party_type, party, company)
|
||||
if advance_account:
|
||||
return [account, advance_account]
|
||||
else:
|
||||
return [account]
|
||||
|
||||
return account
|
||||
|
||||
|
||||
def get_party_advance_account(party_type, party, company):
|
||||
account = frappe.db.get_value(
|
||||
"Party Account",
|
||||
{"parenttype": party_type, "parent": party, "company": company},
|
||||
"advance_account",
|
||||
)
|
||||
|
||||
if not account:
|
||||
party_group_doctype = "Customer Group" if party_type == "Customer" else "Supplier Group"
|
||||
group = frappe.get_cached_value(party_type, party, scrub(party_group_doctype))
|
||||
account = frappe.db.get_value(
|
||||
"Party Account",
|
||||
{"parenttype": party_group_doctype, "parent": group, "company": company},
|
||||
"advance_account",
|
||||
)
|
||||
|
||||
if not account:
|
||||
account_name = (
|
||||
"default_advance_received_account"
|
||||
if party_type == "Customer"
|
||||
else "default_advance_paid_account"
|
||||
)
|
||||
account = frappe.get_cached_value("Company", company, account_name)
|
||||
|
||||
return account
|
||||
|
||||
|
||||
@ -517,7 +551,10 @@ def validate_party_accounts(doc):
|
||||
)
|
||||
|
||||
# validate if account is mapped for same company
|
||||
validate_account_head(account.idx, account.account, account.company)
|
||||
if account.account:
|
||||
validate_account_head(account.idx, account.account, account.company)
|
||||
if account.advance_account:
|
||||
validate_account_head(account.idx, account.advance_account, account.company)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
@ -470,6 +470,9 @@ def reconcile_against_document(args, skip_ref_details_update_for_pe=False): # n
|
||||
gl_map = doc.build_gl_map()
|
||||
create_payment_ledger_entry(gl_map, update_outstanding="No", cancel=0, adv_adj=1)
|
||||
|
||||
if voucher_type == "Payment Entry":
|
||||
doc.make_advance_gl_entries()
|
||||
|
||||
# Only update outstanding for newly linked vouchers
|
||||
for entry in entries:
|
||||
update_voucher_outstanding(
|
||||
@ -490,50 +493,53 @@ def check_if_advance_entry_modified(args):
|
||||
|
||||
ret = None
|
||||
if args.voucher_type == "Journal Entry":
|
||||
ret = frappe.db.sql(
|
||||
"""
|
||||
select t2.{dr_or_cr} from `tabJournal Entry` t1, `tabJournal Entry Account` t2
|
||||
where t1.name = t2.parent and t2.account = %(account)s
|
||||
and t2.party_type = %(party_type)s and t2.party = %(party)s
|
||||
and (t2.reference_type is null or t2.reference_type in ('', 'Sales Order', 'Purchase Order'))
|
||||
and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s
|
||||
and t1.docstatus=1 """.format(
|
||||
dr_or_cr=args.get("dr_or_cr")
|
||||
),
|
||||
args,
|
||||
journal_entry = frappe.qb.DocType("Journal Entry")
|
||||
journal_acc = frappe.qb.DocType("Journal Entry Account")
|
||||
|
||||
q = (
|
||||
frappe.qb.from_(journal_entry)
|
||||
.inner_join(journal_acc)
|
||||
.on(journal_entry.name == journal_acc.parent)
|
||||
.select(journal_acc[args.get("dr_or_cr")])
|
||||
.where(
|
||||
(journal_acc.account == args.get("account"))
|
||||
& ((journal_acc.party_type == args.get("party_type")))
|
||||
& ((journal_acc.party == args.get("party")))
|
||||
& (
|
||||
(journal_acc.reference_type.isnull())
|
||||
| (journal_acc.reference_type.isin(["", "Sales Order", "Purchase Order"]))
|
||||
)
|
||||
& ((journal_entry.name == args.get("voucher_no")))
|
||||
& ((journal_acc.name == args.get("voucher_detail_no")))
|
||||
& ((journal_entry.docstatus == 1))
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
party_account_field = (
|
||||
"paid_from" if erpnext.get_party_account_type(args.party_type) == "Receivable" else "paid_to"
|
||||
payment_entry = frappe.qb.DocType("Payment Entry")
|
||||
payment_ref = frappe.qb.DocType("Payment Entry Reference")
|
||||
|
||||
q = (
|
||||
frappe.qb.from_(payment_entry)
|
||||
.select(payment_entry.name)
|
||||
.where(payment_entry.name == args.get("voucher_no"))
|
||||
.where(payment_entry.docstatus == 1)
|
||||
.where(payment_entry.party_type == args.get("party_type"))
|
||||
.where(payment_entry.party == args.get("party"))
|
||||
)
|
||||
|
||||
if args.voucher_detail_no:
|
||||
ret = frappe.db.sql(
|
||||
"""select t1.name
|
||||
from `tabPayment Entry` t1, `tabPayment Entry Reference` t2
|
||||
where
|
||||
t1.name = t2.parent and t1.docstatus = 1
|
||||
and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s
|
||||
and t1.party_type = %(party_type)s and t1.party = %(party)s and t1.{0} = %(account)s
|
||||
and t2.reference_doctype in ('', 'Sales Order', 'Purchase Order')
|
||||
and t2.allocated_amount = %(unreconciled_amount)s
|
||||
""".format(
|
||||
party_account_field
|
||||
),
|
||||
args,
|
||||
q = (
|
||||
q.inner_join(payment_ref)
|
||||
.on(payment_entry.name == payment_ref.parent)
|
||||
.where(payment_ref.name == args.get("voucher_detail_no"))
|
||||
.where(payment_ref.reference_doctype.isin(("", "Sales Order", "Purchase Order")))
|
||||
.where(payment_ref.allocated_amount == args.get("unreconciled_amount"))
|
||||
)
|
||||
else:
|
||||
ret = frappe.db.sql(
|
||||
"""select name from `tabPayment Entry`
|
||||
where
|
||||
name = %(voucher_no)s and docstatus = 1
|
||||
and party_type = %(party_type)s and party = %(party)s and {0} = %(account)s
|
||||
and unallocated_amount = %(unreconciled_amount)s
|
||||
""".format(
|
||||
party_account_field
|
||||
),
|
||||
args,
|
||||
)
|
||||
q = q.where(payment_entry.unallocated_amount == args.get("unreconciled_amount"))
|
||||
|
||||
ret = q.run(as_dict=True)
|
||||
|
||||
if not ret:
|
||||
throw(_("""Payment Entry has been modified after you pulled it. Please pull it again."""))
|
||||
@ -612,6 +618,7 @@ def update_reference_in_payment_entry(
|
||||
if not d.exchange_gain_loss
|
||||
else payment_entry.get_exchange_rate(),
|
||||
"exchange_gain_loss": d.exchange_gain_loss, # only populated from invoice in case of advance allocation
|
||||
"account": d.account,
|
||||
}
|
||||
|
||||
if d.voucher_detail_no:
|
||||
@ -724,6 +731,7 @@ def remove_ref_doc_link_from_pe(ref_type, ref_no):
|
||||
try:
|
||||
pe_doc = frappe.get_doc("Payment Entry", pe)
|
||||
pe_doc.set_amounts()
|
||||
pe_doc.make_advance_gl_entries(against_voucher_type=ref_type, against_voucher=ref_no, cancel=1)
|
||||
pe_doc.clear_unallocated_reference_document_rows()
|
||||
pe_doc.validate_payment_type_with_outstanding()
|
||||
except Exception as e:
|
||||
@ -915,6 +923,7 @@ def get_outstanding_invoices(
|
||||
"outstanding_amount": outstanding_amount,
|
||||
"due_date": d.due_date,
|
||||
"currency": d.currency,
|
||||
"account": d.account,
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -1453,6 +1462,7 @@ def get_payment_ledger_entries(gl_entries, cancel=0):
|
||||
due_date=gle.due_date,
|
||||
voucher_type=gle.voucher_type,
|
||||
voucher_no=gle.voucher_no,
|
||||
voucher_detail_no=gle.voucher_detail_no,
|
||||
against_voucher_type=gle.against_voucher_type
|
||||
if gle.against_voucher_type
|
||||
else gle.voucher_type,
|
||||
@ -1474,7 +1484,7 @@ def get_payment_ledger_entries(gl_entries, cancel=0):
|
||||
|
||||
|
||||
def create_payment_ledger_entry(
|
||||
gl_entries, cancel=0, adv_adj=0, update_outstanding="Yes", from_repost=0
|
||||
gl_entries, cancel=0, adv_adj=0, update_outstanding="Yes", from_repost=0, partial_cancel=False
|
||||
):
|
||||
if gl_entries:
|
||||
ple_map = get_payment_ledger_entries(gl_entries, cancel=cancel)
|
||||
@ -1484,7 +1494,7 @@ def create_payment_ledger_entry(
|
||||
ple = frappe.get_doc(entry)
|
||||
|
||||
if cancel:
|
||||
delink_original_entry(ple)
|
||||
delink_original_entry(ple, partial_cancel=partial_cancel)
|
||||
|
||||
ple.flags.ignore_permissions = 1
|
||||
ple.flags.adv_adj = adv_adj
|
||||
@ -1531,7 +1541,7 @@ def update_voucher_outstanding(voucher_type, voucher_no, account, party_type, pa
|
||||
ref_doc.set_status(update=True)
|
||||
|
||||
|
||||
def delink_original_entry(pl_entry):
|
||||
def delink_original_entry(pl_entry, partial_cancel=False):
|
||||
if pl_entry:
|
||||
ple = qb.DocType("Payment Ledger Entry")
|
||||
query = (
|
||||
@ -1551,6 +1561,10 @@ def delink_original_entry(pl_entry):
|
||||
& (ple.against_voucher_no == pl_entry.against_voucher_no)
|
||||
)
|
||||
)
|
||||
|
||||
if partial_cancel:
|
||||
query = query.where(ple.voucher_detail_no == pl_entry.voucher_detail_no)
|
||||
|
||||
query.run()
|
||||
|
||||
|
||||
|
@ -8,7 +8,7 @@ frappe.ui.form.on("Supplier", {
|
||||
frm.set_value("represents_company", "");
|
||||
}
|
||||
frm.set_query('account', 'accounts', function (doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
let d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
'account_type': 'Payable',
|
||||
@ -17,6 +17,19 @@ frappe.ui.form.on("Supplier", {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query('advance_account', 'accounts', function (doc, cdt, cdn) {
|
||||
let d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
"account_type": "Payable",
|
||||
"root_type": "Asset",
|
||||
"company": d.company,
|
||||
"is_group": 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("default_bank_account", function() {
|
||||
return {
|
||||
filters: {
|
||||
|
@ -53,6 +53,7 @@
|
||||
"primary_address",
|
||||
"accounting_tab",
|
||||
"payment_terms",
|
||||
"default_accounts_section",
|
||||
"accounts",
|
||||
"settings_tab",
|
||||
"allow_purchase_invoice_creation_without_purchase_order",
|
||||
@ -449,6 +450,11 @@
|
||||
"fieldname": "column_break_59",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "default_accounts_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Default Accounts"
|
||||
},
|
||||
{
|
||||
"fieldname": "portal_users_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
|
@ -7,6 +7,7 @@ import json
|
||||
import frappe
|
||||
from frappe import _, bold, throw
|
||||
from frappe.model.workflow import get_workflow_name, is_transition_condition_satisfied
|
||||
from frappe.query_builder.custom import ConstantColumn
|
||||
from frappe.query_builder.functions import Abs, Sum
|
||||
from frappe.utils import (
|
||||
add_days,
|
||||
@ -755,6 +756,7 @@ class AccountsController(TransactionBase):
|
||||
"party": None,
|
||||
"project": self.get("project"),
|
||||
"post_net_value": args.get("post_net_value"),
|
||||
"voucher_detail_no": args.get("voucher_detail_no"),
|
||||
}
|
||||
)
|
||||
|
||||
@ -858,7 +860,6 @@ class AccountsController(TransactionBase):
|
||||
amount = self.get("base_rounded_total") or self.base_grand_total
|
||||
else:
|
||||
amount = self.get("rounded_total") or self.grand_total
|
||||
|
||||
allocated_amount = min(amount - advance_allocated, d.amount)
|
||||
advance_allocated += flt(allocated_amount)
|
||||
|
||||
@ -872,25 +873,31 @@ class AccountsController(TransactionBase):
|
||||
"allocated_amount": allocated_amount,
|
||||
"ref_exchange_rate": flt(d.exchange_rate), # exchange_rate of advance entry
|
||||
}
|
||||
if d.get("paid_from"):
|
||||
advance_row["account"] = d.paid_from
|
||||
if d.get("paid_to"):
|
||||
advance_row["account"] = d.paid_to
|
||||
|
||||
self.append("advances", advance_row)
|
||||
|
||||
def get_advance_entries(self, include_unallocated=True):
|
||||
if self.doctype == "Sales Invoice":
|
||||
party_account = self.debit_to
|
||||
party_type = "Customer"
|
||||
party = self.customer
|
||||
amount_field = "credit_in_account_currency"
|
||||
order_field = "sales_order"
|
||||
order_doctype = "Sales Order"
|
||||
else:
|
||||
party_account = self.credit_to
|
||||
party_type = "Supplier"
|
||||
party = self.supplier
|
||||
amount_field = "debit_in_account_currency"
|
||||
order_field = "purchase_order"
|
||||
order_doctype = "Purchase Order"
|
||||
|
||||
party_account = get_party_account(
|
||||
party_type, party=party, company=self.company, include_advance=True
|
||||
)
|
||||
|
||||
order_list = list(set(d.get(order_field) for d in self.get("items") if d.get(order_field)))
|
||||
|
||||
journal_entries = get_advance_journal_entries(
|
||||
@ -2140,45 +2147,46 @@ def get_advance_journal_entries(
|
||||
order_list,
|
||||
include_unallocated=True,
|
||||
):
|
||||
dr_or_cr = (
|
||||
"credit_in_account_currency" if party_type == "Customer" else "debit_in_account_currency"
|
||||
journal_entry = frappe.qb.DocType("Journal Entry")
|
||||
journal_acc = frappe.qb.DocType("Journal Entry Account")
|
||||
q = (
|
||||
frappe.qb.from_(journal_entry)
|
||||
.inner_join(journal_acc)
|
||||
.on(journal_entry.name == journal_acc.parent)
|
||||
.select(
|
||||
ConstantColumn("Journal Entry").as_("reference_type"),
|
||||
(journal_entry.name).as_("reference_name"),
|
||||
(journal_entry.remark).as_("remarks"),
|
||||
(journal_acc[amount_field]).as_("amount"),
|
||||
(journal_acc.name).as_("reference_row"),
|
||||
(journal_acc.reference_name).as_("against_order"),
|
||||
(journal_acc.exchange_rate),
|
||||
)
|
||||
.where(
|
||||
journal_acc.account.isin(party_account)
|
||||
& (journal_acc.party_type == party_type)
|
||||
& (journal_acc.party == party)
|
||||
& (journal_acc.is_advance == "Yes")
|
||||
& (journal_entry.docstatus == 1)
|
||||
)
|
||||
)
|
||||
if party_type == "Customer":
|
||||
q = q.where(journal_acc.credit_in_account_currency > 0)
|
||||
|
||||
else:
|
||||
q = q.where(journal_acc.debit_in_account_currency > 0)
|
||||
|
||||
conditions = []
|
||||
if include_unallocated:
|
||||
conditions.append("ifnull(t2.reference_name, '')=''")
|
||||
q = q.where((journal_acc.reference_name.isnull()) | (journal_acc.reference_name == ""))
|
||||
|
||||
if order_list:
|
||||
order_condition = ", ".join(["%s"] * len(order_list))
|
||||
conditions.append(
|
||||
" (t2.reference_type = '{0}' and ifnull(t2.reference_name, '') in ({1}))".format(
|
||||
order_doctype, order_condition
|
||||
)
|
||||
q = q.where(
|
||||
(journal_acc.reference_type == order_doctype) & ((journal_acc.reference_type).isin(order_list))
|
||||
)
|
||||
|
||||
reference_condition = " and (" + " or ".join(conditions) + ")" if conditions else ""
|
||||
|
||||
# nosemgrep
|
||||
journal_entries = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
'Journal Entry' as reference_type, t1.name as reference_name,
|
||||
t1.remark as remarks, t2.{0} as amount, t2.name as reference_row,
|
||||
t2.reference_name as against_order, t2.exchange_rate
|
||||
from
|
||||
`tabJournal Entry` t1, `tabJournal Entry Account` t2
|
||||
where
|
||||
t1.name = t2.parent and t2.account = %s
|
||||
and t2.party_type = %s and t2.party = %s
|
||||
and t2.is_advance = 'Yes' and t1.docstatus = 1
|
||||
and {1} > 0 {2}
|
||||
order by t1.posting_date""".format(
|
||||
amount_field, dr_or_cr, reference_condition
|
||||
),
|
||||
[party_account, party_type, party] + order_list,
|
||||
as_dict=1,
|
||||
)
|
||||
q = q.orderby(journal_entry.posting_date)
|
||||
|
||||
journal_entries = q.run(as_dict=True)
|
||||
return list(journal_entries)
|
||||
|
||||
|
||||
@ -2193,65 +2201,131 @@ def get_advance_payment_entries(
|
||||
limit=None,
|
||||
condition=None,
|
||||
):
|
||||
party_account_field = "paid_from" if party_type == "Customer" else "paid_to"
|
||||
currency_field = (
|
||||
"paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency"
|
||||
)
|
||||
payment_type = "Receive" if party_type == "Customer" else "Pay"
|
||||
exchange_rate_field = (
|
||||
"source_exchange_rate" if payment_type == "Receive" else "target_exchange_rate"
|
||||
)
|
||||
|
||||
payment_entries_against_order, unallocated_payment_entries = [], []
|
||||
limit_cond = "limit %s" % limit if limit else ""
|
||||
payment_entries = []
|
||||
payment_entry = frappe.qb.DocType("Payment Entry")
|
||||
|
||||
if order_list or against_all_orders:
|
||||
q = get_common_query(
|
||||
party_type,
|
||||
party,
|
||||
party_account,
|
||||
limit,
|
||||
condition,
|
||||
)
|
||||
payment_ref = frappe.qb.DocType("Payment Entry Reference")
|
||||
|
||||
q = q.inner_join(payment_ref).on(payment_entry.name == payment_ref.parent)
|
||||
q = q.select(
|
||||
(payment_ref.allocated_amount).as_("amount"),
|
||||
(payment_ref.name).as_("reference_row"),
|
||||
(payment_ref.reference_name).as_("against_order"),
|
||||
)
|
||||
|
||||
q = q.where(payment_ref.reference_doctype == order_doctype)
|
||||
if order_list:
|
||||
reference_condition = " and t2.reference_name in ({0})".format(
|
||||
", ".join(["%s"] * len(order_list))
|
||||
q = q.where(payment_ref.reference_name.isin(order_list))
|
||||
|
||||
allocated = list(q.run(as_dict=True))
|
||||
payment_entries += allocated
|
||||
if include_unallocated:
|
||||
q = get_common_query(
|
||||
party_type,
|
||||
party,
|
||||
party_account,
|
||||
limit,
|
||||
condition,
|
||||
)
|
||||
q = q.select((payment_entry.unallocated_amount).as_("amount"))
|
||||
q = q.where(payment_entry.unallocated_amount > 0)
|
||||
|
||||
unallocated = list(q.run(as_dict=True))
|
||||
payment_entries += unallocated
|
||||
return payment_entries
|
||||
|
||||
|
||||
def get_common_query(
|
||||
party_type,
|
||||
party,
|
||||
party_account,
|
||||
limit,
|
||||
condition,
|
||||
):
|
||||
payment_type = "Receive" if party_type == "Customer" else "Pay"
|
||||
payment_entry = frappe.qb.DocType("Payment Entry")
|
||||
|
||||
q = (
|
||||
frappe.qb.from_(payment_entry)
|
||||
.select(
|
||||
ConstantColumn("Payment Entry").as_("reference_type"),
|
||||
(payment_entry.name).as_("reference_name"),
|
||||
payment_entry.posting_date,
|
||||
(payment_entry.remarks).as_("remarks"),
|
||||
)
|
||||
.where(payment_entry.payment_type == payment_type)
|
||||
.where(payment_entry.party_type == party_type)
|
||||
.where(payment_entry.party == party)
|
||||
.where(payment_entry.docstatus == 1)
|
||||
)
|
||||
|
||||
if party_type == "Customer":
|
||||
q = q.select((payment_entry.paid_from_account_currency).as_("currency"))
|
||||
q = q.select(payment_entry.paid_from)
|
||||
q = q.where(payment_entry.paid_from.isin(party_account))
|
||||
else:
|
||||
q = q.select((payment_entry.paid_to_account_currency).as_("currency"))
|
||||
q = q.select(payment_entry.paid_to)
|
||||
q = q.where(payment_entry.paid_to.isin(party_account))
|
||||
|
||||
if payment_type == "Receive":
|
||||
q = q.select((payment_entry.source_exchange_rate).as_("exchange_rate"))
|
||||
else:
|
||||
q = q.select((payment_entry.target_exchange_rate).as_("exchange_rate"))
|
||||
|
||||
if condition:
|
||||
q = q.where(payment_entry.company == condition["company"])
|
||||
q = (
|
||||
q.where(payment_entry.posting_date >= condition["from_payment_date"])
|
||||
if condition.get("from_payment_date")
|
||||
else q
|
||||
)
|
||||
q = (
|
||||
q.where(payment_entry.posting_date <= condition["to_payment_date"])
|
||||
if condition.get("to_payment_date")
|
||||
else q
|
||||
)
|
||||
if condition.get("get_payments") == True:
|
||||
q = (
|
||||
q.where(payment_entry.cost_center == condition["cost_center"])
|
||||
if condition.get("cost_center")
|
||||
else q
|
||||
)
|
||||
q = (
|
||||
q.where(payment_entry.unallocated_amount >= condition["minimum_payment_amount"])
|
||||
if condition.get("minimum_payment_amount")
|
||||
else q
|
||||
)
|
||||
q = (
|
||||
q.where(payment_entry.unallocated_amount <= condition["maximum_payment_amount"])
|
||||
if condition.get("maximum_payment_amount")
|
||||
else q
|
||||
)
|
||||
else:
|
||||
reference_condition = ""
|
||||
order_list = []
|
||||
q = (
|
||||
q.where(payment_entry.total_debit >= condition["minimum_payment_amount"])
|
||||
if condition.get("minimum_payment_amount")
|
||||
else q
|
||||
)
|
||||
q = (
|
||||
q.where(payment_entry.total_debit <= condition["maximum_payment_amount"])
|
||||
if condition.get("maximum_payment_amount")
|
||||
else q
|
||||
)
|
||||
|
||||
payment_entries_against_order = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
'Payment Entry' as reference_type, t1.name as reference_name,
|
||||
t1.remarks, t2.allocated_amount as amount, t2.name as reference_row,
|
||||
t2.reference_name as against_order, t1.posting_date,
|
||||
t1.{0} as currency, t1.{4} as exchange_rate
|
||||
from `tabPayment Entry` t1, `tabPayment Entry Reference` t2
|
||||
where
|
||||
t1.name = t2.parent and t1.{1} = %s and t1.payment_type = %s
|
||||
and t1.party_type = %s and t1.party = %s and t1.docstatus = 1
|
||||
and t2.reference_doctype = %s {2}
|
||||
order by t1.posting_date {3}
|
||||
""".format(
|
||||
currency_field, party_account_field, reference_condition, limit_cond, exchange_rate_field
|
||||
),
|
||||
[party_account, payment_type, party_type, party, order_doctype] + order_list,
|
||||
as_dict=1,
|
||||
)
|
||||
q = q.orderby(payment_entry.posting_date)
|
||||
q = q.limit(limit) if limit else q
|
||||
|
||||
if include_unallocated:
|
||||
unallocated_payment_entries = frappe.db.sql(
|
||||
"""
|
||||
select 'Payment Entry' as reference_type, name as reference_name, posting_date,
|
||||
remarks, unallocated_amount as amount, {2} as exchange_rate, {3} as currency
|
||||
from `tabPayment Entry`
|
||||
where
|
||||
{0} = %s and party_type = %s and party = %s and payment_type = %s
|
||||
and docstatus = 1 and unallocated_amount > 0 {condition}
|
||||
order by posting_date {1}
|
||||
""".format(
|
||||
party_account_field, limit_cond, exchange_rate_field, currency_field, condition=condition or ""
|
||||
),
|
||||
(party_account, party_type, party, payment_type),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
return list(payment_entries_against_order) + list(unallocated_payment_entries)
|
||||
return q
|
||||
|
||||
|
||||
def update_invoice_status():
|
||||
|
@ -20,8 +20,8 @@ frappe.ui.form.on("Customer", {
|
||||
frm.set_query('customer_group', {'is_group': 0});
|
||||
frm.set_query('default_price_list', { 'selling': 1});
|
||||
frm.set_query('account', 'accounts', function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
var filters = {
|
||||
let d = locals[cdt][cdn];
|
||||
let filters = {
|
||||
'account_type': 'Receivable',
|
||||
'company': d.company,
|
||||
"is_group": 0
|
||||
@ -35,6 +35,19 @@ frappe.ui.form.on("Customer", {
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query('advance_account', 'accounts', function (doc, cdt, cdn) {
|
||||
let d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
"account_type": 'Receivable',
|
||||
"root_type": "Liability",
|
||||
"company": d.company,
|
||||
"is_group": 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (frm.doc.__islocal == 1) {
|
||||
frm.set_value("represents_company", "");
|
||||
}
|
||||
|
@ -336,15 +336,15 @@
|
||||
{
|
||||
"fieldname": "default_receivable_accounts",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Default Receivable Accounts"
|
||||
"label": "Default Accounts"
|
||||
},
|
||||
{
|
||||
"description": "Mention if a non-standard receivable account",
|
||||
"fieldname": "accounts",
|
||||
"fieldtype": "Table",
|
||||
"label": "Receivable Accounts",
|
||||
"options": "Party Account"
|
||||
},
|
||||
"description": "Mention if non-standard Receivable account",
|
||||
"fieldname": "accounts",
|
||||
"fieldtype": "Table",
|
||||
"label": "Accounts",
|
||||
"options": "Party Account"
|
||||
},
|
||||
{
|
||||
"fieldname": "credit_limit_section",
|
||||
"fieldtype": "Section Break",
|
||||
|
@ -226,7 +226,9 @@ erpnext.company.setup_queries = function(frm) {
|
||||
["capital_work_in_progress_account", {"account_type": "Capital Work in Progress"}],
|
||||
["asset_received_but_not_billed", {"account_type": "Asset Received But Not Billed"}],
|
||||
["unrealized_profit_loss_account", {"root_type": ["in", ["Liability", "Asset"]]}],
|
||||
["default_provisional_account", {"root_type": ["in", ["Liability", "Asset"]]}]
|
||||
["default_provisional_account", {"root_type": ["in", ["Liability", "Asset"]]}],
|
||||
["default_advance_received_account", {"root_type": "Liability", "account_type": "Receivable"}],
|
||||
["default_advance_paid_account", {"root_type": "Asset", "account_type": "Payable"}],
|
||||
], function(i, v) {
|
||||
erpnext.company.set_custom_query(frm, v);
|
||||
});
|
||||
|
@ -70,6 +70,11 @@
|
||||
"payment_terms",
|
||||
"cost_center",
|
||||
"default_finance_book",
|
||||
"advance_payments_section",
|
||||
"book_advance_payments_in_separate_party_account",
|
||||
"column_break_fwcf",
|
||||
"default_advance_received_account",
|
||||
"default_advance_paid_account",
|
||||
"auto_accounting_for_stock_settings",
|
||||
"enable_perpetual_inventory",
|
||||
"enable_provisional_accounting_for_non_stock_items",
|
||||
@ -694,6 +699,38 @@
|
||||
"label": "Default Provisional Account",
|
||||
"no_copy": 1,
|
||||
"options": "Account"
|
||||
},
|
||||
{
|
||||
"fieldname": "advance_payments_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Advance Payments"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.book_advance_payments_in_separate_party_account",
|
||||
"fieldname": "default_advance_received_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Advance Received Account",
|
||||
"mandatory_depends_on": "book_advance_payments_as_liability",
|
||||
"options": "Account"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.book_advance_payments_in_separate_party_account",
|
||||
"fieldname": "default_advance_paid_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Advance Paid Account",
|
||||
"mandatory_depends_on": "book_advance_payments_as_liability",
|
||||
"options": "Account"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_fwcf",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Enabling this option will allow you to record - <br><br> 1. Advances Received in a <b>Liability Account</b> instead of the <b>Asset Account</b><br><br>2. Advances Paid in an <b>Asset Account</b> instead of the <b> Liability Account</b>",
|
||||
"fieldname": "book_advance_payments_in_separate_party_account",
|
||||
"fieldtype": "Check",
|
||||
"label": "Book Advance Payments in Separate Party Account"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-building",
|
||||
@ -701,7 +738,7 @@
|
||||
"image_field": "company_logo",
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2022-08-16 16:09:02.327724",
|
||||
"modified": "2023-06-23 18:22:27.219706",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Company",
|
||||
|
@ -16,23 +16,36 @@ cur_frm.cscript.set_root_readonly = function(doc) {
|
||||
}
|
||||
}
|
||||
|
||||
//get query select Customer Group
|
||||
cur_frm.fields_dict['parent_customer_group'].get_query = function(doc,cdt,cdn) {
|
||||
return {
|
||||
filters: {
|
||||
'is_group': 1,
|
||||
'name': ['!=', cur_frm.doc.customer_group_name]
|
||||
}
|
||||
}
|
||||
}
|
||||
frappe.ui.form.on("Customer Group", {
|
||||
setup: function(frm){
|
||||
frm.set_query('parent_customer_group', function (doc) {
|
||||
return {
|
||||
filters: {
|
||||
'is_group': 1,
|
||||
'name': ['!=', cur_frm.doc.customer_group_name]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cur_frm.fields_dict['accounts'].grid.get_field('account').get_query = function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
'account_type': 'Receivable',
|
||||
'company': d.company,
|
||||
"is_group": 0
|
||||
}
|
||||
frm.set_query('account', 'accounts', function (doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
"account_type": 'Receivable',
|
||||
"company": locals[cdt][cdn].company,
|
||||
"is_group": 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query('advance_account', 'accounts', function (doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
"root_type": 'Liability',
|
||||
"account_type": "Receivable",
|
||||
"company": locals[cdt][cdn].company,
|
||||
"is_group": 0
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -113,7 +113,7 @@
|
||||
{
|
||||
"fieldname": "default_receivable_account",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Default Receivable Account"
|
||||
"label": "Default Accounts"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
@ -139,7 +139,7 @@
|
||||
"idx": 1,
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2022-12-24 11:15:17.142746",
|
||||
"modified": "2023-06-02 13:40:34.435822",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Customer Group",
|
||||
@ -171,7 +171,6 @@
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales Master Manager",
|
||||
"set_user_permissions": 1,
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
|
@ -16,23 +16,36 @@ cur_frm.cscript.set_root_readonly = function(doc) {
|
||||
}
|
||||
};
|
||||
|
||||
// get query select Customer Group
|
||||
cur_frm.fields_dict['parent_supplier_group'].get_query = function() {
|
||||
return {
|
||||
filters: {
|
||||
'is_group': 1,
|
||||
'name': ['!=', cur_frm.doc.supplier_group_name]
|
||||
}
|
||||
};
|
||||
};
|
||||
frappe.ui.form.on("Supplier Group", {
|
||||
setup: function(frm){
|
||||
frm.set_query('parent_supplier_group', function (doc) {
|
||||
return {
|
||||
filters: {
|
||||
'is_group': 1,
|
||||
'name': ['!=', cur_frm.doc.supplier_group_name]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cur_frm.fields_dict['accounts'].grid.get_field('account').get_query = function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
'account_type': 'Payable',
|
||||
'company': d.company,
|
||||
"is_group": 0
|
||||
}
|
||||
};
|
||||
};
|
||||
frm.set_query('account', 'accounts', function (doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
'account_type': 'Payable',
|
||||
'company': locals[cdt][cdn].company,
|
||||
"is_group": 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query('advance_account', 'accounts', function (doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
"root_type": 'Asset',
|
||||
"account_type": "Payable",
|
||||
"company": locals[cdt][cdn].company,
|
||||
"is_group": 0
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user