Merge pull request #5480 from vjFaLk/restrict-newsletter-list
Added code to Restrict Newsletter List Recipients
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.js b/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
index 70c0397..356f11b 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
@@ -93,4 +93,10 @@
//Dynamically change the description based on type of margin
cur_frm.cscript.type = function(doc){
cur_frm.set_df_property('rate', 'description', doc.type=='Percentage'?'In Percentage %':'In Amount')
-}
\ No newline at end of file
+}
+
+frappe.ui.form.on('Pricing Rule', 'price_or_discount', function(frm){
+ if(frm.doc.price_or_discount == 'Price') {
+ frm.set_value('for_price_list', "")
+ }
+})
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index 54d47b5..ec0e50c 100644
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -134,12 +134,14 @@
return customer_list
def get_pricing_rules(doc):
+ pricing_rules = ""
if doc.ignore_pricing_rule == 0:
- return frappe.db.sql(""" Select * from `tabPricing Rule` where docstatus < 2 and disable = 0
- and selling = 1 and ifnull(company, '') in (%(company)s, '') and
- ifnull(for_price_list, '') in (%(price_list)s, '') and %(date)s between
- ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31') order by priority desc, name desc""",
- {'company': doc.company, 'price_list': doc.selling_price_list, 'date': nowdate()}, as_dict=1)
+ pricing_rules = frappe.db.sql(""" Select * from `tabPricing Rule` where docstatus < 2 and disable = 0
+ and selling = 1 and ifnull(company, '') in (%(company)s, '') and
+ ifnull(for_price_list, '') in (%(price_list)s, '') and %(date)s between
+ ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31') order by priority desc, name desc""",
+ {'company': doc.company, 'price_list': doc.selling_price_list, 'date': nowdate()}, as_dict=1)
+ return pricing_rules
@frappe.whitelist()
def make_invoice(doc_list):
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
index c3017eb..d1513fe 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
@@ -3,6 +3,7 @@
"allow_import": 0,
"allow_rename": 0,
"autoname": "INVTD.######",
+ "beta": 0,
"creation": "2013-04-24 11:39:32",
"custom": 0,
"docstatus": 0,
@@ -508,18 +509,22 @@
"hide_heading": 1,
"hide_toolbar": 0,
"idx": 1,
+ "image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2016-02-22 09:35:25.423372",
+ "modified": "2016-06-15 14:49:31.101752",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",
"owner": "Administrator",
"permissions": [],
+ "quick_entry": 0,
"read_only": 0,
- "read_only_onload": 0
+ "read_only_onload": 0,
+ "sort_order": "ASC",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/accounts/page/pos/pos_page.html b/erpnext/accounts/page/pos/pos_page.html
deleted file mode 100644
index 5a4c538..0000000
--- a/erpnext/accounts/page/pos/pos_page.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<div class="text-center" style="padding: 40px;">
- <img src="/assets/erpnext/images/pos.svg"
- style="width: 100px; height: 100px; margin-bottom: 30px; opacity: 0.2" class="text-muted">
- <p>{%= __("Select type of transaction") %}</p>
- <p class="select-type" style="margin: auto; max-width: 300px; margin-bottom: 30px;">
-
- </p>
- <p style="margin-bottom: 30px;">
- <button class="btn btn-primary btn-lg">{%= __("Start") %}</button>
- </p>
- <p class="pos-setting-message hide">
- <a class="btn btn-default btn-sm" href="#Form/POS Profile/New POS Profile">
- {%= __("Make new POS Profile") %}</a>
- </p>
-</div>
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py
index 9a90f2f..4bba066 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -147,10 +147,11 @@
def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts):
tax_details = frappe.db.sql("""
- select parent, account_head, sum(base_tax_amount_after_discount_amount) as tax_amount
+ select parent, account_head, case add_deduct_tax when "Add" then sum(base_tax_amount_after_discount_amount)
+ else sum(base_tax_amount_after_discount_amount) * -1 end as tax_amount
from `tabPurchase Taxes and Charges`
where parent in (%s) and category in ('Total', 'Valuation and Total')
- group by parent, account_head
+ group by parent, account_head, add_deduct_tax
""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
invoice_tax_map = {}
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js
index 6416a23..c684715 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.js
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.js
@@ -25,6 +25,26 @@
onload: function() {
this.setup_queries();
this._super();
+
+ if(this.frm.get_field('shipping_address')) {
+ this.frm.set_query("shipping_address", function(){
+ if(me.frm.doc.customer){
+ return{
+ filters:{
+ "customer": me.frm.doc.customer
+ }
+ }
+ }
+ else{
+ return{
+ filters:{
+ "is_your_company_address": 1,
+ "company": me.frm.doc.company
+ }
+ }
+ }
+ });
+ }
},
setup_queries: function() {
@@ -225,25 +245,6 @@
shipping_address: function(){
var me = this;
-
- this.frm.set_query("shipping_address", function(){
- if(me.frm.doc.customer){
- return{
- filters:{
- "customer": me.frm.doc.customer
- }
- }
- }
- else{
- return{
- filters:{
- "is_your_company_address": 1,
- "company": me.frm.doc.company
- }
- }
- }
- });
-
erpnext.utils.get_address_display(this.frm, "shipping_address",
"shipping_address_display", is_your_company_address=true)
},
diff --git a/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json
index 2892e3b..7a23f43 100644
--- a/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json
+++ b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json
@@ -3,6 +3,7 @@
"allow_import": 0,
"allow_rename": 0,
"autoname": "hash",
+ "beta": 0,
"creation": "2016-02-25 08:04:02.452958",
"custom": 0,
"docstatus": 0,
@@ -496,7 +497,7 @@
"no_copy": 1,
"permlevel": 0,
"precision": "",
- "print_hide": 0,
+ "print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
@@ -593,19 +594,21 @@
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
+ "image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2016-03-29 05:28:39.203232",
- "modified_by": "Administrator",
+ "modified": "2016-06-17 12:25:37.655901",
+ "modified_by": "umair@erpnext.com",
"module": "Buying",
"name": "Request for Quotation Item",
"name_case": "",
"owner": "Administrator",
"permissions": [],
+ "quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
diff --git a/erpnext/config/crm.py b/erpnext/config/crm.py
index 26e9e03..dfefb75 100644
--- a/erpnext/config/crm.py
+++ b/erpnext/config/crm.py
@@ -40,6 +40,12 @@
},
{
"type": "report",
+ "name": "Minutes to First Response for Opportunity",
+ "doctype": "Opportunity",
+ "is_query_report": True
+ },
+ {
+ "type": "report",
"is_query_report": True,
"name": "Lead Details",
"doctype": "Lead"
diff --git a/erpnext/config/support.py b/erpnext/config/support.py
index ca97164..98fa595 100644
--- a/erpnext/config/support.py
+++ b/erpnext/config/support.py
@@ -64,6 +64,12 @@
"label": _("Support Analytics"),
"icon": "icon-bar-chart"
},
+ {
+ "type": "report",
+ "name": "Minutes to First Response for Issues",
+ "doctype": "Issue",
+ "is_query_report": True
+ },
]
},
]
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 34f098e..e3a66a4 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -48,7 +48,7 @@
self.validate_party()
self.validate_currency()
-
+
if self.meta.get_field("is_recurring"):
if self.amended_from and self.recurring_id:
self.recurring_id = None
@@ -65,7 +65,7 @@
if cint(is_paid) == 1:
if flt(self.paid_amount) == 0 and flt(self.outstanding_amount) > 0:
if self.cash_bank_account:
- self.paid_amount = flt(flt(self.grand_total) - flt(self.write_off_amount),
+ self.paid_amount = flt(flt(self.grand_total) - flt(self.write_off_amount),
self.precision("paid_amount"))
self.base_paid_amount = flt(self.paid_amount * self.conversion_rate, self.precision("base_paid_amount"))
else:
@@ -227,13 +227,13 @@
def get_gl_dict(self, args, account_currency=None):
"""this method populates the common properties of a gl entry record"""
-
+
fiscal_years = get_fiscal_years(self.posting_date, company=self.company)
if len(fiscal_years) > 1:
frappe.throw(_("Multiple fiscal years exist for the date {0}. Please set company in Fiscal Year").format(formatdate(self.posting_date)))
else:
fiscal_year = fiscal_years[0][0]
-
+
gl_dict = frappe._dict({
'company': self.company,
'posting_date': self.posting_date,
@@ -471,31 +471,31 @@
# Note: not validating with gle account because we don't have the account
# at quotation / sales order level and we shouldn't stop someone
# from creating a sales invoice if sales order is already created
-
+
def validate_fixed_asset(self):
for d in self.get("items"):
if d.is_fixed_asset:
if d.qty > 1:
frappe.throw(_("Row #{0}: Qty must be 1, as item is a fixed asset. Please use separate row for multiple qty.").format(d.idx))
-
+
if d.meta.get_field("asset"):
if not d.asset:
frappe.throw(_("Row #{0}: Asset is mandatory for fixed asset purchase/sale")
.format(d.idx))
else:
asset = frappe.get_doc("Asset", d.asset)
-
+
if asset.company != self.company:
frappe.throw(_("Row #{0}: Asset {1} does not belong to company {2}")
.format(d.idx, d.asset, self.company))
-
+
elif asset.item_code != d.item_code:
frappe.throw(_("Row #{0}: Asset {1} does not linked to Item {2}")
.format(d.idx, d.asset, d.item_code))
-
+
elif asset.docstatus != 1:
frappe.throw(_("Row #{0}: Asset {1} must be submitted").format(d.idx, d.asset))
-
+
elif self.doctype == "Purchase Invoice":
if asset.status != "Submitted":
frappe.throw(_("Row #{0}: Asset {1} is already {2}")
@@ -504,18 +504,18 @@
frappe.throw(_("Row #{0}: Posting Date must be same as purchase date {1} of asset {2}").format(d.idx, asset.purchase_date, d.asset))
elif asset.is_existing_asset:
frappe.throw(_("Row #{0}: Purchase Invoice cannot be made against an existing asset {1}").format(d.idx, d.asset))
-
+
elif self.docstatus=="Sales Invoice" and self.docstatus == 1:
if self.update_stock:
frappe.throw(_("'Update Stock' cannot be checked for fixed asset sale"))
-
+
elif asset.status in ("Scrapped", "Cancelled", "Sold"):
frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}")
.format(d.idx, d.asset, asset.status))
@frappe.whitelist()
def get_tax_rate(account_head):
- return frappe.db.get_value("Account", account_head, "tax_rate")
+ return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)
@frappe.whitelist()
def get_default_taxes_and_charges(master_doctype):
diff --git a/erpnext/crm/report/__init__.py b/erpnext/crm/report/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/crm/report/__init__.py
diff --git a/erpnext/crm/report/minutes_to_first_response_for_opportunity/__init__.py b/erpnext/crm/report/minutes_to_first_response_for_opportunity/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/crm/report/minutes_to_first_response_for_opportunity/__init__.py
diff --git a/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.js b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.js
new file mode 100644
index 0000000..b1e4917
--- /dev/null
+++ b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.js
@@ -0,0 +1,43 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.query_reports["Minutes to First Response for Opportunity"] = {
+ "filters": [
+ {
+ "fieldname":"from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ 'reqd': 1,
+ "default": frappe.datetime.add_days(frappe.datetime.nowdate(), -30)
+ },
+ {
+ "fieldname":"to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ 'reqd': 1,
+ "default":frappe.datetime.nowdate()
+ },
+ ],
+ get_chart_data: function(columns, result) {
+ return {
+ data: {
+ x: 'Date',
+ columns: [
+ ['Date'].concat($.map(result, function(d) { return d[0]; })),
+ ['Mins to first response'].concat($.map(result, function(d) { return d[1]; }))
+ ]
+ // rows: [['Date', 'Mins to first response']].concat(result)
+ },
+ axis: {
+ x: {
+ type: 'timeseries',
+ tick: {
+ format: frappe.ui.py_date_format
+ }
+ }
+ },
+ chart_type: 'line',
+
+ }
+ }
+}
diff --git a/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.json b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.json
new file mode 100644
index 0000000..a366b3e
--- /dev/null
+++ b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.json
@@ -0,0 +1,18 @@
+{
+ "add_total_row": 0,
+ "apply_user_permissions": 0,
+ "creation": "2016-06-17 11:28:25.867258",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2016-06-17 11:28:25.867258",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Minutes to First Response for Opportunity",
+ "owner": "Administrator",
+ "ref_doctype": "Opportunity",
+ "report_name": "Minutes to First Response for Opportunity",
+ "report_type": "Script Report"
+}
\ No newline at end of file
diff --git a/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.py b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.py
new file mode 100644
index 0000000..54e3a60
--- /dev/null
+++ b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute(filters=None):
+ columns = [
+ {
+ 'fieldname': 'creation_date',
+ 'label': 'Date',
+ 'fieldtype': 'Date'
+ },
+ {
+ 'fieldname': 'mins',
+ 'fieldtype': 'Float',
+ 'label': 'Mins to First Response'
+ },
+ ]
+
+ data = frappe.db.sql('''select date(creation) as creation_date,
+ avg(mins_to_first_response) as mins
+ from tabOpportunity
+ where date(creation) between %s and %s
+ and mins_to_first_response > 0
+ group by creation_date order by creation_date desc''', (filters.from_date, filters.to_date))
+
+ return columns, data
diff --git a/erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md b/erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md
index 163bd88..5fc8a0b 100644
--- a/erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md
+++ b/erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md
@@ -50,7 +50,7 @@
<img class="screenshot" alt="Asset" src="{{docs_base_url}}/assets/img/accounts/asset-graph.png">
-## Purchase an asset
+## Purchase an Asset
For purchasing a new asset, create and submit the asset record with all the depreciation settings. Then create a Purchase Invoice via "Make Purchase Invoice" button. On clicking the button, system will load a new Purchase Invoice form with pre-loaded items table. It will also set proper fixed asset account (defined in teh Asset Category) in the Expense Account field. You need to select Supplier and other necessary details and submit the Purchase Invoice.
@@ -59,7 +59,7 @@
On submission of the invoice, the "Fixed Asset Account" will be debited and payable account will be credited. It also updates purchase date, supplier and Purchase Invoice no in the Asset record.
-## Sale an ssset
+## Sale an Asset
To sale an asset, open the asset record and create a Sales Invoice using "Sale Asset" button. On submission of the Sales Invoice, following entries will take place:
diff --git a/erpnext/docs/user/manual/en/introduction/index.md b/erpnext/docs/user/manual/en/introduction/index.md
index 76e77b1..6471090 100644
--- a/erpnext/docs/user/manual/en/introduction/index.md
+++ b/erpnext/docs/user/manual/en/introduction/index.md
@@ -4,17 +4,12 @@
organization, you can skip this page.)
If you are running a small business that has a few employees, you understand
-that it's hard to manage the dynamic nature of doing businesses. You are
-already using a software like Accounting, and may be some more to manage your
-inventory and sales (or CRM).
-
-An ERP brings all of this together in one place.
-
-Small businesses are not so different from large ones. They contain most of
-the complexities of a large business along with many other constraints. Small
-businesses have to communicate with customers, do accounts, pay taxes, do
-payroll, manage timelines, deliver quality, answer questions, and keep
-everyone happy just like in large businesses.
+that it's hard to manage the dynamic nature of doing businesses. Small businesses
+are not so different from large ones. They contain most of the complexities of
+a large business along with many other constraints. Small businesses have to
+communicate with customers, do accounts, pay taxes, do payroll, manage timelines,
+deliver quality goods and services, answer questions, and keep everyone happy,
+just like in large businesses.
Large businesses have the advantage of using advanced data systems to manage
their process efficiently. Small businesses, on the other hand, typically
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.js b/erpnext/manufacturing/doctype/production_order/production_order.js
index e4bf46f..ba7026e 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.js
+++ b/erpnext/manufacturing/doctype/production_order/production_order.js
@@ -220,7 +220,7 @@
flt(this.frm.doc.material_transferred_for_manufacturing) - flt(this.frm.doc.produced_qty) :
flt(this.frm.doc.qty) - flt(this.frm.doc.material_transferred_for_manufacturing);
- frappe.prompt({fieldtype:"Int", label: __("Qty for {0}", [purpose]), fieldname:"qty",
+ frappe.prompt({fieldtype:"Float", label: __("Qty for {0}", [purpose]), fieldname:"qty",
description: __("Max: {0}", [max]), 'default': max },
function(data) {
if(data.qty > max) {
diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js
index e19919d..202000f 100644
--- a/erpnext/public/js/controllers/accounts.js
+++ b/erpnext/public/js/controllers/accounts.js
@@ -6,6 +6,14 @@
frappe.provide("erpnext.taxes.flags");
frappe.ui.form.on(cur_frm.doctype, {
+ setup: function(frm) {
+ // set conditional display for rate column in taxes
+ $(frm.wrapper).on('grid-row-render', function(e, grid_row) {
+ if(in_list(['Sales Taxes and Charges', 'Purchase Taxes and Charges'], grid_row.doc.doctype)) {
+ erpnext.taxes.set_conditional_mandatory_rate_or_amount(grid_row);
+ }
+ });
+ },
onload: function(frm) {
if(frm.get_field("taxes")) {
frm.set_query("account_head", "taxes", function(doc) {
@@ -40,10 +48,10 @@
frm.get_docfield("taxes", "rate").reqd = 0;
frm.get_docfield("taxes", "tax_amount").reqd = 0;
}
-
+
},
taxes_on_form_rendered: function(frm) {
- erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm);
+ erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm.open_grid_row());
}
});
@@ -58,7 +66,8 @@
method: "erpnext.controllers.accounts_controller.get_tax_rate",
args: {"account_head":d.account_head},
callback: function(r) {
- frappe.model.set_value(cdt, cdn, "rate", r.message || 0);
+ frappe.model.set_value(cdt, cdn, "rate", r.message.tax_rate || 0);
+ frappe.model.set_value(cdt, cdn, "description", r.message.account_name);
}
})
}
@@ -67,6 +76,12 @@
cur_frm.cscript.validate_taxes_and_charges = function(cdt, cdn) {
var d = locals[cdt][cdn];
var msg = "";
+
+ if(d.account_head && !d.description) {
+ // set description from account head
+ d.description = d.account_head.split(' - ').slice(0, -1).join(' - ');
+ }
+
if(!d.charge_type && (d.row_id || d.rate || d.tax_amount)) {
msg = __("Please select Charge Type first");
d.row_id = "";
@@ -143,8 +158,14 @@
});
frappe.ui.form.on(cur_frm.cscript.tax_table, "charge_type", function(frm, cdt, cdn) {
- cur_frm.cscript.validate_taxes_and_charges(cdt, cdn);
- erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm);
+ frm.cscript.validate_taxes_and_charges(cdt, cdn);
+ var open_form = frm.open_grid_row();
+ if(open_form) {
+ erpnext.taxes.set_conditional_mandatory_rate_or_amount(open_form);
+ } else {
+ // apply in current row
+ erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm.get_field('taxes').grid.get_grid_row(cdn));
+ }
});
frappe.ui.form.on(cur_frm.cscript.tax_table, "included_in_print_rate", function(frm, cdt, cdn) {
@@ -160,18 +181,19 @@
});
}
-erpnext.taxes.set_conditional_mandatory_rate_or_amount = function(frm) {
- var grid_row = frm.open_grid_row();
- if(grid_row.doc.charge_type==="Actual") {
- grid_row.toggle_display("tax_amount", true);
- grid_row.toggle_reqd("tax_amount", true);
- grid_row.toggle_display("rate", false);
- grid_row.toggle_reqd("rate", false);
- } else {
- grid_row.toggle_display("rate", true);
- grid_row.toggle_reqd("rate", true);
- grid_row.toggle_display("tax_amount", false);
- grid_row.toggle_reqd("tax_amount", false);
+erpnext.taxes.set_conditional_mandatory_rate_or_amount = function(grid_row) {
+ if(grid_row) {
+ if(grid_row.doc.charge_type==="Actual") {
+ grid_row.toggle_editable("tax_amount", true);
+ grid_row.toggle_reqd("tax_amount", true);
+ grid_row.toggle_editable("rate", false);
+ grid_row.toggle_reqd("rate", false);
+ } else {
+ grid_row.toggle_editable("rate", true);
+ grid_row.toggle_reqd("rate", true);
+ grid_row.toggle_editable("tax_amount", false);
+ grid_row.toggle_reqd("tax_amount", false);
+ }
}
}
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index cf66501..a0507ef 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -2,6 +2,18 @@
// License: GNU General Public License v3. See license.txt
erpnext.taxes_and_totals = erpnext.payments.extend({
+ setup: function() {
+ if(this.frm.get_field('taxes')) {
+ this.frm.get_field('taxes').grid.editable_fields = [
+ {fieldname: 'charge_type', columns: 2},
+ {fieldname: 'account_head', columns: 3},
+ {fieldname: 'rate', columns: 2},
+ {fieldname: 'tax_amount', columns: 2},
+ {fieldname: 'total', columns: 2}
+ ];
+ }
+
+ },
apply_pricing_rule_on_item: function(item){
if(!item.margin_type){
item.margin_rate_or_amount = 0.0;
@@ -460,8 +472,8 @@
if (this.frm.doc.discount_amount) {
if(!this.frm.doc.apply_discount_on)
frappe.throw(__("Please select Apply Discount On"));
-
- this.frm.doc.base_discount_amount = flt(this.frm.doc.discount_amount * this.frm.doc.conversion_rate,
+
+ this.frm.doc.base_discount_amount = flt(this.frm.doc.discount_amount * this.frm.doc.conversion_rate,
precision("base_discount_amount"));
var total_for_discount_amount = this.get_total_for_discount_amount();
@@ -550,11 +562,11 @@
this.frm.refresh_field("paid_amount");
this.frm.refresh_field("base_paid_amount");
}
-
+
if(this.frm.doc.doctype == "Sales Invoice"){
this.calculate_paid_amount()
}
-
+
var outstanding_amount = 0.0
var paid_amount = (this.frm.doc.party_account_currency == this.frm.doc.currency) ?
@@ -572,7 +584,7 @@
this.frm.doc.outstanding_amount = outstanding_amount;
this.calculate_change_amount()
},
-
+
calculate_paid_amount: function(){
var me = this;
var paid_amount = base_paid_amount = 0.0;
@@ -580,24 +592,24 @@
if(data.amount > -1){
data.base_amount = flt(data.amount * me.frm.doc.conversion_rate);
paid_amount += data.amount;
- base_paid_amount += data.base_amount;
+ base_paid_amount += data.base_amount;
}
})
-
+
this.frm.doc.paid_amount = flt(paid_amount, precision("paid_amount"));
this.frm.doc.base_paid_amount = flt(base_paid_amount, precision("base_paid_amount"));
},
-
+
calculate_change_amount: function(){
var change_amount = 0.0;
if(this.frm.doc.paid_amount > this.frm.doc.grand_total){
- change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total,
+ change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total,
precision("change_amount"))
}
-
- this.frm.doc.change_amount = flt(change_amount,
+
+ this.frm.doc.change_amount = flt(change_amount,
precision("change_amount"))
- this.frm.doc.base_change_amount = flt(change_amount * this.frm.doc.conversion_rate,
+ this.frm.doc.base_change_amount = flt(change_amount * this.frm.doc.conversion_rate,
precision("base_change_amount"))
},
})
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index ac0287d..ce11c8a 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -3,6 +3,7 @@
erpnext.TransactionController = erpnext.taxes_and_totals.extend({
setup: function() {
+ this._super();
frappe.ui.form.on(this.frm.doctype + " Item", "rate", function(frm, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["rate", "price_list_rate"]);
@@ -978,7 +979,4 @@
this.item_selector = new erpnext.ItemSelector({frm: this.frm});
}
}
-
-
-
});
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/item_list.js b/erpnext/stock/doctype/item/item_list.js
index 2fee589..40319e5 100644
--- a/erpnext/stock/doctype/item/item_list.js
+++ b/erpnext/stock/doctype/item/item_list.js
@@ -15,7 +15,28 @@
} else if (doc.variant_of) {
return [__("Variant"), "green", "variant_of,=," + doc.variant_of];
}
- }
+ },
+
+ reports: [
+ {
+ name: 'Stock Summary',
+ report_type: 'Page',
+ route: 'stock-balance'
+ },
+ {
+ name: 'Stock Ledger',
+ report_type: 'Script Report'
+ },
+ {
+ name: 'Stock Balance',
+ report_type: 'Script Report'
+ },
+ {
+ name: 'Stock Projected Qty',
+ report_type: 'Script Report'
+ }
+
+ ]
};
frappe.help.youtube_id["Item"] = "qXaEwld4_Ps";
diff --git a/erpnext/stock/page/stock_balance/stock_balance.js b/erpnext/stock/page/stock_balance/stock_balance.js
index efaf96f..9494045 100644
--- a/erpnext/stock/page/stock_balance/stock_balance.js
+++ b/erpnext/stock/page/stock_balance/stock_balance.js
@@ -1,7 +1,7 @@
frappe.pages['stock-balance'].on_page_load = function(wrapper) {
var page = frappe.ui.make_app_page({
parent: wrapper,
- title: 'Stock Balance',
+ title: 'Stock Summary',
single_column: true
});
page.start = 0;
diff --git a/erpnext/support/report/minutes_to_first_response_for_issues/__init__.py b/erpnext/support/report/minutes_to_first_response_for_issues/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/support/report/minutes_to_first_response_for_issues/__init__.py
diff --git a/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.js b/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.js
new file mode 100644
index 0000000..e84b13c
--- /dev/null
+++ b/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.js
@@ -0,0 +1,40 @@
+frappe.query_reports["Minutes to First Response for Issues"] = {
+ "filters": [
+ {
+ "fieldname":"from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ 'reqd': 1,
+ "default": frappe.datetime.add_days(frappe.datetime.nowdate(), -30)
+ },
+ {
+ "fieldname":"to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ 'reqd': 1,
+ "default":frappe.datetime.nowdate()
+ },
+ ],
+ get_chart_data: function(columns, result) {
+ return {
+ data: {
+ x: 'Date',
+ columns: [
+ ['Date'].concat($.map(result, function(d) { return d[0]; })),
+ ['Mins to first response'].concat($.map(result, function(d) { return d[1]; }))
+ ]
+ // rows: [['Date', 'Mins to first response']].concat(result)
+ },
+ axis: {
+ x: {
+ type: 'timeseries',
+ tick: {
+ format: frappe.ui.py_date_format
+ }
+ }
+ },
+ chart_type: 'line',
+
+ }
+ }
+}
diff --git a/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.json b/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.json
new file mode 100644
index 0000000..e6dc383
--- /dev/null
+++ b/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.json
@@ -0,0 +1,19 @@
+{
+ "add_total_row": 0,
+ "apply_user_permissions": 1,
+ "creation": "2016-06-14 17:44:26.034112",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2016-06-14 17:50:28.082090",
+ "modified_by": "Administrator",
+ "module": "Support",
+ "name": "Minutes to First Response for Issues",
+ "owner": "Administrator",
+ "query": "select date(creation) as creation_date, avg(mins_to_first_response) from tabIssue where creation > '2016-05-01' group by date(creation) order by creation_date;",
+ "ref_doctype": "Issue",
+ "report_name": "Minutes to First Response for Issues",
+ "report_type": "Script Report"
+}
\ No newline at end of file
diff --git a/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.py b/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.py
new file mode 100644
index 0000000..57c2d44
--- /dev/null
+++ b/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute(filters=None):
+ columns = [
+ {
+ 'fieldname': 'creation_date',
+ 'label': 'Date',
+ 'fieldtype': 'Date'
+ },
+ {
+ 'fieldname': 'mins',
+ 'fieldtype': 'Float',
+ 'label': 'Mins to First Response'
+ },
+ ]
+
+ data = frappe.db.sql('''select date(creation) as creation_date,
+ avg(mins_to_first_response) as mins
+ from tabIssue
+ where date(creation) between %s and %s
+ and mins_to_first_response > 0
+ group by creation_date order by creation_date desc''', (filters.from_date, filters.to_date))
+
+ return columns, data