Merge branch 'develop' of https://github.com/frappe/erpnext into inactive_items
This commit is contained in:
commit
cab2d82ea8
@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '11.1.17'
|
||||
__version__ = '11.1.20'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
@ -1,5 +1,7 @@
|
||||
frappe.dashboard_chart_sources["Account Balance Timeline"] = {
|
||||
method_path: "erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get",
|
||||
frappe.provide('frappe.dashboards.chart_sources');
|
||||
|
||||
frappe.dashboards.chart_sources["Account Balance Timeline"] = {
|
||||
method: "erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get",
|
||||
filters: [
|
||||
{
|
||||
fieldname: "company",
|
||||
@ -16,30 +18,5 @@ frappe.dashboard_chart_sources["Account Balance Timeline"] = {
|
||||
options: "Account",
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: "timespan",
|
||||
label: __("Period"),
|
||||
fieldtype: "Select",
|
||||
options: [
|
||||
{value: "Last Year", label: __("Last Year")},
|
||||
{value: "Last Quarter", label: __("Last Quarter")},
|
||||
{value: "Last Month", label: __("Last Month")},
|
||||
{value: "Last Week", label: __("Last Week")}
|
||||
],
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: "timegrain",
|
||||
label: __("Periodicity"),
|
||||
fieldtype: "Select",
|
||||
options: [
|
||||
{value: "Quarterly", label: __("Quarterly")},
|
||||
{value: "Monthly", label: __("Monthly")},
|
||||
{value: "Weekly", label: __("Weekly")},
|
||||
{value: "Daily", label: __("Daily")}
|
||||
],
|
||||
reqd: 1
|
||||
},
|
||||
],
|
||||
is_time_series: true
|
||||
]
|
||||
};
|
@ -1,13 +1,13 @@
|
||||
{
|
||||
"config": "{\n \"method_path\": \"erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get\",\n\t\"filters\": [\n\t\t{\n\t\t\t\"fieldname\": \"company\",\n\t\t\t\"label\": \"Company\",\n\t\t\t\"fieldtype\": \"Link\",\n\t\t\t\"options\": \"Company\",\n\t\t\t\"reqd\": 1\n\t\t},\n\t\t{\n\t\t\t\"fieldname\": \"account\",\n\t\t\t\"label\": \"Account\",\n\t\t\t\"fieldtype\": \"Link\",\n\t\t\t\"options\": \"Account\",\n\t\t\t\"reqd\": 1\n\t\t},\n\t\t{\n\t\t\t\"fieldname\": \"timespan\",\n\t\t\t\"label\": \"Period\",\n\t\t\t\"fieldtype\": \"Select\",\n\t\t\t\"options\": [\n\t\t\t\t{\"value\": \"Last Year\", \"label\": \"Last Year\"},\n\t\t\t\t{\"value\": \"Last Quarter\", \"label\": \"Last Quarter\"},\n\t\t\t\t{\"value\": \"Last Month\", \"label\": \"Last Month\"},\n\t\t\t\t{\"value\": \"Last Week\", \"label\": \"Last Week\"}\n\t\t\t],\n\t\t\t\"reqd\": 1\n\t\t},\n\t\t{\n\t\t\t\"fieldname\": \"timegrain\",\n\t\t\t\"label\": \"Periodicity\",\n\t\t\t\"fieldtype\": \"Select\",\n\t\t\t\"options\": [\n\t\t\t\t{\"value\": \"Quarterly\", \"label\": \"Quarterly\"},\n\t\t\t\t{\"value\": \"Monthly\", \"label\": \"Monthly\"},\n\t\t\t\t{\"value\": \"Weekly\", \"label\": \"Weekly\"},\n\t\t\t\t{\"value\": \"Daily\", \"label\": \"Daily\"}\n\t\t\t],\n\t\t\t\"reqd\": 1\n\t\t}\n\t],\n\t\"is_time_series\": true\n}\n",
|
||||
"creation": "2019-02-06 07:57:10.377718",
|
||||
"docstatus": 0,
|
||||
"doctype": "Dashboard Chart Source",
|
||||
"idx": 0,
|
||||
"modified": "2019-03-15 16:14:26.505986",
|
||||
"modified": "2019-04-09 18:30:49.943174",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Account Balance Timeline",
|
||||
"owner": "Administrator",
|
||||
"source_name": "Account Balance Timeline"
|
||||
"source_name": "Account Balance Timeline",
|
||||
"timeseries": 1
|
||||
}
|
@ -2,82 +2,88 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from itertools import groupby
|
||||
from operator import itemgetter
|
||||
import frappe
|
||||
from frappe.core.page.dashboard.dashboard import cache_source
|
||||
from frappe.utils import add_to_date, date_diff, getdate, nowdate
|
||||
import frappe, json
|
||||
from frappe.utils import add_to_date, date_diff, getdate, nowdate, get_last_day
|
||||
from erpnext.accounts.report.general_ledger.general_ledger import execute
|
||||
from frappe.core.page.dashboard.dashboard import cache_source, get_from_date_from_timespan
|
||||
from frappe.desk.doctype.dashboard_chart.dashboard_chart import get_period_ending
|
||||
|
||||
from frappe.utils.nestedset import get_descendants_of
|
||||
|
||||
@frappe.whitelist()
|
||||
@cache_source
|
||||
def get(filters=None):
|
||||
timespan = filters.get("timespan")
|
||||
timegrain = filters.get("timegrain")
|
||||
def get(chart_name=None, from_date = None, to_date = None):
|
||||
chart = frappe.get_doc('Dashboard Chart', chart_name)
|
||||
timespan = chart.timespan
|
||||
timegrain = chart.time_interval
|
||||
filters = json.loads(chart.filters_json)
|
||||
|
||||
account = filters.get("account")
|
||||
company = filters.get("company")
|
||||
|
||||
from_date = get_from_date_from_timespan(timespan)
|
||||
to_date = nowdate()
|
||||
filters = frappe._dict({
|
||||
"company": company,
|
||||
"from_date": from_date,
|
||||
"to_date": to_date,
|
||||
"account": account,
|
||||
"group_by": "Group by Voucher (Consolidated)"
|
||||
})
|
||||
report_results = execute(filters=filters)[1]
|
||||
if not to_date:
|
||||
to_date = nowdate()
|
||||
if not from_date:
|
||||
if timegrain in ('Monthly', 'Quarterly'):
|
||||
from_date = get_from_date_from_timespan(to_date, timespan)
|
||||
|
||||
interesting_fields = ["posting_date", "balance"]
|
||||
# fetch dates to plot
|
||||
dates = get_dates_from_timegrain(from_date, to_date, timegrain)
|
||||
|
||||
_results = []
|
||||
for row in report_results[1:-2]:
|
||||
_results.append([row[key] for key in interesting_fields])
|
||||
# get all the entries for this account and its descendants
|
||||
gl_entries = get_gl_entries(account, get_period_ending(to_date, timegrain))
|
||||
|
||||
_results = add_opening_balance(from_date, _results, report_results[0])
|
||||
grouped_results = groupby(_results, key=itemgetter(0))
|
||||
results = [list(values)[-1] for key, values in grouped_results]
|
||||
results = add_missing_dates(results, from_date, to_date)
|
||||
results = granulate_results(results, from_date, to_date, timegrain)
|
||||
# compile balance values
|
||||
result = build_result(account, dates, gl_entries)
|
||||
|
||||
return {
|
||||
"labels": [result[0] for result in results],
|
||||
"labels": [r[0].strftime('%Y-%m-%d') for r in result],
|
||||
"datasets": [{
|
||||
"name": account,
|
||||
"values": [result[1] for result in results]
|
||||
"values": [r[1] for r in result]
|
||||
}]
|
||||
}
|
||||
|
||||
def get_from_date_from_timespan(timespan):
|
||||
days = months = years = 0
|
||||
if "Last Week" == timespan:
|
||||
days = -7
|
||||
if "Last Month" == timespan:
|
||||
months = -1
|
||||
elif "Last Quarter" == timespan:
|
||||
months = -3
|
||||
elif "Last Year" == timespan:
|
||||
years = -1
|
||||
return add_to_date(None, years=years, months=months, days=days,
|
||||
as_string=True, as_datetime=True)
|
||||
def build_result(account, dates, gl_entries):
|
||||
result = [[getdate(date), 0.0] for date in dates]
|
||||
root_type = frappe.db.get_value('Account', account, 'root_type')
|
||||
|
||||
# start with the first date
|
||||
date_index = 0
|
||||
|
||||
def add_opening_balance(from_date, _results, opening):
|
||||
if not _results or (_results[0][0] != getdate(from_date)):
|
||||
_results.insert(0, [from_date, opening.balance])
|
||||
return _results
|
||||
# get balances in debit
|
||||
for entry in gl_entries:
|
||||
|
||||
def add_missing_dates(incomplete_results, from_date, to_date):
|
||||
day_count = date_diff(to_date, from_date)
|
||||
# entry date is after the current pointer, so move the pointer forward
|
||||
while getdate(entry.posting_date) > result[date_index][0]:
|
||||
date_index += 1
|
||||
|
||||
results_dict = dict(incomplete_results)
|
||||
last_balance = incomplete_results[0][1]
|
||||
results = []
|
||||
for date in (add_to_date(getdate(from_date), days=n) for n in range(day_count + 1)):
|
||||
if date in results_dict:
|
||||
last_balance = results_dict[date]
|
||||
results.append([date, last_balance])
|
||||
return results
|
||||
result[date_index][1] += entry.debit - entry.credit
|
||||
|
||||
# if account type is credit, switch balances
|
||||
if root_type not in ('Asset', 'Expense'):
|
||||
for r in result:
|
||||
r[1] = -1 * r[1]
|
||||
|
||||
# for balance sheet accounts, the totals are cumulative
|
||||
if root_type in ('Asset', 'Liability', 'Equity'):
|
||||
for i, r in enumerate(result):
|
||||
if i > 0:
|
||||
r[1] = r[1] + result[i-1][1]
|
||||
|
||||
return result
|
||||
|
||||
def get_gl_entries(account, to_date):
|
||||
child_accounts = get_descendants_of('Account', account, ignore_permissions=True)
|
||||
child_accounts.append(account)
|
||||
|
||||
return frappe.db.get_all('GL Entry',
|
||||
fields = ['posting_date', 'debit', 'credit'],
|
||||
filters = [
|
||||
dict(posting_date = ('<', to_date)),
|
||||
dict(account = ('in', child_accounts))
|
||||
],
|
||||
order_by = 'posting_date asc')
|
||||
|
||||
def get_dates_from_timegrain(from_date, to_date, timegrain):
|
||||
days = months = years = 0
|
||||
@ -90,11 +96,8 @@ def get_dates_from_timegrain(from_date, to_date, timegrain):
|
||||
elif "Quarterly" == timegrain:
|
||||
months = 3
|
||||
|
||||
dates = [from_date]
|
||||
while dates[-1] <= to_date:
|
||||
dates.append(add_to_date(dates[-1], years=years, months=months, days=days))
|
||||
dates = [get_period_ending(from_date, timegrain)]
|
||||
while getdate(dates[-1]) < getdate(to_date):
|
||||
date = get_period_ending(add_to_date(dates[-1], years=years, months=months, days=days), timegrain)
|
||||
dates.append(date)
|
||||
return dates
|
||||
|
||||
def granulate_results(incomplete_results, from_date, to_date, timegrain):
|
||||
dates = set(get_dates_from_timegrain(getdate(from_date), getdate(to_date), timegrain))
|
||||
return list(filter(lambda x: x[0] in dates,incomplete_results))
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 1,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
@ -13,11 +14,14 @@
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Select account head of the bank where cheque was deposited.",
|
||||
"fetch_from": "bank_account_no.account",
|
||||
"fetch_if_empty": 1,
|
||||
"fieldname": "bank_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -40,14 +44,17 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "account_currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
@ -70,14 +77,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "from_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@ -99,14 +109,17 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "to_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@ -128,14 +141,83 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_5",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "bank_account_no",
|
||||
"fieldtype": "Link",
|
||||
"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": "Bank Account No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "include_reconciled_entries",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@ -157,14 +239,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "include_pos_transactions",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@ -187,14 +272,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "get_payment_entries",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
@ -217,14 +305,49 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 1,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 1,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "payment_entries",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@ -247,14 +370,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "update_clearance_date",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
@ -277,14 +403,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@ -307,22 +436,21 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 1,
|
||||
"hide_toolbar": 1,
|
||||
"icon": "fa fa-check",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2018-03-07 18:58:48.658687",
|
||||
"modified": "2019-04-09 18:41:06.110453",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Reconciliation",
|
||||
@ -330,7 +458,6 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
@ -351,9 +478,9 @@
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 1,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -19,8 +19,11 @@ class BankReconciliation(Document):
|
||||
|
||||
condition = ""
|
||||
if not self.include_reconciled_entries:
|
||||
condition = "and (clearance_date is null or clearance_date='0000-00-00')"
|
||||
condition = " and (clearance_date is null or clearance_date='0000-00-00')"
|
||||
|
||||
account_cond = ""
|
||||
if self.bank_account_no:
|
||||
account_cond = " and t2.bank_account_no = {0}".format(frappe.db.escape(self.bank_account_no))
|
||||
|
||||
journal_entries = frappe.db.sql("""
|
||||
select
|
||||
@ -33,10 +36,13 @@ class BankReconciliation(Document):
|
||||
where
|
||||
t2.parent = t1.name and t2.account = %s and t1.docstatus=1
|
||||
and t1.posting_date >= %s and t1.posting_date <= %s
|
||||
and ifnull(t1.is_opening, 'No') = 'No' {0}
|
||||
and ifnull(t1.is_opening, 'No') = 'No' {0} {1}
|
||||
group by t2.account, t1.name
|
||||
order by t1.posting_date ASC, t1.name DESC
|
||||
""".format(condition), (self.bank_account, self.from_date, self.to_date), as_dict=1)
|
||||
""".format(condition, account_cond), (self.bank_account, self.from_date, self.to_date), as_dict=1)
|
||||
|
||||
if self.bank_account_no:
|
||||
condition = " and bank_account = %(bank_account_no)s"
|
||||
|
||||
payment_entries = frappe.db.sql("""
|
||||
select
|
||||
@ -53,7 +59,8 @@ class BankReconciliation(Document):
|
||||
order by
|
||||
posting_date ASC, name DESC
|
||||
""".format(condition),
|
||||
{"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1)
|
||||
{"account":self.bank_account, "from":self.from_date,
|
||||
"to":self.to_date, "bank_account_no": self.bank_account_no}, as_dict=1)
|
||||
|
||||
pos_entries = []
|
||||
if self.include_pos_transactions:
|
||||
|
@ -0,0 +1,177 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2019-03-07 12:07:09.416101",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sales_invoice",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Invoice",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Invoice",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "sales_invoice.customer",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Customer",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "sales_invoice.posting_date",
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "sales_invoice.grand_total",
|
||||
"fieldname": "outstanding_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Outstanding Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-07 16:38:03.622666",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Discounted Invoice",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class DiscountedInvoice(Document):
|
||||
pass
|
@ -7,6 +7,7 @@ from frappe import _
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.naming import set_name_from_naming_options
|
||||
from frappe.model.meta import get_field_precision
|
||||
from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
@ -63,7 +64,7 @@ class GLEntry(Document):
|
||||
.format(self.voucher_type, self.voucher_no, self.account))
|
||||
|
||||
# Zero value transaction is not allowed
|
||||
if not (flt(self.debit) or flt(self.credit)):
|
||||
if not (flt(self.debit, self.precision("debit")) or flt(self.credit, self.precision("credit"))):
|
||||
frappe.throw(_("{0} {1}: Either debit or credit amount is required for {2}")
|
||||
.format(self.voucher_type, self.voucher_no, self.account))
|
||||
|
||||
@ -174,13 +175,20 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
|
||||
else:
|
||||
party_condition = ""
|
||||
|
||||
if against_voucher_type == "Sales Invoice":
|
||||
party_account = frappe.db.get_value(against_voucher_type, against_voucher, "debit_to")
|
||||
account_condition = "and account in ({0}, {1})".format(frappe.db.escape(account), frappe.db.escape(party_account))
|
||||
else:
|
||||
account_condition = " and account = {0}".format(frappe.db.escape(account))
|
||||
|
||||
# get final outstanding amt
|
||||
bal = flt(frappe.db.sql("""
|
||||
select sum(debit_in_account_currency) - sum(credit_in_account_currency)
|
||||
from `tabGL Entry`
|
||||
where against_voucher_type=%s and against_voucher=%s
|
||||
and account = %s {0}""".format(party_condition),
|
||||
(against_voucher_type, against_voucher, account))[0][0] or 0.0)
|
||||
and voucher_type != 'Invoice Discounting'
|
||||
{0} {1}""".format(party_condition, account_condition),
|
||||
(against_voucher_type, against_voucher))[0][0] or 0.0)
|
||||
|
||||
if against_voucher_type == 'Purchase Invoice':
|
||||
bal = -bal
|
||||
@ -223,17 +231,23 @@ def validate_frozen_account(account, adv_adj=None):
|
||||
def update_against_account(voucher_type, voucher_no):
|
||||
entries = frappe.db.get_all("GL Entry",
|
||||
filters={"voucher_type": voucher_type, "voucher_no": voucher_no},
|
||||
fields=["name", "party", "against", "debit", "credit", "account"])
|
||||
fields=["name", "party", "against", "debit", "credit", "account", "company"])
|
||||
|
||||
if not entries:
|
||||
return
|
||||
company_currency = erpnext.get_company_currency(entries[0].company)
|
||||
precision = get_field_precision(frappe.get_meta("GL Entry")
|
||||
.get_field("debit"), company_currency)
|
||||
|
||||
accounts_debited, accounts_credited = [], []
|
||||
for d in entries:
|
||||
if flt(d.debit > 0): accounts_debited.append(d.party or d.account)
|
||||
if flt(d.credit) > 0: accounts_credited.append(d.party or d.account)
|
||||
if flt(d.debit, precision) > 0: accounts_debited.append(d.party or d.account)
|
||||
if flt(d.credit, precision) > 0: accounts_credited.append(d.party or d.account)
|
||||
|
||||
for d in entries:
|
||||
if flt(d.debit > 0):
|
||||
if flt(d.debit, precision) > 0:
|
||||
new_against = ", ".join(list(set(accounts_credited)))
|
||||
if flt(d.credit > 0):
|
||||
if flt(d.credit, precision) > 0:
|
||||
new_against = ", ".join(list(set(accounts_debited)))
|
||||
|
||||
if d.against != new_against:
|
||||
|
@ -0,0 +1,197 @@
|
||||
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Invoice Discounting', {
|
||||
setup: (frm) => {
|
||||
frm.set_query("sales_invoice", "invoices", (doc) => {
|
||||
return {
|
||||
"filters": {
|
||||
"docstatus": 1,
|
||||
"company": doc.company,
|
||||
"outstanding_amount": [">", 0]
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.events.filter_accounts("bank_account", frm, {"account_type": "Bank"});
|
||||
frm.events.filter_accounts("bank_charges_account", frm, {"root_type": "Expense"});
|
||||
frm.events.filter_accounts("short_term_loan", frm, {"root_type": "Liability"});
|
||||
frm.events.filter_accounts("accounts_receivable_credit", frm, {"account_type": "Receivable"});
|
||||
frm.events.filter_accounts("accounts_receivable_discounted", frm, {"account_type": "Receivable"});
|
||||
frm.events.filter_accounts("accounts_receivable_unpaid", frm, {"account_type": "Receivable"});
|
||||
|
||||
},
|
||||
|
||||
filter_accounts: (fieldname, frm, addl_filters) => {
|
||||
let filters = {
|
||||
"company": frm.doc.company,
|
||||
"is_group": 0
|
||||
};
|
||||
if(addl_filters) Object.assign(filters, addl_filters);
|
||||
|
||||
frm.set_query(fieldname, () => { return { "filters": filters }; });
|
||||
},
|
||||
|
||||
refresh: (frm) => {
|
||||
frm.events.show_general_ledger(frm);
|
||||
|
||||
if(frm.doc.docstatus === 0) {
|
||||
frm.add_custom_button(__('Get Invoices'), function() {
|
||||
frm.events.get_invoices(frm);
|
||||
});
|
||||
}
|
||||
|
||||
if(frm.doc.docstatus === 1 && frm.doc.status !== "Settled") {
|
||||
if(frm.doc.status == "Sanctioned") {
|
||||
frm.add_custom_button(__('Disburse Loan'), function() {
|
||||
frm.events.create_disbursement_entry(frm);
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
if(frm.doc.status == "Disbursed") {
|
||||
frm.add_custom_button(__('Close Loan'), function() {
|
||||
frm.events.close_loan(frm);
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
loan_start_date: (frm) => {
|
||||
frm.events.set_end_date(frm);
|
||||
},
|
||||
|
||||
loan_period: (frm) => {
|
||||
frm.events.set_end_date(frm);
|
||||
},
|
||||
|
||||
set_end_date: (frm) => {
|
||||
if(frm.doc.loan_start_date && frm.doc.loan_period) {
|
||||
let end_date = frappe.datetime.add_days(frm.doc.loan_start_date, frm.doc.loan_period);
|
||||
frm.set_value("loan_end_date", end_date);
|
||||
}
|
||||
},
|
||||
|
||||
validate: (frm) => {
|
||||
frm.events.calculate_total_amount(frm);
|
||||
},
|
||||
|
||||
calculate_total_amount: (frm) => {
|
||||
let total_amount = 0.0;
|
||||
for (let row of (frm.doc.invoices || [])) {
|
||||
total_amount += flt(row.outstanding_amount);
|
||||
}
|
||||
frm.set_value("total_amount", total_amount);
|
||||
},
|
||||
|
||||
get_invoices: (frm) => {
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __('Get Invoices based on Filters'),
|
||||
fields: [
|
||||
{
|
||||
"label": "Customer",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"options": "Customer"
|
||||
},
|
||||
{
|
||||
"label": "From Date",
|
||||
"fieldname": "from_date",
|
||||
"fieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"label": "To Date",
|
||||
"fieldname": "to_date",
|
||||
"fieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break",
|
||||
"fieldtype": "Column Break",
|
||||
},
|
||||
{
|
||||
"label": "Min Amount",
|
||||
"fieldname": "min_amount",
|
||||
"fieldtype": "Currency"
|
||||
},
|
||||
{
|
||||
"label": "Max Amount",
|
||||
"fieldname": "max_amount",
|
||||
"fieldtype": "Currency"
|
||||
}
|
||||
],
|
||||
primary_action: function() {
|
||||
var data = d.get_values();
|
||||
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.invoice_discounting.invoice_discounting.get_invoices",
|
||||
args: {
|
||||
filters: data
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
d.hide();
|
||||
$.each(r.message, function(i, v) {
|
||||
frm.doc.invoices = frm.doc.invoices.filter(row => row.sales_invoice);
|
||||
let row = frm.add_child("invoices");
|
||||
$.extend(row, v);
|
||||
});
|
||||
refresh_field("invoices");
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
primary_action_label: __('Get Invocies')
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
|
||||
create_disbursement_entry: (frm) => {
|
||||
frappe.call({
|
||||
method:"create_disbursement_entry",
|
||||
doc: frm.doc,
|
||||
callback: function(r) {
|
||||
if(!r.exc){
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
close_loan: (frm) => {
|
||||
frappe.call({
|
||||
method:"close_loan",
|
||||
doc: frm.doc,
|
||||
callback: function(r) {
|
||||
if(!r.exc){
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
show_general_ledger: (frm) => {
|
||||
if(frm.doc.docstatus===1) {
|
||||
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,
|
||||
company: frm.doc.company,
|
||||
group_by: "Group by Voucher (Consolidated)"
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, __("View"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Discounted Invoice', {
|
||||
sales_invoice: (frm) => {
|
||||
frm.events.calculate_total_amount(frm);
|
||||
},
|
||||
invoices_remove: (frm) => {
|
||||
frm.events.calculate_total_amount(frm);
|
||||
}
|
||||
});
|
@ -0,0 +1,773 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "ACC-INV-DISC-.YYYY.-.#####",
|
||||
"beta": 0,
|
||||
"creation": "2019-03-07 12:01:56.296952",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Posting Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "loan_start_date",
|
||||
"fieldtype": "Date",
|
||||
"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": "Loan Start Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "loan_period",
|
||||
"fieldtype": "Int",
|
||||
"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": "Loan Period",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "loan_end_date",
|
||||
"fieldtype": "Date",
|
||||
"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": "Loan End Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"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": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Draft\nSanctioned\nDisbursed\nSettled\nCancelled",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoices",
|
||||
"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": "Invoices",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Discounted Invoice",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_7",
|
||||
"fieldtype": "Section Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_amount",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Total Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bank_charges",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Bank Charges",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "short_term_loan",
|
||||
"fieldtype": "Link",
|
||||
"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": "Short Term Loan Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bank_account",
|
||||
"fieldtype": "Link",
|
||||
"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": "Bank Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bank_charges_account",
|
||||
"fieldtype": "Link",
|
||||
"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": "Bank Charges Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_15",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "accounts_receivable_credit",
|
||||
"fieldtype": "Link",
|
||||
"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": "Accounts Receivable Credit Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "accounts_receivable_discounted",
|
||||
"fieldtype": "Link",
|
||||
"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": "Accounts Receivable Discounted Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "accounts_receivable_unpaid",
|
||||
"fieldtype": "Link",
|
||||
"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": "Accounts Receivable Unpaid Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"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": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Invoice Discounting",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-08 14:24:31.222027",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Invoice Discounting",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
from frappe import _
|
||||
from frappe.utils import flt, getdate, nowdate, add_days
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
|
||||
class InvoiceDiscounting(AccountsController):
|
||||
def validate(self):
|
||||
self.validate_mandatory()
|
||||
self.calculate_total_amount()
|
||||
self.set_status()
|
||||
self.set_end_date()
|
||||
|
||||
def set_end_date(self):
|
||||
if self.loan_start_date and self.loan_period:
|
||||
self.loan_end_date = add_days(self.loan_start_date, self.loan_period)
|
||||
|
||||
def validate_mandatory(self):
|
||||
if self.docstatus == 1 and not (self.loan_start_date and self.loan_period):
|
||||
frappe.throw(_("Loan Start Date and Loan Period are mandatory to save the Invoice Discounting"))
|
||||
|
||||
def calculate_total_amount(self):
|
||||
self.total_amount = sum([flt(d.outstanding_amount) for d in self.invoices])
|
||||
|
||||
def on_submit(self):
|
||||
self.make_gl_entries()
|
||||
|
||||
def on_cancel(self):
|
||||
self.set_status()
|
||||
self.make_gl_entries()
|
||||
|
||||
def set_status(self):
|
||||
self.status = "Draft"
|
||||
if self.docstatus == 1:
|
||||
self.status = "Sanctioned"
|
||||
elif self.docstatus == 2:
|
||||
self.status = "Cancelled"
|
||||
|
||||
def make_gl_entries(self):
|
||||
company_currency = frappe.get_cached_value('Company', self.company, "default_currency")
|
||||
|
||||
gl_entries = []
|
||||
for d in self.invoices:
|
||||
inv = frappe.db.get_value("Sales Invoice", d.sales_invoice,
|
||||
["debit_to", "party_account_currency", "conversion_rate", "cost_center"], as_dict=1)
|
||||
|
||||
if d.outstanding_amount:
|
||||
outstanding_in_company_currency = flt(d.outstanding_amount * inv.conversion_rate,
|
||||
d.precision("outstanding_amount"))
|
||||
ar_credit_account_currency = frappe.get_cached_value("Account", self.accounts_receivable_credit, "currency")
|
||||
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": inv.debit_to,
|
||||
"party_type": "Customer",
|
||||
"party": d.customer,
|
||||
"against": self.accounts_receivable_credit,
|
||||
"credit": outstanding_in_company_currency,
|
||||
"credit_in_account_currency": outstanding_in_company_currency \
|
||||
if inv.party_account_currency==company_currency else d.outstanding_amount,
|
||||
"cost_center": inv.cost_center,
|
||||
"against_voucher": d.sales_invoice,
|
||||
"against_voucher_type": "Sales Invoice"
|
||||
}, inv.party_account_currency))
|
||||
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": self.accounts_receivable_credit,
|
||||
"party_type": "Customer",
|
||||
"party": d.customer,
|
||||
"against": inv.debit_to,
|
||||
"debit": outstanding_in_company_currency,
|
||||
"debit_in_account_currency": outstanding_in_company_currency \
|
||||
if ar_credit_account_currency==company_currency else d.outstanding_amount,
|
||||
"cost_center": inv.cost_center,
|
||||
"against_voucher": d.sales_invoice,
|
||||
"against_voucher_type": "Sales Invoice"
|
||||
}, ar_credit_account_currency))
|
||||
|
||||
make_gl_entries(gl_entries, cancel=(self.docstatus == 2), update_outstanding='No')
|
||||
|
||||
def create_disbursement_entry(self):
|
||||
je = frappe.new_doc("Journal Entry")
|
||||
je.voucher_type = 'Journal Entry'
|
||||
je.company = self.company
|
||||
je.remark = 'Loan Disbursement entry against Invoice Discounting: ' + self.name
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.bank_account,
|
||||
"debit_in_account_currency": flt(self.total_amount) - flt(self.bank_charges),
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.bank_charges_account,
|
||||
"debit_in_account_currency": flt(self.bank_charges)
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.short_term_loan,
|
||||
"credit_in_account_currency": flt(self.total_amount),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name
|
||||
})
|
||||
for d in self.invoices:
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_discounted,
|
||||
"debit_in_account_currency": flt(d.outstanding_amount),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
"party": d.customer
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_credit,
|
||||
"credit_in_account_currency": flt(d.outstanding_amount),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
"party": d.customer
|
||||
})
|
||||
|
||||
return je
|
||||
|
||||
def close_loan(self):
|
||||
je = frappe.new_doc("Journal Entry")
|
||||
je.voucher_type = 'Journal Entry'
|
||||
je.company = self.company
|
||||
je.remark = 'Loan Settlement entry against Invoice Discounting: ' + self.name
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.short_term_loan,
|
||||
"debit_in_account_currency": flt(self.total_amount),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.bank_account,
|
||||
"credit_in_account_currency": flt(self.total_amount)
|
||||
})
|
||||
|
||||
if getdate(self.loan_end_date) > getdate(nowdate()):
|
||||
for d in self.invoices:
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_discounted,
|
||||
"credit_in_account_currency": flt(d.outstanding_amount),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
"party": d.customer
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_unpaid,
|
||||
"debit_in_account_currency": flt(d.outstanding_amount),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
"party": d.customer
|
||||
})
|
||||
|
||||
return je
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_invoices(filters):
|
||||
filters = frappe._dict(json.loads(filters))
|
||||
cond = []
|
||||
if filters.customer:
|
||||
cond.append("customer=%(customer)s")
|
||||
if filters.from_date:
|
||||
cond.append("posting_date >= %(from_date)s")
|
||||
if filters.to_date:
|
||||
cond.append("posting_date <= %(to_date)s")
|
||||
if filters.min_amount:
|
||||
cond.append("base_grand_total >= %(min_amount)s")
|
||||
if filters.max_amount:
|
||||
cond.append("base_grand_total <= %(max_amount)s")
|
||||
|
||||
where_condition = ""
|
||||
if cond:
|
||||
where_condition += " and " + " and ".join(cond)
|
||||
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
name as sales_invoice,
|
||||
customer,
|
||||
posting_date,
|
||||
outstanding_amount
|
||||
from `tabSales Invoice`
|
||||
where
|
||||
docstatus = 1
|
||||
and outstanding_amount > 0
|
||||
%s
|
||||
""" % where_condition, filters, as_dict=1)
|
@ -0,0 +1,21 @@
|
||||
frappe.listview_settings['Invoice Discounting'] = {
|
||||
add_fields: ["status"],
|
||||
get_indicator: function(doc)
|
||||
{
|
||||
if(doc.status == "Draft") {
|
||||
return [__("Draft"), "red", "status,=,Draft"];
|
||||
}
|
||||
else if(doc.status == "Sanctioned") {
|
||||
return [__("Sanctioned"), "green", "status,=,Sanctioned"];
|
||||
}
|
||||
else if(doc.status == "Disbursed") {
|
||||
return [__("Disbursed"), "blue", "status,=,Disbursed"];
|
||||
}
|
||||
else if(doc.status == "Settled") {
|
||||
return [__("Settled"), "orange", "status,=,Settled"];
|
||||
}
|
||||
else if(doc.status == "Canceled") {
|
||||
return [__("Canceled"), "red", "status,=,Canceled"];
|
||||
}
|
||||
}
|
||||
};
|
@ -0,0 +1,269 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
from frappe.utils import nowdate, add_days, flt
|
||||
import unittest
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries
|
||||
from erpnext.accounts.doctype.account.test_account import create_account
|
||||
from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry_against_invoice
|
||||
class TestInvoiceDiscounting(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.ar_credit = create_account(account_name="_Test Accounts Receivable Credit", parent_account = "Accounts Receivable - _TC", company="_Test Company")
|
||||
self.ar_discounted = create_account(account_name="_Test Accounts Receivable Discounted", parent_account = "Accounts Receivable - _TC", company="_Test Company")
|
||||
self.ar_unpaid = create_account(account_name="_Test Accounts Receivable Unpaid", parent_account = "Accounts Receivable - _TC", company="_Test Company")
|
||||
self.short_term_loan = create_account(account_name="_Test Short Term Loan", parent_account = "Source of Funds (Liabilities) - _TC", company="_Test Company")
|
||||
self.bank_account = create_account(account_name="_Test Bank 2", parent_account = "Bank Accounts - _TC", company="_Test Company")
|
||||
self.bank_charges_account = create_account(account_name="_Test Bank Charges Account", parent_account = "Expenses - _TC", company="_Test Company")
|
||||
frappe.db.set_value("Company", "_Test Company", "default_bank_account", self.bank_account)
|
||||
|
||||
def test_total_amount(self):
|
||||
inv1 = create_sales_invoice(rate=200)
|
||||
inv2 = create_sales_invoice(rate=500)
|
||||
|
||||
inv_disc = create_invoice_discounting([inv1.name, inv2.name],
|
||||
do_not_submit=True,
|
||||
accounts_receivable_credit=self.ar_credit,
|
||||
accounts_receivable_discounted=self.ar_discounted,
|
||||
accounts_receivable_unpaid=self.ar_unpaid,
|
||||
short_term_loan=self.short_term_loan,
|
||||
bank_charges_account=self.bank_charges_account,
|
||||
bank_account=self.bank_account
|
||||
)
|
||||
self.assertEqual(inv_disc.total_amount, 700)
|
||||
|
||||
def test_gl_entries_in_base_currency(self):
|
||||
inv = create_sales_invoice(rate=200)
|
||||
inv_disc = create_invoice_discounting([inv.name],
|
||||
accounts_receivable_credit=self.ar_credit,
|
||||
accounts_receivable_discounted=self.ar_discounted,
|
||||
accounts_receivable_unpaid=self.ar_unpaid,
|
||||
short_term_loan=self.short_term_loan,
|
||||
bank_charges_account=self.bank_charges_account,
|
||||
bank_account=self.bank_account
|
||||
)
|
||||
|
||||
gle = get_gl_entries("Invoice Discounting", inv_disc.name)
|
||||
|
||||
expected_gle = {
|
||||
inv.debit_to: [0.0, 200],
|
||||
self.ar_credit: [200, 0.0]
|
||||
}
|
||||
for i, gle in enumerate(gle):
|
||||
self.assertEqual([gle.debit, gle.credit], expected_gle.get(gle.account))
|
||||
|
||||
def test_loan_on_submit(self):
|
||||
inv = create_sales_invoice(rate=300)
|
||||
inv_disc = create_invoice_discounting([inv.name],
|
||||
accounts_receivable_credit=self.ar_credit,
|
||||
accounts_receivable_discounted=self.ar_discounted,
|
||||
accounts_receivable_unpaid=self.ar_unpaid,
|
||||
short_term_loan=self.short_term_loan,
|
||||
bank_charges_account=self.bank_charges_account,
|
||||
bank_account=self.bank_account,
|
||||
start=nowdate(),
|
||||
period=60
|
||||
)
|
||||
self.assertEqual(inv_disc.status, "Sanctioned")
|
||||
self.assertEqual(inv_disc.loan_end_date, add_days(inv_disc.loan_start_date, inv_disc.loan_period))
|
||||
|
||||
|
||||
def test_on_disbursed(self):
|
||||
inv = create_sales_invoice(rate=500)
|
||||
inv_disc = create_invoice_discounting([inv.name],
|
||||
accounts_receivable_credit=self.ar_credit,
|
||||
accounts_receivable_discounted=self.ar_discounted,
|
||||
accounts_receivable_unpaid=self.ar_unpaid,
|
||||
short_term_loan=self.short_term_loan,
|
||||
bank_charges_account=self.bank_charges_account,
|
||||
bank_account=self.bank_account,
|
||||
)
|
||||
|
||||
je = inv_disc.create_disbursement_entry()
|
||||
|
||||
self.assertEqual(je.accounts[0].account, self.bank_account)
|
||||
self.assertEqual(je.accounts[0].debit_in_account_currency, flt(inv_disc.total_amount) - flt(inv_disc.bank_charges))
|
||||
|
||||
self.assertEqual(je.accounts[1].account, self.bank_charges_account)
|
||||
self.assertEqual(je.accounts[1].debit_in_account_currency, flt(inv_disc.bank_charges))
|
||||
|
||||
self.assertEqual(je.accounts[2].account, self.short_term_loan)
|
||||
self.assertEqual(je.accounts[2].credit_in_account_currency, flt(inv_disc.total_amount))
|
||||
|
||||
self.assertEqual(je.accounts[3].account, self.ar_discounted)
|
||||
self.assertEqual(je.accounts[3].debit_in_account_currency, flt(inv.outstanding_amount))
|
||||
|
||||
self.assertEqual(je.accounts[4].account, self.ar_credit)
|
||||
self.assertEqual(je.accounts[4].credit_in_account_currency, flt(inv.outstanding_amount))
|
||||
|
||||
|
||||
je.posting_date = nowdate()
|
||||
je.submit()
|
||||
|
||||
inv_disc.reload()
|
||||
self.assertEqual(inv_disc.status, "Disbursed")
|
||||
|
||||
inv.reload()
|
||||
self.assertEqual(inv.outstanding_amount, 500)
|
||||
|
||||
def test_on_close_after_loan_period(self):
|
||||
inv = create_sales_invoice(rate=600)
|
||||
inv_disc = create_invoice_discounting([inv.name],
|
||||
accounts_receivable_credit=self.ar_credit,
|
||||
accounts_receivable_discounted=self.ar_discounted,
|
||||
accounts_receivable_unpaid=self.ar_unpaid,
|
||||
short_term_loan=self.short_term_loan,
|
||||
bank_charges_account=self.bank_charges_account,
|
||||
bank_account=self.bank_account,
|
||||
start=nowdate(),
|
||||
period=60
|
||||
)
|
||||
|
||||
inv_disc.create_disbursement_entry()
|
||||
je = inv_disc.close_loan()
|
||||
|
||||
self.assertEqual(je.accounts[0].account, self.short_term_loan)
|
||||
self.assertEqual(je.accounts[0].debit_in_account_currency, flt(inv_disc.total_amount))
|
||||
|
||||
self.assertEqual(je.accounts[1].account, self.bank_account)
|
||||
self.assertEqual(je.accounts[1].credit_in_account_currency, flt(inv_disc.total_amount))
|
||||
|
||||
self.assertEqual(je.accounts[2].account, self.ar_discounted)
|
||||
self.assertEqual(je.accounts[2].credit_in_account_currency, flt(inv.outstanding_amount))
|
||||
|
||||
self.assertEqual(je.accounts[3].account, self.ar_unpaid)
|
||||
self.assertEqual(je.accounts[3].debit_in_account_currency, flt(inv.outstanding_amount))
|
||||
|
||||
je.posting_date = nowdate()
|
||||
je.submit()
|
||||
inv_disc.reload()
|
||||
|
||||
self.assertEqual(inv_disc.status, "Settled")
|
||||
|
||||
def test_on_close_before_loan_period(self):
|
||||
inv = create_sales_invoice(rate=700)
|
||||
inv_disc = create_invoice_discounting([inv.name],
|
||||
accounts_receivable_credit=self.ar_credit,
|
||||
accounts_receivable_discounted=self.ar_discounted,
|
||||
accounts_receivable_unpaid=self.ar_unpaid,
|
||||
short_term_loan=self.short_term_loan,
|
||||
bank_charges_account=self.bank_charges_account,
|
||||
bank_account=self.bank_account,
|
||||
start=add_days(nowdate(), -80),
|
||||
period=60
|
||||
)
|
||||
|
||||
inv_disc.create_disbursement_entry()
|
||||
je = inv_disc.close_loan()
|
||||
|
||||
je.posting_date = nowdate()
|
||||
je.submit()
|
||||
|
||||
self.assertEqual(je.accounts[0].account, self.short_term_loan)
|
||||
self.assertEqual(je.accounts[0].debit_in_account_currency, flt(inv_disc.total_amount))
|
||||
|
||||
self.assertEqual(je.accounts[1].account, self.bank_account)
|
||||
self.assertEqual(je.accounts[1].credit_in_account_currency, flt(inv_disc.total_amount))
|
||||
|
||||
inv_disc.reload()
|
||||
|
||||
self.assertEqual(inv_disc.status, "Settled")
|
||||
|
||||
def test_make_payment_before_loan_period(self):
|
||||
#it has problem
|
||||
inv = create_sales_invoice(rate=700)
|
||||
inv_disc = create_invoice_discounting([inv.name],
|
||||
accounts_receivable_credit=self.ar_credit,
|
||||
accounts_receivable_discounted=self.ar_discounted,
|
||||
accounts_receivable_unpaid=self.ar_unpaid,
|
||||
short_term_loan=self.short_term_loan,
|
||||
bank_charges_account=self.bank_charges_account,
|
||||
bank_account=self.bank_account
|
||||
)
|
||||
je = inv_disc.create_disbursement_entry()
|
||||
inv_disc.reload()
|
||||
je.posting_date = nowdate()
|
||||
je.submit()
|
||||
|
||||
je_on_payment = frappe.get_doc(get_payment_entry_against_invoice("Sales Invoice", inv.name))
|
||||
je_on_payment.posting_date = nowdate()
|
||||
je_on_payment.cheque_no = "126981"
|
||||
je_on_payment.cheque_date = nowdate()
|
||||
je_on_payment.save()
|
||||
je_on_payment.submit()
|
||||
|
||||
self.assertEqual(je_on_payment.accounts[0].account, self.ar_discounted)
|
||||
self.assertEqual(je_on_payment.accounts[0].credit_in_account_currency, flt(inv.outstanding_amount))
|
||||
self.assertEqual(je_on_payment.accounts[1].account, self.bank_account)
|
||||
self.assertEqual(je_on_payment.accounts[1].debit_in_account_currency, flt(inv.outstanding_amount))
|
||||
|
||||
inv.reload()
|
||||
self.assertEqual(inv.outstanding_amount, 0)
|
||||
|
||||
def test_make_payment_before_after_period(self):
|
||||
#it has problem
|
||||
inv = create_sales_invoice(rate=700)
|
||||
inv_disc = create_invoice_discounting([inv.name],
|
||||
accounts_receivable_credit=self.ar_credit,
|
||||
accounts_receivable_discounted=self.ar_discounted,
|
||||
accounts_receivable_unpaid=self.ar_unpaid,
|
||||
short_term_loan=self.short_term_loan,
|
||||
bank_charges_account=self.bank_charges_account,
|
||||
bank_account=self.bank_account,
|
||||
loan_start_date=add_days(nowdate(), -10),
|
||||
period=5
|
||||
)
|
||||
je = inv_disc.create_disbursement_entry()
|
||||
inv_disc.reload()
|
||||
je.posting_date = nowdate()
|
||||
je.submit()
|
||||
|
||||
je = inv_disc.close_loan()
|
||||
inv_disc.reload()
|
||||
je.posting_date = nowdate()
|
||||
je.submit()
|
||||
|
||||
je_on_payment = frappe.get_doc(get_payment_entry_against_invoice("Sales Invoice", inv.name))
|
||||
je_on_payment.posting_date = nowdate()
|
||||
je_on_payment.cheque_no = "126981"
|
||||
je_on_payment.cheque_date = nowdate()
|
||||
je_on_payment.submit()
|
||||
|
||||
self.assertEqual(je_on_payment.accounts[0].account, self.ar_unpaid)
|
||||
self.assertEqual(je_on_payment.accounts[0].credit_in_account_currency, flt(inv.outstanding_amount))
|
||||
self.assertEqual(je_on_payment.accounts[1].account, self.bank_account)
|
||||
self.assertEqual(je_on_payment.accounts[1].debit_in_account_currency, flt(inv.outstanding_amount))
|
||||
|
||||
inv.reload()
|
||||
self.assertEqual(inv.outstanding_amount, 0)
|
||||
|
||||
|
||||
def create_invoice_discounting(invoices, **args):
|
||||
args = frappe._dict(args)
|
||||
inv_disc = frappe.new_doc("Invoice Discounting")
|
||||
inv_disc.posting_date = args.posting_date or nowdate()
|
||||
inv_disc.company = args.company or "_Test Company"
|
||||
inv_disc.bank_account = args.bank_account
|
||||
inv_disc.short_term_loan = args.short_term_loan
|
||||
inv_disc.accounts_receivable_credit = args.accounts_receivable_credit
|
||||
inv_disc.accounts_receivable_discounted = args.accounts_receivable_discounted
|
||||
inv_disc.accounts_receivable_unpaid = args.accounts_receivable_unpaid
|
||||
inv_disc.short_term_loan=args.short_term_loan
|
||||
inv_disc.bank_charges_account=args.bank_charges_account
|
||||
inv_disc.bank_account=args.bank_account
|
||||
inv_disc.loan_start_date = args.start or nowdate()
|
||||
inv_disc.loan_period = args.period or 30
|
||||
|
||||
for d in invoices:
|
||||
inv_disc.append("invoices", {
|
||||
"sales_invoice": d
|
||||
})
|
||||
inv_disc.insert()
|
||||
|
||||
if not args.do_not_submit:
|
||||
inv_disc.submit()
|
||||
|
||||
return inv_disc
|
@ -6,6 +6,10 @@ frappe.provide("erpnext.journal_entry");
|
||||
|
||||
|
||||
frappe.ui.form.on("Journal Entry", {
|
||||
setup: function(frm) {
|
||||
frm.add_fetch("bank_account_no", "account", "account");
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
erpnext.toggle_naming_series();
|
||||
frm.cscript.voucher_type(frm.doc);
|
||||
@ -234,7 +238,7 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
|
||||
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
|
||||
}
|
||||
|
||||
|
||||
if(jvd.party_type && jvd.party) {
|
||||
var party_field = "";
|
||||
if(jvd.reference_type.indexOf("Sales")===0) {
|
||||
|
@ -51,6 +51,7 @@ class JournalEntry(AccountsController):
|
||||
self.update_expense_claim()
|
||||
self.update_loan()
|
||||
self.update_inter_company_jv()
|
||||
self.update_invoice_discounting()
|
||||
|
||||
|
||||
def get_title(self):
|
||||
@ -81,6 +82,18 @@ class JournalEntry(AccountsController):
|
||||
frappe.db.set_value("Journal Entry", self.inter_company_journal_entry_reference,\
|
||||
"inter_company_journal_entry_reference", self.name)
|
||||
|
||||
def update_invoice_discounting(self):
|
||||
invoice_discounting_list = [d.reference_name for d in self.accounts if d.reference_type=="Invoice Discounting"]
|
||||
for inv_disc in invoice_discounting_list:
|
||||
short_term_loan_account = frappe.db.get_value("Invoice Discounting", inv_disc, "short_term_loan")
|
||||
for d in self.accounts:
|
||||
if d.account == short_term_loan_account and d.reference_name == inv_disc:
|
||||
if d.credit > 0:
|
||||
status = "Disbursed"
|
||||
elif d.debit > 0:
|
||||
status = "Settled"
|
||||
frappe.db.set_value("Invoice Discounting", inv_disc, "status", status)
|
||||
|
||||
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
|
||||
@ -246,7 +259,11 @@ class JournalEntry(AccountsController):
|
||||
|
||||
# check if party and account match
|
||||
if d.reference_type in ("Sales Invoice", "Purchase Invoice"):
|
||||
if (against_voucher[0] != d.party or against_voucher[1] != d.account):
|
||||
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],
|
||||
d.reference_type, d.reference_name))
|
||||
@ -688,7 +705,7 @@ def get_payment_entry_against_invoice(dt, dn, amount=None, debit_in_account_cur
|
||||
ref_doc = frappe.get_doc(dt, dn)
|
||||
if dt == "Sales Invoice":
|
||||
party_type = "Customer"
|
||||
party_account = ref_doc.debit_to
|
||||
party_account = get_party_account_based_on_invoice_discounting(dn) or ref_doc.debit_to
|
||||
else:
|
||||
party_type = "Supplier"
|
||||
party_account = ref_doc.credit_to
|
||||
@ -715,6 +732,22 @@ def get_payment_entry_against_invoice(dt, dn, amount=None, debit_in_account_cur
|
||||
"journal_entry": journal_entry
|
||||
})
|
||||
|
||||
def get_party_account_based_on_invoice_discounting(sales_invoice):
|
||||
party_account = None
|
||||
invoice_discounting = frappe.db.sql("""
|
||||
select par.accounts_receivable_discounted, par.accounts_receivable_unpaid, par.status
|
||||
from `tabInvoice Discounting` par, `tabDiscounted Invoice` ch
|
||||
where par.name=ch.parent
|
||||
and par.docstatus=1
|
||||
and ch.sales_invoice = %s
|
||||
""", (sales_invoice), as_dict=1)
|
||||
if invoice_discounting:
|
||||
if invoice_discounting[0].status == "Disbursed":
|
||||
party_account = invoice_discounting[0].accounts_receivable_discounted
|
||||
elif invoice_discounting[0].status == "Settled":
|
||||
party_account = invoice_discounting[0].accounts_receivable_unpaid
|
||||
|
||||
return party_account
|
||||
|
||||
def get_payment_entry(ref_doc, args):
|
||||
cost_center = ref_doc.get("cost_center") or frappe.get_cached_value('Company', ref_doc.company, "cost_center")
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -232,6 +232,13 @@ frappe.ui.form.on('Payment Entry', {
|
||||
},
|
||||
|
||||
party_type: function(frm) {
|
||||
|
||||
let party_types = Object.keys(frappe.boot.party_account_types);
|
||||
if(frm.doc.party_type && !party_types.includes(frm.doc.party_type)){
|
||||
frm.set_value("party_type", "");
|
||||
frappe.throw(__("Party can only be one of "+ party_types.join(", ")));
|
||||
}
|
||||
|
||||
if(frm.doc.party) {
|
||||
$.each(["party", "party_balance", "paid_from", "paid_to",
|
||||
"paid_from_account_currency", "paid_from_account_balance",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -536,9 +536,13 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_outstanding_reference_documents(args):
|
||||
|
||||
if isinstance(args, string_types):
|
||||
args = json.loads(args)
|
||||
|
||||
if args.get('party_type') == 'Member':
|
||||
return
|
||||
|
||||
# confirm that Supplier is not blocked
|
||||
if args.get('party_type') == 'Supplier':
|
||||
supplier_status = get_supplier_block_status(args['party'])
|
||||
|
@ -96,7 +96,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
||||
},
|
||||
get_query_filters: {
|
||||
docstatus: 1,
|
||||
status: ["!=", "Closed"],
|
||||
status: ["not in", ["Closed", "On Hold"]],
|
||||
per_billed: ["<", 99.99],
|
||||
company: me.frm.doc.company
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,7 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_bille
|
||||
from erpnext.stock import get_warehouse_account_map
|
||||
from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entries, delete_gl_entries
|
||||
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
|
||||
from erpnext.buying.utils import check_for_closed_status
|
||||
from erpnext.buying.utils import check_on_hold_or_closed_status
|
||||
from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
|
||||
from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_disabled
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
@ -89,7 +89,7 @@ class PurchaseInvoice(BuyingController):
|
||||
self.check_conversion_rate()
|
||||
self.validate_credit_to_acc()
|
||||
self.clear_unallocated_advances("Purchase Invoice Advance", "advances")
|
||||
self.check_for_closed_status()
|
||||
self.check_on_hold_or_closed_status()
|
||||
self.validate_with_previous_doc()
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
||||
@ -152,13 +152,13 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
self.party_account_currency = account.account_currency
|
||||
|
||||
def check_for_closed_status(self):
|
||||
def check_on_hold_or_closed_status(self):
|
||||
check_list = []
|
||||
|
||||
for d in self.get('items'):
|
||||
if d.purchase_order and not d.purchase_order in check_list and not d.purchase_receipt:
|
||||
check_list.append(d.purchase_order)
|
||||
check_for_closed_status('Purchase Order', d.purchase_order)
|
||||
check_on_hold_or_closed_status('Purchase Order', d.purchase_order)
|
||||
|
||||
def validate_with_previous_doc(self):
|
||||
super(PurchaseInvoice, self).validate_with_previous_doc({
|
||||
@ -760,7 +760,7 @@ class PurchaseInvoice(BuyingController):
|
||||
def on_cancel(self):
|
||||
super(PurchaseInvoice, self).on_cancel()
|
||||
|
||||
self.check_for_closed_status()
|
||||
self.check_on_hold_or_closed_status()
|
||||
|
||||
self.update_status_updater_args()
|
||||
|
||||
|
@ -344,6 +344,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
|
||||
pi = frappe.copy_doc(test_records[0])
|
||||
pi.disable_rounded_total = 1
|
||||
pi.allocate_advances_automatically = 0
|
||||
pi.append("advances", {
|
||||
"reference_type": "Journal Entry",
|
||||
"reference_name": jv.name,
|
||||
@ -383,6 +384,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
|
||||
pi = frappe.copy_doc(test_records[0])
|
||||
pi.disable_rounded_total = 1
|
||||
pi.allocate_advances_automatically = 0
|
||||
pi.append("advances", {
|
||||
"reference_type": "Journal Entry",
|
||||
"reference_name": jv.name,
|
||||
|
@ -171,7 +171,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
},
|
||||
get_query_filters: {
|
||||
docstatus: 1,
|
||||
status: ["!=", "Closed"],
|
||||
status: ["not in", ["Closed", "On Hold"]],
|
||||
per_billed: ["<", 99.99],
|
||||
company: me.frm.doc.company
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -81,7 +81,7 @@ class SalesInvoice(SellingController):
|
||||
self.validate_with_previous_doc()
|
||||
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
self.check_close_sales_order("sales_order")
|
||||
self.check_sales_order_on_hold_or_close("sales_order")
|
||||
self.validate_debit_to_acc()
|
||||
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
|
||||
self.add_remarks()
|
||||
@ -209,7 +209,7 @@ class SalesInvoice(SellingController):
|
||||
def on_cancel(self):
|
||||
super(SalesInvoice, self).on_cancel()
|
||||
|
||||
self.check_close_sales_order("sales_order")
|
||||
self.check_sales_order_on_hold_or_close("sales_order")
|
||||
|
||||
if self.is_return and not self.update_billed_amount_in_sales_order:
|
||||
# NOTE status updating bypassed for is_return
|
||||
@ -1397,4 +1397,4 @@ def get_loyalty_programs(customer):
|
||||
frappe.db.set(customer, 'loyalty_program', lp_details[0])
|
||||
return []
|
||||
else:
|
||||
return lp_details
|
||||
return lp_details
|
@ -18,7 +18,7 @@ def get_data():
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Payment'),
|
||||
'items': ['Payment Entry', 'Payment Request', 'Journal Entry']
|
||||
'items': ['Payment Entry', 'Payment Request', 'Journal Entry', 'Invoice Discounting']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
|
@ -913,6 +913,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
jv.submit()
|
||||
|
||||
si = frappe.copy_doc(test_records[0])
|
||||
si.allocate_advances_automatically = 0
|
||||
si.append("advances", {
|
||||
"doctype": "Sales Invoice Advance",
|
||||
"reference_type": "Journal Entry",
|
||||
|
@ -6,17 +6,18 @@
|
||||
|
||||
|
||||
</style>
|
||||
<div class="page-break">
|
||||
<div>
|
||||
{% set gl = frappe.get_list(doctype="GL Entry", fields=["account", "party_type", "party", "debit", "credit", "remarks"], filters={"voucher_type": doc.doctype, "voucher_no": doc.name}) %}
|
||||
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
|
||||
and doc.set("select_print_heading", _("Payment Entry")) -%}{%- endif -%}
|
||||
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
|
||||
<div class="row margin-bottom">
|
||||
<div class="col-sm-6">
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
|
||||
</table>
|
||||
@ -30,53 +31,46 @@
|
||||
<th>Party</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="top-bottom" colspan="5"><strong>Debit</strong></td>
|
||||
</tr>
|
||||
{% for entries in gl %}
|
||||
{% if entries.credit == 0.0 %}
|
||||
<tr>
|
||||
<td class="right top-bottom">{{ entries.account }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party_type }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party }}</td>
|
||||
<td class="left top-bottom">{{ entries.debit }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="top-bottom"colspan="4"><strong> Narration </strong><br>{{ entries.remarks }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td class="right" colspan="3" ><strong>Total (debit) </strong></td>
|
||||
<td class="left" >{{ gl | sum(attribute='debit') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="top-bottom" colspan="5"><strong>Credit</strong></td>
|
||||
</tr>
|
||||
{% set total_credit = 0 -%}
|
||||
{% for entries in doc.gl_entries %}
|
||||
{% for entries in gl %}
|
||||
{% if entries.debit == 0.0 %}
|
||||
<tr>
|
||||
<td class="right top-bottom">{{ entries.account }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party_type }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party }}</td>
|
||||
<td class="left top-bottom">{{ entries.credit }}</td>
|
||||
{% set total_credit = total_credit + entries.credit -%}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="top-bottom" colspan="4"><strong> Narration </strong><br>{{ entries.remarks }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td class="right" colspan="3"><strong>Total (credit) </strong></td>
|
||||
<td class="left" >{{total_credit}}</td>
|
||||
<td class="left" >{{ gl | sum(attribute='credit') }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td class="top-bottom" colspan="4"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="top-bottom" colspan="5"><strong>Debit</strong></td>
|
||||
</tr>
|
||||
{% set total_debit = 0 -%}
|
||||
{% for entries in doc.gl_entries %}
|
||||
{% if entries.credit == 0.0 %}
|
||||
<tr>
|
||||
<td class="right top-bottom">{{ entries.account }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party_type }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party }}</td>
|
||||
{% set total_debit = total_debit + entries.debit -%}
|
||||
<td class="left top-bottom">{{ entries.debit }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="top-bottom"colspan="4"><strong> Narration </strong><br>{{ entries.remarks }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right" colspan="3" ><strong>Total (debit) </strong></td>
|
||||
<td class="left" >{{total_debit}}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
<div>
|
||||
</div>
|
@ -3,26 +3,25 @@
|
||||
.table-bordered td.top-bottom {border-top: none !important;border-bottom: none !important;}
|
||||
.table-bordered td.right{border-right: none !important;}
|
||||
.table-bordered td.left{border-left: none !important;}
|
||||
|
||||
|
||||
</style>
|
||||
<div class="page-break">
|
||||
<div>
|
||||
{% set gl = frappe.get_list(doctype="GL Entry", fields=["account", "party_type", "party", "debit", "credit", "remarks"], filters={"voucher_type": doc.doctype, "voucher_no": doc.name}) %}
|
||||
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
|
||||
and doc.set("select_print_heading", _("Journal Entry")) -%}{%- endif -%}
|
||||
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
|
||||
<div class="row margin-bottom">
|
||||
<div class="col-sm-6">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
|
||||
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="margin-top">
|
||||
<div>
|
||||
<table class="table table-bordered table-condensed">
|
||||
<tr>
|
||||
<th>Account</th>
|
||||
@ -30,47 +29,43 @@
|
||||
<th>Party</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="top-bottom" colspan="5"><strong>Debit</strong></td>
|
||||
</tr>
|
||||
{% for entries in gl %}
|
||||
{% if entries.credit == 0.0 %}
|
||||
<tr>
|
||||
<td class="right top-bottom">{{ entries.account }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party_type }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party }}</td>
|
||||
<td class="left top-bottom">{{ entries.debit }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td class="right" colspan="3" ><strong>Total (debit) </strong></td>
|
||||
<td class="left" >{{ gl | sum(attribute='debit') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="top-bottom" colspan="5"><strong>Credit</strong></td>
|
||||
</tr>
|
||||
{% set total_credit = 0 -%}
|
||||
{% for entries in doc.gl_entries %}
|
||||
{% for entries in gl %}
|
||||
{% if entries.debit == 0.0 %}
|
||||
<tr>
|
||||
<td class="right top-bottom">{{ entries.account }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party_type }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party }}</td>
|
||||
<td class="left top-bottom">{{ entries.credit }}</td>
|
||||
{% set total_credit = total_credit + entries.credit -%}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right" colspan="3"><strong>Total (credit) </strong></td>
|
||||
<td class="left" >{{total_credit}}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td class="top-bottom" colspan="4"> </td>
|
||||
<td class="right" colspan="3"><strong>Total (credit) </strong></td>
|
||||
<td class="left" >{{ gl | sum(attribute='credit') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="top-bottom" colspan="5"><strong>Debit</strong></td>
|
||||
<td class="top-bottom" colspan="5"><b>Narration: </b>{{ gl[0].remarks }}</td>
|
||||
</tr>
|
||||
{% set total_debit = 0 -%}
|
||||
{% for entries in doc.gl_entries %}
|
||||
{% if entries.credit == 0.0 %}
|
||||
<tr>
|
||||
<td class="right top-bottom">{{ entries.account }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party_type }}</td>
|
||||
<td class="right left top-bottom">{{ entries.party }}</td>
|
||||
{% set total_debit = total_debit + entries.debit -%}
|
||||
<td class="left top-bottom">{{ entries.debit }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="right" colspan="3" ><strong>Total (debit) </strong></td>
|
||||
<td class="left" >{{total_debit}}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
<div>
|
||||
</div>
|
@ -1,10 +1,11 @@
|
||||
{%- from "templates/print_formats/standard_macros.html" import add_header -%}
|
||||
<div class="page-break">
|
||||
<div>
|
||||
{% set gl = frappe.get_list(doctype="GL Entry", fields=["account", "party_type", "party", "debit", "credit", "remarks"], filters={"voucher_type": doc.doctype, "voucher_no": doc.name}) %}
|
||||
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
|
||||
and doc.set("select_print_heading", _("Purchase Invoice")) -%}{%- endif -%}
|
||||
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
|
||||
<div class="row margin-bottom">
|
||||
<div class="col-sm-6">
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Supplier Name: </strong></td><td>{{ doc.supplier }}</td></tr>
|
||||
<tr><td><strong>Due Date: </strong></td><td>{{ frappe.utils.formatdate(doc.due_date) }}</td></tr>
|
||||
@ -13,7 +14,7 @@
|
||||
<tr><td><strong>Mobile no: </strong> </td><td>{{doc.contact_mobile}}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
|
||||
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
|
||||
@ -49,21 +50,27 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class="row margin-bottom">
|
||||
<div class="col-sm-6">
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Total Quantity: </strong></td><td>{{ doc.total_qty }}</td></tr>
|
||||
<tr><td><strong>Total: </strong></td><td>{{doc.total}}</td></tr>
|
||||
<tr><td><strong>Net Weight: </strong></td><td>{{ doc.total_net_weight }}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Tax and Charges: </strong></td><td>{{doc.taxes_and_charges}}</td></tr>
|
||||
{% for tax in doc.taxes %}
|
||||
<tr><td><strong>{{ tax.account_head }}: </strong></td><td>{{ tax.tax_amount_after_discount_amount }}</td></tr>
|
||||
{% if tax.tax_amount_after_discount_amount!= 0 %}
|
||||
<tr><td><strong>{{ tax.account_head }}: </strong></td><td>{{ tax.tax_amount_after_discount_amount }}</td></tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if doc.taxes_and_charges_added!= 0 %}
|
||||
<tr><td><strong> Taxes and Charges Added: </strong></td><td>{{ doc.taxes_and_charges_added }}</td></tr>
|
||||
{% endif %}
|
||||
{% if doc.taxes_and_charges_deducted!= 0 %}
|
||||
<tr><td><strong> Taxes and Charges Deducted: </strong></td><td>{{ doc.taxes_and_charges_deducted }}</td></tr>
|
||||
{% endif %}
|
||||
<tr><td><strong> Total Taxes and Charges: </strong></td><td>{{ doc.total_taxes_and_charges }}</td></tr>
|
||||
<tr><td><strong> Net Payable: </strong></td><td>{{ doc.grand_total }}</td></tr>
|
||||
</table>
|
||||
@ -76,17 +83,17 @@
|
||||
<th>Account</th>
|
||||
<th>Party Type</th>
|
||||
<th>Party</th>
|
||||
<th>Credit Amount</th>
|
||||
<th>Debit Amount</th>
|
||||
<th>Credit Amount</th>
|
||||
</tr>
|
||||
{% for entries in doc.gl_entries %}
|
||||
{% for entries in gl %}
|
||||
<tr>
|
||||
<td>{{ loop.index }}</td>
|
||||
<td>{{ entries.account }}</td>
|
||||
<td>{{ entries.party_type }}</td>
|
||||
<td>{{ entries.party }}</td>
|
||||
<td>{{ entries.credit }}</td>
|
||||
<td>{{ entries.debit }}</td>
|
||||
<td>{{ entries.credit }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
|
@ -1,10 +1,11 @@
|
||||
{%- from "templates/print_formats/standard_macros.html" import add_header -%}
|
||||
<div class="page-break">
|
||||
<div>
|
||||
{% set gl = frappe.get_list(doctype="GL Entry", fields=["account", "party_type", "party", "debit", "credit", "remarks"], filters={"voucher_type": doc.doctype, "voucher_no": doc.name}) %}
|
||||
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
|
||||
and doc.set("select_print_heading", _("Sales Invoice")) -%}{%- endif -%}
|
||||
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
|
||||
<div class="row margin-bottom">
|
||||
<div class="col-sm-6">
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Customer Name: </strong></td><td>{{ doc.customer }}</td></tr>
|
||||
<tr><td><strong>Due Date: </strong></td><td>{{ frappe.utils.formatdate(doc.due_date) }}</td></tr>
|
||||
@ -13,7 +14,7 @@
|
||||
<tr><td><strong>Mobile no: </strong> </td><td>{{doc.contact_mobile}}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
|
||||
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
|
||||
@ -45,18 +46,20 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class="row margin-bottom">
|
||||
<div class="col-sm-6">
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Total Quantity: </strong></td><td>{{ doc.total_qty }}</td></tr>
|
||||
<tr><td><strong>Total: </strong></td><td>{{doc.total}}</td></tr>
|
||||
<tr><td><strong>Net Weight: </strong></td><td>{{ doc.total_net_weight }}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-xs-6">
|
||||
<table>
|
||||
<tr><td><strong>Tax and Charges: </strong></td><td>{{doc.taxes_and_charges}}</td></tr>
|
||||
{% for tax in doc.taxes %}
|
||||
<tr><td><strong>{{ tax.account_head }}: </strong></td><td>{{ tax.tax_amount_after_discount_amount }}</td></tr>
|
||||
{% if tax.tax_amount_after_discount_amount!= 0 %}
|
||||
<tr><td><strong>{{ tax.account_head }}: </strong></td><td>{{ tax.tax_amount_after_discount_amount }}</td></tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<tr><td><strong> Total Taxes and Charges: </strong></td><td>{{ doc.total_taxes_and_charges }}</td></tr>
|
||||
<tr><td><strong> Net Payable: </strong></td><td>{{ doc.grand_total }}</td></tr>
|
||||
@ -70,17 +73,17 @@
|
||||
<th>Account</th>
|
||||
<th>Party Type</th>
|
||||
<th>Party</th>
|
||||
<th>Credit Amount</th>
|
||||
<th>Debit Amount</th>
|
||||
<th>Credit Amount</th>
|
||||
</tr>
|
||||
{% for entries in doc.gl_entries %}
|
||||
{% for entries in gl %}
|
||||
<tr>
|
||||
<td>{{ loop.index }}</td>
|
||||
<td>{{ entries.account }}</td>
|
||||
<td>{{ entries.party_type }}</td>
|
||||
<td>{{ entries.party }}</td>
|
||||
<td>{{ entries.credit }}</td>
|
||||
<td>{{ entries.debit }}</td>
|
||||
<td>{{ entries.credit }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
|
@ -107,26 +107,28 @@
|
||||
<thead>
|
||||
<tr>
|
||||
{% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
|
||||
<th style="width: 7%">{%= __("Date") %}</th>
|
||||
<th style="width: 7%">{%= __("Age (Days)") %}</th>
|
||||
<th style="width: 13%">{%= __("Reference") %}</th>
|
||||
{% if(report.report_name === "Accounts Receivable") { %}
|
||||
<th style="width: 10%">{%= __("Sales Person") %}</th>
|
||||
<th style="width: 9%">{%= __("Date") %}</th>
|
||||
<th style="width: 5%">{%= __("Age (Days)") %}</th>
|
||||
|
||||
{% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %}
|
||||
<th style="width: 16%">{%= __("Reference") %}</th>
|
||||
<th style="width: 10%">{%= __("Sales Person") %}</th>
|
||||
{% } else { %}
|
||||
<th style="width: 26%">{%= __("Reference") %}</th>
|
||||
{% } %}
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
<th style="width: 20%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
|
||||
<th style="width: 20%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
|
||||
{% } %}
|
||||
<th style="width: 10%; text-align: right">{%= __("Invoiced Amount") %}</th>
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
<th style="width: 10%; text-align: right">{%= __("Paid Amount") %}</th>
|
||||
<th style="width: 10%; text-align: right">{%= report.report_name === "Accounts Receivable" ? __('Credit Note') : __('Debit Note') %}</th>
|
||||
{% } %}
|
||||
<th style="width: 15%; text-align: right">{%= __("Outstanding Amount") %}</th>
|
||||
<th style="width: 10%; text-align: right">{%= __("Outstanding Amount") %}</th>
|
||||
{% if(filters.show_pdc_in_print) { %}
|
||||
{% if(report.report_name === "Accounts Receivable") { %}
|
||||
<th style="width: 10%">{%= __("Customer LPO No.") %}</th>
|
||||
{% } %}
|
||||
<th style="width: 10%">{%= __("PDC/LC Date") %}</th>
|
||||
<th style="width: 10%">{%= __("PDC/LC Ref") %}</th>
|
||||
<th style="width: 10%">{%= __("PDC/LC Amount") %}</th>
|
||||
<th style="width: 10%">{%= __("Remaining Balance") %}</th>
|
||||
@ -155,7 +157,7 @@
|
||||
{%= data[i]["voucher_no"] %}
|
||||
</td>
|
||||
|
||||
{% if(report.report_name === "Accounts Receivable") { %}
|
||||
{% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %}
|
||||
<td>{%= data[i]["sales_person"] %}</td>
|
||||
{% } %}
|
||||
|
||||
@ -195,7 +197,6 @@
|
||||
<td style="text-align: right">
|
||||
{%= data[i]["po_no"] %}</td>
|
||||
{% } %}
|
||||
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][("pdc/lc_date")]) %}</td>
|
||||
<td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
|
||||
@ -226,7 +227,6 @@
|
||||
<td style="text-align: right">
|
||||
{%= data[i][__("Customer LPO")] %}</td>
|
||||
{% } %}
|
||||
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][__("PDC/LC Date")]) %}</td>
|
||||
<td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
|
||||
|
@ -116,14 +116,19 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
"fieldtype": "Link",
|
||||
"options": "Sales Person"
|
||||
},
|
||||
{
|
||||
"fieldname":"based_on_payment_terms",
|
||||
"label": __("Based On Payment Terms"),
|
||||
"fieldtype": "Check",
|
||||
},
|
||||
{
|
||||
"fieldname":"show_pdc_in_print",
|
||||
"label": __("Show PDC in Print"),
|
||||
"fieldtype": "Check",
|
||||
},
|
||||
{
|
||||
"fieldname":"based_on_payment_terms",
|
||||
"label": __("Based On Payment Terms"),
|
||||
"fieldname":"show_sales_person_in_print",
|
||||
"label": __("Show Sales Person in Print"),
|
||||
"fieldtype": "Check",
|
||||
},
|
||||
{
|
||||
|
@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import erpnext
|
||||
from frappe import _
|
||||
from frappe import _, scrub
|
||||
from frappe.utils import getdate, nowdate
|
||||
from six import iteritems, itervalues
|
||||
|
||||
@ -14,6 +14,9 @@ class PartyLedgerSummaryReport(object):
|
||||
self.filters.from_date = getdate(self.filters.from_date or nowdate())
|
||||
self.filters.to_date = getdate(self.filters.to_date or nowdate())
|
||||
|
||||
if not self.filters.get("company"):
|
||||
self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company')
|
||||
|
||||
def run(self, args):
|
||||
if self.filters.from_date > self.filters.to_date:
|
||||
frappe.throw(_("From Date must be before To Date"))
|
||||
@ -21,10 +24,9 @@ class PartyLedgerSummaryReport(object):
|
||||
self.filters.party_type = args.get("party_type")
|
||||
self.party_naming_by = frappe.db.get_value(args.get("naming_by")[0], None, args.get("naming_by")[1])
|
||||
|
||||
discount_account_field = "discount_allowed_account" if self.filters.party_type == "Customer" \
|
||||
else "discount_received_account"
|
||||
self.round_off_account, self.write_off_account, self.discount_account = frappe.get_cached_value('Company',
|
||||
self.filters.company, ["round_off_account", "write_off_account", discount_account_field])
|
||||
self.get_gl_entries()
|
||||
self.get_return_invoices()
|
||||
self.get_party_adjustment_amounts()
|
||||
|
||||
columns = self.get_columns()
|
||||
data = self.get_data()
|
||||
@ -48,7 +50,6 @@ class PartyLedgerSummaryReport(object):
|
||||
})
|
||||
|
||||
credit_or_debit_note = "Credit Note" if self.filters.party_type == "Customer" else "Debit Note"
|
||||
discount_allowed_or_received = "Discount Allowed" if self.filters.party_type == "Customer" else "Discount Received"
|
||||
|
||||
columns += [
|
||||
{
|
||||
@ -79,27 +80,19 @@ class PartyLedgerSummaryReport(object):
|
||||
"options": "currency",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _(discount_allowed_or_received),
|
||||
"fieldname": "discount_amount",
|
||||
]
|
||||
|
||||
for account in self.party_adjustment_accounts:
|
||||
columns.append({
|
||||
"label": account,
|
||||
"fieldname": "adj_" + scrub(account),
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _("Write Off Amount"),
|
||||
"fieldname": "write_off_amount",
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _("Other Adjustments"),
|
||||
"fieldname": "adjustment_amount",
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
"width": 120
|
||||
},
|
||||
"width": 120,
|
||||
"is_adjustment": 1
|
||||
})
|
||||
|
||||
columns += [
|
||||
{
|
||||
"label": _("Closing Balance"),
|
||||
"fieldname": "closing_balance",
|
||||
@ -119,17 +112,10 @@ class PartyLedgerSummaryReport(object):
|
||||
return columns
|
||||
|
||||
def get_data(self):
|
||||
if not self.filters.get("company"):
|
||||
self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company')
|
||||
|
||||
company_currency = frappe.get_cached_value('Company', self.filters.get("company"), "default_currency")
|
||||
invoice_dr_or_cr = "debit" if self.filters.party_type == "Customer" else "credit"
|
||||
reverse_dr_or_cr = "credit" if self.filters.party_type == "Customer" else "debit"
|
||||
|
||||
self.get_gl_entries()
|
||||
self.get_return_invoices()
|
||||
self.get_party_adjustment_amounts()
|
||||
|
||||
self.party_data = frappe._dict({})
|
||||
for gle in self.gl_entries:
|
||||
self.party_data.setdefault(gle.party, frappe._dict({
|
||||
@ -146,7 +132,7 @@ class PartyLedgerSummaryReport(object):
|
||||
amount = gle.get(invoice_dr_or_cr) - gle.get(reverse_dr_or_cr)
|
||||
self.party_data[gle.party].closing_balance += amount
|
||||
|
||||
if gle.posting_date < self.filters.from_date:
|
||||
if gle.posting_date < self.filters.from_date or gle.is_opening == "Yes":
|
||||
self.party_data[gle.party].opening_balance += amount
|
||||
else:
|
||||
if amount > 0:
|
||||
@ -161,9 +147,10 @@ class PartyLedgerSummaryReport(object):
|
||||
if row.opening_balance or row.invoiced_amount or row.paid_amount or row.return_amount or row.closing_amount:
|
||||
total_party_adjustment = sum([amount for amount in itervalues(self.party_adjustment_details.get(party, {}))])
|
||||
row.paid_amount -= total_party_adjustment
|
||||
row.discount_amount = self.party_adjustment_details.get(party, {}).get(self.discount_account, 0)
|
||||
row.write_off_amount = self.party_adjustment_details.get(party, {}).get(self.write_off_account, 0)
|
||||
row.adjustment_amount = total_party_adjustment - row.discount_amount - row.write_off_amount
|
||||
|
||||
adjustments = self.party_adjustment_details.get(party, {})
|
||||
for account in self.party_adjustment_accounts:
|
||||
row["adj_" + scrub(account)] = adjustments.get(account, 0)
|
||||
|
||||
out.append(row)
|
||||
|
||||
@ -182,7 +169,7 @@ class PartyLedgerSummaryReport(object):
|
||||
self.gl_entries = frappe.db.sql("""
|
||||
select
|
||||
gle.posting_date, gle.party, gle.voucher_type, gle.voucher_no, gle.against_voucher_type,
|
||||
gle.against_voucher, gle.debit, gle.credit {join_field}
|
||||
gle.against_voucher, gle.debit, gle.credit, gle.is_opening {join_field}
|
||||
from `tabGL Entry` gle
|
||||
{join}
|
||||
where
|
||||
@ -254,9 +241,10 @@ class PartyLedgerSummaryReport(object):
|
||||
|
||||
def get_party_adjustment_amounts(self):
|
||||
conditions = self.prepare_conditions()
|
||||
income_or_expense = "Expense" if self.filters.party_type == "Customer" else "Income"
|
||||
income_or_expense = "Expense Account" if self.filters.party_type == "Customer" else "Income Account"
|
||||
invoice_dr_or_cr = "debit" if self.filters.party_type == "Customer" else "credit"
|
||||
reverse_dr_or_cr = "credit" if self.filters.party_type == "Customer" else "debit"
|
||||
round_off_account = frappe.get_cached_value('Company', self.filters.company, "round_off_account")
|
||||
|
||||
gl_entries = frappe.db.sql("""
|
||||
select
|
||||
@ -267,7 +255,7 @@ class PartyLedgerSummaryReport(object):
|
||||
docstatus < 2
|
||||
and (voucher_type, voucher_no) in (
|
||||
select voucher_type, voucher_no from `tabGL Entry` gle, `tabAccount` acc
|
||||
where acc.name = gle.account and acc.root_type = '{income_or_expense}'
|
||||
where acc.name = gle.account and acc.account_type = '{income_or_expense}'
|
||||
and gle.posting_date between %(from_date)s and %(to_date)s and gle.docstatus < 2
|
||||
) and (voucher_type, voucher_no) in (
|
||||
select voucher_type, voucher_no from `tabGL Entry` gle
|
||||
@ -277,6 +265,7 @@ class PartyLedgerSummaryReport(object):
|
||||
""".format(conditions=conditions, income_or_expense=income_or_expense), self.filters, as_dict=True)
|
||||
|
||||
self.party_adjustment_details = {}
|
||||
self.party_adjustment_accounts = set()
|
||||
adjustment_voucher_entries = {}
|
||||
for gle in gl_entries:
|
||||
adjustment_voucher_entries.setdefault((gle.voucher_type, gle.voucher_no), [])
|
||||
@ -288,12 +277,12 @@ class PartyLedgerSummaryReport(object):
|
||||
has_irrelevant_entry = False
|
||||
|
||||
for gle in voucher_gl_entries:
|
||||
if gle.account == self.round_off_account:
|
||||
if gle.account == round_off_account:
|
||||
continue
|
||||
elif gle.party:
|
||||
parties.setdefault(gle.party, 0)
|
||||
parties[gle.party] += gle.get(reverse_dr_or_cr) - gle.get(invoice_dr_or_cr)
|
||||
elif frappe.get_cached_value("Account", gle.account, "root_type") == income_or_expense:
|
||||
elif frappe.get_cached_value("Account", gle.account, "account_type") == income_or_expense:
|
||||
accounts.setdefault(gle.account, 0)
|
||||
accounts[gle.account] += gle.get(invoice_dr_or_cr) - gle.get(reverse_dr_or_cr)
|
||||
else:
|
||||
@ -303,11 +292,13 @@ class PartyLedgerSummaryReport(object):
|
||||
if len(parties) == 1:
|
||||
party = parties.keys()[0]
|
||||
for account, amount in iteritems(accounts):
|
||||
self.party_adjustment_accounts.add(account)
|
||||
self.party_adjustment_details.setdefault(party, {})
|
||||
self.party_adjustment_details[party].setdefault(account, 0)
|
||||
self.party_adjustment_details[party][account] += amount
|
||||
elif len(accounts) == 1 and not has_irrelevant_entry:
|
||||
account = accounts.keys()[0]
|
||||
self.party_adjustment_accounts.add(account)
|
||||
for party, amount in iteritems(parties):
|
||||
self.party_adjustment_details.setdefault(party, {})
|
||||
self.party_adjustment_details[party].setdefault(account, 0)
|
||||
|
@ -14,13 +14,13 @@ def execute(filters=None):
|
||||
|
||||
def get_column():
|
||||
return [
|
||||
_("Delivery Note") + ":Link/Delivery Note:120", _("Date") + ":Date:100",
|
||||
_("Delivery Note") + ":Link/Delivery Note:120", _("Status") + "::120", _("Date") + ":Date:100",
|
||||
_("Suplier") + ":Link/Customer:120", _("Customer Name") + "::120",
|
||||
_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item: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': 'Delivery Note', 'party': 'customer',
|
||||
return {'doctype': 'Delivery Note', 'party': 'customer',
|
||||
'date': 'posting_date', 'order': 'name', 'order_by': 'desc'}
|
@ -54,8 +54,10 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
||||
delivery_note, d.income_account, d.cost_center, d.stock_qty, d.stock_uom
|
||||
]
|
||||
|
||||
row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount] \
|
||||
if d.stock_uom != d.uom and d.stock_qty != 0 else [d.base_net_rate, d.base_net_amount]
|
||||
if d.stock_uom != d.uom and d.stock_qty:
|
||||
row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount]
|
||||
else:
|
||||
row += [d.base_net_rate, d.base_net_amount]
|
||||
|
||||
total_tax = 0
|
||||
for tax in tax_columns:
|
||||
@ -108,13 +110,13 @@ def get_conditions(filters):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Payment`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
|
||||
|
||||
|
||||
if filters.get("warehouse"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)"""
|
||||
|
||||
|
||||
|
||||
if filters.get("brand"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
||||
where parent=`tabSales Invoice`.name
|
||||
@ -131,10 +133,10 @@ def get_conditions(filters):
|
||||
def get_items(filters, additional_query_columns):
|
||||
conditions = get_conditions(filters)
|
||||
match_conditions = frappe.build_match_conditions("Sales Invoice")
|
||||
|
||||
|
||||
if match_conditions:
|
||||
match_conditions = " and {0} ".format(match_conditions)
|
||||
|
||||
|
||||
if additional_query_columns:
|
||||
additional_query_columns = ', ' + ', '.join(additional_query_columns)
|
||||
|
||||
|
@ -12,14 +12,14 @@ def get_ordered_to_be_billed_data(args):
|
||||
child_tab = doctype + " Item"
|
||||
precision = get_field_precision(frappe.get_meta(child_tab).get_field("billed_amt"),
|
||||
currency=get_default_currency()) or 2
|
||||
|
||||
|
||||
project_field = get_project_field(doctype, party)
|
||||
|
||||
return frappe.db.sql("""
|
||||
Select
|
||||
`{parent_tab}`.name, `{parent_tab}`.{date_field}, `{parent_tab}`.{party}, `{parent_tab}`.{party}_name,
|
||||
`{parent_tab}`.name, `{parent_tab}`.status, `{parent_tab}`.{date_field}, `{parent_tab}`.{party}, `{parent_tab}`.{party}_name,
|
||||
{project_field}, `{child_tab}`.item_code, `{child_tab}`.base_amount,
|
||||
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)),
|
||||
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)),
|
||||
(`{child_tab}`.base_amount - (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1))),
|
||||
`{child_tab}`.item_name, `{child_tab}`.description, `{parent_tab}`.company
|
||||
from
|
||||
|
@ -14,13 +14,13 @@ def execute(filters=None):
|
||||
|
||||
def get_column():
|
||||
return [
|
||||
_("Sales Order") + ":Link/Sales Order:120", _("Date") + ":Date:100",
|
||||
_("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",
|
||||
_("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',
|
||||
return {'doctype': 'Sales Order', 'party': 'customer',
|
||||
'date': 'transaction_date', 'order': 'transaction_date', 'order_by': 'asc'}
|
@ -14,13 +14,13 @@ def execute(filters=None):
|
||||
|
||||
def get_column():
|
||||
return [
|
||||
_("Purchase Order") + ":Link/Purchase Order:120", _("Date") + ":Date:100",
|
||||
_("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",
|
||||
_("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',
|
||||
return {'doctype': 'Purchase Order', 'party': 'supplier',
|
||||
'date': 'transaction_date', 'order': 'transaction_date', 'order_by': 'asc'}
|
||||
|
@ -14,7 +14,7 @@ def execute(filters=None):
|
||||
|
||||
def get_column():
|
||||
return [
|
||||
_("Purchase Receipt") + ":Link/Purchase Receipt:120", _("Date") + ":Date:100",
|
||||
_("Purchase Receipt") + ":Link/Purchase Receipt:120", _("Status") + "::120", _("Date") + ":Date:100",
|
||||
_("Supplier") + ":Link/Supplier:120", _("Supplier Name") + "::120",
|
||||
_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
|
||||
_("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Amount to Bill") + ":Currency:100",
|
||||
|
@ -55,12 +55,15 @@ def get_result(filters):
|
||||
supplier = supplier_map[d]
|
||||
|
||||
tds_doc = tds_docs[supplier.tax_withholding_category]
|
||||
account = [i.account for i in tds_doc.accounts if i.company == filters.company][0]
|
||||
account_list = [i.account for i in tds_doc.accounts if i.company == filters.company]
|
||||
|
||||
if account_list:
|
||||
account = account_list[0]
|
||||
|
||||
for k in gle_map[d]:
|
||||
if k.party == supplier_map[d] and k.credit > 0:
|
||||
total_amount_credited += k.credit
|
||||
elif k.account == account and k.credit > 0:
|
||||
elif account_list and k.account == account and k.credit > 0:
|
||||
tds_deducted = k.credit
|
||||
total_amount_credited += k.credit
|
||||
|
||||
|
@ -206,12 +206,10 @@ frappe.ui.form.on('Asset', {
|
||||
erpnext.asset.set_accululated_depreciation(frm);
|
||||
},
|
||||
|
||||
depreciation_method: function(frm) {
|
||||
frm.events.make_schedules_editable(frm);
|
||||
},
|
||||
|
||||
make_schedules_editable: function(frm) {
|
||||
var is_editable = frm.doc.depreciation_method==="Manual" ? true : false;
|
||||
var is_editable = frm.doc.finance_books.filter(d => d.depreciation_method == "Manual").length > 0
|
||||
? true : false;
|
||||
|
||||
frm.toggle_enable("schedules", is_editable);
|
||||
frm.fields_dict["schedules"].grid.toggle_enable("schedule_date", is_editable);
|
||||
frm.fields_dict["schedules"].grid.toggle_enable("depreciation_amount", is_editable);
|
||||
@ -296,6 +294,44 @@ frappe.ui.form.on('Asset', {
|
||||
})
|
||||
|
||||
frm.toggle_reqd("finance_books", frm.doc.calculate_depreciation);
|
||||
},
|
||||
|
||||
set_depreciation_rate: function(frm, row) {
|
||||
if (row.total_number_of_depreciations && row.frequency_of_depreciation) {
|
||||
frappe.call({
|
||||
method: "get_depreciation_rate",
|
||||
doc: frm.doc,
|
||||
args: row,
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
frappe.model.set_value(row.doctype, row.name, "rate_of_depreciation", r.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Asset Finance Book', {
|
||||
depreciation_method: function(frm, cdt, cdn) {
|
||||
const row = locals[cdt][cdn];
|
||||
frm.events.set_depreciation_rate(frm, row);
|
||||
frm.events.make_schedules_editable(frm);
|
||||
},
|
||||
|
||||
expected_value_after_useful_life: function(frm, cdt, cdn) {
|
||||
const row = locals[cdt][cdn];
|
||||
frm.events.set_depreciation_rate(frm, row);
|
||||
},
|
||||
|
||||
frequency_of_depreciation: function(frm, cdt, cdn) {
|
||||
const row = locals[cdt][cdn];
|
||||
frm.events.set_depreciation_rate(frm, row);
|
||||
},
|
||||
|
||||
total_number_of_depreciations: function(frm, cdt, cdn) {
|
||||
const row = locals[cdt][cdn];
|
||||
frm.events.set_depreciation_rate(frm, row);
|
||||
}
|
||||
});
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,8 +3,9 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
import frappe, erpnext, math, json
|
||||
from frappe import _
|
||||
from six import string_types
|
||||
from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff
|
||||
from frappe.model.document import Document
|
||||
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
||||
@ -20,6 +21,7 @@ class Asset(AccountsController):
|
||||
self.validate_item()
|
||||
self.set_missing_values()
|
||||
if self.calculate_depreciation:
|
||||
self.set_depreciation_rate()
|
||||
self.make_depreciation_schedule()
|
||||
self.set_accumulated_depreciation()
|
||||
else:
|
||||
@ -89,17 +91,22 @@ class Asset(AccountsController):
|
||||
if self.is_existing_asset:
|
||||
return
|
||||
|
||||
date = nowdate()
|
||||
docname = self.purchase_receipt or self.purchase_invoice
|
||||
if docname:
|
||||
doctype = 'Purchase Receipt' if self.purchase_receipt else 'Purchase Invoice'
|
||||
date = frappe.db.get_value(doctype, docname, 'posting_date')
|
||||
|
||||
if self.available_for_use_date and getdate(self.available_for_use_date) < getdate(date):
|
||||
if self.available_for_use_date and getdate(self.available_for_use_date) < getdate(self.purchase_date):
|
||||
frappe.throw(_("Available-for-use Date should be after purchase date"))
|
||||
|
||||
def set_depreciation_rate(self):
|
||||
for d in self.get("finance_books"):
|
||||
d.rate_of_depreciation = self.get_depreciation_rate(d)
|
||||
|
||||
def make_depreciation_schedule(self):
|
||||
if self.depreciation_method != 'Manual':
|
||||
depreciation_method = [d.depreciation_method for d in self.finance_books]
|
||||
|
||||
if 'Manual' not in depreciation_method:
|
||||
self.schedules = []
|
||||
|
||||
if not self.get("schedules") and self.available_for_use_date:
|
||||
@ -254,14 +261,16 @@ class Asset(AccountsController):
|
||||
return flt(self.get('finance_books')[cint(idx)-1].value_after_depreciation)
|
||||
|
||||
def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
|
||||
percentage_value = 100.0 if row.depreciation_method == 'Written Down Value' else 200.0
|
||||
if row.depreciation_method in ["Straight Line", "Manual"]:
|
||||
amt = (flt(self.gross_purchase_amount) - flt(row.expected_value_after_useful_life) -
|
||||
flt(self.opening_accumulated_depreciation))
|
||||
|
||||
factor = percentage_value / cint(total_number_of_depreciations)
|
||||
depreciation_amount = flt(depreciable_value * factor / 100, 0)
|
||||
|
||||
value_after_depreciation = flt(depreciable_value) - depreciation_amount
|
||||
if value_after_depreciation < flt(row.expected_value_after_useful_life):
|
||||
depreciation_amount = flt(depreciable_value) - flt(row.expected_value_after_useful_life)
|
||||
depreciation_amount = amt * row.rate_of_depreciation
|
||||
else:
|
||||
depreciation_amount = flt(depreciable_value) * (flt(row.rate_of_depreciation) / 100)
|
||||
value_after_depreciation = flt(depreciable_value) - depreciation_amount
|
||||
if value_after_depreciation < flt(row.expected_value_after_useful_life):
|
||||
depreciation_amount = flt(depreciable_value) - flt(row.expected_value_after_useful_life)
|
||||
|
||||
return depreciation_amount
|
||||
|
||||
@ -394,6 +403,32 @@ class Asset(AccountsController):
|
||||
make_gl_entries(gl_entries)
|
||||
self.db_set('booked_fixed_asset', 1)
|
||||
|
||||
def get_depreciation_rate(self, args):
|
||||
if isinstance(args, string_types):
|
||||
args = json.loads(args)
|
||||
|
||||
number_of_depreciations_booked = 0
|
||||
if self.is_existing_asset:
|
||||
number_of_depreciations_booked = self.number_of_depreciations_booked
|
||||
|
||||
float_precision = cint(frappe.db.get_default("float_precision")) or 2
|
||||
tot_no_of_depreciation = flt(args.get("total_number_of_depreciations")) - flt(number_of_depreciations_booked)
|
||||
|
||||
if args.get("depreciation_method") in ["Straight Line", "Manual"]:
|
||||
return 1.0 / tot_no_of_depreciation
|
||||
|
||||
if args.get("depreciation_method") == 'Double Declining Balance':
|
||||
return 200.0 / args.get("total_number_of_depreciations")
|
||||
|
||||
if args.get("depreciation_method") == "Written Down Value" and not args.get("rate_of_depreciation"):
|
||||
no_of_years = flt(args.get("total_number_of_depreciations") * flt(args.get("frequency_of_depreciation"))) / 12
|
||||
value = flt(args.get("expected_value_after_useful_life")) / flt(self.gross_purchase_amount)
|
||||
|
||||
# square root of flt(salvage_value) / flt(asset_cost)
|
||||
depreciation_rate = math.pow(value, 1.0/flt(no_of_years, 2))
|
||||
|
||||
return 100 * (1 - flt(depreciation_rate, float_precision))
|
||||
|
||||
def update_maintenance_status():
|
||||
assets = frappe.get_all('Asset', filters = {'docstatus': 1, 'maintenance_required': 1})
|
||||
|
||||
@ -480,7 +515,6 @@ def create_asset_adjustment(asset, asset_category, company):
|
||||
|
||||
@frappe.whitelist()
|
||||
def transfer_asset(args):
|
||||
import json
|
||||
args = json.loads(args)
|
||||
|
||||
if args.get('serial_no'):
|
||||
@ -557,4 +591,4 @@ def make_journal_entry(asset_name):
|
||||
return je
|
||||
|
||||
def is_cwip_accounting_disabled():
|
||||
return cint(frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting"))
|
||||
return cint(frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting"))
|
||||
|
@ -160,9 +160,9 @@ class TestAsset(unittest.TestCase):
|
||||
asset.save()
|
||||
|
||||
expected_schedules = [
|
||||
["2020-06-06", 66667.0, 66667.0],
|
||||
["2021-04-06", 22222.0, 88889.0],
|
||||
["2022-02-06", 1111.0, 90000.0]
|
||||
["2020-06-06", 66666.67, 66666.67],
|
||||
["2021-04-06", 22222.22, 88888.89],
|
||||
["2022-02-06", 1111.11, 90000.0]
|
||||
]
|
||||
|
||||
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
|
||||
@ -192,8 +192,8 @@ class TestAsset(unittest.TestCase):
|
||||
asset.save()
|
||||
|
||||
expected_schedules = [
|
||||
["2020-06-06", 33333.0, 83333.0],
|
||||
["2021-04-06", 6667.0, 90000.0]
|
||||
["2020-06-06", 33333.33, 83333.33],
|
||||
["2021-04-06", 6666.67, 90000.0]
|
||||
]
|
||||
|
||||
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
|
||||
@ -209,7 +209,7 @@ class TestAsset(unittest.TestCase):
|
||||
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
|
||||
asset = frappe.get_doc('Asset', asset_name)
|
||||
asset.calculate_depreciation = 1
|
||||
asset.purchase_date = '2020-06-06'
|
||||
asset.purchase_date = '2020-01-30'
|
||||
asset.is_existing_asset = 0
|
||||
asset.available_for_use_date = "2020-01-30"
|
||||
asset.append("finance_books", {
|
||||
@ -244,7 +244,7 @@ class TestAsset(unittest.TestCase):
|
||||
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
|
||||
asset = frappe.get_doc('Asset', asset_name)
|
||||
asset.calculate_depreciation = 1
|
||||
asset.purchase_date = '2020-06-06'
|
||||
asset.purchase_date = '2020-01-30'
|
||||
asset.available_for_use_date = "2020-01-30"
|
||||
asset.append("finance_books", {
|
||||
"expected_value_after_useful_life": 10000,
|
||||
@ -277,6 +277,37 @@ class TestAsset(unittest.TestCase):
|
||||
self.assertEqual(gle, expected_gle)
|
||||
self.assertEqual(asset.get("value_after_depreciation"), 0)
|
||||
|
||||
def test_depreciation_entry_for_wdv(self):
|
||||
pr = make_purchase_receipt(item_code="Macbook Pro",
|
||||
qty=1, rate=8000.0, location="Test Location")
|
||||
|
||||
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
|
||||
asset = frappe.get_doc('Asset', asset_name)
|
||||
asset.calculate_depreciation = 1
|
||||
asset.available_for_use_date = '2030-06-06'
|
||||
asset.purchase_date = '2030-06-06'
|
||||
asset.append("finance_books", {
|
||||
"expected_value_after_useful_life": 1000,
|
||||
"depreciation_method": "Written Down Value",
|
||||
"total_number_of_depreciations": 3,
|
||||
"frequency_of_depreciation": 12,
|
||||
"depreciation_start_date": "2030-12-31"
|
||||
})
|
||||
asset.save(ignore_permissions=True)
|
||||
|
||||
self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0)
|
||||
|
||||
expected_schedules = [
|
||||
["2030-12-31", 4000.0, 4000.0],
|
||||
["2031-12-31", 2000.0, 6000.0],
|
||||
["2032-12-31", 1000.0, 7000.0],
|
||||
]
|
||||
|
||||
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
|
||||
for d in asset.get("schedules")]
|
||||
|
||||
self.assertEqual(schedules, expected_schedules)
|
||||
|
||||
def test_depreciation_entry_cancellation(self):
|
||||
pr = make_purchase_receipt(item_code="Macbook Pro",
|
||||
qty=1, rate=100000.0, location="Test Location")
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
@ -14,11 +15,13 @@
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "finance_book",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -42,14 +45,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "depreciation_method",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@ -73,14 +79,17 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_number_of_depreciations",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
@ -103,14 +112,17 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_5",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -133,14 +145,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "frequency_of_depreciation",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
@ -163,15 +178,18 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:parent.doctype == 'Asset'",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "depreciation_start_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@ -194,16 +212,19 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"depends_on": "eval:parent.doctype == 'Asset'",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "expected_value_after_useful_life",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@ -227,14 +248,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "value_after_depreciation",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 1,
|
||||
@ -258,20 +282,54 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.depreciation_method == 'Written Down Value'",
|
||||
"description": "In Percentage",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "rate_of_depreciation",
|
||||
"fieldtype": "Percent",
|
||||
"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": "Rate of Depreciation",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-05-12 14:56:44.800046",
|
||||
"modified": "2019-04-09 19:45:14.523488",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Finance Book",
|
||||
@ -280,10 +338,10 @@
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -36,7 +36,8 @@ frappe.ui.form.on("Purchase Order", {
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
if(frm.doc.docstatus == 1 && frm.doc.status == 'To Receive and Bill') {
|
||||
if(frm.doc.docstatus === 1 && frm.doc.status !== 'Closed'
|
||||
&& flt(frm.doc.per_received) < 100 && flt(frm.doc.per_billed) < 100) {
|
||||
frm.add_custom_button(__('Update Items'), () => {
|
||||
erpnext.utils.update_child_items({
|
||||
frm: frm,
|
||||
@ -93,62 +94,63 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.set_df_property("drop_ship", "hidden", !is_drop_ship);
|
||||
this.frm.set_df_property("drop_ship", "hidden", !is_drop_ship);
|
||||
|
||||
if(doc.docstatus == 1 && !in_list(["Closed", "Delivered"], doc.status)) {
|
||||
if (this.frm.has_perm("submit")) {
|
||||
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100) {
|
||||
cur_frm.add_custom_button(__('Close'), this.close_purchase_order, __("Status"));
|
||||
if(doc.docstatus == 1) {
|
||||
if(!in_list(["Closed", "Delivered"], doc.status)) {
|
||||
if (this.frm.has_perm("submit")) {
|
||||
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100) {
|
||||
if (doc.status != "On Hold") {
|
||||
this.frm.add_custom_button(__('Hold'), () => this.hold_purchase_order(), __("Status"));
|
||||
} else{
|
||||
this.frm.add_custom_button(__('Resume'), () => this.unhold_purchase_order(), __("Status"));
|
||||
}
|
||||
this.frm.add_custom_button(__('Close'), () => this.close_purchase_order(), __("Status"));
|
||||
}
|
||||
}
|
||||
|
||||
if(is_drop_ship && doc.status!="Delivered") {
|
||||
this.frm.add_custom_button(__('Delivered'),
|
||||
this.delivered_by_supplier, __("Status"));
|
||||
|
||||
this.frm.page.set_inner_btn_group_as_primary(__("Status"));
|
||||
}
|
||||
} else if(in_list(["Closed", "Delivered"], doc.status)) {
|
||||
if (this.frm.has_perm("submit")) {
|
||||
this.frm.add_custom_button(__('Re-open'), () => this.unclose_purchase_order(), __("Status"));
|
||||
}
|
||||
}
|
||||
if(doc.status != "Closed") {
|
||||
if (doc.status != "On Hold") {
|
||||
if(flt(doc.per_received, 2) < 100 && allow_receipt) {
|
||||
cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __('Create'));
|
||||
if(doc.is_subcontracted==="Yes") {
|
||||
cur_frm.add_custom_button(__('Material to Supplier'),
|
||||
function() { me.make_stock_entry(); }, __("Transfer"));
|
||||
}
|
||||
}
|
||||
if(flt(doc.per_billed, 2) < 100)
|
||||
cur_frm.add_custom_button(__('Invoice'),
|
||||
this.make_purchase_invoice, __('Create'));
|
||||
|
||||
if(is_drop_ship && doc.status!="Delivered"){
|
||||
cur_frm.add_custom_button(__('Delivered'),
|
||||
this.delivered_by_supplier, __("Status"));
|
||||
|
||||
cur_frm.page.set_inner_btn_group_as_primary(__("Status"));
|
||||
if(!doc.auto_repeat) {
|
||||
cur_frm.add_custom_button(__('Subscription'), function() {
|
||||
erpnext.utils.make_subscription(doc.doctype, doc.name)
|
||||
}, __('Create'))
|
||||
}
|
||||
}
|
||||
if(flt(doc.per_billed)==0) {
|
||||
this.frm.add_custom_button(__('Payment Request'),
|
||||
function() { me.make_payment_request() }, __('Create'));
|
||||
}
|
||||
if(flt(doc.per_billed)==0 && doc.status != "Delivered") {
|
||||
cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_payment_entry, __('Create'));
|
||||
}
|
||||
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
|
||||
}
|
||||
} else if(doc.docstatus===0) {
|
||||
cur_frm.cscript.add_from_mappers();
|
||||
}
|
||||
|
||||
if(doc.docstatus == 1 && in_list(["Closed", "Delivered"], doc.status)) {
|
||||
if (this.frm.has_perm("submit")) {
|
||||
cur_frm.add_custom_button(__('Re-open'), this.unclose_purchase_order, __("Status"));
|
||||
}
|
||||
}
|
||||
|
||||
if(doc.docstatus == 1 && doc.status != "Closed") {
|
||||
if(flt(doc.per_received, 2) < 100 && allow_receipt) {
|
||||
cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __('Create'));
|
||||
|
||||
if(doc.is_subcontracted==="Yes") {
|
||||
cur_frm.add_custom_button(__('Material to Supplier'),
|
||||
function() { me.make_stock_entry(); }, __("Transfer"));
|
||||
}
|
||||
}
|
||||
|
||||
if(flt(doc.per_billed, 2) < 100)
|
||||
cur_frm.add_custom_button(__('Invoice'),
|
||||
this.make_purchase_invoice, __('Create'));
|
||||
|
||||
if(flt(doc.per_billed)==0 && doc.status != "Delivered") {
|
||||
cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_payment_entry, __('Create'));
|
||||
}
|
||||
|
||||
if(!doc.auto_repeat) {
|
||||
cur_frm.add_custom_button(__('Subscription'), function() {
|
||||
erpnext.utils.make_subscription(doc.doctype, doc.name)
|
||||
}, __('Create'))
|
||||
}
|
||||
|
||||
if(flt(doc.per_billed)==0) {
|
||||
this.frm.add_custom_button(__('Payment Request'),
|
||||
function() { me.make_payment_request() }, __('Create'));
|
||||
}
|
||||
|
||||
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
|
||||
}
|
||||
},
|
||||
|
||||
get_items_from_open_material_requests: function() {
|
||||
@ -427,6 +429,43 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
||||
}
|
||||
},
|
||||
|
||||
unhold_purchase_order: function(){
|
||||
cur_frm.cscript.update_status("Resume", "Draft")
|
||||
},
|
||||
|
||||
hold_purchase_order: function(){
|
||||
var me = this;
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __('Reason for Hold'),
|
||||
fields: [
|
||||
{
|
||||
"fieldname": "reason_for_hold",
|
||||
"fieldtype": "Text",
|
||||
"reqd": 1,
|
||||
}
|
||||
],
|
||||
primary_action: function() {
|
||||
var data = d.get_values();
|
||||
frappe.call({
|
||||
method: "frappe.desk.form.utils.add_comment",
|
||||
args: {
|
||||
reference_doctype: me.frm.doctype,
|
||||
reference_name: me.frm.docname,
|
||||
content: __('Reason for hold: ')+data.reason_for_hold,
|
||||
comment_email: frappe.session.user
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
me.update_status('Hold', 'On Hold')
|
||||
d.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
|
||||
unclose_purchase_order: function(){
|
||||
cur_frm.cscript.update_status('Re-open', 'Submitted')
|
||||
},
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ from erpnext.controllers.buying_controller import BuyingController
|
||||
from erpnext.stock.doctype.item.item import get_last_purchase_details
|
||||
from erpnext.stock.stock_balance import update_bin_qty, get_ordered_qty
|
||||
from frappe.desk.notifications import clear_doctype_notifications
|
||||
from erpnext.buying.utils import validate_for_items, check_for_closed_status
|
||||
from erpnext.buying.utils import validate_for_items, check_on_hold_or_closed_status
|
||||
from erpnext.stock.utils import get_bin
|
||||
from erpnext.accounts.party import get_party_account_currency
|
||||
from six import string_types
|
||||
@ -45,7 +45,7 @@ class PurchaseOrder(BuyingController):
|
||||
self.validate_supplier()
|
||||
self.validate_schedule_date()
|
||||
validate_for_items(self)
|
||||
self.check_for_closed_status()
|
||||
self.check_on_hold_or_closed_status()
|
||||
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
||||
@ -144,12 +144,12 @@ class PurchaseOrder(BuyingController):
|
||||
= d.rate = d.last_purchase_rate = item_last_purchase_rate
|
||||
|
||||
# Check for Closed status
|
||||
def check_for_closed_status(self):
|
||||
def check_on_hold_or_closed_status(self):
|
||||
check_list =[]
|
||||
for d in self.get('items'):
|
||||
if d.meta.get_field('material_request') and d.material_request and d.material_request not in check_list:
|
||||
check_list.append(d.material_request)
|
||||
check_for_closed_status('Material Request', d.material_request)
|
||||
check_on_hold_or_closed_status('Material Request', d.material_request)
|
||||
|
||||
def update_requested_qty(self):
|
||||
material_request_map = {}
|
||||
@ -232,7 +232,7 @@ class PurchaseOrder(BuyingController):
|
||||
if self.is_subcontracted == "Yes":
|
||||
self.update_reserved_qty_for_subcontract()
|
||||
|
||||
self.check_for_closed_status()
|
||||
self.check_on_hold_or_closed_status()
|
||||
|
||||
frappe.db.set(self,'status','Cancelled')
|
||||
|
||||
@ -382,7 +382,9 @@ def make_purchase_invoice(source_name, target_doc=None):
|
||||
def postprocess(source, target):
|
||||
set_missing_values(source, target)
|
||||
#Get the advance paid Journal Entries in Purchase Invoice Advance
|
||||
target.set_advances()
|
||||
|
||||
if target.get("allocate_advances_automatically"):
|
||||
target.set_advances()
|
||||
|
||||
def update_item(obj, target, source_parent):
|
||||
target.amount = flt(obj.amount) - flt(obj.billed_amt)
|
||||
|
@ -4,6 +4,8 @@ frappe.listview_settings['Purchase Order'] = {
|
||||
get_indicator: function (doc) {
|
||||
if (doc.status === "Closed") {
|
||||
return [__("Closed"), "green", "status,=,Closed"];
|
||||
} else if (doc.status === "On Hold") {
|
||||
return [__("On Hold"), "orange", "status,=,On Hold"];
|
||||
} else if (doc.status === "Delivered") {
|
||||
return [__("Delivered"), "green", "status,=,Closed"];
|
||||
} else if (flt(doc.per_received, 2) < 100 && doc.status !== "Closed") {
|
||||
|
@ -120,6 +120,15 @@ class TestPurchaseOrder(unittest.TestCase):
|
||||
self.assertEqual(pi.doctype, "Purchase Invoice")
|
||||
self.assertEqual(len(pi.get("items", [])), 1)
|
||||
|
||||
def test_purchase_order_on_hold(self):
|
||||
po = create_purchase_order(item_code="_Test Product Bundle Item")
|
||||
po.db_set('Status', "On Hold")
|
||||
pi = make_purchase_invoice(po.name)
|
||||
pr = make_purchase_receipt(po.name)
|
||||
self.assertRaises(frappe.ValidationError, pr.submit)
|
||||
self.assertRaises(frappe.ValidationError, pi.submit)
|
||||
|
||||
|
||||
def test_make_purchase_invoice_with_terms(self):
|
||||
po = create_purchase_order(do_not_save=True)
|
||||
|
||||
|
@ -73,10 +73,10 @@ def validate_for_items(doc):
|
||||
not cint(frappe.db.get_single_value("Buying Settings", "allow_multiple_items") or 0):
|
||||
frappe.throw(_("Same item cannot be entered multiple times."))
|
||||
|
||||
def check_for_closed_status(doctype, docname):
|
||||
def check_on_hold_or_closed_status(doctype, docname):
|
||||
status = frappe.db.get_value(doctype, docname, "status")
|
||||
|
||||
if status == "Closed":
|
||||
if status in ("Closed", "On Hold"):
|
||||
frappe.throw(_("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError)
|
||||
|
||||
@frappe.whitelist()
|
||||
|
@ -119,12 +119,6 @@ class AccountsController(TransactionBase):
|
||||
self.validate_non_invoice_documents_schedule()
|
||||
|
||||
def before_print(self):
|
||||
if self.doctype in ['Journal Entry', 'Payment Entry', 'Sales Invoice', 'Purchase Invoice']:
|
||||
self.gl_entries = frappe.get_list("GL Entry", filters={
|
||||
"voucher_type": self.doctype,
|
||||
"voucher_no": self.name
|
||||
}, fields=["account", "party_type", "party", "debit", "credit", "remarks"])
|
||||
|
||||
if self.doctype in ['Purchase Order', 'Sales Order', 'Sales Invoice', 'Purchase Invoice',
|
||||
'Supplier Quotation', 'Purchase Receipt', 'Delivery Note', 'Quotation']:
|
||||
if self.get("group_same_items"):
|
||||
|
@ -442,6 +442,13 @@ class BuyingController(StockController):
|
||||
frappe.throw(_("Row #{0}: {1} can not be negative for item {2}".format(item_row['idx'],
|
||||
frappe.get_meta(item_row.doctype).get_label(fieldname), item_row['item_code'])))
|
||||
|
||||
def check_for_on_hold_or_closed_status(self, ref_doctype, ref_fieldname):
|
||||
for d in self.get("items"):
|
||||
if d.get(ref_fieldname):
|
||||
status = frappe.db.get_value(ref_doctype, d.get(ref_fieldname), "status")
|
||||
if status in ("Closed", "On Hold"):
|
||||
frappe.throw(_("{0} {1} is {2}").format(ref_doctype,d.get(ref_fieldname), status))
|
||||
|
||||
def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
|
||||
self.update_ordered_and_reserved_qty()
|
||||
|
||||
|
@ -2,8 +2,9 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import frappe, erpnext
|
||||
from frappe import _
|
||||
from frappe.model.meta import get_field_precision
|
||||
from frappe.utils import flt, get_datetime, format_datetime
|
||||
|
||||
class StockOverReturnError(frappe.ValidationError): pass
|
||||
@ -116,6 +117,10 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
||||
|
||||
already_returned_data = already_returned_items.get(args.item_code) or {}
|
||||
|
||||
company_currency = erpnext.get_company_currency(doc.company)
|
||||
stock_qty_precision = get_field_precision(frappe.get_meta(doc.doctype + " Item")
|
||||
.get_field("stock_qty"), company_currency)
|
||||
|
||||
for column in fields:
|
||||
returned_qty = flt(already_returned_data.get(column, 0)) if len(already_returned_data) > 0 else 0
|
||||
|
||||
@ -126,7 +131,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
||||
reference_qty = ref.get(column) * ref.get("conversion_factor", 1.0)
|
||||
current_stock_qty = args.get(column) * args.get("conversion_factor", 1.0)
|
||||
|
||||
max_returnable_qty = flt(reference_qty) - returned_qty
|
||||
max_returnable_qty = flt(reference_qty, stock_qty_precision) - returned_qty
|
||||
label = column.replace('_', ' ').title()
|
||||
|
||||
if reference_qty:
|
||||
@ -135,7 +140,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
||||
elif returned_qty >= reference_qty and args.get(column):
|
||||
frappe.throw(_("Item {0} has already been returned")
|
||||
.format(args.item_code), StockOverReturnError)
|
||||
elif abs(current_stock_qty) > max_returnable_qty:
|
||||
elif abs(flt(current_stock_qty, stock_qty_precision)) > max_returnable_qty:
|
||||
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
|
||||
.format(args.idx, max_returnable_qty, args.item_code), StockOverReturnError)
|
||||
|
||||
@ -239,6 +244,10 @@ def make_return_doc(doctype, source_name, target_doc=None):
|
||||
doc.paid_amount = -1 * source.paid_amount
|
||||
doc.base_paid_amount = -1 * source.base_paid_amount
|
||||
|
||||
if doc.get("is_return") and hasattr(doc, "packed_items"):
|
||||
for d in doc.get("packed_items"):
|
||||
d.qty = d.qty * -1
|
||||
|
||||
doc.discount_amount = -1 * source.discount_amount
|
||||
doc.run_method("calculate_taxes_and_totals")
|
||||
|
||||
|
@ -257,11 +257,11 @@ class SellingController(StockController):
|
||||
so_warehouse = so_item and so_item[0]["warehouse"] or ""
|
||||
return so_qty, so_warehouse
|
||||
|
||||
def check_close_sales_order(self, ref_fieldname):
|
||||
def check_sales_order_on_hold_or_close(self, ref_fieldname):
|
||||
for d in self.get("items"):
|
||||
if d.get(ref_fieldname):
|
||||
status = frappe.db.get_value("Sales Order", d.get(ref_fieldname), "status")
|
||||
if status == "Closed":
|
||||
if status in ("Closed", "On Hold"):
|
||||
frappe.throw(_("Sales Order {0} is {1}").format(d.get(ref_fieldname), status))
|
||||
|
||||
def update_reserved_qty(self):
|
||||
|
@ -41,6 +41,7 @@ status_map = {
|
||||
["Completed", "eval:self.order_type == 'Maintenance' and self.per_billed == 100 and self.docstatus == 1"],
|
||||
["Cancelled", "eval:self.docstatus==2"],
|
||||
["Closed", "eval:self.status=='Closed'"],
|
||||
["On Hold", "eval:self.status=='On Hold'"],
|
||||
],
|
||||
"Sales Invoice": [
|
||||
["Draft", None],
|
||||
@ -70,6 +71,7 @@ status_map = {
|
||||
["Completed", "eval:self.per_received == 100 and self.per_billed == 100 and self.docstatus == 1"],
|
||||
["Delivered", "eval:self.status=='Delivered'"],
|
||||
["Cancelled", "eval:self.docstatus==2"],
|
||||
["On Hold", "eval:self.status=='On Hold'"],
|
||||
["Closed", "eval:self.status=='Closed'"],
|
||||
],
|
||||
"Delivery Note": [
|
||||
|
@ -42,10 +42,10 @@ def create_variant_with_tables(item, args):
|
||||
return variant
|
||||
|
||||
def make_item_variant():
|
||||
frappe.delete_doc_if_exists("Item", "_Test Variant Item-S", force=1)
|
||||
variant = create_variant_with_tables("_Test Variant Item", '{"Test Size": "Small"}')
|
||||
variant.item_code = "_Test Variant Item-S"
|
||||
variant.item_name = "_Test Variant Item-S"
|
||||
frappe.delete_doc_if_exists("Item", "_Test Variant Item-XSL", force=1)
|
||||
variant = create_variant_with_tables("_Test Variant Item", '{"Test Size": "Extra Small"}')
|
||||
variant.item_code = "_Test Variant Item-XSL"
|
||||
variant.item_name = "_Test Variant Item-XSL"
|
||||
variant.save()
|
||||
return variant
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,6 +9,7 @@ from frappe.model.mapper import get_mapped_doc
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from erpnext.accounts.party import get_party_account_currency
|
||||
from frappe.desk.form import assign_to
|
||||
|
||||
subject_field = "title"
|
||||
sender_field = "contact_email"
|
||||
@ -153,6 +154,9 @@ class Opportunity(TransactionBase):
|
||||
def on_update(self):
|
||||
self.add_calendar_event()
|
||||
|
||||
# assign to customer account manager or lead owner
|
||||
assign_to_user(self, subject_field)
|
||||
|
||||
def add_calendar_event(self, opts=None, force=False):
|
||||
if not opts:
|
||||
opts = frappe._dict()
|
||||
@ -329,3 +333,19 @@ def auto_close_opportunity():
|
||||
doc.flags.ignore_permissions = True
|
||||
doc.flags.ignore_mandatory = True
|
||||
doc.save()
|
||||
|
||||
def assign_to_user(doc, subject_field):
|
||||
assign_user = None
|
||||
if doc.customer:
|
||||
assign_user = frappe.db.get_value('Customer', doc.customer, 'account_manager')
|
||||
elif doc.lead:
|
||||
assign_user = frappe.db.get_value('Lead', doc.lead, 'lead_owner')
|
||||
|
||||
if assign_user and assign_user != 'Administrator':
|
||||
if not assign_to.get(dict(doctype = doc.doctype, name = doc.name)):
|
||||
assign_to.add({
|
||||
"assign_to": assign_user,
|
||||
"doctype": doc.doctype,
|
||||
"name": doc.name,
|
||||
"description": doc.get(subject_field)
|
||||
})
|
||||
|
@ -3,10 +3,11 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
from frappe.utils import today
|
||||
from frappe.utils import today, random_string
|
||||
from erpnext.crm.doctype.lead.lead import make_customer
|
||||
from erpnext.crm.doctype.opportunity.opportunity import make_quotation
|
||||
import unittest
|
||||
from frappe.desk.form import assign_to
|
||||
|
||||
test_records = frappe.get_test_records('Opportunity')
|
||||
|
||||
@ -27,9 +28,10 @@ class TestOpportunity(unittest.TestCase):
|
||||
self.assertEqual(doc.status, "Quotation")
|
||||
|
||||
def test_make_new_lead_if_required(self):
|
||||
new_lead_email_id = "new{}@example.com".format(random_string(5))
|
||||
args = {
|
||||
"doctype": "Opportunity",
|
||||
"contact_email":"new.opportunity@example.com",
|
||||
"contact_email": new_lead_email_id,
|
||||
"opportunity_type": "Sales",
|
||||
"with_items": 0,
|
||||
"transaction_date": today()
|
||||
@ -40,13 +42,13 @@ class TestOpportunity(unittest.TestCase):
|
||||
self.assertTrue(opp_doc.lead)
|
||||
self.assertEqual(opp_doc.enquiry_from, "Lead")
|
||||
self.assertEqual(frappe.db.get_value("Lead", opp_doc.lead, "email_id"),
|
||||
'new.opportunity@example.com')
|
||||
new_lead_email_id)
|
||||
|
||||
# create new customer and create new contact against 'new.opportunity@example.com'
|
||||
customer = make_customer(opp_doc.lead).insert(ignore_permissions=True)
|
||||
frappe.get_doc({
|
||||
"doctype": "Contact",
|
||||
"email_id": "new.opportunity@example.com",
|
||||
"email_id": new_lead_email_id,
|
||||
"first_name": "_Test Opportunity Customer",
|
||||
"links": [{
|
||||
"link_doctype": "Customer",
|
||||
@ -59,6 +61,21 @@ class TestOpportunity(unittest.TestCase):
|
||||
self.assertEqual(opp_doc.enquiry_from, "Customer")
|
||||
self.assertEqual(opp_doc.customer, customer.name)
|
||||
|
||||
def test_assignment(self):
|
||||
# assign cutomer account manager
|
||||
frappe.db.set_value('Customer', '_Test Customer', 'account_manager', 'test1@example.com')
|
||||
doc = make_opportunity(with_items=0)
|
||||
|
||||
self.assertEqual(assign_to.get(dict(doctype = doc.doctype, name = doc.name))[0].get('owner'), 'test1@example.com')
|
||||
|
||||
# assign lead owner
|
||||
frappe.db.set_value('Customer', '_Test Customer', 'account_manager', '')
|
||||
frappe.db.set_value('Lead', '_T-Lead-00001', 'lead_owner', 'test2@example.com')
|
||||
doc = make_opportunity(with_items=0, enquiry_from='Lead')
|
||||
|
||||
self.assertEqual(assign_to.get(dict(doctype = doc.doctype, name = doc.name))[0].get('owner'), 'test2@example.com')
|
||||
|
||||
|
||||
def make_opportunity(**args):
|
||||
args = frappe._dict(args)
|
||||
|
||||
@ -75,7 +92,7 @@ def make_opportunity(**args):
|
||||
opp_doc.customer = args.customer or "_Test Customer"
|
||||
|
||||
if opp_doc.enquiry_from == 'Lead':
|
||||
opp_doc.customer = args.lead or "_T-Lead-00001"
|
||||
opp_doc.lead = args.lead or "_T-Lead-00001"
|
||||
|
||||
if args.with_items:
|
||||
opp_doc.append('items', {
|
||||
|
@ -19,27 +19,24 @@ def verify_request():
|
||||
frappe.get_request_header("X-Wc-Webhook-Signature") and \
|
||||
not sig == bytes(frappe.get_request_header("X-Wc-Webhook-Signature").encode()):
|
||||
frappe.throw(_("Unverified Webhook Data"))
|
||||
frappe.set_user(woocommerce_settings.modified_by)
|
||||
frappe.set_user(woocommerce_settings.creation_user)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def order(data=None):
|
||||
if not data:
|
||||
verify_request()
|
||||
def order():
|
||||
woocommerce_settings = frappe.get_doc("Woocommerce Settings")
|
||||
if frappe.flags.woocomm_test_order_data:
|
||||
fd = frappe.flags.woocomm_test_order_data
|
||||
event = "created"
|
||||
|
||||
if frappe.request and frappe.request.data:
|
||||
elif frappe.request and frappe.request.data:
|
||||
verify_request()
|
||||
fd = json.loads(frappe.request.data)
|
||||
elif data:
|
||||
fd = data
|
||||
event = frappe.get_request_header("X-Wc-Webhook-Event")
|
||||
|
||||
else:
|
||||
return "success"
|
||||
|
||||
if not data:
|
||||
event = frappe.get_request_header("X-Wc-Webhook-Event")
|
||||
else:
|
||||
event = "created"
|
||||
|
||||
if event == "created":
|
||||
|
||||
raw_billing_data = fd.get("billing")
|
||||
customer_woo_com_email = raw_billing_data.get("email")
|
||||
|
||||
@ -73,7 +70,7 @@ def order(data=None):
|
||||
|
||||
new_sales_order.po_no = fd.get("id")
|
||||
new_sales_order.woocommerce_id = fd.get("id")
|
||||
new_sales_order.naming_series = "SO-"
|
||||
new_sales_order.naming_series = woocommerce_settings.sales_order_series or "SO-WOO-"
|
||||
|
||||
placed_order_date = created_date[0]
|
||||
raw_date = datetime.datetime.strptime(placed_order_date, "%Y-%m-%d")
|
||||
@ -100,10 +97,10 @@ def order(data=None):
|
||||
"item_name": found_item.item_name,
|
||||
"description": found_item.item_name,
|
||||
"delivery_date":order_delivery_date,
|
||||
"uom": "Nos",
|
||||
"uom": woocommerce_settings.uom or _("Nos"),
|
||||
"qty": item.get("quantity"),
|
||||
"rate": item.get("price"),
|
||||
"warehouse": "Stores" + " - " + company_abbr
|
||||
"warehouse": woocommerce_settings.warehouse or "Stores" + " - " + company_abbr
|
||||
})
|
||||
|
||||
add_tax_details(new_sales_order,ordered_items_tax,"Ordered Item tax",0)
|
||||
@ -175,6 +172,7 @@ def link_customer_and_address(raw_billing_data,customer_status):
|
||||
frappe.db.commit()
|
||||
|
||||
def link_item(item_data,item_status):
|
||||
woocommerce_settings = frappe.get_doc("Woocommerce Settings")
|
||||
|
||||
if item_status == 0:
|
||||
#Create Item
|
||||
@ -189,6 +187,7 @@ def link_item(item_data,item_status):
|
||||
item.item_code = "woocommerce - " + str(item_data.get("product_id"))
|
||||
item.woocommerce_id = str(item_data.get("product_id"))
|
||||
item.item_group = "WooCommerce Products"
|
||||
item.stock_uom = woocommerce_settings.uom or _("Nos")
|
||||
item.save()
|
||||
frappe.db.commit()
|
||||
|
||||
@ -209,4 +208,4 @@ def add_tax_details(sales_order,price,desc,status):
|
||||
"account_head": account_head_type,
|
||||
"tax_amount": price,
|
||||
"description": desc
|
||||
})
|
||||
})
|
||||
|
@ -42,4 +42,15 @@ frappe.ui.form.on('Woocommerce Settings', {
|
||||
frm.set_df_property("api_consumer_key", "reqd", frm.doc.enable_sync);
|
||||
frm.set_df_property("api_consumer_secret", "reqd", frm.doc.enable_sync);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Woocommerce Settings", "onload", function () {
|
||||
frappe.call({
|
||||
method: "erpnext.erpnext_integrations.doctype.woocommerce_settings.woocommerce_settings.get_series",
|
||||
callback: function (r) {
|
||||
$.each(r.message, function (key, value) {
|
||||
set_field_options(key, value);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -65,7 +65,7 @@ class WoocommerceSettings(Document):
|
||||
if not frappe.get_value("Item Group",{"name": "WooCommerce Products"}):
|
||||
item_group = frappe.new_doc("Item Group")
|
||||
item_group.item_group_name = "WooCommerce Products"
|
||||
item_group.parent_item_group = "All Item Groups"
|
||||
item_group.parent_item_group = _("All Item Groups")
|
||||
item_group.save()
|
||||
|
||||
|
||||
@ -122,3 +122,9 @@ def generate_secret():
|
||||
woocommerce_settings = frappe.get_doc("Woocommerce Settings")
|
||||
woocommerce_settings.secret = frappe.generate_hash()
|
||||
woocommerce_settings.save()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_series():
|
||||
return {
|
||||
"sales_order_series" : frappe.get_meta("Sales Order").get_options("naming_series") or "SO-WOO-",
|
||||
}
|
@ -49,7 +49,7 @@ frappe.ui.form.on('Healthcare Service Unit Type', {
|
||||
var disable = function(frm){
|
||||
var doc = frm.doc;
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
|
||||
method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
|
||||
args: {status: 1, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable},
|
||||
callback: function(){
|
||||
cur_frm.reload_doc();
|
||||
@ -60,7 +60,7 @@ var disable = function(frm){
|
||||
var enable = function(frm){
|
||||
var doc = frm.doc;
|
||||
frappe.call({
|
||||
method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
|
||||
method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
|
||||
args: {status: 0, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable},
|
||||
callback: function(){
|
||||
cur_frm.reload_doc();
|
||||
|
@ -111,7 +111,7 @@ def change_item_code(item, item_code, doc_name):
|
||||
frappe.db.set_value("Healthcare Service Unit Type", doc_name, "item_code", item_code)
|
||||
|
||||
@frappe.whitelist()
|
||||
def disable_enable(status, doc_name, item, is_billable):
|
||||
def disable_enable(status, doc_name, item=None, is_billable=None):
|
||||
frappe.db.set_value("Healthcare Service Unit Type", doc_name, "disabled", status)
|
||||
if(is_billable == 1):
|
||||
frappe.db.set_value("Item", item, "disabled", status)
|
||||
|
@ -74,7 +74,7 @@ website_generators = ["Item Group", "Item", "BOM", "Sales Partner",
|
||||
|
||||
website_context = {
|
||||
"favicon": "/assets/erpnext/images/favicon.png",
|
||||
"splash_image": "/assets/erpnext/images/erp-icon.svg"
|
||||
"splash_image": "/assets/erpnext/images/erpnext-12.svg"
|
||||
}
|
||||
|
||||
website_route_rules = [
|
||||
|
@ -1,291 +1,341 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-05-09 05:37:18.439763",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-05-09 05:37:18.439763",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "activity_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Activity Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "activity_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Activity Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "User",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "User",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "role",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Role",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Role",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "role",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Role",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Role",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "task",
|
||||
"fieldtype": "Link",
|
||||
"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": "Task",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Task",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "task",
|
||||
"fieldtype": "Link",
|
||||
"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": "Task",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Task",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Applicable in the case of Employee Onboarding",
|
||||
"fieldname": "required_for_employee_creation",
|
||||
"fieldtype": "Check",
|
||||
"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": "Required for Employee Creation",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "task_weight",
|
||||
"fieldtype": "Float",
|
||||
"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": "Task Weight",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Applicable in the case of Employee Onboarding",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "required_for_employee_creation",
|
||||
"fieldtype": "Check",
|
||||
"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": "Required for Employee Creation",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"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": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break",
|
||||
"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,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"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": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-05-10 06:54:47.282492",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Boarding Activity",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2019-04-12 11:31:27.080747",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Boarding Activity",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -288,11 +288,7 @@ frappe.ui.form.on("Expense Claim Detail", {
|
||||
claim_amount: function(frm, cdt, cdn) {
|
||||
var child = locals[cdt][cdn];
|
||||
var doc = frm.doc;
|
||||
|
||||
if(!child.sanctioned_amount){
|
||||
frappe.model.set_value(cdt, cdn, 'sanctioned_amount', child.claim_amount);
|
||||
}
|
||||
|
||||
frappe.model.set_value(cdt, cdn, 'sanctioned_amount', child.claim_amount);
|
||||
cur_frm.cscript.calculate_total(doc,cdt,cdn);
|
||||
},
|
||||
|
||||
@ -339,4 +335,4 @@ cur_frm.fields_dict['task'].get_query = function(doc) {
|
||||
'project': doc.project
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -513,7 +513,7 @@ def add_department_leaves(events, start, end, employee, company):
|
||||
department_employees = frappe.db.sql_list("""select name from tabEmployee where department=%s
|
||||
and company=%s""", (department, company))
|
||||
|
||||
filter_conditions = "employee in (\"%s\")" % '", "'.join(department_employees)
|
||||
filter_conditions = " and employee in (\"%s\")" % '", "'.join(department_employees)
|
||||
add_leaves(events, start, end, filter_conditions=filter_conditions)
|
||||
|
||||
def add_leaves(events, start, end, filter_conditions=None):
|
||||
|
@ -454,7 +454,7 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
self.net_pay = 0
|
||||
if self.total_working_days:
|
||||
self.net_pay = (flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))) * flt(self.payment_days / self.total_working_days)
|
||||
self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))
|
||||
|
||||
self.rounded_total = rounded(self.net_pay,
|
||||
self.precision("net_pay") if disable_rounded_total else 0)
|
||||
|
@ -189,7 +189,7 @@
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "<h4>Condition Examples</h4>\n<ol>\n<li>Applying tax if employee born between 31-12-1937 and 01-01-1958 (Employees aged 60 to 80)<br>\n<code>Condition: date_of_birth>date(1937, 12, 31) and date_of_birth<date(1958, 01, 01)</code></li><br><li>Applying tax by employee gender<br>\n<code>Condition: gender=\"Male\"</code></li><br>\n<li>Applying tax by Salary Component<br>\n<code>Condition: base > 10000</code></li></ol>",
|
||||
"options": "<h4>Condition Examples</h4>\n<ol>\n<li>Applying tax if employee born between 31-12-1937 and 01-01-1958 (Employees aged 60 to 80)<br>\n<code>Condition: date_of_birth>date(1937, 12, 31) and date_of_birth<date(1958, 01, 01)</code></li><br><li>Applying tax by employee gender<br>\n<code>Condition: gender==\"Male\"</code></li><br>\n<li>Applying tax by Salary Component<br>\n<code>Condition: base > 10000</code></li></ol>",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -229,4 +229,4 @@
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,11 @@ class TrainingFeedback(Document):
|
||||
|
||||
def on_submit(self):
|
||||
training_event = frappe.get_doc("Training Event", self.training_event)
|
||||
status = None
|
||||
for e in training_event.employees:
|
||||
if e.employee == self.employee:
|
||||
training_event.status = 'Feedback Submitted'
|
||||
status = 'Feedback Submitted'
|
||||
break
|
||||
|
||||
training_event.save()
|
||||
if status:
|
||||
frappe.db.set_value("Training Event", self.training_event, "status", status)
|
||||
|
@ -29,19 +29,12 @@ erpnext.hr.AttendanceControlPanel = frappe.ui.form.Controller.extend({
|
||||
});
|
||||
},
|
||||
|
||||
show_upload: function() {
|
||||
var me = this;
|
||||
show_upload() {
|
||||
var $wrapper = $(cur_frm.fields_dict.upload_html.wrapper).empty();
|
||||
|
||||
// upload
|
||||
frappe.upload.make({
|
||||
parent: $wrapper,
|
||||
args: {
|
||||
method: 'erpnext.hr.doctype.upload_attendance.upload_attendance.upload'
|
||||
},
|
||||
no_socketio: true,
|
||||
sample_url: "e.g. http://example.com/somefile.csv",
|
||||
callback: function(attachment, r) {
|
||||
new frappe.ui.FileUploader({
|
||||
wrapper: $wrapper,
|
||||
method: 'erpnext.hr.doctype.upload_attendance.upload_attendance.upload',
|
||||
on_success(file_doc, r) {
|
||||
var $log_wrapper = $(cur_frm.fields_dict.import_log.wrapper).empty();
|
||||
|
||||
if(!r.messages) r.messages = [];
|
||||
@ -59,10 +52,10 @@ erpnext.hr.AttendanceControlPanel = frappe.ui.form.Controller.extend({
|
||||
});
|
||||
|
||||
r.messages = ["<h4 style='color:red'>"+__("Import Failed!")+"</h4>"]
|
||||
.concat(r.messages)
|
||||
.concat(r.messages);
|
||||
} else {
|
||||
r.messages = ["<h4 style='color:green'>"+__("Import Successful!")+"</h4>"].
|
||||
concat(r.message.messages)
|
||||
r.messages = ["<h4 style='color:green'>"+__("Import Successful!")+"</h4>"]
|
||||
.concat(r.message.messages);
|
||||
}
|
||||
|
||||
$.each(r.messages, function(i, v) {
|
||||
@ -79,11 +72,7 @@ erpnext.hr.AttendanceControlPanel = frappe.ui.form.Controller.extend({
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// rename button
|
||||
$wrapper.find('form input[type="submit"]')
|
||||
.attr('value', 'Upload and Import')
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
cur_frm.cscript = new erpnext.hr.AttendanceControlPanel({frm: cur_frm});
|
||||
|
@ -116,10 +116,10 @@ def upload():
|
||||
if not frappe.has_permission("Attendance", "create"):
|
||||
raise frappe.PermissionError
|
||||
|
||||
from frappe.utils.csvutils import read_csv_content_from_uploaded_file
|
||||
from frappe.utils.csvutils import read_csv_content
|
||||
from frappe.modules import scrub
|
||||
|
||||
rows = read_csv_content_from_uploaded_file()
|
||||
rows = read_csv_content(frappe.local.uploaded_file)
|
||||
rows = list(filter(lambda x: x and any(x), rows))
|
||||
if not rows:
|
||||
msg = [_("Please select a csv file")]
|
||||
|
@ -45,7 +45,8 @@ class EmployeeBoardingController(Document):
|
||||
"subject": activity.activity_name + " : " + self.employee_name,
|
||||
"description": activity.description,
|
||||
"department": self.department,
|
||||
"company": self.company
|
||||
"company": self.company,
|
||||
"task_weight": activity.task_weight
|
||||
}).insert(ignore_permissions=True)
|
||||
activity.db_set("task", task.name)
|
||||
users = [activity.user] if activity.user else []
|
||||
|
@ -620,7 +620,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
|
||||
is_stock_item=is_stock_item,
|
||||
qty_field="stock_qty",
|
||||
select_columns = """, bom_item.source_warehouse, bom_item.operation, bom_item.include_item_in_manufacturing,
|
||||
(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s ) as idx""")
|
||||
(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s limit 1) as idx""")
|
||||
|
||||
items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True)
|
||||
elif fetch_scrap_items:
|
||||
|
@ -32,6 +32,14 @@ frappe.ui.form.on("Work Order", {
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("sales_order", function() {
|
||||
return {
|
||||
filters: {
|
||||
"status": ["not in", ["Closed", "On Hold"]]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("fg_warehouse", function() {
|
||||
return {
|
||||
filters: {
|
||||
|
@ -56,6 +56,7 @@ class WorkOrder(Document):
|
||||
|
||||
def validate_sales_order(self):
|
||||
if self.sales_order:
|
||||
self.check_sales_order_on_hold_or_close()
|
||||
so = frappe.db.sql("""
|
||||
select so.name, so_item.delivery_date, so.project
|
||||
from `tabSales Order` so
|
||||
@ -91,6 +92,11 @@ class WorkOrder(Document):
|
||||
else:
|
||||
frappe.throw(_("Sales Order {0} is not valid").format(self.sales_order))
|
||||
|
||||
def check_sales_order_on_hold_or_close(self):
|
||||
status = frappe.db.get_value("Sales Order", self.sales_order, "status")
|
||||
if status in ("Closed", "On Hold"):
|
||||
frappe.throw(_("Sales Order {0} is {1}").format(self.sales_order, status))
|
||||
|
||||
def set_default_warehouse(self):
|
||||
if not self.wip_warehouse:
|
||||
self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
|
||||
|
@ -568,7 +568,7 @@ execute:frappe.delete_doc_if_exists("Page", "sales-analytics")
|
||||
execute:frappe.delete_doc_if_exists("Page", "purchase-analytics")
|
||||
execute:frappe.delete_doc_if_exists("Page", "stock-analytics")
|
||||
execute:frappe.delete_doc_if_exists("Page", "production-analytics")
|
||||
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09
|
||||
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09 #2019-04-01
|
||||
erpnext.patches.v11_0.drop_column_max_days_allowed
|
||||
erpnext.patches.v10_0.update_user_image_in_employee
|
||||
erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
|
||||
@ -595,3 +595,5 @@ erpnext.patches.v12_0.move_target_distribution_from_parent_to_child
|
||||
erpnext.patches.v12_0.stock_entry_enhancements
|
||||
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
|
||||
erpnext.patches.v12_0.move_item_tax_to_item_tax_template
|
||||
erpnext.patches.v11_1.set_variant_based_on
|
||||
erpnext.patches.v11_1.woocommerce_set_creation_user
|
||||
|
11
erpnext/patches/v11_1/set_variant_based_on.py
Normal file
11
erpnext/patches/v11_1/set_variant_based_on.py
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.db.sql("""update tabItem set variant_based_on = 'Item Attribute'
|
||||
where ifnull(variant_based_on, '') = ''
|
||||
and (has_variants=1 or ifnull(variant_of, '') != '')
|
||||
""")
|
10
erpnext/patches/v11_1/woocommerce_set_creation_user.py
Normal file
10
erpnext/patches/v11_1/woocommerce_set_creation_user.py
Normal file
@ -0,0 +1,10 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
woocommerce_setting_enable_sync = frappe.db.sql("SELECT t.value FROM tabSingles t WHERE doctype = 'Woocommerce Settings' AND field = 'enable_sync'", as_dict=True)
|
||||
if len(woocommerce_setting_enable_sync) and woocommerce_setting_enable_sync[0].value == '1':
|
||||
frappe.db.sql("""UPDATE tabSingles
|
||||
SET value = (SELECT t.value FROM tabSingles t WHERE doctype = 'Woocommerce Settings' AND field = 'modified_by')
|
||||
WHERE doctype = 'Woocommerce Settings'
|
||||
AND field = 'creation_user';""")
|
@ -39,6 +39,19 @@ class ItemVariantsCacheManager:
|
||||
|
||||
return frappe.cache().hget('optional_attributes', self.item_code)
|
||||
|
||||
def get_ordered_attribute_values(self):
|
||||
val = frappe.cache().get_value('ordered_attribute_values_map')
|
||||
if val: return val
|
||||
|
||||
all_attribute_values = frappe.db.get_all('Item Attribute Value',
|
||||
['attribute_value', 'idx', 'parent'], order_by='idx asc')
|
||||
|
||||
ordered_attribute_values_map = frappe._dict({})
|
||||
for d in all_attribute_values:
|
||||
ordered_attribute_values_map.setdefault(d.parent, []).append(d.attribute_value)
|
||||
|
||||
frappe.cache().set_value('ordered_attribute_values_map', ordered_attribute_values_map)
|
||||
return ordered_attribute_values_map
|
||||
|
||||
def build_cache(self):
|
||||
parent_item_code = self.item_code
|
||||
|
@ -167,8 +167,13 @@ def get_attributes_and_values(item_code):
|
||||
if attribute in attribute_list:
|
||||
valid_options.setdefault(attribute, set()).add(attribute_value)
|
||||
|
||||
# build attribute values in idx order
|
||||
ordered_attribute_value_map = item_cache.get_ordered_attribute_values()
|
||||
for attr in attributes:
|
||||
attr['values'] = valid_options.get(attr.attribute, [])
|
||||
valid_attribute_values = valid_options.get(attr.attribute, [])
|
||||
ordered_values = ordered_attribute_value_map.get(attr.attribute, [])
|
||||
attr['values'] = [v for v in ordered_values if v in valid_attribute_values]
|
||||
attr['values'] = valid_attribute_values
|
||||
|
||||
return attributes
|
||||
|
||||
|
@ -117,4 +117,4 @@ def create_task(subject, start=None, end=None, depends_on=None, project=None, sa
|
||||
if save:
|
||||
task.save()
|
||||
|
||||
return task
|
||||
return task
|
||||
|
@ -31,20 +31,20 @@ def get_columns():
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"label": _("Total Billable Hours"),
|
||||
"fieldtype": "Int",
|
||||
"label": _("Billable Hours"),
|
||||
"fieldtype": "Float",
|
||||
"fieldname": "total_billable_hours",
|
||||
"width": 50
|
||||
},
|
||||
{
|
||||
"label": _("Total Hours"),
|
||||
"fieldtype": "Int",
|
||||
"label": _("Working Hours"),
|
||||
"fieldtype": "Float",
|
||||
"fieldname": "total_hours",
|
||||
"width": 50
|
||||
},
|
||||
{
|
||||
"label": _("Amount"),
|
||||
"fieldtype": "Int",
|
||||
"fieldtype": "Currency",
|
||||
"fieldname": "amount",
|
||||
"width": 100
|
||||
}
|
||||
@ -54,6 +54,9 @@ def get_data(filters):
|
||||
data = []
|
||||
record = get_records(filters)
|
||||
|
||||
billable_hours_worked = 0
|
||||
hours_worked = 0
|
||||
working_cost = 0
|
||||
for entries in record:
|
||||
total_hours = 0
|
||||
total_billable_hours = 0
|
||||
@ -67,16 +70,28 @@ def get_data(filters):
|
||||
from_date = frappe.utils.get_datetime(filters.from_date)
|
||||
to_date = frappe.utils.get_datetime(filters.to_date)
|
||||
|
||||
if time_start <= from_date and time_end <= to_date:
|
||||
if time_start <= from_date and time_end >= from_date:
|
||||
total_hours, total_billable_hours, total_amount = get_billable_and_total_hours(activity,
|
||||
time_end, from_date, total_hours, total_billable_hours, total_amount)
|
||||
|
||||
billable_hours_worked += total_billable_hours
|
||||
hours_worked += total_hours
|
||||
working_cost += total_amount
|
||||
elif time_start >= from_date and time_end >= to_date:
|
||||
total_hours, total_billable_hours, total_amount = get_billable_and_total_hours(activity,
|
||||
to_date, time_start, total_hours, total_billable_hours, total_amount)
|
||||
|
||||
billable_hours_worked += total_billable_hours
|
||||
hours_worked += total_hours
|
||||
working_cost += total_amount
|
||||
elif time_start >= from_date and time_end <= to_date:
|
||||
total_hours, total_billable_hours, total_amount = get_billable_and_total_hours(activity,
|
||||
time_end, time_start, total_hours, total_billable_hours, total_amount)
|
||||
|
||||
billable_hours_worked += total_billable_hours
|
||||
hours_worked += total_hours
|
||||
working_cost += total_amount
|
||||
|
||||
row = {
|
||||
"employee": entries.employee,
|
||||
"employee_name": entries.employee_name,
|
||||
@ -90,12 +105,20 @@ def get_data(filters):
|
||||
data.append(row)
|
||||
entries_exists = False
|
||||
|
||||
total = {
|
||||
"total_billable_hours": billable_hours_worked,
|
||||
"total_hours": hours_worked,
|
||||
"amount": working_cost
|
||||
}
|
||||
if billable_hours_worked !=0 or hours_worked !=0 or working_cost !=0:
|
||||
data.append(total)
|
||||
return data
|
||||
|
||||
def get_records(filters):
|
||||
record_filters = [
|
||||
["start_date", "<=", filters.to_date],
|
||||
["end_date", ">=", filters.from_date]
|
||||
["end_date", ">=", filters.from_date],
|
||||
["docstatus", "=", 1]
|
||||
]
|
||||
|
||||
if "employee" in filters:
|
||||
|
@ -15,14 +15,14 @@ frappe.query_reports["Employee Billing Summary"] = {
|
||||
fieldname:"from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.get_today(),
|
||||
default: frappe.datetime.add_months(frappe.datetime.month_start(), -1),
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname:"to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.add_days(frappe.datetime.get_today(), 30),
|
||||
default: frappe.datetime.add_days(frappe.datetime.month_start(), -1),
|
||||
reqd: 1
|
||||
},
|
||||
]
|
||||
|
@ -15,14 +15,14 @@ frappe.query_reports["Project Billing Summary"] = {
|
||||
fieldname:"from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.get_today(),
|
||||
default: frappe.datetime.add_months(frappe.datetime.month_start(), -1),
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname:"to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.add_days(frappe.datetime.get_today(), 30),
|
||||
default: frappe.datetime.add_days(frappe.datetime.month_start(),-1),
|
||||
reqd: 1
|
||||
},
|
||||
]
|
||||
|
26
erpnext/public/images/erpnext-12.svg
Normal file
26
erpnext/public/images/erpnext-12.svg
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="165px" height="88px" viewBox="0 0 165 88" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 44.1 (41455) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>version-12</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="version-12" transform="translate(-2.000000, -2.000000)">
|
||||
<g id="erp-icon" fill-rule="nonzero">
|
||||
<g id="g1422-7-2" transform="translate(0.025630, 0.428785)" fill="#5E64FF">
|
||||
<g id="g1418-4-6" transform="translate(0.268998, 0.867736)">
|
||||
<g id="g1416-4-9" transform="translate(0.749997, 0.000000)">
|
||||
<path d="M14.1845844,0.703479866 L75.0387175,0.703479866 C82.3677094,0.703479866 88.2679029,6.60367875 88.2679029,13.9326374 L88.2679029,74.7868158 C88.2679029,82.1157744 82.3677094,88.0159833 75.0387175,88.0159833 L14.1845844,88.0159833 C6.85569246,88.0159833 0.955398949,82.1157744 0.955398949,74.7868158 L0.955398949,13.9326374 C0.955398949,6.60367875 6.85569246,0.703479866 14.1845844,0.703479866 L14.1845844,0.703479866 Z" id="path1414-3-4"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="g1444-6-7" transform="translate(27.708247, 23.320960)" fill="#FFFFFF">
|
||||
<path d="M4.06942472,0.507006595 C3.79457554,0.507006595 3.52673783,0.534925429 3.26792241,0.587619847 C3.00908052,0.640314265 2.75926093,0.717948309 2.52171801,0.818098395 C2.40292009,0.868173438 2.28745592,0.924056085 2.17495509,0.985013441 C1.94997987,1.10692286 1.73828674,1.24983755 1.54244215,1.41134187 C0.661062132,2.13811791 0.100674618,3.23899362 0.100674618,4.4757567 L0.100674618,4.71760174 L0.100674618,39.9531653 L0.100674618,40.1945182 C0.100674618,42.3932057 1.87073716,44.1632683 4.06942472,44.1632683 L31.8263867,44.1632683 C34.0250742,44.1632683 35.7951368,42.3932057 35.7951368,40.1945182 L35.7951368,39.9531653 C35.7951368,37.7544777 34.0250742,35.9844152 31.8263867,35.9844152 L8.28000399,35.9844152 L8.28000399,26.0992376 L25.7874571,26.0992376 C27.9861447,26.0992376 29.7562072,24.3291751 29.7562072,22.1304875 L29.7562072,21.8891611 C29.7562072,19.6904735 27.9861447,17.920411 25.7874571,17.920411 L8.28000399,17.920411 L8.28000399,8.68635184 L31.8263867,8.68635184 C34.0250742,8.68635184 35.7951368,6.9162893 35.7951368,4.71760174 L35.7951368,4.4757567 C35.7951368,2.27706914 34.0250742,0.507006595 31.8263867,0.507006595 L4.06942472,0.507006595 Z" id="rect1436-8-4"></path>
|
||||
</g>
|
||||
</g>
|
||||
<text id="12" font-family="SourceSansPro-Regular, Source Sans Pro" font-size="72" font-weight="normal" letter-spacing="-0.386831313" fill="#D1D8DD">
|
||||
<tspan x="99" y="71">12</tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
@ -1389,14 +1389,17 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
args: {
|
||||
"master_doctype": frappe.meta.get_docfield(this.frm.doc.doctype, "taxes_and_charges",
|
||||
this.frm.doc.name).options,
|
||||
"master_name": this.frm.doc.taxes_and_charges,
|
||||
"master_name": this.frm.doc.taxes_and_charges
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
for (let tax of r.message) {
|
||||
me.frm.add_child("taxes", tax);
|
||||
me.frm.set_value("taxes", r.message);
|
||||
|
||||
if(me.frm.doc.shipping_rule) {
|
||||
me.frm.script_manager.trigger("shipping_rule");
|
||||
} else {
|
||||
me.calculate_taxes_and_totals();
|
||||
}
|
||||
me.calculate_taxes_and_totals();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -31,7 +31,7 @@
|
||||
<base-image :src="image" :alt="title" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="col-md-8" style='padding-left: 30px;'>
|
||||
<h2>{{ title }}</h2>
|
||||
<div class="text-muted">
|
||||
<slot name="detail-header-item"></slot>
|
||||
|
@ -111,21 +111,21 @@
|
||||
<tr>
|
||||
<td>{{__("Suppliies made to Composition Taxable Persons")}}</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.unreg_details %}
|
||||
{% for row in data.inter_sup.comp_details %}
|
||||
{% if row %}
|
||||
{{ row.pos }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.unreg_details %}
|
||||
{% for row in data.inter_sup.comp_details %}
|
||||
{% if row %}
|
||||
{{ flt(row.txval, 2) }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.unreg_details %}
|
||||
{% for row in data.inter_sup.comp_details %}
|
||||
{% if row %}
|
||||
{{ flt(row.iamt, 2) }}<br>
|
||||
{% endif %}
|
||||
@ -135,21 +135,21 @@
|
||||
<tr>
|
||||
<td>{{__("Supplies made to UIN holders")}}</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.unreg_details %}
|
||||
{% for row in data.inter_sup.uin_details %}
|
||||
{% if row %}
|
||||
{{ row.pos }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.unreg_details %}
|
||||
{% for row in data.inter_sup.uin_details %}
|
||||
{% if row %}
|
||||
{{ flt(row.txval, 2) }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="right">
|
||||
{% for row in data.inter_sup.unreg_details %}
|
||||
{% for row in data.inter_sup.uin_details %}
|
||||
{% if row %}
|
||||
{{ flt(row.iamt, 2) }}<br>
|
||||
{% endif %}
|
||||
|
@ -93,7 +93,7 @@ def add_print_formats():
|
||||
def make_custom_fields(update=True):
|
||||
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
|
||||
fieldtype='Data', fetch_from='item_code.gst_hsn_code', insert_after='description',
|
||||
allow_on_submit=1, print_hide=1)
|
||||
allow_on_submit=1, print_hide=1, fetch_if_empty=1)
|
||||
nil_rated_exempt = dict(fieldname='is_nil_exempt', label='Is nil rated or exempted',
|
||||
fieldtype='Check', fetch_from='item_code.is_nil_exempt', insert_after='gst_hsn_code',
|
||||
print_hide=1)
|
||||
|
@ -184,11 +184,7 @@
|
||||
<UnitaMisura>{{ item.stock_uom }}</UnitaMisura>
|
||||
<PrezzoUnitario>{{ format_float(item.price_list_rate or item.rate) }}</PrezzoUnitario>
|
||||
{{ render_discount_or_margin(item) }}
|
||||
{%- if (item.discount_amount or item.rate_with_margin) %}
|
||||
<PrezzoTotale>{{ format_float(item.net_amount) }}</PrezzoTotale>
|
||||
{%- else %}
|
||||
<PrezzoTotale>{{ format_float(item.amount) }}</PrezzoTotale>
|
||||
{%- endif %}
|
||||
<PrezzoTotale>{{ format_float(item.amount) }}</PrezzoTotale>
|
||||
<AliquotaIVA>{{ format_float(item.tax_rate) }}</AliquotaIVA>
|
||||
{%- if item.tax_exemption_reason %}
|
||||
<Natura>{{ item.tax_exemption_reason.split("-")[0] }}</Natura>
|
||||
|
@ -22,6 +22,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "basic_info",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -56,6 +57,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@ -89,6 +91,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.customer_type!='Company'",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "salutation",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -122,6 +125,7 @@
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@ -156,6 +160,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.customer_type != 'Company'",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "gender",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -190,6 +195,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Company",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@ -224,6 +230,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "default_bank_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -257,6 +264,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "lead_name",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -291,6 +299,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "image",
|
||||
"fieldtype": "Attach Image",
|
||||
"hidden": 1,
|
||||
@ -323,6 +332,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break0",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -347,6 +357,40 @@
|
||||
"unique": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "account_manager",
|
||||
"fieldtype": "Link",
|
||||
"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": "Account Manager",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@ -355,6 +399,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_group",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -390,6 +435,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -424,6 +470,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "tax_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@ -456,6 +503,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "tax_category",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -490,6 +538,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@ -523,6 +572,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "is_internal_customer",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@ -556,6 +606,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "is_internal_customer",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "represents_company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -590,6 +641,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "represents_company",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "allowed_to_transact_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -623,6 +675,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "represents_company",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "companies",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@ -656,6 +709,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "currency_and_price_list",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -688,6 +742,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "default_currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -720,6 +775,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "default_price_list",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -752,6 +808,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_14",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -783,6 +840,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "language",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -817,6 +875,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "address_contacts",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -849,6 +908,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "address_html",
|
||||
"fieldtype": "HTML",
|
||||
"hidden": 0,
|
||||
@ -880,6 +940,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "website",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@ -911,6 +972,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -942,6 +1004,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "contact_html",
|
||||
"fieldtype": "HTML",
|
||||
"hidden": 0,
|
||||
@ -975,6 +1038,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Select, to make the customer searchable with these fields",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "primary_address_and_contact_detail",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -1008,6 +1072,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Reselect, if the chosen contact is edited after save",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_primary_contact",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1042,6 +1107,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "customer_primary_contact.mobile_no",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "mobile_no",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
@ -1076,6 +1142,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "customer_primary_contact.email_id",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "email_id",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
@ -1109,6 +1176,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_26",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -1141,6 +1209,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Reselect, if the chosen address is edited after save",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_primary_address",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1175,6 +1244,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "primary_address",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
@ -1209,6 +1279,7 @@
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "",
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "default_receivable_accounts",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -1242,6 +1313,7 @@
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"description": "Mention if non-standard receivable account",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "accounts",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@ -1275,6 +1347,7 @@
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "",
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "credit_limit_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -1307,6 +1380,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "credit_limit",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@ -1342,6 +1416,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "bypass_credit_limit_check_at_sales_order",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@ -1374,6 +1449,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_34",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -1406,6 +1482,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "payment_terms",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1440,6 +1517,7 @@
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "customer_details",
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "more_info",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -1474,6 +1552,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Additional information regarding the customer.",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_details",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
@ -1507,6 +1586,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_45",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@ -1538,6 +1618,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "market_segment",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1571,6 +1652,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "industry",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1604,6 +1686,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "is_frozen",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@ -1636,6 +1719,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_38",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -1668,6 +1752,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "loyalty_program",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1701,6 +1786,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "loyalty_program_tier",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@ -1734,6 +1820,7 @@
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "default_sales_partner",
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "sales_team_section_break",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -1767,6 +1854,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "default_sales_partner",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1801,6 +1889,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "default_commission_rate",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@ -1835,6 +1924,7 @@
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "sales_team",
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "sales_team_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -1867,6 +1957,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "sales_team",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@ -1901,6 +1992,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_pos_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@ -1928,18 +2020,17 @@
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-user",
|
||||
"idx": 363,
|
||||
"image_field": "image",
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-01-17 13:10:24.360876",
|
||||
"menu_index": 0,
|
||||
"modified": "2019-04-12 08:45:39.357491",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Customer",
|
||||
@ -2120,7 +2211,6 @@
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"search_fields": "customer_name,customer_group,territory, mobile_no,primary_address",
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_order": "ASC",
|
||||
@ -2128,4 +2218,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
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