feat: Process deferred accounting entry (#19658)
* feat: process deferred accounting * feat: maintain entry for deferred accounting * feat: add check for automatic deferred accounting entry * feat: add build conditions for company and account * fix: create record for automatic processing of deferred accounting * feat: add custom naming series * fix: change the deferred revenue creation via hooks * fix: add client side validations * test: creation of gl entries on submission of process deferred accounting * fix: add multiple validations * patch(accounts-settings): set automatically process deferred accounting entry * fix: On cancel function for deferred entry * fix: Send email per process instead of per invoice * fix: Test cases * fix: Label * fix: Process deferred accounting fixes * fix: Error flag Co-authored-by: Nabin Hait <nabinhait@gmail.com> Co-authored-by: deepeshgarg007 <deepeshgarg6@gmail.com> Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
This commit is contained in:
parent
6d32f3d50a
commit
2f7861a9b8
@ -2,9 +2,10 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day
|
from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day, cint, get_link_to_form
|
||||||
from erpnext.accounts.utils import get_account_currency
|
from erpnext.accounts.utils import get_account_currency
|
||||||
from frappe.email import sendmail_to_system_managers
|
from frappe.email import sendmail_to_system_managers
|
||||||
|
from frappe.utils.background_jobs import enqueue
|
||||||
|
|
||||||
def validate_service_stop_date(doc):
|
def validate_service_stop_date(doc):
|
||||||
''' Validates service_stop_date for Purchase Invoice and Sales Invoice '''
|
''' Validates service_stop_date for Purchase Invoice and Sales Invoice '''
|
||||||
@ -32,8 +33,20 @@ def validate_service_stop_date(doc):
|
|||||||
if old_stop_dates and old_stop_dates.get(item.name) and item.service_stop_date!=old_stop_dates.get(item.name):
|
if old_stop_dates and old_stop_dates.get(item.name) and item.service_stop_date!=old_stop_dates.get(item.name):
|
||||||
frappe.throw(_("Cannot change Service Stop Date for item in row {0}").format(item.idx))
|
frappe.throw(_("Cannot change Service Stop Date for item in row {0}").format(item.idx))
|
||||||
|
|
||||||
def convert_deferred_expense_to_expense(start_date=None, end_date=None):
|
def build_conditions(process_type, account, company):
|
||||||
|
conditions=''
|
||||||
|
deferred_account = "item.deferred_revenue_account" if process_type=="Income" else "item.deferred_expense_account"
|
||||||
|
|
||||||
|
if account:
|
||||||
|
conditions += "AND %s='%s'"%(deferred_account, account)
|
||||||
|
elif company:
|
||||||
|
conditions += "AND p.company='%s'"%(company)
|
||||||
|
|
||||||
|
return conditions
|
||||||
|
|
||||||
|
def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_date=None, conditions=''):
|
||||||
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
|
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
|
||||||
|
|
||||||
if not start_date:
|
if not start_date:
|
||||||
start_date = add_months(today(), -1)
|
start_date = add_months(today(), -1)
|
||||||
if not end_date:
|
if not end_date:
|
||||||
@ -41,18 +54,25 @@ def convert_deferred_expense_to_expense(start_date=None, end_date=None):
|
|||||||
|
|
||||||
# check for the purchase invoice for which GL entries has to be done
|
# check for the purchase invoice for which GL entries has to be done
|
||||||
invoices = frappe.db.sql_list('''
|
invoices = frappe.db.sql_list('''
|
||||||
select distinct parent from `tabPurchase Invoice Item`
|
select distinct item.parent
|
||||||
where service_start_date<=%s and service_end_date>=%s
|
from `tabPurchase Invoice Item` item, `tabPurchase Invoice` p
|
||||||
and enable_deferred_expense = 1 and docstatus = 1 and ifnull(amount, 0) > 0
|
where item.service_start_date<=%s and item.service_end_date>=%s
|
||||||
''', (end_date, start_date))
|
and item.enable_deferred_expense = 1 and item.parent=p.name
|
||||||
|
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
|
||||||
|
{0}
|
||||||
|
'''.format(conditions), (end_date, start_date)) #nosec
|
||||||
|
|
||||||
# For each invoice, book deferred expense
|
# For each invoice, book deferred expense
|
||||||
for invoice in invoices:
|
for invoice in invoices:
|
||||||
doc = frappe.get_doc("Purchase Invoice", invoice)
|
doc = frappe.get_doc("Purchase Invoice", invoice)
|
||||||
book_deferred_income_or_expense(doc, end_date)
|
book_deferred_income_or_expense(doc, deferred_process, end_date)
|
||||||
|
|
||||||
def convert_deferred_revenue_to_income(start_date=None, end_date=None):
|
if frappe.flags.deferred_accounting_error:
|
||||||
|
send_mail(deferred_process)
|
||||||
|
|
||||||
|
def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_date=None, conditions=''):
|
||||||
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
|
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
|
||||||
|
|
||||||
if not start_date:
|
if not start_date:
|
||||||
start_date = add_months(today(), -1)
|
start_date = add_months(today(), -1)
|
||||||
if not end_date:
|
if not end_date:
|
||||||
@ -60,14 +80,20 @@ def convert_deferred_revenue_to_income(start_date=None, end_date=None):
|
|||||||
|
|
||||||
# check for the sales invoice for which GL entries has to be done
|
# check for the sales invoice for which GL entries has to be done
|
||||||
invoices = frappe.db.sql_list('''
|
invoices = frappe.db.sql_list('''
|
||||||
select distinct parent from `tabSales Invoice Item`
|
select distinct item.parent
|
||||||
where service_start_date<=%s and service_end_date>=%s
|
from `tabSales Invoice Item` item, `tabSales Invoice` p
|
||||||
and enable_deferred_revenue = 1 and docstatus = 1 and ifnull(amount, 0) > 0
|
where item.service_start_date<=%s and item.service_end_date>=%s
|
||||||
''', (end_date, start_date))
|
and item.enable_deferred_revenue = 1 and item.parent=p.name
|
||||||
|
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
|
||||||
|
{0}
|
||||||
|
'''.format(conditions), (end_date, start_date)) #nosec
|
||||||
|
|
||||||
for invoice in invoices:
|
for invoice in invoices:
|
||||||
doc = frappe.get_doc("Sales Invoice", invoice)
|
doc = frappe.get_doc("Sales Invoice", invoice)
|
||||||
book_deferred_income_or_expense(doc, end_date)
|
book_deferred_income_or_expense(doc, deferred_process, end_date)
|
||||||
|
|
||||||
|
if frappe.flags.deferred_accounting_error:
|
||||||
|
send_mail(deferred_process)
|
||||||
|
|
||||||
def get_booking_dates(doc, item, posting_date=None):
|
def get_booking_dates(doc, item, posting_date=None):
|
||||||
if not posting_date:
|
if not posting_date:
|
||||||
@ -136,7 +162,7 @@ def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, a
|
|||||||
|
|
||||||
return amount, base_amount
|
return amount, base_amount
|
||||||
|
|
||||||
def book_deferred_income_or_expense(doc, posting_date=None):
|
def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
||||||
enable_check = "enable_deferred_revenue" \
|
enable_check = "enable_deferred_revenue" \
|
||||||
if doc.doctype=="Sales Invoice" else "enable_deferred_expense"
|
if doc.doctype=="Sales Invoice" else "enable_deferred_expense"
|
||||||
|
|
||||||
@ -159,7 +185,11 @@ def book_deferred_income_or_expense(doc, posting_date=None):
|
|||||||
total_days, total_booking_days, account_currency)
|
total_days, total_booking_days, account_currency)
|
||||||
|
|
||||||
make_gl_entries(doc, credit_account, debit_account, against,
|
make_gl_entries(doc, credit_account, debit_account, against,
|
||||||
amount, base_amount, end_date, project, account_currency, item.cost_center, item.name)
|
amount, base_amount, end_date, project, account_currency, item.cost_center, item.name, deferred_process)
|
||||||
|
|
||||||
|
# Returned in case of any errors because it tries to submit the same record again and again in case of errors
|
||||||
|
if frappe.flags.deferred_accounting_error:
|
||||||
|
return
|
||||||
|
|
||||||
if getdate(end_date) < getdate(posting_date) and not last_gl_entry:
|
if getdate(end_date) < getdate(posting_date) and not last_gl_entry:
|
||||||
_book_deferred_revenue_or_expense(item)
|
_book_deferred_revenue_or_expense(item)
|
||||||
@ -169,8 +199,30 @@ def book_deferred_income_or_expense(doc, posting_date=None):
|
|||||||
if item.get(enable_check):
|
if item.get(enable_check):
|
||||||
_book_deferred_revenue_or_expense(item)
|
_book_deferred_revenue_or_expense(item)
|
||||||
|
|
||||||
|
def process_deferred_accounting(posting_date=today()):
|
||||||
|
''' Converts deferred income/expense into income/expense
|
||||||
|
Executed via background jobs on every month end '''
|
||||||
|
|
||||||
|
if not cint(frappe.db.get_singles_value('Accounts Settings', 'automatically_process_deferred_accounting_entry')):
|
||||||
|
return
|
||||||
|
|
||||||
|
start_date = add_months(today(), -1)
|
||||||
|
end_date = add_days(today(), -1)
|
||||||
|
|
||||||
|
for record_type in ('Income', 'Expense'):
|
||||||
|
doc = frappe.get_doc(dict(
|
||||||
|
doctype='Process Deferred Accounting',
|
||||||
|
posting_date=posting_date,
|
||||||
|
start_date=start_date,
|
||||||
|
end_date=end_date,
|
||||||
|
type=record_type
|
||||||
|
))
|
||||||
|
|
||||||
|
doc.insert()
|
||||||
|
doc.submit()
|
||||||
|
|
||||||
def make_gl_entries(doc, credit_account, debit_account, against,
|
def make_gl_entries(doc, credit_account, debit_account, against,
|
||||||
amount, base_amount, posting_date, project, account_currency, cost_center, voucher_detail_no):
|
amount, base_amount, posting_date, project, account_currency, cost_center, voucher_detail_no, deferred_process=None):
|
||||||
# GL Entry for crediting the amount in the deferred expense
|
# GL Entry for crediting the amount in the deferred expense
|
||||||
from erpnext.accounts.general_ledger import make_gl_entries
|
from erpnext.accounts.general_ledger import make_gl_entries
|
||||||
|
|
||||||
@ -186,7 +238,9 @@ def make_gl_entries(doc, credit_account, debit_account, against,
|
|||||||
"cost_center": cost_center,
|
"cost_center": cost_center,
|
||||||
"voucher_detail_no": voucher_detail_no,
|
"voucher_detail_no": voucher_detail_no,
|
||||||
'posting_date': posting_date,
|
'posting_date': posting_date,
|
||||||
'project': project
|
'project': project,
|
||||||
|
'against_voucher_type': 'Process Deferred Accounting',
|
||||||
|
'against_voucher': deferred_process
|
||||||
}, account_currency)
|
}, account_currency)
|
||||||
)
|
)
|
||||||
# GL Entry to debit the amount from the expense
|
# GL Entry to debit the amount from the expense
|
||||||
@ -199,7 +253,9 @@ def make_gl_entries(doc, credit_account, debit_account, against,
|
|||||||
"cost_center": cost_center,
|
"cost_center": cost_center,
|
||||||
"voucher_detail_no": voucher_detail_no,
|
"voucher_detail_no": voucher_detail_no,
|
||||||
'posting_date': posting_date,
|
'posting_date': posting_date,
|
||||||
'project': project
|
'project': project,
|
||||||
|
'against_voucher_type': 'Process Deferred Accounting',
|
||||||
|
'against_voucher': deferred_process
|
||||||
}, account_currency)
|
}, account_currency)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -209,7 +265,16 @@ def make_gl_entries(doc, credit_account, debit_account, against,
|
|||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
except:
|
except:
|
||||||
frappe.db.rollback()
|
frappe.db.rollback()
|
||||||
title = _("Error while processing deferred accounting for {0}").format(doc.name)
|
|
||||||
traceback = frappe.get_traceback()
|
traceback = frappe.get_traceback()
|
||||||
frappe.log_error(message=traceback , title=title)
|
frappe.log_error(message=traceback)
|
||||||
sendmail_to_system_managers(title, traceback)
|
|
||||||
|
frappe.flags.deferred_accounting_error = True
|
||||||
|
|
||||||
|
def send_mail(deferred_process):
|
||||||
|
title = _("Error while processing deferred accounting for {0}".format(deferred_process))
|
||||||
|
content = _("""
|
||||||
|
Deferred accounting failed for some invoices:
|
||||||
|
Please check Process Deferred Accounting {0}
|
||||||
|
and submit manually after resolving errors
|
||||||
|
""").format(get_link_to_form('Process Deferred Accounting', deferred_process))
|
||||||
|
sendmail_to_system_managers(title, content)
|
||||||
|
@ -1,210 +1,226 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-06-24 15:49:57",
|
"actions": [],
|
||||||
"description": "Settings for Accounts",
|
"creation": "2013-06-24 15:49:57",
|
||||||
"doctype": "DocType",
|
"description": "Settings for Accounts",
|
||||||
"document_type": "Other",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"document_type": "Other",
|
||||||
"engine": "InnoDB",
|
"editable_grid": 1,
|
||||||
"field_order": [
|
"engine": "InnoDB",
|
||||||
"auto_accounting_for_stock",
|
"field_order": [
|
||||||
"acc_frozen_upto",
|
"auto_accounting_for_stock",
|
||||||
"frozen_accounts_modifier",
|
"acc_frozen_upto",
|
||||||
"determine_address_tax_category_from",
|
"frozen_accounts_modifier",
|
||||||
"over_billing_allowance",
|
"determine_address_tax_category_from",
|
||||||
"column_break_4",
|
"over_billing_allowance",
|
||||||
"credit_controller",
|
"column_break_4",
|
||||||
"check_supplier_invoice_uniqueness",
|
"credit_controller",
|
||||||
"make_payment_via_journal_entry",
|
"check_supplier_invoice_uniqueness",
|
||||||
"unlink_payment_on_cancellation_of_invoice",
|
"make_payment_via_journal_entry",
|
||||||
"unlink_advance_payment_on_cancelation_of_order",
|
"unlink_payment_on_cancellation_of_invoice",
|
||||||
"book_asset_depreciation_entry_automatically",
|
"unlink_advance_payment_on_cancelation_of_order",
|
||||||
"allow_cost_center_in_entry_of_bs_account",
|
"book_asset_depreciation_entry_automatically",
|
||||||
"add_taxes_from_item_tax_template",
|
"allow_cost_center_in_entry_of_bs_account",
|
||||||
"automatically_fetch_payment_terms",
|
"add_taxes_from_item_tax_template",
|
||||||
"print_settings",
|
"automatically_fetch_payment_terms",
|
||||||
"show_inclusive_tax_in_print",
|
"automatically_process_deferred_accounting_entry",
|
||||||
"column_break_12",
|
"print_settings",
|
||||||
"show_payment_schedule_in_print",
|
"show_inclusive_tax_in_print",
|
||||||
"currency_exchange_section",
|
"column_break_12",
|
||||||
"allow_stale",
|
"show_payment_schedule_in_print",
|
||||||
"stale_days",
|
"currency_exchange_section",
|
||||||
"report_settings_sb",
|
"allow_stale",
|
||||||
"use_custom_cash_flow"
|
"stale_days",
|
||||||
],
|
"report_settings_sb",
|
||||||
"fields": [
|
"use_custom_cash_flow"
|
||||||
{
|
],
|
||||||
"default": "1",
|
"fields": [
|
||||||
"description": "If enabled, the system will post accounting entries for inventory automatically.",
|
{
|
||||||
"fieldname": "auto_accounting_for_stock",
|
"default": "1",
|
||||||
"fieldtype": "Check",
|
"description": "If enabled, the system will post accounting entries for inventory automatically.",
|
||||||
"hidden": 1,
|
"fieldname": "auto_accounting_for_stock",
|
||||||
"in_list_view": 1,
|
"fieldtype": "Check",
|
||||||
"label": "Make Accounting Entry For Every Stock Movement"
|
"hidden": 1,
|
||||||
},
|
"in_list_view": 1,
|
||||||
{
|
"label": "Make Accounting Entry For Every Stock Movement"
|
||||||
"description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",
|
},
|
||||||
"fieldname": "acc_frozen_upto",
|
{
|
||||||
"fieldtype": "Date",
|
"description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",
|
||||||
"in_list_view": 1,
|
"fieldname": "acc_frozen_upto",
|
||||||
"label": "Accounts Frozen Upto"
|
"fieldtype": "Date",
|
||||||
},
|
"in_list_view": 1,
|
||||||
{
|
"label": "Accounts Frozen Upto"
|
||||||
"description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts",
|
},
|
||||||
"fieldname": "frozen_accounts_modifier",
|
{
|
||||||
"fieldtype": "Link",
|
"description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts",
|
||||||
"in_list_view": 1,
|
"fieldname": "frozen_accounts_modifier",
|
||||||
"label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
|
"fieldtype": "Link",
|
||||||
"options": "Role"
|
"in_list_view": 1,
|
||||||
},
|
"label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
|
||||||
{
|
"options": "Role"
|
||||||
"default": "Billing Address",
|
},
|
||||||
"description": "Address used to determine Tax Category in transactions.",
|
{
|
||||||
"fieldname": "determine_address_tax_category_from",
|
"default": "Billing Address",
|
||||||
"fieldtype": "Select",
|
"description": "Address used to determine Tax Category in transactions.",
|
||||||
"label": "Determine Address Tax Category From",
|
"fieldname": "determine_address_tax_category_from",
|
||||||
"options": "Billing Address\nShipping Address"
|
"fieldtype": "Select",
|
||||||
},
|
"label": "Determine Address Tax Category From",
|
||||||
{
|
"options": "Billing Address\nShipping Address"
|
||||||
"fieldname": "column_break_4",
|
},
|
||||||
"fieldtype": "Column Break"
|
{
|
||||||
},
|
"fieldname": "column_break_4",
|
||||||
{
|
"fieldtype": "Column Break"
|
||||||
"description": "Role that is allowed to submit transactions that exceed credit limits set.",
|
},
|
||||||
"fieldname": "credit_controller",
|
{
|
||||||
"fieldtype": "Link",
|
"description": "Role that is allowed to submit transactions that exceed credit limits set.",
|
||||||
"in_list_view": 1,
|
"fieldname": "credit_controller",
|
||||||
"label": "Credit Controller",
|
"fieldtype": "Link",
|
||||||
"options": "Role"
|
"in_list_view": 1,
|
||||||
},
|
"label": "Credit Controller",
|
||||||
{
|
"options": "Role"
|
||||||
"fieldname": "check_supplier_invoice_uniqueness",
|
},
|
||||||
"fieldtype": "Check",
|
{
|
||||||
"label": "Check Supplier Invoice Number Uniqueness"
|
"default": "0",
|
||||||
},
|
"fieldname": "check_supplier_invoice_uniqueness",
|
||||||
{
|
"fieldtype": "Check",
|
||||||
"fieldname": "make_payment_via_journal_entry",
|
"label": "Check Supplier Invoice Number Uniqueness"
|
||||||
"fieldtype": "Check",
|
},
|
||||||
"label": "Make Payment via Journal Entry"
|
{
|
||||||
},
|
"default": "0",
|
||||||
{
|
"fieldname": "make_payment_via_journal_entry",
|
||||||
"default": "1",
|
"fieldtype": "Check",
|
||||||
"fieldname": "unlink_payment_on_cancellation_of_invoice",
|
"label": "Make Payment via Journal Entry"
|
||||||
"fieldtype": "Check",
|
},
|
||||||
"label": "Unlink Payment on Cancellation of Invoice"
|
{
|
||||||
},
|
"default": "1",
|
||||||
{
|
"fieldname": "unlink_payment_on_cancellation_of_invoice",
|
||||||
"default": "1",
|
"fieldtype": "Check",
|
||||||
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
|
"label": "Unlink Payment on Cancellation of Invoice"
|
||||||
"fieldtype": "Check",
|
},
|
||||||
"label": "Unlink Advance Payment on Cancelation of Order"
|
{
|
||||||
},
|
"default": "1",
|
||||||
{
|
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
|
||||||
"default": "1",
|
"fieldtype": "Check",
|
||||||
"fieldname": "book_asset_depreciation_entry_automatically",
|
"label": "Unlink Advance Payment on Cancelation of Order"
|
||||||
"fieldtype": "Check",
|
},
|
||||||
"label": "Book Asset Depreciation Entry Automatically"
|
{
|
||||||
},
|
"default": "1",
|
||||||
{
|
"fieldname": "book_asset_depreciation_entry_automatically",
|
||||||
"fieldname": "allow_cost_center_in_entry_of_bs_account",
|
"fieldtype": "Check",
|
||||||
"fieldtype": "Check",
|
"label": "Book Asset Depreciation Entry Automatically"
|
||||||
"label": "Allow Cost Center In Entry of Balance Sheet Account"
|
},
|
||||||
},
|
{
|
||||||
{
|
"default": "0",
|
||||||
"default": "1",
|
"fieldname": "allow_cost_center_in_entry_of_bs_account",
|
||||||
"fieldname": "add_taxes_from_item_tax_template",
|
"fieldtype": "Check",
|
||||||
"fieldtype": "Check",
|
"label": "Allow Cost Center In Entry of Balance Sheet Account"
|
||||||
"label": "Automatically Add Taxes and Charges from Item Tax Template"
|
},
|
||||||
},
|
{
|
||||||
{
|
"default": "1",
|
||||||
"fieldname": "print_settings",
|
"fieldname": "add_taxes_from_item_tax_template",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Check",
|
||||||
"label": "Print Settings"
|
"label": "Automatically Add Taxes and Charges from Item Tax Template"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "show_inclusive_tax_in_print",
|
"fieldname": "print_settings",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Section Break",
|
||||||
"label": "Show Inclusive Tax In Print"
|
"label": "Print Settings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_12",
|
"default": "0",
|
||||||
"fieldtype": "Column Break"
|
"fieldname": "show_inclusive_tax_in_print",
|
||||||
},
|
"fieldtype": "Check",
|
||||||
{
|
"label": "Show Inclusive Tax In Print"
|
||||||
"fieldname": "show_payment_schedule_in_print",
|
},
|
||||||
"fieldtype": "Check",
|
{
|
||||||
"label": "Show Payment Schedule in Print"
|
"fieldname": "column_break_12",
|
||||||
},
|
"fieldtype": "Column Break"
|
||||||
{
|
},
|
||||||
"fieldname": "currency_exchange_section",
|
{
|
||||||
"fieldtype": "Section Break",
|
"default": "0",
|
||||||
"label": "Currency Exchange Settings"
|
"fieldname": "show_payment_schedule_in_print",
|
||||||
},
|
"fieldtype": "Check",
|
||||||
{
|
"label": "Show Payment Schedule in Print"
|
||||||
"default": "1",
|
},
|
||||||
"fieldname": "allow_stale",
|
{
|
||||||
"fieldtype": "Check",
|
"fieldname": "currency_exchange_section",
|
||||||
"in_list_view": 1,
|
"fieldtype": "Section Break",
|
||||||
"label": "Allow Stale Exchange Rates"
|
"label": "Currency Exchange Settings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "1",
|
"default": "1",
|
||||||
"depends_on": "eval:doc.allow_stale==0",
|
"fieldname": "allow_stale",
|
||||||
"fieldname": "stale_days",
|
"fieldtype": "Check",
|
||||||
"fieldtype": "Int",
|
"in_list_view": 1,
|
||||||
"label": "Stale Days"
|
"label": "Allow Stale Exchange Rates"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "report_settings_sb",
|
"default": "1",
|
||||||
"fieldtype": "Section Break",
|
"depends_on": "eval:doc.allow_stale==0",
|
||||||
"label": "Report Settings"
|
"fieldname": "stale_days",
|
||||||
},
|
"fieldtype": "Int",
|
||||||
{
|
"label": "Stale Days"
|
||||||
"default": "0",
|
},
|
||||||
"description": "Only select if you have setup Cash Flow Mapper documents",
|
{
|
||||||
"fieldname": "use_custom_cash_flow",
|
"fieldname": "report_settings_sb",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Section Break",
|
||||||
"label": "Use Custom Cash Flow Format"
|
"label": "Report Settings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "automatically_fetch_payment_terms",
|
"default": "0",
|
||||||
"fieldtype": "Check",
|
"description": "Only select if you have setup Cash Flow Mapper documents",
|
||||||
"label": "Automatically Fetch Payment Terms"
|
"fieldname": "use_custom_cash_flow",
|
||||||
},
|
"fieldtype": "Check",
|
||||||
{
|
"label": "Use Custom Cash Flow Format"
|
||||||
"description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.",
|
},
|
||||||
"fieldname": "over_billing_allowance",
|
{
|
||||||
"fieldtype": "Currency",
|
"default": "0",
|
||||||
"label": "Over Billing Allowance (%)"
|
"fieldname": "automatically_fetch_payment_terms",
|
||||||
}
|
"fieldtype": "Check",
|
||||||
],
|
"label": "Automatically Fetch Payment Terms"
|
||||||
"icon": "icon-cog",
|
},
|
||||||
"idx": 1,
|
{
|
||||||
"issingle": 1,
|
"description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.",
|
||||||
"modified": "2019-07-04 18:20:55.789946",
|
"fieldname": "over_billing_allowance",
|
||||||
"modified_by": "Administrator",
|
"fieldtype": "Currency",
|
||||||
"module": "Accounts",
|
"label": "Over Billing Allowance (%)"
|
||||||
"name": "Accounts Settings",
|
},
|
||||||
"owner": "Administrator",
|
{
|
||||||
"permissions": [
|
"default": "1",
|
||||||
{
|
"fieldname": "automatically_process_deferred_accounting_entry",
|
||||||
"create": 1,
|
"fieldtype": "Check",
|
||||||
"email": 1,
|
"label": "Automatically Process Deferred Accounting Entry"
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"role": "Accounts Manager",
|
|
||||||
"share": 1,
|
|
||||||
"write": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"read": 1,
|
|
||||||
"role": "Sales User"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"read": 1,
|
|
||||||
"role": "Purchase User"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"quick_entry": 1,
|
|
||||||
"sort_order": "ASC",
|
|
||||||
"track_changes": 1
|
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"icon": "icon-cog",
|
||||||
|
"idx": 1,
|
||||||
|
"issingle": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2019-12-19 16:58:17.395595",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Accounts Settings",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"email": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"role": "Accounts Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"read": 1,
|
||||||
|
"role": "Sales User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"read": 1,
|
||||||
|
"role": "Purchase User"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quick_entry": 1,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "ASC",
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"autoname": "ACC-GLE-.YYYY.-.#####",
|
"autoname": "ACC-GLE-.YYYY.-.#####",
|
||||||
"creation": "2013-01-10 16:34:06",
|
"creation": "2013-01-10 16:34:06",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Process Deferred Accounting', {
|
||||||
|
setup: function(frm) {
|
||||||
|
frm.set_query("document_type", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
'name': ['in', ['Sales Invoice', 'Purchase Invoice']]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
validate: function() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
return frappe.db.get_single_value('Accounts Settings', 'automatically_process_deferred_accounting_entry')
|
||||||
|
.then(value => {
|
||||||
|
if(value) {
|
||||||
|
frappe.throw(__('Manual entry cannot be created! Disable automatic entry for deferred accounting in accounts settings and try again'));
|
||||||
|
}
|
||||||
|
resolve(value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
end_date: function(frm) {
|
||||||
|
if (frm.doc.end_date && frm.doc.end_date < frm.doc.start_date) {
|
||||||
|
frappe.throw(__("End date cannot be before start date"));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onload: function(frm) {
|
||||||
|
if (frm.doc.posting_date && frm.doc.docstatus === 0) {
|
||||||
|
frm.set_value('start_date', frappe.datetime.add_months(frm.doc.posting_date, -1));
|
||||||
|
frm.set_value('end_date', frm.doc.posting_date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
@ -0,0 +1,128 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"autoname": "ACC-PDA-.#####",
|
||||||
|
"creation": "2019-11-04 18:01:23.454775",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"company",
|
||||||
|
"type",
|
||||||
|
"account",
|
||||||
|
"column_break_3",
|
||||||
|
"posting_date",
|
||||||
|
"start_date",
|
||||||
|
"end_date",
|
||||||
|
"amended_from"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Type",
|
||||||
|
"options": "\nIncome\nExpense",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "amended_from",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Amended From",
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "Process Deferred Accounting",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "start_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Service Start Date",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "end_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Service End Date",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_3",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "Today",
|
||||||
|
"fieldname": "posting_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Posting Date",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Account",
|
||||||
|
"options": "Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "company",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Company",
|
||||||
|
"options": "Company",
|
||||||
|
"reqd": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_submittable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2020-02-06 18:18:09.852844",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Process Deferred Accounting",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"cancel": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"submit": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cancel": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts Manager",
|
||||||
|
"share": 1,
|
||||||
|
"submit": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts User",
|
||||||
|
"share": 1,
|
||||||
|
"submit": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC"
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
import erpnext
|
||||||
|
from frappe import _
|
||||||
|
from frappe.model.document import Document
|
||||||
|
from erpnext.accounts.general_ledger import make_reverse_gl_entries
|
||||||
|
from erpnext.accounts.deferred_revenue import convert_deferred_expense_to_expense, \
|
||||||
|
convert_deferred_revenue_to_income, build_conditions
|
||||||
|
|
||||||
|
class ProcessDeferredAccounting(Document):
|
||||||
|
def validate(self):
|
||||||
|
if self.end_date < self.start_date:
|
||||||
|
frappe.throw(_("End date cannot be before start date"))
|
||||||
|
|
||||||
|
def on_submit(self):
|
||||||
|
conditions = build_conditions(self.type, self.account, self.company)
|
||||||
|
if self.type == 'Income':
|
||||||
|
convert_deferred_revenue_to_income(self.name, self.start_date, self.end_date, conditions)
|
||||||
|
else:
|
||||||
|
convert_deferred_expense_to_expense(self.name, self.start_date, self.end_date, conditions)
|
||||||
|
|
||||||
|
def on_cancel(self):
|
||||||
|
self.ignore_linked_doctypes = ['GL Entry']
|
||||||
|
gl_entries = frappe.get_all('GL Entry', fields = ['*'],
|
||||||
|
filters={
|
||||||
|
'against_voucher_type': self.doctype,
|
||||||
|
'against_voucher': self.name
|
||||||
|
})
|
||||||
|
|
||||||
|
make_reverse_gl_entries(gl_entries=gl_entries)
|
@ -0,0 +1,48 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
import unittest
|
||||||
|
from erpnext.accounts.doctype.account.test_account import create_account
|
||||||
|
from erpnext.stock.doctype.item.test_item import create_item
|
||||||
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice, check_gl_entries
|
||||||
|
|
||||||
|
class TestProcessDeferredAccounting(unittest.TestCase):
|
||||||
|
def test_creation_of_ledger_entry_on_submit(self):
|
||||||
|
''' test creation of gl entries on submission of document '''
|
||||||
|
deferred_account = create_account(account_name="Deferred Revenue",
|
||||||
|
parent_account="Current Liabilities - _TC", company="_Test Company")
|
||||||
|
|
||||||
|
item = create_item("_Test Item for Deferred Accounting")
|
||||||
|
item.enable_deferred_revenue = 1
|
||||||
|
item.deferred_revenue_account = deferred_account
|
||||||
|
item.no_of_months = 12
|
||||||
|
item.save()
|
||||||
|
|
||||||
|
si = create_sales_invoice(item=item.name, posting_date="2019-01-10", do_not_submit=True)
|
||||||
|
si.items[0].enable_deferred_revenue = 1
|
||||||
|
si.items[0].service_start_date = "2019-01-10"
|
||||||
|
si.items[0].service_end_date = "2019-03-15"
|
||||||
|
si.items[0].deferred_revenue_account = deferred_account
|
||||||
|
si.save()
|
||||||
|
si.submit()
|
||||||
|
|
||||||
|
process_deferred_accounting = doc = frappe.get_doc(dict(
|
||||||
|
doctype='Process Deferred Accounting',
|
||||||
|
posting_date="2019-01-01",
|
||||||
|
start_date="2019-01-01",
|
||||||
|
end_date="2019-01-31",
|
||||||
|
type="Income"
|
||||||
|
))
|
||||||
|
|
||||||
|
process_deferred_accounting.insert()
|
||||||
|
process_deferred_accounting.submit()
|
||||||
|
|
||||||
|
expected_gle = [
|
||||||
|
[deferred_account, 33.85, 0.0, "2019-01-31"],
|
||||||
|
["Sales - _TC", 0.0, 33.85, "2019-01-31"]
|
||||||
|
]
|
||||||
|
|
||||||
|
check_gl_entries(self, si.name, expected_gle, "2019-01-10")
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
import unittest, copy, time
|
import unittest, copy, time
|
||||||
from frappe.utils import nowdate, flt, getdate, cint, add_days
|
from frappe.utils import nowdate, flt, getdate, cint, add_days, add_months
|
||||||
from frappe.model.dynamic_links import get_dynamic_link_map
|
from frappe.model.dynamic_links import get_dynamic_link_map
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
|
||||||
@ -1721,37 +1721,76 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
si.submit()
|
si.submit()
|
||||||
|
|
||||||
from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income
|
from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income
|
||||||
convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-01-31")
|
|
||||||
|
pda1 = frappe.get_doc(dict(
|
||||||
|
doctype='Process Deferred Accounting',
|
||||||
|
posting_date=nowdate(),
|
||||||
|
start_date="2019-01-01",
|
||||||
|
end_date="2019-03-31",
|
||||||
|
type="Income",
|
||||||
|
company="_Test Company"
|
||||||
|
))
|
||||||
|
|
||||||
|
pda1.insert()
|
||||||
|
pda1.submit()
|
||||||
|
|
||||||
expected_gle = [
|
expected_gle = [
|
||||||
[deferred_account, 33.85, 0.0, "2019-01-31"],
|
[deferred_account, 33.85, 0.0, "2019-01-31"],
|
||||||
["Sales - _TC", 0.0, 33.85, "2019-01-31"]
|
["Sales - _TC", 0.0, 33.85, "2019-01-31"],
|
||||||
]
|
|
||||||
|
|
||||||
self.check_gl_entries(si.name, expected_gle, "2019-01-10")
|
|
||||||
|
|
||||||
convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-03-31")
|
|
||||||
|
|
||||||
expected_gle = [
|
|
||||||
[deferred_account, 43.08, 0.0, "2019-02-28"],
|
[deferred_account, 43.08, 0.0, "2019-02-28"],
|
||||||
["Sales - _TC", 0.0, 43.08, "2019-02-28"],
|
["Sales - _TC", 0.0, 43.08, "2019-02-28"],
|
||||||
[deferred_account, 23.07, 0.0, "2019-03-15"],
|
[deferred_account, 23.07, 0.0, "2019-03-15"],
|
||||||
["Sales - _TC", 0.0, 23.07, "2019-03-15"]
|
["Sales - _TC", 0.0, 23.07, "2019-03-15"]
|
||||||
]
|
]
|
||||||
|
|
||||||
self.check_gl_entries(si.name, expected_gle, "2019-01-31")
|
check_gl_entries(self, si.name, expected_gle, "2019-01-30")
|
||||||
|
|
||||||
def check_gl_entries(self, voucher_no, expected_gle, posting_date):
|
def test_deferred_error_email(self):
|
||||||
gl_entries = frappe.db.sql("""select account, debit, credit, posting_date
|
deferred_account = create_account(account_name="Deferred Revenue",
|
||||||
from `tabGL Entry`
|
parent_account="Current Liabilities - _TC", company="_Test Company")
|
||||||
where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s
|
|
||||||
order by posting_date asc, account asc""", (voucher_no, posting_date), as_dict=1)
|
|
||||||
|
|
||||||
for i, gle in enumerate(gl_entries):
|
item = create_item("_Test Item for Deferred Accounting")
|
||||||
self.assertEqual(expected_gle[i][0], gle.account)
|
item.enable_deferred_revenue = 1
|
||||||
self.assertEqual(expected_gle[i][1], gle.debit)
|
item.deferred_revenue_account = deferred_account
|
||||||
self.assertEqual(expected_gle[i][2], gle.credit)
|
item.no_of_months = 12
|
||||||
self.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
|
item.save()
|
||||||
|
|
||||||
|
si = create_sales_invoice(item=item.name, posting_date="2019-01-10", do_not_submit=True)
|
||||||
|
si.items[0].enable_deferred_revenue = 1
|
||||||
|
si.items[0].service_start_date = "2019-01-10"
|
||||||
|
si.items[0].service_end_date = "2019-03-15"
|
||||||
|
si.items[0].deferred_revenue_account = deferred_account
|
||||||
|
si.save()
|
||||||
|
si.submit()
|
||||||
|
|
||||||
|
from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income
|
||||||
|
|
||||||
|
acc_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||||
|
acc_settings.acc_frozen_upto = '2019-01-31'
|
||||||
|
acc_settings.save()
|
||||||
|
|
||||||
|
pda = frappe.get_doc(dict(
|
||||||
|
doctype='Process Deferred Accounting',
|
||||||
|
posting_date=nowdate(),
|
||||||
|
start_date="2019-01-01",
|
||||||
|
end_date="2019-03-31",
|
||||||
|
type="Income",
|
||||||
|
company="_Test Company"
|
||||||
|
))
|
||||||
|
|
||||||
|
pda.insert()
|
||||||
|
pda.submit()
|
||||||
|
|
||||||
|
email = frappe.db.sql(""" select name from `tabEmail Queue`
|
||||||
|
where message like %(txt)s """, {
|
||||||
|
'txt': "%%%s%%" % "Error while processing deferred accounting for {0}".format(pda.name)
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertTrue(email)
|
||||||
|
|
||||||
|
acc_settings.load_from_db()
|
||||||
|
acc_settings.acc_frozen_upto = None
|
||||||
|
acc_settings.save()
|
||||||
|
|
||||||
def test_inter_company_transaction(self):
|
def test_inter_company_transaction(self):
|
||||||
|
|
||||||
@ -1912,6 +1951,18 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
self.assertEqual(data['billLists'][0]['vehicleNo'], 'KA12KA1234')
|
self.assertEqual(data['billLists'][0]['vehicleNo'], 'KA12KA1234')
|
||||||
self.assertEqual(data['billLists'][0]['itemList'][0]['taxableAmount'], 60000)
|
self.assertEqual(data['billLists'][0]['itemList'][0]['taxableAmount'], 60000)
|
||||||
|
|
||||||
|
def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
|
||||||
|
gl_entries = frappe.db.sql("""select account, debit, credit, posting_date
|
||||||
|
from `tabGL Entry`
|
||||||
|
where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s
|
||||||
|
order by posting_date asc, account asc""", (voucher_no, posting_date), as_dict=1)
|
||||||
|
|
||||||
|
for i, gle in enumerate(gl_entries):
|
||||||
|
doc.assertEqual(expected_gle[i][0], gle.account)
|
||||||
|
doc.assertEqual(expected_gle[i][1], gle.debit)
|
||||||
|
doc.assertEqual(expected_gle[i][2], gle.credit)
|
||||||
|
doc.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
|
||||||
|
|
||||||
def test_item_tax_validity(self):
|
def test_item_tax_validity(self):
|
||||||
item = frappe.get_doc("Item", "_Test Item 2")
|
item = frappe.get_doc("Item", "_Test Item 2")
|
||||||
|
|
||||||
|
@ -245,6 +245,10 @@ def get_data():
|
|||||||
"name": "Supplier Ledger Summary",
|
"name": "Supplier Ledger Summary",
|
||||||
"doctype": "Sales Invoice",
|
"doctype": "Sales Invoice",
|
||||||
"is_query_report": True,
|
"is_query_report": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Process Deferred Accounting"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -643,6 +643,7 @@ erpnext.patches.v12_0.set_default_shopify_app_type
|
|||||||
erpnext.patches.v12_0.set_cwip_and_delete_asset_settings
|
erpnext.patches.v12_0.set_cwip_and_delete_asset_settings
|
||||||
erpnext.patches.v12_0.set_expense_account_in_landed_cost_voucher_taxes
|
erpnext.patches.v12_0.set_expense_account_in_landed_cost_voucher_taxes
|
||||||
erpnext.patches.v12_0.replace_accounting_with_accounts_in_home_settings
|
erpnext.patches.v12_0.replace_accounting_with_accounts_in_home_settings
|
||||||
|
erpnext.patches.v12_0.set_automatically_process_deferred_accounting_in_accounts_settings
|
||||||
erpnext.patches.v12_0.set_payment_entry_status
|
erpnext.patches.v12_0.set_payment_entry_status
|
||||||
erpnext.patches.v12_0.update_owner_fields_in_acc_dimension_custom_fields
|
erpnext.patches.v12_0.update_owner_fields_in_acc_dimension_custom_fields
|
||||||
erpnext.patches.v12_0.add_export_type_field_in_party_master
|
erpnext.patches.v12_0.add_export_type_field_in_party_master
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc("accounts", "doctype", "accounts_settings")
|
||||||
|
|
||||||
|
frappe.db.set_value("Accounts Settings", None, "automatically_process_deferred_accounting_entry", 1)
|
Loading…
x
Reference in New Issue
Block a user