Merge branch 'develop' of https://github.com/frappe/erpnext into loan_patch_and_fixes
This commit is contained in:
commit
04e8af7dca
14
.github/workflows/docker-release.yml
vendored
Normal file
14
.github/workflows/docker-release.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
name: Trigger Docker build on release
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
jobs:
|
||||
curl:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: alpine:latest
|
||||
steps:
|
||||
- name: curl
|
||||
run: |
|
||||
apk add curl bash
|
||||
curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Travis-API-Version: 3" -H "Authorization: token ${{ secrets.TRAVIS_CI_TOKEN }}" -d '{"request":{"branch":"master"}}' https://api.travis-ci.com/repo/frappe%2Ffrappe_docker/requests
|
21
CODEOWNERS
21
CODEOWNERS
@ -3,17 +3,16 @@
|
||||
# These owners will be the default owners for everything in
|
||||
# the repo. Unless a later match takes precedence,
|
||||
|
||||
* @nabinhait
|
||||
manufacturing/ @rohitwaghchaure
|
||||
manufacturing/ @rohitwaghchaure @marination
|
||||
accounts/ @deepeshgarg007 @nextchamp-saqib
|
||||
loan_management/ @deepeshgarg007
|
||||
pos* @nextchamp-saqib
|
||||
assets/ @nextchamp-saqib
|
||||
loan_management/ @deepeshgarg007 @rohitwaghchaure
|
||||
pos* @nextchamp-saqib @rohitwaghchaure
|
||||
assets/ @nextchamp-saqib @deepeshgarg007
|
||||
stock/ @marination @rohitwaghchaure
|
||||
buying/ @marination @rohitwaghchaure
|
||||
hr/ @Anurag810
|
||||
projects/ @hrwX
|
||||
support/ @hrwX
|
||||
healthcare/ @ruchamahabal
|
||||
erpnext_integrations/ @Mangesh-Khairnar
|
||||
buying/ @marination @deepeshgarg007
|
||||
hr/ @Anurag810 @rohitwaghchaure
|
||||
projects/ @hrwX @nextchamp-saqib
|
||||
support/ @hrwX @marination
|
||||
healthcare/ @ruchamahabal @marination
|
||||
erpnext_integrations/ @Mangesh-Khairnar @nextchamp-saqib
|
||||
requirements.txt @gavindsouza
|
||||
|
@ -1,127 +1,284 @@
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
from erpnext import get_default_company
|
||||
|
||||
import frappe
|
||||
import json
|
||||
from frappe.utils import nowdate, add_months, get_date_str
|
||||
from frappe import _
|
||||
from erpnext.accounts.utils import get_fiscal_year, get_account_name, FiscalYearError
|
||||
|
||||
def _get_fiscal_year(date=None):
|
||||
try:
|
||||
fiscal_year = get_fiscal_year(date=nowdate(), as_dict=True)
|
||||
return fiscal_year
|
||||
|
||||
except FiscalYearError:
|
||||
#if no fiscal year for current date then get default fiscal year
|
||||
try:
|
||||
fiscal_year = get_fiscal_year(as_dict=True)
|
||||
return fiscal_year
|
||||
|
||||
except FiscalYearError:
|
||||
#if still no fiscal year found then no accounting data created, return
|
||||
return None
|
||||
|
||||
def get_company_for_dashboards():
|
||||
company = frappe.defaults.get_defaults().company
|
||||
if company:
|
||||
return company
|
||||
else:
|
||||
company_list = frappe.get_list("Company")
|
||||
if company_list:
|
||||
return company_list[0].name
|
||||
return None
|
||||
|
||||
def get_data():
|
||||
data = frappe._dict({
|
||||
"dashboards": [],
|
||||
"charts": []
|
||||
|
||||
fiscal_year = _get_fiscal_year(nowdate())
|
||||
|
||||
if not fiscal_year:
|
||||
return frappe._dict()
|
||||
|
||||
return frappe._dict({
|
||||
"dashboards": get_dashboards(),
|
||||
"charts": get_charts(fiscal_year),
|
||||
"number_cards": get_number_cards(fiscal_year)
|
||||
})
|
||||
company = get_company_for_dashboards()
|
||||
if company:
|
||||
company_doc = frappe.get_doc("Company", company)
|
||||
data.dashboards = get_dashboards()
|
||||
data.charts = get_charts(company_doc)
|
||||
return data
|
||||
|
||||
def get_dashboards():
|
||||
return [{
|
||||
"name": "Accounts",
|
||||
"dashboard_name": "Accounts",
|
||||
"doctype": "Dashboard",
|
||||
"charts": [
|
||||
{ "chart": "Outgoing Bills (Sales Invoice)" },
|
||||
{ "chart": "Incoming Bills (Purchase Invoice)" },
|
||||
{ "chart": "Bank Balance" },
|
||||
{ "chart": "Income" },
|
||||
{ "chart": "Expenses" }
|
||||
{ "chart": "Profit and Loss" , "width": "Full"},
|
||||
{ "chart": "Incoming Bills (Purchase Invoice)", "width": "Half"},
|
||||
{ "chart": "Outgoing Bills (Sales Invoice)", "width": "Half"},
|
||||
{ "chart": "Accounts Receivable Ageing", "width": "Half"},
|
||||
{ "chart": "Accounts Payable Ageing", "width": "Half"},
|
||||
{ "chart": "Budget Variance", "width": "Full"},
|
||||
{ "chart": "Bank Balance", "width": "Full"}
|
||||
],
|
||||
"cards": [
|
||||
{"card": "Total Outgoing Bills"},
|
||||
{"card": "Total Incoming Bills"},
|
||||
{"card": "Total Incoming Payment"},
|
||||
{"card": "Total Outgoing Payment"}
|
||||
]
|
||||
}]
|
||||
|
||||
def get_charts(company):
|
||||
income_account = company.default_income_account or get_account("Income Account", company.name)
|
||||
expense_account = company.default_expense_account or get_account("Expense Account", company.name)
|
||||
bank_account = company.default_bank_account or get_account("Bank", company.name)
|
||||
def get_charts(fiscal_year):
|
||||
company = frappe.get_doc("Company", get_company_for_dashboards())
|
||||
bank_account = company.default_bank_account or get_account_name("Bank", company=company.name)
|
||||
default_cost_center = company.cost_center
|
||||
|
||||
return [
|
||||
{
|
||||
"doctype": "Dashboard Chart",
|
||||
"time_interval": "Quarterly",
|
||||
"name": "Income",
|
||||
"chart_name": "Income",
|
||||
"timespan": "Last Year",
|
||||
"color": None,
|
||||
"filters_json": json.dumps({"company": company.name, "account": income_account}),
|
||||
"source": "Account Balance Timeline",
|
||||
"chart_type": "Custom",
|
||||
"timeseries": 1,
|
||||
"doctype": "Dashboard Charts",
|
||||
"name": "Profit and Loss",
|
||||
"owner": "Administrator",
|
||||
"type": "Line"
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Chart",
|
||||
"time_interval": "Quarterly",
|
||||
"name": "Expenses",
|
||||
"chart_name": "Expenses",
|
||||
"timespan": "Last Year",
|
||||
"color": None,
|
||||
"filters_json": json.dumps({"company": company.name, "account": expense_account}),
|
||||
"source": "Account Balance Timeline",
|
||||
"chart_type": "Custom",
|
||||
"timeseries": 1,
|
||||
"owner": "Administrator",
|
||||
"type": "Line"
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Chart",
|
||||
"time_interval": "Quarterly",
|
||||
"name": "Bank Balance",
|
||||
"chart_name": "Bank Balance",
|
||||
"timespan": "Last Year",
|
||||
"color": "#ffb868",
|
||||
"filters_json": json.dumps({"company": company.name, "account": bank_account}),
|
||||
"source": "Account Balance Timeline",
|
||||
"chart_type": "Custom",
|
||||
"timeseries": 1,
|
||||
"owner": "Administrator",
|
||||
"type": "Line"
|
||||
"report_name": "Profit and Loss Statement",
|
||||
"filters_json": json.dumps({
|
||||
"company": company.name,
|
||||
"filter_based_on": "Fiscal Year",
|
||||
"from_fiscal_year": fiscal_year.get('name'),
|
||||
"to_fiscal_year": fiscal_year.get('name'),
|
||||
"periodicity": "Monthly",
|
||||
"include_default_book_entries": 1
|
||||
}),
|
||||
"type": "Bar",
|
||||
'timeseries': 0,
|
||||
"chart_type": "Report",
|
||||
"chart_name": _("Profit and Loss"),
|
||||
"is_custom": 1,
|
||||
"is_public": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Chart",
|
||||
"time_interval": "Monthly",
|
||||
"name": "Incoming Bills (Purchase Invoice)",
|
||||
"chart_name": "Incoming Bills (Purchase Invoice)",
|
||||
"chart_name": _("Incoming Bills (Purchase Invoice)"),
|
||||
"timespan": "Last Year",
|
||||
"color": "#a83333",
|
||||
"value_based_on": "base_grand_total",
|
||||
"filters_json": json.dumps({}),
|
||||
"value_based_on": "base_net_total",
|
||||
"filters_json": json.dumps([["Purchase Invoice", "docstatus", "=", 1]]),
|
||||
"chart_type": "Sum",
|
||||
"timeseries": 1,
|
||||
"based_on": "posting_date",
|
||||
"owner": "Administrator",
|
||||
"document_type": "Purchase Invoice",
|
||||
"type": "Bar"
|
||||
"type": "Bar",
|
||||
"width": "Half",
|
||||
"is_public": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Chart",
|
||||
"time_interval": "Monthly",
|
||||
"name": "Outgoing Bills (Sales Invoice)",
|
||||
"chart_name": "Outgoing Bills (Sales Invoice)",
|
||||
"time_interval": "Monthly",
|
||||
"chart_name": _("Outgoing Bills (Sales Invoice)"),
|
||||
"timespan": "Last Year",
|
||||
"color": "#7b933d",
|
||||
"value_based_on": "base_grand_total",
|
||||
"filters_json": json.dumps({}),
|
||||
"value_based_on": "base_net_total",
|
||||
"filters_json": json.dumps([["Sales Invoice", "docstatus", "=", 1]]),
|
||||
"chart_type": "Sum",
|
||||
"timeseries": 1,
|
||||
"based_on": "posting_date",
|
||||
"owner": "Administrator",
|
||||
"document_type": "Sales Invoice",
|
||||
"type": "Bar"
|
||||
}
|
||||
"type": "Bar",
|
||||
"width": "Half",
|
||||
"is_public": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Charts",
|
||||
"name": "Accounts Receivable Ageing",
|
||||
"owner": "Administrator",
|
||||
"report_name": "Accounts Receivable",
|
||||
"filters_json": json.dumps({
|
||||
"company": company.name,
|
||||
"report_date": nowdate(),
|
||||
"ageing_based_on": "Due Date",
|
||||
"range1": 30,
|
||||
"range2": 60,
|
||||
"range3": 90,
|
||||
"range4": 120
|
||||
}),
|
||||
"type": "Donut",
|
||||
'timeseries': 0,
|
||||
"chart_type": "Report",
|
||||
"chart_name": _("Accounts Receivable Ageing"),
|
||||
"is_custom": 1,
|
||||
"is_public": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Charts",
|
||||
"name": "Accounts Payable Ageing",
|
||||
"owner": "Administrator",
|
||||
"report_name": "Accounts Payable",
|
||||
"filters_json": json.dumps({
|
||||
"company": company.name,
|
||||
"report_date": nowdate(),
|
||||
"ageing_based_on": "Due Date",
|
||||
"range1": 30,
|
||||
"range2": 60,
|
||||
"range3": 90,
|
||||
"range4": 120
|
||||
}),
|
||||
"type": "Donut",
|
||||
'timeseries': 0,
|
||||
"chart_type": "Report",
|
||||
"chart_name": _("Accounts Payable Ageing"),
|
||||
"is_custom": 1,
|
||||
"is_public": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Charts",
|
||||
"name": "Budget Variance",
|
||||
"owner": "Administrator",
|
||||
"report_name": "Budget Variance Report",
|
||||
"filters_json": json.dumps({
|
||||
"company": company.name,
|
||||
"from_fiscal_year": fiscal_year.get('name'),
|
||||
"to_fiscal_year": fiscal_year.get('name'),
|
||||
"period": "Monthly",
|
||||
"budget_against": "Cost Center"
|
||||
}),
|
||||
"type": "Bar",
|
||||
"timeseries": 0,
|
||||
"chart_type": "Report",
|
||||
"chart_name": _("Budget Variance"),
|
||||
"is_custom": 1,
|
||||
"is_public": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Charts",
|
||||
"name": "Bank Balance",
|
||||
"time_interval": "Quarterly",
|
||||
"chart_name": "Bank Balance",
|
||||
"timespan": "Last Year",
|
||||
"filters_json": json.dumps({
|
||||
"company": company.name,
|
||||
"account": bank_account
|
||||
}),
|
||||
"source": "Account Balance Timeline",
|
||||
"chart_type": "Custom",
|
||||
"timeseries": 1,
|
||||
"owner": "Administrator",
|
||||
"type": "Line",
|
||||
"width": "Half",
|
||||
"is_public": 1
|
||||
},
|
||||
]
|
||||
|
||||
def get_account(account_type, company):
|
||||
accounts = frappe.get_list("Account", filters={"account_type": account_type, "company": company})
|
||||
if accounts:
|
||||
return accounts[0].name
|
||||
def get_number_cards(fiscal_year):
|
||||
|
||||
def get_company_for_dashboards():
|
||||
company = get_default_company()
|
||||
if not company:
|
||||
company_list = frappe.get_list("Company")
|
||||
if company_list:
|
||||
company = company_list[0].name
|
||||
return company
|
||||
year_start_date = get_date_str(fiscal_year.get("year_start_date"))
|
||||
year_end_date = get_date_str(fiscal_year.get("year_end_date"))
|
||||
return [
|
||||
{
|
||||
"doctype": "Number Card",
|
||||
"document_type": "Payment Entry",
|
||||
"name": "Total Incoming Payment",
|
||||
"filters_json": json.dumps([
|
||||
['Payment Entry', 'docstatus', '=', 1],
|
||||
['Payment Entry', 'posting_date', 'between', [year_start_date, year_end_date]],
|
||||
['Payment Entry', 'payment_type', '=', 'Receive']
|
||||
]),
|
||||
"label": _("Total Incoming Payment"),
|
||||
"function": "Sum",
|
||||
"aggregate_function_based_on": "base_received_amount",
|
||||
"is_public": 1,
|
||||
"is_custom": 1,
|
||||
"show_percentage_stats": 1,
|
||||
"stats_time_interval": "Monthly"
|
||||
},
|
||||
{
|
||||
"doctype": "Number Card",
|
||||
"document_type": "Payment Entry",
|
||||
"name": "Total Outgoing Payment",
|
||||
"filters_json": json.dumps([
|
||||
['Payment Entry', 'docstatus', '=', 1],
|
||||
['Payment Entry', 'posting_date', 'between', [year_start_date, year_end_date]],
|
||||
['Payment Entry', 'payment_type', '=', 'Pay']
|
||||
]),
|
||||
"label": _("Total Outgoing Payment"),
|
||||
"function": "Sum",
|
||||
"aggregate_function_based_on": "base_paid_amount",
|
||||
"is_public": 1,
|
||||
"is_custom": 1,
|
||||
"show_percentage_stats": 1,
|
||||
"stats_time_interval": "Monthly"
|
||||
},
|
||||
{
|
||||
"doctype": "Number Card",
|
||||
"document_type": "Sales Invoice",
|
||||
"name": "Total Outgoing Bills",
|
||||
"filters_json": json.dumps([
|
||||
['Sales Invoice', 'docstatus', '=', 1],
|
||||
['Sales Invoice', 'posting_date', 'between', [year_start_date, year_end_date]]
|
||||
]),
|
||||
"label": _("Total Outgoing Bills"),
|
||||
"function": "Sum",
|
||||
"aggregate_function_based_on": "base_net_total",
|
||||
"is_public": 1,
|
||||
"is_custom": 1,
|
||||
"show_percentage_stats": 1,
|
||||
"stats_time_interval": "Monthly"
|
||||
},
|
||||
{
|
||||
"doctype": "Number Card",
|
||||
"document_type": "Purchase Invoice",
|
||||
"name": "Total Incoming Bills",
|
||||
"filters_json": json.dumps([
|
||||
['Purchase Invoice', 'docstatus', '=', 1],
|
||||
['Purchase Invoice', 'posting_date', 'between', [year_start_date, year_end_date]]
|
||||
]),
|
||||
"label": _("Total Incoming Bills"),
|
||||
"function": "Sum",
|
||||
"aggregate_function_based_on": "base_net_total",
|
||||
"is_public": 1,
|
||||
"is_custom": 1,
|
||||
"show_percentage_stats": 1,
|
||||
"stats_time_interval": "Monthly"
|
||||
}
|
||||
]
|
||||
|
@ -2,10 +2,11 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day, cint, get_link_to_form
|
||||
from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day, get_first_day, cint, get_link_to_form, rounded
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
from frappe.email import sendmail_to_system_managers
|
||||
from frappe.utils.background_jobs import enqueue
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
|
||||
|
||||
def validate_service_stop_date(doc):
|
||||
''' Validates service_stop_date for Purchase Invoice and Sales Invoice '''
|
||||
@ -109,6 +110,18 @@ def get_booking_dates(doc, item, posting_date=None):
|
||||
order by posting_date desc limit 1
|
||||
''', (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
|
||||
|
||||
prev_gl_via_je = frappe.db.sql('''
|
||||
SELECT p.name, p.posting_date FROM `tabJournal Entry` p, `tabJournal Entry Account` c
|
||||
WHERE p.name = c.parent and p.company=%s and c.account=%s
|
||||
and c.reference_type=%s and c.reference_name=%s
|
||||
and c.reference_detail_no=%s and c.docstatus < 2 order by posting_date desc limit 1
|
||||
''', (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
|
||||
|
||||
if prev_gl_via_je:
|
||||
if (not prev_gl_entry) or (prev_gl_entry and
|
||||
prev_gl_entry[0].posting_date < prev_gl_via_je[0].posting_date):
|
||||
prev_gl_entry = prev_gl_via_je
|
||||
|
||||
if prev_gl_entry:
|
||||
start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
|
||||
else:
|
||||
@ -130,14 +143,48 @@ def get_booking_dates(doc, item, posting_date=None):
|
||||
else:
|
||||
return None, None, None
|
||||
|
||||
def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, account_currency):
|
||||
if doc.doctype == "Sales Invoice":
|
||||
total_credit_debit, total_credit_debit_currency = "debit", "debit_in_account_currency"
|
||||
deferred_account = "deferred_revenue_account"
|
||||
else:
|
||||
total_credit_debit, total_credit_debit_currency = "credit", "credit_in_account_currency"
|
||||
deferred_account = "deferred_expense_account"
|
||||
def calculate_monthly_amount(doc, item, last_gl_entry, start_date, end_date, total_days, total_booking_days, account_currency):
|
||||
amount, base_amount = 0, 0
|
||||
|
||||
if not last_gl_entry:
|
||||
total_months = (item.service_end_date.year - item.service_start_date.year) * 12 + \
|
||||
(item.service_end_date.month - item.service_start_date.month) + 1
|
||||
|
||||
prorate_factor = flt(date_diff(item.service_end_date, item.service_start_date)) \
|
||||
/ flt(date_diff(get_last_day(item.service_end_date), get_first_day(item.service_start_date)))
|
||||
|
||||
actual_months = rounded(total_months * prorate_factor, 1)
|
||||
|
||||
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(doc, item)
|
||||
base_amount = flt(item.base_net_amount / actual_months, item.precision("base_net_amount"))
|
||||
|
||||
if base_amount + already_booked_amount > item.base_net_amount:
|
||||
base_amount = item.base_net_amount - already_booked_amount
|
||||
|
||||
if account_currency==doc.company_currency:
|
||||
amount = base_amount
|
||||
else:
|
||||
amount = flt(item.net_amount/actual_months, item.precision("net_amount"))
|
||||
if amount + already_booked_amount_in_account_currency > item.net_amount:
|
||||
amount = item.net_amount - already_booked_amount_in_account_currency
|
||||
|
||||
if not (get_first_day(start_date) == start_date and get_last_day(end_date) == end_date):
|
||||
partial_month = flt(date_diff(end_date, start_date)) \
|
||||
/ flt(date_diff(get_last_day(end_date), get_first_day(start_date)))
|
||||
|
||||
base_amount = rounded(partial_month, 1) * base_amount
|
||||
amount = rounded(partial_month, 1) * amount
|
||||
else:
|
||||
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(doc, item)
|
||||
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
|
||||
if account_currency==doc.company_currency:
|
||||
amount = base_amount
|
||||
else:
|
||||
amount = flt(item.net_amount - already_booked_amount_in_account_currency, item.precision("net_amount"))
|
||||
|
||||
return amount, base_amount
|
||||
|
||||
def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, account_currency):
|
||||
amount, base_amount = 0, 0
|
||||
if not last_gl_entry:
|
||||
base_amount = flt(item.base_net_amount*total_booking_days/flt(total_days), item.precision("base_net_amount"))
|
||||
@ -146,27 +193,55 @@ def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, a
|
||||
else:
|
||||
amount = flt(item.net_amount*total_booking_days/flt(total_days), item.precision("net_amount"))
|
||||
else:
|
||||
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(doc, item)
|
||||
|
||||
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
|
||||
if account_currency==doc.company_currency:
|
||||
amount = base_amount
|
||||
else:
|
||||
amount = flt(item.net_amount - already_booked_amount_in_account_currency, item.precision("net_amount"))
|
||||
|
||||
return amount, base_amount
|
||||
|
||||
def get_already_booked_amount(doc, item):
|
||||
if doc.doctype == "Sales Invoice":
|
||||
total_credit_debit, total_credit_debit_currency = "debit", "debit_in_account_currency"
|
||||
deferred_account = "deferred_revenue_account"
|
||||
else:
|
||||
total_credit_debit, total_credit_debit_currency = "credit", "credit_in_account_currency"
|
||||
deferred_account = "deferred_expense_account"
|
||||
|
||||
gl_entries_details = frappe.db.sql('''
|
||||
select sum({0}) as total_credit, sum({1}) as total_credit_in_account_currency, voucher_detail_no
|
||||
from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
|
||||
group by voucher_detail_no
|
||||
'''.format(total_credit_debit, total_credit_debit_currency),
|
||||
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
|
||||
|
||||
journal_entry_details = frappe.db.sql('''
|
||||
SELECT sum(c.{0}) as total_credit, sum(c.{1}) as total_credit_in_account_currency, reference_detail_no
|
||||
FROM `tabJournal Entry` p , `tabJournal Entry Account` c WHERE p.name = c.parent and
|
||||
p.company = %s and c.account=%s and c.reference_type=%s and c.reference_name=%s and c.reference_detail_no=%s
|
||||
and p.docstatus < 2 group by reference_detail_no
|
||||
'''.format(total_credit_debit, total_credit_debit_currency),
|
||||
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
|
||||
|
||||
already_booked_amount = gl_entries_details[0].total_credit if gl_entries_details else 0
|
||||
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
|
||||
if account_currency==doc.company_currency:
|
||||
amount = base_amount
|
||||
already_booked_amount += journal_entry_details[0].total_credit if journal_entry_details else 0
|
||||
|
||||
if doc.currency == doc.company_currency:
|
||||
already_booked_amount_in_account_currency = already_booked_amount
|
||||
else:
|
||||
already_booked_amount_in_account_currency = gl_entries_details[0].total_credit_in_account_currency if gl_entries_details else 0
|
||||
amount = flt(item.net_amount - already_booked_amount_in_account_currency, item.precision("net_amount"))
|
||||
already_booked_amount_in_account_currency += journal_entry_details[0].total_credit_in_account_currency if journal_entry_details else 0
|
||||
|
||||
return amount, base_amount
|
||||
return already_booked_amount, already_booked_amount_in_account_currency
|
||||
|
||||
def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
||||
enable_check = "enable_deferred_revenue" \
|
||||
if doc.doctype=="Sales Invoice" else "enable_deferred_expense"
|
||||
|
||||
def _book_deferred_revenue_or_expense(item):
|
||||
def _book_deferred_revenue_or_expense(item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on):
|
||||
start_date, end_date, last_gl_entry = get_booking_dates(doc, item, posting_date=posting_date)
|
||||
if not (start_date and end_date): return
|
||||
|
||||
@ -181,9 +256,17 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
||||
total_days = date_diff(item.service_end_date, item.service_start_date) + 1
|
||||
total_booking_days = date_diff(end_date, start_date) + 1
|
||||
|
||||
if book_deferred_entries_based_on == 'Months':
|
||||
amount, base_amount = calculate_monthly_amount(doc, item, last_gl_entry,
|
||||
start_date, end_date, total_days, total_booking_days, account_currency)
|
||||
else:
|
||||
amount, base_amount = calculate_amount(doc, item, last_gl_entry,
|
||||
total_days, total_booking_days, account_currency)
|
||||
|
||||
if via_journal_entry:
|
||||
book_revenue_via_journal_entry(doc, credit_account, debit_account, against, amount,
|
||||
base_amount, end_date, project, account_currency, item.cost_center, item, deferred_process, submit_journal_entry)
|
||||
else:
|
||||
make_gl_entries(doc, credit_account, debit_account, against,
|
||||
amount, base_amount, end_date, project, account_currency, item.cost_center, item, deferred_process)
|
||||
|
||||
@ -192,17 +275,23 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
||||
return
|
||||
|
||||
if getdate(end_date) < getdate(posting_date) and not last_gl_entry:
|
||||
_book_deferred_revenue_or_expense(item)
|
||||
_book_deferred_revenue_or_expense(item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on)
|
||||
|
||||
via_journal_entry = cint(frappe.db.get_singles_value('Accounts Settings', 'book_deferred_entries_via_journal_entry'))
|
||||
submit_journal_entry = cint(frappe.db.get_singles_value('Accounts Settings', 'submit_journal_entries'))
|
||||
book_deferred_entries_based_on = frappe.db.get_singles_value('Accounts Settings', 'book_deferred_entries_based_on')
|
||||
|
||||
for item in doc.get('items'):
|
||||
if item.get(enable_check):
|
||||
_book_deferred_revenue_or_expense(item)
|
||||
_book_deferred_revenue_or_expense(item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on)
|
||||
|
||||
def process_deferred_accounting(posting_date=today()):
|
||||
def process_deferred_accounting(posting_date=None):
|
||||
''' Converts deferred income/expense into income/expense
|
||||
Executed via background jobs on every month end '''
|
||||
|
||||
if not posting_date:
|
||||
posting_date = today()
|
||||
|
||||
if not cint(frappe.db.get_singles_value('Accounts Settings', 'automatically_process_deferred_accounting_entry')):
|
||||
return
|
||||
|
||||
@ -278,3 +367,83 @@ def send_mail(deferred_process):
|
||||
and submit manually after resolving errors
|
||||
""").format(get_link_to_form('Process Deferred Accounting', deferred_process))
|
||||
sendmail_to_system_managers(title, content)
|
||||
|
||||
def book_revenue_via_journal_entry(doc, credit_account, debit_account, against,
|
||||
amount, base_amount, posting_date, project, account_currency, cost_center, item,
|
||||
deferred_process=None, submit='No'):
|
||||
|
||||
if amount == 0: return
|
||||
|
||||
journal_entry = frappe.new_doc('Journal Entry')
|
||||
journal_entry.posting_date = posting_date
|
||||
journal_entry.company = doc.company
|
||||
journal_entry.voucher_type = 'Deferred Revenue' if doc.doctype == 'Sales Invoice' \
|
||||
else 'Deferred Expense'
|
||||
|
||||
debit_entry = {
|
||||
'account': credit_account,
|
||||
'credit': base_amount,
|
||||
'credit_in_account_currency': amount,
|
||||
'party_type': 'Customer' if doc.doctype == 'Sales Invoice' else 'Supplier',
|
||||
'party': against,
|
||||
'account_currency': account_currency,
|
||||
'reference_name': doc.name,
|
||||
'reference_type': doc.doctype,
|
||||
'reference_detail_no': item.name,
|
||||
'cost_center': cost_center,
|
||||
'project': project,
|
||||
}
|
||||
|
||||
credit_entry = {
|
||||
'account': debit_account,
|
||||
'debit': base_amount,
|
||||
'debit_in_account_currency': amount,
|
||||
'party_type': 'Customer' if doc.doctype == 'Sales Invoice' else 'Supplier',
|
||||
'party': against,
|
||||
'account_currency': account_currency,
|
||||
'reference_name': doc.name,
|
||||
'reference_type': doc.doctype,
|
||||
'reference_detail_no': item.name,
|
||||
'cost_center': cost_center,
|
||||
'project': project,
|
||||
}
|
||||
|
||||
for dimension in get_accounting_dimensions():
|
||||
debit_entry.update({
|
||||
dimension: item.get(dimension)
|
||||
})
|
||||
|
||||
credit_entry.update({
|
||||
dimension: item.get(dimension)
|
||||
})
|
||||
|
||||
journal_entry.append('accounts', debit_entry)
|
||||
journal_entry.append('accounts', credit_entry)
|
||||
|
||||
try:
|
||||
journal_entry.save()
|
||||
|
||||
if submit:
|
||||
journal_entry.submit()
|
||||
except:
|
||||
frappe.db.rollback()
|
||||
traceback = frappe.get_traceback()
|
||||
frappe.log_error(message=traceback)
|
||||
|
||||
frappe.flags.deferred_accounting_error = True
|
||||
|
||||
def get_deferred_booking_accounts(doctype, voucher_detail_no, dr_or_cr):
|
||||
|
||||
if doctype == 'Sales Invoice':
|
||||
credit_account, debit_account = frappe.db.get_value('Sales Invoice Item', {'name': voucher_detail_no},
|
||||
['income_account', 'deferred_revenue_account'])
|
||||
else:
|
||||
credit_account, debit_account = frappe.db.get_value('Purchase Invoice Item', {'name': voucher_detail_no},
|
||||
['deferred_expense_account', 'expense_account'])
|
||||
|
||||
if dr_or_cr == 'Debit':
|
||||
return debit_account
|
||||
else:
|
||||
return credit_account
|
||||
|
||||
|
||||
|
@ -13,12 +13,12 @@
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Accounts Receivable",
|
||||
"links": "[\n {\n \"description\": \"Bills raised to Customers.\",\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Payment Request\",\n \"label\": \"Payment Request\",\n \"name\": \"Payment Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable\",\n \"name\": \"Accounts Receivable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable Summary\",\n \"name\": \"Accounts Receivable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Register\",\n \"name\": \"Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales Register\",\n \"name\": \"Item-wise Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Ordered Items To Be Billed\",\n \"name\": \"Ordered Items To Be Billed\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Delivered Items To Be Billed\",\n \"name\": \"Delivered Items To Be Billed\",\n \"type\": \"report\"\n }\n]"
|
||||
"links": "[\n {\n \"description\": \"Bills raised to Customers.\",\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Payment Request\",\n \"label\": \"Payment Request\",\n \"name\": \"Payment Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable\",\n \"name\": \"Accounts Receivable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable Summary\",\n \"name\": \"Accounts Receivable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Register\",\n \"name\": \"Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales Register\",\n \"name\": \"Item-wise Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Analysis\",\n \"name\": \"Sales Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Delivered Items To Be Billed\",\n \"name\": \"Delivered Items To Be Billed\",\n \"type\": \"report\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Accounts Payable",
|
||||
"links": "[\n {\n \"description\": \"Bills raised by Suppliers.\",\n \"label\": \"Purchase Invoice\",\n \"name\": \"Purchase Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Supplier database.\",\n \"label\": \"Supplier\",\n \"name\": \"Supplier\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Payable\",\n \"name\": \"Accounts Payable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Payable Summary\",\n \"name\": \"Accounts Payable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Register\",\n \"name\": \"Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase Register\",\n \"name\": \"Item-wise Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Items To Be Billed\",\n \"name\": \"Purchase Order Items To Be Billed\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Received Items To Be Billed\",\n \"name\": \"Received Items To Be Billed\",\n \"type\": \"report\"\n }\n]"
|
||||
"links": "[\n {\n \"description\": \"Bills raised by Suppliers.\",\n \"label\": \"Purchase Invoice\",\n \"name\": \"Purchase Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Supplier database.\",\n \"label\": \"Supplier\",\n \"name\": \"Supplier\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Payable\",\n \"name\": \"Accounts Payable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Payable Summary\",\n \"name\": \"Accounts Payable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Register\",\n \"name\": \"Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase Register\",\n \"name\": \"Item-wise Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Analysis\",\n \"name\": \"Purchase Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Received Items To Be Billed\",\n \"name\": \"Received Items To Be Billed\",\n \"type\": \"report\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
@ -45,11 +45,6 @@
|
||||
"label": "Bank Statement",
|
||||
"links": "[\n {\n \"label\": \"Bank\",\n \"name\": \"Bank\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Account\",\n \"name\": \"Bank Account\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Statement Transaction Entry\",\n \"name\": \"Bank Statement Transaction Entry\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Statement Settings\",\n \"name\": \"Bank Statement Settings\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"links": "[\n {\n \"description\": \"Match non-linked Invoices and Payments.\",\n \"label\": \"Match Payments with Invoices\",\n \"name\": \"Payment Reconciliation\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Update bank payment dates with journals.\",\n \"label\": \"Update Bank Clearance Dates\",\n \"name\": \"Bank Clearance\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Invoice Discounting\",\n \"name\": \"Invoice Discounting\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Reconciliation Statement\",\n \"name\": \"Bank Reconciliation Statement\",\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Bank Reconciliation\",\n \"name\": \"bank-reconciliation\",\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Bank Clearance Summary\",\n \"name\": \"Bank Clearance Summary\",\n \"type\": \"report\"\n },\n {\n \"label\": \"Bank Guarantee\",\n \"name\": \"Bank Guarantee\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Setup cheque dimensions for printing\",\n \"label\": \"Cheque Print Template\",\n \"name\": \"Cheque Print Template\",\n \"type\": \"doctype\"\n }\n]",
|
||||
"title": "Banking and Payments"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Subscription Management",
|
||||
@ -89,8 +84,8 @@
|
||||
"category": "Modules",
|
||||
"charts": [
|
||||
{
|
||||
"chart_name": "Bank Balance",
|
||||
"label": "Bank Balance"
|
||||
"chart_name": "Profit and Loss",
|
||||
"label": "Profit and Loss"
|
||||
}
|
||||
],
|
||||
"creation": "2020-03-02 15:41:59.515192",
|
||||
@ -99,23 +94,34 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "Desk Page",
|
||||
"extends_another_page": 0,
|
||||
"icon": "",
|
||||
"hide_custom": 0,
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"label": "Accounting",
|
||||
"modified": "2020-04-29 12:17:34.844397",
|
||||
"modified": "2020-06-19 12:42:44.054598",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting",
|
||||
"onboarding": "Accounts",
|
||||
"owner": "Administrator",
|
||||
"pin_to_bottom": 0,
|
||||
"pin_to_top": 0,
|
||||
"shortcuts": [
|
||||
{
|
||||
"label": "Account",
|
||||
"label": "Chart Of Accounts",
|
||||
"link_to": "Account",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Sales Invoice",
|
||||
"link_to": "Sales Invoice",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Purchase Invoice",
|
||||
"link_to": "Purchase Invoice",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Journal Entry",
|
||||
"link_to": "Journal Entry",
|
||||
@ -136,15 +142,15 @@
|
||||
"link_to": "General Ledger",
|
||||
"type": "Report"
|
||||
},
|
||||
{
|
||||
"label": "Profit and Loss Statement",
|
||||
"link_to": "Profit and Loss Statement",
|
||||
"type": "Report"
|
||||
},
|
||||
{
|
||||
"label": "Trial Balance",
|
||||
"link_to": "Trial Balance",
|
||||
"type": "Report"
|
||||
},
|
||||
{
|
||||
"label": "Dashboard",
|
||||
"link_to": "Accounts",
|
||||
"type": "Dashboard"
|
||||
}
|
||||
]
|
||||
}
|
@ -34,11 +34,15 @@
|
||||
{
|
||||
"fieldname": "properties",
|
||||
"fieldtype": "Section Break",
|
||||
"oldfieldtype": "Section Break"
|
||||
"oldfieldtype": "Section Break",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break0",
|
||||
"fieldtype": "Column Break",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
@ -49,7 +53,9 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "account_name",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 1
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "account_number",
|
||||
@ -57,13 +63,17 @@
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Account Number",
|
||||
"read_only": 1
|
||||
"read_only": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_group",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Group"
|
||||
"label": "Is Group",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
@ -75,7 +85,9 @@
|
||||
"options": "Company",
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 1,
|
||||
"reqd": 1
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "root_type",
|
||||
@ -83,7 +95,9 @@
|
||||
"in_standard_filter": 1,
|
||||
"label": "Root Type",
|
||||
"options": "\nAsset\nLiability\nIncome\nExpense\nEquity",
|
||||
"read_only": 1
|
||||
"read_only": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "report_type",
|
||||
@ -91,24 +105,32 @@
|
||||
"in_standard_filter": 1,
|
||||
"label": "Report Type",
|
||||
"options": "\nBalance Sheet\nProfit and Loss",
|
||||
"read_only": 1
|
||||
"read_only": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.is_group==0",
|
||||
"fieldname": "account_currency",
|
||||
"fieldtype": "Link",
|
||||
"label": "Currency",
|
||||
"options": "Currency"
|
||||
"options": "Currency",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "inter_company_account",
|
||||
"fieldtype": "Check",
|
||||
"label": "Inter Company Account"
|
||||
"label": "Inter Company Account",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
@ -120,7 +142,9 @@
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Account",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
"search_index": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"description": "Setting Account Type helps in selecting this Account in transactions.",
|
||||
@ -130,7 +154,9 @@
|
||||
"label": "Account Type",
|
||||
"oldfieldname": "account_type",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nTax\nTemporary"
|
||||
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"description": "Rate at which this tax is applied",
|
||||
@ -138,7 +164,9 @@
|
||||
"fieldtype": "Float",
|
||||
"label": "Rate",
|
||||
"oldfieldname": "tax_rate",
|
||||
"oldfieldtype": "Currency"
|
||||
"oldfieldtype": "Currency",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"description": "If the account is frozen, entries are allowed to restricted users.",
|
||||
@ -147,13 +175,17 @@
|
||||
"label": "Frozen",
|
||||
"oldfieldname": "freeze_account",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "No\nYes"
|
||||
"options": "No\nYes",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "balance_must_be",
|
||||
"fieldtype": "Select",
|
||||
"label": "Balance must be",
|
||||
"options": "\nDebit\nCredit"
|
||||
"options": "\nDebit\nCredit",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "lft",
|
||||
@ -162,7 +194,9 @@
|
||||
"label": "Lft",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
"search_index": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "rgt",
|
||||
@ -171,7 +205,9 @@
|
||||
"label": "Rgt",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
"search_index": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "old_parent",
|
||||
@ -179,27 +215,33 @@
|
||||
"hidden": 1,
|
||||
"label": "Old Parent",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"read_only": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:(doc.report_type == 'Profit and Loss' && !doc.is_group)",
|
||||
"fieldname": "include_in_gross",
|
||||
"fieldtype": "Check",
|
||||
"label": "Include in gross"
|
||||
"label": "Include in gross",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disable"
|
||||
"label": "Disable",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-money",
|
||||
"idx": 1,
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2020-03-18 17:57:52.063233",
|
||||
"modified": "2020-06-11 15:15:54.338622",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Account",
|
||||
|
@ -14,6 +14,9 @@ frappe.treeview_settings["Account"] = {
|
||||
on_change: function() {
|
||||
var me = frappe.treeview_settings['Account'].treeview;
|
||||
var company = me.page.fields_dict.company.get_value();
|
||||
if (!company) {
|
||||
frappe.throw(__("Please set a Company"));
|
||||
}
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.account.account.get_root_company",
|
||||
args: {
|
||||
|
@ -72,6 +72,10 @@ def make_dimension_in_accounting_doctypes(doc):
|
||||
if doctype == "Budget":
|
||||
add_dimension_to_budget_doctype(df, doc)
|
||||
else:
|
||||
meta = frappe.get_meta(doctype, cached=False)
|
||||
fieldnames = [d.fieldname for d in meta.get("fields")]
|
||||
|
||||
if df['fieldname'] not in fieldnames:
|
||||
create_custom_field(doctype, df)
|
||||
|
||||
count += 1
|
||||
|
@ -19,10 +19,14 @@
|
||||
"unlink_payment_on_cancellation_of_invoice",
|
||||
"unlink_advance_payment_on_cancelation_of_order",
|
||||
"book_asset_depreciation_entry_automatically",
|
||||
"allow_cost_center_in_entry_of_bs_account",
|
||||
"add_taxes_from_item_tax_template",
|
||||
"automatically_fetch_payment_terms",
|
||||
"deferred_accounting_settings_section",
|
||||
"automatically_process_deferred_accounting_entry",
|
||||
"book_deferred_entries_based_on",
|
||||
"column_break_18",
|
||||
"book_deferred_entries_via_journal_entry",
|
||||
"submit_journal_entries",
|
||||
"print_settings",
|
||||
"show_inclusive_tax_in_print",
|
||||
"column_break_12",
|
||||
@ -108,12 +112,6 @@
|
||||
"fieldtype": "Check",
|
||||
"label": "Book Asset Depreciation Entry Automatically"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "allow_cost_center_in_entry_of_bs_account",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Cost Center In Entry of Balance Sheet Account"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "add_taxes_from_item_tax_template",
|
||||
@ -189,13 +187,45 @@
|
||||
"fieldname": "automatically_process_deferred_accounting_entry",
|
||||
"fieldtype": "Check",
|
||||
"label": "Automatically Process Deferred Accounting Entry"
|
||||
},
|
||||
{
|
||||
"fieldname": "deferred_accounting_settings_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Deferred Accounting Settings"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_18",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "If this is unchecked direct GL Entries will be created to book Deferred Revenue/Expense",
|
||||
"fieldname": "book_deferred_entries_via_journal_entry",
|
||||
"fieldtype": "Check",
|
||||
"label": "Book Deferred Entries Via Journal Entry"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.book_deferred_entries_via_journal_entry",
|
||||
"description": "If this is unchecked Journal Entries will be saved in a Draft state and will have to be submitted manually",
|
||||
"fieldname": "submit_journal_entries",
|
||||
"fieldtype": "Check",
|
||||
"label": "Submit Journal Entries"
|
||||
},
|
||||
{
|
||||
"default": "Days",
|
||||
"description": "If \"Months\" is selected then fixed amount will be booked as deferred revenue or expense for each month irrespective of number of days in a month. Will be prorated if deferred revenue or expense is not booked for an entire month.",
|
||||
"fieldname": "book_deferred_entries_based_on",
|
||||
"fieldtype": "Select",
|
||||
"label": "Book Deferred Entries Based On",
|
||||
"options": "Days\nMonths"
|
||||
}
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
"idx": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2019-12-19 16:58:17.395595",
|
||||
"modified": "2020-06-22 20:13:26.043092",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
@ -20,7 +20,6 @@ class AccountsSettings(Document):
|
||||
|
||||
self.validate_stale_days()
|
||||
self.enable_payment_schedule_in_print()
|
||||
self.enable_fields_for_cost_center_settings()
|
||||
|
||||
def validate_stale_days(self):
|
||||
if not self.allow_stale and cint(self.stale_days) <= 0:
|
||||
@ -33,8 +32,3 @@ class AccountsSettings(Document):
|
||||
for doctype in ("Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"):
|
||||
make_property_setter(doctype, "due_date", "print_hide", show_in_print, "Check")
|
||||
make_property_setter(doctype, "payment_schedule", "print_hide", 0 if show_in_print else 1, "Check")
|
||||
|
||||
def enable_fields_for_cost_center_settings(self):
|
||||
show_field = 0 if cint(self.allow_cost_center_in_entry_of_bs_account) else 1
|
||||
for doctype in ("Sales Invoice", "Purchase Invoice", "Payment Entry"):
|
||||
make_property_setter(doctype, "cost_center", "hidden", show_field, "Check")
|
||||
|
@ -14,7 +14,18 @@ frappe.ui.form.on('Cost Center', {
|
||||
is_group: 1
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
frm.set_query("cost_center", "distributed_cost_center", function() {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
is_group: 0,
|
||||
enable_distributed_cost_center: 0,
|
||||
name: ['!=', frm.doc.name]
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
refresh: function(frm) {
|
||||
if (!frm.is_new()) {
|
||||
@ -60,8 +71,13 @@ frappe.ui.form.on('Cost Center', {
|
||||
"label": "Cost Center Number",
|
||||
"fieldname": "cost_center_number",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1,
|
||||
"default": frm.doc.cost_center_number
|
||||
},
|
||||
{
|
||||
"label": __("Merge with existing"),
|
||||
"fieldname": "merge",
|
||||
"fieldtype": "Check",
|
||||
"default": 0
|
||||
}
|
||||
],
|
||||
primary_action: function() {
|
||||
@ -76,8 +92,9 @@ frappe.ui.form.on('Cost Center', {
|
||||
args: {
|
||||
docname: frm.doc.name,
|
||||
cost_center_name: data.cost_center_name,
|
||||
cost_center_number: data.cost_center_number,
|
||||
company: frm.doc.company
|
||||
cost_center_number: cstr(data.cost_center_number),
|
||||
company: frm.doc.company,
|
||||
merge: data.merge
|
||||
},
|
||||
callback: function(r) {
|
||||
frappe.dom.unfreeze();
|
||||
|
@ -16,6 +16,9 @@
|
||||
"cb0",
|
||||
"is_group",
|
||||
"disabled",
|
||||
"section_break_9",
|
||||
"enable_distributed_cost_center",
|
||||
"distributed_cost_center",
|
||||
"lft",
|
||||
"rgt",
|
||||
"old_parent"
|
||||
@ -119,13 +122,31 @@
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "enable_distributed_cost_center",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable Distributed Cost Center"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.is_group==0",
|
||||
"fieldname": "section_break_9",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "enable_distributed_cost_center",
|
||||
"fieldname": "distributed_cost_center",
|
||||
"fieldtype": "Table",
|
||||
"label": "Distributed Cost Center",
|
||||
"options": "Distributed Cost Center"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-money",
|
||||
"idx": 1,
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-29 16:09:30.025214",
|
||||
"modified": "2020-06-17 16:09:30.025214",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Cost Center",
|
||||
|
@ -19,6 +19,24 @@ class CostCenter(NestedSet):
|
||||
def validate(self):
|
||||
self.validate_mandatory()
|
||||
self.validate_parent_cost_center()
|
||||
self.validate_distributed_cost_center()
|
||||
|
||||
def validate_distributed_cost_center(self):
|
||||
if cint(self.enable_distributed_cost_center):
|
||||
if not self.distributed_cost_center:
|
||||
frappe.throw(_("Please enter distributed cost center"))
|
||||
if sum(x.percentage_allocation for x in self.distributed_cost_center) != 100:
|
||||
frappe.throw(_("Total percentage allocation for distributed cost center should be equal to 100"))
|
||||
if not self.get('__islocal'):
|
||||
if not cint(frappe.get_cached_value("Cost Center", {"name": self.name}, "enable_distributed_cost_center")) \
|
||||
and self.check_if_part_of_distributed_cost_center():
|
||||
frappe.throw(_("Cannot enable Distributed Cost Center for a Cost Center already allocated in another Distributed Cost Center"))
|
||||
if next((True for x in self.distributed_cost_center if x.cost_center == x.parent), False):
|
||||
frappe.throw(_("Parent Cost Center cannot be added in Distributed Cost Center"))
|
||||
if check_if_distributed_cost_center_enabled(list(x.cost_center for x in self.distributed_cost_center)):
|
||||
frappe.throw(_("A Distributed Cost Center cannot be added in the Distributed Cost Center allocation table."))
|
||||
else:
|
||||
self.distributed_cost_center = []
|
||||
|
||||
def validate_mandatory(self):
|
||||
if self.cost_center_name != self.company and not self.parent_cost_center:
|
||||
@ -43,9 +61,12 @@ class CostCenter(NestedSet):
|
||||
return 1
|
||||
|
||||
def convert_ledger_to_group(self):
|
||||
if cint(self.enable_distributed_cost_center):
|
||||
frappe.throw(_("Cost Center with enabled distributed cost center can not be converted to group"))
|
||||
if self.check_if_part_of_distributed_cost_center():
|
||||
frappe.throw(_("Cost Center Already Allocated in a Distributed Cost Center cannot be converted to group"))
|
||||
if self.check_gle_exists():
|
||||
frappe.throw(_("Cost Center with existing transactions can not be converted to group"))
|
||||
else:
|
||||
self.is_group = 1
|
||||
self.save()
|
||||
return 1
|
||||
@ -57,6 +78,9 @@ class CostCenter(NestedSet):
|
||||
return frappe.db.sql("select name from `tabCost Center` where \
|
||||
parent_cost_center = %s and docstatus != 2", self.name)
|
||||
|
||||
def check_if_part_of_distributed_cost_center(self):
|
||||
return frappe.db.get_value("Distributed Cost Center", {"cost_center": self.name})
|
||||
|
||||
def before_rename(self, olddn, newdn, merge=False):
|
||||
# Add company abbr if not provided
|
||||
from erpnext.setup.doctype.company.company import get_name_with_abbr
|
||||
@ -100,3 +124,7 @@ def get_name_with_number(new_account, account_number):
|
||||
if account_number and not new_account[0].isdigit():
|
||||
new_account = account_number + " - " + new_account
|
||||
return new_account
|
||||
|
||||
def check_if_distributed_cost_center_enabled(cost_center_list):
|
||||
value_list = frappe.get_list("Cost Center", {"name": ["in", cost_center_list]}, "enable_distributed_cost_center", as_list=1)
|
||||
return next((True for x in value_list if x[0]), False)
|
@ -22,6 +22,33 @@ class TestCostCenter(unittest.TestCase):
|
||||
|
||||
self.assertRaises(frappe.ValidationError, cost_center.save)
|
||||
|
||||
def test_validate_distributed_cost_center(self):
|
||||
|
||||
if not frappe.db.get_value('Cost Center', {'name': '_Test Cost Center - _TC'}):
|
||||
frappe.get_doc(test_records[0]).insert()
|
||||
|
||||
if not frappe.db.get_value('Cost Center', {'name': '_Test Cost Center 2 - _TC'}):
|
||||
frappe.get_doc(test_records[1]).insert()
|
||||
|
||||
invalid_distributed_cost_center = frappe.get_doc({
|
||||
"company": "_Test Company",
|
||||
"cost_center_name": "_Test Distributed Cost Center",
|
||||
"doctype": "Cost Center",
|
||||
"is_group": 0,
|
||||
"parent_cost_center": "_Test Company - _TC",
|
||||
"enable_distributed_cost_center": 1,
|
||||
"distributed_cost_center": [{
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"percentage_allocation": 40
|
||||
}, {
|
||||
"cost_center": "_Test Cost Center 2 - _TC",
|
||||
"percentage_allocation": 50
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
self.assertRaises(frappe.ValidationError, invalid_distributed_cost_center.save)
|
||||
|
||||
def create_cost_center(**args):
|
||||
args = frappe._dict(args)
|
||||
if args.cost_center_name:
|
||||
|
@ -0,0 +1,40 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-03-19 12:34:01.500390",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"cost_center",
|
||||
"percentage_allocation"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Cost Center",
|
||||
"options": "Cost Center",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "percentage_allocation",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Percentage Allocation",
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-03-19 12:54:43.674655",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Distributed Cost Center",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class DistributedCostCenter(Document):
|
||||
pass
|
@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
from frappe import _
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate, cint
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.naming import set_name_from_naming_options
|
||||
from frappe.model.meta import get_field_precision
|
||||
@ -72,12 +72,6 @@ class GLEntry(Document):
|
||||
if not self.cost_center and self.voucher_type != 'Period Closing Voucher':
|
||||
frappe.throw(_("{0} {1}: Cost Center is required for 'Profit and Loss' account {2}. Please set up a default Cost Center for the Company.")
|
||||
.format(self.voucher_type, self.voucher_no, self.account))
|
||||
else:
|
||||
from erpnext.accounts.utils import get_allow_cost_center_in_entry_of_bs_account
|
||||
if not get_allow_cost_center_in_entry_of_bs_account() and self.cost_center:
|
||||
self.cost_center = None
|
||||
if self.project:
|
||||
self.project = None
|
||||
|
||||
def validate_dimensions_for_pl_and_bs(self):
|
||||
|
||||
@ -134,10 +128,17 @@ class GLEntry(Document):
|
||||
|
||||
return self.cost_center_company[self.cost_center]
|
||||
|
||||
def _check_is_group():
|
||||
return cint(frappe.get_cached_value('Cost Center', self.cost_center, 'is_group'))
|
||||
|
||||
if self.cost_center and _get_cost_center_company() != self.company:
|
||||
frappe.throw(_("{0} {1}: Cost Center {2} does not belong to Company {3}")
|
||||
.format(self.voucher_type, self.voucher_no, self.cost_center, self.company))
|
||||
|
||||
if self.cost_center and _check_is_group():
|
||||
frappe.throw(_("""{0} {1}: Cost Center {2} is a group cost center and group cost centers cannot
|
||||
be used in transactions""").format(self.voucher_type, self.voucher_no, frappe.bold(self.cost_center)))
|
||||
|
||||
def validate_party(self):
|
||||
validate_party_frozen_disabled(self.party_type, self.party)
|
||||
|
||||
|
@ -188,14 +188,15 @@ frappe.ui.form.on('Invoice Discounting', {
|
||||
},
|
||||
|
||||
show_general_ledger: (frm) => {
|
||||
if(frm.doc.docstatus===1) {
|
||||
if(frm.doc.docstatus > 0) {
|
||||
cur_frm.add_custom_button(__('Accounting Ledger'), function() {
|
||||
frappe.route_options = {
|
||||
voucher_no: frm.doc.name,
|
||||
from_date: frm.doc.posting_date,
|
||||
to_date: frm.doc.posting_date,
|
||||
to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
|
||||
company: frm.doc.company,
|
||||
group_by: "Group by Voucher (Consolidated)"
|
||||
group_by: "Group by Voucher (Consolidated)",
|
||||
show_cancelled_entries: frm.doc.docstatus === 2
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, __("View"));
|
||||
|
@ -3,7 +3,7 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
import frappe, json, erpnext
|
||||
from frappe import _
|
||||
from frappe.utils import flt, getdate, nowdate, add_days
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
@ -134,16 +134,19 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.bank_account,
|
||||
"debit_in_account_currency": flt(self.total_amount) - flt(self.bank_charges),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company)
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.bank_charges_account,
|
||||
"debit_in_account_currency": flt(self.bank_charges)
|
||||
"debit_in_account_currency": flt(self.bank_charges),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company)
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.short_term_loan,
|
||||
"credit_in_account_currency": flt(self.total_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name
|
||||
})
|
||||
@ -151,6 +154,7 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_discounted,
|
||||
"debit_in_account_currency": flt(d.outstanding_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
@ -160,6 +164,7 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_credit,
|
||||
"credit_in_account_currency": flt(d.outstanding_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
@ -177,13 +182,15 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.short_term_loan,
|
||||
"debit_in_account_currency": flt(self.total_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.bank_account,
|
||||
"credit_in_account_currency": flt(self.total_amount)
|
||||
"credit_in_account_currency": flt(self.total_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company)
|
||||
})
|
||||
|
||||
if getdate(self.loan_end_date) > getdate(nowdate()):
|
||||
@ -193,6 +200,7 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_discounted,
|
||||
"credit_in_account_currency": flt(outstanding_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
@ -202,6 +210,7 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_unpaid,
|
||||
"debit_in_account_currency": flt(outstanding_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
|
@ -6,6 +6,18 @@ frappe.ui.form.on('Item Tax Template', {
|
||||
frm.set_query("tax_type", "taxes", function(doc) {
|
||||
return {
|
||||
filters: [
|
||||
['Account', 'company', '=', frm.doc.company],
|
||||
['Account', 'is_group', '=', 0],
|
||||
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
|
||||
]
|
||||
}
|
||||
});
|
||||
},
|
||||
company: function (frm) {
|
||||
frm.set_query("tax_type", "taxes", function(doc) {
|
||||
return {
|
||||
filters: [
|
||||
['Account', 'company', '=', frm.doc.company],
|
||||
['Account', 'is_group', '=', 0],
|
||||
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
|
||||
]
|
||||
|
@ -1,168 +1,85 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:title",
|
||||
"beta": 0,
|
||||
"creation": "2018-11-22 22:45:00.370913",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"title",
|
||||
"company",
|
||||
"taxes"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Title",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "taxes",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Tax Rates",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item Tax Template Detail",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-12-21 23:51:16.328340",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2020-06-18 20:27:42.615842",
|
||||
"modified_by": "ahmad@havenir.com",
|
||||
"module": "Accounts",
|
||||
"name": "Item Tax Template",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
"share": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"search_fields": "",
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
"track_changes": 1
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"title": "_Test Account Excise Duty @ 10",
|
||||
"company": "_Test Company",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Item Tax Template Detail",
|
||||
@ -14,6 +15,7 @@
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"title": "_Test Account Excise Duty @ 12",
|
||||
"company": "_Test Company",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Item Tax Template Detail",
|
||||
@ -26,6 +28,7 @@
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"title": "_Test Account Excise Duty @ 15",
|
||||
"company": "_Test Company",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Item Tax Template Detail",
|
||||
@ -38,6 +41,7 @@
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"title": "_Test Account Excise Duty @ 20",
|
||||
"company": "_Test Company",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Item Tax Template Detail",
|
||||
@ -50,6 +54,7 @@
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"title": "_Test Item Tax Template 1",
|
||||
"company": "_Test Company",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Item Tax Template Detail",
|
||||
|
@ -13,15 +13,16 @@ frappe.ui.form.on("Journal Entry", {
|
||||
refresh: function(frm) {
|
||||
erpnext.toggle_naming_series();
|
||||
|
||||
if(frm.doc.docstatus==1) {
|
||||
if(frm.doc.docstatus > 0) {
|
||||
frm.add_custom_button(__('Ledger'), function() {
|
||||
frappe.route_options = {
|
||||
"voucher_no": frm.doc.name,
|
||||
"from_date": frm.doc.posting_date,
|
||||
"to_date": frm.doc.posting_date,
|
||||
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
|
||||
"company": frm.doc.company,
|
||||
"finance_book": frm.doc.finance_book,
|
||||
"group_by_voucher": 0
|
||||
"group_by": '',
|
||||
"show_cancelled_entries": frm.doc.docstatus === 2
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, __('View'));
|
||||
@ -278,7 +279,7 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
// payroll entry
|
||||
if(jvd.reference_type==="Payroll Entry") {
|
||||
return {
|
||||
query: "erpnext.hr.doctype.payroll_entry.payroll_entry.get_payroll_entries_for_jv",
|
||||
query: "erpnext.payroll.doctype.payroll_entry.payroll_entry.get_payroll_entries_for_jv",
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@
|
||||
"label": "Entry Type",
|
||||
"oldfieldname": "voucher_type",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Journal Entry\nInter Company Journal Entry\nBank Entry\nCash Entry\nCredit Card Entry\nDebit Note\nCredit Note\nContra Entry\nExcise Entry\nWrite Off Entry\nOpening Entry\nDepreciation Entry\nExchange Rate Revaluation",
|
||||
"options": "Journal Entry\nInter Company Journal Entry\nBank Entry\nCash Entry\nCredit Card Entry\nDebit Note\nCredit Note\nContra Entry\nExcise Entry\nWrite Off Entry\nOpening Entry\nDepreciation Entry\nExchange Rate Revaluation\nDeferred Revenue\nDeferred Expense",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
@ -191,6 +191,7 @@
|
||||
{
|
||||
"fieldname": "total_debit",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Total Debit",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "total_debit",
|
||||
@ -252,7 +253,6 @@
|
||||
"fieldname": "total_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Total Amount",
|
||||
"no_copy": 1,
|
||||
"options": "total_amount_currency",
|
||||
@ -503,7 +503,7 @@
|
||||
"idx": 176,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-29 10:55:28.240916",
|
||||
"modified": "2020-06-02 18:15:46.955697",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry",
|
||||
|
@ -10,6 +10,7 @@ from erpnext.accounts.utils import get_balance_on, get_account_currency
|
||||
from erpnext.accounts.party import get_party_account
|
||||
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
|
||||
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
|
||||
from erpnext.accounts.deferred_revenue import get_deferred_booking_accounts
|
||||
|
||||
from six import string_types, iteritems
|
||||
|
||||
@ -54,7 +55,7 @@ class JournalEntry(AccountsController):
|
||||
|
||||
def on_cancel(self):
|
||||
from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
|
||||
from erpnext.hr.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip
|
||||
from erpnext.payroll.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip
|
||||
unlink_ref_doc_from_payment_entries(self)
|
||||
unlink_ref_doc_from_salary_slip(self.name)
|
||||
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||
@ -265,7 +266,10 @@ class JournalEntry(AccountsController):
|
||||
# set totals
|
||||
if not d.reference_name in self.reference_totals:
|
||||
self.reference_totals[d.reference_name] = 0.0
|
||||
|
||||
if self.voucher_type not in ('Deferred Revenue', 'Deferred Expense'):
|
||||
self.reference_totals[d.reference_name] += flt(d.get(dr_or_cr))
|
||||
|
||||
self.reference_types[d.reference_name] = d.reference_type
|
||||
self.reference_accounts[d.reference_name] = d.account
|
||||
|
||||
@ -277,10 +281,16 @@ class JournalEntry(AccountsController):
|
||||
|
||||
# check if party and account match
|
||||
if d.reference_type in ("Sales Invoice", "Purchase Invoice"):
|
||||
if self.voucher_type in ('Deferred Revenue', 'Deferred Expense') and d.reference_detail_no:
|
||||
debit_or_credit = 'Debit' if d.debit else 'Credit'
|
||||
party_account = get_deferred_booking_accounts(d.reference_type, d.reference_detail_no,
|
||||
debit_or_credit)
|
||||
else:
|
||||
if d.reference_type == "Sales Invoice":
|
||||
party_account = get_party_account_based_on_invoice_discounting(d.reference_name) or against_voucher[1]
|
||||
else:
|
||||
party_account = against_voucher[1]
|
||||
|
||||
if (against_voucher[0] != d.party or party_account != d.account):
|
||||
frappe.throw(_("Row {0}: Party / Account does not match with {1} / {2} in {3} {4}")
|
||||
.format(d.idx, field_dict.get(d.reference_type)[0], field_dict.get(d.reference_type)[1],
|
||||
@ -513,14 +523,20 @@ class JournalEntry(AccountsController):
|
||||
"against_voucher_type": d.reference_type,
|
||||
"against_voucher": d.reference_name,
|
||||
"remarks": remarks,
|
||||
"voucher_detail_no": d.reference_detail_no,
|
||||
"cost_center": d.cost_center,
|
||||
"project": d.project,
|
||||
"finance_book": self.finance_book
|
||||
}, item=d)
|
||||
)
|
||||
|
||||
if self.voucher_type in ('Deferred Revenue', 'Deferred Expense'):
|
||||
update_outstanding = 'No'
|
||||
else:
|
||||
update_outstanding = 'Yes'
|
||||
|
||||
if gl_map:
|
||||
make_gl_entries(gl_map, cancel=cancel, adv_adj=adv_adj)
|
||||
make_gl_entries(gl_map, cancel=cancel, adv_adj=adv_adj, update_outstanding=update_outstanding)
|
||||
|
||||
def get_balance(self):
|
||||
if not self.get('accounts'):
|
||||
@ -824,6 +840,7 @@ def get_opening_accounts(company):
|
||||
return [{"account": a, "balance": get_balance_on(a)} for a in accounts]
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
|
||||
from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
|
||||
|
@ -204,11 +204,8 @@ class TestJournalEntry(unittest.TestCase):
|
||||
self.assertEqual(jv.inter_company_journal_entry_reference, "")
|
||||
self.assertEqual(jv1.inter_company_journal_entry_reference, "")
|
||||
|
||||
def test_jv_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_jv_with_cost_centre(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, cost_center = cost_center, save=False)
|
||||
@ -237,15 +234,45 @@ class TestJournalEntry(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
def test_jv_with_project(self):
|
||||
from erpnext.projects.doctype.project.test_project import make_project
|
||||
project = make_project({
|
||||
'project_name': 'Journal Entry Project',
|
||||
'project_template_name': 'Test Project Template',
|
||||
'start_date': '2020-01-01'
|
||||
})
|
||||
|
||||
def test_jv_account_and_party_balance_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, save=False)
|
||||
for d in jv.accounts:
|
||||
d.project = project.project_name
|
||||
jv.voucher_type = "Bank Entry"
|
||||
jv.multi_currency = 0
|
||||
jv.cheque_no = "112233"
|
||||
jv.cheque_date = nowdate()
|
||||
jv.insert()
|
||||
jv.submit()
|
||||
|
||||
expected_values = {
|
||||
"_Test Cash - _TC": {
|
||||
"project": project.project_name
|
||||
},
|
||||
"_Test Bank - _TC": {
|
||||
"project": project.project_name
|
||||
}
|
||||
}
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, project, debit, credit
|
||||
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
|
||||
order by account asc""", jv.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["project"], gle.project)
|
||||
|
||||
def test_jv_account_and_party_balance_with_cost_centre(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, cost_center = cost_center, save=False)
|
||||
@ -261,9 +288,6 @@ class TestJournalEntry(unittest.TestCase):
|
||||
account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=cost_center)
|
||||
self.assertEqual(expected_account_balance, account_balance)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def make_journal_entry(account1, account2, amount, cost_center=None, posting_date=None, exchange_rate=1, save=True, submit=False, project=None):
|
||||
if not cost_center:
|
||||
cost_center = "_Test Cost Center - _TC"
|
||||
|
@ -18,6 +18,7 @@
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
"dimension_col_break",
|
||||
"project",
|
||||
"currency_section",
|
||||
"account_currency",
|
||||
"column_break_10",
|
||||
@ -32,7 +33,7 @@
|
||||
"reference_type",
|
||||
"reference_name",
|
||||
"reference_due_date",
|
||||
"project",
|
||||
"reference_detail_no",
|
||||
"col_break3",
|
||||
"is_advance",
|
||||
"user_remark",
|
||||
@ -268,12 +269,18 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Bank Account",
|
||||
"options": "Bank Account"
|
||||
},
|
||||
{
|
||||
"fieldname": "reference_detail_no",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Reference Detail No"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-25 01:47:49.060128",
|
||||
"modified": "2020-06-24 14:06:54.833738",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry Account",
|
||||
|
@ -11,21 +11,9 @@ frappe.ui.form.on('Opening Invoice Creation Tool', {
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('cost_center', 'invoices', function(doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
'company': doc.company
|
||||
if (frm.doc.company) {
|
||||
frm.trigger('setup_company_filters');
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('cost_center', function(doc) {
|
||||
return {
|
||||
filters: {
|
||||
'company': doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
@ -51,7 +39,37 @@ frappe.ui.form.on('Opening Invoice Creation Tool', {
|
||||
});
|
||||
},
|
||||
|
||||
setup_company_filters: function(frm) {
|
||||
frm.set_query('cost_center', 'invoices', function(doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
'company': doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('cost_center', function(doc) {
|
||||
return {
|
||||
filters: {
|
||||
'company': doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('temporary_opening_account', 'invoices', function(doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
'company': doc.company
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
company: function(frm) {
|
||||
if (frm.doc.company) {
|
||||
|
||||
frm.trigger('setup_company_filters');
|
||||
|
||||
frappe.call({
|
||||
method: 'erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool.get_temporary_opening_account',
|
||||
args: {
|
||||
@ -64,6 +82,7 @@ frappe.ui.form.on('Opening Invoice Creation Tool', {
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
invoice_type: function(frm) {
|
||||
|
@ -68,6 +68,9 @@ class OpeningInvoiceCreationTool(Document):
|
||||
if not self.company:
|
||||
frappe.throw(_("Please select the Company"))
|
||||
|
||||
company_details = frappe.get_cached_value('Company', self.company,
|
||||
["default_currency", "default_letter_head"], as_dict=1) or {}
|
||||
|
||||
for row in self.invoices:
|
||||
if not row.qty:
|
||||
row.qty = 1.0
|
||||
@ -99,6 +102,12 @@ class OpeningInvoiceCreationTool(Document):
|
||||
if not args:
|
||||
continue
|
||||
|
||||
if company_details:
|
||||
args.update({
|
||||
"currency": company_details.get("default_currency"),
|
||||
"letter_head": company_details.get("default_letter_head")
|
||||
})
|
||||
|
||||
doc = frappe.get_doc(args).insert()
|
||||
doc.submit()
|
||||
names.append(doc.name)
|
||||
@ -172,8 +181,7 @@ class OpeningInvoiceCreationTool(Document):
|
||||
"due_date": row.due_date,
|
||||
"posting_date": row.posting_date,
|
||||
frappe.scrub(party_type): row.party,
|
||||
"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice",
|
||||
"currency": frappe.get_cached_value('Company', self.company, "default_currency")
|
||||
"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice"
|
||||
})
|
||||
|
||||
accounting_dimension = get_accounting_dimensions()
|
||||
|
@ -234,14 +234,15 @@ frappe.ui.form.on('Payment Entry', {
|
||||
},
|
||||
|
||||
show_general_ledger: function(frm) {
|
||||
if(frm.doc.docstatus==1) {
|
||||
if(frm.doc.docstatus > 0) {
|
||||
frm.add_custom_button(__('Ledger'), function() {
|
||||
frappe.route_options = {
|
||||
"voucher_no": frm.doc.name,
|
||||
"from_date": frm.doc.posting_date,
|
||||
"to_date": frm.doc.posting_date,
|
||||
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
|
||||
"company": frm.doc.company,
|
||||
group_by: ""
|
||||
"group_by": "",
|
||||
"show_cancelled_entries": frm.doc.docstatus === 2
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, "fa fa-table");
|
||||
|
@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
||||
import frappe, erpnext, json
|
||||
from frappe import _, scrub, ValidationError
|
||||
from frappe.utils import flt, comma_or, nowdate, getdate
|
||||
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on, get_allow_cost_center_in_entry_of_bs_account
|
||||
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
|
||||
from erpnext.accounts.party import get_party_account
|
||||
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
@ -319,7 +319,7 @@ class PaymentEntry(AccountsController):
|
||||
invoice_payment_amount_map.setdefault(key, 0.0)
|
||||
invoice_payment_amount_map[key] += reference.allocated_amount
|
||||
|
||||
if not invoice_paid_amount_map.get(reference.reference_name):
|
||||
if not invoice_paid_amount_map.get(key):
|
||||
payment_schedule = frappe.get_all('Payment Schedule', filters={'parent': reference.reference_name},
|
||||
fields=['paid_amount', 'payment_amount', 'payment_term'])
|
||||
for term in payment_schedule:
|
||||
@ -332,10 +332,12 @@ class PaymentEntry(AccountsController):
|
||||
frappe.db.sql(""" UPDATE `tabPayment Schedule` SET paid_amount = `paid_amount` - %s
|
||||
WHERE parent = %s and payment_term = %s""", (amount, key[1], key[0]))
|
||||
else:
|
||||
outstanding = invoice_paid_amount_map.get(key)['outstanding']
|
||||
outstanding = flt(invoice_paid_amount_map.get(key, {}).get('outstanding'))
|
||||
|
||||
if amount > outstanding:
|
||||
frappe.throw(_('Cannot allocate more than {0} against payment term {1}').format(outstanding, key[0]))
|
||||
|
||||
if amount and outstanding:
|
||||
frappe.db.sql(""" UPDATE `tabPayment Schedule` SET paid_amount = `paid_amount` + %s
|
||||
WHERE parent = %s and payment_term = %s""", (amount, key[1], key[0]))
|
||||
|
||||
@ -451,6 +453,8 @@ class PaymentEntry(AccountsController):
|
||||
frappe.throw(_("Reference No and Reference Date is mandatory for Bank transaction"))
|
||||
|
||||
def set_remarks(self):
|
||||
if self.remarks: return
|
||||
|
||||
if self.payment_type=="Internal Transfer":
|
||||
remarks = [_("Amount {0} {1} transferred from {2} to {3}")
|
||||
.format(self.paid_from_account_currency, self.paid_amount, self.paid_from, self.paid_to)]
|
||||
@ -654,7 +658,7 @@ def get_outstanding_reference_documents(args):
|
||||
.format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]))
|
||||
|
||||
# Add cost center condition
|
||||
if args.get("cost_center") and get_allow_cost_center_in_entry_of_bs_account():
|
||||
if args.get("cost_center"):
|
||||
condition += " and cost_center='%s'" % args.get("cost_center")
|
||||
|
||||
date_fields_dict = {
|
||||
@ -1025,14 +1029,14 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
||||
if bank_amount:
|
||||
received_amount = bank_amount
|
||||
else:
|
||||
received_amount = paid_amount * doc.conversion_rate
|
||||
received_amount = paid_amount * doc.get('conversion_rate', 1)
|
||||
else:
|
||||
received_amount = abs(outstanding_amount)
|
||||
if bank_amount:
|
||||
paid_amount = bank_amount
|
||||
else:
|
||||
# if party account currency and bank currency is different then populate paid amount as well
|
||||
paid_amount = received_amount * doc.conversion_rate
|
||||
paid_amount = received_amount * doc.get('conversion_rate', 1)
|
||||
|
||||
pe = frappe.new_doc("Payment Entry")
|
||||
pe.payment_type = payment_type
|
||||
@ -1091,6 +1095,10 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
||||
def get_reference_as_per_payment_terms(payment_schedule, dt, dn, doc, grand_total, outstanding_amount):
|
||||
references = []
|
||||
for payment_term in payment_schedule:
|
||||
payment_term_outstanding = flt(payment_term.payment_amount - payment_term.paid_amount,
|
||||
payment_term.precision('payment_amount'))
|
||||
|
||||
if payment_term_outstanding:
|
||||
references.append({
|
||||
'reference_doctype': dt,
|
||||
'reference_name': dn,
|
||||
@ -1099,8 +1107,7 @@ def get_reference_as_per_payment_terms(payment_schedule, dt, dn, doc, grand_tota
|
||||
'total_amount': grand_total,
|
||||
'outstanding_amount': outstanding_amount,
|
||||
'payment_term': payment_term.payment_term,
|
||||
'allocated_amount': flt(payment_term.payment_amount - payment_term.paid_amount,
|
||||
payment_term.precision('payment_amount'))
|
||||
'allocated_amount': payment_term_outstanding
|
||||
})
|
||||
|
||||
return references
|
||||
|
@ -460,11 +460,8 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||
self.assertEqual(outstanding_amount, 0)
|
||||
|
||||
def test_payment_entry_against_sales_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_payment_entry_against_sales_invoice_with_cost_centre(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
|
||||
@ -499,39 +496,8 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def test_payment_entry_against_sales_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
si = create_sales_invoice(debit_to="Debtors - _TC")
|
||||
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
|
||||
|
||||
pe.reference_no = "112211-2"
|
||||
pe.reference_date = nowdate()
|
||||
pe.paid_to = "_Test Bank - _TC"
|
||||
pe.paid_amount = si.grand_total
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
|
||||
order by account asc""", pe.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(gle.cost_center, None)
|
||||
|
||||
def test_payment_entry_against_purchase_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_payment_entry_against_purchase_invoice_with_cost_center(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
|
||||
@ -566,40 +532,9 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def test_payment_entry_against_purchase_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
pi = make_purchase_invoice(credit_to="Creditors - _TC")
|
||||
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||
|
||||
pe.reference_no = "112222-2"
|
||||
pe.reference_date = nowdate()
|
||||
pe.paid_from = "_Test Bank - _TC"
|
||||
pe.paid_amount = pi.grand_total
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
|
||||
order by account asc""", pe.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(gle.cost_center, None)
|
||||
|
||||
def test_payment_entry_account_and_party_balance_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_payment_entry_account_and_party_balance_with_cost_center(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
|
||||
@ -630,9 +565,6 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
self.assertEqual(expected_party_balance, party_balance)
|
||||
self.assertEqual(expected_party_account_balance, party_account_balance)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def create_payment_terms_template():
|
||||
|
||||
create_payment_term('Basic Amount Receivable')
|
||||
|
@ -26,6 +26,7 @@ class PaymentOrder(Document):
|
||||
for d in self.references:
|
||||
frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), ref_field, status)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_mop_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql(""" select mode_of_payment from `tabPayment Order Reference`
|
||||
where parent = %(parent)s and mode_of_payment like %(txt)s
|
||||
@ -36,6 +37,7 @@ def get_mop_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
'txt': "%%%s%%" % txt
|
||||
})
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_supplier_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql(""" select supplier from `tabPayment Order Reference`
|
||||
where parent = %(parent)s and supplier like %(txt)s and
|
||||
|
@ -170,7 +170,7 @@ class PaymentReconciliation(Document):
|
||||
reconcile_against_document(lst)
|
||||
|
||||
if dr_or_cr_notes:
|
||||
reconcile_dr_cr_note(dr_or_cr_notes)
|
||||
reconcile_dr_cr_note(dr_or_cr_notes, self.company)
|
||||
|
||||
msgprint(_("Successfully Reconciled"))
|
||||
self.get_unreconciled_entries()
|
||||
@ -261,7 +261,7 @@ class PaymentReconciliation(Document):
|
||||
|
||||
return cond
|
||||
|
||||
def reconcile_dr_cr_note(dr_cr_notes):
|
||||
def reconcile_dr_cr_note(dr_cr_notes, company):
|
||||
for d in dr_cr_notes:
|
||||
voucher_type = ('Credit Note'
|
||||
if d.voucher_type == 'Sales Invoice' else 'Debit Note')
|
||||
@ -273,6 +273,7 @@ def reconcile_dr_cr_note(dr_cr_notes):
|
||||
"doctype": "Journal Entry",
|
||||
"voucher_type": voucher_type,
|
||||
"posting_date": today(),
|
||||
"company": company,
|
||||
"accounts": [
|
||||
{
|
||||
'account': d.account,
|
||||
@ -280,7 +281,8 @@ def reconcile_dr_cr_note(dr_cr_notes):
|
||||
'party_type': d.party_type,
|
||||
d.dr_or_cr: abs(d.allocated_amount),
|
||||
'reference_type': d.against_voucher_type,
|
||||
'reference_name': d.against_voucher
|
||||
'reference_name': d.against_voucher,
|
||||
'cost_center': erpnext.get_default_cost_center(company)
|
||||
},
|
||||
{
|
||||
'account': d.account,
|
||||
@ -289,7 +291,8 @@ def reconcile_dr_cr_note(dr_cr_notes):
|
||||
reconcile_dr_or_cr: (abs(d.allocated_amount)
|
||||
if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
|
||||
'reference_type': d.voucher_type,
|
||||
'reference_name': d.voucher_no
|
||||
'reference_name': d.voucher_no,
|
||||
'cost_center': erpnext.get_default_cost_center(company)
|
||||
}
|
||||
]
|
||||
})
|
||||
|
@ -349,9 +349,10 @@
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"in_create": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-05-08 10:23:02.815237",
|
||||
"modified": "2020-05-29 17:38:49.392713",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Request",
|
||||
|
@ -69,7 +69,7 @@ class PaymentRequest(Document):
|
||||
elif self.payment_request_type == 'Inward':
|
||||
self.db_set('status', 'Requested')
|
||||
|
||||
send_mail = self.payment_gateway_validation()
|
||||
send_mail = self.payment_gateway_validation() if self.payment_gateway else None
|
||||
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") \
|
||||
|
@ -25,9 +25,10 @@ frappe.ui.form.on('Period Closing Voucher', {
|
||||
frappe.route_options = {
|
||||
"voucher_no": frm.doc.name,
|
||||
"from_date": frm.doc.posting_date,
|
||||
"to_date": frm.doc.posting_date,
|
||||
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
|
||||
"company": frm.doc.company,
|
||||
group_by_voucher: 0
|
||||
"group_by": "",
|
||||
"show_cancelled_entries": frm.doc.docstatus === 2
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, "fa fa-table");
|
||||
|
@ -115,6 +115,7 @@ def get_item_groups(pos_profile):
|
||||
def get_series():
|
||||
return frappe.get_meta("Sales Invoice").get_field("naming_series").options or ""
|
||||
|
||||
@frappe.whitelist()
|
||||
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
user = frappe.session['user']
|
||||
company = filters.get('company') or frappe.defaults.get_user_default('company')
|
||||
|
@ -17,6 +17,8 @@ from six import string_types
|
||||
apply_on_dict = {"Item Code": "items",
|
||||
"Item Group": "item_groups", "Brand": "brands"}
|
||||
|
||||
other_fields = ["other_item_code", "other_item_group", "other_brand"]
|
||||
|
||||
class PricingRule(Document):
|
||||
def validate(self):
|
||||
self.validate_mandatory()
|
||||
@ -47,6 +49,13 @@ class PricingRule(Document):
|
||||
if tocheck and not self.get(tocheck):
|
||||
throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError)
|
||||
|
||||
if self.apply_rule_on_other:
|
||||
o_field = 'other_' + frappe.scrub(self.apply_rule_on_other)
|
||||
if not self.get(o_field) and o_field in other_fields:
|
||||
frappe.throw(_("For the 'Apply Rule On Other' condition the field {0} is mandatory")
|
||||
.format(frappe.bold(self.apply_rule_on_other)))
|
||||
|
||||
|
||||
if self.price_or_product_discount == 'Price' and not self.rate_or_discount:
|
||||
throw(_("Rate or Discount is required for the price discount."), frappe.MandatoryError)
|
||||
|
||||
@ -80,13 +89,27 @@ class PricingRule(Document):
|
||||
for f in options:
|
||||
if not f: continue
|
||||
|
||||
f = frappe.scrub(f)
|
||||
if f!=fieldname:
|
||||
self.set(f, None)
|
||||
scrubbed_f = frappe.scrub(f)
|
||||
|
||||
if logic_field == 'apply_on':
|
||||
apply_on_f = apply_on_dict.get(f, f)
|
||||
else:
|
||||
apply_on_f = scrubbed_f
|
||||
|
||||
if scrubbed_f != fieldname:
|
||||
self.set(apply_on_f, None)
|
||||
|
||||
if self.mixed_conditions and self.get("same_item"):
|
||||
self.same_item = 0
|
||||
|
||||
apply_rule_on_other = frappe.scrub(self.apply_rule_on_other or "")
|
||||
|
||||
cleanup_other_fields = (other_fields if not apply_rule_on_other
|
||||
else [o_field for o_field in other_fields if o_field != 'other_' + apply_rule_on_other])
|
||||
|
||||
for other_field in cleanup_other_fields:
|
||||
self.set(other_field, None)
|
||||
|
||||
def validate_rate_or_discount(self):
|
||||
for field in ["Rate"]:
|
||||
if flt(self.get(frappe.scrub(field))) < 0:
|
||||
@ -409,6 +432,7 @@ def make_pricing_rule(doctype, docname):
|
||||
|
||||
return doc
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
|
||||
items = [filters.get('value')]
|
||||
if filters.get('apply_on') != 'Item Code':
|
||||
|
@ -386,6 +386,50 @@ class TestPricingRule(unittest.TestCase):
|
||||
self.assertEqual(so.items[1].is_free_item, 1)
|
||||
self.assertEqual(so.items[1].item_code, "_Test Item 2")
|
||||
|
||||
def test_cumulative_pricing_rule(self):
|
||||
frappe.delete_doc_if_exists('Pricing Rule', '_Test Cumulative Pricing Rule')
|
||||
test_record = {
|
||||
"doctype": "Pricing Rule",
|
||||
"title": "_Test Cumulative Pricing Rule",
|
||||
"apply_on": "Item Code",
|
||||
"currency": "USD",
|
||||
"items": [{
|
||||
"item_code": "_Test Item",
|
||||
}],
|
||||
"is_cumulative": 1,
|
||||
"selling": 1,
|
||||
"applicable_for": "Customer",
|
||||
"customer": "_Test Customer",
|
||||
"rate_or_discount": "Discount Percentage",
|
||||
"rate": 0,
|
||||
"min_amt": 0,
|
||||
"max_amt": 10000,
|
||||
"discount_percentage": 17.5,
|
||||
"price_or_product_discount": "Price",
|
||||
"company": "_Test Company",
|
||||
"valid_from": frappe.utils.nowdate(),
|
||||
"valid_upto": frappe.utils.nowdate()
|
||||
}
|
||||
frappe.get_doc(test_record.copy()).insert()
|
||||
|
||||
args = frappe._dict({
|
||||
"item_code": "_Test Item",
|
||||
"company": "_Test Company",
|
||||
"price_list": "_Test Price List",
|
||||
"currency": "_Test Currency",
|
||||
"doctype": "Sales Invoice",
|
||||
"conversion_rate": 1,
|
||||
"price_list_currency": "_Test Currency",
|
||||
"plc_conversion_rate": 1,
|
||||
"order_type": "Sales",
|
||||
"customer": "_Test Customer",
|
||||
"name": None,
|
||||
"transaction_date": frappe.utils.nowdate()
|
||||
})
|
||||
details = get_item_details(args)
|
||||
|
||||
self.assertTrue(details)
|
||||
|
||||
def make_pricing_rule(**args):
|
||||
args = frappe._dict(args)
|
||||
|
||||
|
@ -319,7 +319,9 @@ def apply_internal_priority(pricing_rules, field_set, args):
|
||||
filtered_rules = []
|
||||
for field in field_set:
|
||||
if args.get(field):
|
||||
filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
|
||||
# filter function always returns a filter object even if empty
|
||||
# list conversion is necessary to check for an empty result
|
||||
filtered_rules = list(filter(lambda x: x.get(field)==args.get(field), pricing_rules))
|
||||
if filtered_rules: break
|
||||
|
||||
return filtered_rules or pricing_rules
|
||||
@ -366,8 +368,7 @@ def get_qty_amount_data_for_cumulative(pr_doc, doc, items=[]):
|
||||
sum_qty, sum_amt = [0, 0]
|
||||
doctype = doc.get('parenttype') or doc.doctype
|
||||
|
||||
date_field = ('transaction_date'
|
||||
if doc.get('transaction_date') else 'posting_date')
|
||||
date_field = 'transaction_date' if frappe.get_meta(doctype).has_field('transaction_date') else 'posting_date'
|
||||
|
||||
child_doctype = '{0} Item'.format(doctype)
|
||||
apply_on = frappe.scrub(pr_doc.get('apply_on'))
|
||||
|
@ -10,6 +10,18 @@ frappe.ui.form.on('Process Deferred Accounting', {
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
if (frm.doc.company) {
|
||||
frm.set_query("account", function() {
|
||||
return {
|
||||
filters: {
|
||||
'company': frm.doc.company,
|
||||
'root_type': 'Liability',
|
||||
'is_group': 0
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -238,6 +238,12 @@ class PurchaseInvoice(BuyingController):
|
||||
not frappe.db.get_value("Purchase Order Item", item.po_detail, "delivered_by_supplier")):
|
||||
|
||||
if self.update_stock and (not item.from_warehouse):
|
||||
if for_validate and item.expense_account and item.expense_account != warehouse_account[item.warehouse]["account"]:
|
||||
frappe.msgprint(_('''Row {0}: Expense Head changed to {1} because account {2}
|
||||
is not linked to warehouse {3} or it is not the default inventory account'''.format(
|
||||
item.idx, frappe.bold(warehouse_account[item.warehouse]["account"]),
|
||||
frappe.bold(item.expense_account), frappe.bold(item.warehouse))))
|
||||
|
||||
item.expense_account = warehouse_account[item.warehouse]["account"]
|
||||
else:
|
||||
# check if 'Stock Received But Not Billed' account is credited in Purchase receipt or not
|
||||
@ -247,10 +253,21 @@ class PurchaseInvoice(BuyingController):
|
||||
(item.purchase_receipt, stock_not_billed_account))
|
||||
|
||||
if negative_expense_booked_in_pr:
|
||||
if for_validate and item.expense_account and item.expense_account != stock_not_billed_account:
|
||||
frappe.msgprint(_('''Row {0}: Expense Head changed to {1} because
|
||||
expense is booked against this account in Purchase Receipt {2}'''.format(
|
||||
item.idx, frappe.bold(stock_not_billed_account), frappe.bold(item.purchase_receipt))))
|
||||
|
||||
item.expense_account = stock_not_billed_account
|
||||
else:
|
||||
# If no purchase receipt present then book expense in 'Stock Received But Not Billed'
|
||||
# This is done in cases when Purchase Invoice is created before Purchase Receipt
|
||||
if for_validate and item.expense_account and item.expense_account != stock_not_billed_account:
|
||||
frappe.msgprint(_('''Row {0}: Expense Head changed to {1} as no Purchase
|
||||
Receipt is created against Item {2}. This is done to handle accounting for cases
|
||||
when Purchase Receipt is created after Purchase Invoice'''.format(
|
||||
item.idx, frappe.bold(stock_not_billed_account), frappe.bold(item.item_code))))
|
||||
|
||||
item.expense_account = stock_not_billed_account
|
||||
|
||||
elif item.is_fixed_asset and not is_cwip_accounting_enabled(asset_category):
|
||||
@ -421,6 +438,8 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
self.make_tax_gl_entries(gl_entries)
|
||||
|
||||
gl_entries = make_regional_gl_entries(gl_entries, self)
|
||||
|
||||
gl_entries = merge_similar_entries(gl_entries)
|
||||
|
||||
self.make_payment_gl_entries(gl_entries)
|
||||
@ -459,6 +478,7 @@ class PurchaseInvoice(BuyingController):
|
||||
if self.party_account_currency==self.company_currency else grand_total,
|
||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"project": self.project,
|
||||
"cost_center": self.cost_center
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
@ -499,6 +519,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"account": warehouse_account[item.warehouse]['account'],
|
||||
"against": warehouse_account[item.from_warehouse]["account"],
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"debit": warehouse_debit_amount,
|
||||
}, warehouse_account[item.warehouse]["account_currency"], item=item))
|
||||
@ -508,6 +529,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"account": warehouse_account[item.from_warehouse]['account'],
|
||||
"against": warehouse_account[item.warehouse]["account"],
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"debit": -1 * flt(item.base_net_amount, item.precision("base_net_amount")),
|
||||
}, warehouse_account[item.from_warehouse]["account_currency"], item=item))
|
||||
@ -531,7 +553,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"debit": warehouse_debit_amount,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, account_currency, item=item)
|
||||
)
|
||||
|
||||
@ -544,7 +566,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": item.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"credit": flt(amount),
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
# sub-contracting warehouse
|
||||
@ -557,6 +579,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"account": supplier_warehouse_account,
|
||||
"against": item.expense_account,
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"credit": flt(item.rm_supp_cost)
|
||||
}, warehouse_account[self.supplier_warehouse]["account_currency"], item=item))
|
||||
@ -570,12 +593,26 @@ class PurchaseInvoice(BuyingController):
|
||||
else:
|
||||
amount = flt(item.base_net_amount + item.item_tax_amount, item.precision("base_net_amount"))
|
||||
|
||||
auto_accounting_for_non_stock_items = cint(frappe.db.get_value('Company', self.company, 'enable_perpetual_inventory_for_non_stock_items'))
|
||||
|
||||
if auto_accounting_for_non_stock_items:
|
||||
service_received_but_not_billed_account = self.get_company_default("service_received_but_not_billed")
|
||||
|
||||
if item.purchase_receipt:
|
||||
# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
|
||||
expense_booked_in_pr = frappe.db.get_value('GL Entry', {'is_cancelled': 0,
|
||||
'voucher_type': 'Purchase Receipt', 'voucher_no': item.purchase_receipt, 'voucher_detail_no': item.pr_detail,
|
||||
'account':service_received_but_not_billed_account}, ['name'])
|
||||
|
||||
if expense_booked_in_pr:
|
||||
expense_account = service_received_but_not_billed_account
|
||||
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": expense_account,
|
||||
"against": self.supplier,
|
||||
"debit": amount,
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, account_currency, item=item))
|
||||
|
||||
# If asset is bought through this document and not linked to PR
|
||||
@ -588,7 +625,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": item.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"credit": flt(item.landed_cost_voucher_amount),
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
@ -597,7 +634,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": item.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"debit": flt(item.landed_cost_voucher_amount),
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
# update gross amount of asset bought through this document
|
||||
@ -623,7 +660,8 @@ class PurchaseInvoice(BuyingController):
|
||||
"against": self.supplier,
|
||||
"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
|
||||
"remarks": self.remarks or "Accounting Entry for Stock",
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": item.project or self.project
|
||||
}, item=item)
|
||||
)
|
||||
|
||||
@ -652,7 +690,8 @@ class PurchaseInvoice(BuyingController):
|
||||
"debit": base_asset_amount,
|
||||
"debit_in_account_currency": (base_asset_amount
|
||||
if arbnb_currency == self.company_currency else asset_amount),
|
||||
"cost_center": item.cost_center
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
if item.item_tax_amount:
|
||||
@ -662,6 +701,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"against": self.supplier,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project,
|
||||
"credit": item.item_tax_amount,
|
||||
"credit_in_account_currency": (item.item_tax_amount
|
||||
if asset_eiiav_currency == self.company_currency else
|
||||
@ -678,7 +718,8 @@ class PurchaseInvoice(BuyingController):
|
||||
"debit": base_asset_amount,
|
||||
"debit_in_account_currency": (base_asset_amount
|
||||
if cwip_account_currency == self.company_currency else asset_amount),
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
if item.item_tax_amount and not cint(erpnext.is_perpetual_inventory_enabled(self.company)):
|
||||
@ -689,6 +730,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"cost_center": item.cost_center,
|
||||
"credit": item.item_tax_amount,
|
||||
"project": item.project or self.project,
|
||||
"credit_in_account_currency": (item.item_tax_amount
|
||||
if asset_eiiav_currency == self.company_currency else
|
||||
item.item_tax_amount / self.conversion_rate)
|
||||
@ -704,7 +746,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": item.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"credit": flt(item.landed_cost_voucher_amount),
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
@ -713,7 +755,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": item.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"debit": flt(item.landed_cost_voucher_amount),
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
# update gross amount of assets bought through this document
|
||||
@ -748,7 +790,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"debit": stock_adjustment_amt,
|
||||
"remarks": self.get("remarks") or _("Stock Adjustment"),
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, account_currency, item=item)
|
||||
)
|
||||
|
||||
@ -840,7 +882,8 @@ class PurchaseInvoice(BuyingController):
|
||||
if self.party_account_currency==self.company_currency else self.paid_amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
|
||||
@ -872,7 +915,8 @@ class PurchaseInvoice(BuyingController):
|
||||
if self.party_account_currency==self.company_currency else self.write_off_amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
gl_entries.append(
|
||||
@ -1066,6 +1110,10 @@ def get_list_context(context=None):
|
||||
})
|
||||
return list_context
|
||||
|
||||
@erpnext.allow_regional
|
||||
def make_regional_gl_entries(gl_entries, doc):
|
||||
return gl_entries
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_debit_note(source_name, target_doc=None):
|
||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||
|
@ -16,7 +16,7 @@ frappe.listview_settings['Purchase Invoice'] = {
|
||||
} else if(frappe.datetime.get_diff(doc.due_date) < 0) {
|
||||
return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<,Today"];
|
||||
} else {
|
||||
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due,>=,Today"];
|
||||
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>=,Today"];
|
||||
}
|
||||
} else if(cint(doc.is_return)) {
|
||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||
|
@ -7,14 +7,16 @@ import unittest
|
||||
import frappe, erpnext
|
||||
import frappe.model
|
||||
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
||||
from frappe.utils import cint, flt, today, nowdate, add_days
|
||||
from frappe.utils import cint, flt, today, nowdate, add_days, getdate
|
||||
import frappe.defaults
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
|
||||
test_records as pr_test_records, make_purchase_receipt, get_taxes
|
||||
from erpnext.controllers.accounts_controller import get_payment_terms
|
||||
from erpnext.exceptions import InvalidCurrency
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction
|
||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||
from erpnext.projects.doctype.project.test_project import make_project
|
||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
|
||||
test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Template"]
|
||||
test_ignore = ["Serial No"]
|
||||
@ -434,6 +436,8 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_total_purchase_cost_for_project(self):
|
||||
make_project({'project_name':'_Test Project'})
|
||||
|
||||
existing_purchase_cost = frappe.db.sql("""select sum(base_net_amount)
|
||||
from `tabPurchase Invoice Item` where project = '_Test Project' and docstatus=1""")
|
||||
existing_purchase_cost = existing_purchase_cost and existing_purchase_cost[0][0] or 0
|
||||
@ -807,11 +811,8 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
pi_doc = frappe.get_doc('Purchase Invoice', pi.name)
|
||||
self.assertEqual(pi_doc.outstanding_amount, 0)
|
||||
|
||||
def test_purchase_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_purchase_invoice_with_cost_center(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
|
||||
@ -837,13 +838,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def test_purchase_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
def test_purchase_invoice_without_cost_center(self):
|
||||
cost_center = "_Test Cost Center - _TC"
|
||||
pi = make_purchase_invoice(credit_to="Creditors - _TC")
|
||||
|
||||
@ -866,6 +861,104 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
def test_purchase_invoice_with_project_link(self):
|
||||
project = make_project({
|
||||
'project_name': 'Purchase Invoice Project',
|
||||
'project_template_name': 'Test Project Template',
|
||||
'start_date': '2020-01-01'
|
||||
})
|
||||
item_project = make_project({
|
||||
'project_name': 'Purchase Invoice Item Project',
|
||||
'project_template_name': 'Test Project Template',
|
||||
'start_date': '2019-06-01'
|
||||
})
|
||||
|
||||
pi = make_purchase_invoice(credit_to="Creditors - _TC" ,do_not_save=1)
|
||||
pi.items[0].project = item_project.project_name
|
||||
pi.project = project.project_name
|
||||
|
||||
pi.submit()
|
||||
|
||||
expected_values = {
|
||||
"Creditors - _TC": {
|
||||
"project": project.project_name
|
||||
},
|
||||
"_Test Account Cost for Goods Sold - _TC": {
|
||||
"project": item_project.project_name
|
||||
}
|
||||
}
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, cost_center, project, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
|
||||
order by account asc""", pi.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["project"], gle.project)
|
||||
|
||||
def test_deferred_expense_via_journal_entry(self):
|
||||
deferred_account = create_account(account_name="Deferred Expense",
|
||||
parent_account="Current Assets - _TC", company="_Test Company")
|
||||
|
||||
acc_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
acc_settings.book_deferred_entries_via_journal_entry = 1
|
||||
acc_settings.submit_journal_entries = 1
|
||||
acc_settings.save()
|
||||
|
||||
item = create_item("_Test Item for Deferred Accounting")
|
||||
item.enable_deferred_expense = 1
|
||||
item.deferred_expense_account = deferred_account
|
||||
item.save()
|
||||
|
||||
pi = make_purchase_invoice(item=item.name, qty=1, rate=100, do_not_save=True)
|
||||
pi.set_posting_time = 1
|
||||
pi.posting_date = '2019-03-15'
|
||||
pi.items[0].enable_deferred_expense = 1
|
||||
pi.items[0].service_start_date = "2019-01-10"
|
||||
pi.items[0].service_end_date = "2019-03-15"
|
||||
pi.items[0].deferred_expense_account = deferred_account
|
||||
pi.save()
|
||||
pi.submit()
|
||||
|
||||
pda1 = frappe.get_doc(dict(
|
||||
doctype='Process Deferred Accounting',
|
||||
posting_date=nowdate(),
|
||||
start_date="2019-01-01",
|
||||
end_date="2019-03-31",
|
||||
type="Expense",
|
||||
company="_Test Company"
|
||||
))
|
||||
|
||||
pda1.insert()
|
||||
pda1.submit()
|
||||
|
||||
expected_gle = [
|
||||
["_Test Account Cost for Goods Sold - _TC", 0.0, 33.85, "2019-01-31"],
|
||||
[deferred_account, 33.85, 0.0, "2019-01-31"],
|
||||
["_Test Account Cost for Goods Sold - _TC", 0.0, 43.08, "2019-02-28"],
|
||||
[deferred_account, 43.08, 0.0, "2019-02-28"],
|
||||
["_Test Account Cost for Goods Sold - _TC", 0.0, 23.07, "2019-03-15"],
|
||||
[deferred_account, 23.07, 0.0, "2019-03-15"]
|
||||
]
|
||||
|
||||
gl_entries = gl_entries = frappe.db.sql("""select account, debit, credit, posting_date
|
||||
from `tabGL Entry`
|
||||
where voucher_type='Journal Entry' and voucher_detail_no=%s and posting_date <= %s
|
||||
order by posting_date asc, account asc""", (pi.items[0].name, pi.posting_date), as_dict=1)
|
||||
|
||||
for i, gle in enumerate(gl_entries):
|
||||
self.assertEqual(expected_gle[i][0], gle.account)
|
||||
self.assertEqual(expected_gle[i][1], gle.credit)
|
||||
self.assertEqual(expected_gle[i][2], gle.debit)
|
||||
self.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
|
||||
|
||||
acc_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
acc_settings.book_deferred_entries_via_journal_entry = 0
|
||||
acc_settings.submit_journal_entriessubmit_journal_entries = 0
|
||||
acc_settings.save()
|
||||
|
||||
|
||||
def unlink_payment_on_cancel_of_invoice(enable=1):
|
||||
accounts_settings = frappe.get_doc("Accounts Settings")
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -582,14 +582,14 @@ class SalesInvoice(SellingController):
|
||||
|
||||
def validate_item_code(self):
|
||||
for d in self.get('items'):
|
||||
if not d.item_code:
|
||||
if not d.item_code and self.is_opening == "No":
|
||||
msgprint(_("Item Code required at Row No {0}").format(d.idx), raise_exception=True)
|
||||
|
||||
def validate_warehouse(self):
|
||||
super(SalesInvoice, self).validate_warehouse()
|
||||
|
||||
for d in self.get_item_list():
|
||||
if not d.warehouse and frappe.get_cached_value("Item", d.item_code, "is_stock_item"):
|
||||
if not d.warehouse and d.item_code and frappe.get_cached_value("Item", d.item_code, "is_stock_item"):
|
||||
frappe.throw(_("Warehouse required for stock Item {0}").format(d.item_code))
|
||||
|
||||
def validate_delivery_note(self):
|
||||
@ -790,7 +790,8 @@ class SalesInvoice(SellingController):
|
||||
if self.party_account_currency==self.company_currency else grand_total,
|
||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
|
||||
@ -845,7 +846,8 @@ class SalesInvoice(SellingController):
|
||||
"credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount"))
|
||||
if account_currency==self.company_currency
|
||||
else flt(item.net_amount, item.precision("net_amount"))),
|
||||
"cost_center": item.cost_center
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project
|
||||
}, account_currency, item=item)
|
||||
)
|
||||
|
||||
@ -926,7 +928,8 @@ class SalesInvoice(SellingController):
|
||||
if self.party_account_currency==self.company_currency else flt(self.change_amount),
|
||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
|
||||
@ -959,7 +962,8 @@ class SalesInvoice(SellingController):
|
||||
else flt(self.write_off_amount, self.precision("write_off_amount"))),
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
gl_entries.append(
|
||||
@ -1109,7 +1113,10 @@ class SalesInvoice(SellingController):
|
||||
expiry_date=self.posting_date, include_expired_entry=True)
|
||||
if lp_details and getdate(lp_details.from_date) <= getdate(self.posting_date) and \
|
||||
(not lp_details.to_date or getdate(lp_details.to_date) >= getdate(self.posting_date)):
|
||||
points_earned = cint(eligible_amount/lp_details.collection_factor)
|
||||
|
||||
collection_factor = lp_details.collection_factor if lp_details.collection_factor else 1.0
|
||||
points_earned = cint(eligible_amount/collection_factor)
|
||||
|
||||
doc = frappe.get_doc({
|
||||
"doctype": "Loyalty Point Entry",
|
||||
"company": self.company,
|
||||
@ -1450,11 +1457,17 @@ def get_inter_company_details(doc, doctype):
|
||||
parties = frappe.db.get_all("Supplier", fields=["name"], filters={"disabled": 0, "is_internal_supplier": 1, "represents_company": doc.company})
|
||||
company = frappe.get_cached_value("Customer", doc.customer, "represents_company")
|
||||
|
||||
if not parties:
|
||||
frappe.throw(_('No Supplier found for Inter Company Transactions which represents company {0}').format(frappe.bold(doc.company)))
|
||||
|
||||
party = get_internal_party(parties, "Supplier", doc)
|
||||
else:
|
||||
parties = frappe.db.get_all("Customer", fields=["name"], filters={"disabled": 0, "is_internal_customer": 1, "represents_company": doc.company})
|
||||
company = frappe.get_cached_value("Supplier", doc.supplier, "represents_company")
|
||||
|
||||
if not parties:
|
||||
frappe.throw(_('No Customer found for Inter Company Transactions which represents company {0}').format(frappe.bold(doc.company)))
|
||||
|
||||
party = get_internal_party(parties, "Customer", doc)
|
||||
|
||||
return {
|
||||
@ -1519,14 +1532,22 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
|
||||
def update_details(source_doc, target_doc, source_parent):
|
||||
target_doc.inter_company_invoice_reference = source_doc.name
|
||||
if target_doc.doctype in ["Purchase Invoice", "Purchase Order"]:
|
||||
currency = frappe.db.get_value('Supplier', details.get('party'), 'default_currency')
|
||||
target_doc.company = details.get("company")
|
||||
target_doc.supplier = details.get("party")
|
||||
target_doc.buying_price_list = source_doc.selling_price_list
|
||||
|
||||
if currency:
|
||||
target_doc.currency = currency
|
||||
else:
|
||||
currency = frappe.db.get_value('Customer', details.get('party'), 'default_currency')
|
||||
target_doc.company = details.get("company")
|
||||
target_doc.customer = details.get("party")
|
||||
target_doc.selling_price_list = source_doc.buying_price_list
|
||||
|
||||
if currency:
|
||||
target_doc.currency = currency
|
||||
|
||||
doclist = get_mapped_doc(doctype, source_name, {
|
||||
doctype: {
|
||||
"doctype": target_doctype,
|
||||
|
@ -3,6 +3,7 @@
|
||||
"company": "_Test Company",
|
||||
"conversion_rate": 1.0,
|
||||
"currency": "INR",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"customer": "_Test Customer",
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
@ -38,6 +39,7 @@
|
||||
"description": "VAT",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"rate": 6
|
||||
},
|
||||
{
|
||||
@ -46,6 +48,7 @@
|
||||
"description": "Service Tax",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"rate": 6.36
|
||||
}
|
||||
],
|
||||
@ -76,6 +79,7 @@
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
"doctype": "Sales Invoice",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"items": [
|
||||
{
|
||||
"amount": 500.0,
|
||||
@ -108,6 +112,7 @@
|
||||
"description": "VAT",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"rate": 16
|
||||
},
|
||||
{
|
||||
@ -116,6 +121,7 @@
|
||||
"description": "Service Tax",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"rate": 10
|
||||
}
|
||||
],
|
||||
@ -132,6 +138,7 @@
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
"doctype": "Sales Invoice",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"items": [
|
||||
{
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
@ -259,6 +266,7 @@
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
"doctype": "Sales Invoice",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"items": [
|
||||
{
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
|
@ -1640,11 +1640,8 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si_doc = frappe.get_doc('Sales Invoice', si.name)
|
||||
self.assertEqual(si_doc.outstanding_amount, 0)
|
||||
|
||||
def test_sales_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_sales_invoice_with_cost_center(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
|
||||
@ -1670,13 +1667,46 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
def test_sales_invoice_with_project_link(self):
|
||||
from erpnext.projects.doctype.project.test_project import make_project
|
||||
|
||||
def test_sales_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
project = make_project({
|
||||
'project_name': 'Sales Invoice Project',
|
||||
'project_template_name': 'Test Project Template',
|
||||
'start_date': '2020-01-01'
|
||||
})
|
||||
item_project = make_project({
|
||||
'project_name': 'Sales Invoice Item Project',
|
||||
'project_template_name': 'Test Project Template',
|
||||
'start_date': '2019-06-01'
|
||||
})
|
||||
|
||||
sales_invoice = create_sales_invoice(do_not_save=1)
|
||||
sales_invoice.items[0].project = item_project.project_name
|
||||
sales_invoice.project = project.project_name
|
||||
|
||||
sales_invoice.submit()
|
||||
|
||||
expected_values = {
|
||||
"Debtors - _TC": {
|
||||
"project": project.project_name
|
||||
},
|
||||
"Sales - _TC": {
|
||||
"project": item_project.project_name
|
||||
}
|
||||
}
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, cost_center, project, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
|
||||
order by account asc""", sales_invoice.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["project"], gle.project)
|
||||
|
||||
def test_sales_invoice_without_cost_center(self):
|
||||
cost_center = "_Test Cost Center - _TC"
|
||||
si = create_sales_invoice(debit_to="Debtors - _TC")
|
||||
|
||||
@ -1699,9 +1729,6 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def test_deferred_revenue(self):
|
||||
deferred_account = create_account(account_name="Deferred Revenue",
|
||||
parent_account="Current Liabilities - _TC", company="_Test Company")
|
||||
@ -1720,8 +1747,6 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si.save()
|
||||
si.submit()
|
||||
|
||||
from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income
|
||||
|
||||
pda1 = frappe.get_doc(dict(
|
||||
doctype='Process Deferred Accounting',
|
||||
posting_date=nowdate(),
|
||||
@ -1745,51 +1770,53 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
check_gl_entries(self, si.name, expected_gle, "2019-01-30")
|
||||
|
||||
def test_deferred_error_email(self):
|
||||
def test_fixed_deferred_revenue(self):
|
||||
deferred_account = create_account(account_name="Deferred Revenue",
|
||||
parent_account="Current Liabilities - _TC", company="_Test Company")
|
||||
|
||||
acc_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
acc_settings.book_deferred_entries_based_on = 'Months'
|
||||
acc_settings.save()
|
||||
|
||||
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 = create_sales_invoice(item=item.name, posting_date="2019-01-16", rate=50000, 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].service_start_date = "2019-01-16"
|
||||
si.items[0].service_end_date = "2019-03-31"
|
||||
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(
|
||||
pda1 = frappe.get_doc(dict(
|
||||
doctype='Process Deferred Accounting',
|
||||
posting_date=nowdate(),
|
||||
posting_date='2019-03-31',
|
||||
start_date="2019-01-01",
|
||||
end_date="2019-03-31",
|
||||
type="Income",
|
||||
company="_Test Company"
|
||||
))
|
||||
|
||||
pda.insert()
|
||||
pda.submit()
|
||||
pda1.insert()
|
||||
pda1.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)
|
||||
})
|
||||
expected_gle = [
|
||||
[deferred_account, 10000.0, 0.0, "2019-01-31"],
|
||||
["Sales - _TC", 0.0, 10000.0, "2019-01-31"],
|
||||
[deferred_account, 20000.0, 0.0, "2019-02-28"],
|
||||
["Sales - _TC", 0.0, 20000.0, "2019-02-28"],
|
||||
[deferred_account, 20000.0, 0.0, "2019-03-31"],
|
||||
["Sales - _TC", 0.0, 20000.0, "2019-03-31"]
|
||||
]
|
||||
|
||||
self.assertTrue(email)
|
||||
check_gl_entries(self, si.name, expected_gle, "2019-01-30")
|
||||
|
||||
acc_settings.load_from_db()
|
||||
acc_settings.acc_frozen_upto = None
|
||||
acc_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
acc_settings.book_deferred_entries_based_on = 'Days'
|
||||
acc_settings.save()
|
||||
|
||||
def test_inter_company_transaction(self):
|
||||
|
@ -94,6 +94,7 @@
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
"dimension_col_break",
|
||||
"project",
|
||||
"section_break_54",
|
||||
"page_break"
|
||||
],
|
||||
@ -783,12 +784,18 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Finance Book",
|
||||
"options": "Finance Book"
|
||||
},
|
||||
{
|
||||
"fieldname": "project",
|
||||
"fieldtype": "Link",
|
||||
"label": "Project",
|
||||
"options": "Project"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2019-12-04 12:22:38.517710",
|
||||
"modified": "2020-03-11 12:24:41.749986",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Item",
|
||||
|
@ -45,6 +45,8 @@ class ShippingRule(Document):
|
||||
shipping_amount = 0.0
|
||||
by_value = False
|
||||
|
||||
if doc.get_shipping_address():
|
||||
# validate country only if there is address
|
||||
self.validate_countries(doc)
|
||||
|
||||
if self.calculate_based_on == 'Net Total':
|
||||
|
@ -180,7 +180,7 @@ def get_advance_vouchers(suppliers, fiscal_year=None, company=None, from_date=No
|
||||
if company:
|
||||
condition += "and company =%s" % (company)
|
||||
if from_date and to_date:
|
||||
condition += "and posting_date between %s and %s" % (company, from_date, to_date)
|
||||
condition += "and posting_date between %s and %s" % (from_date, to_date)
|
||||
|
||||
## Appending the same supplier again if length of suppliers list is 1
|
||||
## since tuple of single element list contains None, For example ('Test Supplier 1', )
|
||||
|
@ -140,10 +140,8 @@ def make_entry(args, adv_adj, update_outstanding):
|
||||
gle = frappe.new_doc("GL Entry")
|
||||
gle.update(args)
|
||||
gle.flags.ignore_permissions = 1
|
||||
gle.validate()
|
||||
gle.db_insert()
|
||||
gle.insert()
|
||||
gle.run_method("on_update_with_args", adv_adj, update_outstanding)
|
||||
gle.flags.ignore_validate = True
|
||||
gle.submit()
|
||||
|
||||
# check against budget
|
||||
|
50
erpnext/accounts/module_onboarding/accounts/accounts.json
Normal file
50
erpnext/accounts/module_onboarding/accounts/accounts.json
Normal file
@ -0,0 +1,50 @@
|
||||
{
|
||||
"allow_roles": [
|
||||
{
|
||||
"role": "Accounts Manager"
|
||||
},
|
||||
{
|
||||
"role": "Accounts User"
|
||||
}
|
||||
],
|
||||
"creation": "2020-05-13 19:03:32.564049",
|
||||
"docstatus": 0,
|
||||
"doctype": "Module Onboarding",
|
||||
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/accounts",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"modified": "2020-07-08 14:06:09.033880",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts",
|
||||
"owner": "Administrator",
|
||||
"steps": [
|
||||
{
|
||||
"step": "Chart Of Accounts"
|
||||
},
|
||||
{
|
||||
"step": "Setup Taxes"
|
||||
},
|
||||
{
|
||||
"step": "Create a Product"
|
||||
},
|
||||
{
|
||||
"step": "Create a Supplier"
|
||||
},
|
||||
{
|
||||
"step": "Create Your First Purchase Invoice"
|
||||
},
|
||||
{
|
||||
"step": "Create a Customer"
|
||||
},
|
||||
{
|
||||
"step": "Create Your First Sales Invoice"
|
||||
},
|
||||
{
|
||||
"step": "Configure Account Settings"
|
||||
}
|
||||
],
|
||||
"subtitle": "Accounts, Invoices, Taxation, and more.",
|
||||
"success_message": "The Accounts Module is all set up!",
|
||||
"title": "Let's Set Up Your Accounts and Taxes."
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"action": "Go to Page",
|
||||
"creation": "2020-05-13 19:58:20.928127",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-05-14 17:40:28.410447",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Chart Of Accounts",
|
||||
"owner": "Administrator",
|
||||
"path": "Tree/Account",
|
||||
"reference_document": "Account",
|
||||
"show_full_form": 0,
|
||||
"title": "Review Chart Of Accounts",
|
||||
"validate_action": 0
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"creation": "2020-05-14 17:53:00.876946",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_mandatory": 0,
|
||||
"is_single": 1,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-05-14 18:06:25.212923",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Configure Account Settings",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Accounts Settings",
|
||||
"show_full_form": 1,
|
||||
"title": "Configure Account Settings",
|
||||
"validate_action": 1
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"creation": "2020-05-14 17:46:41.831517",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-06-01 13:16:19.731719",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create a Customer",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Customer",
|
||||
"show_full_form": 0,
|
||||
"title": "Create a Customer",
|
||||
"validate_action": 1
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"creation": "2020-05-12 18:16:06.624554",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-05-12 18:30:02.489949",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create a Product",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Item",
|
||||
"show_full_form": 0,
|
||||
"title": "Create a Product",
|
||||
"validate_action": 1
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"creation": "2020-05-14 22:09:10.043554",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-05-14 22:09:10.043554",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create a Supplier",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Supplier",
|
||||
"show_full_form": 0,
|
||||
"title": "Create a Supplier",
|
||||
"validate_action": 1
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"creation": "2020-05-14 22:10:07.049704",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-05-14 22:10:07.049704",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create Your First Purchase Invoice",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Purchase Invoice",
|
||||
"show_full_form": 1,
|
||||
"title": "Create Your First Purchase Invoice ",
|
||||
"validate_action": 1
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"creation": "2020-05-14 17:48:21.019019",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-05-14 17:48:21.019019",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create Your First Sales Invoice",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Sales Invoice",
|
||||
"show_full_form": 1,
|
||||
"title": "Create Your First Sales Invoice ",
|
||||
"validate_action": 1
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"creation": "2020-05-13 19:29:43.844463",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_mandatory": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-05-14 17:40:16.014413",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Setup Taxes",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Sales Taxes and Charges Template",
|
||||
"show_full_form": 1,
|
||||
"title": "Lets create a Tax Template for Sales ",
|
||||
"validate_action": 0
|
||||
}
|
@ -289,6 +289,7 @@ def get_matching_transactions_payments(description_matching):
|
||||
else:
|
||||
return []
|
||||
|
||||
@frappe.whitelist()
|
||||
def payment_entry_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
|
||||
if not account:
|
||||
@ -317,6 +318,7 @@ def payment_entry_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
}
|
||||
)
|
||||
|
||||
@frappe.whitelist()
|
||||
def journal_entry_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
|
||||
|
||||
@ -352,6 +354,7 @@ def journal_entry_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
}
|
||||
)
|
||||
|
||||
@frappe.whitelist()
|
||||
def sales_invoices_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""
|
||||
SELECT
|
||||
|
@ -602,10 +602,14 @@ def get_party_shipping_address(doctype, name):
|
||||
else:
|
||||
return ''
|
||||
|
||||
def get_partywise_advanced_payment_amount(party_type, posting_date = None, company=None):
|
||||
def get_partywise_advanced_payment_amount(party_type, posting_date = None, future_payment=0, company=None):
|
||||
cond = "1=1"
|
||||
if posting_date:
|
||||
if future_payment:
|
||||
cond = "posting_date <= '{0}' OR DATE(creation) <= '{0}' """.format(posting_date)
|
||||
else:
|
||||
cond = "posting_date <= '{0}'".format(posting_date)
|
||||
|
||||
if company:
|
||||
cond += "and company = '{0}'".format(company)
|
||||
|
||||
|
@ -61,7 +61,7 @@ def make_sales_invoice():
|
||||
debit_to = 'Debtors - _TC2',
|
||||
income_account = 'Sales - _TC2',
|
||||
expense_account = 'Cost of Goods Sold - _TC2',
|
||||
cost_center = '_Test Company 2 - _TC2')
|
||||
cost_center = 'Main - _TC2')
|
||||
|
||||
|
||||
|
||||
|
@ -17,41 +17,6 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
},
|
||||
{
|
||||
"fieldname":"ageing_based_on",
|
||||
"label": __("Ageing Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": 'Posting Date\nDue Date\nSupplier Invoice Date',
|
||||
"default": "Due Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"range1",
|
||||
"label": __("Ageing Range 1"),
|
||||
"fieldtype": "Int",
|
||||
"default": "30",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range2",
|
||||
"label": __("Ageing Range 2"),
|
||||
"fieldtype": "Int",
|
||||
"default": "60",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range3",
|
||||
"label": __("Ageing Range 3"),
|
||||
"fieldtype": "Int",
|
||||
"default": "90",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range4",
|
||||
"label": __("Ageing Range 4"),
|
||||
"fieldtype": "Int",
|
||||
"default": "120",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"finance_book",
|
||||
"label": __("Finance Book"),
|
||||
@ -88,6 +53,41 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname":"ageing_based_on",
|
||||
"label": __("Ageing Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": 'Posting Date\nDue Date\nSupplier Invoice Date',
|
||||
"default": "Due Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"range1",
|
||||
"label": __("Ageing Range 1"),
|
||||
"fieldtype": "Int",
|
||||
"default": "30",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range2",
|
||||
"label": __("Ageing Range 2"),
|
||||
"fieldtype": "Int",
|
||||
"default": "60",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range3",
|
||||
"label": __("Ageing Range 3"),
|
||||
"fieldtype": "Int",
|
||||
"default": "90",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range4",
|
||||
"label": __("Ageing Range 4"),
|
||||
"fieldtype": "Int",
|
||||
"default": "120",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"payment_terms_template",
|
||||
"label": __("Payment Terms Template"),
|
||||
@ -135,12 +135,5 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.dimension_filters.forEach((dimension) => {
|
||||
frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{
|
||||
"fieldname": dimension["fieldname"],
|
||||
"label": __(dimension["label"]),
|
||||
"fieldtype": "Link",
|
||||
"options": dimension["document_type"]
|
||||
});
|
||||
});
|
||||
erpnext.utils.add_dimensions('Accounts Payable', 9);
|
||||
|
||||
|
@ -104,12 +104,5 @@ frappe.query_reports["Accounts Payable Summary"] = {
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.dimension_filters.forEach((dimension) => {
|
||||
frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{
|
||||
"fieldname": dimension["fieldname"],
|
||||
"label": __(dimension["label"]),
|
||||
"fieldtype": "Link",
|
||||
"options": dimension["document_type"]
|
||||
});
|
||||
});
|
||||
erpnext.utils.add_dimensions('Accounts Payable Summary', 9);
|
||||
|
||||
|
@ -17,41 +17,6 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
},
|
||||
{
|
||||
"fieldname":"ageing_based_on",
|
||||
"label": __("Ageing Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": 'Posting Date\nDue Date',
|
||||
"default": "Due Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"range1",
|
||||
"label": __("Ageing Range 1"),
|
||||
"fieldtype": "Int",
|
||||
"default": "30",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range2",
|
||||
"label": __("Ageing Range 2"),
|
||||
"fieldtype": "Int",
|
||||
"default": "60",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range3",
|
||||
"label": __("Ageing Range 3"),
|
||||
"fieldtype": "Int",
|
||||
"default": "90",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range4",
|
||||
"label": __("Ageing Range 4"),
|
||||
"fieldtype": "Int",
|
||||
"default": "120",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"finance_book",
|
||||
"label": __("Finance Book"),
|
||||
@ -101,6 +66,41 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname":"ageing_based_on",
|
||||
"label": __("Ageing Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": 'Posting Date\nDue Date',
|
||||
"default": "Due Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"range1",
|
||||
"label": __("Ageing Range 1"),
|
||||
"fieldtype": "Int",
|
||||
"default": "30",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range2",
|
||||
"label": __("Ageing Range 2"),
|
||||
"fieldtype": "Int",
|
||||
"default": "60",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range3",
|
||||
"label": __("Ageing Range 3"),
|
||||
"fieldtype": "Int",
|
||||
"default": "90",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range4",
|
||||
"label": __("Ageing Range 4"),
|
||||
"fieldtype": "Int",
|
||||
"default": "120",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"customer_group",
|
||||
"label": __("Customer Group"),
|
||||
@ -113,12 +113,6 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
"fieldtype": "Link",
|
||||
"options": "Payment Terms Template"
|
||||
},
|
||||
{
|
||||
"fieldname":"territory",
|
||||
"label": __("Territory"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Territory"
|
||||
},
|
||||
{
|
||||
"fieldname":"sales_partner",
|
||||
"label": __("Sales Partner"),
|
||||
@ -131,6 +125,12 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
"fieldtype": "Link",
|
||||
"options": "Sales Person"
|
||||
},
|
||||
{
|
||||
"fieldname":"territory",
|
||||
"label": __("Territory"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Territory"
|
||||
},
|
||||
{
|
||||
"fieldname": "group_by_party",
|
||||
"label": __("Group By Customer"),
|
||||
@ -199,12 +199,5 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.dimension_filters.forEach((dimension) => {
|
||||
frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{
|
||||
"fieldname": dimension["fieldname"],
|
||||
"label": __(dimension["label"]),
|
||||
"fieldtype": "Link",
|
||||
"options": dimension["document_type"]
|
||||
});
|
||||
});
|
||||
erpnext.utils.add_dimensions('Accounts Receivable', 9);
|
||||
|
||||
|
@ -169,6 +169,8 @@ class ReceivablePayableReport(object):
|
||||
|
||||
def append_subtotal_row(self, party):
|
||||
sub_total_row = self.total_row_map.get(party)
|
||||
|
||||
if sub_total_row:
|
||||
self.data.append(sub_total_row)
|
||||
self.data.append({})
|
||||
self.update_sub_total_row(sub_total_row, 'Total')
|
||||
@ -232,6 +234,7 @@ class ReceivablePayableReport(object):
|
||||
|
||||
if self.filters.get('group_by_party'):
|
||||
self.append_subtotal_row(self.previous_party)
|
||||
if self.data:
|
||||
self.data.append(self.total_row_map.get('Total'))
|
||||
|
||||
def append_row(self, row):
|
||||
@ -534,7 +537,7 @@ class ReceivablePayableReport(object):
|
||||
|
||||
def get_ageing_data(self, entry_date, row):
|
||||
# [0-30, 30-60, 60-90, 90-120, 120-above]
|
||||
row.range1 = row.range2 = row.range3 = row.range4 = range5 = 0.0
|
||||
row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0
|
||||
|
||||
if not (self.age_as_on and entry_date):
|
||||
return
|
||||
@ -546,7 +549,7 @@ class ReceivablePayableReport(object):
|
||||
self.filters.range1, self.filters.range2, self.filters.range3, self.filters.range4 = 30, 60, 90, 120
|
||||
|
||||
for i, days in enumerate([self.filters.range1, self.filters.range2, self.filters.range3, self.filters.range4]):
|
||||
if row.age <= days:
|
||||
if cint(row.age) <= cint(days):
|
||||
index = i
|
||||
break
|
||||
|
||||
@ -559,6 +562,14 @@ class ReceivablePayableReport(object):
|
||||
conditions, values = self.prepare_conditions()
|
||||
order_by = self.get_order_by_condition()
|
||||
|
||||
if self.filters.show_future_payments:
|
||||
values.insert(2, self.filters.report_date)
|
||||
|
||||
date_condition = """AND (posting_date <= %s
|
||||
OR (against_voucher IS NULL AND DATE(creation) <= %s))"""
|
||||
else:
|
||||
date_condition = "AND posting_date <=%s"
|
||||
|
||||
if self.filters.get(scrub(self.party_type)):
|
||||
select_fields = "debit_in_account_currency as debit, credit_in_account_currency as credit"
|
||||
else:
|
||||
@ -574,9 +585,8 @@ class ReceivablePayableReport(object):
|
||||
docstatus < 2
|
||||
and party_type=%s
|
||||
and (party is not null and party != '')
|
||||
and posting_date <= %s
|
||||
{1} {2}"""
|
||||
.format(select_fields, conditions, order_by), values, as_dict=True)
|
||||
{1} {2} {3}"""
|
||||
.format(select_fields, date_condition, conditions, order_by), values, as_dict=True)
|
||||
|
||||
def get_sales_invoices_or_customers_based_on_sales_person(self):
|
||||
if self.filters.get("sales_person"):
|
||||
|
@ -63,7 +63,7 @@ def make_sales_invoice():
|
||||
debit_to = 'Debtors - _TC2',
|
||||
income_account = 'Sales - _TC2',
|
||||
expense_account = 'Cost of Goods Sold - _TC2',
|
||||
cost_center = '_Test Company 2 - _TC2',
|
||||
cost_center = 'Main - _TC2',
|
||||
do_not_save=1)
|
||||
|
||||
si.append('payment_schedule', dict(due_date=getdate(add_days(today(), 30)), invoice_portion=30.00, payment_amount=30))
|
||||
@ -90,7 +90,7 @@ def make_credit_note(docname):
|
||||
debit_to = 'Debtors - _TC2',
|
||||
income_account = 'Sales - _TC2',
|
||||
expense_account = 'Cost of Goods Sold - _TC2',
|
||||
cost_center = '_Test Company 2 - _TC2',
|
||||
cost_center = 'Main - _TC2',
|
||||
is_return = 1,
|
||||
return_against = docname)
|
||||
|
||||
|
@ -111,7 +111,12 @@ frappe.query_reports["Accounts Receivable Summary"] = {
|
||||
"fieldname":"based_on_payment_terms",
|
||||
"label": __("Based On Payment Terms"),
|
||||
"fieldtype": "Check",
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname":"show_future_payments",
|
||||
"label": __("Show Future Payments"),
|
||||
"fieldtype": "Check",
|
||||
},
|
||||
],
|
||||
|
||||
onload: function(report) {
|
||||
@ -122,11 +127,4 @@ frappe.query_reports["Accounts Receivable Summary"] = {
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.dimension_filters.forEach((dimension) => {
|
||||
frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{
|
||||
"fieldname": dimension["fieldname"],
|
||||
"label": __(dimension["label"]),
|
||||
"fieldtype": "Link",
|
||||
"options": dimension["document_type"]
|
||||
});
|
||||
});
|
||||
erpnext.utils.add_dimensions('Accounts Receivable Summary', 9);
|
||||
|
@ -33,7 +33,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
self.get_party_total(args)
|
||||
|
||||
party_advance_amount = get_partywise_advanced_payment_amount(self.party_type,
|
||||
self.filters.report_date, self.filters.company) or {}
|
||||
self.filters.report_date, self.filters.show_future_payments, self.filters.company) or {}
|
||||
|
||||
for party, party_dict in iteritems(self.party_total):
|
||||
if party_dict.outstanding == 0:
|
||||
|
@ -93,7 +93,7 @@ def get_assets(filters):
|
||||
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
|
||||
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
|
||||
from (SELECT a.asset_category,
|
||||
ifnull(sum(case when ds.schedule_date < %(from_date)s then
|
||||
ifnull(sum(case when ds.schedule_date < %(from_date)s and (ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s) then
|
||||
ds.depreciation_amount
|
||||
else
|
||||
0
|
||||
@ -111,13 +111,11 @@ def get_assets(filters):
|
||||
0
|
||||
end), 0) as depreciation_amount_during_the_period
|
||||
from `tabAsset` a, `tabDepreciation Schedule` ds
|
||||
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and a.name = ds.parent
|
||||
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and a.name = ds.parent and ifnull(ds.journal_entry, '') != ''
|
||||
group by a.asset_category
|
||||
union
|
||||
SELECT a.asset_category,
|
||||
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
|
||||
and (a.disposal_date < %(from_date)s or a.disposal_date > %(to_date)s)
|
||||
then
|
||||
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and (a.disposal_date < %(from_date)s or a.disposal_date > %(to_date)s) then
|
||||
0
|
||||
else
|
||||
a.opening_accumulated_depreciation
|
||||
|
@ -4,6 +4,8 @@
|
||||
frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
frappe.query_reports["Balance Sheet"] = $.extend({}, erpnext.financial_statements);
|
||||
|
||||
erpnext.utils.add_dimensions('Balance Sheet', 10);
|
||||
|
||||
frappe.query_reports["Balance Sheet"]["filters"].push({
|
||||
"fieldname": "accumulated_values",
|
||||
"label": __("Accumulated Values"),
|
||||
|
@ -29,6 +29,26 @@ def execute(filters=None):
|
||||
for dimension in dimensions:
|
||||
dimension_items = cam_map.get(dimension)
|
||||
if dimension_items:
|
||||
data = get_final_data(dimension, dimension_items, filters, period_month_ranges, data, 0)
|
||||
else:
|
||||
DCC_allocation = frappe.db.sql('''SELECT parent, sum(percentage_allocation) as percentage_allocation
|
||||
FROM `tabDistributed Cost Center`
|
||||
WHERE cost_center IN %(dimension)s
|
||||
AND parent NOT IN %(dimension)s
|
||||
GROUP BY parent''',{'dimension':[dimension]})
|
||||
if DCC_allocation:
|
||||
filters['budget_against_filter'] = [DCC_allocation[0][0]]
|
||||
cam_map = get_dimension_account_month_map(filters)
|
||||
dimension_items = cam_map.get(DCC_allocation[0][0])
|
||||
if dimension_items:
|
||||
data = get_final_data(dimension, dimension_items, filters, period_month_ranges, data, DCC_allocation[0][1])
|
||||
|
||||
chart = get_chart_data(filters, columns, data)
|
||||
|
||||
return columns, data, None, chart
|
||||
|
||||
def get_final_data(dimension, dimension_items, filters, period_month_ranges, data, DCC_allocation):
|
||||
|
||||
for account, monthwise_data in iteritems(dimension_items):
|
||||
row = [dimension, account]
|
||||
totals = [0, 0, 0]
|
||||
@ -46,24 +66,39 @@ def execute(filters=None):
|
||||
|
||||
period_data[0] += last_total
|
||||
|
||||
if filters.get("show_cumulative"):
|
||||
if DCC_allocation:
|
||||
period_data[0] = period_data[0]*(DCC_allocation/100)
|
||||
period_data[1] = period_data[1]*(DCC_allocation/100)
|
||||
|
||||
if(filters.get("show_cumulative")):
|
||||
last_total = period_data[0] - period_data[1]
|
||||
|
||||
period_data[2] = period_data[0] - period_data[1]
|
||||
row += period_data
|
||||
totals[2] = totals[0] - totals[1]
|
||||
if filters["period"] != "Yearly":
|
||||
if filters["period"] != "Yearly" :
|
||||
row += totals
|
||||
data.append(row)
|
||||
|
||||
return columns, data
|
||||
return data
|
||||
|
||||
|
||||
def get_columns(filters):
|
||||
columns = [
|
||||
_(filters.get("budget_against"))
|
||||
+ ":Link/%s:150" % (filters.get("budget_against")),
|
||||
_("Account") + ":Link/Account:150"
|
||||
{
|
||||
'label': _(filters.get("budget_against")),
|
||||
'fieldtype': 'Link',
|
||||
'fieldname': 'budget_against',
|
||||
'options': filters.get('budget_against'),
|
||||
'width': 150
|
||||
},
|
||||
{
|
||||
'label': _('Account'),
|
||||
'fieldname': 'Account',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Account',
|
||||
'width': 150
|
||||
}
|
||||
]
|
||||
|
||||
group_months = False if filters["period"] == "Monthly" else True
|
||||
@ -79,7 +114,12 @@ def get_columns(filters):
|
||||
_("Variance ") + " " + str(year[0])
|
||||
]
|
||||
for label in labels:
|
||||
columns.append(label + ":Float:150")
|
||||
columns.append({
|
||||
'label': label,
|
||||
'fieldtype': 'Float',
|
||||
'fieldname': frappe.scrub(label),
|
||||
'width': 150
|
||||
})
|
||||
else:
|
||||
for label in [
|
||||
_("Budget") + " (%s)" + " " + str(year[0]),
|
||||
@ -95,14 +135,23 @@ def get_columns(filters):
|
||||
else:
|
||||
label = label % formatdate(from_date, format_string="MMM")
|
||||
|
||||
columns.append(label + ":Float:150")
|
||||
columns.append({
|
||||
'label': label,
|
||||
'fieldtype': 'Float',
|
||||
'fieldname': frappe.scrub(label),
|
||||
'width': 150
|
||||
})
|
||||
|
||||
if filters["period"] != "Yearly":
|
||||
return columns + [
|
||||
_("Total Budget") + ":Float:150",
|
||||
_("Total Actual") + ":Float:150",
|
||||
_("Total Variance") + ":Float:150"
|
||||
]
|
||||
for label in [_("Total Budget"), _("Total Actual"), _("Total Variance")]:
|
||||
columns.append({
|
||||
'label': label,
|
||||
'fieldtype': 'Float',
|
||||
'fieldname': frappe.scrub(label),
|
||||
'width': 150
|
||||
})
|
||||
|
||||
return columns
|
||||
else:
|
||||
return columns
|
||||
|
||||
@ -173,7 +222,7 @@ def get_dimension_target_details(filters):
|
||||
filters.budget_against,
|
||||
filters.company,
|
||||
]
|
||||
+ filters.get("budget_against_filter")
|
||||
+ (filters.get("budget_against_filter") or [])
|
||||
), as_dict=True)
|
||||
|
||||
|
||||
@ -305,3 +354,49 @@ def get_fiscal_years(filters):
|
||||
})
|
||||
|
||||
return fiscal_year
|
||||
|
||||
def get_chart_data(filters, columns, data):
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
labels = []
|
||||
|
||||
fiscal_year = get_fiscal_years(filters)
|
||||
group_months = False if filters["period"] == "Monthly" else True
|
||||
|
||||
for year in fiscal_year:
|
||||
for from_date, to_date in get_period_date_ranges(filters["period"], year[0]):
|
||||
if filters['period'] == 'Yearly':
|
||||
labels.append(year[0])
|
||||
else:
|
||||
if group_months:
|
||||
label = formatdate(from_date, format_string="MMM") + "-" \
|
||||
+ formatdate(to_date, format_string="MMM")
|
||||
labels.append(label)
|
||||
else:
|
||||
label = formatdate(from_date, format_string="MMM")
|
||||
labels.append(label)
|
||||
|
||||
no_of_columns = len(labels)
|
||||
|
||||
budget_values, actual_values = [0] * no_of_columns, [0] * no_of_columns
|
||||
for d in data:
|
||||
values = d[2:]
|
||||
index = 0
|
||||
|
||||
for i in range(no_of_columns):
|
||||
budget_values[i] += values[index]
|
||||
actual_values[i] += values[index+1]
|
||||
index += 3
|
||||
|
||||
return {
|
||||
'data': {
|
||||
'labels': labels,
|
||||
'datasets': [
|
||||
{'name': 'Budget', 'chartType': 'bar', 'values': budget_values},
|
||||
{'name': 'Actual Expense', 'chartType': 'bar', 'values': actual_values}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
frappe.query_reports["Cash Flow"] = $.extend({},
|
||||
erpnext.financial_statements);
|
||||
|
||||
erpnext.utils.add_dimensions('Cash Flow', 10);
|
||||
|
||||
// The last item in the array is the definition for Presentation Currency
|
||||
// filter. It won't be used in cash flow for now so we pop it. Please take
|
||||
// of this if you are working here.
|
||||
|
@ -334,10 +334,9 @@ def compute_data(filters, company_currency, profit_data, period_list, light_mapp
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters.periodicity: filters.periodicity = "Monthly"
|
||||
period_list = get_period_list(
|
||||
filters.from_fiscal_year, filters.to_fiscal_year, filters.periodicity,
|
||||
filters.accumulated_values, filters.company
|
||||
)
|
||||
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
|
||||
filters.period_start_date, filters.period_end_date, filters.filter_based_on,
|
||||
filters.periodicity, company=filters.company)
|
||||
|
||||
mappers = get_mappers_from_db()
|
||||
|
||||
|
@ -33,7 +33,6 @@ frappe.query_reports["Consolidated Financial Statement"] = {
|
||||
"fieldname":"period_start_date",
|
||||
"label": __("Start Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.nowdate(),
|
||||
"hidden": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
@ -41,7 +40,6 @@ frappe.query_reports["Consolidated Financial Statement"] = {
|
||||
"fieldname":"period_end_date",
|
||||
"label": __("End Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.add_months(frappe.datetime.nowdate(), 12),
|
||||
"hidden": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
@ -106,5 +104,16 @@ frappe.query_reports["Consolidated Financial Statement"] = {
|
||||
value = $value.wrap("<p></p>").parent().html();
|
||||
}
|
||||
return value;
|
||||
},
|
||||
onload: function() {
|
||||
let fiscal_year = frappe.defaults.get_user_default("fiscal_year")
|
||||
|
||||
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
|
||||
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
|
||||
frappe.query_report.set_filter_value({
|
||||
period_start_date: fy.year_start_date,
|
||||
period_end_date: fy.year_end_date
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for(let j=0, k=data.length-1; j<k; j++) { %}
|
||||
{% for(let j=0, k=data.length; j<k; j++) { %}
|
||||
{%
|
||||
var row = data[j];
|
||||
var row_class = data[j].parent_account ? "" : "financial-statements-important";
|
||||
|
@ -8,6 +8,7 @@ from __future__ import unicode_literals
|
||||
import re
|
||||
from past.builtins import cmp
|
||||
import functools
|
||||
import math
|
||||
|
||||
import frappe, erpnext
|
||||
from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
|
||||
@ -19,7 +20,7 @@ from six import itervalues
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children
|
||||
|
||||
def get_period_list(from_fiscal_year, to_fiscal_year, period_start_date, period_end_date, filter_based_on, periodicity, accumulated_values=False,
|
||||
company=None, reset_period_on_fy_change=True):
|
||||
company=None, reset_period_on_fy_change=True, ignore_fiscal_year=False):
|
||||
"""Get a list of dict {"from_date": from_date, "to_date": to_date, "key": key, "label": label}
|
||||
Periodicity can be (Yearly, Quarterly, Monthly)"""
|
||||
|
||||
@ -45,10 +46,7 @@ def get_period_list(from_fiscal_year, to_fiscal_year, period_start_date, period_
|
||||
start_date = year_start_date
|
||||
months = get_months(year_start_date, year_end_date)
|
||||
|
||||
if (months // months_to_add) != (months / months_to_add):
|
||||
months += months_to_add
|
||||
|
||||
for i in range(months // months_to_add):
|
||||
for i in range(math.ceil(months / months_to_add)):
|
||||
period = frappe._dict({
|
||||
"from_date": start_date
|
||||
})
|
||||
@ -56,8 +54,7 @@ def get_period_list(from_fiscal_year, to_fiscal_year, period_start_date, period_
|
||||
to_date = add_months(start_date, months_to_add)
|
||||
start_date = to_date
|
||||
|
||||
if to_date == get_first_day(to_date):
|
||||
# if to_date is the first day, get the last day of previous month
|
||||
# Subtract one day from to_date, as it may be first day in next fiscal year or month
|
||||
to_date = add_days(to_date, -1)
|
||||
|
||||
if to_date <= year_end_date:
|
||||
@ -67,6 +64,7 @@ def get_period_list(from_fiscal_year, to_fiscal_year, period_start_date, period_
|
||||
# if a fiscal year ends before a 12 month period
|
||||
period.to_date = year_end_date
|
||||
|
||||
if not ignore_fiscal_year:
|
||||
period.to_date_fiscal_year = get_fiscal_year(period.to_date, company=company)[0]
|
||||
period.from_date_fiscal_year_start_date = get_fiscal_year(period.from_date, company=company)[1]
|
||||
|
||||
@ -386,11 +384,43 @@ def set_gl_entries_by_account(
|
||||
key: value
|
||||
})
|
||||
|
||||
distributed_cost_center_query = ""
|
||||
if filters and filters.get('cost_center'):
|
||||
distributed_cost_center_query = """
|
||||
UNION ALL
|
||||
SELECT posting_date,
|
||||
account,
|
||||
debit*(DCC_allocation.percentage_allocation/100) as debit,
|
||||
credit*(DCC_allocation.percentage_allocation/100) as credit,
|
||||
is_opening,
|
||||
fiscal_year,
|
||||
debit_in_account_currency*(DCC_allocation.percentage_allocation/100) as debit_in_account_currency,
|
||||
credit_in_account_currency*(DCC_allocation.percentage_allocation/100) as credit_in_account_currency,
|
||||
account_currency
|
||||
FROM `tabGL Entry`,
|
||||
(
|
||||
SELECT parent, sum(percentage_allocation) as percentage_allocation
|
||||
FROM `tabDistributed Cost Center`
|
||||
WHERE cost_center IN %(cost_center)s
|
||||
AND parent NOT IN %(cost_center)s
|
||||
GROUP BY parent
|
||||
) as DCC_allocation
|
||||
WHERE company=%(company)s
|
||||
{additional_conditions}
|
||||
AND posting_date <= %(to_date)s
|
||||
AND is_cancelled = 0
|
||||
AND cost_center = DCC_allocation.parent
|
||||
""".format(additional_conditions=additional_conditions.replace("and cost_center in %(cost_center)s ", ''))
|
||||
|
||||
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
|
||||
where company=%(company)s
|
||||
{additional_conditions}
|
||||
and posting_date <= %(to_date)s
|
||||
order by account, posting_date""".format(additional_conditions=additional_conditions), gl_filters, as_dict=True) #nosec
|
||||
and is_cancelled = 0
|
||||
{distributed_cost_center_query}
|
||||
order by account, posting_date""".format(
|
||||
additional_conditions=additional_conditions,
|
||||
distributed_cost_center_query=distributed_cost_center_query), gl_filters, as_dict=True) #nosec
|
||||
|
||||
if filters and filters.get('presentation_currency'):
|
||||
convert_to_presentation_currency(gl_entries, get_currency(filters))
|
||||
|
@ -164,12 +164,5 @@ frappe.query_reports["General Ledger"] = {
|
||||
]
|
||||
}
|
||||
|
||||
erpnext.dimension_filters.forEach((dimension) => {
|
||||
frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{
|
||||
"fieldname": dimension["fieldname"],
|
||||
"label": __(dimension["label"]),
|
||||
"fieldtype": "Link",
|
||||
"options": dimension["document_type"]
|
||||
});
|
||||
});
|
||||
erpnext.utils.add_dimensions('General Ledger', 15)
|
||||
|
||||
|
@ -128,18 +128,53 @@ def get_gl_entries(filters):
|
||||
filters['company_fb'] = frappe.db.get_value("Company",
|
||||
filters.get("company"), 'default_finance_book')
|
||||
|
||||
distributed_cost_center_query = ""
|
||||
if filters and filters.get('cost_center'):
|
||||
select_fields_with_percentage = """, debit*(DCC_allocation.percentage_allocation/100) as debit, credit*(DCC_allocation.percentage_allocation/100) as credit, debit_in_account_currency*(DCC_allocation.percentage_allocation/100) as debit_in_account_currency,
|
||||
credit_in_account_currency*(DCC_allocation.percentage_allocation/100) as credit_in_account_currency """
|
||||
|
||||
distributed_cost_center_query = """
|
||||
UNION ALL
|
||||
SELECT name as gl_entry,
|
||||
posting_date,
|
||||
account,
|
||||
party_type,
|
||||
party,
|
||||
voucher_type,
|
||||
voucher_no,
|
||||
cost_center, project,
|
||||
against_voucher_type,
|
||||
against_voucher,
|
||||
account_currency,
|
||||
remarks, against,
|
||||
is_opening, `tabGL Entry`.creation {select_fields_with_percentage}
|
||||
FROM `tabGL Entry`,
|
||||
(
|
||||
SELECT parent, sum(percentage_allocation) as percentage_allocation
|
||||
FROM `tabDistributed Cost Center`
|
||||
WHERE cost_center IN %(cost_center)s
|
||||
AND parent NOT IN %(cost_center)s
|
||||
GROUP BY parent
|
||||
) as DCC_allocation
|
||||
WHERE company=%(company)s
|
||||
{conditions}
|
||||
AND posting_date <= %(to_date)s
|
||||
AND cost_center = DCC_allocation.parent
|
||||
""".format(select_fields_with_percentage=select_fields_with_percentage, conditions=get_conditions(filters).replace("and cost_center in %(cost_center)s ", ''))
|
||||
|
||||
gl_entries = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
name as gl_entry, posting_date, account, party_type, party,
|
||||
voucher_type, voucher_no, cost_center, project,
|
||||
against_voucher_type, against_voucher, account_currency,
|
||||
remarks, against, is_opening {select_fields}
|
||||
remarks, against, is_opening, creation {select_fields}
|
||||
from `tabGL Entry`
|
||||
where company=%(company)s {conditions}
|
||||
{distributed_cost_center_query}
|
||||
{order_by_statement}
|
||||
""".format(
|
||||
select_fields=select_fields, conditions=get_conditions(filters),
|
||||
select_fields=select_fields, conditions=get_conditions(filters), distributed_cost_center_query=distributed_cost_center_query,
|
||||
order_by_statement=order_by_statement
|
||||
),
|
||||
filters, as_dict=1)
|
||||
@ -296,7 +331,7 @@ def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||
data[key].debit_in_account_currency += flt(gle.debit_in_account_currency)
|
||||
data[key].credit_in_account_currency += flt(gle.credit_in_account_currency)
|
||||
|
||||
if data[key].against_voucher:
|
||||
if data[key].against_voucher and gle.against_voucher:
|
||||
data[key].against_voucher += ', ' + gle.against_voucher
|
||||
|
||||
from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
|
||||
|
@ -4,11 +4,18 @@
|
||||
frappe.query_reports["Item-wise Purchase Register"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname":"date_range",
|
||||
"label": __("Date Range"),
|
||||
"fieldtype": "DateRange",
|
||||
"default": [frappe.datetime.add_months(frappe.datetime.get_today(),-1), frappe.datetime.get_today()],
|
||||
"reqd": 1
|
||||
"fieldname":"from_date",
|
||||
"label": __("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
|
||||
"reqd": 1,
|
||||
},
|
||||
{
|
||||
"fieldname":"to_date",
|
||||
"label": __("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today(),
|
||||
"reqd": 1,
|
||||
},
|
||||
{
|
||||
"fieldname": "item_code",
|
||||
|
@ -14,7 +14,6 @@ def execute(filters=None):
|
||||
|
||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
||||
if not filters: filters = {}
|
||||
filters.update({"from_date": filters.get("date_range")[0], "to_date": filters.get("date_range")[1]})
|
||||
columns = get_columns(additional_table_columns, filters)
|
||||
|
||||
company_currency = erpnext.get_company_currency(filters.company)
|
||||
@ -266,13 +265,6 @@ def get_columns(additional_table_columns, filters):
|
||||
'fieldtype': 'Currency',
|
||||
'options': 'currency',
|
||||
'width': 100
|
||||
},
|
||||
{
|
||||
'fieldname': 'currency',
|
||||
'label': _('Currency'),
|
||||
'fieldtype': 'Currency',
|
||||
'width': 80,
|
||||
'hidden': 1
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -4,11 +4,18 @@
|
||||
frappe.query_reports["Item-wise Sales Register"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname": "date_range",
|
||||
"label": __("Date Range"),
|
||||
"fieldtype": "DateRange",
|
||||
"default": [frappe.datetime.add_months(frappe.datetime.get_today(),-1), frappe.datetime.get_today()],
|
||||
"reqd": 1
|
||||
"fieldname":"from_date",
|
||||
"label": __("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
|
||||
"reqd": 1,
|
||||
},
|
||||
{
|
||||
"fieldname":"to_date",
|
||||
"label": __("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today(),
|
||||
"reqd": 1,
|
||||
},
|
||||
{
|
||||
"fieldname": "customer",
|
||||
|
@ -14,7 +14,6 @@ def execute(filters=None):
|
||||
|
||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
||||
if not filters: filters = {}
|
||||
filters.update({"from_date": filters.get("date_range") and filters.get("date_range")[0], "to_date": filters.get("date_range") and filters.get("date_range")[1]})
|
||||
columns = get_columns(additional_table_columns, filters)
|
||||
|
||||
company_currency = frappe.get_cached_value('Company', filters.get("company"), "default_currency")
|
||||
@ -224,7 +223,7 @@ def get_columns(additional_table_columns, filters):
|
||||
}
|
||||
]
|
||||
|
||||
if filters.get('group_by') != 'Terriotory':
|
||||
if filters.get('group_by') != 'Territory':
|
||||
columns.extend([
|
||||
{
|
||||
'label': _("Territory"),
|
||||
@ -305,13 +304,6 @@ def get_columns(additional_table_columns, filters):
|
||||
'fieldtype': 'Currency',
|
||||
'options': 'currency',
|
||||
'width': 100
|
||||
},
|
||||
{
|
||||
'fieldname': 'currency',
|
||||
'label': _('Currency'),
|
||||
'fieldtype': 'Currency',
|
||||
'width': 80,
|
||||
'hidden': 1
|
||||
}
|
||||
]
|
||||
|
||||
@ -537,6 +529,13 @@ def get_tax_accounts(item_list, columns, company_currency,
|
||||
'fieldtype': 'Currency',
|
||||
'options': 'currency',
|
||||
'width': 100
|
||||
},
|
||||
{
|
||||
'fieldname': 'currency',
|
||||
'label': _('Currency'),
|
||||
'fieldtype': 'Currency',
|
||||
'width': 80,
|
||||
'hidden': 1
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -1,27 +0,0 @@
|
||||
{
|
||||
"add_total_row": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-02-21 14:26:44",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 3,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2017-11-06 13:04:51.559061",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Ordered Items To Be Billed",
|
||||
"owner": "Administrator",
|
||||
"query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`customer_name` as \"Customer Name:150\",\n`tabSales Order`.`status` as \"Status\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.base_amount as \"Amount:Currency:110\",\n (`tabSales Order Item`.billed_amt * ifnull(`tabSales Order`.conversion_rate, 1)) as \"Billed Amount:Currency:110\",\n (`tabSales Order Item`.base_amount - (`tabSales Order Item`.billed_amt * ifnull(`tabSales Order`.conversion_rate, 1))) as \"Pending Amount:Currency:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order`.`company` as \"Company:Link/Company:\"\nfrom\n `tabSales Order`, `tabSales Order Item`\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status != \"Closed\"\n and `tabSales Order Item`.amount > 0\n and `tabSales Order Item`.billed_amt < `tabSales Order Item`.amount\norder by `tabSales Order`.transaction_date asc",
|
||||
"ref_doctype": "Sales Invoice",
|
||||
"report_name": "Ordered Items To Be Billed",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Accounts Manager"
|
||||
},
|
||||
{
|
||||
"role": "Accounts User"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
|
||||
|
||||
def execute(filters=None):
|
||||
columns = get_column()
|
||||
args = get_args()
|
||||
data = get_ordered_to_be_billed_data(args)
|
||||
return columns, data
|
||||
|
||||
def get_column():
|
||||
return [
|
||||
_("Sales Order") + ":Link/Sales Order:120", _("Status") + "::120", _("Date") + ":Date:100",
|
||||
_("Suplier") + ":Link/Customer:120", _("Customer Name") + "::120",
|
||||
_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
|
||||
_("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Pending Amount") + ":Currency:100",
|
||||
_("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120",
|
||||
]
|
||||
|
||||
def get_args():
|
||||
return {'doctype': 'Sales Order', 'party': 'customer',
|
||||
'date': 'transaction_date', 'order': 'transaction_date', 'order_by': 'asc'}
|
@ -6,6 +6,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
frappe.query_reports["Profit and Loss Statement"] = $.extend({},
|
||||
erpnext.financial_statements);
|
||||
|
||||
erpnext.utils.add_dimensions('Profit and Loss Statement', 10);
|
||||
|
||||
frappe.query_reports["Profit and Loss Statement"]["filters"].push(
|
||||
{
|
||||
"fieldname": "project",
|
||||
|
@ -105,6 +105,7 @@ def accumulate_values_into_parents(accounts, accounts_by_name):
|
||||
|
||||
def prepare_data(accounts, filters, total_row, parent_children_map, based_on):
|
||||
data = []
|
||||
new_accounts = accounts
|
||||
company_currency = frappe.get_cached_value('Company', filters.get("company"), "default_currency")
|
||||
|
||||
for d in accounts:
|
||||
@ -118,6 +119,19 @@ def prepare_data(accounts, filters, total_row, parent_children_map, based_on):
|
||||
"currency": company_currency,
|
||||
"based_on": based_on
|
||||
}
|
||||
if based_on == 'cost_center':
|
||||
cost_center_doc = frappe.get_doc("Cost Center",d.name)
|
||||
if not cost_center_doc.enable_distributed_cost_center:
|
||||
DCC_allocation = frappe.db.sql("""SELECT parent, sum(percentage_allocation) as percentage_allocation
|
||||
FROM `tabDistributed Cost Center`
|
||||
WHERE cost_center IN %(cost_center)s
|
||||
AND parent NOT IN %(cost_center)s
|
||||
GROUP BY parent""",{'cost_center': [d.name]})
|
||||
if DCC_allocation:
|
||||
for account in new_accounts:
|
||||
if account['name'] == DCC_allocation[0][0]:
|
||||
for value in value_fields:
|
||||
d[value] += account[value]*(DCC_allocation[0][1]/100)
|
||||
|
||||
for key in value_fields:
|
||||
row[key] = flt(d.get(key, 0.0), 3)
|
||||
|
@ -1,8 +0,0 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.query_reports["Purchase Order Items To Be Billed"] = {
|
||||
"filters": [
|
||||
|
||||
]
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
{
|
||||
"add_total_row": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-05-28 15:54:16",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 3,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2017-02-24 20:00:24.302988",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Order Items To Be Billed",
|
||||
"owner": "Administrator",
|
||||
"query": "select \n `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n `tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order`.`supplier_name` as \"Supplier Name::150\",\n\t`tabPurchase Order Item`.`project` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.base_amount as \"Amount:Currency:100\",\n\t(`tabPurchase Order Item`.billed_amt * ifnull(`tabPurchase Order`.conversion_rate, 1)) as \"Billed Amount:Currency:100\", \n\t(`tabPurchase Order Item`.base_amount - (`tabPurchase Order Item`.billed_amt * ifnull(`tabPurchase Order`.conversion_rate, 1))) as \"Amount to Bill:Currency:100\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\",\n\t`tabPurchase Order`.company as \"Company:Link/Company:\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status != \"Closed\"\n and `tabPurchase Order Item`.amount > 0\n\tand (`tabPurchase Order Item`.billed_amt * ifnull(`tabPurchase Order`.conversion_rate, 1)) < `tabPurchase Order Item`.base_amount\norder by `tabPurchase Order`.transaction_date asc",
|
||||
"ref_doctype": "Purchase Invoice",
|
||||
"report_name": "Purchase Order Items To Be Billed",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Accounts User"
|
||||
},
|
||||
{
|
||||
"role": "Purchase User"
|
||||
},
|
||||
{
|
||||
"role": "Auditor"
|
||||
},
|
||||
{
|
||||
"role": "Accounts Manager"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
|
||||
|
||||
def execute(filters=None):
|
||||
columns = get_column()
|
||||
args = get_args()
|
||||
data = get_ordered_to_be_billed_data(args)
|
||||
return columns, data
|
||||
|
||||
def get_column():
|
||||
return [
|
||||
_("Purchase Order") + ":Link/Purchase Order:120", _("Status") + "::120", _("Date") + ":Date:100",
|
||||
_("Suplier") + ":Link/Supplier:120", _("Suplier Name") + "::120",
|
||||
_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
|
||||
_("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Amount to Bill") + ":Currency:100",
|
||||
_("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120",
|
||||
]
|
||||
|
||||
def get_args():
|
||||
return {'doctype': 'Purchase Order', 'party': 'supplier',
|
||||
'date': 'transaction_date', 'order': 'transaction_date', 'order_by': 'asc'}
|
@ -56,11 +56,4 @@ frappe.query_reports["Purchase Register"] = {
|
||||
]
|
||||
}
|
||||
|
||||
erpnext.dimension_filters.forEach((dimension) => {
|
||||
frappe.query_reports["Purchase Register"].filters.splice(7, 0 ,{
|
||||
"fieldname": dimension["fieldname"],
|
||||
"label": __(dimension["label"]),
|
||||
"fieldtype": "Link",
|
||||
"options": dimension["document_type"]
|
||||
});
|
||||
});
|
||||
erpnext.utils.add_dimensions('Purchase Register', 7);
|
@ -68,12 +68,5 @@ frappe.query_reports["Sales Register"] = {
|
||||
]
|
||||
}
|
||||
|
||||
erpnext.dimension_filters.forEach((dimension) => {
|
||||
frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{
|
||||
"fieldname": dimension["fieldname"],
|
||||
"label": __(dimension["label"]),
|
||||
"fieldtype": "Link",
|
||||
"options": dimension["document_type"]
|
||||
});
|
||||
});
|
||||
erpnext.utils.add_dimensions('Sales Register', 7);
|
||||
|
||||
|
@ -111,7 +111,7 @@ def get_gle_map(filters):
|
||||
# {"purchase_invoice": list of dict of all gle created for this invoice}
|
||||
gle_map = {}
|
||||
gle = frappe.db.get_all('GL Entry',\
|
||||
{"voucher_no": ["in", [d.get("name") for d in filters["invoices"]]]},
|
||||
{"voucher_no": ["in", [d.get("name") for d in filters["invoices"]]], 'is_cancelled': 0},
|
||||
["fiscal_year", "credit", "debit", "account", "voucher_no", "posting_date"])
|
||||
|
||||
for d in gle:
|
||||
|
@ -102,14 +102,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
"initial_depth": 3
|
||||
}
|
||||
|
||||
erpnext.dimension_filters.forEach((dimension) => {
|
||||
frappe.query_reports["Trial Balance"].filters.splice(6, 0 ,{
|
||||
"fieldname": dimension["fieldname"],
|
||||
"label": __(dimension["label"]),
|
||||
"fieldtype": "Link",
|
||||
"options": dimension["document_type"]
|
||||
});
|
||||
});
|
||||
erpnext.utils.add_dimensions('Trial Balance', 6);
|
||||
});
|
||||
|
||||
|
||||
|
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