diff --git a/erpnext/__init__.py b/erpnext/__init__.py index c433ddb33c..cde4c0e70f 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '7.0.28' +__version__ = '7.0.29' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json index cb637d254a..01a87c42e7 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.json +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json @@ -118,6 +118,32 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "campaign", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Campaign", + "length": 0, + "no_copy": 0, + "options": "Campaign", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -690,6 +716,32 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "account_for_change_amount", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Account for Change Amount", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -833,7 +885,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-08-06 17:05:59.990031", + "modified": "2016-08-17 15:12:56.713748", "modified_by": "Administrator", "module": "Accounts", "name": "POS Profile", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index c655626b86..c51231e881 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -232,7 +232,8 @@ cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) { cur_frm.fields_dict['items'].grid.get_field("item_code").get_query = function(doc, cdt, cdn) { return { - query: "erpnext.controllers.queries.item_query" + query: "erpnext.controllers.queries.item_query", + filters: {'is_purchase_item': 1} } } diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js index 433cda7372..a1d8bf85d2 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js @@ -18,3 +18,13 @@ frappe.ui.form.on("Purchase Taxes and Charges", "add_deduct_tax", function(doc, } refresh_field('add_deduct_tax', d.name, 'taxes'); }); + +frappe.ui.form.on("Purchase Taxes and Charges", "category", function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + + if (d.category != 'Total' && d.add_deduct_tax == 'Deduct') { + msgprint(__("Cannot deduct when category is for 'Valuation' or 'Vaulation and Total'")); + d.add_deduct_tax = ''; + } + refresh_field('add_deduct_tax', d.name, 'taxes'); +}); diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index 33032bf1e9..df0874bce4 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -35,7 +35,6 @@ def get_pos_data(): 'customers': get_customers(pos_profile, doc), 'pricing_rules': get_pricing_rules(doc), 'print_template': print_template, - 'write_off_account': pos_profile.get('write_off_account'), 'meta': { 'invoice': frappe.get_meta('Sales Invoice'), 'items': frappe.get_meta('Sales Invoice Item'), @@ -45,7 +44,12 @@ def get_pos_data(): def update_pos_profile_data(doc, pos_profile): company_data = frappe.db.get_value('Company', doc.company, '*', as_dict=1) + doc.campaign = pos_profile.get('campaign') + doc.write_off_account = pos_profile.get('write_off_account') or \ + company_data.write_off_account + doc.change_amount_account = pos_profile.get('change_amount_account') or \ + company_data.default_cash_account doc.taxes_and_charges = pos_profile.get('taxes_and_charges') if doc.taxes_and_charges: update_tax_table(doc) @@ -54,7 +58,8 @@ def update_pos_profile_data(doc, pos_profile): doc.conversion_rate = 1.0 if doc.currency != company_data.default_currency: doc.conversion_rate = get_exchange_rate(doc.currency, company_data.default_currency) - doc.selling_price_list = pos_profile.get('selling_price_list') or frappe.db.get_value('Selling Settings', None, 'selling_price_list') + doc.selling_price_list = pos_profile.get('selling_price_list') or \ + frappe.db.get_value('Selling Settings', None, 'selling_price_list') doc.naming_series = pos_profile.get('naming_series') or 'SINV-' doc.letter_head = pos_profile.get('letter_head') or company_data.default_letter_head doc.ignore_pricing_rule = pos_profile.get('ignore_pricing_rule') or 0 @@ -157,10 +162,11 @@ def get_customers(pos_profile, doc): def get_pricing_rules(doc): pricing_rules = "" if doc.ignore_pricing_rule == 0: - 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""", + pricing_rules = frappe.db.sql(""" Select * from `tabPricing Rule` where docstatus < 2 + and ifnull(for_price_list, '') in (%(price_list)s, '') and selling = 1 + and ifnull(company, '') in (%(company)s, '') and disable = 0 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 @@ -173,9 +179,9 @@ def make_invoice(doc_list): for docs in doc_list: for name, doc in docs.items(): - if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}): - validate_customer(doc) - validate_item(doc) + if not frappe.db.exists('Sales Invoice', + {'offline_pos_name': name, 'docstatus': ("<", "2")}): + validate_records(doc) si_doc = frappe.new_doc('Sales Invoice') si_doc.offline_pos_name = name si_doc.update(doc) @@ -186,6 +192,10 @@ def make_invoice(doc_list): return name_list +def validate_records(doc): + validate_customer(doc) + validate_item(doc) + def validate_customer(doc): if not frappe.db.exists('Customer', doc.get('customer')): customer_doc = frappe.new_doc('Customer') @@ -197,8 +207,6 @@ def validate_customer(doc): frappe.db.commit() doc['customer'] = customer_doc.name - return doc - def validate_item(doc): for item in doc.get('items'): if not frappe.db.exists('Item', item.get('item_code')): diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index b73673fe94..3245e78e13 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -267,6 +267,16 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte amount: function(){ this.write_off_outstanding_amount_automatically() + }, + + change_amount: function(){ + if(this.frm.doc.paid_amount > this.frm.doc.grand_total){ + this.calculate_write_off_amount() + }else { + this.frm.set_value("change_amount", 0.0) + } + + this.frm.refresh_fields(); } }); @@ -458,7 +468,7 @@ frappe.ui.form.on('Sales Invoice', { ] } } - }, + } }) frappe.ui.form.on('Sales Invoice Timesheet', { diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 06bc6359b9..a2e930c820 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -2200,32 +2200,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "base_change_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Base Change Amount (Company Currency)", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_on_submit": 0, "bold": 0, @@ -2278,6 +2252,80 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "section_break_88", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "base_change_amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Base Change Amount (Company Currency)", + "length": 0, + "no_copy": 1, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_90", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -2297,7 +2345,33 @@ "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, - "read_only": 1, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "account_for_change_amount", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Account for Change Amount", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -3677,7 +3751,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2016-08-03 11:50:49.680278", + "modified": "2016-08-17 15:12:39.357372", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index f055140348..871a1512e0 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -61,6 +61,7 @@ class SalesInvoice(SellingController): self.clear_unallocated_advances("Sales Invoice Advance", "advances") self.add_remarks() self.validate_write_off_account() + self.validate_account_for_change_amount() self.validate_fixed_asset() self.set_income_account_for_fixed_assets() @@ -233,12 +234,22 @@ class SalesInvoice(SellingController): from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile pos = get_pos_profile(self.company) + if not self.get('payments'): + pos_profile = frappe.get_doc('POS Profile', pos.name) if pos else None + update_multi_mode_option(self, pos_profile) + + if not self.account_for_change_amount: + self.account_for_change_amount = frappe.db.get_value('Company', self.company, 'default_cash_account') + if pos: if not for_validate and not self.customer: self.customer = pos.customer self.mode_of_payment = pos.mode_of_payment # self.set_customer_defaults() + if pos.get('account_for_change_amount'): + self.account_for_change_amount = pos.get('account_for_change_amount') + for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name', 'selling_price_list', 'company', 'select_print_heading', 'cash_bank_account', 'write_off_account', 'write_off_cost_center'): @@ -265,10 +276,6 @@ class SalesInvoice(SellingController): if self.taxes_and_charges and not len(self.get("taxes")): self.set_taxes() - if not self.get('payments'): - pos_profile = frappe.get_doc('POS Profile', pos.name) - update_multi_mode_option(self, pos_profile) - return pos def get_company_abbr(self): @@ -379,6 +386,9 @@ class SalesInvoice(SellingController): if flt(self.write_off_amount) and not self.write_off_account: msgprint(_("Please enter Write Off Account"), raise_exception=1) + def validate_account_for_change_amount(self): + if flt(self.change_amount) and not self.account_for_change_amount: + msgprint(_("Please enter Account for Change Amount"), raise_exception=1) def validate_c_form(self): """ Blank C-form no if C-form applicable marked as 'No'""" @@ -502,7 +512,7 @@ class SalesInvoice(SellingController): gl_entries = merge_similar_entries(gl_entries) self.make_pos_gl_entries(gl_entries) - self.make_gle_for_change(gl_entries) + self.make_gle_for_change_amount(gl_entries) self.make_write_off_gl_entry(gl_entries) @@ -606,16 +616,15 @@ class SalesInvoice(SellingController): }, payment_mode_account_currency) ) - def make_gle_for_change(self, gl_entries): + def make_gle_for_change_amount(self, gl_entries): if cint(self.is_pos) and self.change_amount: - cash_account = self.get_cash_account() - if cash_account: + if self.account_for_change_amount: gl_entries.append( self.get_gl_dict({ "account": self.debit_to, "party_type": "Customer", "party": self.customer, - "against": cash_account, + "against": self.account_for_change_amount, "debit": flt(self.base_change_amount), "debit_in_account_currency": flt(self.base_change_amount) \ if self.party_account_currency==self.company_currency else flt(self.change_amount), @@ -626,22 +635,13 @@ class SalesInvoice(SellingController): gl_entries.append( self.get_gl_dict({ - "account": cash_account, + "account": self.account_for_change_amount, "against": self.customer, "credit": self.base_change_amount }) ) - - - def get_cash_account(self): - cash_account = [d.account for d in self.payments if d.type=="Cash"] - if cash_account: - cash_account = cash_account[0] - else: - cash_account = frappe.db.get_value("Account", - filters={"company": self.company, "account_type": "Cash", "is_group": 0}) - - return cash_account + else: + frappe.throw(_("Select change amount account"), title="Mandatory Field") def make_write_off_gl_entry(self, gl_entries): # write off entries, applicable if only pos diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index dd28059c43..1bb7b1c2ac 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -455,6 +455,25 @@ class TestSalesInvoice(unittest.TestCase): self.pos_gl_entry(si, pos, 300) + def test_pos_change_amount(self): + set_perpetual_inventory() + self.make_pos_profile() + + self._insert_purchase_receipt() + pos = copy.deepcopy(test_records[1]) + pos["is_pos"] = 1 + pos["update_stock"] = 1 + pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300}, + {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 340}] + + si = frappe.copy_doc(pos) + si.change_amount = 5.0 + si.insert() + si.submit() + + self.assertEquals(si.grand_total, 630.0) + self.assertEquals(si.write_off_amount, -5) + def test_make_pos_invoice(self): from erpnext.accounts.doctype.sales_invoice.pos import make_invoice diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index 0d3e0193d5..06606a97fe 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -183,6 +183,14 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ if(this.frm.doc.customer){ this.party_field.$input.val(this.frm.doc.customer); } + + if(!this.frm.doc.write_off_account){ + this.frm.doc.write_off_account = doc.write_off_account + } + + if(!this.frm.doc.account_for_change_amount){ + this.frm.doc.account_for_change_amount = doc.account_for_change_amount + } }, get_invoice_doc: function(si_docs){ @@ -209,7 +217,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ window.meta = r.message.meta; window.print_template = r.message.print_template; me.default_customer = r.message.default_customer || null; - me.write_off_account = r.message.write_off_account; localStorage.setItem('doc', JSON.stringify(r.message.doc)); if(callback){ callback(); @@ -485,11 +492,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.remove_item = [] $.each(this.frm.doc["items"] || [], function(i, d) { - if (d.item_code == item_code && d.serial_no - && field == 'qty' && cint(value) != value) { - d.qty = 0.0; - me.refresh(); - frappe.throw(__("Serial no item cannot be a fraction")) + if(d.serial_no){ + me.validate_serial_no_qty(d, item_code, field, value) } if (d.item_code == item_code) { @@ -723,49 +727,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }, 1000) }, - write_off_amount: function(){ - var me = this; - var value = 0.0; - - if(this.frm.doc.outstanding_amount > 0){ - dialog = new frappe.ui.Dialog({ - title: 'Write Off Amount', - fields: [ - {fieldtype: "Check", fieldname: "write_off_amount", label: __("Write off Outstanding Amount")}, - {fieldtype: "Link", options:"Account", default:this.write_off_account, fieldname: "write_off_account", - label: __("Write off Account"), get_query: function() { - return { - filters: {'is_group': 0, 'report_type': 'Profit and Loss'} - } - }} - ] - }); - - dialog.show(); - - dialog.fields_dict.write_off_amount.$input.change(function(){ - write_off_amount = dialog.get_values().write_off_amount; - me.frm.doc.write_off_outstanding_amount_automatically = write_off_amount; - me.frm.doc.base_write_off_amount = (write_off_amount==1) ? flt(me.frm.doc.grand_total - me.frm.doc.paid_amount, precision("outstanding_amount")) : 0; - me.frm.doc.write_off_account = (write_off_amount==1) ? dialog.get_values().write_off_account : ''; - me.frm.doc.write_off_amount = flt(me.frm.doc.base_write_off_amount * me.frm.doc.conversion_rate, precision("write_off_amount")) - me.calculate_outstanding_amount(); - me.set_primary_action(); - }) - - dialog.fields_dict.write_off_account.$input.change(function(){ - me.frm.doc.write_off_account = dialog.get_values().write_off_account; - }) - - dialog.set_primary_action(__("Submit"), function(){ - dialog.hide() - me.submit_invoice() - }) - }else{ - this.submit_invoice() - } - }, - submit_invoice: function(){ var me = this; frappe.confirm(__("Do you really want to submit the invoice?"), function () { @@ -951,6 +912,23 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ } }, + validate_serial_no_qty: function(args, item_code, field, value){ + var me = this; + if (args.item_code == item_code && args.serial_no + && field == 'qty' && cint(value) != value) { + args.qty = 0.0; + this.refresh(); + frappe.throw(__("Serial no item cannot be a fraction")) + } + + if(args.serial_no && args.serial_no.split('\n').length != cint(value)){ + args.qty = 0.0; + args.serial_no = '' + this.refresh(); + frappe.throw(__("Total nos of serial no is not equal to quantity.")) + } + }, + mandatory_batch_no: function(){ var me = this; if(this.items[0].has_batch_no && !this.item_batch_no[this.items[0].item_code]){ @@ -978,11 +956,13 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ get_pricing_rule: function(item){ var me = this; return $.grep(this.pricing_rules, function(data){ - if(data.item_code == item.item_code || in_list(['All Item Groups', item.item_group], data.item_group)) { - if(in_list(['Customer', 'Customer Group', 'Territory'], data.applicable_for)){ - return me.validate_condition(data) - }else{ - return true + if(item.qty >= data.min_qty && (item.qty <= (data.max_qty ? data.max_qty : item.qty)) ){ + if(data.item_code == item.item_code || in_list(['All Item Groups', item.item_group], data.item_group)) { + if(in_list(['Customer', 'Customer Group', 'Territory', 'Campaign'], data.applicable_for)){ + return me.validate_condition(data) + }else{ + return true + } } } }) @@ -1001,6 +981,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ 'Customer': [data.customer, [this.frm.doc.customer]], 'Customer Group': [data.customer_group, [this.frm.doc.customer_group, 'All Customer Groups']], 'Territory': [data.territory, [this.frm.doc.territory, 'All Territories']], + 'Campaign': [data.campaign, [this.frm.doc.campaign]], } }, diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js index 2e7651699b..6e27546cce 100644 --- a/erpnext/buying/doctype/purchase_common/purchase_common.js +++ b/erpnext/buying/doctype/purchase_common/purchase_common.js @@ -79,7 +79,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ } } else { return{ - query: "erpnext.controllers.queries.item_query" + query: "erpnext.controllers.queries.item_query", + filters: {'is_purchase_item': 1} } } }); diff --git a/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.js b/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.js index 45bc7381fb..0f44baacaf 100644 --- a/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.js +++ b/erpnext/buying/report/quoted_item_comparison/quoted_item_comparison.js @@ -11,5 +11,72 @@ frappe.query_reports["Quoted Item Comparison"] = { "default": "" } - ] + ], + onload: function(report) { + //Create a button for setting the default supplier + report.page.add_inner_button(__("Select Default Supplier"), function() { + + var reporter = frappe.query_reports["Quoted Item Comparison"]; + + //Always make a new one so that the latest values get updated + reporter.make_default_supplier_dialog(report); + report.dialog.show(); + setTimeout(function() { report.dialog.input.focus(); }, 1000); + + }, 'Tools'); + + }, + "make_default_supplier_dialog": function (report) { + //Get the name of the item to change + var filters = report.get_values(); + var item_code = filters.item; + + //Get a list of the suppliers (with a blank as well) for the user to select + var select_options = ""; + for (let supplier of report.data) + { + select_options += supplier.supplier_name+ '\n' + } + + //Create a dialog window for the user to pick their supplier + var d = new frappe.ui.Dialog({ + title: __('Select Default Supplier'), + fields: [ + {fieldname: 'supplier', fieldtype:'Select', label:'Supplier', reqd:1,options:select_options}, + {fieldname: 'ok_button', fieldtype:'Button', label:'Set Default Supplier'}, + ] + }); + + //On the user clicking the ok button + d.fields_dict.ok_button.input.onclick = function() { + var btn = d.fields_dict.ok_button.input; + var v = report.dialog.get_values(); + if(v) { + $(btn).set_working(); + + //Set the default_supplier field of the appropriate Item to the selected supplier + frappe.call({ + method: "frappe.client.set_value", + args: { + doctype: "Item", + name: item_code, + fieldname: "default_supplier", + value: v.supplier, + }, + callback: function (r){ + $(btn).done_working(); + msgprint("Successfully Set Supplier"); + report.dialog.hide(); + + } + }); + } + } + report.dialog = d; + + + } + } + + diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 28b2f7c756..125f4fedb6 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -440,6 +440,7 @@ class calculate_taxes_and_totals(object): paid_amount = self.doc.paid_amount \ if self.doc.party_account_currency == self.doc.currency else self.doc.base_paid_amount + self.calculate_write_off_amount() self.calculate_change_amount() self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) + @@ -468,6 +469,12 @@ class calculate_taxes_and_totals(object): self.doc.base_change_amount = flt(self.doc.change_amount * self.doc.conversion_rate, self.doc.precision("base_change_amount")) + def calculate_write_off_amount(self): + if flt(self.doc.change_amount) > 0: + self.doc.write_off_amount = self.doc.grand_total - self.doc.paid_amount + self.doc.change_amount + self.doc.base_write_off_amount = flt(self.doc.write_off_amount * self.doc.conversion_rate, + self.doc.precision("base_write_off_amount")) + def calculate_margin(self, item): total_margin = 0.0 if item.price_list_rate: diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js index 21a7429be2..c9f1ffb1a5 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.js +++ b/erpnext/crm/doctype/opportunity/opportunity.js @@ -51,7 +51,8 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({ this.frm.set_query("item_code", "items", function() { return { - query: "erpnext.controllers.queries.item_query" + query: "erpnext.controllers.queries.item_query", + filters: {'is_sales_item': 1} }; }); diff --git a/erpnext/docs/assets/img/accounts/perpetual-2.png b/erpnext/docs/assets/img/accounts/perpetual-2.png new file mode 100644 index 0000000000..5a2b20b21d Binary files /dev/null and b/erpnext/docs/assets/img/accounts/perpetual-2.png differ diff --git a/erpnext/docs/assets/img/accounts/perpetual-3.png b/erpnext/docs/assets/img/accounts/perpetual-3.png new file mode 100644 index 0000000000..faa77245c5 Binary files /dev/null and b/erpnext/docs/assets/img/accounts/perpetual-3.png differ diff --git a/erpnext/docs/assets/img/articles/fixed-asset-dep-1.gif b/erpnext/docs/assets/img/articles/fixed-asset-dep-1.gif deleted file mode 100644 index e6330adb87..0000000000 Binary files a/erpnext/docs/assets/img/articles/fixed-asset-dep-1.gif and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/fixed-asset-dep-2.png b/erpnext/docs/assets/img/articles/fixed-asset-dep-2.png deleted file mode 100644 index 0679403e14..0000000000 Binary files a/erpnext/docs/assets/img/articles/fixed-asset-dep-2.png and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/fixed-asset-dep-2.textClipping b/erpnext/docs/assets/img/articles/fixed-asset-dep-2.textClipping deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/docs/assets/img/articles/freeze-account-1.png b/erpnext/docs/assets/img/articles/freeze-account-1.png new file mode 100644 index 0000000000..c2f4257b86 Binary files /dev/null and b/erpnext/docs/assets/img/articles/freeze-account-1.png differ diff --git a/erpnext/docs/assets/img/articles/freeze-account-2.png b/erpnext/docs/assets/img/articles/freeze-account-2.png new file mode 100644 index 0000000000..4562a26a82 Binary files /dev/null and b/erpnext/docs/assets/img/articles/freeze-account-2.png differ diff --git a/erpnext/docs/assets/img/articles/post-dated-1.gif b/erpnext/docs/assets/img/articles/post-dated-1.gif deleted file mode 100644 index 3bb03b5984..0000000000 Binary files a/erpnext/docs/assets/img/articles/post-dated-1.gif and /dev/null differ diff --git a/erpnext/docs/assets/img/articles/post-dated-1.png b/erpnext/docs/assets/img/articles/post-dated-1.png new file mode 100644 index 0000000000..50696b7fbb Binary files /dev/null and b/erpnext/docs/assets/img/articles/post-dated-1.png differ diff --git a/erpnext/docs/assets/img/setup-wizard/step-1.png b/erpnext/docs/assets/img/setup-wizard/step-1.png new file mode 100644 index 0000000000..0a3c230ae8 Binary files /dev/null and b/erpnext/docs/assets/img/setup-wizard/step-1.png differ diff --git a/erpnext/docs/assets/img/setup/dropbox-1.png b/erpnext/docs/assets/img/setup/dropbox-1.png new file mode 100644 index 0000000000..f839d25720 Binary files /dev/null and b/erpnext/docs/assets/img/setup/dropbox-1.png differ diff --git a/erpnext/docs/assets/img/setup/dropbox-2.png b/erpnext/docs/assets/img/setup/dropbox-2.png new file mode 100644 index 0000000000..d0a65588d1 Binary files /dev/null and b/erpnext/docs/assets/img/setup/dropbox-2.png differ diff --git a/erpnext/docs/assets/img/setup/dropbox-3.png b/erpnext/docs/assets/img/setup/dropbox-3.png new file mode 100644 index 0000000000..0275597769 Binary files /dev/null and b/erpnext/docs/assets/img/setup/dropbox-3.png differ diff --git a/erpnext/docs/assets/img/setup/dropbox-open-1.png b/erpnext/docs/assets/img/setup/dropbox-open-1.png new file mode 100644 index 0000000000..cc1d57ce8b Binary files /dev/null and b/erpnext/docs/assets/img/setup/dropbox-open-1.png differ diff --git a/erpnext/docs/assets/img/setup/dropbox-open-2.png b/erpnext/docs/assets/img/setup/dropbox-open-2.png new file mode 100644 index 0000000000..969d7a7166 Binary files /dev/null and b/erpnext/docs/assets/img/setup/dropbox-open-2.png differ diff --git a/erpnext/docs/assets/img/setup/dropbox-open-3.png b/erpnext/docs/assets/img/setup/dropbox-open-3.png new file mode 100644 index 0000000000..150a95a4ec Binary files /dev/null and b/erpnext/docs/assets/img/setup/dropbox-open-3.png differ diff --git a/erpnext/docs/assets/img/users-and-permissions/permissions-lead-list.png b/erpnext/docs/assets/img/users-and-permissions/permissions-lead-list.png new file mode 100644 index 0000000000..c2fdc7cd04 Binary files /dev/null and b/erpnext/docs/assets/img/users-and-permissions/permissions-lead-list.png differ diff --git a/erpnext/docs/assets/img/users-and-permissions/user-permission-company.png b/erpnext/docs/assets/img/users-and-permissions/user-permission-company.png new file mode 100644 index 0000000000..eb529f1792 Binary files /dev/null and b/erpnext/docs/assets/img/users-and-permissions/user-permission-company.png differ diff --git a/erpnext/docs/assets/img/users-and-permissions/user-permission-quotation.png b/erpnext/docs/assets/img/users-and-permissions/user-permission-quotation.png new file mode 100644 index 0000000000..ee7a19b51a Binary files /dev/null and b/erpnext/docs/assets/img/users-and-permissions/user-permission-quotation.png differ diff --git a/erpnext/docs/assets/img/users-and-permissions/user-permission-user-limited-by-company.png b/erpnext/docs/assets/img/users-and-permissions/user-permission-user-limited-by-company.png deleted file mode 100644 index e23f1229b0..0000000000 Binary files a/erpnext/docs/assets/img/users-and-permissions/user-permission-user-limited-by-company.png and /dev/null differ diff --git a/erpnext/docs/assets/img/users-and-permissions/user-permissions-company-wind-power-llc.png b/erpnext/docs/assets/img/users-and-permissions/user-permissions-company-wind-power-llc.png deleted file mode 100644 index 6d78e5dc1e..0000000000 Binary files a/erpnext/docs/assets/img/users-and-permissions/user-permissions-company-wind-power-llc.png and /dev/null differ diff --git a/erpnext/docs/assets/img/users-and-permissions/user-permissions-company.png b/erpnext/docs/assets/img/users-and-permissions/user-permissions-company.png deleted file mode 100644 index e091a61b76..0000000000 Binary files a/erpnext/docs/assets/img/users-and-permissions/user-permissions-company.png and /dev/null differ diff --git a/erpnext/docs/assets/img/users-and-permissions/user-permissions-new.gif b/erpnext/docs/assets/img/users-and-permissions/user-permissions-new.gif new file mode 100644 index 0000000000..609bf257e2 Binary files /dev/null and b/erpnext/docs/assets/img/users-and-permissions/user-permissions-new.gif differ diff --git a/erpnext/docs/assets/old_images/erpnext/accounting-for-stock-2.png b/erpnext/docs/assets/old_images/erpnext/accounting-for-stock-2.png deleted file mode 100644 index f194360b8f..0000000000 Binary files a/erpnext/docs/assets/old_images/erpnext/accounting-for-stock-2.png and /dev/null differ diff --git a/erpnext/docs/assets/old_images/erpnext/accounting-for-stock-3.png b/erpnext/docs/assets/old_images/erpnext/accounting-for-stock-3.png deleted file mode 100644 index c6e336f8a8..0000000000 Binary files a/erpnext/docs/assets/old_images/erpnext/accounting-for-stock-3.png and /dev/null differ diff --git a/erpnext/docs/assets/old_images/erpnext/user-permissions-lead-based-on-territory.png b/erpnext/docs/assets/old_images/erpnext/user-permissions-lead-based-on-territory.png deleted file mode 100644 index e0b237329b..0000000000 Binary files a/erpnext/docs/assets/old_images/erpnext/user-permissions-lead-based-on-territory.png and /dev/null differ diff --git a/erpnext/docs/assets/old_images/erpnext/user-permissions-quotation-list.png b/erpnext/docs/assets/old_images/erpnext/user-permissions-quotation-list.png deleted file mode 100644 index 8a7e9c64ae..0000000000 Binary files a/erpnext/docs/assets/old_images/erpnext/user-permissions-quotation-list.png and /dev/null differ diff --git a/erpnext/docs/user/manual/en/accounts/articles/cheque-print.md b/erpnext/docs/user/manual/en/accounts/articles/cheque-print.md deleted file mode 100644 index 811e948fd5..0000000000 --- a/erpnext/docs/user/manual/en/accounts/articles/cheque-print.md +++ /dev/null @@ -1,36 +0,0 @@ -#Cheque Print - -** Whats is Cheque Print? ** - -You can choose to print Cheques at the time of making payments to Creditors/ parties during Voucher Entry i.e., directly from the Payment Vouchers and Inter-bank payment or transfers through Contra Vouchers. - -###Setup Cheque Print - -To enable cheque printing, - -1. Create cheque settings under `Accounts > Cheque Print Template`. - -![Cheque Print Template]({{docs_base_url}}/assets/img/articles/cueque_print_template.png) - -You can see a preview of cheque print by attaching scanned copy of cheque to avoid miss printing. - -![Cheque scanned copy]({{docs_base_url}}/assets/img/articles/attach_scanned_copy.png) - -![Cheque Print Preview]({{docs_base_url}}/assets/img/articles/cueque_print_preview.png) - -2. After saving cheque print settings, you can Create / Update print format for settings. - -To create print format, click on `Create Print Format`. - -![Create Print Format]({{docs_base_url}}/assets/img/articles/create_print_format.png) - -If you have already created a Print Format, you can update it by clicking on `Update Print Format`. - -3. You will see newly created / updated print format under Journal Entry. - -![Print from Journal Entry]({{docs_base_url}}/assets/img/articles/journal_entry_cheque_print.png) - - -###Cheque Print - -![Print from Journal Entry]({{docs_base_url}}/assets/img/articles/cheque_print.gif) diff --git a/erpnext/docs/user/manual/en/accounts/articles/depreciation-for-fixed-asset-items.md b/erpnext/docs/user/manual/en/accounts/articles/depreciation-for-fixed-asset-items.md deleted file mode 100644 index f7d1c5bef5..0000000000 --- a/erpnext/docs/user/manual/en/accounts/articles/depreciation-for-fixed-asset-items.md +++ /dev/null @@ -1,41 +0,0 @@ -#Depreciation for Fixed Asset Items - -Depreciation is when you write off certain value of your assets as an expense. For example, office computer will be used for five years. Hence total value of computer should be booked as expense over the period of five years. - -As per perpetual inventory valuation system (set by default), you should create Stock Reconciliation for depreciating value of fixed asset items. Check below steps to learn more. - -#### Step 1: Depreciation Account - -Depreciation account is auto-created, under Indirect Expenses account. - -Project Default Cost Center - -#### Step 2: Stock Reconciliation - -To create new Stock Reconciliation, go to: - -`Stock > Setup > Stock Reconciliation > New` - -Set Posting Date and Time of Stock Reconciliation will when you wish depreciation entry to be posted in your accounts. - -#### Step 3: Item - -Select Fixed Asset Items in the item table. Update Warehouse of an item. For item valuation, update post-depreciation value. For example, item value was 100. Depreciation amount is 20. As per this post-depreciation valuation of an item will be 80. Hence 80 should be posted as valuation in the Stock Reconciliation. - -Project Default Cost Center - -#### Step 4: Depreciation Account - -Select Depereciation Account in which depereciation amount will be booked. - -Project Default Cost Center - -#### Step 5: Submit - -On submission of Stock Reconciliation, depreciation will booked for items asset items. - -Project Default Cost Center - -Click [here]({{docs_base_url}}/user/manual/en/setting-up/stock-reconciliation-for-non-serialized-item.html) for steps to be followed when making Stock Reconciliation entry. - - \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/accounts/articles/how-to-freeze-accounting-ledger.md b/erpnext/docs/user/manual/en/accounts/articles/how-to-freeze-accounting-ledger.md index f21bf2d99e..80aed6d40e 100644 --- a/erpnext/docs/user/manual/en/accounts/articles/how-to-freeze-accounting-ledger.md +++ b/erpnext/docs/user/manual/en/accounts/articles/how-to-freeze-accounting-ledger.md @@ -1,28 +1,36 @@ #How To Freeze Accounting Ledger? -You can freeze any accounting ledger in ERPNext. So that frozen accounting ledger became unsearchable in accounting transaction. Follow below step to understand the process. +If you want to discontinue using specific Account, you can freeze it. -#### 1. Set Frozen Accounts Modifier +>Account can be Frozen by the User having specific Role. This Role for set in the Account Settings, in the field "Role Allowed to Set Frozen Accounts & Edit Frozen Entries". -To set frozen accounts modifier go to `Accounts > Setup > Accounts Setting` +Please check following steps to freeze an Account from the Chart of Accounts master. -Search and select Role under Frozen Accounts Modifier field and save the Account Settings form. - -![Account Settings]({{docs_base_url}}/assets/img/articles/Selection_001f1e2ff.png) +####Step 1: Chart of Accounts -#### 2. Edit Accounting Ledger. +To edit an Account, go to Chart of Accounts: -To edit accounting ledger go to `Accounts > Setup > Chart of Accounts` +`Explore > Accounts > Chart of Accounts` -![Account Settings]({{docs_base_url}}/assets/img/articles/Selection_0027e4d09.png) +Freeze Account -#### 3. Set Frozen Status of Ledger. +Click on Account in which Frozen Date is to be updated. -![Account Settings]({{docs_base_url}}/assets/img/articles/Selection_003bf981b.png) +####Step 2: Set Account as Frozen + +In the Account form, you will find a field called **Frozen**. Set value in this field as 'Yes' + +Freeze Account + +####Step 3: Save + +After update Save an Account. + +On saving, this Account will be frozen and will not be selectable in any accounting transaction. + +
Note: In future, if you want to make an accounting transaction against this Account, then you can unfreeze this account by setting values in the Frozen field as 'No'.
-Set Frozen field status of ledger as 'Yes' and save the ledger form. On save this ledger will be frozen and you will became unable to search this ledger in accounting transactions. -
Note: If you want to make accounting transaction against this ledger in the future, then that time again set frozen field status as 'No'.
\ No newline at end of file diff --git a/erpnext/docs/user/manual/en/accounts/articles/index.txt b/erpnext/docs/user/manual/en/accounts/articles/index.txt index d54f0cda8e..c2fbf70726 100644 --- a/erpnext/docs/user/manual/en/accounts/articles/index.txt +++ b/erpnext/docs/user/manual/en/accounts/articles/index.txt @@ -1,7 +1,5 @@ tracking-project-profitability-using-cost-center -c-form changing-parent-account -depreciation-for-fixed-asset-items difference-entry-button fiscal-year-error freeze-accounting-entries @@ -13,4 +11,4 @@ post-dated-cheque-entry update-stock-option-in-sales-invoice what-is-the-differences-of-total-and-valuation-in-tax-and-charges withdrawing-salary-from-owners-equity-account -cheque-print \ No newline at end of file +c-form \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/accounts/articles/post-dated-cheque-entry.md b/erpnext/docs/user/manual/en/accounts/articles/post-dated-cheque-entry.md index 66da24e8e0..0b61000686 100644 --- a/erpnext/docs/user/manual/en/accounts/articles/post-dated-cheque-entry.md +++ b/erpnext/docs/user/manual/en/accounts/articles/post-dated-cheque-entry.md @@ -1,32 +1,32 @@ #Post Dated Cheque Entry -Post Dated Cheque is a cheque dated on future date. Party generally give post dated cheque, as advance payment. This cheque would be cleared only after cheque date has arrived. +Post Dated Cheque is a cheque dated on future date. Party generally give post dated cheque, as advance payment. This cheque would be cleared only when cheque date arrives. -In ERPNext, create Journal Entries for post dated cheque. +In ERPNext, create Payment Entry for post dated cheque. -####New Journal Entry +####New Payment Entry To open new journal voucher go to -`Accounts > Documents > Journal Entry > New` +`Explore > Accounts > Payment Entry > New` #### Set Posting Date Assuming your Cheque Date is 31st December, 2016 (or any future date). As a result, this posting in your bank ledger will appear on Posting Date updated. -JE Posting Date +JE Posting Date -Note: Journal Voucher Reference Date should equal to or less than Posting Date. +Note: Payment Entry Reference Date should equal to or less than Posting Date. ####Step 3: Save and Submit -After entering required details, Save and Submit the Journal Entry. +After entering required details, Save and Submit the Payment Entry. ####Adjusting Post Dated Cheque Entry -If Post Dated Journal Entry needs to be adjusted against any invoice, it can be accomplished via [Payment Reconciliation Tool]({{docs_base_url}}/user/manual/en/accounts/tools/payment-reconciliation.html). +You can adjust Post Dated Payment Entry against an invoice via [Payment Reconciliation Tool]({{docs_base_url}}/user/manual/en/accounts/tools/payment-reconciliation.html). When cheque is cleared, i.e. on actual date on the cheque, you can update its Clearance Date via [Bank Reconciliation Tool]({{docs_base_url}}/user/manual/en/accounts/tools/bank-reconciliation.html). -You might find value of this Journal Entry already reflecting against bank's ledger. You should check **Bank Reconciliation Statement**, a report in the account module to know difference of bank balance as per system, and actual balance in a account. +In the Chart of Accounts, you might find value of this Payment Entry already reflecting against bank Account. You should check **Bank Reconciliation Statement**, a report in the account module to know difference of bank balance as per system, and actual balance in the bank's statement. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/articles/setting-up-dropbox-backups.html b/erpnext/docs/user/manual/en/setting-up/articles/setting-up-dropbox-backups.html deleted file mode 100644 index 1b7e4f7977..0000000000 --- a/erpnext/docs/user/manual/en/setting-up/articles/setting-up-dropbox-backups.html +++ /dev/null @@ -1,74 +0,0 @@ -

Setting Up Dropbox Backups

- -

Setting Up Dropbox Backups

- -

If you wish to store your backups on a periodic basis,on Dropbox, you can do it directly through ERPNext.

-
-

Setup > Manage 3rd Party Backups

-
-

Step 1: Click on Integrations > Backup Manager -
-

-
-
-

In the Backup Manager page, enter the email addresses of those people whom you wish to notify about the upload status. Under the topic 'Sync with Dropbox', select whether you wish to upload Daily, Weekly or Never.

-

Step 2 Click on Allow Dropbox Access.

-
-

Tip: In future, if you wish to discontinue uploading backups to dropbox, then select the Never option.

-
- -
-
  -
-
-
- Step 3 -
-
-
-

You need to login to your dropbox account, with your user id and password.

-
-
-   -
-
-
-
-
-
-
-

Open Source Users

- -
-
-
-
-
Step 1: Go to https://www.dropbox.com/developers/apps - -
-
Step 2: Create a new app
-
- -
-
-
Step 3: Fill in details for the app.
-
- -
-
-
-
-
-
Step 4: After the app is created, note the app key and app secret and enter in `sites/{sitename}/site_config.json` as follows,
-
-
-
-
{ 
- "db_name": "demo", 
- "db_password": "DZ1Idd55xJ9qvkHvUH", 
- "dropbox_access_key": "ACCESSKEY", 
- "dropbox_secret_key": "SECRECTKEY" 
-} 
-
-
-
Step 5: Setup dropbox backups from the backup manager as shown in previous section.
\ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/articles/setting-up-dropbox-backups.md b/erpnext/docs/user/manual/en/setting-up/articles/setting-up-dropbox-backups.md new file mode 100644 index 0000000000..68e4031281 --- /dev/null +++ b/erpnext/docs/user/manual/en/setting-up/articles/setting-up-dropbox-backups.md @@ -0,0 +1,74 @@ +#Setting Up Dropbox Backups + +We always recommend customers to maintain backup of their data in ERPNext. he database backup is downloaded in the form of an SQL file. If needed, this SQL file of backup can be restored in the another ERPNext account as well. + +You can automate database backup download of your ERPNext account into your Dropbox account. + +####Step 1: Go to Setup + +`Explore > Setup > Integrations > Dropbox Backup` + +####Step 2: Activate + +In the Dropbox Backup, check "Send Backups to Dropbox" to active this feature. On checking this field, you will find field to set Frequency and notification Email. + +####Step 3: Set Frequency + +Set Frequency to download backup in your Dropbox account. + +set frequency + +####Step 4: Allow Dropbox Access + +After setting frequency and updating notification email, click on `Allow Dropbox access`. On clicking this button, the Dropbox login page will open in the new tab. This might require you to allow pop-up for your ERPNext account. + +####Step 5: Login to Dropbox + +Login to your Dropbox account by entering login credentials. + +Login + +####Step 6: Allow + +On successfull login, you will find a confirmation message as following. Click on "Allow" to let your ERPNext account have access to your Dropbox account. + +Allow + +With this, a folder called "ERPNext" will be created in your Dropbox account, and database backup will start to auto-download in it. + +##Open Source Users + +####Step 1: Go to + +https://www.dropbox.com/developers/apps + +####Step 2:Create a new app + +Create new + +####Step 3: Fill in details for the app + +Create new + +- +Create new + +####Step 4: Settings in Site Config + +After the app is created, note the app key and app secret and enter in `sites/{sitename}/site_config.json` as follows, + +
+
+		{ 
+ "db_name": "demo", 
+ "db_password": "DZ1Idd55xJ9qvkHvUH", 
+ "dropbox_access_key": "ACCESSKEY", 
+ "dropbox_secret_key": "SECRECTKEY" 
+} 		
+		
+	
+
+ +####Step 5: Complete Backup + +Setup dropbox backups from the backup manager as shown in previous section. \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/print/letter-head.md b/erpnext/docs/user/manual/en/setting-up/print/letter-head.md index d3c24f2247..72b79e1ad9 100644 --- a/erpnext/docs/user/manual/en/setting-up/print/letter-head.md +++ b/erpnext/docs/user/manual/en/setting-up/print/letter-head.md @@ -1,23 +1,38 @@ -# Letter Heads +#Letter Head -You can manage multiple letter heads in ERPNext. In a letter head you can: +Each company has default Letter Head for their company. This Letter Head values are generally set as Header and Footer in the documents. In ERPNext, you can capture the these details in the Letter Head master. - * Create an image with your logo, brand and other information that you want to put on your letter head. - * Attach the image in your Letter Head record by clicking on image icon to automatically generate the HTML required for this Letter Head. - * If you want to make this the default letter head, click on “Is Default”. +In the Letter Head master, you can track Header and Footer details of the company. These details will appear in the Print Format of the transactions like Sales Order, Sales Invoice, Salary Slip, Purchase Order etc. -Your letter head will now appear in all Prints and Emails of documents. +####Step 1: Go to Setup -You can create / manage Letter Heads from: +`Explore > Setup > Printing > Letter Head > New Letter Head` -> Setup > Printing > Letter Head > New Letter Head +####Step 2: Letter Head Name -### Example +In one ERPNext account, you can enter multiple Letter Head, hence name Letter Head so that you can identify it easily. For example, if your Letter Head also contains office address, then you should create separate Letter Head for each office location. + +####Step 3: Enter Details + +Following is how you can enter details in the Letter Head. + + * Logo Image: You can insert the image in your Letter Head record by clicking on image icon. Once image is inserted, HTML for it will be generated automatically. + * Other information (like Address, tax ID etc.) that you want to put on your letter head. Print Heading + +> If you want to make this the default letter head, click on “Is Default”. -This is how the letter head looks in a document print: +####Step 4: Save + +After enter values in the Header and Footer section, Save Letter Head. + +####Letter Head in the Print Format + +This is how the letter head looks in a document's print. Print Heading -{next} +> Please note that Footer will be visible only when document's print is seen in the PDF. Footer will not be visible in the HTML based print preview. + +{next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/setting-up/users-and-permissions/user-permissions.md b/erpnext/docs/user/manual/en/setting-up/users-and-permissions/user-permissions.md index c1cefc6037..7fae95cbe7 100644 --- a/erpnext/docs/user/manual/en/setting-up/users-and-permissions/user-permissions.md +++ b/erpnext/docs/user/manual/en/setting-up/users-and-permissions/user-permissions.md @@ -1,72 +1,60 @@ # User Permissions -Limit access for a User to a set of documents using User Permissions Manager - Role Base Permissions define the periphery of document types within which a user with a set of Roles can move around in. However, you can have an even finer control by defining User Permissions for a User. By setting specific documents in User Permissions list, you can limit access for that User to specific documents of a particular DocType, on the condition that "Apply User Permissions" is checked in Role Permissions Manager. To start with, go to: + > Setup > Permissions > User Permissions Manager -
- User Permissions Manager -
User Permissions Manager displaying how users can access only a specific Company.
-
+User Permissions Manager displaying how users can access only a specific Company. #### Example -User 'aromn@example.com' has Sales User role and we want to limit the user to access records for only a specific Company 'Wind Power LLC'. +User 'tom.hagen@riosolutions.com' has Sales User role and we want to limit the user to access records for only a specific Company 'Rio Solutions'. 1. We add a User Permissions row for Company. -
- User Permissions For Company -
Add User Permissions row for a combination of User 'aromn@example.com' and Company 'Wind Power LLC'.
-
+ + User Permissions For Company + + Add User Permissions row for a combination of User 'tom.hagen@riosolutions.com' and Company 'Rio Solutions'. 1. Also Role "All" has only Read permission for Company, with 'Apply User Permissions' checked. -
- Role Permissions for All on Company -
Read Permission with Apply User Permissions checked for DocType Company.
-
+ + Role Permissions for All on Company - 1. The combined effect of the above two rules lead to User 'aromn@example.com' having only Read access to Company 'Wind Power LLC'. -
- Effect of Role and User Permissions on Company -
Access is limited to Company 'Wind Power LLC'.
-
+ Read Permission with Apply User Permissions checked for DocType Company. + + 1. The combined effect of the above two rules lead to User 'tom.hagen@riosolutions.com' having only Read access to Company 'Rio Solutions'. + + Effect of Role and User Permissions on Company + + Access is limited to Company 'Rio Solutions'. 1. We want this User Permission on Company to get applied on other documents like Quotation, Sales Order, etc. -These forms have a **Link Field based on Company**. As a result, User Permissions on Company also get applied on these documents, which leads to User 'aromn@example.com' to acces these documents having Company 'Wind Power LLC'. -
- Sales User Role Permissions for Quotation -
Users with Sales User Role can Read, Write, Create, Submit and Cancel Quotations based on their User Permissions, since 'Apply User Permissions' is checked.
-
-
- Quotation List limited to results for Company 'Wind Power LLC' -
Quotation List is limited to results for Company 'Wind Power LLC' for User 'aromn@example.com'.
-
+ + These forms have a **Link Field based on Company**. As a result, User Permissions on Company also get applied on these documents, which leads to User 'tom.hagen@riosolutions' to acces these documents having Company 'Rio Solutions'. - 1. User Permissions get applied automatically based on Link Fields, just like how it worked for Quotation. But, Lead Form has 4 Link fields: Territory, Company, Lead Owner and Next Contact By. Say, you want Leads to limit access to Users based only on Territory, even though you have defined User Permissions for DocTypes User, Territory and Company. You can do this by setting 'Ignore User Permissions' for Link fields: Company, Lead Owner and Next Contact By. -
- Role Permissions on Lead for Sales User Role -
Sales User can Read, Write and Create Leads limited by User Permissions.
-
-
- Set Ingore User Permissions from Setup > Customize > Customize Form -
Check 'Ingore User Permissions' for Company, Lead Owner and Next Contact By fields using Setup > Customize > Customize Form for Lead.
-
-
- Lead List is limited to records with Territory 'United States' -
Due to the effect of the above combination, User 'aromn@example.com' can only access Leads with Territory 'United States'.
-
+ Sales User Role Permissions for Quotation + + Users with Sales User Role can Read, Write, Create, Submit and Cancel Quotations based on their User Permissions, since 'Apply User Permissions' is checked. + + Quotation List limited to results for Company 'Rio Solutions' + + Quotation List is limited to results for Company 'Rio Solutions' for User 'tom.hagen@riosolutions.com'. + + 1. User Permissions get applied automatically based on Link Fields, just like how it worked for Quotation. But, Lead Form has 4 Link fields: Territory, Company, Lead Owner and Next Contact By. Say, you want Leads to limit access to Users based only on Territory, even though you have defined User Permissions for DocTypes User, Territory and Company. You can do this by setting 'Ignore User Permissions' for Link fields: Company, Lead Owner and Next Contact By. + +Role Permissions on Lead for Sales User Role + +Sales User can Read, Write and Create Leads limited by User Permissions. + +Set Ingore User Permissions from Setup > Customize > Customize Form + +Check 'Ingore User Permissions' for Company, Lead Owner and Next Contact By fields using Setup > Customize > Customize Form for Lead. + +Lead List is limited to records with Territory 'United States' + +Due to the effect of the above combination, User 'tom.hagen@riosolutions.com' can only access Leads with Territory 'United States'. {next} diff --git a/erpnext/docs/user/manual/en/stock/accounting-of-inventory-stock/perpetual-inventory.md b/erpnext/docs/user/manual/en/stock/accounting-of-inventory-stock/perpetual-inventory.md index c31d1ac78f..84fe545174 100644 --- a/erpnext/docs/user/manual/en/stock/accounting-of-inventory-stock/perpetual-inventory.md +++ b/erpnext/docs/user/manual/en/stock/accounting-of-inventory-stock/perpetual-inventory.md @@ -1,42 +1,38 @@ -In perpetual inventory, system creates accounting entries for each stock -transactions, so that stock and account balance will always remain same. The -account balance will be posted against their respective account heads for each -Warehouse. On saving of a Warehouse, the system will automatically create an -account head with the same name as warehouse. As account balance is maintained -for each Warehouse, you should create Warehouses, based on the type of items -(Current / Fixed Assets) it stores. +As per the perpetual inventory system, accounts posting is done for every stock transaction. -At the time of items received in a particular warehouse, the balance of asset -account (linked to that warehouse) will be increased. Similarly when you -deliver some items from that warehouse, an expense will be booked and the -asset account will be reduced, based on the valuation amount of those items. +On creating new Warehouse, the system will automatically create an Account in the Chart of Accout, with the same name as Warehouse Name. -## **Activation** +On receipt of items in a particular warehouse, the balance in the Warehouse Account will increase. Similarly when items are delivered from the Warehouse, an expense will be booked, and balance in the Warehouse Account will reduce. - 1. Setup the following default accounts for each Company +##Activation + + 1. Setup the following default accounts for each Company. These accounts are created automatically in the new ERPNext accounts. * Stock Received But Not Billed * Stock Adjustment Account * Expenses Included In Valuation * Cost Center - 2. In perpetual inventory, the system will maintain separate account balance for each warehouse under separate account head. To create that account head, enter "Create Account Under" in Warehouse master. + + 2. Ensure each Warehouse is an Account in the Chart of Accounts master. As per the default configuration, Accounts for Warehouse are created under `Assets > Current Asset > Stock Assets > (Warehouse)` 3. Activate Perpetual Inventory -> Setup > Accounts Settings > Make Accounting Entry For Every Stock Movement + > Explore > Accounts > Accounts Settings > "Make Accounting Entry For Every Stock Movement" + +Perpetual Inventory * * * -## **Example** +##Example Consider following Chart of Accounts and Warehouse setup for your company: -#### Chart of Accounts +####Chart of Accounts * Assets (Dr) * Current Assets * Accounts Receivable - * Jane Doe + * Debtor * Stock Assets * Stores * Finished Goods @@ -44,11 +40,11 @@ Consider following Chart of Accounts and Warehouse setup for your company: * Tax Assets * VAT * Fixed Assets - * Fixed Asset Warehouse + * Fixed Asset Warehouse * Liabilities (Cr) * Current Liabilities * Accounts Payable - * East Wind Inc. + * Creditors * Stock Liabilities * Stock Received But Not Billed * Tax Liabilities @@ -65,18 +61,15 @@ Consider following Chart of Accounts and Warehouse setup for your company: * Shipping Charges * Customs Duty -#### Warehouse - Account Configuration +####Warehouse - Account Configuration * Stores * Work In Progress * Finished Goods - * Fixed Asset Warehouse -### **Purchase Receipt** +###Purchase Receipt -Suppose you have purchased _10 nos_ of item "RM0001" at _$200_ and _5 nos_ of -item "Desktop" at **$100** from supplier "East Wind Inc". Following are the -details of Purchase Receipt: +Suppose you have purchased _10 nos_ of item "RM0001" at _$200_ and _5 nos_ of item "Base Plate" at **$100** from supplier "East Wind Inc". Following are the details of Purchase Receipt: **Supplier:** East Wind Inc. @@ -100,15 +93,7 @@ details of Purchase Receipt: 10 200 2000 - 2200 - - - Desktop - Fixed Asset Warehouse - 5 - 100 - 500 - 550 + 2250 @@ -129,8 +114,8 @@ details of Purchase Receipt: Total and Valuation - VAT - 120 + VAT (10%) + 200 Total @@ -140,25 +125,22 @@ details of Purchase Receipt: -

Stock Ledger -

-Stock +**Stock Ledger** + +Perpetual Inventory **General Ledger** -Leger +Perpetual Inventory -As stock balance increases through Purchase Receipt, "Store" and "Fixed Asset -Warehouse" accounts are debited and a temporary account "Stock Receipt But Not -Billed" account is credited, to maintain double entry accounting system. At the same time, negative expense is booked in account "Expense included in Valuation" for the amount added for valuation purpose, to avoid double expense booking. +As stock balance increases through Purchase Receipt, "Store" accounts are debited and a temporary account "Stock Receipt But Not Billed" account is credited, to maintain double entry accounting system. At the same time, negative expense is booked in account "Expense included in Valuation" for the amount added for valuation purpose, to avoid double expense booking. * * * -### **Purchase Invoice** +###Purchase Invoice -On receiving Bill from supplier, for the above Purchase Receipt, you will make -Purchase Invoice for the same. The general ledger entries are as follows: +On receiving Bill from supplier, for the above Purchase Receipt, you will make Purchase Invoice for the same. The general ledger entries are as follows: **General Ledger** @@ -169,7 +151,7 @@ effect of Purchase Receipt. * * * -### **Delivery Note** +###Delivery Note Lets say, you have an order from "Jane Doe" to deliver 5 nos of item "RM0001" at $300. Following are the details of Delivery Note: @@ -246,7 +228,7 @@ valuation method (FIFO / Moving Average) or actual cost of serialized items. * * * -### **Sales Invoice with Update Stock** +###Sales Invoice with Update Stock Lets say, you did not make Delivery Note against the above order and instead you have made Sales Invoice directly, with "Update Stock" options. The details @@ -265,7 +247,7 @@ Goods Sold" accounts are also affected based on the valuation amount. * * * -### **Stock Entry (Material Receipt)** +###Stock Entry (Material Receipt) **Items:** @@ -300,7 +282,7 @@ Goods Sold" accounts are also affected based on the valuation amount. * * * -### **Stock Entry (Material Issue)** +###Stock Entry (Material Issue) **Items:** @@ -335,7 +317,7 @@ Goods Sold" accounts are also affected based on the valuation amount. * * * -### **Stock Entry (Material Transfer)** +###Stock Entry (Material Transfer) **Items:** diff --git a/erpnext/docs/user/manual/en/website/shopping-cart.md b/erpnext/docs/user/manual/en/website/shopping-cart.md index 773e1628df..16820842c6 100644 --- a/erpnext/docs/user/manual/en/website/shopping-cart.md +++ b/erpnext/docs/user/manual/en/website/shopping-cart.md @@ -14,14 +14,10 @@ To set up a shopping cart, go to the selling module. ![Shopping Cart]({{docs_base_url}}/assets/old_images/erpnext/shopping-cart-1.png) - - #### Step 2: Enter Price List, Tax Master and Shipping Rule. ![Shopping Cart]({{docs_base_url}}/assets/old_images/erpnext/shopping-cart-2.png) - - #### Shopping Cart Display On the Website, the shopping cart image will be seen below the Item price. @@ -31,8 +27,6 @@ to the flower sign. ![Shopping Cart]({{docs_base_url}}/assets/old_images/erpnext/shopping-cart-display-1.png) - - Click on the flower sign on the right hand side to see the cart details. Click on the cart to get the final amount details. diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py index 836e524015..c2f95af904 100644 --- a/erpnext/hr/doctype/salary_structure/salary_structure.py +++ b/erpnext/hr/doctype/salary_structure/salary_structure.py @@ -99,7 +99,7 @@ def make_salary_slip(source_name, target_doc=None): for d in source.get(key): target.append(key, { 'amount': d.amount, - 'default_amount': d.default_amount, + 'default_amount': d.amount, 'depends_on_lwp' : d.depends_on_lwp, 'salary_component' : d.salary_component }) diff --git a/erpnext/patches/v5_2/change_item_selects_to_checks.py b/erpnext/patches/v5_2/change_item_selects_to_checks.py index dde0b56eeb..1ee8f6caa5 100644 --- a/erpnext/patches/v5_2/change_item_selects_to_checks.py +++ b/erpnext/patches/v5_2/change_item_selects_to_checks.py @@ -4,8 +4,7 @@ import frappe def execute(): fields = ("is_stock_item", "is_asset_item", "has_batch_no", "has_serial_no", - "inspection_required", "is_sub_contracted_item") - + "is_sales_item", "is_purchase_item", "inspection_required", "is_sub_contracted_item") # convert to 1 or 0 update_str = ", ".join(["`{0}`=if(`{0}`='Yes',1,0)".format(f) for f in fields]) diff --git a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py index 072ba13cd0..b802656f7f 100644 --- a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py +++ b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py @@ -1,23 +1,30 @@ import frappe from erpnext.manufacturing.doctype.production_order.production_order \ import make_timesheet, add_timesheet_detail -from erpnext.projects.doctype.timesheet.timesheet import OverlapError def execute(): frappe.reload_doc('projects', 'doctype', 'timesheet') for data in frappe.get_all('Time Log', fields=["*"], filters = [["docstatus", "<", "2"]]): - try: - time_sheet = make_timesheet(data.production_order) - args = get_timelog_data(data) - add_timesheet_detail(time_sheet, args) - time_sheet.docstatus = data.docstatus - time_sheet.note = data.note - time_sheet.company = frappe.db.get_single_value('Global Defaults', 'default_company') - time_sheet.save(ignore_permissions=True) - except OverlapError: - time_sheet.flags.ignore_validate = True - time_sheet.save(ignore_permissions=True) + if data.task: + company = frappe.db.get_value("Task", data.task, "company") + elif data.production_order: + company = frappe.db.get_value("Prodction Order", data.production_order, "company") + else: + company = frappe.db.get_single_value('Global Defaults', 'default_company') + + time_sheet = make_timesheet(data.production_order) + args = get_timelog_data(data) + add_timesheet_detail(time_sheet, args) + time_sheet.docstatus = data.docstatus + time_sheet.note = data.note + time_sheet.company = company + + time_sheet.set_status() + time_sheet.update_cost() + time_sheet.calculate_total_amounts() + time_sheet.flags.ignore_validate = True + time_sheet.save(ignore_permissions=True) def get_timelog_data(data): return { diff --git a/erpnext/patches/v7_0/make_guardian.py b/erpnext/patches/v7_0/make_guardian.py index f654b796f4..0839c4f624 100644 --- a/erpnext/patches/v7_0/make_guardian.py +++ b/erpnext/patches/v7_0/make_guardian.py @@ -2,19 +2,25 @@ from __future__ import unicode_literals import frappe def execute(): - if frappe.db.exists("DocType", "Student") and "father_name" in frappe.db.get_table_columns("Student"): - frappe.reload_doc("schools", "doctype", "student") - frappe.reload_doc("schools", "doctype", "guardian") - frappe.reload_doc("schools", "doctype", "guardian_interest") - frappe.reload_doc("hr", "doctype", "interest") + if frappe.db.exists("DocType", "Student"): + student_table_cols = frappe.db.get_table_columns("Student") + if "father_name" in student_table_cols: + frappe.reload_doc("schools", "doctype", "student") + frappe.reload_doc("schools", "doctype", "guardian") + frappe.reload_doc("schools", "doctype", "guardian_interest") + frappe.reload_doc("hr", "doctype", "interest") + + fields = ["name", "father_name", "mother_name"] + + if "father_email_id" in student_table_cols: + fields += ["father_email_id", "mother_email_id"] - students = frappe.get_all("Student", fields=["name", "father_name", "father_email_id", - "mother_name", "mother_email_id"]) - for stud in students: - if stud.father_name: - make_guardian(stud.father_name, stud.name, stud.father_email_id) - if stud.mother_name: - make_guardian(stud.mother_name, stud.name, stud.mother_email_id) + students = frappe.get_all("Student", fields) + for stud in students: + if stud.father_name: + make_guardian(stud.father_name, stud.name, stud.father_email_id) + if stud.mother_name: + make_guardian(stud.mother_name, stud.name, stud.mother_email_id) def make_guardian(name, student, email=None): frappe.get_doc({ diff --git a/erpnext/patches/v7_0/migrate_schools_to_erpnext.py b/erpnext/patches/v7_0/migrate_schools_to_erpnext.py index 80e9eac896..f64f400feb 100644 --- a/erpnext/patches/v7_0/migrate_schools_to_erpnext.py +++ b/erpnext/patches/v7_0/migrate_schools_to_erpnext.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals import frappe, os +from frappe.installer import remove_from_installed_apps def execute(): reload_doctypes_for_schools_icons() @@ -10,18 +11,15 @@ def execute(): if 'schools' in frappe.get_installed_apps(): frappe.db.sql("""delete from `tabDesktop Icon`""") - if not frappe.db.exists('Module Def', 'Schools'): - frappe.get_doc({ - 'doctype': 'Module Def', - 'module_name': 'Schools', - 'app_name': 'erpnext' - }).insert() - frappe.db.sql("""update `tabDocType` set module='Schools' where module='Academics'""") - from frappe.installer import remove_from_installed_apps + + if not frappe.db.exists('Module Def', 'Schools') and frappe.db.exists('Module Def', 'Academics'): + frappe.rename_doc("Module Def", "Academics", "Schools") + remove_from_installed_apps("schools") def reload_doctypes_for_schools_icons(): base_path = frappe.get_app_path('erpnext', 'schools', 'doctype') for doctype in os.listdir(base_path): - if os.path.exists(os.path.join(base_path, doctype, doctype + '.json')): - frappe.reload_doc('schools', 'doctype', doctype) + if os.path.exists(os.path.join(base_path, doctype, doctype + '.json')) \ + and doctype not in ("fee_component", "assessment", "assessment_result"): + frappe.reload_doc('schools', 'doctype', doctype) \ No newline at end of file diff --git a/erpnext/patches/v7_0/rename_examination_to_assessment.py b/erpnext/patches/v7_0/rename_examination_to_assessment.py index 3c79c51763..1d6e688282 100644 --- a/erpnext/patches/v7_0/rename_examination_to_assessment.py +++ b/erpnext/patches/v7_0/rename_examination_to_assessment.py @@ -9,7 +9,9 @@ from frappe.model.utils.rename_field import rename_field def execute(): if frappe.db.exists("DocType", "Examination"): frappe.rename_doc("DocType", "Examination", "Assessment") - frappe.reload_doctype("Assessment") + frappe.rename_doc("DocType", "Examination Result", "Assessment Result") + frappe.reload_doc("schools", "doctype", "assessment") + frappe.reload_doc("schools", "doctype", "assessment_result") rename_field("Assessment", "exam_name", "assessment_name") rename_field("Assessment", "exam_code", "assessment_code") diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 9140927279..0379f906de 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -159,8 +159,8 @@ class Timesheet(Document): existing = self.get_overlap_for(fieldname, args, value) if existing: - frappe.throw(_("Row {0}: From Time and To Time overlap with existing from and to time").format(args.idx), - OverlapError) + frappe.throw(_("Row {0}: From Time and To Time of {1} is overlapping with {2}") + .format(args.idx, self.name, existing.name), OverlapError) def get_overlap_for(self, fieldname, args, value): cond = "ts.`{0}`".format(fieldname) diff --git a/erpnext/public/css/erpnext.css b/erpnext/public/css/erpnext.css index d67f9e0731..535f83a73d 100644 --- a/erpnext/public/css/erpnext.css +++ b/erpnext/public/css/erpnext.css @@ -138,12 +138,14 @@ font-size: 15px; } .pos-payment-row .col-xs-6 { - padding: 10px; + padding: 15px; } .pos-payment-row { border-bottom: 1px solid #d1d8dd; margin: 2px 0px 5px 0px; height: 60px; + margin-top: 0px; + margin-bottom: 0px; } .pos-payment-row:hover, .pos-keyboard-key:hover { @@ -203,3 +205,8 @@ body[data-route="pos"] .modal-dialog { .pos-invoice-list { padding: 15px 10px; } +.write_off_amount, +.change_amount { + margin: 15px; + width: 130px; +} diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 576bc7137b..c3f4b70043 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -615,4 +615,18 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ this.frm.doc.base_change_amount = flt(this.frm.doc.change_amount * this.frm.doc.conversion_rate, precision("base_change_amount")); }, + + calculate_write_off_amount: function(){ + if(this.frm.doc.paid_amount > this.frm.doc.grand_total){ + this.frm.doc.write_off_amount = flt(this.frm.doc.grand_total - this.frm.doc.paid_amount + this.frm.doc.change_amount, + precision("write_off_amount")) + + this.frm.doc.base_write_off_amount = flt(this.frm.doc.write_off_amount * this.frm.doc.conversion_rate, + precision("base_write_off_amount")); + }else{ + this.frm.doc.paid_amount = 0.0 + } + + this.calculate_outstanding_amount(false) + } }) diff --git a/erpnext/public/js/payment/payment_details.html b/erpnext/public/js/payment/payment_details.html index 18f9d03885..596f139ea0 100644 --- a/erpnext/public/js/payment/payment_details.html +++ b/erpnext/public/js/payment/payment_details.html @@ -1,5 +1,5 @@
-
{{mode_of_payment}}
+
{{mode_of_payment}}
diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js index 7437f2a648..06df425262 100644 --- a/erpnext/public/js/payment/payments.js +++ b/erpnext/public/js/payment/payments.js @@ -13,6 +13,14 @@ erpnext.payments = erpnext.stock.StockController.extend({ this.$body = this.dialog.body; this.set_payment_primary_action(); this.make_keyboard(); + this.select_text() + }, + + select_text: function(){ + var me = this; + $(this.$body).find('.form-control').click(function(){ + $(this).select(); + }) }, set_payment_primary_action: function(){ @@ -20,7 +28,7 @@ erpnext.payments = erpnext.stock.StockController.extend({ this.dialog.set_primary_action(__("Submit"), function() { me.dialog.hide() - me.write_off_amount() + me.submit_invoice() }) }, @@ -78,7 +86,7 @@ erpnext.payments = erpnext.stock.StockController.extend({ //When user first time click on row this.payment_val = flt(this.frm.doc.outstanding_amount) this.selected_mode.val(format_number(this.payment_val, 2)); - this.update_paid_amount() + this.update_payment_amount() }else if(flt(this.selected_mode.val()) > 0){ //If user click on existing row which has value this.payment_val = flt(this.selected_mode.val()); @@ -90,17 +98,29 @@ erpnext.payments = erpnext.stock.StockController.extend({ bind_keyboard_event: function(){ var me = this; this.payment_val = ''; - this.bind_payment_mode_keys_event(); - this.bind_keyboard_keys_event(); + this.bind_form_control_event(); + this.bind_numeric_keys_event(); }, - bind_payment_mode_keys_event: function(){ + bind_form_control_event: function(){ var me = this; $(this.$body).find('.pos-payment-row').click(function(){ - if(me.frm.doc.outstanding_amount > 0){ - me.idx = $(this).attr("idx"); - me.set_outstanding_amount() - } + me.idx = $(this).attr("idx"); + me.set_outstanding_amount() + }) + + $(this.$body).find('.form-control').click(function(){ + me.idx = $(this).attr("idx"); + me.set_outstanding_amount(); + me.update_paid_amount(); + }) + + $(this.$body).find('.write_off_amount').change(function(){ + me.write_off_amount(flt($(this).val())); + }) + + $(this.$body).find('.change_amount').change(function(){ + me.change_amount(flt($(this).val())); }) }, @@ -113,13 +133,13 @@ erpnext.payments = erpnext.stock.StockController.extend({ this.selected_mode.attr('disabled', false); }, - bind_keyboard_keys_event: function(){ + bind_numeric_keys_event: function(){ var me = this; $(this.$body).find('.pos-keyboard-key').click(function(){ me.payment_val += $(this).text(); me.selected_mode.val(format_number(me.payment_val, 2)) me.idx = me.selected_mode.attr("idx") - me.update_paid_amount() + me.selected_mode.change() }) $(this.$body).find('.delete-btn').click(function(){ @@ -137,15 +157,11 @@ erpnext.payments = erpnext.stock.StockController.extend({ me.payment_val = flt($(this).val()) || 0.0; me.selected_mode.val(format_number(me.payment_val, 2)) me.idx = me.selected_mode.attr("idx") - me.update_paid_amount() - }) - - this.selected_mode.click(function(){ - me.selected_mode.select(); + me.update_payment_amount() }) }, - clear_amount: function(){ + clear_amount: function() { var me = this; $(this.$body).find('.clr').click(function(e){ e.stopPropagation(); @@ -154,25 +170,65 @@ erpnext.payments = erpnext.stock.StockController.extend({ me.payment_val = 0.0; me.selected_mode.val(0.0); me.highlight_selected_row(); - me.update_paid_amount(); + me.update_payment_amount(); }) }, - update_paid_amount: function(){ + write_off_amount: function(write_off_amount) { var me = this; + + if(this.frm.doc.paid_amount > 0){ + this.frm.doc.write_off_amount = write_off_amount; + this.frm.doc.base_write_off_amount = flt(this.frm.doc.write_off_amount * this.frm.doc.conversion_rate, + precision("base_write_off_amount")); + this.calculate_outstanding_amount(false) + this.show_amounts() + } + }, + + change_amount: function(change_amount) { + var me = this; + + this.frm.doc.change_amount = change_amount; + this.calculate_write_off_amount() + this.show_amounts() + }, + + update_paid_amount: function() { + var me = this; + if(in_list(['change_amount', 'write_off_amount'], this.idx)){ + value = flt(me.selected_mode.val(), 2) + if(me.idx == 'change_amount'){ + me.change_amount(value) + } else{ + if(value == 0) { + value = me.frm.doc.outstanding_amount; + } + me.write_off_amount(value) + } + }else{ + this.update_payment_amount() + } + }, + + update_payment_amount: function(){ + var me = this; + $.each(this.frm.doc.payments, function(index, data){ if(cint(me.idx) == cint(data.idx)){ data.amount = flt(me.selected_mode.val(), 2) } }) + this.calculate_outstanding_amount(false); this.show_amounts(); }, - + show_amounts: function(){ var me = this; + $(this.$body).find(".write_off_amount").val(format_number(this.frm.doc.write_off_amount, 2)); $(this.$body).find('.paid_amount').text(format_currency(this.frm.doc.paid_amount, this.frm.doc.currency)); - $(this.$body).find('.change_amount').text(format_currency(this.frm.doc.change_amount, this.frm.doc.currency)) + $(this.$body).find('.change_amount').val(format_number(this.frm.doc.change_amount, 2)) $(this.$body).find('.outstanding_amount').text(format_currency(this.frm.doc.outstanding_amount, this.frm.doc.currency)) this.update_invoice(); } diff --git a/erpnext/public/js/payment/pos_payment.html b/erpnext/public/js/payment/pos_payment.html index c5d963aa85..e94f3a52ae 100644 --- a/erpnext/public/js/payment/pos_payment.html +++ b/erpnext/public/js/payment/pos_payment.html @@ -1,8 +1,8 @@
+
+

Total Amount: {%= format_currency(grand_total, currency) %}

+
-
-

Total

{%= format_currency(grand_total, currency) %}

-

Paid

@@ -10,13 +10,19 @@

Outstanding

{%= format_currency(outstanding_amount, currency) %}

-

Change

{%= format_currency(change_amount, currency) %}

+

Change +

+
+
+

Write off


-
+
+
+
{% for(var i=0; i<3; i++) { %} diff --git a/erpnext/public/less/erpnext.less b/erpnext/public/less/erpnext.less index d39f92497f..2d74b5f204 100644 --- a/erpnext/public/less/erpnext.less +++ b/erpnext/public/less/erpnext.less @@ -176,13 +176,15 @@ } .pos-payment-row .col-xs-6 { - padding :10px; + padding :15px; } .pos-payment-row { border-bottom:1px solid #d1d8dd; margin: 2px 0px 5px 0px; height: 60px; + margin-top: 0px; + margin-bottom: 0px; } .pos-payment-row:hover, .pos-keyboard-key:hover{ @@ -248,3 +250,8 @@ body[data-route="pos"] .modal-dialog { .pos-invoice-list { padding: 15px 10px; } + +.write_off_amount, .change_amount { + margin: 15px; + width: 130px; +} diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index d58adce06f..402ff116ec 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -66,7 +66,8 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ if(this.frm.fields_dict["items"].grid.get_field('item_code')) { this.frm.set_query("item_code", "items", function() { return { - query: "erpnext.controllers.queries.item_query" + query: "erpnext.controllers.queries.item_query", + filters: {'is_sales_item': 1} } }); } diff --git a/erpnext/setup/setup_wizard/sample_data.py b/erpnext/setup/setup_wizard/sample_data.py index 8078ebca3a..955f6633ca 100644 --- a/erpnext/setup/setup_wizard/sample_data.py +++ b/erpnext/setup/setup_wizard/sample_data.py @@ -11,7 +11,7 @@ import random def make_sample_data(): """Create a few opportunities, quotes, material requests, issues, todos, projects to help the user get started""" - items = frappe.get_all("Item") + items = frappe.get_all("Item", {'is_sales_item': 1}) customers = frappe.get_all("Customer") warehouses = frappe.get_all("Warehouse") @@ -25,7 +25,7 @@ def make_sample_data(): make_projects() if items and warehouses: - make_material_request(items) + make_material_request(frappe.get_all("Item")) frappe.db.commit() diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py index c9679bd9a0..191f1699b2 100644 --- a/erpnext/setup/setup_wizard/setup_wizard.py +++ b/erpnext/setup/setup_wizard/setup_wizard.py @@ -318,6 +318,8 @@ def create_items(args): "item_name": item, "description": item, "show_in_website": 1, + "is_sales_item": is_sales_item, + "is_purchase_item": is_purchase_item, "is_stock_item": is_stock_item and 1 or 0, "item_group": item_group, "stock_uom": args.get("item_uom_" + str(i)), diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index b86378d1c6..18fdad7c8c 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -1054,6 +1054,32 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "default": "1", + "fieldname": "is_purchase_item", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Is Purchase Item", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -1483,6 +1509,32 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "default": "1", + "fieldname": "is_sales_item", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Is Sales Item", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -2335,7 +2387,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2016-08-03 17:30:51.323382", + "modified": "2016-08-17 17:30:51.323382", "modified_by": "Administrator", "module": "Stock", "name": "Item",