Merge branch 'develop' into quoted-item-report
This commit is contained in:
commit
b8011197d9
17
.travis.yml
17
.travis.yml
@ -1,6 +1,5 @@
|
|||||||
dist: trusty
|
|
||||||
|
|
||||||
language: python
|
language: python
|
||||||
|
dist: trusty
|
||||||
|
|
||||||
git:
|
git:
|
||||||
depth: 1
|
depth: 1
|
||||||
@ -14,21 +13,10 @@ addons:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- name: "Python 2.7 Server Side Test"
|
|
||||||
python: 2.7
|
|
||||||
script: bench --site test_site run-tests --app erpnext --coverage
|
|
||||||
|
|
||||||
- name: "Python 3.6 Server Side Test"
|
- name: "Python 3.6 Server Side Test"
|
||||||
python: 3.6
|
python: 3.6
|
||||||
script: bench --site test_site run-tests --app erpnext --coverage
|
script: bench --site test_site run-tests --app erpnext --coverage
|
||||||
|
|
||||||
- name: "Python 2.7 Patch Test"
|
|
||||||
python: 2.7
|
|
||||||
before_script:
|
|
||||||
- wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz
|
|
||||||
- bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz
|
|
||||||
script: bench --site test_site migrate
|
|
||||||
|
|
||||||
- name: "Python 3.6 Patch Test"
|
- name: "Python 3.6 Patch Test"
|
||||||
python: 3.6
|
python: 3.6
|
||||||
before_script:
|
before_script:
|
||||||
@ -40,8 +28,7 @@ install:
|
|||||||
- cd ~
|
- cd ~
|
||||||
- nvm install 10
|
- nvm install 10
|
||||||
|
|
||||||
- git clone https://github.com/frappe/bench --depth 1
|
- pip install frappe-bench
|
||||||
- pip install -e ./bench
|
|
||||||
|
|
||||||
- git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1
|
- git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1
|
||||||
- bench init --skip-assets --frappe-path ~/frappe --python $(which python) frappe-bench
|
- bench init --skip-assets --frappe-path ~/frappe --python $(which python) frappe-bench
|
||||||
|
|||||||
@ -14,7 +14,7 @@ from frappe.utils.nestedset import get_descendants_of
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@cache_source
|
@cache_source
|
||||||
def get(chart_name = None, chart = None, no_cache = None, filters = None, from_date = None,
|
def get(chart_name = None, chart = None, no_cache = None, filters = None, from_date = None,
|
||||||
to_date = None, timespan = None, time_interval = None):
|
to_date = None, timespan = None, time_interval = None, heatmap_year = None):
|
||||||
if chart_name:
|
if chart_name:
|
||||||
chart = frappe.get_doc('Dashboard Chart', chart_name)
|
chart = frappe.get_doc('Dashboard Chart', chart_name)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -1,15 +1,22 @@
|
|||||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
from erpnext import get_default_company
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
def get_data():
|
def get_data():
|
||||||
return frappe._dict({
|
data = frappe._dict({
|
||||||
"dashboards": get_dashboards(),
|
"dashboards": [],
|
||||||
"charts": get_charts(),
|
"charts": []
|
||||||
})
|
})
|
||||||
|
company = get_company_for_dashboards()
|
||||||
|
if company:
|
||||||
|
company_doc = frappe.get_doc("Company", company)
|
||||||
|
data.dashboards = get_dashboards()
|
||||||
|
data.charts = get_charts(company_doc)
|
||||||
|
return data
|
||||||
|
|
||||||
def get_dashboards():
|
def get_dashboards():
|
||||||
return [{
|
return [{
|
||||||
@ -24,88 +31,87 @@ def get_dashboards():
|
|||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def get_charts():
|
def get_charts(company):
|
||||||
company = frappe.get_doc("Company", get_company_for_dashboards())
|
|
||||||
income_account = company.default_income_account or get_account("Income Account", company.name)
|
income_account = company.default_income_account or get_account("Income Account", company.name)
|
||||||
expense_account = company.default_expense_account or get_account("Expense Account", company.name)
|
expense_account = company.default_expense_account or get_account("Expense Account", company.name)
|
||||||
bank_account = company.default_bank_account or get_account("Bank", company.name)
|
bank_account = company.default_bank_account or get_account("Bank", company.name)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"doctype": "Dashboard Chart",
|
"doctype": "Dashboard Chart",
|
||||||
"time_interval": "Quarterly",
|
"time_interval": "Quarterly",
|
||||||
"name": "Income",
|
"name": "Income",
|
||||||
"chart_name": "Income",
|
"chart_name": "Income",
|
||||||
"timespan": "Last Year",
|
"timespan": "Last Year",
|
||||||
"color": None,
|
"color": None,
|
||||||
"filters_json": json.dumps({"company": company.name, "account": income_account}),
|
"filters_json": json.dumps({"company": company.name, "account": income_account}),
|
||||||
"source": "Account Balance Timeline",
|
"source": "Account Balance Timeline",
|
||||||
"chart_type": "Custom",
|
"chart_type": "Custom",
|
||||||
"timeseries": 1,
|
"timeseries": 1,
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"type": "Line"
|
"type": "Line"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Dashboard Chart",
|
"doctype": "Dashboard Chart",
|
||||||
"time_interval": "Quarterly",
|
"time_interval": "Quarterly",
|
||||||
"name": "Expenses",
|
"name": "Expenses",
|
||||||
"chart_name": "Expenses",
|
"chart_name": "Expenses",
|
||||||
"timespan": "Last Year",
|
"timespan": "Last Year",
|
||||||
"color": None,
|
"color": None,
|
||||||
"filters_json": json.dumps({"company": company.name, "account": expense_account}),
|
"filters_json": json.dumps({"company": company.name, "account": expense_account}),
|
||||||
"source": "Account Balance Timeline",
|
"source": "Account Balance Timeline",
|
||||||
"chart_type": "Custom",
|
"chart_type": "Custom",
|
||||||
"timeseries": 1,
|
"timeseries": 1,
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"type": "Line"
|
"type": "Line"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Dashboard Chart",
|
"doctype": "Dashboard Chart",
|
||||||
"time_interval": "Quarterly",
|
"time_interval": "Quarterly",
|
||||||
"name": "Bank Balance",
|
"name": "Bank Balance",
|
||||||
"chart_name": "Bank Balance",
|
"chart_name": "Bank Balance",
|
||||||
"timespan": "Last Year",
|
"timespan": "Last Year",
|
||||||
"color": "#ffb868",
|
"color": "#ffb868",
|
||||||
"filters_json": json.dumps({"company": company.name, "account": bank_account}),
|
"filters_json": json.dumps({"company": company.name, "account": bank_account}),
|
||||||
"source": "Account Balance Timeline",
|
"source": "Account Balance Timeline",
|
||||||
"chart_type": "Custom",
|
"chart_type": "Custom",
|
||||||
"timeseries": 1,
|
"timeseries": 1,
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"type": "Line"
|
"type": "Line"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Dashboard Chart",
|
"doctype": "Dashboard Chart",
|
||||||
"time_interval": "Monthly",
|
"time_interval": "Monthly",
|
||||||
"name": "Incoming Bills (Purchase Invoice)",
|
"name": "Incoming Bills (Purchase Invoice)",
|
||||||
"chart_name": "Incoming Bills (Purchase Invoice)",
|
"chart_name": "Incoming Bills (Purchase Invoice)",
|
||||||
"timespan": "Last Year",
|
"timespan": "Last Year",
|
||||||
"color": "#a83333",
|
"color": "#a83333",
|
||||||
"value_based_on": "base_grand_total",
|
"value_based_on": "base_grand_total",
|
||||||
"filters_json": json.dumps({}),
|
"filters_json": json.dumps({}),
|
||||||
"chart_type": "Sum",
|
"chart_type": "Sum",
|
||||||
"timeseries": 1,
|
"timeseries": 1,
|
||||||
"based_on": "posting_date",
|
"based_on": "posting_date",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"document_type": "Purchase Invoice",
|
"document_type": "Purchase Invoice",
|
||||||
"type": "Bar"
|
"type": "Bar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Dashboard Chart",
|
"doctype": "Dashboard Chart",
|
||||||
"time_interval": "Monthly",
|
"time_interval": "Monthly",
|
||||||
"name": "Outgoing Bills (Sales Invoice)",
|
"name": "Outgoing Bills (Sales Invoice)",
|
||||||
"chart_name": "Outgoing Bills (Sales Invoice)",
|
"chart_name": "Outgoing Bills (Sales Invoice)",
|
||||||
"timespan": "Last Year",
|
"timespan": "Last Year",
|
||||||
"color": "#7b933d",
|
"color": "#7b933d",
|
||||||
"value_based_on": "base_grand_total",
|
"value_based_on": "base_grand_total",
|
||||||
"filters_json": json.dumps({}),
|
"filters_json": json.dumps({}),
|
||||||
"chart_type": "Sum",
|
"chart_type": "Sum",
|
||||||
"timeseries": 1,
|
"timeseries": 1,
|
||||||
"based_on": "posting_date",
|
"based_on": "posting_date",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"document_type": "Sales Invoice",
|
"document_type": "Sales Invoice",
|
||||||
"type": "Bar"
|
"type": "Bar"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_account(account_type, company):
|
def get_account(account_type, company):
|
||||||
accounts = frappe.get_list("Account", filters={"account_type": account_type, "company": company})
|
accounts = frappe.get_list("Account", filters={"account_type": account_type, "company": company})
|
||||||
@ -113,11 +119,9 @@ def get_account(account_type, company):
|
|||||||
return accounts[0].name
|
return accounts[0].name
|
||||||
|
|
||||||
def get_company_for_dashboards():
|
def get_company_for_dashboards():
|
||||||
company = frappe.defaults.get_defaults().company
|
company = get_default_company()
|
||||||
if company:
|
if not company:
|
||||||
return company
|
|
||||||
else:
|
|
||||||
company_list = frappe.get_list("Company")
|
company_list = frappe.get_list("Company")
|
||||||
if company_list:
|
if company_list:
|
||||||
return company_list[0].name
|
company = company_list[0].name
|
||||||
return None
|
return company
|
||||||
|
|||||||
@ -53,7 +53,7 @@ frappe.query_reports["General Ledger"] = {
|
|||||||
"label": __("Voucher No"),
|
"label": __("Voucher No"),
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
on_change: function() {
|
on_change: function() {
|
||||||
frappe.query_report.set_filter_value('group_by', "");
|
frappe.query_report.set_filter_value('group_by', "Group by Voucher (Consolidated)");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -141,7 +141,7 @@
|
|||||||
],
|
],
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-03-18 18:00:08.885805",
|
"modified": "2020-05-08 16:11:11.375701",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Assets",
|
"module": "Assets",
|
||||||
"name": "Location",
|
"name": "Location",
|
||||||
@ -221,7 +221,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"restrict_to_domain": "Agriculture",
|
|
||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class LinkedInSettings(Document):
|
|||||||
params = urlencode({
|
params = urlencode({
|
||||||
"response_type":"code",
|
"response_type":"code",
|
||||||
"client_id": self.consumer_key,
|
"client_id": self.consumer_key,
|
||||||
"redirect_uri": get_site_url(frappe.local.site) + "/api/method/erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback?",
|
"redirect_uri": "{0}/api/method/erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback?".format(frappe.utils.get_url()),
|
||||||
"scope": "r_emailaddress w_organization_social r_basicprofile r_liteprofile r_organization_social rw_organization_admin w_member_social"
|
"scope": "r_emailaddress w_organization_social r_basicprofile r_liteprofile r_organization_social rw_organization_admin w_member_social"
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ class LinkedInSettings(Document):
|
|||||||
"code": code,
|
"code": code,
|
||||||
"client_id": self.consumer_key,
|
"client_id": self.consumer_key,
|
||||||
"client_secret": self.get_password(fieldname="consumer_secret"),
|
"client_secret": self.get_password(fieldname="consumer_secret"),
|
||||||
"redirect_uri": get_site_url(frappe.local.site) + "/api/method/erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback?",
|
"redirect_uri": "{0}/api/method/erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback?".format(frappe.utils.get_url()),
|
||||||
}
|
}
|
||||||
headers = {
|
headers = {
|
||||||
"Content-Type": "application/x-www-form-urlencoded"
|
"Content-Type": "application/x-www-form-urlencoded"
|
||||||
|
|||||||
@ -11,8 +11,8 @@
|
|||||||
"consumer_key",
|
"consumer_key",
|
||||||
"column_break_5",
|
"column_break_5",
|
||||||
"consumer_secret",
|
"consumer_secret",
|
||||||
"oauth_token",
|
"access_token",
|
||||||
"oauth_secret",
|
"access_token_secret",
|
||||||
"session_status"
|
"session_status"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@ -41,20 +41,6 @@
|
|||||||
"label": "API Secret Key",
|
"label": "API Secret Key",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "oauth_token",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 1,
|
|
||||||
"label": "OAuth Token",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "oauth_secret",
|
|
||||||
"fieldtype": "Password",
|
|
||||||
"hidden": 1,
|
|
||||||
"label": "OAuth Token Secret",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_5",
|
"fieldname": "column_break_5",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
@ -72,12 +58,26 @@
|
|||||||
"label": "Session Status",
|
"label": "Session Status",
|
||||||
"options": "Expired\nActive",
|
"options": "Expired\nActive",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "access_token",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Access Token",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "access_token_secret",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Access Token Secret",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"image_field": "profile_pic",
|
"image_field": "profile_pic",
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-21 22:06:43.726798",
|
"modified": "2020-05-13 17:50:47.934776",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "CRM",
|
"module": "CRM",
|
||||||
"name": "Twitter Settings",
|
"name": "Twitter Settings",
|
||||||
|
|||||||
@ -31,13 +31,13 @@ class TwitterSettings(Document):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
auth.get_access_token(oauth_verifier)
|
auth.get_access_token(oauth_verifier)
|
||||||
api = self.get_api()
|
api = self.get_api(auth.access_token, auth.access_token_secret)
|
||||||
user = api.me()
|
user = api.me()
|
||||||
profile_pic = (user._json["profile_image_url"]).replace("_normal","")
|
profile_pic = (user._json["profile_image_url"]).replace("_normal","")
|
||||||
|
|
||||||
frappe.db.set_value(self.doctype, self.name, {
|
frappe.db.set_value(self.doctype, self.name, {
|
||||||
"oauth_token" : auth.access_token,
|
"access_token" : auth.access_token,
|
||||||
"oauth_secret" : auth.access_token_secret,
|
"access_token_secret" : auth.access_token_secret,
|
||||||
"account_name" : user._json["screen_name"],
|
"account_name" : user._json["screen_name"],
|
||||||
"profile_pic" : profile_pic,
|
"profile_pic" : profile_pic,
|
||||||
"session_status" : "Active"
|
"session_status" : "Active"
|
||||||
@ -49,11 +49,11 @@ class TwitterSettings(Document):
|
|||||||
frappe.msgprint(_("Error! Failed to get access token."))
|
frappe.msgprint(_("Error! Failed to get access token."))
|
||||||
frappe.throw(_('Invalid Consumer Key or Consumer Secret Key'))
|
frappe.throw(_('Invalid Consumer Key or Consumer Secret Key'))
|
||||||
|
|
||||||
def get_api(self):
|
def get_api(self, access_token, access_token_secret):
|
||||||
# authentication of consumer key and secret
|
# authentication of consumer key and secret
|
||||||
auth = tweepy.OAuthHandler(self.consumer_key, self.get_password(fieldname="consumer_secret"))
|
auth = tweepy.OAuthHandler(self.consumer_key, self.get_password(fieldname="consumer_secret"))
|
||||||
# authentication of access token and secret
|
# authentication of access token and secret
|
||||||
auth.set_access_token(self.oauth_token, self.get_password(fieldname="oauth_secret"))
|
auth.set_access_token(access_token, access_token_secret)
|
||||||
|
|
||||||
return tweepy.API(auth)
|
return tweepy.API(auth)
|
||||||
|
|
||||||
@ -67,13 +67,13 @@ class TwitterSettings(Document):
|
|||||||
|
|
||||||
def upload_image(self, media):
|
def upload_image(self, media):
|
||||||
media = get_file_path(media)
|
media = get_file_path(media)
|
||||||
api = self.get_api()
|
api = self.get_api(self.access_token, self.access_token_secret)
|
||||||
media = api.media_upload(media)
|
media = api.media_upload(media)
|
||||||
|
|
||||||
return media.media_id
|
return media.media_id
|
||||||
|
|
||||||
def send_tweet(self, text, media_id=None):
|
def send_tweet(self, text, media_id=None):
|
||||||
api = self.get_api()
|
api = self.get_api(self.access_token, self.access_token_secret)
|
||||||
try:
|
try:
|
||||||
if media_id:
|
if media_id:
|
||||||
response = api.update_status(status = text, media_ids = [media_id])
|
response = api.update_status(status = text, media_ids = [media_id])
|
||||||
|
|||||||
@ -38,7 +38,7 @@ class LoanSecurityPledge(Document):
|
|||||||
for pledge in self.securities:
|
for pledge in self.securities:
|
||||||
|
|
||||||
if not pledge.qty and not pledge.amount:
|
if not pledge.qty and not pledge.amount:
|
||||||
frappe.throw(_("Qty or Amount is mandatroy for loan security"))
|
frappe.throw(_("Qty or Amount is mandatory for loan security!"))
|
||||||
|
|
||||||
if not (self.loan_application and pledge.loan_security_price):
|
if not (self.loan_application and pledge.loan_security_price):
|
||||||
pledge.loan_security_price = get_loan_security_price(pledge.loan_security)
|
pledge.loan_security_price = get_loan_security_price(pledge.loan_security)
|
||||||
|
|||||||
@ -680,4 +680,6 @@ erpnext.patches.v12_0.update_appointment_reminder_scheduler_entry
|
|||||||
erpnext.patches.v12_0.retain_permission_rules_for_video_doctype
|
erpnext.patches.v12_0.retain_permission_rules_for_video_doctype
|
||||||
erpnext.patches.v13_0.patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive
|
erpnext.patches.v13_0.patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive
|
||||||
execute:frappe.delete_doc_if_exists("Page", "appointment-analytic")
|
execute:frappe.delete_doc_if_exists("Page", "appointment-analytic")
|
||||||
|
execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True)
|
||||||
|
erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price
|
||||||
erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation
|
erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation
|
||||||
@ -1,8 +1,9 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
hr_settings = frappe.get_single("HR Settings")
|
hr_settings = frappe.get_single("HR Settings")
|
||||||
hr_settings.leave_approval_notification_template = "Leave Approval Notification"
|
hr_settings.leave_approval_notification_template = _("Leave Approval Notification")
|
||||||
hr_settings.leave_status_notification_template = "Leave Status Notification"
|
hr_settings.leave_status_notification_template = _("Leave Status Notification")
|
||||||
hr_settings.save()
|
hr_settings.save()
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
invalid_selling_item_price = frappe.db.sql(
|
||||||
|
"""SELECT name FROM `tabItem Price` WHERE selling = 1 and buying = 0 and (supplier IS NOT NULL or supplier = '')"""
|
||||||
|
)
|
||||||
|
invalid_buying_item_price = frappe.db.sql(
|
||||||
|
"""SELECT name FROM `tabItem Price` WHERE selling = 0 and buying = 1 and (customer IS NOT NULL or customer = '')"""
|
||||||
|
)
|
||||||
|
docs_to_modify = invalid_buying_item_price + invalid_selling_item_price
|
||||||
|
for d in docs_to_modify:
|
||||||
|
# saving the doc will auto reset invalid customer/supplier field
|
||||||
|
doc = frappe.get_doc("Item Price", d[0])
|
||||||
|
doc.save()
|
||||||
@ -7,7 +7,7 @@ import frappe
|
|||||||
from frappe.model.utils.rename_field import rename_field
|
from frappe.model.utils.rename_field import rename_field
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
if not frappe.db.table_exists("Payroll Period"):
|
if not (frappe.db.table_exists("Payroll Period") and frappe.db.table_exists("Taxable Salary Slab")):
|
||||||
return
|
return
|
||||||
|
|
||||||
for doctype in ("income_tax_slab", "salary_structure_assignment", "employee_other_income", "income_tax_slab_other_charges"):
|
for doctype in ("income_tax_slab", "salary_structure_assignment", "employee_other_income", "income_tax_slab_other_charges"):
|
||||||
@ -60,6 +60,9 @@ def execute():
|
|||||||
""", (income_tax_slab.name, company.name, period.start_date))
|
""", (income_tax_slab.name, company.name, period.start_date))
|
||||||
|
|
||||||
# move other incomes to separate document
|
# move other incomes to separate document
|
||||||
|
if not frappe.db.table_exists("Employee Tax Exemption Proof Submission"):
|
||||||
|
return
|
||||||
|
|
||||||
migrated = []
|
migrated = []
|
||||||
proofs = frappe.get_all("Employee Tax Exemption Proof Submission",
|
proofs = frappe.get_all("Employee Tax Exemption Proof Submission",
|
||||||
filters = {'docstatus': 1},
|
filters = {'docstatus': 1},
|
||||||
@ -79,6 +82,9 @@ def execute():
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if not frappe.db.table_exists("Employee Tax Exemption Declaration"):
|
||||||
|
return
|
||||||
|
|
||||||
declerations = frappe.get_all("Employee Tax Exemption Declaration",
|
declerations = frappe.get_all("Employee Tax Exemption Declaration",
|
||||||
filters = {'docstatus': 1},
|
filters = {'docstatus': 1},
|
||||||
fields =['payroll_period', 'employee', 'company', 'income_from_other_sources']
|
fields =['payroll_period', 'employee', 'company', 'income_from_other_sources']
|
||||||
|
|||||||
@ -165,6 +165,10 @@ class Customer(TransactionBase):
|
|||||||
contact.mobile_no = lead.mobile_no
|
contact.mobile_no = lead.mobile_no
|
||||||
contact.is_primary_contact = 1
|
contact.is_primary_contact = 1
|
||||||
contact.append('links', dict(link_doctype='Customer', link_name=self.name))
|
contact.append('links', dict(link_doctype='Customer', link_name=self.name))
|
||||||
|
if lead.email_id:
|
||||||
|
contact.append('email_ids', dict(email_id=lead.email_id, is_primary=1))
|
||||||
|
if lead.mobile_no:
|
||||||
|
contact.append('phone_nos', dict(phone=lead.mobile_no, is_primary_mobile_no=1))
|
||||||
contact.flags.ignore_permissions = self.flags.ignore_permissions
|
contact.flags.ignore_permissions = self.flags.ignore_permissions
|
||||||
contact.autoname()
|
contact.autoname()
|
||||||
if not frappe.db.exists("Contact", contact.name):
|
if not frappe.db.exists("Contact", contact.name):
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
|
|
||||||
frappe.query_reports["Customer Acquisition and Loyalty"] = {
|
frappe.query_reports["Customer Acquisition and Loyalty"] = {
|
||||||
"filters": [
|
"filters": [
|
||||||
|
{
|
||||||
|
"fieldname": "view_type",
|
||||||
|
"label": __("View Type"),
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": ["Monthly", "Territory Wise"],
|
||||||
|
"default": "Monthly",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"company",
|
"fieldname":"company",
|
||||||
"label": __("Company"),
|
"label": __("Company"),
|
||||||
@ -24,6 +32,13 @@ frappe.query_reports["Customer Acquisition and Loyalty"] = {
|
|||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"default": frappe.defaults.get_user_default("year_end_date"),
|
"default": frappe.defaults.get_user_default("year_end_date"),
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
}
|
||||||
]
|
],
|
||||||
|
'formatter': function(value, row, column, data, default_formatter) {
|
||||||
|
value = default_formatter(value, row, column, data);
|
||||||
|
if (data && data.bold) {
|
||||||
|
value = value.bold();
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -2,65 +2,186 @@
|
|||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
import calendar
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import getdate, cint, cstr
|
from frappe.utils import cint, cstr
|
||||||
import calendar
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
# key yyyy-mm
|
common_columns = [
|
||||||
new_customers_in = {}
|
{
|
||||||
repeat_customers_in = {}
|
'label': _('New Customers'),
|
||||||
customers = []
|
'fieldname': 'new_customers',
|
||||||
company_condition = ""
|
'fieldtype': 'Int',
|
||||||
|
'default': 0,
|
||||||
|
'width': 125
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Repeat Customers'),
|
||||||
|
'fieldname': 'repeat_customers',
|
||||||
|
'fieldtype': 'Int',
|
||||||
|
'default': 0,
|
||||||
|
'width': 125
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Total'),
|
||||||
|
'fieldname': 'total',
|
||||||
|
'fieldtype': 'Int',
|
||||||
|
'default': 0,
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('New Customer Revenue'),
|
||||||
|
'fieldname': 'new_customer_revenue',
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'default': 0.0,
|
||||||
|
'width': 175
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Repeat Customer Revenue'),
|
||||||
|
'fieldname': 'repeat_customer_revenue',
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'default': 0.0,
|
||||||
|
'width': 175
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Total Revenue'),
|
||||||
|
'fieldname': 'total_revenue',
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'default': 0.0,
|
||||||
|
'width': 175
|
||||||
|
}
|
||||||
|
]
|
||||||
|
if filters.get('view_type') == 'Monthly':
|
||||||
|
return get_data_by_time(filters, common_columns)
|
||||||
|
else:
|
||||||
|
return get_data_by_territory(filters, common_columns)
|
||||||
|
|
||||||
if filters.get("company"):
|
def get_data_by_time(filters, common_columns):
|
||||||
company_condition = ' and company=%(company)s'
|
# key yyyy-mm
|
||||||
|
columns = [
|
||||||
|
{
|
||||||
|
'label': _('Year'),
|
||||||
|
'fieldname': 'year',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Month'),
|
||||||
|
'fieldname': 'month',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
]
|
||||||
|
columns += common_columns
|
||||||
|
|
||||||
for si in frappe.db.sql("""select posting_date, customer, base_grand_total from `tabSales Invoice`
|
customers_in = get_customer_stats(filters)
|
||||||
where docstatus=1 and posting_date <= %(to_date)s
|
|
||||||
{company_condition} order by posting_date""".format(company_condition=company_condition),
|
|
||||||
filters, as_dict=1):
|
|
||||||
|
|
||||||
key = si.posting_date.strftime("%Y-%m")
|
# time series
|
||||||
if not si.customer in customers:
|
from_year, from_month, temp = filters.get('from_date').split('-')
|
||||||
new_customers_in.setdefault(key, [0, 0.0])
|
to_year, to_month, temp = filters.get('to_date').split('-')
|
||||||
new_customers_in[key][0] += 1
|
|
||||||
new_customers_in[key][1] += si.base_grand_total
|
|
||||||
customers.append(si.customer)
|
|
||||||
else:
|
|
||||||
repeat_customers_in.setdefault(key, [0, 0.0])
|
|
||||||
repeat_customers_in[key][0] += 1
|
|
||||||
repeat_customers_in[key][1] += si.base_grand_total
|
|
||||||
|
|
||||||
# time series
|
from_year, from_month, to_year, to_month = \
|
||||||
from_year, from_month, temp = filters.get("from_date").split("-")
|
cint(from_year), cint(from_month), cint(to_year), cint(to_month)
|
||||||
to_year, to_month, temp = filters.get("to_date").split("-")
|
|
||||||
|
|
||||||
from_year, from_month, to_year, to_month = \
|
out = []
|
||||||
cint(from_year), cint(from_month), cint(to_year), cint(to_month)
|
for year in range(from_year, to_year+1):
|
||||||
|
for month in range(from_month if year==from_year else 1, (to_month+1) if year==to_year else 13):
|
||||||
|
key = '{year}-{month:02d}'.format(year=year, month=month)
|
||||||
|
data = customers_in.get(key)
|
||||||
|
new = data['new'] if data else [0, 0.0]
|
||||||
|
repeat = data['repeat'] if data else [0, 0.0]
|
||||||
|
out.append({
|
||||||
|
'year': cstr(year),
|
||||||
|
'month': calendar.month_name[month],
|
||||||
|
'new_customers': new[0],
|
||||||
|
'repeat_customers': repeat[0],
|
||||||
|
'total': new[0] + repeat[0],
|
||||||
|
'new_customer_revenue': new[1],
|
||||||
|
'repeat_customer_revenue': repeat[1],
|
||||||
|
'total_revenue': new[1] + repeat[1]
|
||||||
|
})
|
||||||
|
return columns, out
|
||||||
|
|
||||||
out = []
|
def get_data_by_territory(filters, common_columns):
|
||||||
for year in range(from_year, to_year+1):
|
columns = [{
|
||||||
for month in range(from_month if year==from_year else 1, (to_month+1) if year==to_year else 13):
|
'label': 'Territory',
|
||||||
key = "{year}-{month:02d}".format(year=year, month=month)
|
'fieldname': 'territory',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Territory',
|
||||||
|
'width': 150
|
||||||
|
}]
|
||||||
|
columns += common_columns
|
||||||
|
|
||||||
new = new_customers_in.get(key, [0,0.0])
|
customers_in = get_customer_stats(filters, tree_view=True)
|
||||||
repeat = repeat_customers_in.get(key, [0,0.0])
|
|
||||||
|
|
||||||
out.append([cstr(year), calendar.month_name[month],
|
territory_dict = {}
|
||||||
new[0], repeat[0], new[0] + repeat[0],
|
for t in frappe.db.sql('''SELECT name, lft, parent_territory, is_group FROM `tabTerritory` ORDER BY lft''', as_dict=1):
|
||||||
new[1], repeat[1], new[1] + repeat[1]])
|
territory_dict.update({
|
||||||
|
t.name: {
|
||||||
|
'parent': t.parent_territory,
|
||||||
|
'is_group': t.is_group
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return [
|
depth_map = frappe._dict()
|
||||||
_("Year") + "::100",
|
for name, info in territory_dict.items():
|
||||||
_("Month") + "::100",
|
default = depth_map.get(info['parent']) + 1 if info['parent'] else 0
|
||||||
_("New Customers") + ":Int:100",
|
depth_map.setdefault(name, default)
|
||||||
_("Repeat Customers") + ":Int:100",
|
|
||||||
_("Total") + ":Int:100",
|
|
||||||
_("New Customer Revenue") + ":Currency:150",
|
|
||||||
_("Repeat Customer Revenue") + ":Currency:150",
|
|
||||||
_("Total Revenue") + ":Currency:150"
|
|
||||||
], out
|
|
||||||
|
|
||||||
|
data = []
|
||||||
|
for name, indent in depth_map.items():
|
||||||
|
condition = customers_in.get(name)
|
||||||
|
new = customers_in[name]['new'] if condition else [0, 0.0]
|
||||||
|
repeat = customers_in[name]['repeat'] if condition else [0, 0.0]
|
||||||
|
temp = {
|
||||||
|
'territory': name,
|
||||||
|
'parent_territory': territory_dict[name]['parent'],
|
||||||
|
'indent': indent,
|
||||||
|
'new_customers': new[0],
|
||||||
|
'repeat_customers': repeat[0],
|
||||||
|
'total': new[0] + repeat[0],
|
||||||
|
'new_customer_revenue': new[1],
|
||||||
|
'repeat_customer_revenue': repeat[1],
|
||||||
|
'total_revenue': new[1] + repeat[1],
|
||||||
|
'bold': 0 if indent else 1
|
||||||
|
}
|
||||||
|
data.append(temp)
|
||||||
|
|
||||||
|
loop_data = sorted(data, key=lambda k: k['indent'], reverse=True)
|
||||||
|
|
||||||
|
for ld in loop_data:
|
||||||
|
if ld['parent_territory']:
|
||||||
|
parent_data = [x for x in data if x['territory'] == ld['parent_territory']][0]
|
||||||
|
for key in parent_data.keys():
|
||||||
|
if key not in ['indent', 'territory', 'parent_territory', 'bold']:
|
||||||
|
parent_data[key] += ld[key]
|
||||||
|
|
||||||
|
return columns, data, None, None, None, 1
|
||||||
|
|
||||||
|
def get_customer_stats(filters, tree_view=False):
|
||||||
|
""" Calculates number of new and repeated customers. """
|
||||||
|
company_condition = ''
|
||||||
|
if filters.get('company'):
|
||||||
|
company_condition = ' and company=%(company)s'
|
||||||
|
|
||||||
|
customers = []
|
||||||
|
customers_in = {}
|
||||||
|
|
||||||
|
for si in frappe.db.sql('''select territory, posting_date, customer, base_grand_total from `tabSales Invoice`
|
||||||
|
where docstatus=1 and posting_date <= %(to_date)s and posting_date >= %(from_date)s
|
||||||
|
{company_condition} order by posting_date'''.format(company_condition=company_condition),
|
||||||
|
filters, as_dict=1):
|
||||||
|
|
||||||
|
key = si.territory if tree_view else si.posting_date.strftime('%Y-%m')
|
||||||
|
customers_in.setdefault(key, {'new': [0, 0.0], 'repeat': [0, 0.0]})
|
||||||
|
|
||||||
|
if not si.customer in customers:
|
||||||
|
customers_in[key]['new'][0] += 1
|
||||||
|
customers_in[key]['new'][1] += si.base_grand_total
|
||||||
|
customers.append(si.customer)
|
||||||
|
else:
|
||||||
|
customers_in[key]['repeat'][0] += 1
|
||||||
|
customers_in[key]['repeat'][1] += si.base_grand_total
|
||||||
|
|
||||||
|
return customers_in
|
||||||
|
|||||||
@ -20,31 +20,36 @@ def get_columns():
|
|||||||
"label": _("Territory"),
|
"label": _("Territory"),
|
||||||
"fieldname": "territory",
|
"fieldname": "territory",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Territory"
|
"options": "Territory",
|
||||||
|
"width": 150
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Opportunity Amount"),
|
"label": _("Opportunity Amount"),
|
||||||
"fieldname": "opportunity_amount",
|
"fieldname": "opportunity_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"options": currency
|
"options": currency,
|
||||||
|
"width": 150
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Quotation Amount"),
|
"label": _("Quotation Amount"),
|
||||||
"fieldname": "quotation_amount",
|
"fieldname": "quotation_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"options": currency
|
"options": currency,
|
||||||
|
"width": 150
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Order Amount"),
|
"label": _("Order Amount"),
|
||||||
"fieldname": "order_amount",
|
"fieldname": "order_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"options": currency
|
"options": currency,
|
||||||
|
"width": 150
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Billing Amount"),
|
"label": _("Billing Amount"),
|
||||||
"fieldname": "billing_amount",
|
"fieldname": "billing_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"options": currency
|
"options": currency,
|
||||||
|
"width": 150
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -63,7 +68,6 @@ def get_data(filters=None):
|
|||||||
t_opportunity_names = []
|
t_opportunity_names = []
|
||||||
if territory_opportunities:
|
if territory_opportunities:
|
||||||
t_opportunity_names = [t.name for t in territory_opportunities]
|
t_opportunity_names = [t.name for t in territory_opportunities]
|
||||||
|
|
||||||
territory_quotations = []
|
territory_quotations = []
|
||||||
if t_opportunity_names and quotations:
|
if t_opportunity_names and quotations:
|
||||||
territory_quotations = list(filter(lambda x: x.opportunity in t_opportunity_names, quotations))
|
territory_quotations = list(filter(lambda x: x.opportunity in t_opportunity_names, quotations))
|
||||||
|
|||||||
@ -47,26 +47,20 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"category": "Modules",
|
"category": "Modules",
|
||||||
"charts": [
|
"charts": [],
|
||||||
{
|
|
||||||
"chart_name": "Bank Balance",
|
|
||||||
"label": "Bank Balance"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"creation": "2020-01-23 13:46:38.833076",
|
"creation": "2020-01-23 13:46:38.833076",
|
||||||
"developer_mode_only": 0,
|
"developer_mode_only": 0,
|
||||||
"disable_user_customization": 0,
|
"disable_user_customization": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Desk Page",
|
"doctype": "Desk Page",
|
||||||
"extends_another_page": 0,
|
"extends_another_page": 0,
|
||||||
"icon": "",
|
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"label": "Getting Started",
|
"label": "Home",
|
||||||
"modified": "2020-04-01 11:30:19.763099",
|
"modified": "2020-05-11 10:20:37.358701",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Getting Started",
|
"name": "Home",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"pin_to_bottom": 0,
|
"pin_to_bottom": 0,
|
||||||
"pin_to_top": 1,
|
"pin_to_top": 1,
|
||||||
@ -47,9 +47,7 @@ class TestCompany(unittest.TestCase):
|
|||||||
frappe.delete_doc("Company", "COA from Existing Company")
|
frappe.delete_doc("Company", "COA from Existing Company")
|
||||||
|
|
||||||
def test_coa_based_on_country_template(self):
|
def test_coa_based_on_country_template(self):
|
||||||
countries = ["India", "Brazil", "United Arab Emirates", "Canada", "Germany", "France",
|
countries = ["Canada", "Germany", "France"]
|
||||||
"Guatemala", "Indonesia", "Italy", "Mexico", "Nicaragua", "Netherlands", "Singapore",
|
|
||||||
"Brazil", "Argentina", "Hungary", "Taiwan"]
|
|
||||||
|
|
||||||
for country in countries:
|
for country in countries:
|
||||||
templates = get_charts_for_country(country)
|
templates = get_charts_for_country(country)
|
||||||
|
|||||||
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
@ -14,6 +12,7 @@ class Territory(NestedSet):
|
|||||||
nsm_parent_field = 'parent_territory'
|
nsm_parent_field = 'parent_territory'
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
|
||||||
for d in self.get('targets') or []:
|
for d in self.get('targets') or []:
|
||||||
if not flt(d.target_qty) and not flt(d.target_amount):
|
if not flt(d.target_qty) and not flt(d.target_amount):
|
||||||
frappe.throw(_("Either target qty or target amount is mandatory"))
|
frappe.throw(_("Either target qty or target amount is mandatory"))
|
||||||
|
|||||||
@ -69,3 +69,10 @@ class ItemPrice(Document):
|
|||||||
self.reference = self.customer
|
self.reference = self.customer
|
||||||
if self.buying:
|
if self.buying:
|
||||||
self.reference = self.supplier
|
self.reference = self.supplier
|
||||||
|
|
||||||
|
if self.selling and not self.buying:
|
||||||
|
# if only selling then remove supplier
|
||||||
|
self.supplier = None
|
||||||
|
if self.buying and not self.selling:
|
||||||
|
# if only buying then remove customer
|
||||||
|
self.customer = None
|
||||||
|
|||||||
@ -470,7 +470,7 @@ class StockEntry(StockController):
|
|||||||
"qty": item.s_warehouse and -1*flt(item.transfer_qty) or flt(item.transfer_qty),
|
"qty": item.s_warehouse and -1*flt(item.transfer_qty) or flt(item.transfer_qty),
|
||||||
"serial_no": item.serial_no,
|
"serial_no": item.serial_no,
|
||||||
"voucher_type": self.doctype,
|
"voucher_type": self.doctype,
|
||||||
"voucher_no": item.name,
|
"voucher_no": self.name,
|
||||||
"company": self.company,
|
"company": self.company,
|
||||||
"allow_zero_valuation": item.allow_zero_valuation_rate,
|
"allow_zero_valuation": item.allow_zero_valuation_rate,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -630,7 +630,7 @@ def get_item_price(args, item_code, ignore_party=False):
|
|||||||
elif args.get("supplier"):
|
elif args.get("supplier"):
|
||||||
conditions += " and supplier=%(supplier)s"
|
conditions += " and supplier=%(supplier)s"
|
||||||
else:
|
else:
|
||||||
conditions += " and (customer is null or customer = '') and (supplier is null or supplier = '')"
|
conditions += "and (customer is null or customer = '') and (supplier is null or supplier = '')"
|
||||||
|
|
||||||
if args.get('transaction_date'):
|
if args.get('transaction_date'):
|
||||||
conditions += """ and %(transaction_date)s between
|
conditions += """ and %(transaction_date)s between
|
||||||
|
|||||||
@ -548,7 +548,16 @@ def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no,
|
|||||||
if not allow_zero_rate and not valuation_rate and raise_error_if_no_rate \
|
if not allow_zero_rate and not valuation_rate and raise_error_if_no_rate \
|
||||||
and cint(erpnext.is_perpetual_inventory_enabled(company)):
|
and cint(erpnext.is_perpetual_inventory_enabled(company)):
|
||||||
frappe.local.message_log = []
|
frappe.local.message_log = []
|
||||||
frappe.throw(_("Valuation rate not found for the Item {0}, which is required to do accounting entries for {1} {2}. If the item is transacting as a zero valuation rate item in the {1}, please mention that in the {1} Item table. Otherwise, please create an incoming stock transaction for the item or mention valuation rate in the Item record, and then try submiting / cancelling this entry.")
|
form_link = frappe.utils.get_link_to_form("Item", item_code)
|
||||||
.format(item_code, voucher_type, voucher_no))
|
|
||||||
|
message = _("Valuation Rate for the Item {0}, is required to do accounting entries for {1} {2}.").format(form_link, voucher_type, voucher_no)
|
||||||
|
message += "<br><br>" + _(" Here are the options to proceed:")
|
||||||
|
solutions = "<li>" + _("If the item is transacting as a Zero Valuation Rate item in this entry, please enable 'Allow Zero Valuation Rate' in the {0} Item table.").format(voucher_type) + "</li>"
|
||||||
|
solutions += "<li>" + _("If not, you can Cancel / Submit this entry ") + _("{0}").format(frappe.bold("after")) + _(" performing either one below:") + "</li>"
|
||||||
|
sub_solutions = "<ul><li>" + _("Create an incoming stock transaction for the Item.") + "</li>"
|
||||||
|
sub_solutions += "<li>" + _("Mention Valuation Rate in the Item master.") + "</li></ul>"
|
||||||
|
msg = message + solutions + sub_solutions + "</li>"
|
||||||
|
|
||||||
|
frappe.throw(msg=msg, title=_("Valuation Rate Missing"))
|
||||||
|
|
||||||
return valuation_rate
|
return valuation_rate
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user