Merge branch 'develop' into dev_fix_payment_terms_status_for_sales_order_report
This commit is contained in:
commit
735576ab27
12
.github/workflows/linters.yml
vendored
12
.github/workflows/linters.yml
vendored
@ -20,6 +20,18 @@ jobs:
|
|||||||
- name: Install and Run Pre-commit
|
- name: Install and Run Pre-commit
|
||||||
uses: pre-commit/action@v3.0.0
|
uses: pre-commit/action@v3.0.0
|
||||||
|
|
||||||
|
semgrep:
|
||||||
|
name: semgrep
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Python 3.10
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
cache: pip
|
||||||
|
|
||||||
- name: Download Semgrep rules
|
- name: Download Semgrep rules
|
||||||
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
|
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 20
|
||||||
- name: Setup dependencies
|
- name: Setup dependencies
|
||||||
run: |
|
run: |
|
||||||
npm install @semantic-release/git @semantic-release/exec --no-save
|
npm install @semantic-release/git @semantic-release/exec --no-save
|
||||||
|
|||||||
@ -358,11 +358,9 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
|
|
||||||
account_currency = get_account_currency(item.expense_account or item.income_account)
|
account_currency = get_account_currency(item.expense_account or item.income_account)
|
||||||
if doc.doctype == "Sales Invoice":
|
if doc.doctype == "Sales Invoice":
|
||||||
against_type = "Customer"
|
|
||||||
against, project = doc.customer, doc.project
|
against, project = doc.customer, doc.project
|
||||||
credit_account, debit_account = item.income_account, item.deferred_revenue_account
|
credit_account, debit_account = item.income_account, item.deferred_revenue_account
|
||||||
else:
|
else:
|
||||||
against_type = "Supplier"
|
|
||||||
against, project = doc.supplier, item.project
|
against, project = doc.supplier, item.project
|
||||||
credit_account, debit_account = item.deferred_expense_account, item.expense_account
|
credit_account, debit_account = item.deferred_expense_account, item.expense_account
|
||||||
|
|
||||||
@ -415,7 +413,6 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
doc,
|
doc,
|
||||||
credit_account,
|
credit_account,
|
||||||
debit_account,
|
debit_account,
|
||||||
against_type,
|
|
||||||
against,
|
against,
|
||||||
amount,
|
amount,
|
||||||
base_amount,
|
base_amount,
|
||||||
@ -497,7 +494,6 @@ def make_gl_entries(
|
|||||||
doc,
|
doc,
|
||||||
credit_account,
|
credit_account,
|
||||||
debit_account,
|
debit_account,
|
||||||
against_type,
|
|
||||||
against,
|
against,
|
||||||
amount,
|
amount,
|
||||||
base_amount,
|
base_amount,
|
||||||
@ -519,9 +515,7 @@ def make_gl_entries(
|
|||||||
doc.get_gl_dict(
|
doc.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": credit_account,
|
"account": credit_account,
|
||||||
"against_type": against_type,
|
|
||||||
"against": against,
|
"against": against,
|
||||||
"against_link": against,
|
|
||||||
"credit": base_amount,
|
"credit": base_amount,
|
||||||
"credit_in_account_currency": amount,
|
"credit_in_account_currency": amount,
|
||||||
"cost_center": cost_center,
|
"cost_center": cost_center,
|
||||||
@ -540,9 +534,7 @@ def make_gl_entries(
|
|||||||
doc.get_gl_dict(
|
doc.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": debit_account,
|
"account": debit_account,
|
||||||
"against_type": against_type,
|
|
||||||
"against": against,
|
"against": against,
|
||||||
"against_link": against,
|
|
||||||
"debit": base_amount,
|
"debit": base_amount,
|
||||||
"debit_in_account_currency": amount,
|
"debit_in_account_currency": amount,
|
||||||
"cost_center": cost_center,
|
"cost_center": cost_center,
|
||||||
|
|||||||
@ -36,16 +36,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Fixed Assets": {
|
"Fixed Assets": {
|
||||||
"Capital Equipments": {
|
"Capital Equipment": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Electronic Equipments": {
|
"Electronic Equipment": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Furnitures and Fixtures": {
|
"Furniture and Fixtures": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Office Equipments": {
|
"Office Equipment": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Plants and Machineries": {
|
"Plants and Machineries": {
|
||||||
|
|||||||
@ -23,13 +23,13 @@ def get():
|
|||||||
_("Tax Assets"): {"is_group": 1},
|
_("Tax Assets"): {"is_group": 1},
|
||||||
},
|
},
|
||||||
_("Fixed Assets"): {
|
_("Fixed Assets"): {
|
||||||
_("Capital Equipments"): {"account_type": "Fixed Asset"},
|
_("Capital Equipment"): {"account_type": "Fixed Asset"},
|
||||||
_("Electronic Equipments"): {"account_type": "Fixed Asset"},
|
_("Electronic Equipment"): {"account_type": "Fixed Asset"},
|
||||||
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset"},
|
_("Furniture and Fixtures"): {"account_type": "Fixed Asset"},
|
||||||
_("Office Equipments"): {"account_type": "Fixed Asset"},
|
_("Office Equipment"): {"account_type": "Fixed Asset"},
|
||||||
_("Plants and Machineries"): {"account_type": "Fixed Asset"},
|
_("Plants and Machineries"): {"account_type": "Fixed Asset"},
|
||||||
_("Buildings"): {"account_type": "Fixed Asset"},
|
_("Buildings"): {"account_type": "Fixed Asset"},
|
||||||
_("Softwares"): {"account_type": "Fixed Asset"},
|
_("Software"): {"account_type": "Fixed Asset"},
|
||||||
_("Accumulated Depreciation"): {"account_type": "Accumulated Depreciation"},
|
_("Accumulated Depreciation"): {"account_type": "Accumulated Depreciation"},
|
||||||
_("CWIP Account"): {
|
_("CWIP Account"): {
|
||||||
"account_type": "Capital Work in Progress",
|
"account_type": "Capital Work in Progress",
|
||||||
|
|||||||
@ -36,13 +36,13 @@ def get():
|
|||||||
"account_number": "1100-1600",
|
"account_number": "1100-1600",
|
||||||
},
|
},
|
||||||
_("Fixed Assets"): {
|
_("Fixed Assets"): {
|
||||||
_("Capital Equipments"): {"account_type": "Fixed Asset", "account_number": "1710"},
|
_("Capital Equipment"): {"account_type": "Fixed Asset", "account_number": "1710"},
|
||||||
_("Electronic Equipments"): {"account_type": "Fixed Asset", "account_number": "1720"},
|
_("Electronic Equipment"): {"account_type": "Fixed Asset", "account_number": "1720"},
|
||||||
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
|
_("Furniture and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
|
||||||
_("Office Equipments"): {"account_type": "Fixed Asset", "account_number": "1740"},
|
_("Office Equipment"): {"account_type": "Fixed Asset", "account_number": "1740"},
|
||||||
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
|
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
|
||||||
_("Buildings"): {"account_type": "Fixed Asset", "account_number": "1760"},
|
_("Buildings"): {"account_type": "Fixed Asset", "account_number": "1760"},
|
||||||
_("Softwares"): {"account_type": "Fixed Asset", "account_number": "1770"},
|
_("Software"): {"account_type": "Fixed Asset", "account_number": "1770"},
|
||||||
_("Accumulated Depreciation"): {
|
_("Accumulated Depreciation"): {
|
||||||
"account_type": "Accumulated Depreciation",
|
"account_type": "Accumulated Depreciation",
|
||||||
"account_number": "1780",
|
"account_number": "1780",
|
||||||
|
|||||||
@ -119,7 +119,7 @@ class TestAccount(unittest.TestCase):
|
|||||||
InvalidAccountMergeError,
|
InvalidAccountMergeError,
|
||||||
merge_account,
|
merge_account,
|
||||||
"Capital Stock - _TC",
|
"Capital Stock - _TC",
|
||||||
"Softwares - _TC",
|
"Software - _TC",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Raise error as currency doesn't match
|
# Raise error as currency doesn't match
|
||||||
|
|||||||
@ -55,7 +55,7 @@ class BankAccount(Document):
|
|||||||
|
|
||||||
def validate_company(self):
|
def validate_company(self):
|
||||||
if self.is_company_account and not self.company:
|
if self.is_company_account and not self.company:
|
||||||
frappe.throw(_("Company is manadatory for company account"))
|
frappe.throw(_("Company is mandatory for company account"))
|
||||||
|
|
||||||
def validate_iban(self):
|
def validate_iban(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -48,11 +48,11 @@ class BankGuarantee(Document):
|
|||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
if not self.bank_guarantee_number:
|
if not self.bank_guarantee_number:
|
||||||
frappe.throw(_("Enter the Bank Guarantee Number before submittting."))
|
frappe.throw(_("Enter the Bank Guarantee Number before submitting."))
|
||||||
if not self.name_of_beneficiary:
|
if not self.name_of_beneficiary:
|
||||||
frappe.throw(_("Enter the name of the Beneficiary before submittting."))
|
frappe.throw(_("Enter the name of the Beneficiary before submitting."))
|
||||||
if not self.bank:
|
if not self.bank:
|
||||||
frappe.throw(_("Enter the name of the bank or lending institution before submittting."))
|
frappe.throw(_("Enter the name of the bank or lending institution before submitting."))
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@ -76,6 +76,7 @@ class TestBankReconciliationTool(AccountsTestMixin, FrappeTestCase):
|
|||||||
"deposit": 100,
|
"deposit": 100,
|
||||||
"bank_account": self.bank_account,
|
"bank_account": self.bank_account,
|
||||||
"reference_number": "123",
|
"reference_number": "123",
|
||||||
|
"currency": "INR",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.save()
|
.save()
|
||||||
|
|||||||
@ -49,6 +49,24 @@ class BankTransaction(Document):
|
|||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_duplicate_references()
|
self.validate_duplicate_references()
|
||||||
|
self.validate_currency()
|
||||||
|
|
||||||
|
def validate_currency(self):
|
||||||
|
"""
|
||||||
|
Bank Transaction should be on the same currency as the Bank Account.
|
||||||
|
"""
|
||||||
|
if self.currency and self.bank_account:
|
||||||
|
account = frappe.get_cached_value("Bank Account", self.bank_account, "account")
|
||||||
|
account_currency = frappe.get_cached_value("Account", account, "account_currency")
|
||||||
|
|
||||||
|
if self.currency != account_currency:
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Transaction currency: {0} cannot be different from Bank Account({1}) currency: {2}"
|
||||||
|
).format(
|
||||||
|
frappe.bold(self.currency), frappe.bold(self.bank_account), frappe.bold(account_currency)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def set_status(self):
|
def set_status(self):
|
||||||
if self.docstatus == 2:
|
if self.docstatus == 2:
|
||||||
|
|||||||
@ -80,7 +80,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "valid_upto",
|
"fieldname": "valid_upto",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Valid Upto"
|
"label": "Valid Up To"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval: doc.coupon_type == \"Promotional\"",
|
"depends_on": "eval: doc.coupon_type == \"Promotional\"",
|
||||||
@ -115,7 +115,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2019-10-19 14:48:14.602481",
|
"modified": "2024-01-24 02:20:26.145996",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Coupon Code",
|
"name": "Coupon Code",
|
||||||
|
|||||||
@ -82,11 +82,11 @@
|
|||||||
"icon": "fa fa-calendar",
|
"icon": "fa fa-calendar",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-11-05 12:16:53.081573",
|
"modified": "2024-01-17 13:06:01.608953",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Fiscal Year",
|
"name": "Fiscal Year",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"create": 1,
|
"create": 1,
|
||||||
@ -118,6 +118,14 @@
|
|||||||
{
|
{
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"role": "Employee"
|
"role": "Employee"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"read": 1,
|
||||||
|
"role": "Accounts Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"read": 1,
|
||||||
|
"role": "Stock Manager"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
|
|||||||
@ -39,7 +39,7 @@ def test_record_generator():
|
|||||||
]
|
]
|
||||||
|
|
||||||
start = 2012
|
start = 2012
|
||||||
end = now_datetime().year + 5
|
end = now_datetime().year + 25
|
||||||
for year in range(start, end):
|
for year in range(start, end):
|
||||||
test_records.append(
|
test_records.append(
|
||||||
{
|
{
|
||||||
|
|||||||
@ -17,9 +17,7 @@
|
|||||||
"account_currency",
|
"account_currency",
|
||||||
"debit_in_account_currency",
|
"debit_in_account_currency",
|
||||||
"credit_in_account_currency",
|
"credit_in_account_currency",
|
||||||
"against_type",
|
|
||||||
"against",
|
"against",
|
||||||
"against_link",
|
|
||||||
"against_voucher_type",
|
"against_voucher_type",
|
||||||
"against_voucher",
|
"against_voucher",
|
||||||
"voucher_type",
|
"voucher_type",
|
||||||
@ -131,13 +129,6 @@
|
|||||||
"label": "Credit Amount in Account Currency",
|
"label": "Credit Amount in Account Currency",
|
||||||
"options": "account_currency"
|
"options": "account_currency"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "against_type",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"in_filter": 1,
|
|
||||||
"label": "Against Type",
|
|
||||||
"options": "DocType"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "against",
|
"fieldname": "against",
|
||||||
"fieldtype": "Text",
|
"fieldtype": "Text",
|
||||||
@ -146,13 +137,6 @@
|
|||||||
"oldfieldname": "against",
|
"oldfieldname": "against",
|
||||||
"oldfieldtype": "Text"
|
"oldfieldtype": "Text"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "against_link",
|
|
||||||
"fieldtype": "Dynamic Link",
|
|
||||||
"in_filter": 1,
|
|
||||||
"label": "Against",
|
|
||||||
"options": "against_type"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "against_voucher_type",
|
"fieldname": "against_voucher_type",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@ -306,7 +290,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-12-18 15:38:14.006208",
|
"modified": "2023-09-26 12:03:23.031733",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "GL Entry",
|
"name": "GL Entry",
|
||||||
|
|||||||
@ -154,7 +154,7 @@ frappe.ui.form.on('Invoice Discounting', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
primary_action_label: __('Get Invocies')
|
primary_action_label: __('Get Invoices')
|
||||||
});
|
});
|
||||||
d.show();
|
d.show();
|
||||||
},
|
},
|
||||||
|
|||||||
@ -153,9 +153,7 @@ class InvoiceDiscounting(AccountsController):
|
|||||||
"account": inv.debit_to,
|
"account": inv.debit_to,
|
||||||
"party_type": "Customer",
|
"party_type": "Customer",
|
||||||
"party": d.customer,
|
"party": d.customer,
|
||||||
"against_type": "Account",
|
|
||||||
"against": self.accounts_receivable_credit,
|
"against": self.accounts_receivable_credit,
|
||||||
"against_link": self.accounts_receivable_credit,
|
|
||||||
"credit": outstanding_in_company_currency,
|
"credit": outstanding_in_company_currency,
|
||||||
"credit_in_account_currency": outstanding_in_company_currency
|
"credit_in_account_currency": outstanding_in_company_currency
|
||||||
if inv.party_account_currency == company_currency
|
if inv.party_account_currency == company_currency
|
||||||
@ -175,9 +173,7 @@ class InvoiceDiscounting(AccountsController):
|
|||||||
"account": self.accounts_receivable_credit,
|
"account": self.accounts_receivable_credit,
|
||||||
"party_type": "Customer",
|
"party_type": "Customer",
|
||||||
"party": d.customer,
|
"party": d.customer,
|
||||||
"against_type": "Account",
|
|
||||||
"against": inv.debit_to,
|
"against": inv.debit_to,
|
||||||
"against_link": inv.debit_to,
|
|
||||||
"debit": outstanding_in_company_currency,
|
"debit": outstanding_in_company_currency,
|
||||||
"debit_in_account_currency": outstanding_in_company_currency
|
"debit_in_account_currency": outstanding_in_company_currency
|
||||||
if ar_credit_account_currency == company_currency
|
if ar_credit_account_currency == company_currency
|
||||||
|
|||||||
@ -220,16 +220,6 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
|||||||
return erpnext.journal_entry.account_query(me.frm);
|
return erpnext.journal_entry.account_query(me.frm);
|
||||||
});
|
});
|
||||||
|
|
||||||
me.frm.set_query("against_account_link", "accounts", function(doc, cdt, cdn) {
|
|
||||||
return erpnext.journal_entry.against_account_query(me.frm);
|
|
||||||
});
|
|
||||||
|
|
||||||
me.frm.set_query("against_type", "accounts", function(){
|
|
||||||
return {
|
|
||||||
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_type",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) {
|
me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) {
|
||||||
const row = locals[cdt][cdn];
|
const row = locals[cdt][cdn];
|
||||||
|
|
||||||
@ -601,21 +591,6 @@ $.extend(erpnext.journal_entry, {
|
|||||||
return { filters: filters };
|
return { filters: filters };
|
||||||
},
|
},
|
||||||
|
|
||||||
against_account_query: function(frm) {
|
|
||||||
if (frm.doc.against_type != "Account"){
|
|
||||||
return { filters: {} };
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let filters = { company: frm.doc.company, is_group: 0 };
|
|
||||||
if(!frm.doc.multi_currency) {
|
|
||||||
$.extend(filters, {
|
|
||||||
account_currency: ['in', [frappe.get_doc(":Company", frm.doc.company).default_currency, null]]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return { filters: filters };
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reverse_journal_entry: function() {
|
reverse_journal_entry: function() {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry",
|
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry",
|
||||||
|
|||||||
@ -186,9 +186,12 @@ class JournalEntry(AccountsController):
|
|||||||
|
|
||||||
def update_advance_paid(self):
|
def update_advance_paid(self):
|
||||||
advance_paid = frappe._dict()
|
advance_paid = frappe._dict()
|
||||||
|
advance_payment_doctypes = frappe.get_hooks(
|
||||||
|
"advance_payment_customer_doctypes"
|
||||||
|
) + frappe.get_hooks("advance_payment_supplier_doctypes")
|
||||||
for d in self.get("accounts"):
|
for d in self.get("accounts"):
|
||||||
if d.is_advance:
|
if d.is_advance:
|
||||||
if d.reference_type in frappe.get_hooks("advance_payment_doctypes"):
|
if d.reference_type in advance_payment_doctypes:
|
||||||
advance_paid.setdefault(d.reference_type, []).append(d.reference_name)
|
advance_paid.setdefault(d.reference_type, []).append(d.reference_name)
|
||||||
|
|
||||||
for voucher_type, order_list in advance_paid.items():
|
for voucher_type, order_list in advance_paid.items():
|
||||||
@ -304,7 +307,6 @@ class JournalEntry(AccountsController):
|
|||||||
"account": tax_withholding_details.get("account_head"),
|
"account": tax_withholding_details.get("account_head"),
|
||||||
rev_debit_or_credit: tax_withholding_details.get("tax_amount"),
|
rev_debit_or_credit: tax_withholding_details.get("tax_amount"),
|
||||||
"against_account": parties[0],
|
"against_account": parties[0],
|
||||||
"against_account_link": parties[0],
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -751,90 +753,27 @@ class JournalEntry(AccountsController):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def set_against_account(self):
|
def set_against_account(self):
|
||||||
|
accounts_debited, accounts_credited = [], []
|
||||||
if self.voucher_type in ("Deferred Revenue", "Deferred Expense"):
|
if self.voucher_type in ("Deferred Revenue", "Deferred Expense"):
|
||||||
for d in self.get("accounts"):
|
for d in self.get("accounts"):
|
||||||
if d.reference_type == "Sales Invoice":
|
if d.reference_type == "Sales Invoice":
|
||||||
against_type = "Customer"
|
field = "customer"
|
||||||
else:
|
else:
|
||||||
against_type = "Supplier"
|
field = "supplier"
|
||||||
|
|
||||||
against_account = frappe.db.get_value(d.reference_type, d.reference_name, against_type.lower())
|
d.against_account = frappe.db.get_value(d.reference_type, d.reference_name, field)
|
||||||
d.against_type = against_type
|
|
||||||
d.against_account_link = against_account
|
|
||||||
else:
|
else:
|
||||||
self.get_debited_credited_accounts()
|
for d in self.get("accounts"):
|
||||||
if len(self.accounts_credited) > 1 and len(self.accounts_debited) > 1:
|
if flt(d.debit) > 0:
|
||||||
self.auto_set_against_accounts()
|
accounts_debited.append(d.party or d.account)
|
||||||
return
|
if flt(d.credit) > 0:
|
||||||
self.get_against_accounts()
|
accounts_credited.append(d.party or d.account)
|
||||||
|
|
||||||
def auto_set_against_accounts(self):
|
for d in self.get("accounts"):
|
||||||
for i in range(0, len(self.accounts), 2):
|
if flt(d.debit) > 0:
|
||||||
acc = self.accounts[i]
|
d.against_account = ", ".join(list(set(accounts_credited)))
|
||||||
against_acc = self.accounts[i + 1]
|
if flt(d.credit) > 0:
|
||||||
if acc.debit_in_account_currency > 0:
|
d.against_account = ", ".join(list(set(accounts_debited)))
|
||||||
current_val = acc.debit_in_account_currency * flt(acc.exchange_rate)
|
|
||||||
against_val = against_acc.credit_in_account_currency * flt(against_acc.exchange_rate)
|
|
||||||
else:
|
|
||||||
current_val = acc.credit_in_account_currency * flt(acc.exchange_rate)
|
|
||||||
against_val = against_acc.debit_in_account_currency * flt(against_acc.exchange_rate)
|
|
||||||
|
|
||||||
if current_val == against_val:
|
|
||||||
acc.against_type = against_acc.party_type or "Account"
|
|
||||||
against_acc.against_type = acc.party_type or "Account"
|
|
||||||
|
|
||||||
acc.against_account_link = against_acc.party or against_acc.account
|
|
||||||
against_acc.against_account_link = acc.party or acc.account
|
|
||||||
else:
|
|
||||||
frappe.msgprint(
|
|
||||||
_(
|
|
||||||
"Unable to automatically determine {0} accounts. Set them up in the {1} table if needed."
|
|
||||||
).format(frappe.bold("against"), frappe.bold("Accounting Entries")),
|
|
||||||
alert=True,
|
|
||||||
)
|
|
||||||
break
|
|
||||||
|
|
||||||
def get_against_accounts(self):
|
|
||||||
self.against_accounts = []
|
|
||||||
self.split_account = {}
|
|
||||||
self.get_debited_credited_accounts()
|
|
||||||
|
|
||||||
if self.separate_against_account_entries:
|
|
||||||
no_of_credited_acc, no_of_debited_acc = len(self.accounts_credited), len(self.accounts_debited)
|
|
||||||
if no_of_credited_acc <= 1 and no_of_debited_acc <= 1:
|
|
||||||
self.set_against_accounts_for_single_dr_cr()
|
|
||||||
self.separate_against_account_entries = 0
|
|
||||||
elif no_of_credited_acc == 1:
|
|
||||||
self.against_accounts = self.accounts_debited
|
|
||||||
self.split_account = self.accounts_credited[0]
|
|
||||||
elif no_of_debited_acc == 1:
|
|
||||||
self.against_accounts = self.accounts_credited
|
|
||||||
self.split_account = self.accounts_debited[0]
|
|
||||||
|
|
||||||
def get_debited_credited_accounts(self):
|
|
||||||
self.accounts_debited, self.accounts_credited = [], []
|
|
||||||
self.separate_against_account_entries = 1
|
|
||||||
for d in self.get("accounts"):
|
|
||||||
if flt(d.debit) > 0:
|
|
||||||
self.accounts_debited.append(d)
|
|
||||||
elif flt(d.credit) > 0:
|
|
||||||
self.accounts_credited.append(d)
|
|
||||||
|
|
||||||
if d.against_account_link:
|
|
||||||
self.separate_against_account_entries = 0
|
|
||||||
break
|
|
||||||
|
|
||||||
def set_against_accounts_for_single_dr_cr(self):
|
|
||||||
against_account = None
|
|
||||||
for d in self.accounts:
|
|
||||||
if flt(d.debit) > 0:
|
|
||||||
against_account = self.accounts_credited[0]
|
|
||||||
elif flt(d.credit) > 0:
|
|
||||||
against_account = self.accounts_debited[0]
|
|
||||||
if against_account:
|
|
||||||
d.against_type = against_account.party_type or "Account"
|
|
||||||
d.against_account = against_account.party or against_account.account
|
|
||||||
d.against_account_link = against_account.party or against_account.account
|
|
||||||
|
|
||||||
def validate_debit_credit_amount(self):
|
def validate_debit_credit_amount(self):
|
||||||
if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency):
|
if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency):
|
||||||
@ -1031,108 +970,42 @@ class JournalEntry(AccountsController):
|
|||||||
|
|
||||||
def build_gl_map(self):
|
def build_gl_map(self):
|
||||||
gl_map = []
|
gl_map = []
|
||||||
conversion_rate_map = self.get_conversion_rate_map()
|
|
||||||
transaction_currency_map = self.get_transaction_currency_map()
|
|
||||||
company_currency = erpnext.get_company_currency(self.company)
|
|
||||||
|
|
||||||
self.get_against_accounts()
|
|
||||||
for d in self.get("accounts"):
|
for d in self.get("accounts"):
|
||||||
if d.debit or d.credit or (self.voucher_type == "Exchange Gain Or Loss"):
|
if d.debit or d.credit or (self.voucher_type == "Exchange Gain Or Loss"):
|
||||||
r = [d.user_remark, self.remark]
|
r = [d.user_remark, self.remark]
|
||||||
r = [x for x in r if x]
|
r = [x for x in r if x]
|
||||||
remarks = "\n".join(r)
|
remarks = "\n".join(r)
|
||||||
|
|
||||||
gl_dict = self.get_gl_dict(
|
gl_map.append(
|
||||||
{
|
self.get_gl_dict(
|
||||||
"account": d.account,
|
{
|
||||||
"party_type": d.party_type,
|
"account": d.account,
|
||||||
"due_date": self.due_date,
|
"party_type": d.party_type,
|
||||||
"party": d.party,
|
"due_date": self.due_date,
|
||||||
"debit": flt(d.debit, d.precision("debit")),
|
"party": d.party,
|
||||||
"credit": flt(d.credit, d.precision("credit")),
|
"against": d.against_account,
|
||||||
"account_currency": d.account_currency,
|
"debit": flt(d.debit, d.precision("debit")),
|
||||||
"debit_in_account_currency": flt(
|
"credit": flt(d.credit, d.precision("credit")),
|
||||||
d.debit_in_account_currency, d.precision("debit_in_account_currency")
|
"account_currency": d.account_currency,
|
||||||
),
|
"debit_in_account_currency": flt(
|
||||||
"credit_in_account_currency": flt(
|
d.debit_in_account_currency, d.precision("debit_in_account_currency")
|
||||||
d.credit_in_account_currency, d.precision("credit_in_account_currency")
|
),
|
||||||
),
|
"credit_in_account_currency": flt(
|
||||||
"against_voucher_type": d.reference_type,
|
d.credit_in_account_currency, d.precision("credit_in_account_currency")
|
||||||
"against_voucher": d.reference_name,
|
),
|
||||||
"remarks": remarks,
|
"against_voucher_type": d.reference_type,
|
||||||
"voucher_detail_no": d.reference_detail_no,
|
"against_voucher": d.reference_name,
|
||||||
"cost_center": d.cost_center,
|
"remarks": remarks,
|
||||||
"project": d.project,
|
"voucher_detail_no": d.reference_detail_no,
|
||||||
"finance_book": self.finance_book,
|
"cost_center": d.cost_center,
|
||||||
"conversion_rate": conversion_rate_map.get(d.against_account_link, 1)
|
"project": d.project,
|
||||||
if d.account_currency == company_currency
|
"finance_book": self.finance_book,
|
||||||
else 1,
|
},
|
||||||
"currency": transaction_currency_map.get(d.against_account_link, d.account_currency)
|
item=d,
|
||||||
if d.account_currency == company_currency
|
)
|
||||||
else d.account_currency,
|
|
||||||
},
|
|
||||||
item=d,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if not self.separate_against_account_entries:
|
|
||||||
gl_dict.update(
|
|
||||||
{
|
|
||||||
"against_type": d.against_type,
|
|
||||||
"against_link": d.against_account_link,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
gl_map.append(gl_dict)
|
|
||||||
|
|
||||||
elif d in self.against_accounts:
|
|
||||||
gl_dict.update(
|
|
||||||
{
|
|
||||||
"against_type": self.split_account.get("party_type") or "Account",
|
|
||||||
"against": self.split_account.get("party") or self.split_account.get("account"),
|
|
||||||
"against_link": self.split_account.get("party") or self.split_account.get("account"),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
gl_map.append(gl_dict)
|
|
||||||
|
|
||||||
else:
|
|
||||||
for against_account in self.against_accounts:
|
|
||||||
against_account = against_account.as_dict()
|
|
||||||
debit = against_account.credit or against_account.credit_in_account_currency
|
|
||||||
credit = against_account.debit or against_account.debit_in_account_currency
|
|
||||||
gl_dict = gl_dict.copy()
|
|
||||||
gl_dict.update(
|
|
||||||
{
|
|
||||||
"against_type": against_account.party_type or "Account",
|
|
||||||
"against": against_account.party or against_account.account,
|
|
||||||
"against_link": against_account.party or against_account.account,
|
|
||||||
"debit": flt(debit, d.precision("debit")),
|
|
||||||
"credit": flt(credit, d.precision("credit")),
|
|
||||||
"account_currency": d.account_currency,
|
|
||||||
"debit_in_account_currency": flt(
|
|
||||||
debit / d.exchange_rate, d.precision("debit_in_account_currency")
|
|
||||||
),
|
|
||||||
"credit_in_account_currency": flt(
|
|
||||||
credit / d.exchange_rate, d.precision("credit_in_account_currency")
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
gl_map.append(gl_dict)
|
|
||||||
|
|
||||||
return gl_map
|
return gl_map
|
||||||
|
|
||||||
def get_transaction_currency_map(self):
|
|
||||||
transaction_currency_map = {}
|
|
||||||
for account in self.get("accounts"):
|
|
||||||
transaction_currency_map.setdefault(account.party or account.account, account.account_currency)
|
|
||||||
|
|
||||||
return transaction_currency_map
|
|
||||||
|
|
||||||
def get_conversion_rate_map(self):
|
|
||||||
conversion_rate_map = {}
|
|
||||||
for account in self.get("accounts"):
|
|
||||||
conversion_rate_map.setdefault(account.party or account.account, account.exchange_rate)
|
|
||||||
|
|
||||||
return conversion_rate_map
|
|
||||||
|
|
||||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||||
from erpnext.accounts.general_ledger import make_gl_entries
|
from erpnext.accounts.general_ledger import make_gl_entries
|
||||||
|
|
||||||
@ -1755,10 +1628,3 @@ def make_reverse_journal_entry(source_name, target_doc=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return doclist
|
return doclist
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_against_type(doctype, txt, searchfield, start, page_len, filters):
|
|
||||||
against_types = frappe.db.get_list("Party Type", pluck="name") + ["Account"]
|
|
||||||
doctype = frappe.qb.DocType("DocType")
|
|
||||||
return frappe.qb.from_(doctype).select(doctype.name).where(doctype.name.isin(against_types)).run()
|
|
||||||
|
|||||||
@ -1,12 +1,18 @@
|
|||||||
frappe.listview_settings['Journal Entry'] = {
|
frappe.listview_settings["Journal Entry"] = {
|
||||||
add_fields: ["voucher_type", "posting_date", "total_debit", "company", "user_remark"],
|
add_fields: [
|
||||||
get_indicator: function(doc) {
|
"voucher_type",
|
||||||
if(doc.docstatus==0) {
|
"posting_date",
|
||||||
return [__("Draft", "red", "docstatus,=,0")]
|
"total_debit",
|
||||||
} else if(doc.docstatus==2) {
|
"company",
|
||||||
return [__("Cancelled", "grey", "docstatus,=,2")]
|
"user_remark",
|
||||||
} else {
|
],
|
||||||
return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type]
|
get_indicator: function (doc) {
|
||||||
|
if (doc.docstatus === 1) {
|
||||||
|
return [
|
||||||
|
__(doc.voucher_type),
|
||||||
|
"blue",
|
||||||
|
`voucher_type,=,${doc.voucher_type}`,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -37,9 +37,7 @@
|
|||||||
"col_break3",
|
"col_break3",
|
||||||
"is_advance",
|
"is_advance",
|
||||||
"user_remark",
|
"user_remark",
|
||||||
"against_type",
|
"against_account"
|
||||||
"against_account",
|
|
||||||
"against_account_link"
|
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -252,21 +250,14 @@
|
|||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "against_account",
|
"fieldname": "against_account",
|
||||||
"fieldtype": "Text",
|
"fieldtype": "Text",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"label": "Against Account",
|
|
||||||
"no_copy": 1,
|
|
||||||
"oldfieldname": "against_account",
|
|
||||||
"oldfieldtype": "Text",
|
|
||||||
"print_hide": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "against_account_link",
|
|
||||||
"fieldtype": "Dynamic Link",
|
|
||||||
"label": "Against Account",
|
"label": "Against Account",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "against_type"
|
"oldfieldname": "against_account",
|
||||||
|
"oldfieldtype": "Text",
|
||||||
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
@ -290,18 +281,12 @@
|
|||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"label": "Reference Detail No",
|
"label": "Reference Detail No",
|
||||||
"no_copy": 1
|
"no_copy": 1
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "against_type",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Against Type",
|
|
||||||
"options": "DocType"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-12-02 23:21:22.205409",
|
"modified": "2023-12-03 23:21:22.205409",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Journal Entry Account",
|
"name": "Journal Entry Account",
|
||||||
|
|||||||
@ -270,7 +270,7 @@ def start_import(invoices):
|
|||||||
errors, "<a href='/app/List/Error Log' class='variant-click'>Error Log</a>"
|
errors, "<a href='/app/List/Error Log' class='variant-click'>Error Log</a>"
|
||||||
),
|
),
|
||||||
indicator="red",
|
indicator="red",
|
||||||
title=_("Error Occured"),
|
title=_("Error Occurred"),
|
||||||
)
|
)
|
||||||
return names
|
return names
|
||||||
|
|
||||||
|
|||||||
@ -640,7 +640,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
|
|
||||||
get_outstanding_invoices_or_orders: function(frm, get_outstanding_invoices, get_orders_to_be_billed) {
|
get_outstanding_invoices_or_orders: function(frm, get_outstanding_invoices, get_orders_to_be_billed) {
|
||||||
const today = frappe.datetime.get_today();
|
const today = frappe.datetime.get_today();
|
||||||
const fields = [
|
let fields = [
|
||||||
{fieldtype:"Section Break", label: __("Posting Date")},
|
{fieldtype:"Section Break", label: __("Posting Date")},
|
||||||
{fieldtype:"Date", label: __("From Date"),
|
{fieldtype:"Date", label: __("From Date"),
|
||||||
fieldname:"from_posting_date", default:frappe.datetime.add_days(today, -30)},
|
fieldname:"from_posting_date", default:frappe.datetime.add_days(today, -30)},
|
||||||
@ -655,18 +655,29 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
fieldname:"outstanding_amt_greater_than", default: 0},
|
fieldname:"outstanding_amt_greater_than", default: 0},
|
||||||
{fieldtype:"Column Break"},
|
{fieldtype:"Column Break"},
|
||||||
{fieldtype:"Float", label: __("Less Than Amount"), fieldname:"outstanding_amt_less_than"},
|
{fieldtype:"Float", label: __("Less Than Amount"), fieldname:"outstanding_amt_less_than"},
|
||||||
{fieldtype:"Section Break"},
|
];
|
||||||
{fieldtype:"Link", label:__("Cost Center"), fieldname:"cost_center", options:"Cost Center",
|
|
||||||
"get_query": function() {
|
if (frm.dimension_filters) {
|
||||||
return {
|
let column_break_insertion_point = Math.ceil((frm.dimension_filters.length)/2);
|
||||||
"filters": {"company": frm.doc.company}
|
|
||||||
}
|
fields.push({fieldtype:"Section Break"});
|
||||||
|
frm.dimension_filters.map((elem, idx)=>{
|
||||||
|
fields.push({
|
||||||
|
fieldtype: "Link",
|
||||||
|
label: elem.document_type == "Cost Center" ? "Cost Center" : elem.label,
|
||||||
|
options: elem.document_type,
|
||||||
|
fieldname: elem.fieldname || elem.document_type
|
||||||
|
});
|
||||||
|
if(idx+1 == column_break_insertion_point) {
|
||||||
|
fields.push({fieldtype:"Column Break"});
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
{fieldtype:"Column Break"},
|
}
|
||||||
|
|
||||||
|
fields = fields.concat([
|
||||||
{fieldtype:"Section Break"},
|
{fieldtype:"Section Break"},
|
||||||
{fieldtype:"Check", label: __("Allocate Payment Amount"), fieldname:"allocate_payment_amount", default:1},
|
{fieldtype:"Check", label: __("Allocate Payment Amount"), fieldname:"allocate_payment_amount", default:1},
|
||||||
];
|
]);
|
||||||
|
|
||||||
let btn_text = "";
|
let btn_text = "";
|
||||||
|
|
||||||
@ -933,7 +944,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
if(frm.doc.payment_type == "Receive"
|
if(frm.doc.payment_type == "Receive"
|
||||||
&& frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions
|
&& frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions
|
||||||
&& frm.doc.total_allocated_amount < frm.doc.paid_amount + (total_deductions / frm.doc.source_exchange_rate)) {
|
&& frm.doc.total_allocated_amount < frm.doc.paid_amount + (total_deductions / frm.doc.source_exchange_rate)) {
|
||||||
unallocated_amount = (frm.doc.base_received_amount + total_deductions + flt(frm.doc.base_total_taxes_and_charges)
|
unallocated_amount = (frm.doc.base_received_amount + total_deductions - flt(frm.doc.base_total_taxes_and_charges)
|
||||||
- frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate;
|
- frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate;
|
||||||
} else if (frm.doc.payment_type == "Pay"
|
} else if (frm.doc.payment_type == "Pay"
|
||||||
&& frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions
|
&& frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions
|
||||||
|
|||||||
@ -13,6 +13,7 @@ from pypika import Case
|
|||||||
from pypika.functions import Coalesce, Sum
|
from pypika.functions import Coalesce, Sum
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
|
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_dimensions
|
||||||
from erpnext.accounts.doctype.bank_account.bank_account import (
|
from erpnext.accounts.doctype.bank_account.bank_account import (
|
||||||
get_bank_account_details,
|
get_bank_account_details,
|
||||||
get_party_bank_account,
|
get_party_bank_account,
|
||||||
@ -189,7 +190,7 @@ class PaymentEntry(AccountsController):
|
|||||||
|
|
||||||
def set_liability_account(self):
|
def set_liability_account(self):
|
||||||
# Auto setting liability account should only be done during 'draft' status
|
# Auto setting liability account should only be done during 'draft' status
|
||||||
if self.docstatus > 0:
|
if self.docstatus > 0 or self.payment_type == "Internal Transfer":
|
||||||
return
|
return
|
||||||
|
|
||||||
if not frappe.db.get_value(
|
if not frappe.db.get_value(
|
||||||
@ -925,7 +926,10 @@ class PaymentEntry(AccountsController):
|
|||||||
|
|
||||||
def calculate_base_allocated_amount_for_reference(self, d) -> float:
|
def calculate_base_allocated_amount_for_reference(self, d) -> float:
|
||||||
base_allocated_amount = 0
|
base_allocated_amount = 0
|
||||||
if d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"):
|
advance_payment_doctypes = frappe.get_hooks(
|
||||||
|
"advance_payment_customer_doctypes"
|
||||||
|
) + frappe.get_hooks("advance_payment_supplier_doctypes")
|
||||||
|
if d.reference_doctype in advance_payment_doctypes:
|
||||||
# When referencing Sales/Purchase Order, use the source/target exchange rate depending on payment type.
|
# When referencing Sales/Purchase Order, use the source/target exchange rate depending on payment type.
|
||||||
# This is so there are no Exchange Gain/Loss generated for such doctypes
|
# This is so there are no Exchange Gain/Loss generated for such doctypes
|
||||||
|
|
||||||
@ -1144,9 +1148,7 @@ class PaymentEntry(AccountsController):
|
|||||||
"account": self.party_account,
|
"account": self.party_account,
|
||||||
"party_type": self.party_type,
|
"party_type": self.party_type,
|
||||||
"party": self.party,
|
"party": self.party,
|
||||||
"against_type": "Account",
|
|
||||||
"against": against_account,
|
"against": against_account,
|
||||||
"against_link": against_account,
|
|
||||||
"account_currency": self.party_account_currency,
|
"account_currency": self.party_account_currency,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
},
|
},
|
||||||
@ -1311,9 +1313,7 @@ class PaymentEntry(AccountsController):
|
|||||||
{
|
{
|
||||||
"account": self.paid_from,
|
"account": self.paid_from,
|
||||||
"account_currency": self.paid_from_account_currency,
|
"account_currency": self.paid_from_account_currency,
|
||||||
"against_type": self.party_type if self.payment_type == "Pay" else "Account",
|
|
||||||
"against": self.party if self.payment_type == "Pay" else self.paid_to,
|
"against": self.party if self.payment_type == "Pay" else self.paid_to,
|
||||||
"against_link": self.party if self.payment_type == "Pay" else self.paid_to,
|
|
||||||
"credit_in_account_currency": self.paid_amount,
|
"credit_in_account_currency": self.paid_amount,
|
||||||
"credit": self.base_paid_amount,
|
"credit": self.base_paid_amount,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
@ -1328,9 +1328,7 @@ class PaymentEntry(AccountsController):
|
|||||||
{
|
{
|
||||||
"account": self.paid_to,
|
"account": self.paid_to,
|
||||||
"account_currency": self.paid_to_account_currency,
|
"account_currency": self.paid_to_account_currency,
|
||||||
"against_type": self.party_type if self.payment_type == "Receive" else "Account",
|
|
||||||
"against": self.party if self.payment_type == "Receive" else self.paid_from,
|
"against": self.party if self.payment_type == "Receive" else self.paid_from,
|
||||||
"against_link": self.party if self.payment_type == "Receive" else self.paid_from,
|
|
||||||
"debit_in_account_currency": self.received_amount,
|
"debit_in_account_currency": self.received_amount,
|
||||||
"debit": self.base_received_amount,
|
"debit": self.base_received_amount,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
@ -1354,7 +1352,6 @@ class PaymentEntry(AccountsController):
|
|||||||
rev_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit"
|
rev_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit"
|
||||||
against = self.party or self.paid_to
|
against = self.party or self.paid_to
|
||||||
|
|
||||||
against_type = self.party_type or "Account"
|
|
||||||
payment_account = self.get_party_account_for_taxes()
|
payment_account = self.get_party_account_for_taxes()
|
||||||
tax_amount = d.tax_amount
|
tax_amount = d.tax_amount
|
||||||
base_tax_amount = d.base_tax_amount
|
base_tax_amount = d.base_tax_amount
|
||||||
@ -1363,9 +1360,7 @@ class PaymentEntry(AccountsController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": d.account_head,
|
"account": d.account_head,
|
||||||
"against_type": against_type,
|
|
||||||
"against": against,
|
"against": against,
|
||||||
"against_link": against,
|
|
||||||
dr_or_cr: tax_amount,
|
dr_or_cr: tax_amount,
|
||||||
dr_or_cr + "_in_account_currency": base_tax_amount
|
dr_or_cr + "_in_account_currency": base_tax_amount
|
||||||
if account_currency == self.company_currency
|
if account_currency == self.company_currency
|
||||||
@ -1390,9 +1385,7 @@ class PaymentEntry(AccountsController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": payment_account,
|
"account": payment_account,
|
||||||
"against_type": against_type,
|
|
||||||
"against": against,
|
"against": against,
|
||||||
"against_link": against,
|
|
||||||
rev_dr_or_cr: tax_amount,
|
rev_dr_or_cr: tax_amount,
|
||||||
rev_dr_or_cr + "_in_account_currency": base_tax_amount
|
rev_dr_or_cr + "_in_account_currency": base_tax_amount
|
||||||
if account_currency == self.company_currency
|
if account_currency == self.company_currency
|
||||||
@ -1417,9 +1410,7 @@ class PaymentEntry(AccountsController):
|
|||||||
{
|
{
|
||||||
"account": d.account,
|
"account": d.account,
|
||||||
"account_currency": account_currency,
|
"account_currency": account_currency,
|
||||||
"against_type": self.party_type or "Account",
|
|
||||||
"against": self.party or self.paid_from,
|
"against": self.party or self.paid_from,
|
||||||
"against_link": self.party or self.paid_from,
|
|
||||||
"debit_in_account_currency": d.amount,
|
"debit_in_account_currency": d.amount,
|
||||||
"debit": d.amount,
|
"debit": d.amount,
|
||||||
"cost_center": d.cost_center,
|
"cost_center": d.cost_center,
|
||||||
@ -1436,8 +1427,11 @@ class PaymentEntry(AccountsController):
|
|||||||
|
|
||||||
def update_advance_paid(self):
|
def update_advance_paid(self):
|
||||||
if self.payment_type in ("Receive", "Pay") and self.party:
|
if self.payment_type in ("Receive", "Pay") and self.party:
|
||||||
|
advance_payment_doctypes = frappe.get_hooks(
|
||||||
|
"advance_payment_customer_doctypes"
|
||||||
|
) + frappe.get_hooks("advance_payment_supplier_doctypes")
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
if d.allocated_amount and d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"):
|
if d.allocated_amount and d.reference_doctype in advance_payment_doctypes:
|
||||||
frappe.get_doc(
|
frappe.get_doc(
|
||||||
d.reference_doctype, d.reference_name, for_update=True
|
d.reference_doctype, d.reference_name, for_update=True
|
||||||
).set_total_advance_paid()
|
).set_total_advance_paid()
|
||||||
@ -1684,6 +1678,13 @@ def get_outstanding_reference_documents(args, validate=False):
|
|||||||
condition += " and cost_center='%s'" % args.get("cost_center")
|
condition += " and cost_center='%s'" % args.get("cost_center")
|
||||||
accounting_dimensions_filter.append(ple.cost_center == args.get("cost_center"))
|
accounting_dimensions_filter.append(ple.cost_center == args.get("cost_center"))
|
||||||
|
|
||||||
|
# dynamic dimension filters
|
||||||
|
active_dimensions = get_dimensions()[0]
|
||||||
|
for dim in active_dimensions:
|
||||||
|
if args.get(dim.fieldname):
|
||||||
|
condition += " and {0}='{1}'".format(dim.fieldname, args.get(dim.fieldname))
|
||||||
|
accounting_dimensions_filter.append(ple[dim.fieldname] == args.get(dim.fieldname))
|
||||||
|
|
||||||
date_fields_dict = {
|
date_fields_dict = {
|
||||||
"posting_date": ["from_posting_date", "to_posting_date"],
|
"posting_date": ["from_posting_date", "to_posting_date"],
|
||||||
"due_date": ["from_due_date", "to_due_date"],
|
"due_date": ["from_due_date", "to_due_date"],
|
||||||
@ -1917,6 +1918,12 @@ def get_orders_to_be_billed(
|
|||||||
if doc and hasattr(doc, "cost_center") and doc.cost_center:
|
if doc and hasattr(doc, "cost_center") and doc.cost_center:
|
||||||
condition = " and cost_center='%s'" % cost_center
|
condition = " and cost_center='%s'" % cost_center
|
||||||
|
|
||||||
|
# dynamic dimension filters
|
||||||
|
active_dimensions = get_dimensions()[0]
|
||||||
|
for dim in active_dimensions:
|
||||||
|
if filters.get(dim.fieldname):
|
||||||
|
condition += " and {0}='{1}'".format(dim.fieldname, filters.get(dim.fieldname))
|
||||||
|
|
||||||
if party_account_currency == company_currency:
|
if party_account_currency == company_currency:
|
||||||
grand_total_field = "base_grand_total"
|
grand_total_field = "base_grand_total"
|
||||||
rounded_total_field = "base_rounded_total"
|
rounded_total_field = "base_rounded_total"
|
||||||
|
|||||||
@ -95,6 +95,8 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
this.frm.change_custom_button_type(__('Allocate'), null, 'default');
|
this.frm.change_custom_button_type(__('Allocate'), null, 'default');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.frm.trigger("set_query_for_dimension_filters");
|
||||||
|
|
||||||
// check for any running reconciliation jobs
|
// check for any running reconciliation jobs
|
||||||
if (this.frm.doc.receivable_payable_account) {
|
if (this.frm.doc.receivable_payable_account) {
|
||||||
this.frm.call({
|
this.frm.call({
|
||||||
@ -125,6 +127,25 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
set_query_for_dimension_filters() {
|
||||||
|
frappe.call({
|
||||||
|
method: "erpnext.accounts.doctype.payment_reconciliation.payment_reconciliation.get_queries_for_dimension_filters",
|
||||||
|
args: {
|
||||||
|
company: this.frm.doc.company,
|
||||||
|
},
|
||||||
|
callback: (r) => {
|
||||||
|
if (!r.exc && r.message) {
|
||||||
|
r.message.forEach(x => {
|
||||||
|
this.frm.set_query(x.fieldname, () => {
|
||||||
|
return {
|
||||||
|
'filters': x.filters
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
company() {
|
company() {
|
||||||
this.frm.set_value('party', '');
|
this.frm.set_value('party', '');
|
||||||
|
|||||||
@ -25,7 +25,9 @@
|
|||||||
"invoice_limit",
|
"invoice_limit",
|
||||||
"payment_limit",
|
"payment_limit",
|
||||||
"bank_cash_account",
|
"bank_cash_account",
|
||||||
|
"accounting_dimensions_section",
|
||||||
"cost_center",
|
"cost_center",
|
||||||
|
"dimension_col_break",
|
||||||
"sec_break1",
|
"sec_break1",
|
||||||
"invoice_name",
|
"invoice_name",
|
||||||
"invoices",
|
"invoices",
|
||||||
@ -208,6 +210,18 @@
|
|||||||
"fieldname": "payment_name",
|
"fieldname": "payment_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Filter on Payment"
|
"label": "Filter on Payment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsible": 1,
|
||||||
|
"collapsible_depends_on": "eval: doc.invoices.length == 0",
|
||||||
|
"depends_on": "eval:doc.receivable_payable_account",
|
||||||
|
"fieldname": "accounting_dimensions_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Accounting Dimensions Filter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "dimension_col_break",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_toolbar": 1,
|
"hide_toolbar": 1,
|
||||||
@ -215,7 +229,7 @@
|
|||||||
"is_virtual": 1,
|
"is_virtual": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-11-17 17:33:55.701726",
|
"modified": "2023-12-14 13:38:16.264013",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Reconciliation",
|
"name": "Payment Reconciliation",
|
||||||
|
|||||||
@ -10,6 +10,7 @@ from frappe.query_builder.custom import ConstantColumn
|
|||||||
from frappe.utils import flt, fmt_money, get_link_to_form, getdate, nowdate, today
|
from frappe.utils import flt, fmt_money, get_link_to_form, getdate, nowdate, today
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
|
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_dimensions
|
||||||
from erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation import (
|
from erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation import (
|
||||||
is_any_doc_running,
|
is_any_doc_running,
|
||||||
)
|
)
|
||||||
@ -70,6 +71,7 @@ class PaymentReconciliation(Document):
|
|||||||
self.common_filter_conditions = []
|
self.common_filter_conditions = []
|
||||||
self.accounting_dimension_filter_conditions = []
|
self.accounting_dimension_filter_conditions = []
|
||||||
self.ple_posting_date_filter = []
|
self.ple_posting_date_filter = []
|
||||||
|
self.dimensions = get_dimensions()[0]
|
||||||
|
|
||||||
def load_from_db(self):
|
def load_from_db(self):
|
||||||
# 'modified' attribute is required for `run_doc_method` to work properly.
|
# 'modified' attribute is required for `run_doc_method` to work properly.
|
||||||
@ -172,6 +174,14 @@ class PaymentReconciliation(Document):
|
|||||||
if self.payment_name:
|
if self.payment_name:
|
||||||
condition.update({"name": self.payment_name})
|
condition.update({"name": self.payment_name})
|
||||||
|
|
||||||
|
# pass dynamic dimension filter values to query builder
|
||||||
|
dimensions = {}
|
||||||
|
for x in self.dimensions:
|
||||||
|
dimension = x.fieldname
|
||||||
|
if self.get(dimension):
|
||||||
|
dimensions.update({dimension: self.get(dimension)})
|
||||||
|
condition.update({"accounting_dimensions": dimensions})
|
||||||
|
|
||||||
payment_entries = get_advance_payment_entries_for_regional(
|
payment_entries = get_advance_payment_entries_for_regional(
|
||||||
self.party_type,
|
self.party_type,
|
||||||
self.party,
|
self.party,
|
||||||
@ -185,66 +195,67 @@ class PaymentReconciliation(Document):
|
|||||||
return payment_entries
|
return payment_entries
|
||||||
|
|
||||||
def get_jv_entries(self):
|
def get_jv_entries(self):
|
||||||
condition = self.get_conditions()
|
je = qb.DocType("Journal Entry")
|
||||||
|
jea = qb.DocType("Journal Entry Account")
|
||||||
|
conditions = self.get_journal_filter_conditions()
|
||||||
|
|
||||||
|
# Dimension filters
|
||||||
|
for x in self.dimensions:
|
||||||
|
dimension = x.fieldname
|
||||||
|
if self.get(dimension):
|
||||||
|
conditions.append(jea[dimension] == self.get(dimension))
|
||||||
|
|
||||||
if self.payment_name:
|
if self.payment_name:
|
||||||
condition += f" and t1.name like '%%{self.payment_name}%%'"
|
conditions.append(je.name.like(f"%%{self.payment_name}%%"))
|
||||||
|
|
||||||
if self.get("cost_center"):
|
if self.get("cost_center"):
|
||||||
condition += f" and t2.cost_center = '{self.cost_center}' "
|
conditions.append(jea.cost_center == self.cost_center)
|
||||||
|
|
||||||
dr_or_cr = (
|
dr_or_cr = (
|
||||||
"credit_in_account_currency"
|
"credit_in_account_currency"
|
||||||
if erpnext.get_party_account_type(self.party_type) == "Receivable"
|
if erpnext.get_party_account_type(self.party_type) == "Receivable"
|
||||||
else "debit_in_account_currency"
|
else "debit_in_account_currency"
|
||||||
)
|
)
|
||||||
|
conditions.append(jea[dr_or_cr].gt(0))
|
||||||
|
|
||||||
bank_account_condition = (
|
if self.bank_cash_account:
|
||||||
"t2.against_account like %(bank_cash_account)s" if self.bank_cash_account else "1=1"
|
conditions.append(jea.against_account.like(f"%%{self.bank_cash_account}%%"))
|
||||||
|
|
||||||
|
journal_query = (
|
||||||
|
qb.from_(je)
|
||||||
|
.inner_join(jea)
|
||||||
|
.on(jea.parent == je.name)
|
||||||
|
.select(
|
||||||
|
ConstantColumn("Journal Entry").as_("reference_type"),
|
||||||
|
je.name.as_("reference_name"),
|
||||||
|
je.posting_date,
|
||||||
|
je.remark.as_("remarks"),
|
||||||
|
jea.name.as_("reference_row"),
|
||||||
|
jea[dr_or_cr].as_("amount"),
|
||||||
|
jea.is_advance,
|
||||||
|
jea.exchange_rate,
|
||||||
|
jea.account_currency.as_("currency"),
|
||||||
|
jea.cost_center.as_("cost_center"),
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
(je.docstatus == 1)
|
||||||
|
& (jea.party_type == self.party_type)
|
||||||
|
& (jea.party == self.party)
|
||||||
|
& (jea.account == self.receivable_payable_account)
|
||||||
|
& (
|
||||||
|
(jea.reference_type == "")
|
||||||
|
| (jea.reference_type.isnull())
|
||||||
|
| (jea.reference_type.isin(("Sales Order", "Purchase Order")))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.where(Criterion.all(conditions))
|
||||||
|
.orderby(je.posting_date)
|
||||||
)
|
)
|
||||||
|
|
||||||
limit = f"limit {self.payment_limit}" if self.payment_limit else " "
|
if self.payment_limit:
|
||||||
|
journal_query = journal_query.limit(self.payment_limit)
|
||||||
|
|
||||||
# nosemgrep
|
journal_entries = journal_query.run(as_dict=True)
|
||||||
journal_entries = frappe.db.sql(
|
|
||||||
"""
|
|
||||||
select
|
|
||||||
"Journal Entry" as reference_type, t1.name as reference_name,
|
|
||||||
t1.posting_date, t1.remark as remarks, t2.name as reference_row,
|
|
||||||
{dr_or_cr} as amount, t2.is_advance, t2.exchange_rate,
|
|
||||||
t2.account_currency as currency, t2.cost_center as cost_center
|
|
||||||
from
|
|
||||||
`tabJournal Entry` t1, `tabJournal Entry Account` t2
|
|
||||||
where
|
|
||||||
t1.name = t2.parent and t1.docstatus = 1 and t2.docstatus = 1
|
|
||||||
and t2.party_type = %(party_type)s and t2.party = %(party)s
|
|
||||||
and t2.account = %(account)s and {dr_or_cr} > 0 {condition}
|
|
||||||
and (t2.reference_type is null or t2.reference_type = '' or
|
|
||||||
(t2.reference_type in ('Sales Order', 'Purchase Order')
|
|
||||||
and t2.reference_name is not null and t2.reference_name != ''))
|
|
||||||
and (CASE
|
|
||||||
WHEN t1.voucher_type in ('Debit Note', 'Credit Note')
|
|
||||||
THEN 1=1
|
|
||||||
ELSE {bank_account_condition}
|
|
||||||
END)
|
|
||||||
order by t1.posting_date
|
|
||||||
{limit}
|
|
||||||
""".format(
|
|
||||||
**{
|
|
||||||
"dr_or_cr": dr_or_cr,
|
|
||||||
"bank_account_condition": bank_account_condition,
|
|
||||||
"condition": condition,
|
|
||||||
"limit": limit,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
{
|
|
||||||
"party_type": self.party_type,
|
|
||||||
"party": self.party,
|
|
||||||
"account": self.receivable_payable_account,
|
|
||||||
"bank_cash_account": "%%%s%%" % self.bank_cash_account,
|
|
||||||
},
|
|
||||||
as_dict=1,
|
|
||||||
)
|
|
||||||
|
|
||||||
return list(journal_entries)
|
return list(journal_entries)
|
||||||
|
|
||||||
@ -298,6 +309,7 @@ class PaymentReconciliation(Document):
|
|||||||
min_outstanding=-(self.minimum_payment_amount) if self.minimum_payment_amount else None,
|
min_outstanding=-(self.minimum_payment_amount) if self.minimum_payment_amount else None,
|
||||||
max_outstanding=-(self.maximum_payment_amount) if self.maximum_payment_amount else None,
|
max_outstanding=-(self.maximum_payment_amount) if self.maximum_payment_amount else None,
|
||||||
get_payments=True,
|
get_payments=True,
|
||||||
|
accounting_dimensions=self.accounting_dimension_filter_conditions,
|
||||||
)
|
)
|
||||||
|
|
||||||
for inv in return_outstanding:
|
for inv in return_outstanding:
|
||||||
@ -447,8 +459,15 @@ class PaymentReconciliation(Document):
|
|||||||
row = self.append("allocation", {})
|
row = self.append("allocation", {})
|
||||||
row.update(entry)
|
row.update(entry)
|
||||||
|
|
||||||
|
def update_dimension_values_in_allocated_entries(self, res):
|
||||||
|
for x in self.dimensions:
|
||||||
|
dimension = x.fieldname
|
||||||
|
if self.get(dimension):
|
||||||
|
res[dimension] = self.get(dimension)
|
||||||
|
return res
|
||||||
|
|
||||||
def get_allocated_entry(self, pay, inv, allocated_amount):
|
def get_allocated_entry(self, pay, inv, allocated_amount):
|
||||||
return frappe._dict(
|
res = frappe._dict(
|
||||||
{
|
{
|
||||||
"reference_type": pay.get("reference_type"),
|
"reference_type": pay.get("reference_type"),
|
||||||
"reference_name": pay.get("reference_name"),
|
"reference_name": pay.get("reference_name"),
|
||||||
@ -464,6 +483,9 @@ class PaymentReconciliation(Document):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
res = self.update_dimension_values_in_allocated_entries(res)
|
||||||
|
return res
|
||||||
|
|
||||||
def reconcile_allocations(self, skip_ref_details_update_for_pe=False):
|
def reconcile_allocations(self, skip_ref_details_update_for_pe=False):
|
||||||
adjust_allocations_for_taxes(self)
|
adjust_allocations_for_taxes(self)
|
||||||
dr_or_cr = (
|
dr_or_cr = (
|
||||||
@ -486,10 +508,10 @@ class PaymentReconciliation(Document):
|
|||||||
reconciled_entry.append(payment_details)
|
reconciled_entry.append(payment_details)
|
||||||
|
|
||||||
if entry_list:
|
if entry_list:
|
||||||
reconcile_against_document(entry_list, skip_ref_details_update_for_pe)
|
reconcile_against_document(entry_list, skip_ref_details_update_for_pe, self.dimensions)
|
||||||
|
|
||||||
if dr_or_cr_notes:
|
if dr_or_cr_notes:
|
||||||
reconcile_dr_cr_note(dr_or_cr_notes, self.company)
|
reconcile_dr_cr_note(dr_or_cr_notes, self.company, self.dimensions)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def reconcile(self):
|
def reconcile(self):
|
||||||
@ -518,7 +540,7 @@ class PaymentReconciliation(Document):
|
|||||||
self.get_unreconciled_entries()
|
self.get_unreconciled_entries()
|
||||||
|
|
||||||
def get_payment_details(self, row, dr_or_cr):
|
def get_payment_details(self, row, dr_or_cr):
|
||||||
return frappe._dict(
|
payment_details = frappe._dict(
|
||||||
{
|
{
|
||||||
"voucher_type": row.get("reference_type"),
|
"voucher_type": row.get("reference_type"),
|
||||||
"voucher_no": row.get("reference_name"),
|
"voucher_no": row.get("reference_name"),
|
||||||
@ -541,6 +563,12 @@ class PaymentReconciliation(Document):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for x in self.dimensions:
|
||||||
|
if row.get(x.fieldname):
|
||||||
|
payment_details[x.fieldname] = row.get(x.fieldname)
|
||||||
|
|
||||||
|
return payment_details
|
||||||
|
|
||||||
def check_mandatory_to_fetch(self):
|
def check_mandatory_to_fetch(self):
|
||||||
for fieldname in ["company", "party_type", "party", "receivable_payable_account"]:
|
for fieldname in ["company", "party_type", "party", "receivable_payable_account"]:
|
||||||
if not self.get(fieldname):
|
if not self.get(fieldname):
|
||||||
@ -648,6 +676,13 @@ class PaymentReconciliation(Document):
|
|||||||
if not invoices_to_reconcile:
|
if not invoices_to_reconcile:
|
||||||
frappe.throw(_("No records found in Allocation table"))
|
frappe.throw(_("No records found in Allocation table"))
|
||||||
|
|
||||||
|
def build_dimensions_filter_conditions(self):
|
||||||
|
ple = qb.DocType("Payment Ledger Entry")
|
||||||
|
for x in self.dimensions:
|
||||||
|
dimension = x.fieldname
|
||||||
|
if self.get(dimension):
|
||||||
|
self.accounting_dimension_filter_conditions.append(ple[dimension] == self.get(dimension))
|
||||||
|
|
||||||
def build_qb_filter_conditions(self, get_invoices=False, get_return_invoices=False):
|
def build_qb_filter_conditions(self, get_invoices=False, get_return_invoices=False):
|
||||||
self.common_filter_conditions.clear()
|
self.common_filter_conditions.clear()
|
||||||
self.accounting_dimension_filter_conditions.clear()
|
self.accounting_dimension_filter_conditions.clear()
|
||||||
@ -671,40 +706,30 @@ class PaymentReconciliation(Document):
|
|||||||
if self.to_payment_date:
|
if self.to_payment_date:
|
||||||
self.ple_posting_date_filter.append(ple.posting_date.lte(self.to_payment_date))
|
self.ple_posting_date_filter.append(ple.posting_date.lte(self.to_payment_date))
|
||||||
|
|
||||||
def get_conditions(self, get_payments=False):
|
self.build_dimensions_filter_conditions()
|
||||||
condition = " and company = '{0}' ".format(self.company)
|
|
||||||
|
|
||||||
if self.get("cost_center") and get_payments:
|
def get_journal_filter_conditions(self):
|
||||||
condition = " and cost_center = '{0}' ".format(self.cost_center)
|
conditions = []
|
||||||
|
je = qb.DocType("Journal Entry")
|
||||||
|
jea = qb.DocType("Journal Entry Account")
|
||||||
|
conditions.append(je.company == self.company)
|
||||||
|
|
||||||
condition += (
|
if self.from_payment_date:
|
||||||
" and posting_date >= {0}".format(frappe.db.escape(self.from_payment_date))
|
conditions.append(je.posting_date.gte(self.from_payment_date))
|
||||||
if self.from_payment_date
|
|
||||||
else ""
|
if self.to_payment_date:
|
||||||
)
|
conditions.append(je.posting_date.lte(self.to_payment_date))
|
||||||
condition += (
|
|
||||||
" and posting_date <= {0}".format(frappe.db.escape(self.to_payment_date))
|
|
||||||
if self.to_payment_date
|
|
||||||
else ""
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.minimum_payment_amount:
|
if self.minimum_payment_amount:
|
||||||
condition += (
|
conditions.append(je.total_debit.gte(self.minimum_payment_amount))
|
||||||
" and unallocated_amount >= {0}".format(flt(self.minimum_payment_amount))
|
|
||||||
if get_payments
|
|
||||||
else " and total_debit >= {0}".format(flt(self.minimum_payment_amount))
|
|
||||||
)
|
|
||||||
if self.maximum_payment_amount:
|
if self.maximum_payment_amount:
|
||||||
condition += (
|
conditions.append(je.total_debit.lte(self.maximum_payment_amount))
|
||||||
" and unallocated_amount <= {0}".format(flt(self.maximum_payment_amount))
|
|
||||||
if get_payments
|
|
||||||
else " and total_debit <= {0}".format(flt(self.maximum_payment_amount))
|
|
||||||
)
|
|
||||||
|
|
||||||
return condition
|
return conditions
|
||||||
|
|
||||||
|
|
||||||
def reconcile_dr_cr_note(dr_cr_notes, company):
|
def reconcile_dr_cr_note(dr_cr_notes, company, active_dimensions=None):
|
||||||
for inv in dr_cr_notes:
|
for inv in dr_cr_notes:
|
||||||
voucher_type = "Credit Note" if inv.voucher_type == "Sales Invoice" else "Debit Note"
|
voucher_type = "Credit Note" if inv.voucher_type == "Sales Invoice" else "Debit Note"
|
||||||
|
|
||||||
@ -754,6 +779,15 @@ def reconcile_dr_cr_note(dr_cr_notes, company):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Credit Note(JE) will inherit the same dimension values as payment
|
||||||
|
dimensions_dict = frappe._dict()
|
||||||
|
if active_dimensions:
|
||||||
|
for dim in active_dimensions:
|
||||||
|
dimensions_dict[dim.fieldname] = inv.get(dim.fieldname)
|
||||||
|
|
||||||
|
jv.accounts[0].update(dimensions_dict)
|
||||||
|
jv.accounts[1].update(dimensions_dict)
|
||||||
|
|
||||||
jv.flags.ignore_mandatory = True
|
jv.flags.ignore_mandatory = True
|
||||||
jv.flags.ignore_exchange_rate = True
|
jv.flags.ignore_exchange_rate = True
|
||||||
jv.remark = None
|
jv.remark = None
|
||||||
@ -787,9 +821,27 @@ def reconcile_dr_cr_note(dr_cr_notes, company):
|
|||||||
inv.against_voucher,
|
inv.against_voucher,
|
||||||
None,
|
None,
|
||||||
inv.cost_center,
|
inv.cost_center,
|
||||||
|
dimensions_dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@erpnext.allow_regional
|
@erpnext.allow_regional
|
||||||
def adjust_allocations_for_taxes(doc):
|
def adjust_allocations_for_taxes(doc):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_queries_for_dimension_filters(company: str = None):
|
||||||
|
dimensions_with_filters = []
|
||||||
|
for d in get_dimensions()[0]:
|
||||||
|
filters = {}
|
||||||
|
meta = frappe.get_meta(d.document_type)
|
||||||
|
if meta.has_field("company") and company:
|
||||||
|
filters.update({"company": company})
|
||||||
|
|
||||||
|
if meta.is_tree:
|
||||||
|
filters.update({"is_group": 0})
|
||||||
|
|
||||||
|
dimensions_with_filters.append({"fieldname": d.fieldname, "filters": filters})
|
||||||
|
|
||||||
|
return dimensions_with_filters
|
||||||
|
|||||||
@ -24,7 +24,9 @@
|
|||||||
"difference_account",
|
"difference_account",
|
||||||
"exchange_rate",
|
"exchange_rate",
|
||||||
"currency",
|
"currency",
|
||||||
"cost_center"
|
"accounting_dimensions_section",
|
||||||
|
"cost_center",
|
||||||
|
"dimension_col_break"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -157,12 +159,21 @@
|
|||||||
"fieldname": "gain_loss_posting_date",
|
"fieldname": "gain_loss_posting_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Difference Posting Date"
|
"label": "Difference Posting Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "accounting_dimensions_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Accounting Dimensions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "dimension_col_break",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"is_virtual": 1,
|
"is_virtual": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-11-17 17:33:38.612615",
|
"modified": "2023-12-14 13:38:26.104150",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Reconciliation Allocation",
|
"name": "Payment Reconciliation Allocation",
|
||||||
|
|||||||
@ -169,6 +169,13 @@ class PaymentRequest(Document):
|
|||||||
elif self.payment_channel == "Phone":
|
elif self.payment_channel == "Phone":
|
||||||
self.request_phone_payment()
|
self.request_phone_payment()
|
||||||
|
|
||||||
|
advance_payment_doctypes = frappe.get_hooks(
|
||||||
|
"advance_payment_customer_doctypes"
|
||||||
|
) + frappe.get_hooks("advance_payment_supplier_doctypes")
|
||||||
|
if self.reference_doctype in advance_payment_doctypes:
|
||||||
|
# set advance payment status
|
||||||
|
ref_doc.set_total_advance_paid()
|
||||||
|
|
||||||
def request_phone_payment(self):
|
def request_phone_payment(self):
|
||||||
controller = _get_payment_gateway_controller(self.payment_gateway)
|
controller = _get_payment_gateway_controller(self.payment_gateway)
|
||||||
request_amount = self.get_request_amount()
|
request_amount = self.get_request_amount()
|
||||||
@ -207,6 +214,14 @@ class PaymentRequest(Document):
|
|||||||
self.check_if_payment_entry_exists()
|
self.check_if_payment_entry_exists()
|
||||||
self.set_as_cancelled()
|
self.set_as_cancelled()
|
||||||
|
|
||||||
|
ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
|
||||||
|
advance_payment_doctypes = frappe.get_hooks(
|
||||||
|
"advance_payment_customer_doctypes"
|
||||||
|
) + frappe.get_hooks("advance_payment_supplier_doctypes")
|
||||||
|
if self.reference_doctype in advance_payment_doctypes:
|
||||||
|
# set advance payment status
|
||||||
|
ref_doc.set_total_advance_paid()
|
||||||
|
|
||||||
def make_invoice(self):
|
def make_invoice(self):
|
||||||
ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
|
ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
|
||||||
if hasattr(ref_doc, "order_type") and getattr(ref_doc, "order_type") == "Shopping Cart":
|
if hasattr(ref_doc, "order_type") and getattr(ref_doc, "order_type") == "Shopping Cart":
|
||||||
@ -424,6 +439,15 @@ def make_payment_request(**args):
|
|||||||
"""Make payment request"""
|
"""Make payment request"""
|
||||||
|
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
if args.dt not in [
|
||||||
|
"Sales Order",
|
||||||
|
"Purchase Order",
|
||||||
|
"Sales Invoice",
|
||||||
|
"Purchase Invoice",
|
||||||
|
"POS Invoice",
|
||||||
|
"Fees",
|
||||||
|
]:
|
||||||
|
frappe.throw(_("Payment Requests cannot be created against: {0}").format(frappe.bold(args.dt)))
|
||||||
|
|
||||||
ref_doc = frappe.get_doc(args.dt, args.dn)
|
ref_doc = frappe.get_doc(args.dt, args.dn)
|
||||||
gateway_account = get_gateway_details(args) or frappe._dict()
|
gateway_account = get_gateway_details(args) or frappe._dict()
|
||||||
|
|||||||
@ -371,7 +371,7 @@ class POSInvoice(SalesInvoice):
|
|||||||
if d.get("qty") > 0:
|
if d.get("qty") > 0:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_(
|
_(
|
||||||
"Row #{}: You cannot add postive quantities in a return invoice. Please remove item {} to complete the return."
|
"Row #{}: You cannot add positive quantities in a return invoice. Please remove item {} to complete the return."
|
||||||
).format(d.idx, frappe.bold(d.item_code)),
|
).format(d.idx, frappe.bold(d.item_code)),
|
||||||
title=_("Invalid Item"),
|
title=_("Invalid Item"),
|
||||||
)
|
)
|
||||||
@ -793,7 +793,7 @@ def make_merge_log(invoices):
|
|||||||
invoices = json.loads(invoices)
|
invoices = json.loads(invoices)
|
||||||
|
|
||||||
if len(invoices) == 0:
|
if len(invoices) == 0:
|
||||||
frappe.throw(_("Atleast one invoice has to be selected."))
|
frappe.throw(_("At least one invoice has to be selected."))
|
||||||
|
|
||||||
merge_log = frappe.new_doc("POS Invoice Merge Log")
|
merge_log = frappe.new_doc("POS Invoice Merge Log")
|
||||||
merge_log.posting_date = getdate(nowdate())
|
merge_log.posting_date = getdate(nowdate())
|
||||||
|
|||||||
@ -132,7 +132,7 @@ class POSProfile(Document):
|
|||||||
|
|
||||||
if len(customer_groups) != len(set(customer_groups)):
|
if len(customer_groups) != len(set(customer_groups)):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Duplicate customer group found in the cutomer group table"),
|
_("Duplicate customer group found in the customer group table"),
|
||||||
title=_("Duplicate Customer Group"),
|
title=_("Duplicate Customer Group"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -339,7 +339,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "valid_upto",
|
"fieldname": "valid_upto",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Valid Upto"
|
"label": "Valid Up To"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "col_break1",
|
"fieldname": "col_break1",
|
||||||
@ -608,7 +608,7 @@
|
|||||||
"icon": "fa fa-gift",
|
"icon": "fa fa-gift",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-02-14 04:53:34.887358",
|
"modified": "2024-01-24 02:20:26.145996",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Pricing Rule",
|
"name": "Pricing Rule",
|
||||||
|
|||||||
@ -193,7 +193,7 @@ class PricingRule(Document):
|
|||||||
|
|
||||||
def validate_applicable_for_selling_or_buying(self):
|
def validate_applicable_for_selling_or_buying(self):
|
||||||
if not self.selling and not self.buying:
|
if not self.selling and not self.buying:
|
||||||
throw(_("Atleast one of the Selling or Buying must be selected"))
|
throw(_("At least one of the Selling or Buying must be selected"))
|
||||||
|
|
||||||
if not self.selling and self.applicable_for in [
|
if not self.selling and self.applicable_for in [
|
||||||
"Customer",
|
"Customer",
|
||||||
@ -579,12 +579,17 @@ def apply_price_discount_rule(pricing_rule, item_details, args):
|
|||||||
item_details[field] += pricing_rule.get(field, 0) if pricing_rule else args.get(field, 0)
|
item_details[field] += pricing_rule.get(field, 0) if pricing_rule else args.get(field, 0)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None, rate=None):
|
def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None, rate=None):
|
||||||
from erpnext.accounts.doctype.pricing_rule.utils import (
|
from erpnext.accounts.doctype.pricing_rule.utils import (
|
||||||
get_applied_pricing_rules,
|
get_applied_pricing_rules,
|
||||||
get_pricing_rule_items,
|
get_pricing_rule_items,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if isinstance(item_details, str):
|
||||||
|
item_details = json.loads(item_details)
|
||||||
|
item_details = frappe._dict(item_details)
|
||||||
|
|
||||||
for d in get_applied_pricing_rules(pricing_rules):
|
for d in get_applied_pricing_rules(pricing_rules):
|
||||||
if not d or not frappe.db.exists("Pricing Rule", d):
|
if not d or not frappe.db.exists("Pricing Rule", d):
|
||||||
continue
|
continue
|
||||||
|
|||||||
@ -232,7 +232,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "valid_upto",
|
"fieldname": "valid_upto",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Valid Upto"
|
"label": "Valid Up To"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_26",
|
"fieldname": "column_break_26",
|
||||||
@ -278,7 +278,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-05-06 16:20:22.039078",
|
"modified": "2024-01-24 02:20:26.145996",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Promotional Scheme",
|
"name": "Promotional Scheme",
|
||||||
|
|||||||
@ -827,9 +827,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
"party_type": "Supplier",
|
"party_type": "Supplier",
|
||||||
"party": self.supplier,
|
"party": self.supplier,
|
||||||
"due_date": self.due_date,
|
"due_date": self.due_date,
|
||||||
"against_type": "Account",
|
|
||||||
"against": self.against_expense_account,
|
"against": self.against_expense_account,
|
||||||
"against_link": self.against_expense_account,
|
|
||||||
"credit": base_grand_total,
|
"credit": base_grand_total,
|
||||||
"credit_in_account_currency": base_grand_total
|
"credit_in_account_currency": base_grand_total
|
||||||
if self.party_account_currency == self.company_currency
|
if self.party_account_currency == self.company_currency
|
||||||
@ -902,9 +900,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": warehouse_account[item.warehouse]["account"],
|
"account": warehouse_account[item.warehouse]["account"],
|
||||||
"against_type": "Account",
|
|
||||||
"against": warehouse_account[item.from_warehouse]["account"],
|
"against": warehouse_account[item.from_warehouse]["account"],
|
||||||
"against_link": warehouse_account[item.from_warehouse]["account"],
|
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
"project": item.project or self.project,
|
"project": item.project or self.project,
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
@ -924,9 +920,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": warehouse_account[item.from_warehouse]["account"],
|
"account": warehouse_account[item.from_warehouse]["account"],
|
||||||
"against_type": "Account",
|
|
||||||
"against": warehouse_account[item.warehouse]["account"],
|
"against": warehouse_account[item.warehouse]["account"],
|
||||||
"against_link": warehouse_account[item.warehouse]["account"],
|
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
"project": item.project or self.project,
|
"project": item.project or self.project,
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
@ -943,9 +937,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": item.expense_account,
|
"account": item.expense_account,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"debit": flt(item.base_net_amount, item.precision("base_net_amount")),
|
"debit": flt(item.base_net_amount, item.precision("base_net_amount")),
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
@ -962,9 +954,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": item.expense_account,
|
"account": item.expense_account,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"debit": warehouse_debit_amount,
|
"debit": warehouse_debit_amount,
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
@ -983,9 +973,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": account,
|
"account": account,
|
||||||
"against_type": "Account",
|
|
||||||
"against": item.expense_account,
|
"against": item.expense_account,
|
||||||
"against_link": item.expense_account,
|
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
"credit": flt(amount["base_amount"]),
|
"credit": flt(amount["base_amount"]),
|
||||||
@ -1005,9 +993,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": supplier_warehouse_account,
|
"account": supplier_warehouse_account,
|
||||||
"against_type": "Account",
|
|
||||||
"against": item.expense_account,
|
"against": item.expense_account,
|
||||||
"against_link": item.expense_account,
|
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
"project": item.project or self.project,
|
"project": item.project or self.project,
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
@ -1062,9 +1048,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": expense_account,
|
"account": expense_account,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"debit": amount,
|
"debit": amount,
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
"project": item.project or self.project,
|
"project": item.project or self.project,
|
||||||
@ -1090,9 +1074,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": expense_account,
|
"account": expense_account,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"debit": discrepancy_caused_by_exchange_rate_difference,
|
"debit": discrepancy_caused_by_exchange_rate_difference,
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
"project": item.project or self.project,
|
"project": item.project or self.project,
|
||||||
@ -1105,9 +1087,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": self.get_company_default("exchange_gain_loss_account"),
|
"account": self.get_company_default("exchange_gain_loss_account"),
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"credit": discrepancy_caused_by_exchange_rate_difference,
|
"credit": discrepancy_caused_by_exchange_rate_difference,
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
"project": item.project or self.project,
|
"project": item.project or self.project,
|
||||||
@ -1140,10 +1120,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": stock_rbnb,
|
"account": self.stock_received_but_not_billed,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
|
"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
|
||||||
"remarks": self.remarks or _("Accounting Entry for Stock"),
|
"remarks": self.remarks or _("Accounting Entry for Stock"),
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
@ -1204,9 +1182,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": cost_of_goods_sold_account,
|
"account": cost_of_goods_sold_account,
|
||||||
"against_type": "Account",
|
|
||||||
"against": item.expense_account,
|
"against": item.expense_account,
|
||||||
"against_link": item.expense_account,
|
|
||||||
"debit": stock_adjustment_amt,
|
"debit": stock_adjustment_amt,
|
||||||
"remarks": self.get("remarks") or _("Stock Adjustment"),
|
"remarks": self.get("remarks") or _("Stock Adjustment"),
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
@ -1236,9 +1212,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": tax.account_head,
|
"account": tax.account_head,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
dr_or_cr: base_amount,
|
dr_or_cr: base_amount,
|
||||||
dr_or_cr + "_in_account_currency": base_amount
|
dr_or_cr + "_in_account_currency": base_amount
|
||||||
if account_currency == self.company_currency
|
if account_currency == self.company_currency
|
||||||
@ -1286,10 +1260,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": tax.account_head,
|
"account": tax.account_head,
|
||||||
"against_type": "Supplier",
|
|
||||||
"cost_center": tax.cost_center,
|
"cost_center": tax.cost_center,
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"credit": applicable_amount,
|
"credit": applicable_amount,
|
||||||
"remarks": self.remarks or _("Accounting Entry for Stock"),
|
"remarks": self.remarks or _("Accounting Entry for Stock"),
|
||||||
},
|
},
|
||||||
@ -1307,9 +1279,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
{
|
{
|
||||||
"account": tax.account_head,
|
"account": tax.account_head,
|
||||||
"cost_center": tax.cost_center,
|
"cost_center": tax.cost_center,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"credit": valuation_tax[tax.name],
|
"credit": valuation_tax[tax.name],
|
||||||
"remarks": self.remarks or _("Accounting Entry for Stock"),
|
"remarks": self.remarks or _("Accounting Entry for Stock"),
|
||||||
},
|
},
|
||||||
@ -1324,9 +1294,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": self.unrealized_profit_loss_account,
|
"account": self.unrealized_profit_loss_account,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"credit": flt(self.total_taxes_and_charges),
|
"credit": flt(self.total_taxes_and_charges),
|
||||||
"credit_in_account_currency": flt(self.base_total_taxes_and_charges),
|
"credit_in_account_currency": flt(self.base_total_taxes_and_charges),
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
@ -1347,9 +1315,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
"account": self.credit_to,
|
"account": self.credit_to,
|
||||||
"party_type": "Supplier",
|
"party_type": "Supplier",
|
||||||
"party": self.supplier,
|
"party": self.supplier,
|
||||||
"against_type": "Account",
|
|
||||||
"against": self.cash_bank_account,
|
"against": self.cash_bank_account,
|
||||||
"against_link": self.cash_bank_account,
|
|
||||||
"debit": self.base_paid_amount,
|
"debit": self.base_paid_amount,
|
||||||
"debit_in_account_currency": self.base_paid_amount
|
"debit_in_account_currency": self.base_paid_amount
|
||||||
if self.party_account_currency == self.company_currency
|
if self.party_account_currency == self.company_currency
|
||||||
@ -1370,9 +1336,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": self.cash_bank_account,
|
"account": self.cash_bank_account,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"credit": self.base_paid_amount,
|
"credit": self.base_paid_amount,
|
||||||
"credit_in_account_currency": self.base_paid_amount
|
"credit_in_account_currency": self.base_paid_amount
|
||||||
if bank_account_currency == self.company_currency
|
if bank_account_currency == self.company_currency
|
||||||
@ -1396,9 +1360,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
"account": self.credit_to,
|
"account": self.credit_to,
|
||||||
"party_type": "Supplier",
|
"party_type": "Supplier",
|
||||||
"party": self.supplier,
|
"party": self.supplier,
|
||||||
"against_type": "Account",
|
|
||||||
"against": self.write_off_account,
|
"against": self.write_off_account,
|
||||||
"against_link": self.write_off_account,
|
|
||||||
"debit": self.base_write_off_amount,
|
"debit": self.base_write_off_amount,
|
||||||
"debit_in_account_currency": self.base_write_off_amount
|
"debit_in_account_currency": self.base_write_off_amount
|
||||||
if self.party_account_currency == self.company_currency
|
if self.party_account_currency == self.company_currency
|
||||||
@ -1418,9 +1380,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": self.write_off_account,
|
"account": self.write_off_account,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"credit": flt(self.base_write_off_amount),
|
"credit": flt(self.base_write_off_amount),
|
||||||
"credit_in_account_currency": self.base_write_off_amount
|
"credit_in_account_currency": self.base_write_off_amount
|
||||||
if write_off_account_currency == self.company_currency
|
if write_off_account_currency == self.company_currency
|
||||||
@ -1447,9 +1407,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": round_off_account,
|
"account": round_off_account,
|
||||||
"against_type": "Supplier",
|
|
||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"against_link": self.supplier,
|
|
||||||
"debit_in_account_currency": self.rounding_adjustment,
|
"debit_in_account_currency": self.rounding_adjustment,
|
||||||
"debit": self.base_rounding_adjustment,
|
"debit": self.base_rounding_adjustment,
|
||||||
"cost_center": round_off_cost_center
|
"cost_center": round_off_cost_center
|
||||||
|
|||||||
@ -64,6 +64,7 @@
|
|||||||
"warehouse",
|
"warehouse",
|
||||||
"from_warehouse",
|
"from_warehouse",
|
||||||
"quality_inspection",
|
"quality_inspection",
|
||||||
|
"add_serial_batch_bundle",
|
||||||
"serial_and_batch_bundle",
|
"serial_and_batch_bundle",
|
||||||
"serial_no",
|
"serial_no",
|
||||||
"col_br_wh",
|
"col_br_wh",
|
||||||
@ -913,12 +914,18 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "WIP Composite Asset",
|
"label": "WIP Composite Asset",
|
||||||
"options": "Asset"
|
"options": "Asset"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:parent.update_stock === 1",
|
||||||
|
"fieldname": "add_serial_batch_bundle",
|
||||||
|
"fieldtype": "Button",
|
||||||
|
"label": "Add Serial / Batch No"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-12-25 22:00:28.043555",
|
"modified": "2024-01-21 19:46:25.537861",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Invoice Item",
|
"name": "Purchase Invoice Item",
|
||||||
|
|||||||
@ -126,7 +126,7 @@
|
|||||||
"fieldname": "rate",
|
"fieldname": "rate",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Rate",
|
"label": "Tax Rate",
|
||||||
"oldfieldname": "rate",
|
"oldfieldname": "rate",
|
||||||
"oldfieldtype": "Currency"
|
"oldfieldtype": "Currency"
|
||||||
},
|
},
|
||||||
@ -230,7 +230,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-08-05 20:04:36.618240",
|
"modified": "2024-01-14 10:04:36.618240",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Taxes and Charges",
|
"name": "Purchase Taxes and Charges",
|
||||||
@ -239,4 +239,4 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ from frappe import _, msgprint, throw
|
|||||||
from frappe.contacts.doctype.address.address import get_address_display
|
from frappe.contacts.doctype.address.address import get_address_display
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
from frappe.model.utils import get_fetch_values
|
from frappe.model.utils import get_fetch_values
|
||||||
from frappe.utils import add_days, cint, flt, formatdate, get_link_to_form, getdate, nowdate
|
from frappe.utils import add_days, cint, cstr, flt, formatdate, get_link_to_form, getdate, nowdate
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
from erpnext.accounts.deferred_revenue import validate_service_stop_date
|
from erpnext.accounts.deferred_revenue import validate_service_stop_date
|
||||||
@ -1233,9 +1233,7 @@ class SalesInvoice(SellingController):
|
|||||||
"party_type": "Customer",
|
"party_type": "Customer",
|
||||||
"party": self.customer,
|
"party": self.customer,
|
||||||
"due_date": self.due_date,
|
"due_date": self.due_date,
|
||||||
"against_type": "Account",
|
|
||||||
"against": self.against_income_account,
|
"against": self.against_income_account,
|
||||||
"against_link": self.against_income_account,
|
|
||||||
"debit": base_grand_total,
|
"debit": base_grand_total,
|
||||||
"debit_in_account_currency": base_grand_total
|
"debit_in_account_currency": base_grand_total
|
||||||
if self.party_account_currency == self.company_currency
|
if self.party_account_currency == self.company_currency
|
||||||
@ -1264,9 +1262,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": tax.account_head,
|
"account": tax.account_head,
|
||||||
"against_type": "Customer",
|
|
||||||
"against": self.customer,
|
"against": self.customer,
|
||||||
"against_link": self.customer,
|
|
||||||
"credit": flt(base_amount, tax.precision("tax_amount_after_discount_amount")),
|
"credit": flt(base_amount, tax.precision("tax_amount_after_discount_amount")),
|
||||||
"credit_in_account_currency": (
|
"credit_in_account_currency": (
|
||||||
flt(base_amount, tax.precision("base_tax_amount_after_discount_amount"))
|
flt(base_amount, tax.precision("base_tax_amount_after_discount_amount"))
|
||||||
@ -1287,9 +1283,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": self.unrealized_profit_loss_account,
|
"account": self.unrealized_profit_loss_account,
|
||||||
"against_type": "Customer",
|
|
||||||
"against": self.customer,
|
"against": self.customer,
|
||||||
"against_link": self.customer,
|
|
||||||
"debit": flt(self.total_taxes_and_charges),
|
"debit": flt(self.total_taxes_and_charges),
|
||||||
"debit_in_account_currency": flt(self.base_total_taxes_and_charges),
|
"debit_in_account_currency": flt(self.base_total_taxes_and_charges),
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
@ -1357,9 +1351,7 @@ class SalesInvoice(SellingController):
|
|||||||
add_asset_activity(asset.name, _("Asset sold"))
|
add_asset_activity(asset.name, _("Asset sold"))
|
||||||
|
|
||||||
for gle in fixed_asset_gl_entries:
|
for gle in fixed_asset_gl_entries:
|
||||||
gle["against_type"] = "Customer"
|
|
||||||
gle["against"] = self.customer
|
gle["against"] = self.customer
|
||||||
gle["against_link"] = self.customer
|
|
||||||
gl_entries.append(self.get_gl_dict(gle, item=item))
|
gl_entries.append(self.get_gl_dict(gle, item=item))
|
||||||
|
|
||||||
self.set_asset_status(asset)
|
self.set_asset_status(asset)
|
||||||
@ -1380,9 +1372,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": income_account,
|
"account": income_account,
|
||||||
"against_type": "Customer",
|
|
||||||
"against": self.customer,
|
"against": self.customer,
|
||||||
"against_link": self.customer,
|
|
||||||
"credit": flt(base_amount, item.precision("base_net_amount")),
|
"credit": flt(base_amount, item.precision("base_net_amount")),
|
||||||
"credit_in_account_currency": (
|
"credit_in_account_currency": (
|
||||||
flt(base_amount, item.precision("base_net_amount"))
|
flt(base_amount, item.precision("base_net_amount"))
|
||||||
@ -1436,9 +1426,9 @@ class SalesInvoice(SellingController):
|
|||||||
"account": self.debit_to,
|
"account": self.debit_to,
|
||||||
"party_type": "Customer",
|
"party_type": "Customer",
|
||||||
"party": self.customer,
|
"party": self.customer,
|
||||||
"against_type": "Account",
|
"against": "Expense account - "
|
||||||
"against": self.loyalty_redemption_account,
|
+ cstr(self.loyalty_redemption_account)
|
||||||
"against_link": self.loyalty_redemption_account,
|
+ " for the Loyalty Program",
|
||||||
"credit": self.loyalty_amount,
|
"credit": self.loyalty_amount,
|
||||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||||
"against_voucher_type": self.doctype,
|
"against_voucher_type": self.doctype,
|
||||||
@ -1452,9 +1442,7 @@ class SalesInvoice(SellingController):
|
|||||||
{
|
{
|
||||||
"account": self.loyalty_redemption_account,
|
"account": self.loyalty_redemption_account,
|
||||||
"cost_center": self.cost_center or self.loyalty_redemption_cost_center,
|
"cost_center": self.cost_center or self.loyalty_redemption_cost_center,
|
||||||
"against_type": "Customer",
|
|
||||||
"against": self.customer,
|
"against": self.customer,
|
||||||
"against_link": self.customer,
|
|
||||||
"debit": self.loyalty_amount,
|
"debit": self.loyalty_amount,
|
||||||
"remark": "Loyalty Points redeemed by the customer",
|
"remark": "Loyalty Points redeemed by the customer",
|
||||||
},
|
},
|
||||||
@ -1481,9 +1469,7 @@ class SalesInvoice(SellingController):
|
|||||||
"account": self.debit_to,
|
"account": self.debit_to,
|
||||||
"party_type": "Customer",
|
"party_type": "Customer",
|
||||||
"party": self.customer,
|
"party": self.customer,
|
||||||
"against_type": "Account",
|
|
||||||
"against": payment_mode.account,
|
"against": payment_mode.account,
|
||||||
"against_link": payment_mode.account,
|
|
||||||
"credit": payment_mode.base_amount,
|
"credit": payment_mode.base_amount,
|
||||||
"credit_in_account_currency": payment_mode.base_amount
|
"credit_in_account_currency": payment_mode.base_amount
|
||||||
if self.party_account_currency == self.company_currency
|
if self.party_account_currency == self.company_currency
|
||||||
@ -1504,9 +1490,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": payment_mode.account,
|
"account": payment_mode.account,
|
||||||
"against_type": "Customer",
|
|
||||||
"against": self.customer,
|
"against": self.customer,
|
||||||
"against_link": self.customer,
|
|
||||||
"debit": payment_mode.base_amount,
|
"debit": payment_mode.base_amount,
|
||||||
"debit_in_account_currency": payment_mode.base_amount
|
"debit_in_account_currency": payment_mode.base_amount
|
||||||
if payment_mode_account_currency == self.company_currency
|
if payment_mode_account_currency == self.company_currency
|
||||||
@ -1530,9 +1514,7 @@ class SalesInvoice(SellingController):
|
|||||||
"account": self.debit_to,
|
"account": self.debit_to,
|
||||||
"party_type": "Customer",
|
"party_type": "Customer",
|
||||||
"party": self.customer,
|
"party": self.customer,
|
||||||
"against_type": "Account",
|
|
||||||
"against": self.account_for_change_amount,
|
"against": self.account_for_change_amount,
|
||||||
"against_link": self.account_for_change_amount,
|
|
||||||
"debit": flt(self.base_change_amount),
|
"debit": flt(self.base_change_amount),
|
||||||
"debit_in_account_currency": flt(self.base_change_amount)
|
"debit_in_account_currency": flt(self.base_change_amount)
|
||||||
if self.party_account_currency == self.company_currency
|
if self.party_account_currency == self.company_currency
|
||||||
@ -1553,9 +1535,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": self.account_for_change_amount,
|
"account": self.account_for_change_amount,
|
||||||
"against_type": "Customer",
|
|
||||||
"against": self.customer,
|
"against": self.customer,
|
||||||
"against_link": self.customer,
|
|
||||||
"credit": self.base_change_amount,
|
"credit": self.base_change_amount,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
},
|
},
|
||||||
@ -1581,9 +1561,7 @@ class SalesInvoice(SellingController):
|
|||||||
"account": self.debit_to,
|
"account": self.debit_to,
|
||||||
"party_type": "Customer",
|
"party_type": "Customer",
|
||||||
"party": self.customer,
|
"party": self.customer,
|
||||||
"against_type": "Account",
|
|
||||||
"against": self.write_off_account,
|
"against": self.write_off_account,
|
||||||
"against_link": self.write_off_account,
|
|
||||||
"credit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")),
|
"credit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")),
|
||||||
"credit_in_account_currency": (
|
"credit_in_account_currency": (
|
||||||
flt(self.base_write_off_amount, self.precision("base_write_off_amount"))
|
flt(self.base_write_off_amount, self.precision("base_write_off_amount"))
|
||||||
@ -1603,9 +1581,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": self.write_off_account,
|
"account": self.write_off_account,
|
||||||
"against_type": "Customer",
|
|
||||||
"against": self.customer,
|
"against": self.customer,
|
||||||
"against_link": self.customer,
|
|
||||||
"debit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")),
|
"debit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")),
|
||||||
"debit_in_account_currency": (
|
"debit_in_account_currency": (
|
||||||
flt(self.base_write_off_amount, self.precision("base_write_off_amount"))
|
flt(self.base_write_off_amount, self.precision("base_write_off_amount"))
|
||||||
@ -1633,9 +1609,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": round_off_account,
|
"account": round_off_account,
|
||||||
"against_type": "Customer",
|
|
||||||
"against": self.customer,
|
"against": self.customer,
|
||||||
"against_link": self.customer,
|
|
||||||
"credit_in_account_currency": flt(
|
"credit_in_account_currency": flt(
|
||||||
self.rounding_adjustment, self.precision("rounding_adjustment")
|
self.rounding_adjustment, self.precision("rounding_adjustment")
|
||||||
),
|
),
|
||||||
|
|||||||
@ -108,7 +108,7 @@
|
|||||||
"fieldname": "rate",
|
"fieldname": "rate",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Rate",
|
"label": "Tax Rate",
|
||||||
"oldfieldname": "rate",
|
"oldfieldname": "rate",
|
||||||
"oldfieldtype": "Currency"
|
"oldfieldtype": "Currency"
|
||||||
},
|
},
|
||||||
@ -218,7 +218,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-10-17 13:08:17.776528",
|
"modified": "2022-10-18 13:08:17.776528",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Taxes and Charges",
|
"name": "Sales Taxes and Charges",
|
||||||
@ -227,4 +227,4 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"states": []
|
"states": []
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,7 +51,7 @@
|
|||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid\nCompleted",
|
"options": "\nTrialing\nActive\nPast Due Date\nCancelled\nUnpaid\nCompleted",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -267,7 +267,7 @@
|
|||||||
"link_fieldname": "subscription"
|
"link_fieldname": "subscription"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2023-12-28 17:20:42.687789",
|
"modified": "2024-01-24 02:20:26.145996",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Subscription",
|
"name": "Subscription",
|
||||||
|
|||||||
@ -16,6 +16,7 @@ from frappe.utils.data import (
|
|||||||
date_diff,
|
date_diff,
|
||||||
flt,
|
flt,
|
||||||
get_last_day,
|
get_last_day,
|
||||||
|
get_link_to_form,
|
||||||
getdate,
|
getdate,
|
||||||
nowdate,
|
nowdate,
|
||||||
)
|
)
|
||||||
@ -77,9 +78,7 @@ class Subscription(Document):
|
|||||||
purchase_tax_template: DF.Link | None
|
purchase_tax_template: DF.Link | None
|
||||||
sales_tax_template: DF.Link | None
|
sales_tax_template: DF.Link | None
|
||||||
start_date: DF.Date | None
|
start_date: DF.Date | None
|
||||||
status: DF.Literal[
|
status: DF.Literal["", "Trialing", "Active", "Past Due Date", "Cancelled", "Unpaid", "Completed"]
|
||||||
"", "Trialling", "Active", "Past Due Date", "Cancelled", "Unpaid", "Completed"
|
|
||||||
]
|
|
||||||
submit_invoice: DF.Check
|
submit_invoice: DF.Check
|
||||||
trial_period_end: DF.Date | None
|
trial_period_end: DF.Date | None
|
||||||
trial_period_start: DF.Date | None
|
trial_period_start: DF.Date | None
|
||||||
@ -232,7 +231,7 @@ class Subscription(Document):
|
|||||||
Sets the status of the `Subscription`
|
Sets the status of the `Subscription`
|
||||||
"""
|
"""
|
||||||
if self.is_trialling():
|
if self.is_trialling():
|
||||||
self.status = "Trialling"
|
self.status = "Trialing"
|
||||||
elif (
|
elif (
|
||||||
self.status == "Active" and self.end_date and getdate(posting_date) > getdate(self.end_date)
|
self.status == "Active" and self.end_date and getdate(posting_date) > getdate(self.end_date)
|
||||||
):
|
):
|
||||||
@ -317,6 +316,37 @@ class Subscription(Document):
|
|||||||
if self.is_new():
|
if self.is_new():
|
||||||
self.set_subscription_status()
|
self.set_subscription_status()
|
||||||
|
|
||||||
|
self.validate_party_billing_currency()
|
||||||
|
|
||||||
|
def validate_party_billing_currency(self):
|
||||||
|
"""
|
||||||
|
Subscription should be of the same currency as the Party's default billing currency or company default.
|
||||||
|
"""
|
||||||
|
if self.party:
|
||||||
|
party_billing_currency = frappe.get_cached_value(
|
||||||
|
self.party_type, self.party, "default_currency"
|
||||||
|
) or frappe.get_cached_value("Company", self.company, "default_currency")
|
||||||
|
|
||||||
|
plans = [x.plan for x in self.plans]
|
||||||
|
subscription_plan_currencies = frappe.db.get_all(
|
||||||
|
"Subscription Plan", filters={"name": ("in", plans)}, fields=["name", "currency"]
|
||||||
|
)
|
||||||
|
unsupported_plans = []
|
||||||
|
for x in subscription_plan_currencies:
|
||||||
|
if x.currency != party_billing_currency:
|
||||||
|
unsupported_plans.append("{0}".format(get_link_to_form("Subscription Plan", x.name)))
|
||||||
|
|
||||||
|
if unsupported_plans:
|
||||||
|
unsupported_plans = [
|
||||||
|
_(
|
||||||
|
"Below Subscription Plans are of different currency to the party default billing currency/Company currency: {0}"
|
||||||
|
).format(frappe.bold(party_billing_currency))
|
||||||
|
] + unsupported_plans
|
||||||
|
|
||||||
|
frappe.throw(
|
||||||
|
unsupported_plans, frappe.ValidationError, "Unsupported Subscription Plans", as_list=True
|
||||||
|
)
|
||||||
|
|
||||||
def validate_trial_period(self) -> None:
|
def validate_trial_period(self) -> None:
|
||||||
"""
|
"""
|
||||||
Runs sanity checks on trial period dates for the `Subscription`
|
Runs sanity checks on trial period dates for the `Subscription`
|
||||||
@ -563,6 +593,8 @@ class Subscription(Document):
|
|||||||
) and self.can_generate_new_invoice(posting_date):
|
) and self.can_generate_new_invoice(posting_date):
|
||||||
self.generate_invoice(posting_date=posting_date)
|
self.generate_invoice(posting_date=posting_date)
|
||||||
self.update_subscription_period(add_days(self.current_invoice_end, 1))
|
self.update_subscription_period(add_days(self.current_invoice_end, 1))
|
||||||
|
elif posting_date and getdate(posting_date) > getdate(self.current_invoice_end):
|
||||||
|
self.update_subscription_period()
|
||||||
|
|
||||||
if self.cancel_at_period_end and (
|
if self.cancel_at_period_end and (
|
||||||
getdate(posting_date) >= getdate(self.current_invoice_end)
|
getdate(posting_date) >= getdate(self.current_invoice_end)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
frappe.listview_settings['Subscription'] = {
|
frappe.listview_settings['Subscription'] = {
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if(doc.status === 'Trialling') {
|
if(doc.status === 'Trialing') {
|
||||||
return [__("Trialling"), "green"];
|
return [__("Trialing"), "green"];
|
||||||
} else if(doc.status === 'Active') {
|
} else if(doc.status === 'Active') {
|
||||||
return [__("Active"), "green"];
|
return [__("Active"), "green"];
|
||||||
} else if(doc.status === 'Completed') {
|
} else if(doc.status === 'Completed') {
|
||||||
|
|||||||
@ -46,7 +46,7 @@ class TestSubscription(FrappeTestCase):
|
|||||||
get_date_str(subscription.current_invoice_end),
|
get_date_str(subscription.current_invoice_end),
|
||||||
)
|
)
|
||||||
self.assertEqual(subscription.invoices, [])
|
self.assertEqual(subscription.invoices, [])
|
||||||
self.assertEqual(subscription.status, "Trialling")
|
self.assertEqual(subscription.status, "Trialing")
|
||||||
|
|
||||||
def test_create_subscription_without_trial_with_correct_period(self):
|
def test_create_subscription_without_trial_with_correct_period(self):
|
||||||
subscription = create_subscription()
|
subscription = create_subscription()
|
||||||
@ -460,11 +460,13 @@ class TestSubscription(FrappeTestCase):
|
|||||||
self.assertEqual(len(subscription.invoices), 1)
|
self.assertEqual(len(subscription.invoices), 1)
|
||||||
|
|
||||||
def test_multi_currency_subscription(self):
|
def test_multi_currency_subscription(self):
|
||||||
|
party = "_Test Subscription Customer"
|
||||||
|
frappe.db.set_value("Customer", party, "default_currency", "USD")
|
||||||
subscription = create_subscription(
|
subscription = create_subscription(
|
||||||
start_date="2018-01-01",
|
start_date="2018-01-01",
|
||||||
generate_invoice_at="Beginning of the current subscription period",
|
generate_invoice_at="Beginning of the current subscription period",
|
||||||
plans=[{"plan": "_Test Plan Multicurrency", "qty": 1}],
|
plans=[{"plan": "_Test Plan Multicurrency", "qty": 1, "currency": "USD"}],
|
||||||
party="_Test Subscription Customer",
|
party=party,
|
||||||
)
|
)
|
||||||
|
|
||||||
subscription.process()
|
subscription.process()
|
||||||
@ -528,13 +530,21 @@ class TestSubscription(FrappeTestCase):
|
|||||||
|
|
||||||
|
|
||||||
def make_plans():
|
def make_plans():
|
||||||
create_plan(plan_name="_Test Plan Name", cost=900)
|
create_plan(plan_name="_Test Plan Name", cost=900, currency="INR")
|
||||||
create_plan(plan_name="_Test Plan Name 2", cost=1999)
|
create_plan(plan_name="_Test Plan Name 2", cost=1999, currency="INR")
|
||||||
create_plan(
|
create_plan(
|
||||||
plan_name="_Test Plan Name 3", cost=1999, billing_interval="Day", billing_interval_count=14
|
plan_name="_Test Plan Name 3",
|
||||||
|
cost=1999,
|
||||||
|
billing_interval="Day",
|
||||||
|
billing_interval_count=14,
|
||||||
|
currency="INR",
|
||||||
)
|
)
|
||||||
create_plan(
|
create_plan(
|
||||||
plan_name="_Test Plan Name 4", cost=20000, billing_interval="Month", billing_interval_count=3
|
plan_name="_Test Plan Name 4",
|
||||||
|
cost=20000,
|
||||||
|
billing_interval="Month",
|
||||||
|
billing_interval_count=3,
|
||||||
|
currency="INR",
|
||||||
)
|
)
|
||||||
create_plan(
|
create_plan(
|
||||||
plan_name="_Test Plan Multicurrency", cost=50, billing_interval="Month", currency="USD"
|
plan_name="_Test Plan Multicurrency", cost=50, billing_interval="Month", currency="USD"
|
||||||
|
|||||||
@ -41,7 +41,8 @@
|
|||||||
"fieldname": "currency",
|
"fieldname": "currency",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Currency",
|
"label": "Currency",
|
||||||
"options": "Currency"
|
"options": "Currency",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
@ -148,10 +149,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-12-10 15:24:15.794477",
|
"modified": "2024-01-14 17:59:34.687977",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Subscription Plan",
|
"name": "Subscription Plan",
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@ -193,5 +195,6 @@
|
|||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ class SubscriptionPlan(Document):
|
|||||||
billing_interval_count: DF.Int
|
billing_interval_count: DF.Int
|
||||||
cost: DF.Currency
|
cost: DF.Currency
|
||||||
cost_center: DF.Link | None
|
cost_center: DF.Link | None
|
||||||
currency: DF.Link | None
|
currency: DF.Link
|
||||||
item: DF.Link
|
item: DF.Link
|
||||||
payment_gateway: DF.Link | None
|
payment_gateway: DF.Link | None
|
||||||
plan_name: DF.Data
|
plan_name: DF.Data
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
"doctype": "Form Tour",
|
"doctype": "Form Tour",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"modified": "2021-06-29 17:00:26.145996",
|
"modified": "2024-01-24 02:20:26.145996",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounts Settings",
|
"name": "Accounts Settings",
|
||||||
@ -82,7 +82,7 @@
|
|||||||
"label": "Accounts Frozen Till Date",
|
"label": "Accounts Frozen Till Date",
|
||||||
"parent_field": "",
|
"parent_field": "",
|
||||||
"position": "Right",
|
"position": "Right",
|
||||||
"title": "Accounts Frozen Upto"
|
"title": "Accounts Frozen Up To"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Users with this Role are allowed to set frozen accounts and create/modify accounting entries against frozen accounts.",
|
"description": "Users with this Role are allowed to set frozen accounts and create/modify accounting entries against frozen accounts.",
|
||||||
|
|||||||
@ -280,7 +280,6 @@ def check_if_in_list(gle, gl_map, dimensions=None):
|
|||||||
"project",
|
"project",
|
||||||
"finance_book",
|
"finance_book",
|
||||||
"voucher_no",
|
"voucher_no",
|
||||||
"against_link",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if dimensions:
|
if dimensions:
|
||||||
|
|||||||
@ -39,7 +39,7 @@ frappe.query_reports["Account Balance"] = {
|
|||||||
{ "value": "Asset Received But Not Billed", "label": __("Asset Received But Not Billed") },
|
{ "value": "Asset Received But Not Billed", "label": __("Asset Received But Not Billed") },
|
||||||
{ "value": "Bank", "label": __("Bank") },
|
{ "value": "Bank", "label": __("Bank") },
|
||||||
{ "value": "Cash", "label": __("Cash") },
|
{ "value": "Cash", "label": __("Cash") },
|
||||||
{ "value": "Chargeble", "label": __("Chargeble") },
|
{ "value": "Chargeable", "label": __("Chargeable") },
|
||||||
{ "value": "Capital Work in Progress", "label": __("Capital Work in Progress") },
|
{ "value": "Capital Work in Progress", "label": __("Capital Work in Progress") },
|
||||||
{ "value": "Cost of Goods Sold", "label": __("Cost of Goods Sold") },
|
{ "value": "Cost of Goods Sold", "label": __("Cost of Goods Sold") },
|
||||||
{ "value": "Depreciation", "label": __("Depreciation") },
|
{ "value": "Depreciation", "label": __("Depreciation") },
|
||||||
|
|||||||
@ -22,7 +22,7 @@ def get_columns(filters):
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"fieldname": "account",
|
"fieldname": "account",
|
||||||
"options": "Account",
|
"options": "Account",
|
||||||
"width": 100,
|
"width": 200,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Currency"),
|
"label": _("Currency"),
|
||||||
@ -30,7 +30,7 @@ def get_columns(filters):
|
|||||||
"fieldname": "currency",
|
"fieldname": "currency",
|
||||||
"options": "Currency",
|
"options": "Currency",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"width": 50,
|
"width": 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Balance"),
|
"label": _("Balance"),
|
||||||
|
|||||||
@ -10,10 +10,8 @@
|
|||||||
|
|
||||||
<h2 class="text-center" style="margin-top:0">{%= __(report.report_name) %}</h2>
|
<h2 class="text-center" style="margin-top:0">{%= __(report.report_name) %}</h2>
|
||||||
<h4 class="text-center">
|
<h4 class="text-center">
|
||||||
{% if (filters.customer_name) { %}
|
{% if (filters.party) { %}
|
||||||
{%= filters.customer_name %}
|
{%= __(filters.party) %}
|
||||||
{% } else { %}
|
|
||||||
{%= filters.customer || filters.supplier %}
|
|
||||||
{% } %}
|
{% } %}
|
||||||
</h4>
|
</h4>
|
||||||
<h6 class="text-center">
|
<h6 class="text-center">
|
||||||
@ -141,7 +139,7 @@
|
|||||||
<th style="width: 24%">{%= __("Reference") %}</th>
|
<th style="width: 24%">{%= __("Reference") %}</th>
|
||||||
{% } %}
|
{% } %}
|
||||||
{% if(!filters.show_future_payments) { %}
|
{% if(!filters.show_future_payments) { %}
|
||||||
<th style="width: 20%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
|
<th style="width: 20%">{%= (filters.party) ? __("Remarks"): __("Party") %}</th>
|
||||||
{% } %}
|
{% } %}
|
||||||
<th style="width: 10%; text-align: right">{%= __("Invoiced Amount") %}</th>
|
<th style="width: 10%; text-align: right">{%= __("Invoiced Amount") %}</th>
|
||||||
{% if(!filters.show_future_payments) { %}
|
{% if(!filters.show_future_payments) { %}
|
||||||
@ -158,7 +156,7 @@
|
|||||||
<th style="width: 10%">{%= __("Remaining Balance") %}</th>
|
<th style="width: 10%">{%= __("Remaining Balance") %}</th>
|
||||||
{% } %}
|
{% } %}
|
||||||
{% } else { %}
|
{% } else { %}
|
||||||
<th style="width: 40%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
|
<th style="width: 40%">{%= (filters.party) ? __("Remarks"): __("Party") %}</th>
|
||||||
<th style="width: 15%">{%= __("Total Invoiced Amount") %}</th>
|
<th style="width: 15%">{%= __("Total Invoiced Amount") %}</th>
|
||||||
<th style="width: 15%">{%= __("Total Paid Amount") %}</th>
|
<th style="width: 15%">{%= __("Total Paid Amount") %}</th>
|
||||||
<th style="width: 15%">{%= report.report_name === "Accounts Receivable Summary" ? __('Credit Note Amount') : __('Debit Note Amount') %}</th>
|
<th style="width: 15%">{%= report.report_name === "Accounts Receivable Summary" ? __('Credit Note Amount') : __('Debit Note Amount') %}</th>
|
||||||
@ -187,7 +185,7 @@
|
|||||||
|
|
||||||
{% if(!filters.show_future_payments) { %}
|
{% if(!filters.show_future_payments) { %}
|
||||||
<td>
|
<td>
|
||||||
{% if(!(filters.customer || filters.supplier)) { %}
|
{% if(!(filters.party)) { %}
|
||||||
{%= data[i]["party"] %}
|
{%= data[i]["party"] %}
|
||||||
{% if(data[i]["customer_name"] && data[i]["customer_name"] != data[i]["party"]) { %}
|
{% if(data[i]["customer_name"] && data[i]["customer_name"] != data[i]["party"]) { %}
|
||||||
<br> {%= data[i]["customer_name"] %}
|
<br> {%= data[i]["customer_name"] %}
|
||||||
@ -260,7 +258,7 @@
|
|||||||
{% if(data[i]["party"]|| " ") { %}
|
{% if(data[i]["party"]|| " ") { %}
|
||||||
{% if(!data[i]["is_total_row"]) { %}
|
{% if(!data[i]["is_total_row"]) { %}
|
||||||
<td>
|
<td>
|
||||||
{% if(!(filters.customer || filters.supplier)) { %}
|
{% if(!(filters.party)) { %}
|
||||||
{%= data[i]["party"] %}
|
{%= data[i]["party"] %}
|
||||||
{% if(data[i]["customer_name"] && data[i]["customer_name"] != data[i]["party"]) { %}
|
{% if(data[i]["customer_name"] && data[i]["customer_name"] != data[i]["party"]) { %}
|
||||||
<br> {%= data[i]["customer_name"] %}
|
<br> {%= data[i]["customer_name"] %}
|
||||||
|
|||||||
@ -124,11 +124,11 @@ def get_provisional_profit_loss(
|
|||||||
key = period if consolidated else period.key
|
key = period if consolidated else period.key
|
||||||
effective_liability = 0.0
|
effective_liability = 0.0
|
||||||
if liability:
|
if liability:
|
||||||
effective_liability += flt(liability[-2].get(key))
|
effective_liability += flt(liability[0].get(key))
|
||||||
if equity:
|
if equity:
|
||||||
effective_liability += flt(equity[-2].get(key))
|
effective_liability += flt(equity[0].get(key))
|
||||||
|
|
||||||
provisional_profit_loss[key] = flt(asset[-2].get(key)) - effective_liability
|
provisional_profit_loss[key] = flt(asset[0].get(key)) - effective_liability
|
||||||
total_row[key] = effective_liability + provisional_profit_loss[key]
|
total_row[key] = effective_liability + provisional_profit_loss[key]
|
||||||
|
|
||||||
if provisional_profit_loss[key]:
|
if provisional_profit_loss[key]:
|
||||||
@ -193,11 +193,11 @@ def get_report_summary(
|
|||||||
for period in period_list:
|
for period in period_list:
|
||||||
key = period if consolidated else period.key
|
key = period if consolidated else period.key
|
||||||
if asset:
|
if asset:
|
||||||
net_asset += asset[-2].get(key)
|
net_asset += asset[0].get(key)
|
||||||
if liability:
|
if liability:
|
||||||
net_liability += liability[-2].get(key)
|
net_liability += liability[0].get(key)
|
||||||
if equity:
|
if equity:
|
||||||
net_equity += equity[-2].get(key)
|
net_equity += equity[0].get(key)
|
||||||
if provisional_profit_loss:
|
if provisional_profit_loss:
|
||||||
net_provisional_profit_loss += provisional_profit_loss.get(key)
|
net_provisional_profit_loss += provisional_profit_loss.get(key)
|
||||||
|
|
||||||
|
|||||||
@ -3,49 +3,135 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.tests.utils import FrappeTestCase
|
from frappe.tests.utils import FrappeTestCase
|
||||||
from frappe.utils import today
|
from frappe.utils.data import today
|
||||||
|
|
||||||
from erpnext.accounts.report.balance_sheet.balance_sheet import execute
|
from erpnext.accounts.report.balance_sheet.balance_sheet import execute
|
||||||
|
|
||||||
|
COMPANY = "_Test Company 6"
|
||||||
|
COMPANY_SHORT_NAME = "_TC6"
|
||||||
|
|
||||||
|
test_dependencies = ["Company"]
|
||||||
|
|
||||||
|
|
||||||
class TestBalanceSheet(FrappeTestCase):
|
class TestBalanceSheet(FrappeTestCase):
|
||||||
def test_balance_sheet(self):
|
def test_balance_sheet(self):
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
frappe.db.sql(f"delete from `tabJournal Entry` where company='{COMPANY}'")
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import (
|
frappe.db.sql(f"delete from `tabGL Entry` where company='{COMPANY}'")
|
||||||
create_sales_invoice,
|
|
||||||
make_sales_invoice,
|
|
||||||
)
|
|
||||||
from erpnext.accounts.utils import get_fiscal_year
|
|
||||||
|
|
||||||
frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company 6'")
|
create_account("VAT Liabilities", f"Duties and Taxes - {COMPANY_SHORT_NAME}", COMPANY)
|
||||||
frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company 6'")
|
create_account("Advance VAT Paid", f"Duties and Taxes - {COMPANY_SHORT_NAME}", COMPANY)
|
||||||
frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 6'")
|
create_account("My Bank", f"Bank Accounts - {COMPANY_SHORT_NAME}", COMPANY)
|
||||||
|
|
||||||
pi = make_purchase_invoice(
|
# 1000 equity paid to bank account
|
||||||
company="_Test Company 6",
|
make_journal_entry(
|
||||||
warehouse="Finished Goods - _TC6",
|
[
|
||||||
expense_account="Cost of Goods Sold - _TC6",
|
dict(
|
||||||
cost_center="Main - _TC6",
|
account_name="My Bank",
|
||||||
qty=10,
|
debit_in_account_currency=1000,
|
||||||
rate=100,
|
credit_in_account_currency=0,
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
account_name="Capital Stock",
|
||||||
|
debit_in_account_currency=0,
|
||||||
|
credit_in_account_currency=1000,
|
||||||
|
),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
si = create_sales_invoice(
|
|
||||||
company="_Test Company 6",
|
# 110 income paid to bank account (100 revenue + 10 VAT)
|
||||||
debit_to="Debtors - _TC6",
|
make_journal_entry(
|
||||||
income_account="Sales - _TC6",
|
[
|
||||||
cost_center="Main - _TC6",
|
dict(
|
||||||
qty=5,
|
account_name="My Bank",
|
||||||
rate=110,
|
debit_in_account_currency=110,
|
||||||
|
credit_in_account_currency=0,
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
account_name="Sales",
|
||||||
|
debit_in_account_currency=0,
|
||||||
|
credit_in_account_currency=100,
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
account_name="VAT Liabilities",
|
||||||
|
debit_in_account_currency=0,
|
||||||
|
credit_in_account_currency=10,
|
||||||
|
),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# offset VAT Liabilities with intra-year advance payment
|
||||||
|
make_journal_entry(
|
||||||
|
[
|
||||||
|
dict(
|
||||||
|
account_name="My Bank",
|
||||||
|
debit_in_account_currency=0,
|
||||||
|
credit_in_account_currency=10,
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
account_name="Advance VAT Paid",
|
||||||
|
debit_in_account_currency=10,
|
||||||
|
credit_in_account_currency=0,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
filters = frappe._dict(
|
filters = frappe._dict(
|
||||||
company="_Test Company 6",
|
company=COMPANY,
|
||||||
period_start_date=today(),
|
period_start_date=today(),
|
||||||
period_end_date=today(),
|
period_end_date=today(),
|
||||||
periodicity="Yearly",
|
periodicity="Yearly",
|
||||||
)
|
)
|
||||||
result = execute(filters)[1]
|
results = execute(filters)
|
||||||
for account_dict in result:
|
name_and_total = {
|
||||||
if account_dict.get("account") == "Current Liabilities - _TC6":
|
account_dict["account_name"]: account_dict["total"]
|
||||||
self.assertEqual(account_dict.total, 1000)
|
for account_dict in results[1]
|
||||||
if account_dict.get("account") == "Current Assets - _TC6":
|
if "total" in account_dict and "account_name" in account_dict
|
||||||
self.assertEqual(account_dict.total, 550)
|
}
|
||||||
|
|
||||||
|
self.assertNotIn("Sales", name_and_total)
|
||||||
|
|
||||||
|
self.assertIn("My Bank", name_and_total)
|
||||||
|
self.assertEqual(name_and_total["My Bank"], 1100)
|
||||||
|
|
||||||
|
self.assertIn("VAT Liabilities", name_and_total)
|
||||||
|
self.assertEqual(name_and_total["VAT Liabilities"], 10)
|
||||||
|
|
||||||
|
self.assertIn("Advance VAT Paid", name_and_total)
|
||||||
|
self.assertEqual(name_and_total["Advance VAT Paid"], -10)
|
||||||
|
|
||||||
|
self.assertIn("Duties and Taxes", name_and_total)
|
||||||
|
self.assertEqual(name_and_total["Duties and Taxes"], 0)
|
||||||
|
|
||||||
|
self.assertIn("Application of Funds (Assets)", name_and_total)
|
||||||
|
self.assertEqual(name_and_total["Application of Funds (Assets)"], 1100)
|
||||||
|
|
||||||
|
self.assertIn("Equity", name_and_total)
|
||||||
|
self.assertEqual(name_and_total["Equity"], 1000)
|
||||||
|
|
||||||
|
self.assertIn("'Provisional Profit / Loss (Credit)'", name_and_total)
|
||||||
|
self.assertEqual(name_and_total["'Provisional Profit / Loss (Credit)'"], 100)
|
||||||
|
|
||||||
|
|
||||||
|
def make_journal_entry(rows):
|
||||||
|
jv = frappe.new_doc("Journal Entry")
|
||||||
|
jv.posting_date = today()
|
||||||
|
jv.company = COMPANY
|
||||||
|
jv.user_remark = "test"
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
row["account"] = row.pop("account_name") + " - " + COMPANY_SHORT_NAME
|
||||||
|
jv.append("accounts", row)
|
||||||
|
|
||||||
|
jv.insert()
|
||||||
|
jv.submit()
|
||||||
|
|
||||||
|
|
||||||
|
def create_account(account_name: str, parent_account: str, company: str):
|
||||||
|
if frappe.db.exists("Account", {"account_name": account_name, "company": company}):
|
||||||
|
return
|
||||||
|
|
||||||
|
acc = frappe.new_doc("Account")
|
||||||
|
acc.account_name = account_name
|
||||||
|
acc.company = COMPANY
|
||||||
|
acc.parent_account = parent_account
|
||||||
|
acc.insert()
|
||||||
|
|||||||
@ -84,10 +84,6 @@ function get_filters() {
|
|||||||
options: budget_against_options,
|
options: budget_against_options,
|
||||||
default: "Cost Center",
|
default: "Cost Center",
|
||||||
reqd: 1,
|
reqd: 1,
|
||||||
get_data: function() {
|
|
||||||
console.log(this.options);
|
|
||||||
return ["Emacs", "Rocks"];
|
|
||||||
},
|
|
||||||
on_change: function() {
|
on_change: function() {
|
||||||
frappe.query_report.set_filter_value("budget_against_filter", []);
|
frappe.query_report.set_filter_value("budget_against_filter", []);
|
||||||
frappe.query_report.refresh();
|
frappe.query_report.refresh();
|
||||||
|
|||||||
@ -376,6 +376,10 @@ class PartyLedgerSummaryReport(object):
|
|||||||
if not income_or_expense_accounts:
|
if not income_or_expense_accounts:
|
||||||
# prevent empty 'in' condition
|
# prevent empty 'in' condition
|
||||||
income_or_expense_accounts.append("")
|
income_or_expense_accounts.append("")
|
||||||
|
else:
|
||||||
|
# escape '%' in account name
|
||||||
|
# ignoring frappe.db.escape as it replaces single quotes with double quotes
|
||||||
|
income_or_expense_accounts = [x.replace("%", "%%") for x in income_or_expense_accounts]
|
||||||
|
|
||||||
accounts_query = (
|
accounts_query = (
|
||||||
qb.from_(gl)
|
qb.from_(gl)
|
||||||
|
|||||||
@ -8,17 +8,7 @@ import re
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import (
|
from frappe.utils import add_days, add_months, cint, cstr, flt, formatdate, get_first_day, getdate
|
||||||
add_days,
|
|
||||||
add_months,
|
|
||||||
cint,
|
|
||||||
cstr,
|
|
||||||
flt,
|
|
||||||
formatdate,
|
|
||||||
get_first_day,
|
|
||||||
getdate,
|
|
||||||
today,
|
|
||||||
)
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||||
get_accounting_dimensions,
|
get_accounting_dimensions,
|
||||||
@ -53,8 +43,6 @@ def get_period_list(
|
|||||||
year_start_date = getdate(period_start_date)
|
year_start_date = getdate(period_start_date)
|
||||||
year_end_date = getdate(period_end_date)
|
year_end_date = getdate(period_end_date)
|
||||||
|
|
||||||
year_end_date = getdate(today()) if year_end_date > getdate(today()) else year_end_date
|
|
||||||
|
|
||||||
months_to_add = {"Yearly": 12, "Half-Yearly": 6, "Quarterly": 3, "Monthly": 1}[periodicity]
|
months_to_add = {"Yearly": 12, "Half-Yearly": 6, "Quarterly": 3, "Monthly": 1}[periodicity]
|
||||||
|
|
||||||
period_list = []
|
period_list = []
|
||||||
|
|||||||
@ -203,7 +203,7 @@ def get_gl_entries(filters, accounting_dimensions):
|
|||||||
voucher_type, voucher_subtype, voucher_no, {dimension_fields}
|
voucher_type, voucher_subtype, voucher_no, {dimension_fields}
|
||||||
cost_center, project, {transaction_currency_fields}
|
cost_center, project, {transaction_currency_fields}
|
||||||
against_voucher_type, against_voucher, account_currency,
|
against_voucher_type, against_voucher, account_currency,
|
||||||
against_link, against, is_opening, creation {select_fields}
|
against, is_opening, creation {select_fields}
|
||||||
from `tabGL Entry`
|
from `tabGL Entry`
|
||||||
where company=%(company)s {conditions}
|
where company=%(company)s {conditions}
|
||||||
{order_by_statement}
|
{order_by_statement}
|
||||||
@ -398,7 +398,6 @@ def initialize_gle_map(gl_entries, filters):
|
|||||||
group_by = group_by_field(filters.get("group_by"))
|
group_by = group_by_field(filters.get("group_by"))
|
||||||
|
|
||||||
for gle in gl_entries:
|
for gle in gl_entries:
|
||||||
gle.against = gle.get("against_link") or gle.get("against")
|
|
||||||
gle_map.setdefault(gle.get(group_by), _dict(totals=get_totals_dict(), entries=[]))
|
gle_map.setdefault(gle.get(group_by), _dict(totals=get_totals_dict(), entries=[]))
|
||||||
return gle_map
|
return gle_map
|
||||||
|
|
||||||
@ -449,6 +448,10 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map):
|
|||||||
for gle in gl_entries:
|
for gle in gl_entries:
|
||||||
group_by_value = gle.get(group_by)
|
group_by_value = gle.get(group_by)
|
||||||
gle.voucher_type = _(gle.voucher_type)
|
gle.voucher_type = _(gle.voucher_type)
|
||||||
|
gle.voucher_subtype = _(gle.voucher_subtype)
|
||||||
|
gle.against_voucher_type = _(gle.against_voucher_type)
|
||||||
|
gle.remarks = _(gle.remarks)
|
||||||
|
gle.party_type = _(gle.party_type)
|
||||||
|
|
||||||
if gle.posting_date < from_date or (cstr(gle.is_opening) == "Yes" and not show_opening_entries):
|
if gle.posting_date < from_date or (cstr(gle.is_opening) == "Yes" and not show_opening_entries):
|
||||||
if not group_by_voucher_consolidated:
|
if not group_by_voucher_consolidated:
|
||||||
|
|||||||
@ -134,7 +134,7 @@ def get_revenue(data, period_list, include_in_gross=1):
|
|||||||
|
|
||||||
def remove_parent_with_no_child(data):
|
def remove_parent_with_no_child(data):
|
||||||
data_to_be_removed = False
|
data_to_be_removed = False
|
||||||
for parent in data:
|
for parent in list(data):
|
||||||
if "is_group" in parent and parent.get("is_group") == 1:
|
if "is_group" in parent and parent.get("is_group") == 1:
|
||||||
have_child = False
|
have_child = False
|
||||||
for child in data:
|
for child in data:
|
||||||
|
|||||||
@ -59,7 +59,21 @@ frappe.query_reports["Item-wise Sales Register"] = {
|
|||||||
"fieldname": "group_by",
|
"fieldname": "group_by",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"options": ["Customer Group", "Customer", "Item Group", "Item", "Territory", "Invoice"]
|
"options": ["Customer Group", "Customer", "Item Group", "Item", "Territory", "Invoice"]
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "income_account",
|
||||||
|
"label": __("Income Account"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Account",
|
||||||
|
get_query: () => {
|
||||||
|
let company = frappe.query_report.get_filter_value('company');
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
'company': company,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
],
|
],
|
||||||
"formatter": function(value, row, column, data, default_formatter) {
|
"formatter": function(value, row, column, data, default_formatter) {
|
||||||
value = default_formatter(value, row, column, data);
|
value = default_formatter(value, row, column, data);
|
||||||
|
|||||||
@ -83,9 +83,7 @@ def _execute(filters=None, additional_table_columns=None, additional_conditions=
|
|||||||
"company": d.company,
|
"company": d.company,
|
||||||
"sales_order": d.sales_order,
|
"sales_order": d.sales_order,
|
||||||
"delivery_note": d.delivery_note,
|
"delivery_note": d.delivery_note,
|
||||||
"income_account": d.unrealized_profit_loss_account
|
"income_account": get_income_account(d),
|
||||||
if d.is_internal_customer == 1
|
|
||||||
else d.income_account,
|
|
||||||
"cost_center": d.cost_center,
|
"cost_center": d.cost_center,
|
||||||
"stock_qty": d.stock_qty,
|
"stock_qty": d.stock_qty,
|
||||||
"stock_uom": d.stock_uom,
|
"stock_uom": d.stock_uom,
|
||||||
@ -150,6 +148,15 @@ def _execute(filters=None, additional_table_columns=None, additional_conditions=
|
|||||||
return columns, data, None, None, None, skip_total_row
|
return columns, data, None, None, None, skip_total_row
|
||||||
|
|
||||||
|
|
||||||
|
def get_income_account(row):
|
||||||
|
if row.enable_deferred_revenue:
|
||||||
|
return row.deferred_revenue_account
|
||||||
|
elif row.is_internal_customer == 1:
|
||||||
|
return row.unrealized_profit_loss_account
|
||||||
|
else:
|
||||||
|
return row.income_account
|
||||||
|
|
||||||
|
|
||||||
def get_columns(additional_table_columns, filters):
|
def get_columns(additional_table_columns, filters):
|
||||||
columns = []
|
columns = []
|
||||||
|
|
||||||
@ -358,6 +365,13 @@ def get_conditions(filters, additional_conditions=None):
|
|||||||
if filters.get("item_group"):
|
if filters.get("item_group"):
|
||||||
conditions += """and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s"""
|
conditions += """and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s"""
|
||||||
|
|
||||||
|
if filters.get("income_account"):
|
||||||
|
conditions += """
|
||||||
|
and (ifnull(`tabSales Invoice Item`.income_account, '') = %(income_account)s
|
||||||
|
or ifnull(`tabSales Invoice Item`.deferred_revenue_account, '') = %(income_account)s
|
||||||
|
or ifnull(`tabSales Invoice`.unrealized_profit_loss_account, '') = %(income_account)s)
|
||||||
|
"""
|
||||||
|
|
||||||
if not filters.get("group_by"):
|
if not filters.get("group_by"):
|
||||||
conditions += (
|
conditions += (
|
||||||
"ORDER BY `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_group desc"
|
"ORDER BY `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_group desc"
|
||||||
@ -399,6 +413,7 @@ def get_items(filters, additional_query_columns, additional_conditions=None):
|
|||||||
`tabItem`.`item_name` as i_item_name, `tabItem`.`item_group` as i_item_group,
|
`tabItem`.`item_name` as i_item_name, `tabItem`.`item_group` as i_item_group,
|
||||||
`tabSales Invoice Item`.sales_order, `tabSales Invoice Item`.delivery_note,
|
`tabSales Invoice Item`.sales_order, `tabSales Invoice Item`.delivery_note,
|
||||||
`tabSales Invoice Item`.income_account, `tabSales Invoice Item`.cost_center,
|
`tabSales Invoice Item`.income_account, `tabSales Invoice Item`.cost_center,
|
||||||
|
`tabSales Invoice Item`.enable_deferred_revenue, `tabSales Invoice Item`.deferred_revenue_account,
|
||||||
`tabSales Invoice Item`.stock_qty, `tabSales Invoice Item`.stock_uom,
|
`tabSales Invoice Item`.stock_qty, `tabSales Invoice Item`.stock_uom,
|
||||||
`tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount,
|
`tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount,
|
||||||
`tabSales Invoice`.customer_name, `tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail,
|
`tabSales Invoice`.customer_name, `tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail,
|
||||||
|
|||||||
@ -46,12 +46,10 @@ def get_result(
|
|||||||
|
|
||||||
out = []
|
out = []
|
||||||
for name, details in gle_map.items():
|
for name, details in gle_map.items():
|
||||||
tax_amount, total_amount, grand_total, base_total = 0, 0, 0, 0
|
|
||||||
bill_no, bill_date = "", ""
|
|
||||||
tax_withholding_category = tax_category_map.get(name)
|
|
||||||
rate = tax_rate_map.get(tax_withholding_category)
|
|
||||||
|
|
||||||
for entry in details:
|
for entry in details:
|
||||||
|
tax_amount, total_amount, grand_total, base_total = 0, 0, 0, 0
|
||||||
|
tax_withholding_category, rate = None, None
|
||||||
|
bill_no, bill_date = "", ""
|
||||||
party = entry.party or entry.against
|
party = entry.party or entry.against
|
||||||
posting_date = entry.posting_date
|
posting_date = entry.posting_date
|
||||||
voucher_type = entry.voucher_type
|
voucher_type = entry.voucher_type
|
||||||
@ -61,12 +59,19 @@ def get_result(
|
|||||||
if party_list:
|
if party_list:
|
||||||
party = party_list[0]
|
party = party_list[0]
|
||||||
|
|
||||||
if not tax_withholding_category:
|
if entry.account in tds_accounts.keys():
|
||||||
tax_withholding_category = party_map.get(party, {}).get("tax_withholding_category")
|
|
||||||
rate = tax_rate_map.get(tax_withholding_category)
|
|
||||||
|
|
||||||
if entry.account in tds_accounts:
|
|
||||||
tax_amount += entry.credit - entry.debit
|
tax_amount += entry.credit - entry.debit
|
||||||
|
# infer tax withholding category from the account if it's the single account for this category
|
||||||
|
tax_withholding_category = tds_accounts.get(entry.account)
|
||||||
|
rate = tax_rate_map.get(tax_withholding_category)
|
||||||
|
# or else the consolidated value from the voucher document
|
||||||
|
if not tax_withholding_category:
|
||||||
|
# or else from the party default
|
||||||
|
tax_withholding_category = tax_category_map.get(name)
|
||||||
|
rate = tax_rate_map.get(tax_withholding_category)
|
||||||
|
if not tax_withholding_category:
|
||||||
|
tax_withholding_category = party_map.get(party, {}).get("tax_withholding_category")
|
||||||
|
rate = tax_rate_map.get(tax_withholding_category)
|
||||||
|
|
||||||
if net_total_map.get(name):
|
if net_total_map.get(name):
|
||||||
if voucher_type == "Journal Entry" and tax_amount and rate:
|
if voucher_type == "Journal Entry" and tax_amount and rate:
|
||||||
@ -80,41 +85,41 @@ def get_result(
|
|||||||
else:
|
else:
|
||||||
total_amount += entry.credit
|
total_amount += entry.credit
|
||||||
|
|
||||||
if tax_amount:
|
if tax_amount:
|
||||||
if party_map.get(party, {}).get("party_type") == "Supplier":
|
if party_map.get(party, {}).get("party_type") == "Supplier":
|
||||||
party_name = "supplier_name"
|
party_name = "supplier_name"
|
||||||
party_type = "supplier_type"
|
party_type = "supplier_type"
|
||||||
else:
|
else:
|
||||||
party_name = "customer_name"
|
party_name = "customer_name"
|
||||||
party_type = "customer_type"
|
party_type = "customer_type"
|
||||||
|
|
||||||
row = {
|
row = {
|
||||||
"pan"
|
"pan"
|
||||||
if frappe.db.has_column(filters.party_type, "pan")
|
if frappe.db.has_column(filters.party_type, "pan")
|
||||||
else "tax_id": party_map.get(party, {}).get("pan"),
|
else "tax_id": party_map.get(party, {}).get("pan"),
|
||||||
"party": party_map.get(party, {}).get("name"),
|
"party": party_map.get(party, {}).get("name"),
|
||||||
}
|
|
||||||
|
|
||||||
if filters.naming_series == "Naming Series":
|
|
||||||
row.update({"party_name": party_map.get(party, {}).get(party_name)})
|
|
||||||
|
|
||||||
row.update(
|
|
||||||
{
|
|
||||||
"section_code": tax_withholding_category or "",
|
|
||||||
"entity_type": party_map.get(party, {}).get(party_type),
|
|
||||||
"rate": rate,
|
|
||||||
"total_amount": total_amount,
|
|
||||||
"grand_total": grand_total,
|
|
||||||
"base_total": base_total,
|
|
||||||
"tax_amount": tax_amount,
|
|
||||||
"transaction_date": posting_date,
|
|
||||||
"transaction_type": voucher_type,
|
|
||||||
"ref_no": name,
|
|
||||||
"supplier_invoice_no": bill_no,
|
|
||||||
"supplier_invoice_date": bill_date,
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
out.append(row)
|
if filters.naming_series == "Naming Series":
|
||||||
|
row.update({"party_name": party_map.get(party, {}).get(party_name)})
|
||||||
|
|
||||||
|
row.update(
|
||||||
|
{
|
||||||
|
"section_code": tax_withholding_category or "",
|
||||||
|
"entity_type": party_map.get(party, {}).get(party_type),
|
||||||
|
"rate": rate,
|
||||||
|
"total_amount": total_amount,
|
||||||
|
"grand_total": grand_total,
|
||||||
|
"base_total": base_total,
|
||||||
|
"tax_amount": tax_amount,
|
||||||
|
"transaction_date": posting_date,
|
||||||
|
"transaction_type": voucher_type,
|
||||||
|
"ref_no": name,
|
||||||
|
"supplier_invoice_no": bill_no,
|
||||||
|
"supplier_invoice_date": bill_date,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
out.append(row)
|
||||||
|
|
||||||
out.sort(key=lambda x: x["section_code"])
|
out.sort(key=lambda x: x["section_code"])
|
||||||
|
|
||||||
@ -282,11 +287,20 @@ def get_tds_docs(filters):
|
|||||||
journal_entry_party_map = frappe._dict()
|
journal_entry_party_map = frappe._dict()
|
||||||
bank_accounts = frappe.get_all("Account", {"is_group": 0, "account_type": "Bank"}, pluck="name")
|
bank_accounts = frappe.get_all("Account", {"is_group": 0, "account_type": "Bank"}, pluck="name")
|
||||||
|
|
||||||
tds_accounts = frappe.get_all(
|
_tds_accounts = frappe.get_all(
|
||||||
"Tax Withholding Account", {"company": filters.get("company")}, pluck="account"
|
"Tax Withholding Account",
|
||||||
|
{"company": filters.get("company")},
|
||||||
|
["account", "parent"],
|
||||||
)
|
)
|
||||||
|
tds_accounts = {}
|
||||||
|
for tds_acc in _tds_accounts:
|
||||||
|
# if it turns out not to be the only tax withholding category, then don't include in the map
|
||||||
|
if tds_accounts.get(tds_acc["account"]):
|
||||||
|
tds_accounts[tds_acc["account"]] = None
|
||||||
|
else:
|
||||||
|
tds_accounts[tds_acc["account"]] = tds_acc["parent"]
|
||||||
|
|
||||||
tds_docs = get_tds_docs_query(filters, bank_accounts, tds_accounts).run(as_dict=True)
|
tds_docs = get_tds_docs_query(filters, bank_accounts, list(tds_accounts.keys())).run(as_dict=True)
|
||||||
|
|
||||||
for d in tds_docs:
|
for d in tds_docs:
|
||||||
if d.voucher_type == "Purchase Invoice":
|
if d.voucher_type == "Purchase Invoice":
|
||||||
|
|||||||
@ -453,7 +453,19 @@ def add_cc(args=None):
|
|||||||
return cc.name
|
return cc.name
|
||||||
|
|
||||||
|
|
||||||
def reconcile_against_document(args, skip_ref_details_update_for_pe=False): # nosemgrep
|
def _build_dimensions_dict_for_exc_gain_loss(
|
||||||
|
entry: dict | object = None, active_dimensions: list = None
|
||||||
|
):
|
||||||
|
dimensions_dict = frappe._dict()
|
||||||
|
if entry and active_dimensions:
|
||||||
|
for dim in active_dimensions:
|
||||||
|
dimensions_dict[dim.fieldname] = entry.get(dim.fieldname)
|
||||||
|
return dimensions_dict
|
||||||
|
|
||||||
|
|
||||||
|
def reconcile_against_document(
|
||||||
|
args, skip_ref_details_update_for_pe=False, active_dimensions=None
|
||||||
|
): # nosemgrep
|
||||||
"""
|
"""
|
||||||
Cancel PE or JV, Update against document, split if required and resubmit
|
Cancel PE or JV, Update against document, split if required and resubmit
|
||||||
"""
|
"""
|
||||||
@ -482,6 +494,8 @@ def reconcile_against_document(args, skip_ref_details_update_for_pe=False): # n
|
|||||||
check_if_advance_entry_modified(entry)
|
check_if_advance_entry_modified(entry)
|
||||||
validate_allocated_amount(entry)
|
validate_allocated_amount(entry)
|
||||||
|
|
||||||
|
dimensions_dict = _build_dimensions_dict_for_exc_gain_loss(entry, active_dimensions)
|
||||||
|
|
||||||
# update ref in advance entry
|
# update ref in advance entry
|
||||||
if voucher_type == "Journal Entry":
|
if voucher_type == "Journal Entry":
|
||||||
referenced_row = update_reference_in_journal_entry(entry, doc, do_not_save=False)
|
referenced_row = update_reference_in_journal_entry(entry, doc, do_not_save=False)
|
||||||
@ -489,10 +503,14 @@ def reconcile_against_document(args, skip_ref_details_update_for_pe=False): # n
|
|||||||
# amount and account in args
|
# amount and account in args
|
||||||
# referenced_row is used to deduplicate gain/loss journal
|
# referenced_row is used to deduplicate gain/loss journal
|
||||||
entry.update({"referenced_row": referenced_row})
|
entry.update({"referenced_row": referenced_row})
|
||||||
doc.make_exchange_gain_loss_journal([entry])
|
doc.make_exchange_gain_loss_journal([entry], dimensions_dict)
|
||||||
else:
|
else:
|
||||||
referenced_row = update_reference_in_payment_entry(
|
referenced_row = update_reference_in_payment_entry(
|
||||||
entry, doc, do_not_save=True, skip_ref_details_update_for_pe=skip_ref_details_update_for_pe
|
entry,
|
||||||
|
doc,
|
||||||
|
do_not_save=True,
|
||||||
|
skip_ref_details_update_for_pe=skip_ref_details_update_for_pe,
|
||||||
|
dimensions_dict=dimensions_dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
doc.save(ignore_permissions=True)
|
doc.save(ignore_permissions=True)
|
||||||
@ -600,7 +618,10 @@ def update_reference_in_journal_entry(d, journal_entry, do_not_save=False):
|
|||||||
jv_detail = journal_entry.get("accounts", {"name": d["voucher_detail_no"]})[0]
|
jv_detail = journal_entry.get("accounts", {"name": d["voucher_detail_no"]})[0]
|
||||||
|
|
||||||
# Update Advance Paid in SO/PO since they might be getting unlinked
|
# Update Advance Paid in SO/PO since they might be getting unlinked
|
||||||
if jv_detail.get("reference_type") in ("Sales Order", "Purchase Order"):
|
advance_payment_doctypes = frappe.get_hooks(
|
||||||
|
"advance_payment_customer_doctypes"
|
||||||
|
) + frappe.get_hooks("advance_payment_supplier_doctypes")
|
||||||
|
if jv_detail.get("reference_type") in advance_payment_doctypes:
|
||||||
frappe.get_doc(jv_detail.reference_type, jv_detail.reference_name).set_total_advance_paid()
|
frappe.get_doc(jv_detail.reference_type, jv_detail.reference_name).set_total_advance_paid()
|
||||||
|
|
||||||
if flt(d["unadjusted_amount"]) - flt(d["allocated_amount"]) != 0:
|
if flt(d["unadjusted_amount"]) - flt(d["allocated_amount"]) != 0:
|
||||||
@ -642,7 +663,6 @@ def update_reference_in_journal_entry(d, journal_entry, do_not_save=False):
|
|||||||
new_row.set("reference_name", d["against_voucher"])
|
new_row.set("reference_name", d["against_voucher"])
|
||||||
|
|
||||||
new_row.against_account = cstr(jv_detail.against_account)
|
new_row.against_account = cstr(jv_detail.against_account)
|
||||||
new_row.against_account_link = cstr(jv_detail.against_account)
|
|
||||||
new_row.is_advance = cstr(jv_detail.is_advance)
|
new_row.is_advance = cstr(jv_detail.is_advance)
|
||||||
new_row.docstatus = 1
|
new_row.docstatus = 1
|
||||||
|
|
||||||
@ -655,7 +675,7 @@ def update_reference_in_journal_entry(d, journal_entry, do_not_save=False):
|
|||||||
|
|
||||||
|
|
||||||
def update_reference_in_payment_entry(
|
def update_reference_in_payment_entry(
|
||||||
d, payment_entry, do_not_save=False, skip_ref_details_update_for_pe=False
|
d, payment_entry, do_not_save=False, skip_ref_details_update_for_pe=False, dimensions_dict=None
|
||||||
):
|
):
|
||||||
reference_details = {
|
reference_details = {
|
||||||
"reference_doctype": d.against_voucher_type,
|
"reference_doctype": d.against_voucher_type,
|
||||||
@ -668,13 +688,17 @@ def update_reference_in_payment_entry(
|
|||||||
else payment_entry.get_exchange_rate(),
|
else payment_entry.get_exchange_rate(),
|
||||||
"exchange_gain_loss": d.difference_amount,
|
"exchange_gain_loss": d.difference_amount,
|
||||||
"account": d.account,
|
"account": d.account,
|
||||||
|
"dimensions": d.dimensions,
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.voucher_detail_no:
|
if d.voucher_detail_no:
|
||||||
existing_row = payment_entry.get("references", {"name": d["voucher_detail_no"]})[0]
|
existing_row = payment_entry.get("references", {"name": d["voucher_detail_no"]})[0]
|
||||||
|
|
||||||
# Update Advance Paid in SO/PO since they are getting unlinked
|
# Update Advance Paid in SO/PO since they are getting unlinked
|
||||||
if existing_row.get("reference_doctype") in ("Sales Order", "Purchase Order"):
|
advance_payment_doctypes = frappe.get_hooks(
|
||||||
|
"advance_payment_customer_doctypes"
|
||||||
|
) + frappe.get_hooks("advance_payment_supplier_doctypes")
|
||||||
|
if existing_row.get("reference_doctype") in advance_payment_doctypes:
|
||||||
frappe.get_doc(
|
frappe.get_doc(
|
||||||
existing_row.reference_doctype, existing_row.reference_name
|
existing_row.reference_doctype, existing_row.reference_name
|
||||||
).set_total_advance_paid()
|
).set_total_advance_paid()
|
||||||
@ -700,8 +724,9 @@ def update_reference_in_payment_entry(
|
|||||||
if not skip_ref_details_update_for_pe:
|
if not skip_ref_details_update_for_pe:
|
||||||
payment_entry.set_missing_ref_details()
|
payment_entry.set_missing_ref_details()
|
||||||
payment_entry.set_amounts()
|
payment_entry.set_amounts()
|
||||||
|
|
||||||
payment_entry.make_exchange_gain_loss_journal(
|
payment_entry.make_exchange_gain_loss_journal(
|
||||||
frappe._dict({"difference_posting_date": d.difference_posting_date})
|
frappe._dict({"difference_posting_date": d.difference_posting_date}), dimensions_dict
|
||||||
)
|
)
|
||||||
|
|
||||||
if not do_not_save:
|
if not do_not_save:
|
||||||
@ -2043,6 +2068,7 @@ def create_gain_loss_journal(
|
|||||||
ref2_dn,
|
ref2_dn,
|
||||||
ref2_detail_no,
|
ref2_detail_no,
|
||||||
cost_center,
|
cost_center,
|
||||||
|
dimensions,
|
||||||
) -> str:
|
) -> str:
|
||||||
journal_entry = frappe.new_doc("Journal Entry")
|
journal_entry = frappe.new_doc("Journal Entry")
|
||||||
journal_entry.voucher_type = "Exchange Gain Or Loss"
|
journal_entry.voucher_type = "Exchange Gain Or Loss"
|
||||||
@ -2076,7 +2102,8 @@ def create_gain_loss_journal(
|
|||||||
dr_or_cr + "_in_account_currency": 0,
|
dr_or_cr + "_in_account_currency": 0,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
if dimensions:
|
||||||
|
journal_account.update(dimensions)
|
||||||
journal_entry.append("accounts", journal_account)
|
journal_entry.append("accounts", journal_account)
|
||||||
|
|
||||||
journal_account = frappe._dict(
|
journal_account = frappe._dict(
|
||||||
@ -2092,7 +2119,8 @@ def create_gain_loss_journal(
|
|||||||
reverse_dr_or_cr: abs(exc_gain_loss),
|
reverse_dr_or_cr: abs(exc_gain_loss),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
if dimensions:
|
||||||
|
journal_account.update(dimensions)
|
||||||
journal_entry.append("accounts", journal_account)
|
journal_entry.append("accounts", journal_account)
|
||||||
|
|
||||||
journal_entry.save()
|
journal_entry.save()
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
"label": "Profit and Loss"
|
"label": "Profit and Loss"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"content": "[{\"id\":\"MmUf9abwxg\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"id\":\"VVvJ1lUcfc\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Bills\",\"col\":3}},{\"id\":\"Vlj2FZtlHV\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Bills\",\"col\":3}},{\"id\":\"VVVjQVAhPf\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Payment\",\"col\":3}},{\"id\":\"DySNdlysIW\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Payment\",\"col\":3}},{\"id\":\"i0EtSjDAXq\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"X78jcbq1u3\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"id\":\"pMywM0nhlj\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"id\":\"_pRdD6kqUG\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"El2anpPaFY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"id\":\"1nwcM9upJo\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"id\":\"OF9WOi1Ppc\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"iAwpe-Chra\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Accounting\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"DnNtsmxpty\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"General Ledger\",\"col\":4}},{\"id\":\"xOHTyD8b5l\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Receivable\",\"col\":4}},{\"id\":\"_Cb7C8XdJJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Payable\",\"col\":4}},{\"id\":\"p7NY6MHe2Y\",\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"id\":\"KlqilF5R_V\",\"type\":\"card\",\"data\":{\"card_name\":\"Taxes\",\"col\":4}},{\"id\":\"jTUy8LB0uw\",\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"id\":\"Wn2lhs7WLn\",\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"id\":\"PAQMqqNkBM\",\"type\":\"card\",\"data\":{\"card_name\":\"Banking\",\"col\":4}},{\"id\":\"Q_hBCnSeJY\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"3AK1Zf0oew\",\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}},{\"id\":\"kxhoaiqdLq\",\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"id\":\"q0MAlU2j_Z\",\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"id\":\"ptm7T6Hwu-\",\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}},{\"id\":\"OX7lZHbiTr\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
|
"content": "[{\"id\":\"MmUf9abwxg\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"id\":\"nDhfcJYbKH\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"VVvJ1lUcfc\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Bills\",\"col\":3}},{\"id\":\"Vlj2FZtlHV\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Bills\",\"col\":3}},{\"id\":\"VVVjQVAhPf\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Payment\",\"col\":3}},{\"id\":\"DySNdlysIW\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Payment\",\"col\":3}},{\"id\":\"9k1rDm2C0l\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Shortcuts</b></span>\",\"col\":12}},{\"id\":\"pMywM0nhlj\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"id\":\"_pRdD6kqUG\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"El2anpPaFY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"id\":\"1nwcM9upJo\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"id\":\"OF9WOi1Ppc\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"iAwpe-Chra\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Accounting\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"DnNtsmxpty\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"id\":\"KlqilF5R_V\",\"type\":\"card\",\"data\":{\"card_name\":\"Tax Masters\",\"col\":4}},{\"id\":\"jTUy8LB0uw\",\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"id\":\"Wn2lhs7WLn\",\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"id\":\"PAQMqqNkBM\",\"type\":\"card\",\"data\":{\"card_name\":\"Banking\",\"col\":4}},{\"id\":\"kxhoaiqdLq\",\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"id\":\"q0MAlU2j_Z\",\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"id\":\"ptm7T6Hwu-\",\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}}]",
|
||||||
"creation": "2020-03-02 15:41:59.515192",
|
"creation": "2020-03-02 15:41:59.515192",
|
||||||
"custom_blocks": [],
|
"custom_blocks": [],
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
@ -14,562 +14,10 @@
|
|||||||
"hide_custom": 0,
|
"hide_custom": 0,
|
||||||
"icon": "accounting",
|
"icon": "accounting",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
|
"indicator_color": "",
|
||||||
"is_hidden": 0,
|
"is_hidden": 0,
|
||||||
"label": "Accounting",
|
"label": "Accounting",
|
||||||
"links": [
|
"links": [
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Accounting Masters",
|
|
||||||
"link_count": 0,
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Card Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Company",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Company",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 1,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Chart of Accounts",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Account",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 1,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Accounts Settings",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Accounts Settings",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Fiscal Year",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Fiscal Year",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Accounting Dimension",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Accounting Dimension",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Finance Book",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Finance Book",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Accounting Period",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Accounting Period",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Payment Term",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Payment Term",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "General Ledger",
|
|
||||||
"link_count": 0,
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Card Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Journal Entry",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Journal Entry",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Journal Entry Template",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Journal Entry Template",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "GL Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "General Ledger",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "General Ledger",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Customer Ledger Summary",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Customer Ledger Summary",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Supplier Ledger Summary",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Supplier Ledger Summary",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Accounts Receivable",
|
|
||||||
"link_count": 0,
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Card Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Sales Invoice",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Sales Invoice",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 1,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Customer",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Customer",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 1,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Payment Entry",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Payment Entry",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Payment Request",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Payment Request",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Payment Reconciliation",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Payment Reconciliation",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Accounts Receivable",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Accounts Receivable",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Accounts Receivable Summary",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Accounts Receivable Summary",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Sales Register",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Sales Register",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Item-wise Sales Register",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Item-wise Sales Register",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Sales Order Analysis",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Sales Order Analysis",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Delivered Items To Be Billed",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Delivered Items To Be Billed",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Accounts Payable",
|
|
||||||
"link_count": 0,
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Card Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Purchase Invoice",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Purchase Invoice",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 1,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Supplier",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Supplier",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 1,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Payment Entry",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Payment Entry",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Payment Reconciliation",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Payment Reconciliation",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Purchase Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Accounts Payable",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Accounts Payable",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Purchase Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Accounts Payable Summary",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Accounts Payable Summary",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Purchase Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Purchase Register",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Purchase Register",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Purchase Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Item-wise Purchase Register",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Item-wise Purchase Register",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Purchase Order",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Purchase Order Analysis",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Purchase Order Analysis",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Purchase Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Received Items To Be Billed",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Received Items To Be Billed",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Reports",
|
|
||||||
"link_count": 0,
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Card Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "GL Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Trial Balance for Party",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Trial Balance for Party",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Journal Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Payment Period Based On Invoice Date",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Payment Period Based On Invoice Date",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Sales Partners Commission",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Sales Partners Commission",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Customer",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Customer Credit Balance",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Customer Credit Balance",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Sales Payment Summary",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Sales Payment Summary",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Address",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Address And Contacts",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Address And Contacts",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "GL Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "UAE VAT 201",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "UAE VAT 201",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"only_for": "United Arab Emirates",
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Financial Statements",
|
|
||||||
"link_count": 0,
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Card Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "GL Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Trial Balance",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Trial Balance",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "GL Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Profit and Loss Statement",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Profit and Loss Statement",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "GL Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Balance Sheet",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Balance Sheet",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "GL Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Cash Flow",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Cash Flow",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "GL Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Consolidated Financial Statement",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Consolidated Financial Statement",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
@ -611,102 +59,6 @@
|
|||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"type": "Link"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Settings",
|
|
||||||
"link_count": 0,
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Card Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Payment Gateway Account",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Payment Gateway Account",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Terms and Conditions Template",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Terms and Conditions",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Mode of Payment",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Mode of Payment",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Bank",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Bank",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Bank Account",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Bank Account",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Bank Clearance",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Bank Clearance",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Bank Reconciliation Tool",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Bank Reconciliation Tool",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "GL Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Bank Reconciliation Statement",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Bank Reconciliation Statement",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
@ -918,8 +270,83 @@
|
|||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
"label": "Taxes",
|
"label": "Banking",
|
||||||
|
"link_count": 6,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Bank",
|
||||||
"link_count": 0,
|
"link_count": 0,
|
||||||
|
"link_to": "Bank",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Bank Account",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Bank Account",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Bank Clearance",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Bank Clearance",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Bank Reconciliation Tool",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Bank Reconciliation Tool",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "GL Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Bank Reconciliation Statement",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Bank Reconciliation Statement",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Plaid Settings",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Plaid Settings",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Tax Masters",
|
||||||
|
"link_count": 7,
|
||||||
|
"link_type": "DocType",
|
||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Card Break"
|
"type": "Card Break"
|
||||||
},
|
},
|
||||||
@ -1003,60 +430,8 @@
|
|||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
"label": "Profitability",
|
"label": "Accounting Masters",
|
||||||
"link_count": 0,
|
"link_count": 8,
|
||||||
"onboard": 0,
|
|
||||||
"type": "Card Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Gross Profit",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Gross Profit",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "GL Entry",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Profitability Analysis",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Profitability Analysis",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Sales Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Sales Invoice Trends",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Sales Invoice Trends",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dependencies": "Purchase Invoice",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 1,
|
|
||||||
"label": "Purchase Invoice Trends",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Purchase Invoice Trends",
|
|
||||||
"link_type": "Report",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Banking",
|
|
||||||
"link_count": 6,
|
|
||||||
"link_type": "DocType",
|
"link_type": "DocType",
|
||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Card Break"
|
"type": "Card Break"
|
||||||
@ -1065,9 +440,31 @@
|
|||||||
"dependencies": "",
|
"dependencies": "",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
"label": "Bank",
|
"label": "Company",
|
||||||
"link_count": 0,
|
"link_count": 0,
|
||||||
"link_to": "Bank",
|
"link_to": "Company",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 1,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Chart of Accounts",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Account",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 1,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Accounts Settings",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Accounts Settings",
|
||||||
"link_type": "DocType",
|
"link_type": "DocType",
|
||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"type": "Link"
|
||||||
@ -1076,9 +473,9 @@
|
|||||||
"dependencies": "",
|
"dependencies": "",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
"label": "Bank Account",
|
"label": "Fiscal Year",
|
||||||
"link_count": 0,
|
"link_count": 0,
|
||||||
"link_to": "Bank Account",
|
"link_to": "Fiscal Year",
|
||||||
"link_type": "DocType",
|
"link_type": "DocType",
|
||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"type": "Link"
|
||||||
@ -1087,9 +484,9 @@
|
|||||||
"dependencies": "",
|
"dependencies": "",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
"label": "Bank Clearance",
|
"label": "Accounting Dimension",
|
||||||
"link_count": 0,
|
"link_count": 0,
|
||||||
"link_to": "Bank Clearance",
|
"link_to": "Accounting Dimension",
|
||||||
"link_type": "DocType",
|
"link_type": "DocType",
|
||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"type": "Link"
|
||||||
@ -1098,36 +495,98 @@
|
|||||||
"dependencies": "",
|
"dependencies": "",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
"label": "Bank Reconciliation Tool",
|
"label": "Finance Book",
|
||||||
"link_count": 0,
|
"link_count": 0,
|
||||||
"link_to": "Bank Reconciliation Tool",
|
"link_to": "Finance Book",
|
||||||
"link_type": "DocType",
|
"link_type": "DocType",
|
||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"type": "Link"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"dependencies": "GL Entry",
|
"dependencies": "",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 1,
|
"is_query_report": 0,
|
||||||
"label": "Bank Reconciliation Statement",
|
"label": "Accounting Period",
|
||||||
"link_count": 0,
|
"link_count": 0,
|
||||||
"link_to": "Bank Reconciliation Statement",
|
"link_to": "Accounting Period",
|
||||||
"link_type": "Report",
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Payment Term",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Payment Term",
|
||||||
|
"link_type": "DocType",
|
||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"type": "Link"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
"label": "Plaid Settings",
|
"label": "Payments",
|
||||||
|
"link_count": 5,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Payment Entry",
|
||||||
"link_count": 0,
|
"link_count": 0,
|
||||||
"link_to": "Plaid Settings",
|
"link_to": "Payment Entry",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Journal Entry",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Journal Entry",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Journal Entry Template",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Journal Entry Template",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Terms and Conditions",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Terms and Conditions",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Mode of Payment",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Mode of Payment",
|
||||||
"link_type": "DocType",
|
"link_type": "DocType",
|
||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"type": "Link"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2024-01-02 15:21:09.895531",
|
"modified": "2024-01-18 22:15:40.941711",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounting",
|
"name": "Accounting",
|
||||||
|
|||||||
@ -0,0 +1,277 @@
|
|||||||
|
{
|
||||||
|
"charts": [],
|
||||||
|
"content": "[{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"Ledgers\",\"col\":4}},{\"id\":\"p7NY6MHe2Y\",\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"id\":\"3AK1Zf0oew\",\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}},{\"id\":\"Q_hBCnSeJY\",\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
|
||||||
|
"creation": "2024-01-05 16:09:16.766939",
|
||||||
|
"custom_blocks": [],
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Workspace",
|
||||||
|
"for_user": "",
|
||||||
|
"hide_custom": 0,
|
||||||
|
"icon": "file",
|
||||||
|
"idx": 0,
|
||||||
|
"indicator_color": "",
|
||||||
|
"is_hidden": 0,
|
||||||
|
"label": "Financial Reports",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Profitability",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Gross Profit",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Gross Profit",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "GL Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Profitability Analysis",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Profitability Analysis",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Sales Invoice Trends",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Sales Invoice Trends",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Purchase Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Purchase Invoice Trends",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Purchase Invoice Trends",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Financial Statements",
|
||||||
|
"link_count": 5,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "GL Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Trial Balance",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Trial Balance",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "GL Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Profit and Loss Statement",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Profit and Loss Statement",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "GL Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Balance Sheet",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Balance Sheet",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "GL Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Cash Flow",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Cash Flow",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "GL Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Consolidated Financial Statement",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Consolidated Financial Statement",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Ledgers",
|
||||||
|
"link_count": 3,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "GL Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "General Ledger",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "General Ledger",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Customer Ledger Summary",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Customer Ledger Summary",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Supplier Ledger Summary",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Supplier Ledger Summary",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Other Reports",
|
||||||
|
"link_count": 7,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "GL Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Trial Balance for Party",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Trial Balance for Party",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Journal Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Payment Period Based On Invoice Date",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Payment Period Based On Invoice Date",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Sales Partners Commission",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Sales Partners Commission",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Customer",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Customer Credit Balance",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Customer Credit Balance",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Sales Payment Summary",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Sales Payment Summary",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Address",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Address And Contacts",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Address And Contacts",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "GL Entry",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "UAE VAT 201",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "UAE VAT 201",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"only_for": "United Arab Emirates",
|
||||||
|
"type": "Link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"modified": "2024-01-18 22:13:07.596844",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Financial Reports",
|
||||||
|
"number_cards": [],
|
||||||
|
"owner": "Administrator",
|
||||||
|
"parent_page": "Accounting",
|
||||||
|
"public": 1,
|
||||||
|
"quick_lists": [],
|
||||||
|
"restrict_to_domain": "",
|
||||||
|
"roles": [],
|
||||||
|
"sequence_id": 5.0,
|
||||||
|
"shortcuts": [],
|
||||||
|
"title": "Financial Reports"
|
||||||
|
}
|
||||||
204
erpnext/accounts/workspace/payables/payables.json
Normal file
204
erpnext/accounts/workspace/payables/payables.json
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
{
|
||||||
|
"charts": [],
|
||||||
|
"content": "[{\"id\":\"rMMsfn2eB4\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Shortcuts</b></span>\",\"col\":12}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Payable\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"jAcOH-cC-Q\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"7dj93PEUjW\",\"type\":\"card\",\"data\":{\"card_name\":\"Invoicing\",\"col\":4}},{\"id\":\"_Cb7C8XdJJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"id\":\"9yseIkdG50\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
|
||||||
|
"creation": "2024-01-05 15:29:11.144373",
|
||||||
|
"custom_blocks": [],
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Workspace",
|
||||||
|
"for_user": "",
|
||||||
|
"hide_custom": 0,
|
||||||
|
"icon": "arrow-left",
|
||||||
|
"idx": 0,
|
||||||
|
"indicator_color": "",
|
||||||
|
"is_hidden": 0,
|
||||||
|
"label": "Payables",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Invoicing",
|
||||||
|
"link_count": 2,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Purchase Invoice",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Purchase Invoice",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Supplier",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Supplier",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Payments",
|
||||||
|
"link_count": 3,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Payment Entry",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Payment Entry",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Journal Entry",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Journal Entry",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Payment Reconciliation",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Payment Reconciliation",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Reports",
|
||||||
|
"link_count": 7,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Accounts Payable",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Accounts Payable",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Accounts Payable Summary",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Accounts Payable Summary",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Purchase Register",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Purchase Register",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Item-wise Purchase Register",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Item-wise Purchase Register",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Purchase Order Analysis",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Purchase Order Analysis",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Received Items To Be Billed",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Received Items To Be Billed",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Supplier Ledger Summary",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Supplier Ledger Summary",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"modified": "2024-01-18 22:09:46.221549",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Payables",
|
||||||
|
"number_cards": [],
|
||||||
|
"owner": "Administrator",
|
||||||
|
"parent_page": "Accounting",
|
||||||
|
"public": 1,
|
||||||
|
"quick_lists": [],
|
||||||
|
"restrict_to_domain": "",
|
||||||
|
"roles": [],
|
||||||
|
"sequence_id": 3.0,
|
||||||
|
"shortcuts": [
|
||||||
|
{
|
||||||
|
"doc_view": "",
|
||||||
|
"label": "Accounts Payable",
|
||||||
|
"link_to": "Accounts Payable",
|
||||||
|
"type": "Report"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doc_view": "",
|
||||||
|
"label": "Purchase Invoice",
|
||||||
|
"link_to": "Purchase Invoice",
|
||||||
|
"type": "DocType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doc_view": "",
|
||||||
|
"label": "Journal Entry",
|
||||||
|
"link_to": "Journal Entry",
|
||||||
|
"type": "DocType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doc_view": "",
|
||||||
|
"label": "Payment Entry",
|
||||||
|
"link_to": "Payment Entry",
|
||||||
|
"type": "DocType"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Payables"
|
||||||
|
}
|
||||||
254
erpnext/accounts/workspace/receivables/receivables.json
Normal file
254
erpnext/accounts/workspace/receivables/receivables.json
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
{
|
||||||
|
"charts": [],
|
||||||
|
"content": "[{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Shortcuts</b></span>\",\"col\":12}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"5yHldR0JNk\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"POS Invoice\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"ILlIxJuexy\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Cost Center\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"jLgv00c6ek\",\"type\":\"card\",\"data\":{\"card_name\":\"Invoicing\",\"col\":4}},{\"id\":\"npwfXlz0u1\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"id\":\"am70C27Jrb\",\"type\":\"card\",\"data\":{\"card_name\":\"Dunning\",\"col\":4}},{\"id\":\"xOHTyD8b5l\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
|
||||||
|
"creation": "2024-01-05 15:29:21.084241",
|
||||||
|
"custom_blocks": [],
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Workspace",
|
||||||
|
"for_user": "",
|
||||||
|
"hide_custom": 0,
|
||||||
|
"icon": "arrow-right",
|
||||||
|
"idx": 0,
|
||||||
|
"indicator_color": "",
|
||||||
|
"is_hidden": 0,
|
||||||
|
"label": "Receivables",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Invoicing",
|
||||||
|
"link_count": 2,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Sales Invoice",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Sales Invoice",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Customer",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Customer",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Payments",
|
||||||
|
"link_count": 4,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Payment Entry",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Payment Entry",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Payment Request",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Payment Request",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Payment Reconciliation",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Payment Reconciliation",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Payment Gateway Account",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Payment Gateway Account",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Dunning",
|
||||||
|
"link_count": 2,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Dunning",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Dunning",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Dunning Type",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Dunning Type",
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 0,
|
||||||
|
"label": "Reports",
|
||||||
|
"link_count": 6,
|
||||||
|
"link_type": "DocType",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Card Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Accounts Receivable",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Accounts Receivable",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Accounts Receivable Summary",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Accounts Receivable Summary",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Sales Register",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Sales Register",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Item-wise Sales Register",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Item-wise Sales Register",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Sales Order Analysis",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Sales Order Analysis",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependencies": "Sales Invoice",
|
||||||
|
"hidden": 0,
|
||||||
|
"is_query_report": 1,
|
||||||
|
"label": "Delivered Items To Be Billed",
|
||||||
|
"link_count": 0,
|
||||||
|
"link_to": "Delivered Items To Be Billed",
|
||||||
|
"link_type": "Report",
|
||||||
|
"onboard": 0,
|
||||||
|
"type": "Link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"modified": "2024-01-18 22:11:51.474477",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Receivables",
|
||||||
|
"number_cards": [],
|
||||||
|
"owner": "Administrator",
|
||||||
|
"parent_page": "Accounting",
|
||||||
|
"public": 1,
|
||||||
|
"quick_lists": [],
|
||||||
|
"restrict_to_domain": "",
|
||||||
|
"roles": [],
|
||||||
|
"sequence_id": 4.0,
|
||||||
|
"shortcuts": [
|
||||||
|
{
|
||||||
|
"color": "Grey",
|
||||||
|
"doc_view": "List",
|
||||||
|
"label": "POS Invoice",
|
||||||
|
"link_to": "POS Invoice",
|
||||||
|
"stats_filter": "[]",
|
||||||
|
"type": "DocType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "Grey",
|
||||||
|
"doc_view": "List",
|
||||||
|
"label": "Cost Center",
|
||||||
|
"link_to": "Cost Center",
|
||||||
|
"type": "DocType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doc_view": "",
|
||||||
|
"label": "Sales Invoice",
|
||||||
|
"link_to": "Sales Invoice",
|
||||||
|
"stats_filter": "[]",
|
||||||
|
"type": "DocType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doc_view": "",
|
||||||
|
"label": "Journal Entry",
|
||||||
|
"link_to": "Journal Entry",
|
||||||
|
"type": "DocType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doc_view": "",
|
||||||
|
"label": "Payment Entry",
|
||||||
|
"link_to": "Payment Entry",
|
||||||
|
"type": "DocType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doc_view": "",
|
||||||
|
"label": "Accounts Receivable",
|
||||||
|
"link_to": "Accounts Receivable",
|
||||||
|
"type": "Report"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Receivables"
|
||||||
|
}
|
||||||
@ -202,8 +202,7 @@
|
|||||||
"fieldname": "purchase_date",
|
"fieldname": "purchase_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Purchase Date",
|
"label": "Purchase Date",
|
||||||
"mandatory_depends_on": "eval:!doc.is_existing_asset",
|
"mandatory_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset",
|
||||||
"read_only": 1,
|
|
||||||
"read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset"
|
"read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -590,7 +589,7 @@
|
|||||||
"link_fieldname": "target_asset"
|
"link_fieldname": "target_asset"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2024-01-05 17:36:53.131512",
|
"modified": "2024-01-15 17:35:49.226603",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Assets",
|
"module": "Assets",
|
||||||
"name": "Asset",
|
"name": "Asset",
|
||||||
|
|||||||
@ -162,6 +162,7 @@ class Asset(AccountsController):
|
|||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.validate_cancellation()
|
self.validate_cancellation()
|
||||||
self.cancel_movement_entries()
|
self.cancel_movement_entries()
|
||||||
|
self.cancel_capitalization()
|
||||||
self.delete_depreciation_entries()
|
self.delete_depreciation_entries()
|
||||||
cancel_asset_depr_schedules(self)
|
cancel_asset_depr_schedules(self)
|
||||||
self.set_status()
|
self.set_status()
|
||||||
@ -517,6 +518,16 @@ class Asset(AccountsController):
|
|||||||
movement = frappe.get_doc("Asset Movement", movement.get("name"))
|
movement = frappe.get_doc("Asset Movement", movement.get("name"))
|
||||||
movement.cancel()
|
movement.cancel()
|
||||||
|
|
||||||
|
def cancel_capitalization(self):
|
||||||
|
asset_capitalization = frappe.db.get_value(
|
||||||
|
"Asset Capitalization",
|
||||||
|
{"target_asset": self.name, "docstatus": 1, "entry_type": "Capitalization"},
|
||||||
|
)
|
||||||
|
|
||||||
|
if asset_capitalization:
|
||||||
|
asset_capitalization = frappe.get_doc("Asset Capitalization", asset_capitalization)
|
||||||
|
asset_capitalization.cancel()
|
||||||
|
|
||||||
def delete_depreciation_entries(self):
|
def delete_depreciation_entries(self):
|
||||||
if self.calculate_depreciation:
|
if self.calculate_depreciation:
|
||||||
for row in self.get("finance_books"):
|
for row in self.get("finance_books"):
|
||||||
@ -697,9 +708,7 @@ class Asset(AccountsController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": cwip_account,
|
"account": cwip_account,
|
||||||
"against_type": "Account",
|
|
||||||
"against": fixed_asset_account,
|
"against": fixed_asset_account,
|
||||||
"against_link": fixed_asset_account,
|
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||||
"posting_date": self.available_for_use_date,
|
"posting_date": self.available_for_use_date,
|
||||||
"credit": self.purchase_receipt_amount,
|
"credit": self.purchase_receipt_amount,
|
||||||
@ -714,9 +723,7 @@ class Asset(AccountsController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": fixed_asset_account,
|
"account": fixed_asset_account,
|
||||||
"against_type": "Account",
|
|
||||||
"against": cwip_account,
|
"against": cwip_account,
|
||||||
"against_link": cwip_account,
|
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||||
"posting_date": self.available_for_use_date,
|
"posting_date": self.available_for_use_date,
|
||||||
"debit": self.purchase_receipt_amount,
|
"debit": self.purchase_receipt_amount,
|
||||||
@ -1004,7 +1011,7 @@ def make_asset_movement(assets, purpose=None):
|
|||||||
assets = json.loads(assets)
|
assets = json.loads(assets)
|
||||||
|
|
||||||
if len(assets) == 0:
|
if len(assets) == 0:
|
||||||
frappe.throw(_("Atleast one asset has to be selected."))
|
frappe.throw(_("At least one asset has to be selected."))
|
||||||
|
|
||||||
asset_movement = frappe.new_doc("Asset Movement")
|
asset_movement = frappe.new_doc("Asset Movement")
|
||||||
asset_movement.quantity = len(assets)
|
asset_movement.quantity = len(assets)
|
||||||
@ -1031,6 +1038,8 @@ def is_cwip_accounting_enabled(asset_category):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_asset_value_after_depreciation(asset_name, finance_book=None):
|
def get_asset_value_after_depreciation(asset_name, finance_book=None):
|
||||||
asset = frappe.get_doc("Asset", asset_name)
|
asset = frappe.get_doc("Asset", asset_name)
|
||||||
|
if not asset.calculate_depreciation:
|
||||||
|
return flt(asset.value_after_depreciation)
|
||||||
|
|
||||||
return asset.get_value_after_depreciation(finance_book)
|
return asset.get_value_after_depreciation(finance_book)
|
||||||
|
|
||||||
|
|||||||
@ -251,16 +251,7 @@ class TestAsset(AssetSetup):
|
|||||||
flt(18000.0 + pro_rata_amount, asset.precision("gross_purchase_amount")),
|
flt(18000.0 + pro_rata_amount, asset.precision("gross_purchase_amount")),
|
||||||
0.0,
|
0.0,
|
||||||
),
|
),
|
||||||
(
|
("_Test Fixed Asset - _TC", 0.0, 100000.0),
|
||||||
"_Test Fixed Asset - _TC",
|
|
||||||
0.0,
|
|
||||||
flt(18000.0 + pro_rata_amount, asset.precision("gross_purchase_amount")),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"_Test Fixed Asset - _TC",
|
|
||||||
0.0,
|
|
||||||
flt(82000.0 - pro_rata_amount, asset.precision("gross_purchase_amount")),
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"_Test Gain/Loss on Asset Disposal - _TC",
|
"_Test Gain/Loss on Asset Disposal - _TC",
|
||||||
flt(82000.0 - pro_rata_amount, asset.precision("gross_purchase_amount")),
|
flt(82000.0 - pro_rata_amount, asset.precision("gross_purchase_amount")),
|
||||||
@ -900,7 +891,7 @@ class TestDepreciationMethods(AssetSetup):
|
|||||||
["2030-12-31", 28630.14, 28630.14],
|
["2030-12-31", 28630.14, 28630.14],
|
||||||
["2031-12-31", 35684.93, 64315.07],
|
["2031-12-31", 35684.93, 64315.07],
|
||||||
["2032-12-31", 17842.46, 82157.53],
|
["2032-12-31", 17842.46, 82157.53],
|
||||||
["2033-06-06", 5342.47, 87500.0],
|
["2033-06-06", 5342.46, 87499.99],
|
||||||
]
|
]
|
||||||
|
|
||||||
schedules = [
|
schedules = [
|
||||||
@ -1012,7 +1003,7 @@ class TestDepreciationBasics(AssetSetup):
|
|||||||
asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, "Active")
|
asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, "Active")
|
||||||
|
|
||||||
depreciation_amount = get_depreciation_amount(
|
depreciation_amount = get_depreciation_amount(
|
||||||
asset_depr_schedule_doc, asset, 100000, asset.finance_books[0]
|
asset_depr_schedule_doc, asset, 100000, 100000, asset.finance_books[0]
|
||||||
)
|
)
|
||||||
self.assertEqual(depreciation_amount, 30000)
|
self.assertEqual(depreciation_amount, 30000)
|
||||||
|
|
||||||
|
|||||||
@ -21,10 +21,10 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
|
|||||||
this.show_stock_ledger();
|
this.show_stock_ledger();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.frm.doc.stock_items && !this.frm.doc.stock_items.length && this.frm.doc.target_asset && this.frm.doc.capitalization_method === "Choose a WIP composite asset") {
|
// if (this.frm.doc.stock_items && !this.frm.doc.stock_items.length && this.frm.doc.target_asset && this.frm.doc.capitalization_method === "Choose a WIP composite asset") {
|
||||||
this.set_consumed_stock_items_tagged_to_wip_composite_asset(this.frm.doc.target_asset);
|
// this.set_consumed_stock_items_tagged_to_wip_composite_asset(this.frm.doc.target_asset);
|
||||||
this.get_target_asset_details();
|
// this.get_target_asset_details();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_queries() {
|
setup_queries() {
|
||||||
@ -143,13 +143,20 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
|
|||||||
},
|
},
|
||||||
callback: function (r) {
|
callback: function (r) {
|
||||||
if (!r.exc && r.message) {
|
if (!r.exc && r.message) {
|
||||||
me.frm.clear_table("stock_items");
|
if(r.message[0] && r.message[0].length) {
|
||||||
|
me.frm.clear_table("stock_items");
|
||||||
for (let item of r.message) {
|
for (let item of r.message[0]) {
|
||||||
me.frm.add_child("stock_items", item);
|
me.frm.add_child("stock_items", item);
|
||||||
|
}
|
||||||
|
refresh_field("stock_items");
|
||||||
|
}
|
||||||
|
if (r.message[1] && r.message[1].length) {
|
||||||
|
me.frm.clear_table("asset_items");
|
||||||
|
for (let item of r.message[1]) {
|
||||||
|
me.frm.add_child("asset_items", item);
|
||||||
|
}
|
||||||
|
me.frm.refresh_field("asset_items");
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh_field("stock_items");
|
|
||||||
|
|
||||||
me.calculate_totals();
|
me.calculate_totals();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -136,11 +136,19 @@ class AssetCapitalization(StockController):
|
|||||||
"Stock Ledger Entry",
|
"Stock Ledger Entry",
|
||||||
"Repost Item Valuation",
|
"Repost Item Valuation",
|
||||||
"Serial and Batch Bundle",
|
"Serial and Batch Bundle",
|
||||||
|
"Asset",
|
||||||
)
|
)
|
||||||
|
self.cancel_target_asset()
|
||||||
self.update_stock_ledger()
|
self.update_stock_ledger()
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
self.restore_consumed_asset_items()
|
self.restore_consumed_asset_items()
|
||||||
|
|
||||||
|
def cancel_target_asset(self):
|
||||||
|
if self.entry_type == "Capitalization" and self.target_asset:
|
||||||
|
asset_doc = frappe.get_doc("Asset", self.target_asset)
|
||||||
|
if asset_doc.docstatus == 1:
|
||||||
|
asset_doc.cancel()
|
||||||
|
|
||||||
def set_title(self):
|
def set_title(self):
|
||||||
self.title = self.target_asset_name or self.target_item_name or self.target_item_code
|
self.title = self.target_asset_name or self.target_item_name or self.target_item_code
|
||||||
|
|
||||||
@ -485,9 +493,7 @@ class AssetCapitalization(StockController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": account,
|
"account": account,
|
||||||
"against_type": "Account",
|
|
||||||
"against": target_account,
|
"against": target_account,
|
||||||
"against_link": target_account,
|
|
||||||
"cost_center": item_row.cost_center,
|
"cost_center": item_row.cost_center,
|
||||||
"project": item_row.get("project") or self.get("project"),
|
"project": item_row.get("project") or self.get("project"),
|
||||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||||
@ -528,9 +534,7 @@ class AssetCapitalization(StockController):
|
|||||||
self.set_consumed_asset_status(asset)
|
self.set_consumed_asset_status(asset)
|
||||||
|
|
||||||
for gle in fixed_asset_gl_entries:
|
for gle in fixed_asset_gl_entries:
|
||||||
gle["against_type"] = "Account"
|
|
||||||
gle["against"] = target_account
|
gle["against"] = target_account
|
||||||
gle["against_link"] = target_account
|
|
||||||
gl_entries.append(self.get_gl_dict(gle, item=item))
|
gl_entries.append(self.get_gl_dict(gle, item=item))
|
||||||
target_against.add(gle["account"])
|
target_against.add(gle["account"])
|
||||||
|
|
||||||
@ -546,9 +550,7 @@ class AssetCapitalization(StockController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": item_row.expense_account,
|
"account": item_row.expense_account,
|
||||||
"against_type": "Account",
|
|
||||||
"against": target_account,
|
"against": target_account,
|
||||||
"against_link": target_account,
|
|
||||||
"cost_center": item_row.cost_center,
|
"cost_center": item_row.cost_center,
|
||||||
"project": item_row.get("project") or self.get("project"),
|
"project": item_row.get("project") or self.get("project"),
|
||||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||||
@ -559,46 +561,41 @@ class AssetCapitalization(StockController):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_gl_entries_for_target_item(self, gl_entries, target_against, precision):
|
def get_gl_entries_for_target_item(self, gl_entries, target_against, precision):
|
||||||
for target_account in target_against:
|
if self.target_is_fixed_asset:
|
||||||
if self.target_is_fixed_asset:
|
# Capitalization
|
||||||
# Capitalization
|
gl_entries.append(
|
||||||
|
self.get_gl_dict(
|
||||||
|
{
|
||||||
|
"account": self.target_fixed_asset_account,
|
||||||
|
"against": ", ".join(target_against),
|
||||||
|
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||||
|
"debit": flt(self.total_value, precision),
|
||||||
|
"cost_center": self.get("cost_center"),
|
||||||
|
},
|
||||||
|
item=self,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Target Stock Item
|
||||||
|
sle_list = self.sle_map.get(self.name)
|
||||||
|
for sle in sle_list:
|
||||||
|
stock_value_difference = flt(sle.stock_value_difference, precision)
|
||||||
|
account = self.warehouse_account[sle.warehouse]["account"]
|
||||||
|
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": self.target_fixed_asset_account,
|
"account": account,
|
||||||
"against_type": "Account",
|
"against": ", ".join(target_against),
|
||||||
"against": target_account,
|
"cost_center": self.cost_center,
|
||||||
"against_link": target_account,
|
"project": self.get("project"),
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||||
"debit": flt(self.total_value, precision) / len(target_against),
|
"debit": stock_value_difference,
|
||||||
"cost_center": self.get("cost_center"),
|
|
||||||
},
|
},
|
||||||
|
self.warehouse_account[sle.warehouse]["account_currency"],
|
||||||
item=self,
|
item=self,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
# Target Stock Item
|
|
||||||
sle_list = self.sle_map.get(self.name)
|
|
||||||
for sle in sle_list:
|
|
||||||
stock_value_difference = flt(sle.stock_value_difference, precision)
|
|
||||||
account = self.warehouse_account[sle.warehouse]["account"]
|
|
||||||
|
|
||||||
gl_entries.append(
|
|
||||||
self.get_gl_dict(
|
|
||||||
{
|
|
||||||
"account": account,
|
|
||||||
"against_type": "Account",
|
|
||||||
"against": target_account,
|
|
||||||
"against_link": target_account,
|
|
||||||
"cost_center": self.cost_center,
|
|
||||||
"project": self.get("project"),
|
|
||||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
|
||||||
"debit": stock_value_difference / len(target_against),
|
|
||||||
},
|
|
||||||
self.warehouse_account[sle.warehouse]["account_currency"],
|
|
||||||
item=self,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def create_target_asset(self):
|
def create_target_asset(self):
|
||||||
if (
|
if (
|
||||||
@ -892,7 +889,6 @@ def get_consumed_asset_details(args):
|
|||||||
out.cost_center = get_default_cost_center(
|
out.cost_center = get_default_cost_center(
|
||||||
args, item_defaults, item_group_defaults, brand_defaults
|
args, item_defaults, item_group_defaults, brand_defaults
|
||||||
)
|
)
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
@ -940,10 +936,27 @@ def get_items_tagged_to_wip_composite_asset(asset):
|
|||||||
"qty",
|
"qty",
|
||||||
"valuation_rate",
|
"valuation_rate",
|
||||||
"amount",
|
"amount",
|
||||||
|
"is_fixed_asset",
|
||||||
|
"parent",
|
||||||
]
|
]
|
||||||
|
|
||||||
pr_items = frappe.get_all(
|
pr_items = frappe.get_all(
|
||||||
"Purchase Receipt Item", filters={"wip_composite_asset": asset}, fields=fields
|
"Purchase Receipt Item", filters={"wip_composite_asset": asset, "docstatus": 1}, fields=fields
|
||||||
)
|
)
|
||||||
|
|
||||||
return pr_items
|
stock_items = []
|
||||||
|
asset_items = []
|
||||||
|
for d in pr_items:
|
||||||
|
if not d.is_fixed_asset:
|
||||||
|
stock_items.append(frappe._dict(d))
|
||||||
|
else:
|
||||||
|
asset_details = frappe.db.get_value(
|
||||||
|
"Asset",
|
||||||
|
{"item_code": d.item_code, "purchase_receipt": d.parent},
|
||||||
|
["name as asset", "asset_name"],
|
||||||
|
as_dict=1,
|
||||||
|
)
|
||||||
|
d.update(asset_details)
|
||||||
|
asset_items.append(frappe._dict(d))
|
||||||
|
|
||||||
|
return stock_items, asset_items
|
||||||
|
|||||||
@ -98,12 +98,12 @@ class TestAssetCapitalization(unittest.TestCase):
|
|||||||
|
|
||||||
# Test General Ledger Entries
|
# Test General Ledger Entries
|
||||||
expected_gle = {
|
expected_gle = {
|
||||||
"_Test Fixed Asset - TCP1": 2999.99,
|
"_Test Fixed Asset - TCP1": 3000,
|
||||||
"Expenses Included In Asset Valuation - TCP1": -1000,
|
"Expenses Included In Asset Valuation - TCP1": -1000,
|
||||||
"_Test Warehouse - TCP1": -2000,
|
"_Test Warehouse - TCP1": -2000,
|
||||||
"Round Off - TCP1": 0.01,
|
|
||||||
}
|
}
|
||||||
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
||||||
|
|
||||||
self.assertEqual(actual_gle, expected_gle)
|
self.assertEqual(actual_gle, expected_gle)
|
||||||
|
|
||||||
# Test Stock Ledger Entries
|
# Test Stock Ledger Entries
|
||||||
@ -189,10 +189,9 @@ class TestAssetCapitalization(unittest.TestCase):
|
|||||||
# Test General Ledger Entries
|
# Test General Ledger Entries
|
||||||
default_expense_account = frappe.db.get_value("Company", company, "default_expense_account")
|
default_expense_account = frappe.db.get_value("Company", company, "default_expense_account")
|
||||||
expected_gle = {
|
expected_gle = {
|
||||||
"_Test Fixed Asset - _TC": 2999.99,
|
"_Test Fixed Asset - _TC": 3000,
|
||||||
"Expenses Included In Asset Valuation - _TC": -1000,
|
"Expenses Included In Asset Valuation - _TC": -1000,
|
||||||
default_expense_account: -2000,
|
default_expense_account: -2000,
|
||||||
"Round Off - _TC": 0.01,
|
|
||||||
}
|
}
|
||||||
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
||||||
|
|
||||||
@ -377,10 +376,9 @@ class TestAssetCapitalization(unittest.TestCase):
|
|||||||
|
|
||||||
# Test General Ledger Entries
|
# Test General Ledger Entries
|
||||||
expected_gle = {
|
expected_gle = {
|
||||||
|
"_Test Warehouse - TCP1": consumed_asset_value_before_disposal,
|
||||||
"_Test Accumulated Depreciations - TCP1": accumulated_depreciation,
|
"_Test Accumulated Depreciations - TCP1": accumulated_depreciation,
|
||||||
"_Test Fixed Asset - TCP1": -consumed_asset_purchase_value,
|
"_Test Fixed Asset - TCP1": -consumed_asset_purchase_value,
|
||||||
"_Test Warehouse - TCP1": consumed_asset_value_before_disposal - 0.01,
|
|
||||||
"Round Off - TCP1": 0.01,
|
|
||||||
}
|
}
|
||||||
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
||||||
self.assertEqual(actual_gle, expected_gle)
|
self.assertEqual(actual_gle, expected_gle)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ from frappe.model.document import Document
|
|||||||
from frappe.utils import (
|
from frappe.utils import (
|
||||||
add_days,
|
add_days,
|
||||||
add_months,
|
add_months,
|
||||||
|
add_years,
|
||||||
cint,
|
cint,
|
||||||
date_diff,
|
date_diff,
|
||||||
flt,
|
flt,
|
||||||
@ -18,6 +19,7 @@ from frappe.utils import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
|
|
||||||
|
|
||||||
class AssetDepreciationSchedule(Document):
|
class AssetDepreciationSchedule(Document):
|
||||||
@ -283,12 +285,20 @@ class AssetDepreciationSchedule(Document):
|
|||||||
depreciation_amount = 0
|
depreciation_amount = 0
|
||||||
|
|
||||||
number_of_pending_depreciations = final_number_of_depreciations - start
|
number_of_pending_depreciations = final_number_of_depreciations - start
|
||||||
|
yearly_opening_wdv = value_after_depreciation
|
||||||
|
current_fiscal_year_end_date = None
|
||||||
for n in range(start, final_number_of_depreciations):
|
for n in range(start, final_number_of_depreciations):
|
||||||
# If depreciation is already completed (for double declining balance)
|
# If depreciation is already completed (for double declining balance)
|
||||||
if skip_row:
|
if skip_row:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
schedule_date = add_months(row.depreciation_start_date, n * cint(row.frequency_of_depreciation))
|
||||||
|
if not current_fiscal_year_end_date:
|
||||||
|
current_fiscal_year_end_date = get_fiscal_year(row.depreciation_start_date)[2]
|
||||||
|
elif getdate(schedule_date) > getdate(current_fiscal_year_end_date):
|
||||||
|
current_fiscal_year_end_date = add_years(current_fiscal_year_end_date, 1)
|
||||||
|
yearly_opening_wdv = value_after_depreciation
|
||||||
|
|
||||||
if n > 0 and len(self.get("depreciation_schedule")) > n - 1:
|
if n > 0 and len(self.get("depreciation_schedule")) > n - 1:
|
||||||
prev_depreciation_amount = self.get("depreciation_schedule")[n - 1].depreciation_amount
|
prev_depreciation_amount = self.get("depreciation_schedule")[n - 1].depreciation_amount
|
||||||
else:
|
else:
|
||||||
@ -298,6 +308,7 @@ class AssetDepreciationSchedule(Document):
|
|||||||
self,
|
self,
|
||||||
asset_doc,
|
asset_doc,
|
||||||
value_after_depreciation,
|
value_after_depreciation,
|
||||||
|
yearly_opening_wdv,
|
||||||
row,
|
row,
|
||||||
n,
|
n,
|
||||||
prev_depreciation_amount,
|
prev_depreciation_amount,
|
||||||
@ -401,8 +412,9 @@ class AssetDepreciationSchedule(Document):
|
|||||||
|
|
||||||
if not depreciation_amount:
|
if not depreciation_amount:
|
||||||
continue
|
continue
|
||||||
value_after_depreciation -= flt(
|
value_after_depreciation = flt(
|
||||||
depreciation_amount, asset_doc.precision("gross_purchase_amount")
|
value_after_depreciation - flt(depreciation_amount),
|
||||||
|
asset_doc.precision("gross_purchase_amount"),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Adjust depreciation amount in the last period based on the expected value after useful life
|
# Adjust depreciation amount in the last period based on the expected value after useful life
|
||||||
@ -582,6 +594,7 @@ def get_depreciation_amount(
|
|||||||
asset_depr_schedule,
|
asset_depr_schedule,
|
||||||
asset,
|
asset,
|
||||||
depreciable_value,
|
depreciable_value,
|
||||||
|
yearly_opening_wdv,
|
||||||
fb_row,
|
fb_row,
|
||||||
schedule_idx=0,
|
schedule_idx=0,
|
||||||
prev_depreciation_amount=0,
|
prev_depreciation_amount=0,
|
||||||
@ -597,6 +610,7 @@ def get_depreciation_amount(
|
|||||||
asset,
|
asset,
|
||||||
fb_row,
|
fb_row,
|
||||||
depreciable_value,
|
depreciable_value,
|
||||||
|
yearly_opening_wdv,
|
||||||
schedule_idx,
|
schedule_idx,
|
||||||
prev_depreciation_amount,
|
prev_depreciation_amount,
|
||||||
has_wdv_or_dd_non_yearly_pro_rata,
|
has_wdv_or_dd_non_yearly_pro_rata,
|
||||||
@ -744,6 +758,7 @@ def get_wdv_or_dd_depr_amount(
|
|||||||
asset,
|
asset,
|
||||||
fb_row,
|
fb_row,
|
||||||
depreciable_value,
|
depreciable_value,
|
||||||
|
yearly_opening_wdv,
|
||||||
schedule_idx,
|
schedule_idx,
|
||||||
prev_depreciation_amount,
|
prev_depreciation_amount,
|
||||||
has_wdv_or_dd_non_yearly_pro_rata,
|
has_wdv_or_dd_non_yearly_pro_rata,
|
||||||
|
|||||||
@ -40,7 +40,7 @@ class AssetMaintenance(Document):
|
|||||||
if getdate(task.next_due_date) < getdate(nowdate()):
|
if getdate(task.next_due_date) < getdate(nowdate()):
|
||||||
task.maintenance_status = "Overdue"
|
task.maintenance_status = "Overdue"
|
||||||
if not task.assign_to and self.docstatus == 0:
|
if not task.assign_to and self.docstatus == 0:
|
||||||
throw(_("Row #{}: Please asign task to a member.").format(task.idx))
|
throw(_("Row #{}: Please assign task to a member.").format(task.idx))
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
for task in self.get("asset_maintenance_tasks"):
|
for task in self.get("asset_maintenance_tasks"):
|
||||||
|
|||||||
@ -285,9 +285,7 @@ class AssetRepair(AccountsController):
|
|||||||
"account": fixed_asset_account,
|
"account": fixed_asset_account,
|
||||||
"debit": self.repair_cost,
|
"debit": self.repair_cost,
|
||||||
"debit_in_account_currency": self.repair_cost,
|
"debit_in_account_currency": self.repair_cost,
|
||||||
"against_type": "Account",
|
|
||||||
"against": pi_expense_account,
|
"against": pi_expense_account,
|
||||||
"against_link": pi_expense_account,
|
|
||||||
"voucher_type": self.doctype,
|
"voucher_type": self.doctype,
|
||||||
"voucher_no": self.name,
|
"voucher_no": self.name,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
@ -306,9 +304,7 @@ class AssetRepair(AccountsController):
|
|||||||
"account": pi_expense_account,
|
"account": pi_expense_account,
|
||||||
"credit": self.repair_cost,
|
"credit": self.repair_cost,
|
||||||
"credit_in_account_currency": self.repair_cost,
|
"credit_in_account_currency": self.repair_cost,
|
||||||
"against_type": "Account",
|
|
||||||
"against": fixed_asset_account,
|
"against": fixed_asset_account,
|
||||||
"against_link": fixed_asset_account,
|
|
||||||
"voucher_type": self.doctype,
|
"voucher_type": self.doctype,
|
||||||
"voucher_no": self.name,
|
"voucher_no": self.name,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
@ -342,9 +338,7 @@ class AssetRepair(AccountsController):
|
|||||||
"account": item.expense_account or default_expense_account,
|
"account": item.expense_account or default_expense_account,
|
||||||
"credit": item.amount,
|
"credit": item.amount,
|
||||||
"credit_in_account_currency": item.amount,
|
"credit_in_account_currency": item.amount,
|
||||||
"against_type": "Account",
|
|
||||||
"against": fixed_asset_account,
|
"against": fixed_asset_account,
|
||||||
"against_link": fixed_asset_account,
|
|
||||||
"voucher_type": self.doctype,
|
"voucher_type": self.doctype,
|
||||||
"voucher_no": self.name,
|
"voucher_no": self.name,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
@ -361,9 +355,7 @@ class AssetRepair(AccountsController):
|
|||||||
"account": fixed_asset_account,
|
"account": fixed_asset_account,
|
||||||
"debit": item.amount,
|
"debit": item.amount,
|
||||||
"debit_in_account_currency": item.amount,
|
"debit_in_account_currency": item.amount,
|
||||||
"against_type": "Account",
|
|
||||||
"against": item.expense_account or default_expense_account,
|
"against": item.expense_account or default_expense_account,
|
||||||
"against_link": item.expense_account or default_expense_account,
|
|
||||||
"voucher_type": self.doctype,
|
"voucher_type": self.doctype,
|
||||||
"voucher_no": self.name,
|
"voucher_no": self.name,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
|
|||||||
@ -2,14 +2,14 @@
|
|||||||
"action": "Show Form Tour",
|
"action": "Show Form Tour",
|
||||||
"action_label": "Let's review existing Asset Category",
|
"action_label": "Let's review existing Asset Category",
|
||||||
"creation": "2021-08-13 14:26:18.656303",
|
"creation": "2021-08-13 14:26:18.656303",
|
||||||
"description": "# Asset Category\n\nAn Asset Category classifies different assets of a Company.\n\nYou can create an Asset Category based on the type of assets. For example, all your desktops and laptops can be part of an Asset Category named \"Electronic Equipments\". Create a separate category for furniture. Also, you can update default properties for each category, like:\n - Depreciation type and duration\n - Fixed asset account\n - Depreciation account\n",
|
"description": "# Asset Category\n\nAn Asset Category classifies different assets of a Company.\n\nYou can create an Asset Category based on the type of assets. For example, all your desktops and laptops can be part of an Asset Category named \"Electronic Equipment\". Create a separate category for furniture. Also, you can update default properties for each category, like:\n - Depreciation type and duration\n - Fixed asset account\n - Depreciation account\n",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Onboarding Step",
|
"doctype": "Onboarding Step",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_complete": 0,
|
"is_complete": 0,
|
||||||
"is_single": 0,
|
"is_single": 0,
|
||||||
"is_skipped": 0,
|
"is_skipped": 0,
|
||||||
"modified": "2021-11-23 10:02:03.242127",
|
"modified": "2024-01-24 02:20:26.145996",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"name": "Asset Category",
|
"name": "Asset Category",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
|||||||
@ -202,7 +202,7 @@ def prepare_chart_data(data, filters):
|
|||||||
"values": [flt(d.get("asset_value"), 2) for d in labels_values_map.values()],
|
"values": [flt(d.get("asset_value"), 2) for d in labels_values_map.values()],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": _("Depreciatied Amount"),
|
"name": _("Depreciated Amount"),
|
||||||
"values": [flt(d.get("depreciated_amount"), 2) for d in labels_values_map.values()],
|
"values": [flt(d.get("depreciated_amount"), 2) for d in labels_values_map.values()],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -196,18 +196,18 @@
|
|||||||
"type": "Link"
|
"type": "Link"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2023-05-24 14:47:20.243146",
|
"modified": "2024-01-05 17:40:34.570041",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Assets",
|
"module": "Assets",
|
||||||
"name": "Assets",
|
"name": "Assets",
|
||||||
"number_cards": [],
|
"number_cards": [],
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"parent_page": "Accounting",
|
"parent_page": "",
|
||||||
"public": 1,
|
"public": 1,
|
||||||
"quick_lists": [],
|
"quick_lists": [],
|
||||||
"restrict_to_domain": "",
|
"restrict_to_domain": "",
|
||||||
"roles": [],
|
"roles": [],
|
||||||
"sequence_id": 4.0,
|
"sequence_id": 7.0,
|
||||||
"shortcuts": [
|
"shortcuts": [
|
||||||
{
|
{
|
||||||
"label": "Asset",
|
"label": "Asset",
|
||||||
|
|||||||
@ -214,7 +214,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-01-05 15:26:02.320942",
|
"modified": "2024-01-12 16:42:01.894346",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Buying Settings",
|
"name": "Buying Settings",
|
||||||
@ -240,39 +240,24 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"email": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"role": "Accounts User",
|
"role": "Accounts User"
|
||||||
"share": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"email": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"role": "Accounts Manager",
|
"role": "Accounts Manager"
|
||||||
"share": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"email": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"role": "Stock Manager",
|
"role": "Stock Manager"
|
||||||
"share": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"email": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"role": "Stock User",
|
"role": "Stock User"
|
||||||
"share": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"email": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"role": "Purchase User",
|
"role": "Purchase User"
|
||||||
"share": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
|
|||||||
@ -134,6 +134,7 @@
|
|||||||
"more_info_tab",
|
"more_info_tab",
|
||||||
"tracking_section",
|
"tracking_section",
|
||||||
"status",
|
"status",
|
||||||
|
"advance_payment_status",
|
||||||
"column_break_75",
|
"column_break_75",
|
||||||
"per_billed",
|
"per_billed",
|
||||||
"per_received",
|
"per_received",
|
||||||
@ -1269,13 +1270,25 @@
|
|||||||
"fieldtype": "Tab Break",
|
"fieldtype": "Tab Break",
|
||||||
"label": "Connections",
|
"label": "Connections",
|
||||||
"show_dashboard": 1
|
"show_dashboard": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "advance_payment_status",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Advance Payment Status",
|
||||||
|
"no_copy": 1,
|
||||||
|
"oldfieldname": "status",
|
||||||
|
"oldfieldtype": "Select",
|
||||||
|
"options": "Not Initiated\nInitiated\nPartially Paid\nFully Paid",
|
||||||
|
"print_hide": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 105,
|
"idx": 105,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-10-01 20:58:07.851037",
|
"modified": "2023-10-10 13:37:40.158761",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order",
|
"name": "Purchase Order",
|
||||||
@ -1330,4 +1343,4 @@
|
|||||||
"timeline_field": "supplier",
|
"timeline_field": "supplier",
|
||||||
"title_field": "supplier_name",
|
"title_field": "supplier_name",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
|
|||||||
@ -215,6 +215,10 @@ class PurchaseOrder(BuyingController):
|
|||||||
|
|
||||||
self.validate_fg_item_for_subcontracting()
|
self.validate_fg_item_for_subcontracting()
|
||||||
self.set_received_qty_for_drop_ship_items()
|
self.set_received_qty_for_drop_ship_items()
|
||||||
|
|
||||||
|
if not self.advance_payment_status:
|
||||||
|
self.advance_payment_status = "Not Initiated"
|
||||||
|
|
||||||
validate_inter_company_party(
|
validate_inter_company_party(
|
||||||
self.doctype, self.supplier, self.company, self.inter_company_order_reference
|
self.doctype, self.supplier, self.company, self.inter_company_order_reference
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
frappe.listview_settings['Purchase Order'] = {
|
frappe.listview_settings['Purchase Order'] = {
|
||||||
add_fields: ["base_grand_total", "company", "currency", "supplier",
|
add_fields: ["base_grand_total", "company", "currency", "supplier",
|
||||||
"supplier_name", "per_received", "per_billed", "status"],
|
"supplier_name", "per_received", "per_billed", "status", "advance_payment_status"],
|
||||||
get_indicator: function (doc) {
|
get_indicator: function (doc) {
|
||||||
if (doc.status === "Closed") {
|
if (doc.status === "Closed") {
|
||||||
return [__("Closed"), "green", "status,=,Closed"];
|
return [__("Closed"), "green", "status,=,Closed"];
|
||||||
@ -8,6 +8,8 @@ frappe.listview_settings['Purchase Order'] = {
|
|||||||
return [__("On Hold"), "orange", "status,=,On Hold"];
|
return [__("On Hold"), "orange", "status,=,On Hold"];
|
||||||
} else if (doc.status === "Delivered") {
|
} else if (doc.status === "Delivered") {
|
||||||
return [__("Delivered"), "green", "status,=,Closed"];
|
return [__("Delivered"), "green", "status,=,Closed"];
|
||||||
|
} else if (doc.advance_payment_status == "Initiated") {
|
||||||
|
return [__("To Pay"), "gray", "advance_payment_status,=,Initiated"];
|
||||||
} else if (flt(doc.per_received, 2) < 100 && doc.status !== "Closed") {
|
} else if (flt(doc.per_received, 2) < 100 && doc.status !== "Closed") {
|
||||||
if (flt(doc.per_billed, 2) < 100) {
|
if (flt(doc.per_billed, 2) < 100) {
|
||||||
return [__("To Receive and Bill"), "orange",
|
return [__("To Receive and Bill"), "orange",
|
||||||
|
|||||||
@ -1021,6 +1021,33 @@ class TestPurchaseOrder(FrappeTestCase):
|
|||||||
|
|
||||||
self.assertTrue(frappe.db.get_value("Subcontracting Order", {"purchase_order": po.name}))
|
self.assertTrue(frappe.db.get_value("Subcontracting Order", {"purchase_order": po.name}))
|
||||||
|
|
||||||
|
def test_purchase_order_advance_payment_status(self):
|
||||||
|
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
|
||||||
|
from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request
|
||||||
|
|
||||||
|
po = create_purchase_order()
|
||||||
|
self.assertEqual(
|
||||||
|
frappe.db.get_value(po.doctype, po.name, "advance_payment_status"), "Not Initiated"
|
||||||
|
)
|
||||||
|
|
||||||
|
pr = make_payment_request(dt=po.doctype, dn=po.name, submit_doc=True, return_doc=True)
|
||||||
|
self.assertEqual(frappe.db.get_value(po.doctype, po.name, "advance_payment_status"), "Initiated")
|
||||||
|
|
||||||
|
pe = get_payment_entry(po.doctype, po.name).save().submit()
|
||||||
|
self.assertEqual(
|
||||||
|
frappe.db.get_value(po.doctype, po.name, "advance_payment_status"), "Fully Paid"
|
||||||
|
)
|
||||||
|
|
||||||
|
pe.reload()
|
||||||
|
pe.cancel()
|
||||||
|
self.assertEqual(frappe.db.get_value(po.doctype, po.name, "advance_payment_status"), "Initiated")
|
||||||
|
|
||||||
|
pr.reload()
|
||||||
|
pr.cancel()
|
||||||
|
self.assertEqual(
|
||||||
|
frappe.db.get_value(po.doctype, po.name, "advance_payment_status"), "Not Initiated"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def prepare_data_for_internal_transfer():
|
def prepare_data_for_internal_transfer():
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
|
||||||
|
|||||||
@ -54,7 +54,7 @@ frappe.query_reports["Purchase Order Analysis"] = {
|
|||||||
"fieldtype": "MultiSelectList",
|
"fieldtype": "MultiSelectList",
|
||||||
"width": "80",
|
"width": "80",
|
||||||
get_data: function(txt) {
|
get_data: function(txt) {
|
||||||
let status = ["To Bill", "To Receive", "To Receive and Bill", "Completed"]
|
let status = ["To Pay", "To Bill", "To Receive", "To Receive and Bill", "Completed"]
|
||||||
let options = []
|
let options = []
|
||||||
for (let option of status){
|
for (let option of status){
|
||||||
options.push({
|
options.push({
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import json
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _, bold, qb, throw
|
from frappe import _, bold, qb, throw
|
||||||
from frappe.model.workflow import get_workflow_name, is_transition_condition_satisfied
|
from frappe.model.workflow import get_workflow_name, is_transition_condition_satisfied
|
||||||
|
from frappe.query_builder import Criterion
|
||||||
from frappe.query_builder.custom import ConstantColumn
|
from frappe.query_builder.custom import ConstantColumn
|
||||||
from frappe.query_builder.functions import Abs, Sum
|
from frappe.query_builder.functions import Abs, Sum
|
||||||
from frappe.utils import (
|
from frappe.utils import (
|
||||||
@ -27,6 +28,7 @@ from frappe.utils import (
|
|||||||
import erpnext
|
import erpnext
|
||||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||||
get_accounting_dimensions,
|
get_accounting_dimensions,
|
||||||
|
get_dimensions,
|
||||||
)
|
)
|
||||||
from erpnext.accounts.doctype.pricing_rule.utils import (
|
from erpnext.accounts.doctype.pricing_rule.utils import (
|
||||||
apply_pricing_rule_for_free_items,
|
apply_pricing_rule_for_free_items,
|
||||||
@ -930,7 +932,7 @@ class AccountsController(TransactionBase):
|
|||||||
# Update details in transaction currency
|
# Update details in transaction currency
|
||||||
gl_dict.update(
|
gl_dict.update(
|
||||||
{
|
{
|
||||||
"transaction_currency": args.get("currency") or self.get("currency") or self.company_currency,
|
"transaction_currency": self.get("currency") or self.company_currency,
|
||||||
"transaction_exchange_rate": self.get("conversion_rate", 1),
|
"transaction_exchange_rate": self.get("conversion_rate", 1),
|
||||||
"debit_in_transaction_currency": self.get_value_in_transaction_currency(
|
"debit_in_transaction_currency": self.get_value_in_transaction_currency(
|
||||||
account_currency, args, "debit"
|
account_currency, args, "debit"
|
||||||
@ -969,10 +971,10 @@ class AccountsController(TransactionBase):
|
|||||||
return self.doctype
|
return self.doctype
|
||||||
|
|
||||||
def get_value_in_transaction_currency(self, account_currency, args, field):
|
def get_value_in_transaction_currency(self, account_currency, args, field):
|
||||||
if account_currency == args.get("currency") or self.get("currency"):
|
if account_currency == self.get("currency"):
|
||||||
return args.get(field + "_in_account_currency")
|
return args.get(field + "_in_account_currency")
|
||||||
else:
|
else:
|
||||||
return flt(args.get(field, 0) / (args.get("conversion_rate") or self.get("conversion_rate", 1)))
|
return flt(args.get(field, 0) / self.get("conversion_rate", 1))
|
||||||
|
|
||||||
def validate_qty_is_not_zero(self):
|
def validate_qty_is_not_zero(self):
|
||||||
for item in self.items:
|
for item in self.items:
|
||||||
@ -1161,7 +1163,6 @@ class AccountsController(TransactionBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
credit_or_debit = "credit" if self.doctype == "Purchase Invoice" else "debit"
|
credit_or_debit = "credit" if self.doctype == "Purchase Invoice" else "debit"
|
||||||
against_type = "Supplier" if self.doctype == "Purchase Invoice" else "Customer"
|
|
||||||
against = self.supplier if self.doctype == "Purchase Invoice" else self.customer
|
against = self.supplier if self.doctype == "Purchase Invoice" else self.customer
|
||||||
|
|
||||||
if precision_loss:
|
if precision_loss:
|
||||||
@ -1169,9 +1170,7 @@ class AccountsController(TransactionBase):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": round_off_account,
|
"account": round_off_account,
|
||||||
"against_type": against_type,
|
|
||||||
"against": against,
|
"against": against,
|
||||||
"against_link": against,
|
|
||||||
credit_or_debit: precision_loss,
|
credit_or_debit: precision_loss,
|
||||||
"cost_center": round_off_cost_center
|
"cost_center": round_off_cost_center
|
||||||
if self.use_company_roundoff_cost_center
|
if self.use_company_roundoff_cost_center
|
||||||
@ -1219,7 +1218,9 @@ class AccountsController(TransactionBase):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def make_exchange_gain_loss_journal(self, args: dict = None) -> None:
|
def make_exchange_gain_loss_journal(
|
||||||
|
self, args: dict = None, dimensions_dict: dict = None
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Make Exchange Gain/Loss journal for Invoices and Payments
|
Make Exchange Gain/Loss journal for Invoices and Payments
|
||||||
"""
|
"""
|
||||||
@ -1274,6 +1275,7 @@ class AccountsController(TransactionBase):
|
|||||||
self.name,
|
self.name,
|
||||||
arg.get("referenced_row"),
|
arg.get("referenced_row"),
|
||||||
arg.get("cost_center"),
|
arg.get("cost_center"),
|
||||||
|
dimensions_dict,
|
||||||
)
|
)
|
||||||
frappe.msgprint(
|
frappe.msgprint(
|
||||||
_("Exchange Gain/Loss amount has been booked through {0}").format(
|
_("Exchange Gain/Loss amount has been booked through {0}").format(
|
||||||
@ -1354,6 +1356,7 @@ class AccountsController(TransactionBase):
|
|||||||
self.name,
|
self.name,
|
||||||
d.idx,
|
d.idx,
|
||||||
self.cost_center,
|
self.cost_center,
|
||||||
|
dimensions_dict,
|
||||||
)
|
)
|
||||||
frappe.msgprint(
|
frappe.msgprint(
|
||||||
_("Exchange Gain/Loss amount has been booked through {0}").format(
|
_("Exchange Gain/Loss amount has been booked through {0}").format(
|
||||||
@ -1418,7 +1421,13 @@ class AccountsController(TransactionBase):
|
|||||||
if lst:
|
if lst:
|
||||||
from erpnext.accounts.utils import reconcile_against_document
|
from erpnext.accounts.utils import reconcile_against_document
|
||||||
|
|
||||||
reconcile_against_document(lst)
|
# pass dimension values to utility method
|
||||||
|
active_dimensions = get_dimensions()[0]
|
||||||
|
for x in lst:
|
||||||
|
for dim in active_dimensions:
|
||||||
|
if self.get(dim.fieldname):
|
||||||
|
x.update({dim.fieldname: self.get(dim.fieldname)})
|
||||||
|
reconcile_against_document(lst, active_dimensions=active_dimensions)
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
from erpnext.accounts.doctype.bank_transaction.bank_transaction import (
|
from erpnext.accounts.doctype.bank_transaction.bank_transaction import (
|
||||||
@ -1525,13 +1534,11 @@ class AccountsController(TransactionBase):
|
|||||||
if self.doctype == "Purchase Invoice":
|
if self.doctype == "Purchase Invoice":
|
||||||
dr_or_cr = "credit"
|
dr_or_cr = "credit"
|
||||||
rev_dr_cr = "debit"
|
rev_dr_cr = "debit"
|
||||||
against_type = "Supplier"
|
|
||||||
supplier_or_customer = self.supplier
|
supplier_or_customer = self.supplier
|
||||||
|
|
||||||
else:
|
else:
|
||||||
dr_or_cr = "debit"
|
dr_or_cr = "debit"
|
||||||
rev_dr_cr = "credit"
|
rev_dr_cr = "credit"
|
||||||
against_type = "Customer"
|
|
||||||
supplier_or_customer = self.customer
|
supplier_or_customer = self.customer
|
||||||
|
|
||||||
if enable_discount_accounting:
|
if enable_discount_accounting:
|
||||||
@ -1556,9 +1563,7 @@ class AccountsController(TransactionBase):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": item.discount_account,
|
"account": item.discount_account,
|
||||||
"against_type": against_type,
|
|
||||||
"against": supplier_or_customer,
|
"against": supplier_or_customer,
|
||||||
"against_link": supplier_or_customer,
|
|
||||||
dr_or_cr: flt(
|
dr_or_cr: flt(
|
||||||
discount_amount * self.get("conversion_rate"), item.precision("discount_amount")
|
discount_amount * self.get("conversion_rate"), item.precision("discount_amount")
|
||||||
),
|
),
|
||||||
@ -1576,9 +1581,7 @@ class AccountsController(TransactionBase):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": income_or_expense_account,
|
"account": income_or_expense_account,
|
||||||
"against_type": against_type,
|
|
||||||
"against": supplier_or_customer,
|
"against": supplier_or_customer,
|
||||||
"against_link": supplier_or_customer,
|
|
||||||
rev_dr_cr: flt(
|
rev_dr_cr: flt(
|
||||||
discount_amount * self.get("conversion_rate"), item.precision("discount_amount")
|
discount_amount * self.get("conversion_rate"), item.precision("discount_amount")
|
||||||
),
|
),
|
||||||
@ -1601,9 +1604,7 @@ class AccountsController(TransactionBase):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": self.additional_discount_account,
|
"account": self.additional_discount_account,
|
||||||
"against_type": against_type,
|
|
||||||
"against": supplier_or_customer,
|
"against": supplier_or_customer,
|
||||||
"against_link": supplier_or_customer,
|
|
||||||
dr_or_cr: self.base_discount_amount,
|
dr_or_cr: self.base_discount_amount,
|
||||||
"cost_center": self.cost_center or erpnext.get_default_cost_center(self.company),
|
"cost_center": self.cost_center or erpnext.get_default_cost_center(self.company),
|
||||||
},
|
},
|
||||||
@ -1760,7 +1761,10 @@ class AccountsController(TransactionBase):
|
|||||||
|
|
||||||
def set_total_advance_paid(self):
|
def set_total_advance_paid(self):
|
||||||
ple = frappe.qb.DocType("Payment Ledger Entry")
|
ple = frappe.qb.DocType("Payment Ledger Entry")
|
||||||
party = self.customer if self.doctype == "Sales Order" else self.supplier
|
if self.doctype in frappe.get_hooks("advance_payment_customer_doctypes"):
|
||||||
|
party = self.customer
|
||||||
|
if self.doctype in frappe.get_hooks("advance_payment_supplier_doctypes"):
|
||||||
|
party = self.supplier
|
||||||
advance = (
|
advance = (
|
||||||
frappe.qb.from_(ple)
|
frappe.qb.from_(ple)
|
||||||
.select(ple.account_currency, Abs(Sum(ple.amount_in_account_currency)).as_("amount"))
|
.select(ple.account_currency, Abs(Sum(ple.amount_in_account_currency)).as_("amount"))
|
||||||
@ -1774,6 +1778,8 @@ class AccountsController(TransactionBase):
|
|||||||
.run(as_dict=True)
|
.run(as_dict=True)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
advance_paid, order_total = None, None
|
||||||
|
|
||||||
if advance:
|
if advance:
|
||||||
advance = advance[0]
|
advance = advance[0]
|
||||||
|
|
||||||
@ -1802,7 +1808,38 @@ class AccountsController(TransactionBase):
|
|||||||
).format(formatted_advance_paid, self.name, formatted_order_total)
|
).format(formatted_advance_paid, self.name, formatted_order_total)
|
||||||
)
|
)
|
||||||
|
|
||||||
frappe.db.set_value(self.doctype, self.name, "advance_paid", advance_paid)
|
self.db_set("advance_paid", advance_paid)
|
||||||
|
|
||||||
|
self.set_advance_payment_status(advance_paid, order_total)
|
||||||
|
|
||||||
|
def set_advance_payment_status(
|
||||||
|
self, advance_paid: float | None = None, order_total: float | None = None
|
||||||
|
):
|
||||||
|
new_status = None
|
||||||
|
# if money is paid set the paid states
|
||||||
|
if advance_paid:
|
||||||
|
new_status = "Partially Paid" if advance_paid < order_total else "Fully Paid"
|
||||||
|
|
||||||
|
if not new_status:
|
||||||
|
prs = frappe.db.count(
|
||||||
|
"Payment Request",
|
||||||
|
{
|
||||||
|
"reference_doctype": self.doctype,
|
||||||
|
"reference_name": self.name,
|
||||||
|
"docstatus": 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if self.doctype in frappe.get_hooks("advance_payment_customer_doctypes"):
|
||||||
|
new_status = "Requested" if prs else "Not Requested"
|
||||||
|
if self.doctype in frappe.get_hooks("advance_payment_supplier_doctypes"):
|
||||||
|
new_status = "Initiated" if prs else "Not Initiated"
|
||||||
|
|
||||||
|
if new_status == self.advance_payment_status:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.db_set("advance_payment_status", new_status)
|
||||||
|
self.set_status(update=True)
|
||||||
|
self.notify_update()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def company_abbr(self):
|
def company_abbr(self):
|
||||||
@ -2695,47 +2732,37 @@ def get_common_query(
|
|||||||
q = q.select((payment_entry.target_exchange_rate).as_("exchange_rate"))
|
q = q.select((payment_entry.target_exchange_rate).as_("exchange_rate"))
|
||||||
|
|
||||||
if condition:
|
if condition:
|
||||||
if condition.get("name", None):
|
# conditions should be built as an array and passed as Criterion
|
||||||
q = q.where(payment_entry.name.like(f"%{condition.get('name')}%"))
|
common_filter_conditions = []
|
||||||
|
|
||||||
|
common_filter_conditions.append(payment_entry.company == condition["company"])
|
||||||
|
if condition.get("name", None):
|
||||||
|
common_filter_conditions.append(payment_entry.name.like(f"%{condition.get('name')}%"))
|
||||||
|
|
||||||
|
if condition.get("from_payment_date"):
|
||||||
|
common_filter_conditions.append(payment_entry.posting_date.gte(condition["from_payment_date"]))
|
||||||
|
|
||||||
|
if condition.get("to_payment_date"):
|
||||||
|
common_filter_conditions.append(payment_entry.posting_date.lte(condition["to_payment_date"]))
|
||||||
|
|
||||||
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:
|
if condition.get("get_payments") == True:
|
||||||
q = (
|
if condition.get("cost_center"):
|
||||||
q.where(payment_entry.cost_center == condition["cost_center"])
|
common_filter_conditions.append(payment_entry.cost_center == condition["cost_center"])
|
||||||
if condition.get("cost_center")
|
|
||||||
else q
|
if condition.get("accounting_dimensions"):
|
||||||
)
|
for field, val in condition.get("accounting_dimensions").items():
|
||||||
q = (
|
common_filter_conditions.append(payment_entry[field] == val)
|
||||||
q.where(payment_entry.unallocated_amount >= condition["minimum_payment_amount"])
|
|
||||||
if condition.get("minimum_payment_amount")
|
if condition.get("minimum_payment_amount"):
|
||||||
else q
|
common_filter_conditions.append(
|
||||||
)
|
payment_entry.unallocated_amount.gte(condition["minimum_payment_amount"])
|
||||||
q = (
|
)
|
||||||
q.where(payment_entry.unallocated_amount <= condition["maximum_payment_amount"])
|
|
||||||
if condition.get("maximum_payment_amount")
|
if condition.get("maximum_payment_amount"):
|
||||||
else q
|
common_filter_conditions.append(
|
||||||
)
|
payment_entry.unallocated_amount.lte(condition["maximum_payment_amount"])
|
||||||
else:
|
)
|
||||||
q = (
|
q = q.where(Criterion.all(common_filter_conditions))
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
q = q.orderby(payment_entry.posting_date)
|
q = q.orderby(payment_entry.posting_date)
|
||||||
q = q.limit(limit) if limit else q
|
q = q.limit(limit) if limit else q
|
||||||
|
|||||||
@ -56,7 +56,11 @@ def make_variant_based_on_manufacturer(template, manufacturer, manufacturer_part
|
|||||||
|
|
||||||
copy_attributes_to_variant(template, variant)
|
copy_attributes_to_variant(template, variant)
|
||||||
|
|
||||||
variant.item_code = append_number_if_name_exists("Item", template.name)
|
variant_name = f"{template.name} - {manufacturer}"
|
||||||
|
if manufacturer_part_no:
|
||||||
|
variant_name += f" - {manufacturer_part_no}"
|
||||||
|
|
||||||
|
variant.item_code = append_number_if_name_exists("Item", variant_name)
|
||||||
variant.flags.ignore_mandatory = True
|
variant.flags.ignore_mandatory = True
|
||||||
variant.save()
|
variant.save()
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,12 @@ import json
|
|||||||
from collections import OrderedDict, defaultdict
|
from collections import OrderedDict, defaultdict
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import scrub
|
from frappe import qb, scrub
|
||||||
from frappe.desk.reportview import get_filters_cond, get_match_cond
|
from frappe.desk.reportview import get_filters_cond, get_match_cond
|
||||||
from frappe.query_builder.functions import Concat, Sum
|
from frappe.query_builder import Criterion, CustomFunction
|
||||||
|
from frappe.query_builder.functions import Concat, Locate, Sum
|
||||||
from frappe.utils import nowdate, today, unique
|
from frappe.utils import nowdate, today, unique
|
||||||
|
from pypika import Order
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
from erpnext.stock.get_item_details import _get_item_tax_template
|
from erpnext.stock.get_item_details import _get_item_tax_template
|
||||||
@ -344,37 +346,46 @@ def bom(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@frappe.validate_and_sanitize_search_inputs
|
@frappe.validate_and_sanitize_search_inputs
|
||||||
def get_project_name(doctype, txt, searchfield, start, page_len, filters):
|
def get_project_name(doctype, txt, searchfield, start, page_len, filters):
|
||||||
doctype = "Project"
|
proj = qb.DocType("Project")
|
||||||
cond = ""
|
qb_filter_and_conditions = []
|
||||||
|
qb_filter_or_conditions = []
|
||||||
|
ifelse = CustomFunction("IF", ["condition", "then", "else"])
|
||||||
|
|
||||||
if filters and filters.get("customer"):
|
if filters and filters.get("customer"):
|
||||||
cond = """(`tabProject`.customer = %s or
|
qb_filter_and_conditions.append(proj.customer == filters.get("customer"))
|
||||||
ifnull(`tabProject`.customer,"")="") and""" % (
|
|
||||||
frappe.db.escape(filters.get("customer"))
|
qb_filter_and_conditions.append(proj.status.notin(["Completed", "Cancelled"]))
|
||||||
)
|
|
||||||
|
q = qb.from_(proj)
|
||||||
|
|
||||||
fields = get_fields(doctype, ["name", "project_name"])
|
fields = get_fields(doctype, ["name", "project_name"])
|
||||||
searchfields = frappe.get_meta(doctype).get_search_fields()
|
for x in fields:
|
||||||
searchfields = " or ".join(["`tabProject`." + field + " like %(txt)s" for field in searchfields])
|
q = q.select(proj[x])
|
||||||
|
|
||||||
return frappe.db.sql(
|
# don't consider 'customer' and 'status' fields for pattern search, as they must be exactly matched
|
||||||
"""select {fields} from `tabProject`
|
searchfields = [
|
||||||
where
|
x for x in frappe.get_meta(doctype).get_search_fields() if x not in ["customer", "status"]
|
||||||
`tabProject`.status not in ('Completed', 'Cancelled')
|
]
|
||||||
and {cond} {scond} {match_cond}
|
|
||||||
order by
|
# pattern search
|
||||||
(case when locate(%(_txt)s, `tabProject`.name) > 0 then locate(%(_txt)s, `tabProject`.name) else 99999 end),
|
if txt:
|
||||||
`tabProject`.idx desc,
|
for x in searchfields:
|
||||||
`tabProject`.name asc
|
qb_filter_or_conditions.append(proj[x].like(f"%{txt}%"))
|
||||||
limit {page_len} offset {start}""".format(
|
|
||||||
fields=", ".join(["`tabProject`.{0}".format(f) for f in fields]),
|
q = q.where(Criterion.all(qb_filter_and_conditions)).where(Criterion.any(qb_filter_or_conditions))
|
||||||
cond=cond,
|
|
||||||
scond=searchfields,
|
# ordering
|
||||||
match_cond=get_match_cond(doctype),
|
if txt:
|
||||||
start=start,
|
# project_name containing search string 'txt' will be given higher precedence
|
||||||
page_len=page_len,
|
q = q.orderby(ifelse(Locate(txt, proj.project_name) > 0, Locate(txt, proj.project_name), 99999))
|
||||||
),
|
q = q.orderby(proj.idx, order=Order.desc).orderby(proj.name)
|
||||||
{"txt": "%{0}%".format(txt), "_txt": txt.replace("%", "")},
|
|
||||||
)
|
if page_len:
|
||||||
|
q = q.limit(page_len)
|
||||||
|
|
||||||
|
if start:
|
||||||
|
q = q.offset(start)
|
||||||
|
return q.run()
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@ -421,23 +432,14 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
meta = frappe.get_meta(doctype, cached=True)
|
meta = frappe.get_meta(doctype, cached=True)
|
||||||
searchfields = meta.get_search_fields()
|
searchfields = meta.get_search_fields()
|
||||||
|
|
||||||
query = get_batches_from_stock_ledger_entries(searchfields, txt, filters)
|
batches = get_batches_from_stock_ledger_entries(searchfields, txt, filters, start, page_len)
|
||||||
bundle_query = get_batches_from_serial_and_batch_bundle(searchfields, txt, filters)
|
batches.extend(
|
||||||
|
get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start, page_len)
|
||||||
data = (
|
|
||||||
frappe.qb.from_((query) + (bundle_query))
|
|
||||||
.select("batch_no", "qty", "manufacturing_date", "expiry_date")
|
|
||||||
.offset(start)
|
|
||||||
.limit(page_len)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for field in searchfields:
|
filtered_batches = get_filterd_batches(batches)
|
||||||
data = data.select(field)
|
|
||||||
|
|
||||||
data = data.run()
|
return filtered_batches
|
||||||
data = get_filterd_batches(data)
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def get_filterd_batches(data):
|
def get_filterd_batches(data):
|
||||||
@ -457,7 +459,7 @@ def get_filterd_batches(data):
|
|||||||
return filterd_batch
|
return filterd_batch
|
||||||
|
|
||||||
|
|
||||||
def get_batches_from_stock_ledger_entries(searchfields, txt, filters):
|
def get_batches_from_stock_ledger_entries(searchfields, txt, filters, start=0, page_len=100):
|
||||||
stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
|
stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
|
||||||
batch_table = frappe.qb.DocType("Batch")
|
batch_table = frappe.qb.DocType("Batch")
|
||||||
|
|
||||||
@ -479,6 +481,8 @@ def get_batches_from_stock_ledger_entries(searchfields, txt, filters):
|
|||||||
& (stock_ledger_entry.batch_no.isnotnull())
|
& (stock_ledger_entry.batch_no.isnotnull())
|
||||||
)
|
)
|
||||||
.groupby(stock_ledger_entry.batch_no, stock_ledger_entry.warehouse)
|
.groupby(stock_ledger_entry.batch_no, stock_ledger_entry.warehouse)
|
||||||
|
.offset(start)
|
||||||
|
.limit(page_len)
|
||||||
)
|
)
|
||||||
|
|
||||||
query = query.select(
|
query = query.select(
|
||||||
@ -493,16 +497,16 @@ def get_batches_from_stock_ledger_entries(searchfields, txt, filters):
|
|||||||
query = query.select(batch_table[field])
|
query = query.select(batch_table[field])
|
||||||
|
|
||||||
if txt:
|
if txt:
|
||||||
txt_condition = batch_table.name.like(txt)
|
txt_condition = batch_table.name.like("%{0}%".format(txt))
|
||||||
for field in searchfields + ["name"]:
|
for field in searchfields + ["name"]:
|
||||||
txt_condition |= batch_table[field].like(txt)
|
txt_condition |= batch_table[field].like("%{0}%".format(txt))
|
||||||
|
|
||||||
query = query.where(txt_condition)
|
query = query.where(txt_condition)
|
||||||
|
|
||||||
return query
|
return query.run(as_list=1) or []
|
||||||
|
|
||||||
|
|
||||||
def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters):
|
def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters, start=0, page_len=100):
|
||||||
bundle = frappe.qb.DocType("Serial and Batch Entry")
|
bundle = frappe.qb.DocType("Serial and Batch Entry")
|
||||||
stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
|
stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
|
||||||
batch_table = frappe.qb.DocType("Batch")
|
batch_table = frappe.qb.DocType("Batch")
|
||||||
@ -527,6 +531,8 @@ def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters):
|
|||||||
& (stock_ledger_entry.serial_and_batch_bundle.isnotnull())
|
& (stock_ledger_entry.serial_and_batch_bundle.isnotnull())
|
||||||
)
|
)
|
||||||
.groupby(bundle.batch_no, bundle.warehouse)
|
.groupby(bundle.batch_no, bundle.warehouse)
|
||||||
|
.offset(start)
|
||||||
|
.limit(page_len)
|
||||||
)
|
)
|
||||||
|
|
||||||
bundle_query = bundle_query.select(
|
bundle_query = bundle_query.select(
|
||||||
@ -541,13 +547,13 @@ def get_batches_from_serial_and_batch_bundle(searchfields, txt, filters):
|
|||||||
bundle_query = bundle_query.select(batch_table[field])
|
bundle_query = bundle_query.select(batch_table[field])
|
||||||
|
|
||||||
if txt:
|
if txt:
|
||||||
txt_condition = batch_table.name.like(txt)
|
txt_condition = batch_table.name.like("%{0}%".format(txt))
|
||||||
for field in searchfields + ["name"]:
|
for field in searchfields + ["name"]:
|
||||||
txt_condition |= batch_table[field].like(txt)
|
txt_condition |= batch_table[field].like("%{0}%".format(txt))
|
||||||
|
|
||||||
bundle_query = bundle_query.where(txt_condition)
|
bundle_query = bundle_query.where(txt_condition)
|
||||||
|
|
||||||
return bundle_query
|
return bundle_query.run(as_list=1)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@ -141,7 +141,7 @@ def validate_returned_items(doc):
|
|||||||
items_returned = True
|
items_returned = True
|
||||||
|
|
||||||
if not items_returned:
|
if not items_returned:
|
||||||
frappe.throw(_("Atleast one item should be entered with negative quantity in return document"))
|
frappe.throw(_("At least one item should be entered with negative quantity in return document"))
|
||||||
|
|
||||||
|
|
||||||
def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
||||||
|
|||||||
@ -53,6 +53,10 @@ status_map = {
|
|||||||
"To Deliver",
|
"To Deliver",
|
||||||
"eval:self.per_delivered < 100 and self.per_billed >= 100 and self.docstatus == 1 and not self.skip_delivery_note",
|
"eval:self.per_delivered < 100 and self.per_billed >= 100 and self.docstatus == 1 and not self.skip_delivery_note",
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"To Pay",
|
||||||
|
"eval:self.advance_payment_status == 'Requested' and self.docstatus == 1",
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"Completed",
|
"Completed",
|
||||||
"eval:(self.per_delivered >= 100 or self.skip_delivery_note) and self.per_billed >= 100 and self.docstatus == 1",
|
"eval:(self.per_delivered >= 100 or self.skip_delivery_note) and self.per_billed >= 100 and self.docstatus == 1",
|
||||||
@ -63,15 +67,19 @@ status_map = {
|
|||||||
],
|
],
|
||||||
"Purchase Order": [
|
"Purchase Order": [
|
||||||
["Draft", None],
|
["Draft", None],
|
||||||
[
|
|
||||||
"To Receive and Bill",
|
|
||||||
"eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1",
|
|
||||||
],
|
|
||||||
["To Bill", "eval:self.per_received >= 100 and self.per_billed < 100 and self.docstatus == 1"],
|
["To Bill", "eval:self.per_received >= 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||||
[
|
[
|
||||||
"To Receive",
|
"To Receive",
|
||||||
"eval:self.per_received < 100 and self.per_billed == 100 and self.docstatus == 1",
|
"eval:self.per_received < 100 and self.per_billed == 100 and self.docstatus == 1",
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"To Receive and Bill",
|
||||||
|
"eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"To Pay",
|
||||||
|
"eval:self.advance_payment_status == 'Initiated' and self.docstatus == 1",
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"Completed",
|
"Completed",
|
||||||
"eval:self.per_received >= 100 and self.per_billed == 100 and self.docstatus == 1",
|
"eval:self.per_received >= 100 and self.per_billed == 100 and self.docstatus == 1",
|
||||||
|
|||||||
@ -162,9 +162,7 @@ class StockController(AccountsController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": warehouse_account[sle.warehouse]["account"],
|
"account": warehouse_account[sle.warehouse]["account"],
|
||||||
"against_type": "Account",
|
|
||||||
"against": expense_account,
|
"against": expense_account,
|
||||||
"against_link": expense_account,
|
|
||||||
"cost_center": item_row.cost_center,
|
"cost_center": item_row.cost_center,
|
||||||
"project": item_row.project or self.get("project"),
|
"project": item_row.project or self.get("project"),
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
@ -180,9 +178,7 @@ class StockController(AccountsController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": expense_account,
|
"account": expense_account,
|
||||||
"against_type": "Account",
|
|
||||||
"against": warehouse_account[sle.warehouse]["account"],
|
"against": warehouse_account[sle.warehouse]["account"],
|
||||||
"against_link": warehouse_account[sle.warehouse]["account"],
|
|
||||||
"cost_center": item_row.cost_center,
|
"cost_center": item_row.cost_center,
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
"debit": -1 * flt(sle.stock_value_difference, precision),
|
"debit": -1 * flt(sle.stock_value_difference, precision),
|
||||||
@ -214,9 +210,7 @@ class StockController(AccountsController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": expense_account,
|
"account": expense_account,
|
||||||
"against_type": "Account",
|
|
||||||
"against": warehouse_asset_account,
|
"against": warehouse_asset_account,
|
||||||
"against_link": warehouse_asset_account,
|
|
||||||
"cost_center": item_row.cost_center,
|
"cost_center": item_row.cost_center,
|
||||||
"project": item_row.project or self.get("project"),
|
"project": item_row.project or self.get("project"),
|
||||||
"remarks": _("Rounding gain/loss Entry for Stock Transfer"),
|
"remarks": _("Rounding gain/loss Entry for Stock Transfer"),
|
||||||
@ -232,9 +226,7 @@ class StockController(AccountsController):
|
|||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": warehouse_asset_account,
|
"account": warehouse_asset_account,
|
||||||
"against_type": "Account",
|
|
||||||
"against": expense_account,
|
"against": expense_account,
|
||||||
"against_link": expense_account,
|
|
||||||
"cost_center": item_row.cost_center,
|
"cost_center": item_row.cost_center,
|
||||||
"remarks": _("Rounding gain/loss Entry for Stock Transfer"),
|
"remarks": _("Rounding gain/loss Entry for Stock Transfer"),
|
||||||
"credit": sle_rounding_diff,
|
"credit": sle_rounding_diff,
|
||||||
@ -395,11 +387,7 @@ class StockController(AccountsController):
|
|||||||
}
|
}
|
||||||
|
|
||||||
for row in self.get(table_name):
|
for row in self.get(table_name):
|
||||||
for field in [
|
for field in QTY_FIELD.keys():
|
||||||
"serial_and_batch_bundle",
|
|
||||||
"current_serial_and_batch_bundle",
|
|
||||||
"rejected_serial_and_batch_bundle",
|
|
||||||
]:
|
|
||||||
if row.get(field):
|
if row.get(field):
|
||||||
frappe.get_doc("Serial and Batch Bundle", row.get(field)).set_serial_and_batch_values(
|
frappe.get_doc("Serial and Batch Bundle", row.get(field)).set_serial_and_batch_values(
|
||||||
self, row, qty_field=QTY_FIELD[field]
|
self, row, qty_field=QTY_FIELD[field]
|
||||||
@ -840,7 +828,6 @@ class StockController(AccountsController):
|
|||||||
credit,
|
credit,
|
||||||
remarks,
|
remarks,
|
||||||
against_account,
|
against_account,
|
||||||
against_type="Account",
|
|
||||||
debit_in_account_currency=None,
|
debit_in_account_currency=None,
|
||||||
credit_in_account_currency=None,
|
credit_in_account_currency=None,
|
||||||
account_currency=None,
|
account_currency=None,
|
||||||
@ -855,9 +842,7 @@ class StockController(AccountsController):
|
|||||||
"cost_center": cost_center,
|
"cost_center": cost_center,
|
||||||
"debit": debit,
|
"debit": debit,
|
||||||
"credit": credit,
|
"credit": credit,
|
||||||
"against_type": against_type,
|
|
||||||
"against": against_account,
|
"against": against_account,
|
||||||
"against_link": against_account,
|
|
||||||
"remarks": remarks,
|
"remarks": remarks,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,7 @@ class TestAccountsController(FrappeTestCase):
|
|||||||
20 series - Sales Invoice against Journals
|
20 series - Sales Invoice against Journals
|
||||||
30 series - Sales Invoice against Credit Notes
|
30 series - Sales Invoice against Credit Notes
|
||||||
40 series - Company default Cost center is unset
|
40 series - Company default Cost center is unset
|
||||||
|
50 series - Dimension inheritence
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -1255,3 +1256,214 @@ class TestAccountsController(FrappeTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
frappe.db.set_value("Company", self.company, "cost_center", cc)
|
frappe.db.set_value("Company", self.company, "cost_center", cc)
|
||||||
|
|
||||||
|
def setup_dimensions(self):
|
||||||
|
# create dimension
|
||||||
|
from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import (
|
||||||
|
create_dimension,
|
||||||
|
)
|
||||||
|
|
||||||
|
create_dimension()
|
||||||
|
# make it non-mandatory
|
||||||
|
loc = frappe.get_doc("Accounting Dimension", "Location")
|
||||||
|
for x in loc.dimension_defaults:
|
||||||
|
x.mandatory_for_bs = False
|
||||||
|
x.mandatory_for_pl = False
|
||||||
|
loc.save()
|
||||||
|
|
||||||
|
def test_50_dimensions_filter(self):
|
||||||
|
"""
|
||||||
|
Test workings of dimension filters
|
||||||
|
"""
|
||||||
|
self.setup_dimensions()
|
||||||
|
rate_in_account_currency = 1
|
||||||
|
|
||||||
|
# Invoices
|
||||||
|
si1 = self.create_sales_invoice(qty=1, rate=rate_in_account_currency, do_not_submit=True)
|
||||||
|
si1.department = "Management"
|
||||||
|
si1.save().submit()
|
||||||
|
|
||||||
|
si2 = self.create_sales_invoice(qty=1, rate=rate_in_account_currency, do_not_submit=True)
|
||||||
|
si2.department = "Operations"
|
||||||
|
si2.save().submit()
|
||||||
|
|
||||||
|
# Payments
|
||||||
|
cr_note1 = self.create_sales_invoice(qty=-1, conversion_rate=75, rate=1, do_not_save=True)
|
||||||
|
cr_note1.department = "Management"
|
||||||
|
cr_note1.is_return = 1
|
||||||
|
cr_note1.save().submit()
|
||||||
|
|
||||||
|
cr_note2 = self.create_sales_invoice(qty=-1, conversion_rate=75, rate=1, do_not_save=True)
|
||||||
|
cr_note2.department = "Legal"
|
||||||
|
cr_note2.is_return = 1
|
||||||
|
cr_note2.save().submit()
|
||||||
|
|
||||||
|
pe1 = get_payment_entry(si1.doctype, si1.name)
|
||||||
|
pe1.references = []
|
||||||
|
pe1.department = "Research & Development"
|
||||||
|
pe1.save().submit()
|
||||||
|
|
||||||
|
pe2 = get_payment_entry(si1.doctype, si1.name)
|
||||||
|
pe2.references = []
|
||||||
|
pe2.department = "Management"
|
||||||
|
pe2.save().submit()
|
||||||
|
|
||||||
|
je1 = self.create_journal_entry(
|
||||||
|
acc1=self.debit_usd,
|
||||||
|
acc1_exc_rate=75,
|
||||||
|
acc2=self.cash,
|
||||||
|
acc1_amount=-1,
|
||||||
|
acc2_amount=-75,
|
||||||
|
acc2_exc_rate=1,
|
||||||
|
)
|
||||||
|
je1.accounts[0].party_type = "Customer"
|
||||||
|
je1.accounts[0].party = self.customer
|
||||||
|
je1.accounts[0].department = "Management"
|
||||||
|
je1.save().submit()
|
||||||
|
|
||||||
|
# assert dimension filter's result
|
||||||
|
pr = self.create_payment_reconciliation()
|
||||||
|
pr.get_unreconciled_entries()
|
||||||
|
self.assertEqual(len(pr.invoices), 2)
|
||||||
|
self.assertEqual(len(pr.payments), 5)
|
||||||
|
|
||||||
|
pr.department = "Legal"
|
||||||
|
pr.get_unreconciled_entries()
|
||||||
|
self.assertEqual(len(pr.invoices), 0)
|
||||||
|
self.assertEqual(len(pr.payments), 1)
|
||||||
|
|
||||||
|
pr.department = "Management"
|
||||||
|
pr.get_unreconciled_entries()
|
||||||
|
self.assertEqual(len(pr.invoices), 1)
|
||||||
|
self.assertEqual(len(pr.payments), 3)
|
||||||
|
|
||||||
|
pr.department = "Research & Development"
|
||||||
|
pr.get_unreconciled_entries()
|
||||||
|
self.assertEqual(len(pr.invoices), 0)
|
||||||
|
self.assertEqual(len(pr.payments), 1)
|
||||||
|
|
||||||
|
def test_51_cr_note_should_inherit_dimension(self):
|
||||||
|
self.setup_dimensions()
|
||||||
|
rate_in_account_currency = 1
|
||||||
|
|
||||||
|
# Invoice
|
||||||
|
si = self.create_sales_invoice(qty=1, rate=rate_in_account_currency, do_not_submit=True)
|
||||||
|
si.department = "Management"
|
||||||
|
si.save().submit()
|
||||||
|
|
||||||
|
# Payment
|
||||||
|
cr_note = self.create_sales_invoice(qty=-1, conversion_rate=75, rate=1, do_not_save=True)
|
||||||
|
cr_note.department = "Management"
|
||||||
|
cr_note.is_return = 1
|
||||||
|
cr_note.save().submit()
|
||||||
|
|
||||||
|
pr = self.create_payment_reconciliation()
|
||||||
|
pr.department = "Management"
|
||||||
|
pr.get_unreconciled_entries()
|
||||||
|
self.assertEqual(len(pr.invoices), 1)
|
||||||
|
self.assertEqual(len(pr.payments), 1)
|
||||||
|
invoices = [x.as_dict() for x in pr.invoices]
|
||||||
|
payments = [x.as_dict() for x in pr.payments]
|
||||||
|
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
|
||||||
|
pr.reconcile()
|
||||||
|
self.assertEqual(len(pr.invoices), 0)
|
||||||
|
self.assertEqual(len(pr.payments), 0)
|
||||||
|
|
||||||
|
# There should be 2 journals, JE(Cr Note) and JE(Exchange Gain/Loss)
|
||||||
|
exc_je_for_si = self.get_journals_for(si.doctype, si.name)
|
||||||
|
exc_je_for_cr_note = self.get_journals_for(cr_note.doctype, cr_note.name)
|
||||||
|
self.assertNotEqual(exc_je_for_si, [])
|
||||||
|
self.assertEqual(len(exc_je_for_si), 2)
|
||||||
|
self.assertEqual(len(exc_je_for_cr_note), 2)
|
||||||
|
self.assertEqual(exc_je_for_si, exc_je_for_cr_note)
|
||||||
|
|
||||||
|
for x in exc_je_for_si + exc_je_for_cr_note:
|
||||||
|
with self.subTest(x=x):
|
||||||
|
self.assertEqual(
|
||||||
|
[cr_note.department, cr_note.department],
|
||||||
|
frappe.db.get_all("Journal Entry Account", filters={"parent": x.parent}, pluck="department"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_52_dimension_inhertiance_exc_gain_loss(self):
|
||||||
|
# Sales Invoice in Foreign Currency
|
||||||
|
self.setup_dimensions()
|
||||||
|
rate = 80
|
||||||
|
rate_in_account_currency = 1
|
||||||
|
dpt = "Research & Development"
|
||||||
|
|
||||||
|
si = self.create_sales_invoice(qty=1, rate=rate_in_account_currency, do_not_save=True)
|
||||||
|
si.department = dpt
|
||||||
|
si.save().submit()
|
||||||
|
|
||||||
|
pe = self.create_payment_entry(amount=1, source_exc_rate=82).save()
|
||||||
|
pe.department = dpt
|
||||||
|
pe = pe.save().submit()
|
||||||
|
|
||||||
|
pr = self.create_payment_reconciliation()
|
||||||
|
pr.department = dpt
|
||||||
|
pr.get_unreconciled_entries()
|
||||||
|
self.assertEqual(len(pr.invoices), 1)
|
||||||
|
self.assertEqual(len(pr.payments), 1)
|
||||||
|
invoices = [x.as_dict() for x in pr.invoices]
|
||||||
|
payments = [x.as_dict() for x in pr.payments]
|
||||||
|
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
|
||||||
|
pr.reconcile()
|
||||||
|
self.assertEqual(len(pr.invoices), 0)
|
||||||
|
self.assertEqual(len(pr.payments), 0)
|
||||||
|
|
||||||
|
# Exc Gain/Loss journals should inherit dimension from parent
|
||||||
|
journals = self.get_journals_for(si.doctype, si.name)
|
||||||
|
self.assertEqual(
|
||||||
|
[dpt, dpt],
|
||||||
|
frappe.db.get_all(
|
||||||
|
"Journal Entry Account",
|
||||||
|
filters={"parent": ("in", [x.parent for x in journals])},
|
||||||
|
pluck="department",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_53_dimension_inheritance_on_advance(self):
|
||||||
|
self.setup_dimensions()
|
||||||
|
dpt = "Research & Development"
|
||||||
|
|
||||||
|
adv = self.create_payment_entry(amount=1, source_exc_rate=85)
|
||||||
|
adv.department = dpt
|
||||||
|
adv.save().submit()
|
||||||
|
adv.reload()
|
||||||
|
|
||||||
|
# Sales Invoices in different exchange rates
|
||||||
|
si = self.create_sales_invoice(qty=1, conversion_rate=82, rate=1, do_not_submit=True)
|
||||||
|
si.department = dpt
|
||||||
|
advances = si.get_advance_entries()
|
||||||
|
self.assertEqual(len(advances), 1)
|
||||||
|
self.assertEqual(advances[0].reference_name, adv.name)
|
||||||
|
si.append(
|
||||||
|
"advances",
|
||||||
|
{
|
||||||
|
"doctype": "Sales Invoice Advance",
|
||||||
|
"reference_type": advances[0].reference_type,
|
||||||
|
"reference_name": advances[0].reference_name,
|
||||||
|
"reference_row": advances[0].reference_row,
|
||||||
|
"advance_amount": 1,
|
||||||
|
"allocated_amount": 1,
|
||||||
|
"ref_exchange_rate": advances[0].exchange_rate,
|
||||||
|
"remarks": advances[0].remarks,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
si = si.save().submit()
|
||||||
|
|
||||||
|
# Outstanding in both currencies should be '0'
|
||||||
|
adv.reload()
|
||||||
|
self.assertEqual(si.outstanding_amount, 0)
|
||||||
|
self.assert_ledger_outstanding(si.doctype, si.name, 0.0, 0.0)
|
||||||
|
|
||||||
|
# Exc Gain/Loss journals should inherit dimension from parent
|
||||||
|
journals = self.get_journals_for(si.doctype, si.name)
|
||||||
|
self.assertEqual(
|
||||||
|
[dpt, dpt],
|
||||||
|
frappe.db.get_all(
|
||||||
|
"Journal Entry Account",
|
||||||
|
filters={"parent": ("in", [x.parent for x in journals])},
|
||||||
|
pluck="department",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|||||||
@ -68,7 +68,7 @@ class TestQueries(unittest.TestCase):
|
|||||||
self.assertGreaterEqual(len(query(txt="_Test Item Home Desktop Manufactured")), 1)
|
self.assertGreaterEqual(len(query(txt="_Test Item Home Desktop Manufactured")), 1)
|
||||||
|
|
||||||
def test_project_query(self):
|
def test_project_query(self):
|
||||||
query = add_default_params(queries.get_project_name, "BOM")
|
query = add_default_params(queries.get_project_name, "Project")
|
||||||
|
|
||||||
self.assertGreaterEqual(len(query(txt="_Test Project")), 1)
|
self.assertGreaterEqual(len(query(txt="_Test Project")), 1)
|
||||||
|
|
||||||
|
|||||||
@ -155,7 +155,7 @@ class TallyMigration(Document):
|
|||||||
except RecursionError:
|
except RecursionError:
|
||||||
self.log(
|
self.log(
|
||||||
_(
|
_(
|
||||||
"Error occured while parsing Chart of Accounts: Please make sure that no two accounts have the same name"
|
"Error occurred while parsing Chart of Accounts: Please make sure that no two accounts have the same name"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -481,7 +481,8 @@ payment_gateway_enabled = "erpnext.accounts.utils.create_payment_gateway_account
|
|||||||
|
|
||||||
communication_doctypes = ["Customer", "Supplier"]
|
communication_doctypes = ["Customer", "Supplier"]
|
||||||
|
|
||||||
advance_payment_doctypes = ["Sales Order", "Purchase Order"]
|
advance_payment_customer_doctypes = ["Sales Order"]
|
||||||
|
advance_payment_supplier_doctypes = ["Purchase Order"]
|
||||||
|
|
||||||
invoice_doctypes = ["Sales Invoice", "Purchase Invoice"]
|
invoice_doctypes = ["Sales Invoice", "Purchase Invoice"]
|
||||||
|
|
||||||
@ -538,6 +539,8 @@ accounting_dimension_doctypes = [
|
|||||||
"Account Closing Balance",
|
"Account Closing Balance",
|
||||||
"Supplier Quotation",
|
"Supplier Quotation",
|
||||||
"Supplier Quotation Item",
|
"Supplier Quotation Item",
|
||||||
|
"Payment Reconciliation",
|
||||||
|
"Payment Reconciliation Allocation",
|
||||||
]
|
]
|
||||||
|
|
||||||
get_matching_queries = (
|
get_matching_queries = (
|
||||||
|
|||||||
4305
erpnext/locale/af.po
4305
erpnext/locale/af.po
File diff suppressed because it is too large
Load Diff
4305
erpnext/locale/ar.po
4305
erpnext/locale/ar.po
File diff suppressed because it is too large
Load Diff
4305
erpnext/locale/de.po
4305
erpnext/locale/de.po
File diff suppressed because it is too large
Load Diff
4305
erpnext/locale/es.po
4305
erpnext/locale/es.po
File diff suppressed because it is too large
Load Diff
4305
erpnext/locale/fi.po
4305
erpnext/locale/fi.po
File diff suppressed because it is too large
Load Diff
4305
erpnext/locale/fr.po
4305
erpnext/locale/fr.po
File diff suppressed because it is too large
Load Diff
4305
erpnext/locale/id.po
4305
erpnext/locale/id.po
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user