Merge branch 'develop' of https://github.com/frappe/erpnext.git into Brand-Item-Defaults-V12

# Conflicts:
#	erpnext/stock/doctype/item/item.py
This commit is contained in:
Saif Ur Rehman
2019-02-02 02:49:04 +05:00
351 changed files with 90358 additions and 77878 deletions

View File

@@ -4,6 +4,10 @@
"node": true, "node": true,
"es6": true "es6": true
}, },
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"extends": "eslint:recommended", "extends": "eslint:recommended",
"rules": { "rules": {
"indent": [ "indent": [
@@ -50,9 +54,9 @@
"root": true, "root": true,
"globals": { "globals": {
"frappe": true, "frappe": true,
"Vue": true,
"erpnext": true, "erpnext": true,
"hub": true, "hub": true,
"$": true, "$": true,
"jQuery": true, "jQuery": true,
"moment": true, "moment": true,
@@ -133,6 +137,12 @@
"get_server_fields": true, "get_server_fields": true,
"set_multiple": true, "set_multiple": true,
"QUnit": true, "QUnit": true,
"Chart": true "Chart": true,
"Cypress": true,
"cy": true,
"it": true,
"context": true,
"before": true,
"beforeEach": true
} }
} }

1
.gitignore vendored
View File

@@ -12,5 +12,6 @@ erpnext/docs/current
*.swo *.swo
__pycache__ __pycache__
*~ *~
.idea/
.vscode/ .vscode/
node_modules/ node_modules/

3
cypress.json Normal file
View File

@@ -0,0 +1,3 @@
{
"baseUrl": "http://test_site_ui:8000"
}

View File

@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@@ -0,0 +1,32 @@
context('Form', () => {
before(() => {
cy.login('Administrator', 'qwe');
cy.visit('/desk');
});
it('create a new opportunity', () => {
cy.visit('/desk#Form/Opportunity/New Opportunity 1');
cy.get('.page-title').should('contain', 'Not Saved');
cy.fill_field('enquiry_from', 'Customer', 'Select');
cy.fill_field('customer', 'Test Customer', 'Link').blur();
cy.get('.primary-action').click();
cy.get('.page-title').should('contain', 'Open');
cy.get('.form-inner-toolbar button:contains("Lost")').click({ force: true });
cy.get('.modal input[data-fieldname="lost_reason"]').as('input');
cy.get('@input').focus().type('Higher', { delay: 200 });
cy.get('.modal .awesomplete ul')
.should('be.visible')
.get('li:contains("Higher Price")')
.click({ force: true });
cy.get('@input').focus().type('No Followup', { delay: 200 });
cy.get('.modal .awesomplete ul')
.should('be.visible')
.get('li:contains("No Followup")')
.click();
cy.fill_field('detailed_reason', 'Test Detailed Reason', 'Text');
cy.get('.modal button:contains("Declare Lost")').click({ force: true });
cy.get('.page-title').should('contain', 'Lost');
});
});

17
cypress/plugins/index.js Normal file
View File

@@ -0,0 +1,17 @@
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
// module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
// }

View File

@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

22
cypress/support/index.js Normal file
View File

@@ -0,0 +1,22 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// import frappe commands
import '../../../frappe/cypress/support/index';
// Import commands.js using ES2015 syntax:
import './commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@@ -29,7 +29,7 @@ def validate_service_stop_date(doc):
if date_diff(item.service_stop_date, item.service_end_date) > 0: if date_diff(item.service_stop_date, item.service_end_date) > 0:
frappe.throw(_("Service Stop Date cannot be after Service End Date")) frappe.throw(_("Service Stop Date cannot be after Service End Date"))
if old_stop_dates and old_stop_dates.get(item.name) and item.service_stop_date!=old_stop_dates[item.name]: if old_stop_dates and old_stop_dates.get(item.name) and item.service_stop_date!=old_stop_dates.get(item.name):
frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx))) frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx)))
def convert_deferred_expense_to_expense(start_date=None, end_date=None): def convert_deferred_expense_to_expense(start_date=None, end_date=None):

View File

@@ -61,13 +61,13 @@ frappe.treeview_settings["Account"] = {
frappe.set_route('List', 'Period Closing Voucher', {company: get_company()}); frappe.set_route('List', 'Period Closing Voucher', {company: get_company()});
}, __('View')); }, __('View'));
// make
treeview.page.add_inner_button(__("Journal Entry"), function() { treeview.page.add_inner_button(__("Journal Entry"), function() {
frappe.new_doc('Journal Entry', {company: get_company()}); frappe.new_doc('Journal Entry', {company: get_company()});
}, __('Make')); }, __('Create'));
treeview.page.add_inner_button(__("New Company"), function() { treeview.page.add_inner_button(__("New Company"), function() {
frappe.new_doc('Company'); frappe.new_doc('Company');
}, __('Make')); }, __('Create'));
// financial statements // financial statements
for (let report of ['Trial Balance', 'General Ledger', 'Balance Sheet', for (let report of ['Trial Balance', 'General Ledger', 'Balance Sheet',

View File

@@ -406,9 +406,9 @@ def get_transaction_entries(filename, headers):
from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
rows = read_xlsx_file_from_attached_file(file_id=filename) rows = read_xlsx_file_from_attached_file(file_id=filename)
elif (filename.lower().endswith("csv")): elif (filename.lower().endswith("csv")):
from frappe.utils.file_manager import get_file_path
from frappe.utils.csvutils import read_csv_content from frappe.utils.csvutils import read_csv_content
filepath = get_file_path(filename) _file = frappe.get_doc("File", {"file_name": filename})
filepath = _file.get_full_path()
with open(filepath,'rb') as csvfile: with open(filepath,'rb') as csvfile:
rows = read_csv_content(csvfile.read()) rows = read_csv_content(csvfile.read())
elif (filename.lower().endswith("xls")): elif (filename.lower().endswith("xls")):
@@ -428,8 +428,8 @@ def get_transaction_entries(filename, headers):
return transactions return transactions
def get_rows_from_xls_file(filename): def get_rows_from_xls_file(filename):
from frappe.utils.file_manager import get_file_path _file = frappe.get_doc("File", {"file_name": filename})
filepath = get_file_path(filename) filepath = _file.get_full_path()
import xlrd import xlrd
book = xlrd.open_workbook(filepath) book = xlrd.open_workbook(filepath)
sheets = book.sheets() sheets = book.sheets()

View File

@@ -106,7 +106,7 @@ def validate_expense_against_budget(args):
and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"})): and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"})):
if args.project and budget_against == 'project': if args.project and budget_against == 'project':
condition = "and b.project='%s'" % frappe.db.escape(args.project) condition = "and b.project=%s" % frappe.db.escape(args.project)
args.budget_against_field = "Project" args.budget_against_field = "Project"
elif args.cost_center and budget_against == 'cost_center': elif args.cost_center and budget_against == 'cost_center':

View File

@@ -19,7 +19,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "Cashier-closing-", "default": "POS-CLO-",
"fieldname": "naming_series", "fieldname": "naming_series",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 0, "hidden": 0,
@@ -32,7 +32,7 @@
"label": "Series", "label": "Series",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "Cashier-closing-\n", "options": "POS-CLO-",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
@@ -230,6 +230,37 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.00",
"fieldname": "returns",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Returns",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "2",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@@ -364,7 +395,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-09-03 10:59:54.500567", "modified": "2018-10-21 14:26:15.812416",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Cashier Closing", "name": "Cashier Closing",

View File

@@ -29,7 +29,7 @@ class CashierClosing(Document):
for i in self.payments: for i in self.payments:
total += flt(i.amount) total += flt(i.amount)
self.net_amount = total + self.outstanding_amount + self.expense - self.custody self.net_amount = total + self.outstanding_amount + self.expense - self.custody + self.returns
def validate_time(self): def validate_time(self):
if self.from_time >= self.time: if self.from_time >= self.time:

View File

@@ -21,7 +21,7 @@ frappe.ui.form.on('Exchange Rate Revaluation', {
refresh: function(frm) { refresh: function(frm) {
if(frm.doc.docstatus==1) { if(frm.doc.docstatus==1) {
frm.add_custom_button(__('Make Journal Entry'), function() { frm.add_custom_button(__('Create Journal Entry'), function() {
return frm.events.make_jv(frm); return frm.events.make_jv(frm);
}); });
} }

View File

@@ -1,5 +1,6 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0, "allow_guest_to_view": 0,
"allow_import": 0, "allow_import": 0,
"allow_rename": 0, "allow_rename": 0,
@@ -814,6 +815,39 @@
"set_only_once": 0, "set_only_once": 0,
"translatable": 0, "translatable": 0,
"unique": 0 "unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"fieldname": "to_rename",
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "To Rename",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "has_web_view": 0,
@@ -827,7 +861,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-08-21 16:15:45.156222", "modified": "2019-01-07 07:05:00.366399",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "GL Entry", "name": "GL Entry",

View File

@@ -6,14 +6,21 @@ import frappe, erpnext
from frappe import _ from frappe import _
from frappe.utils import flt, fmt_money, getdate, formatdate from frappe.utils import flt, fmt_money, getdate, formatdate
from frappe.model.document import Document from frappe.model.document import Document
from frappe.model.naming import set_name_from_naming_options
from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled
from erpnext.accounts.utils import get_account_currency from erpnext.accounts.utils import get_account_currency
from erpnext.accounts.utils import get_fiscal_year from erpnext.accounts.utils import get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency from erpnext.exceptions import InvalidAccountCurrency
exclude_from_linked_with = True exclude_from_linked_with = True
class GLEntry(Document): class GLEntry(Document):
def autoname(self):
"""
Temporarily name doc for fast insertion
name will be changed using autoname options (in a scheduled job)
"""
self.name = frappe.generate_hash(txt="", length=10)
def validate(self): def validate(self):
self.flags.ignore_submit_comment = True self.flags.ignore_submit_comment = True
self.check_mandatory() self.check_mandatory()
@@ -161,7 +168,7 @@ def check_freezing_date(posting_date, adv_adj=False):
def update_outstanding_amt(account, party_type, party, against_voucher_type, against_voucher, on_cancel=False): def update_outstanding_amt(account, party_type, party, against_voucher_type, against_voucher, on_cancel=False):
if party_type and party: if party_type and party:
party_condition = " and party_type='{0}' and party='{1}'"\ party_condition = " and party_type={0} and party={1}"\
.format(frappe.db.escape(party_type), frappe.db.escape(party)) .format(frappe.db.escape(party_type), frappe.db.escape(party))
else: else:
party_condition = "" party_condition = ""
@@ -230,3 +237,17 @@ def update_against_account(voucher_type, voucher_no):
if d.against != new_against: if d.against != new_against:
frappe.db.set_value("GL Entry", d.name, "against", new_against) frappe.db.set_value("GL Entry", d.name, "against", new_against)
def rename_gle_sle_docs():
for doctype in ["GL Entry", "Stock Ledger Entry"]:
rename_temporarily_named_docs(doctype)
def rename_temporarily_named_docs(doctype):
"""Rename temporarily named docs using autoname options"""
docs_to_rename = frappe.get_all(doctype, {"to_rename": "1"}, order_by="creation")
for doc in docs_to_rename:
oldname = doc.name
set_name_from_naming_options(frappe.get_meta(doctype).autoname, doc)
newname = doc.name
frappe.db.sql("""UPDATE `tab{}` SET name = %s, to_rename = 0 where name = %s""".format(doctype), (newname, oldname))

View File

@@ -3,7 +3,9 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe, unittest import frappe, unittest
from frappe.model.naming import parse_naming_series
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.accounts.doctype.gl_entry.gl_entry import rename_gle_sle_docs
class TestGLEntry(unittest.TestCase): class TestGLEntry(unittest.TestCase):
def test_round_off_entry(self): def test_round_off_entry(self):
@@ -23,3 +25,32 @@ class TestGLEntry(unittest.TestCase):
and debit = 0 and credit = '.01'""", jv.name) and debit = 0 and credit = '.01'""", jv.name)
self.assertTrue(round_off_entry) self.assertTrue(round_off_entry)
def test_rename_entries(self):
je = make_journal_entry("_Test Account Cost for Goods Sold - _TC", "_Test Bank - _TC", 100, submit=True)
rename_gle_sle_docs()
naming_series = parse_naming_series(parts=frappe.get_meta("GL Entry").autoname.split(".")[:-1])
je = make_journal_entry("_Test Account Cost for Goods Sold - _TC", "_Test Bank - _TC", 100, submit=True)
gl_entries = frappe.get_all("GL Entry",
fields=["name", "to_rename"],
filters={"voucher_type": "Journal Entry", "voucher_no": je.name},
order_by="creation"
)
self.assertTrue(all(entry.to_rename == 1 for entry in gl_entries))
old_naming_series_current_value = frappe.db.sql("SELECT current from tabSeries where name = %s", naming_series)[0][0]
rename_gle_sle_docs()
new_gl_entries = frappe.get_all("GL Entry",
fields=["name", "to_rename"],
filters={"voucher_type": "Journal Entry", "voucher_no": je.name},
order_by="creation"
)
self.assertTrue(all(entry.to_rename == 0 for entry in new_gl_entries))
self.assertTrue(all(new.name != old.name for new, old in zip(gl_entries, new_gl_entries)))
new_naming_series_current_value = frappe.db.sql("SELECT current from tabSeries where name = %s", naming_series)[0][0]
self.assertEquals(old_naming_series_current_value + 2, new_naming_series_current_value)

View File

@@ -40,7 +40,7 @@ frappe.ui.form.on("Journal Entry", {
erpnext.journal_entry.toggle_fields_based_on_currency(frm); erpnext.journal_entry.toggle_fields_based_on_currency(frm);
if ((frm.doc.voucher_type == "Inter Company Journal Entry") && (frm.doc.docstatus == 1) && (!frm.doc.inter_company_journal_entry_reference)) { if ((frm.doc.voucher_type == "Inter Company Journal Entry") && (frm.doc.docstatus == 1) && (!frm.doc.inter_company_journal_entry_reference)) {
frm.add_custom_button(__("Make Inter Company Journal Entry"), frm.add_custom_button(__("Create Inter Company Journal Entry"),
function() { function() {
frm.trigger("make_inter_company_journal_entry"); frm.trigger("make_inter_company_journal_entry");
} }
@@ -68,7 +68,7 @@ frappe.ui.form.on("Journal Entry", {
} }
], ],
}); });
d.set_primary_action(__("Make"), function() { d.set_primary_action(__('Create'), function() {
d.hide(); d.hide();
var args = d.get_values(); var args = d.get_values();
frappe.call({ frappe.call({

View File

@@ -800,7 +800,7 @@ def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s
and (jv_detail.reference_type is null or jv_detail.reference_type = '') and (jv_detail.reference_type is null or jv_detail.reference_type = '')
and jv.docstatus = 1 and jv.`{0}` like %s order by jv.name desc limit %s, %s""".format(frappe.db.escape(searchfield)), and jv.docstatus = 1 and jv.`{0}` like %s order by jv.name desc limit %s, %s""".format(searchfield),
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len)) (filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))

View File

@@ -19,7 +19,7 @@ def get_loyalty_details(customer, loyalty_program, expiry_date=None, company=Non
condition = '' condition = ''
if company: if company:
condition = " and company='%s' " % frappe.db.escape(company) condition = " and company=%s " % frappe.db.escape(company)
if not include_expired_entry: if not include_expired_entry:
condition += " and expiry_date>='%s' " % expiry_date condition += " and expiry_date>='%s' " % expiry_date

View File

@@ -15,7 +15,7 @@ frappe.ui.form.on('Opening Invoice Creation Tool', {
refresh: function(frm) { refresh: function(frm) {
frm.disable_save(); frm.disable_save();
frm.trigger("make_dashboard"); frm.trigger("make_dashboard");
frm.page.set_primary_action(__("Make Invoices"), () => { frm.page.set_primary_action(__('Create Invoices'), () => {
let btn_primary = frm.page.btn_primary.get(0); let btn_primary = frm.page.btn_primary.get(0);
return frm.call({ return frm.call({
doc: frm.doc, doc: frm.doc,

View File

@@ -560,7 +560,7 @@ def get_outstanding_reference_documents(args):
# Get positive outstanding sales /purchase invoices/ Fees # Get positive outstanding sales /purchase invoices/ Fees
condition = "" condition = ""
if args.get("voucher_type") and args.get("voucher_no"): if args.get("voucher_type") and args.get("voucher_no"):
condition = " and voucher_type='{0}' and voucher_no='{1}'"\ condition = " and voucher_type={0} and voucher_no={1}"\
.format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"])) .format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]))
# Add cost center condition # Add cost center condition

View File

@@ -11,10 +11,10 @@ frappe.ui.form.on('Payment Order', {
// payment Entry // payment Entry
if (frm.doc.docstatus==1) { if (frm.doc.docstatus==1) {
frm.add_custom_button(__('Make Payment Entries'), frm.add_custom_button(__('Create Payment Entries'),
function() { function() {
frm.trigger("make_payment_records") frm.trigger("make_payment_records");
}); });
} }
}, },

View File

@@ -24,6 +24,7 @@ class PaymentReconciliation(Document):
def get_payment_entries(self): def get_payment_entries(self):
order_doctype = "Sales Order" if self.party_type=="Customer" else "Purchase Order" order_doctype = "Sales Order" if self.party_type=="Customer" else "Purchase Order"
payment_entries = get_advance_payment_entries(self.party_type, self.party, payment_entries = get_advance_payment_entries(self.party_type, self.party,
self.receivable_payable_account, order_doctype, against_all_orders=True, limit=self.limit) self.receivable_payable_account, order_doctype, against_all_orders=True, limit=self.limit)
@@ -174,8 +175,8 @@ class PaymentReconciliation(Document):
frappe.throw(_("Please select Allocated Amount, Invoice Type and Invoice Number in atleast one row")) frappe.throw(_("Please select Allocated Amount, Invoice Type and Invoice Number in atleast one row"))
def check_condition(self): def check_condition(self):
cond = " and posting_date >= '{0}'".format(frappe.db.escape(self.from_date)) if self.from_date else "" cond = " and posting_date >= {0}".format(frappe.db.escape(self.from_date)) if self.from_date else ""
cond += " and posting_date <= '{0}'".format(frappe.db.escape(self.to_date)) if self.to_date else "" cond += " and posting_date <= {0}".format(frappe.db.escape(self.to_date)) if self.to_date else ""
dr_or_cr = ("debit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable' dr_or_cr = ("debit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable'
else "credit_in_account_currency") else "credit_in_account_currency")

View File

@@ -34,7 +34,7 @@ frappe.ui.form.on("Payment Request", "refresh", function(frm) {
} }
if(!frm.doc.payment_gateway_account && frm.doc.status == "Initiated") { if(!frm.doc.payment_gateway_account && frm.doc.status == "Initiated") {
frm.add_custom_button(__('Make Payment Entry'), function(){ frm.add_custom_button(__('Create Payment Entry'), function(){
frappe.call({ frappe.call({
method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_entry", method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_entry",
args: {"docname": frm.doc.name}, args: {"docname": frm.doc.name},

View File

@@ -107,7 +107,7 @@ def get_item_groups(pos_profile):
if pos_profile.get('item_groups'): if pos_profile.get('item_groups'):
# Get items based on the item groups defined in the POS profile # Get items based on the item groups defined in the POS profile
for data in pos_profile.get('item_groups'): for data in pos_profile.get('item_groups'):
item_groups.extend(["'%s'" % frappe.db.escape(d.name) for d in get_child_nodes('Item Group', data.item_group)]) item_groups.extend(["%s" % frappe.db.escape(d.name) for d in get_child_nodes('Item Group', data.item_group)])
return list(set(item_groups)) return list(set(item_groups))

View File

@@ -255,10 +255,12 @@ def get_pricing_rules(args):
if parent_groups: if parent_groups:
if allow_blank: parent_groups.append('') if allow_blank: parent_groups.append('')
condition = " ifnull("+field+", '') in ('" + \ condition = "ifnull({field}, '') in ({parent_groups})".format(
"', '".join([frappe.db.escape(d) for d in parent_groups])+"')" field=field,
frappe.flags.tree_conditions[key] = condition parent_groups=", ".join([frappe.db.escape(d) for d in parent_groups])
)
frappe.flags.tree_conditions[key] = condition
return condition return condition

View File

@@ -46,40 +46,40 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
this.frm.add_custom_button( this.frm.add_custom_button(
__('Unblock Invoice'), __('Unblock Invoice'),
function() {me.unblock_invoice()}, function() {me.unblock_invoice()},
__('Make') __('Create')
); );
} else if (!doc.on_hold) { } else if (!doc.on_hold) {
this.frm.add_custom_button( this.frm.add_custom_button(
__('Block Invoice'), __('Block Invoice'),
function() {me.block_invoice()}, function() {me.block_invoice()},
__('Make') __('Create')
); );
} }
} }
if(doc.docstatus == 1 && doc.outstanding_amount != 0 if(doc.docstatus == 1 && doc.outstanding_amount != 0
&& !(doc.is_return && doc.return_against)) { && !(doc.is_return && doc.return_against)) {
this.frm.add_custom_button(__('Payment'), this.make_payment_entry, __("Make")); this.frm.add_custom_button(__('Payment'), this.make_payment_entry, __('Create'));
cur_frm.page.set_inner_btn_group_as_primary(__("Make")); cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
} }
if(!doc.is_return && doc.docstatus==1) { if(!doc.is_return && doc.docstatus==1) {
if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) { if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) {
cur_frm.add_custom_button(__('Return / Debit Note'), cur_frm.add_custom_button(__('Return / Debit Note'),
this.make_debit_note, __("Make")); this.make_debit_note, __('Create'));
} }
if(!doc.auto_repeat) { if(!doc.auto_repeat) {
cur_frm.add_custom_button(__('Subscription'), function() { cur_frm.add_custom_button(__('Subscription'), function() {
erpnext.utils.make_subscription(doc.doctype, doc.name) erpnext.utils.make_subscription(doc.doctype, doc.name)
}, __("Make")) }, __('Create'))
} }
} }
if (doc.outstanding_amount > 0 && !cint(doc.is_return)) { if (doc.outstanding_amount > 0 && !cint(doc.is_return)) {
cur_frm.add_custom_button(__('Payment Request'), function() { cur_frm.add_custom_button(__('Payment Request'), function() {
me.make_payment_request() me.make_payment_request()
}, __("Make")); }, __('Create'));
} }
if(doc.docstatus===0) { if(doc.docstatus===0) {
@@ -128,7 +128,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
if (internal == 1 && disabled == 0) { if (internal == 1 && disabled == 0) {
me.frm.add_custom_button("Inter Company Invoice", function() { me.frm.add_custom_button("Inter Company Invoice", function() {
me.make_inter_company_invoice(me.frm); me.make_inter_company_invoice(me.frm);
}, __("Make")); }, __('Create'));
} }
}); });
} }

View File

@@ -15,6 +15,7 @@
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -44,10 +45,12 @@
"reqd": 1, "reqd": 1,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -77,10 +80,12 @@
"reqd": 1, "reqd": 1,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -99,7 +104,7 @@
"no_copy": 0, "no_copy": 0,
"oldfieldname": "charge_type", "oldfieldname": "charge_type",
"oldfieldtype": "Select", "oldfieldtype": "Select",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total", "options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity",
"permlevel": 0, "permlevel": 0,
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
@@ -109,10 +114,12 @@
"reqd": 1, "reqd": 1,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -141,10 +148,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -172,10 +181,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -200,10 +211,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -232,10 +245,12 @@
"reqd": 1, "reqd": 1,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -265,10 +280,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -297,11 +314,13 @@
"reqd": 1, "reqd": 1,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0, "unique": 0,
"width": "300px" "width": "300px"
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -327,10 +346,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -358,10 +379,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -387,10 +410,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -419,10 +444,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -450,10 +477,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -482,10 +511,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -511,10 +542,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -542,10 +575,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -573,10 +608,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -604,10 +641,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -635,10 +674,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -666,6 +707,7 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
} }
], ],
@@ -679,7 +721,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-12-06 13:37:44.483509", "modified": "2018-09-19 13:48:32.755198",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Purchase Taxes and Charges", "name": "Purchase Taxes and Charges",
@@ -690,5 +732,6 @@
"read_only_onload": 0, "read_only_onload": 0,
"show_name_in_global_search": 0, "show_name_in_global_search": 0,
"track_changes": 1, "track_changes": 1,
"track_seen": 0 "track_seen": 0,
"track_views": 0
} }

View File

@@ -51,8 +51,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
if (doc.docstatus == 1 && doc.outstanding_amount!=0 if (doc.docstatus == 1 && doc.outstanding_amount!=0
&& !(cint(doc.is_return) && doc.return_against)) { && !(cint(doc.is_return) && doc.return_against)) {
cur_frm.add_custom_button(__('Payment'), cur_frm.add_custom_button(__('Payment'),
this.make_payment_entry, __("Make")); this.make_payment_entry, __('Create'));
cur_frm.page.set_inner_btn_group_as_primary(__("Make")); cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
} }
if(doc.docstatus==1 && !doc.is_return) { if(doc.docstatus==1 && !doc.is_return) {
@@ -65,8 +65,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) { if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) {
cur_frm.add_custom_button(__('Return / Credit Note'), cur_frm.add_custom_button(__('Return / Credit Note'),
this.make_sales_return, __("Make")); this.make_sales_return, __('Create'));
cur_frm.page.set_inner_btn_group_as_primary(__("Make")); cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
} }
if(cint(doc.update_stock)!=1) { if(cint(doc.update_stock)!=1) {
@@ -79,20 +79,20 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
if(!from_delivery_note && !is_delivered_by_supplier) { if(!from_delivery_note && !is_delivered_by_supplier) {
cur_frm.add_custom_button(__('Delivery'), cur_frm.add_custom_button(__('Delivery'),
cur_frm.cscript['Make Delivery Note'], __("Make")); cur_frm.cscript['Make Delivery Note'], __('Create'));
} }
} }
if (doc.outstanding_amount>0 && !cint(doc.is_return)) { if (doc.outstanding_amount>0 && !cint(doc.is_return)) {
cur_frm.add_custom_button(__('Payment Request'), function() { cur_frm.add_custom_button(__('Payment Request'), function() {
me.make_payment_request(); me.make_payment_request();
}, __("Make")); }, __('Create'));
} }
if(!doc.auto_repeat) { if(!doc.auto_repeat) {
cur_frm.add_custom_button(__('Subscription'), function() { cur_frm.add_custom_button(__('Subscription'), function() {
erpnext.utils.make_subscription(doc.doctype, doc.name) erpnext.utils.make_subscription(doc.doctype, doc.name)
}, __("Make")) }, __('Create'))
} }
} }
@@ -112,7 +112,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
if (internal == 1 && disabled == 0) { if (internal == 1 && disabled == 0) {
me.frm.add_custom_button("Inter Company Invoice", function() { me.frm.add_custom_button("Inter Company Invoice", function() {
me.make_inter_company_invoice(); me.make_inter_company_invoice();
}, __("Make")); }, __('Create'));
} }
}); });
} }

View File

@@ -729,7 +729,7 @@ class TestSalesInvoice(unittest.TestCase):
# check gl entries # check gl entries
gl_entries = frappe.db.sql("""select account, debit, credit gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc, debit asc""", si.name, as_dict=1) order by account asc, debit asc, credit asc""", si.name, as_dict=1)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
stock_in_hand = get_inventory_account('_Test Company') stock_in_hand = get_inventory_account('_Test Company')

View File

@@ -33,7 +33,7 @@
"no_copy": 0, "no_copy": 0,
"oldfieldname": "charge_type", "oldfieldname": "charge_type",
"oldfieldtype": "Select", "oldfieldtype": "Select",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total", "options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity",
"permlevel": 0, "permlevel": 0,
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
@@ -652,7 +652,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-08-21 16:15:51.518582", "modified": "2018-09-19 13:48:59.341454",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Sales Taxes and Charges", "name": "Sales Taxes and Charges",

View File

@@ -17,7 +17,7 @@ frappe.ui.form.on('Share Transfer', {
}; };
}); });
if (frm.doc.docstatus == 1) { if (frm.doc.docstatus == 1) {
frm.add_custom_button(__('Make Journal Entry'), function () { frm.add_custom_button(__('Create Journal Entry'), function () {
erpnext.share_transfer.make_jv(frm); erpnext.share_transfer.make_jv(frm);
}); });
} }

View File

@@ -75,7 +75,7 @@ class TaxRule(Document):
for d in filters: for d in filters:
if conds: if conds:
conds += " and " conds += " and "
conds += """ifnull({0}, '') = '{1}'""".format(d, frappe.db.escape(cstr(filters[d]))) conds += """ifnull({0}, '') = {1}""".format(d, frappe.db.escape(cstr(filters[d])))
if self.from_date and self.to_date: if self.from_date and self.to_date:
conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or
@@ -152,7 +152,7 @@ def get_tax_template(posting_date, args):
customer_group_condition = get_customer_group_condition(value) customer_group_condition = get_customer_group_condition(value)
conditions.append("ifnull({0}, '') in ('', {1})".format(key, customer_group_condition)) conditions.append("ifnull({0}, '') in ('', {1})".format(key, customer_group_condition))
else: else:
conditions.append("ifnull({0}, '') in ('', '{1}')".format(key, frappe.db.escape(cstr(value)))) conditions.append("ifnull({0}, '') in ('', {1})".format(key, frappe.db.escape(cstr(value))))
tax_rule = frappe.db.sql("""select * from `tabTax Rule` tax_rule = frappe.db.sql("""select * from `tabTax Rule`
where {0}""".format(" and ".join(conditions)), as_dict = True) where {0}""".format(" and ".join(conditions)), as_dict = True)
@@ -180,7 +180,7 @@ def get_tax_template(posting_date, args):
def get_customer_group_condition(customer_group): def get_customer_group_condition(customer_group):
condition = "" condition = ""
customer_groups = ["'%s'"%(frappe.db.escape(d.name)) for d in get_parent_customer_groups(customer_group)] customer_groups = ["%s"%(frappe.db.escape(d.name)) for d in get_parent_customer_groups(customer_group)]
if customer_groups: if customer_groups:
condition = ",".join(['%s'] * len(customer_groups))%(tuple(customer_groups)) condition = ",".join(['%s'] * len(customer_groups))%(tuple(customer_groups))
return condition return condition

View File

@@ -450,7 +450,7 @@ def get_timeline_data(doctype, name):
# fetch and append data from Activity Log # fetch and append data from Activity Log
data += frappe.db.sql("""select {fields} data += frappe.db.sql("""select {fields}
from `tabActivity Log` from `tabActivity Log`
where reference_doctype="{doctype}" and reference_name="{name}" where reference_doctype={doctype} and reference_name={name}
and status!='Success' and creation > {after} and status!='Success' and creation > {after}
{group_by} order by creation desc {group_by} order by creation desc
""".format(doctype=frappe.db.escape(doctype), name=frappe.db.escape(name), fields=fields, """.format(doctype=frappe.db.escape(doctype), name=frappe.db.escape(name), fields=fields,

View File

@@ -0,0 +1,64 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
frappe.query_reports["Account Balance"] = {
"filters": [
{
fieldname:"company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company")
},
{
fieldname:"report_date",
label: __("Date"),
fieldtype: "Date",
default: frappe.datetime.get_today(),
reqd: 1
},
{
fieldname: "root_type",
label: __("Root Type"),
fieldtype: "Select",
options: [
{ "value": "Asset", "label": __("Asset") },
{ "value": "Liability", "label": __("Liability") },
{ "value": "Income", "label": __("Income") },
{ "value": "Expense", "label": __("Expense") },
{ "value": "Equity", "label": __("Equity") }
],
},
{
fieldname: "account_type",
label: __("Account Type"),
fieldtype: "Select",
options: [
{ "value": "Accumulated Depreciation", "label": __("Accumulated Depreciation") },
{ "value": "Asset Received But Not Billed", "label": __("Asset Received But Not Billed") },
{ "value": "Bank", "label": __("Bank") },
{ "value": "Cash", "label": __("Cash") },
{ "value": "Chargeble", "label": __("Chargeble") },
{ "value": "Capital Work in Progress", "label": __("Capital Work in Progress") },
{ "value": "Cost of Goods Sold", "label": __("Cost of Goods Sold") },
{ "value": "Depreciation", "label": __("Depreciation") },
{ "value": "Equity", "label": __("Equity") },
{ "value": "Expense Account", "label": __("Expense Account") },
{ "value": "Expenses Included In Asset Valuation", "label": __("Expenses Included In Asset Valuation") },
{ "value": "Expenses Included In Valuation", "label": __("Expenses Included In Valuation") },
{ "value": "Fixed Asset", "label": __("Fixed Asset") },
{ "value": "Income Account", "label": __("Income Account") },
{ "value": "Payable", "label": __("Payable") },
{ "value": "Receivable", "label": __("Receivable") },
{ "value": "Round Off", "label": __("Round Off") },
{ "value": "Stock", "label": __("Stock") },
{ "value": "Stock Adjustment", "label": __("Stock Adjustment") },
{ "value": "Stock Received But Not Billed", "label": __("Stock Received But Not Billed") },
{ "value": "Tax", "label": __("Tax") },
{ "value": "Temporary", "label": __("Temporary") },
],
},
]
}

View File

@@ -0,0 +1,19 @@
{
"add_total_row": 0,
"creation": "2019-01-02 18:01:46.691685",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2019-01-02 18:01:46.691685",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account Balance",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Bank Account",
"report_name": "Account Balance",
"report_type": "Script Report",
"roles": []
}

View File

@@ -0,0 +1,73 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext.accounts.utils import get_balance_on
def execute(filters=None):
filters = frappe._dict(filters or {})
columns = get_columns(filters)
data = get_data(filters)
return columns, data
def get_columns(filters):
columns = [
{
"label": _("Account"),
"fieldtype": "Link",
"fieldname": "account",
"options": "Account",
"width": 100
},
{
"label": _("Currency"),
"fieldtype": "Link",
"fieldname": "currency",
"options": "Currency",
"hidden": 1,
"width": 50
},
{
"label": _("Balance"),
"fieldtype": "Currency",
"fieldname": "balance",
"options": "currency",
"width": 100
}
]
return columns
def get_conditions(filters):
conditions = {}
if filters.account_type:
conditions["account_type"] = filters.account_type
return conditions
if filters.company:
conditions["company"] = filters.company
if filters.root_type:
conditions["root_type"] = filters.root_type
return conditions
def get_data(filters):
data = []
conditions = get_conditions(filters)
accounts = frappe.db.get_all("Account", fields=["name", "account_currency"],
filters=conditions)
for d in accounts:
balance = get_balance_on(d.name, date=filters.report_date)
row = {"account": d.name, "balance": balance, "currency": d.account_currency}
data.append(row)
return data

View File

@@ -0,0 +1,69 @@
from __future__ import unicode_literals
import frappe
import unittest
from frappe.utils import getdate
from erpnext.accounts.report.account_balance.account_balance import execute
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
class TestAccountBalance(unittest.TestCase):
def test_account_balance(self):
frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company 2'")
frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 2'")
filters = {
'company': '_Test Company 2',
'report_date': getdate(),
'root_type': 'Income',
}
make_sales_invoice()
report = execute(filters)
expected_data = [
{
"account": 'Sales - _TC2',
"currency": 'EUR',
"balance": -100.0,
},
{
"account": 'Income - _TC2',
"currency": 'EUR',
"balance": -100.0,
},
{
"account": 'Service - _TC2',
"currency": 'EUR',
"balance": 0.0,
},
{
"account": 'Direct Income - _TC2',
"currency": 'EUR',
"balance": -100.0,
},
{
"account": 'Indirect Income - _TC2',
"currency": 'EUR',
"balance": 0.0,
},
]
self.assertEqual(expected_data, report[1])
def make_sales_invoice():
frappe.set_user("Administrator")
create_sales_invoice(company="_Test Company 2",
customer = '_Test Customer 2',
currency = 'EUR',
warehouse = 'Finished Goods - _TC2',
debit_to = 'Debtors - _TC2',
income_account = 'Sales - _TC2',
expense_account = 'Cost of Goods Sold - _TC2',
cost_center = '_Test Company 2 - _TC2')

View File

@@ -558,7 +558,7 @@ class ReceivablePayableReport(object):
ps.due_date, ps.payment_amount, ps.description ps.due_date, ps.payment_amount, ps.description
from `tabSales Invoice` si, `tabPayment Schedule` ps from `tabSales Invoice` si, `tabPayment Schedule` ps
where si.name = ps.parent and where si.name = ps.parent and
si.docstatus = 1 and si.company = '%s' and si.docstatus = 1 and si.company = %s and
si.name in (%s) order by ps.due_date si.name in (%s) order by ps.due_date
""" % (frappe.db.escape(self.filters.company), ','.join(['%s'] *len(voucher_nos))), """ % (frappe.db.escape(self.filters.company), ','.join(['%s'] *len(voucher_nos))),
(tuple(voucher_nos)), as_dict = 1) (tuple(voucher_nos)), as_dict = 1)

View File

@@ -99,7 +99,7 @@ def get_cost_centers(filters):
def get_cost_center_target_details(filters): def get_cost_center_target_details(filters):
cond = "" cond = ""
if filters.get("cost_center"): if filters.get("cost_center"):
cond += " and b.cost_center='%s'" % frappe.db.escape(filters.get("cost_center")) cond += " and b.cost_center=%s" % frappe.db.escape(filters.get("cost_center"))
return frappe.db.sql(""" return frappe.db.sql("""
select b.{budget_against} as budget_against, b.monthly_distribution, ba.account, ba.budget_amount,b.fiscal_year select b.{budget_against} as budget_against, b.monthly_distribution, ba.account, ba.budget_amount,b.fiscal_year

View File

@@ -274,7 +274,8 @@ def get_companies(filters):
return all_companies, companies return all_companies, companies
def get_subsidiary_companies(company): def get_subsidiary_companies(company):
lft, rgt = frappe.db.get_value('Company', company, ["lft", "rgt"]) lft, rgt = frappe.get_cached_value('Company',
company, ["lft", "rgt"])
return frappe.db.sql_list("""select name from `tabCompany` return frappe.db.sql_list("""select name from `tabCompany`
where lft >= {0} and rgt <= {1} order by lft, rgt""".format(lft, rgt)) where lft >= {0} and rgt <= {1} order by lft, rgt""".format(lft, rgt))
@@ -387,10 +388,10 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
company_finance_book = erpnext.get_default_finance_book(filters.get("company")) company_finance_book = erpnext.get_default_finance_book(filters.get("company"))
if not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book): if not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book):
additional_conditions.append("ifnull(finance_book, '') in ('%s', '')" % additional_conditions.append("ifnull(finance_book, '') in (%s, '')" %
frappe.db.escape(company_finance_book)) frappe.db.escape(company_finance_book))
elif filters.get("finance_book"): elif filters.get("finance_book"):
additional_conditions.append("ifnull(finance_book, '') = '%s' " % additional_conditions.append("ifnull(finance_book, '') = %s " %
frappe.db.escape(filters.get("finance_book"))) frappe.db.escape(filters.get("finance_book")))
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else "" return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""

View File

@@ -343,8 +343,8 @@ def set_gl_entries_by_account(
accounts = frappe.db.sql_list("""select name from `tabAccount` accounts = frappe.db.sql_list("""select name from `tabAccount`
where lft >= %s and rgt <= %s""", (root_lft, root_rgt)) where lft >= %s and rgt <= %s""", (root_lft, root_rgt))
additional_conditions += " and account in ('{}')"\ additional_conditions += " and account in ({})"\
.format("', '".join([frappe.db.escape(d) for d in accounts])) .format(", ".join([frappe.db.escape(d) for d in accounts]))
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry` gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
where company=%(company)s where company=%(company)s
@@ -392,10 +392,10 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
company_finance_book = erpnext.get_default_finance_book(filters.get("company")) company_finance_book = erpnext.get_default_finance_book(filters.get("company"))
if not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book): if not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book):
additional_conditions.append("ifnull(finance_book, '') in ('%s', '')" % additional_conditions.append("ifnull(finance_book, '') in (%s, '')" %
frappe.db.escape(company_finance_book)) frappe.db.escape(company_finance_book))
elif filters.get("finance_book"): elif filters.get("finance_book"):
additional_conditions.append("ifnull(finance_book, '') = '%s' " % additional_conditions.append("ifnull(finance_book, '') = %s " %
frappe.db.escape(filters.get("finance_book"))) frappe.db.escape(filters.get("finance_book")))
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else "" return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""

View File

@@ -329,7 +329,7 @@ class GrossProfitGenerator(object):
where company=%(company)s where company=%(company)s
order by order by
item_code desc, warehouse desc, posting_date desc, item_code desc, warehouse desc, posting_date desc,
posting_time desc, name desc""", self.filters, as_dict=True) posting_time desc, creation desc""", self.filters, as_dict=True)
self.sle = {} self.sle = {}
for r in res: for r in res:
if (r.item_code, r.warehouse) not in self.sle: if (r.item_code, r.warehouse) not in self.sle:

View File

@@ -99,7 +99,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
cond = [] cond = []
if date: if date:
cond.append("posting_date <= '%s'" % frappe.db.escape(cstr(date))) cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
else: else:
# get balance of all entries that exist # get balance of all entries that exist
date = nowdate() date = nowdate()
@@ -127,7 +127,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
)""" % (cc.lft, cc.rgt)) )""" % (cc.lft, cc.rgt))
else: else:
cond.append("""gle.cost_center = "%s" """ % (frappe.db.escape(cost_center, percent=False), )) cond.append("""gle.cost_center = %s """ % (frappe.db.escape(cost_center, percent=False), ))
if account: if account:
@@ -158,14 +158,14 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
if acc.account_currency == frappe.get_cached_value('Company', acc.company, "default_currency"): if acc.account_currency == frappe.get_cached_value('Company', acc.company, "default_currency"):
in_account_currency = False in_account_currency = False
else: else:
cond.append("""gle.account = "%s" """ % (frappe.db.escape(account, percent=False), )) cond.append("""gle.account = %s """ % (frappe.db.escape(account, percent=False), ))
if party_type and party: if party_type and party:
cond.append("""gle.party_type = "%s" and gle.party = "%s" """ % cond.append("""gle.party_type = %s and gle.party = %s """ %
(frappe.db.escape(party_type), frappe.db.escape(party, percent=False))) (frappe.db.escape(party_type), frappe.db.escape(party, percent=False)))
if company: if company:
cond.append("""gle.company = "%s" """ % (frappe.db.escape(company, percent=False))) cond.append("""gle.company = %s """ % (frappe.db.escape(company, percent=False)))
if account or (party_type and party): if account or (party_type and party):
if in_account_currency: if in_account_currency:
@@ -183,7 +183,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
def get_count_on(account, fieldname, date): def get_count_on(account, fieldname, date):
cond = [] cond = []
if date: if date:
cond.append("posting_date <= '%s'" % frappe.db.escape(cstr(date))) cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
else: else:
# get balance of all entries that exist # get balance of all entries that exist
date = nowdate() date = nowdate()
@@ -218,7 +218,7 @@ def get_count_on(account, fieldname, date):
and ac.lft >= %s and ac.rgt <= %s and ac.lft >= %s and ac.rgt <= %s
)""" % (acc.lft, acc.rgt)) )""" % (acc.lft, acc.rgt))
else: else:
cond.append("""gle.account = "%s" """ % (frappe.db.escape(account, percent=False), )) cond.append("""gle.account = %s """ % (frappe.db.escape(account, percent=False), ))
entries = frappe.db.sql(""" entries = frappe.db.sql("""
SELECT name, posting_date, account, party_type, party,debit,credit, SELECT name, posting_date, account, party_type, party,debit,credit,

View File

@@ -81,26 +81,26 @@ frappe.ui.form.on('Asset', {
if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) { if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) {
frm.add_custom_button(__("Purchase Invoice"), function() { frm.add_custom_button(__("Purchase Invoice"), function() {
frm.trigger("make_purchase_invoice"); frm.trigger("make_purchase_invoice");
}, __("Make")); }, __('Create'));
} }
if (frm.doc.maintenance_required && !frm.doc.maintenance_schedule) { if (frm.doc.maintenance_required && !frm.doc.maintenance_schedule) {
frm.add_custom_button(__("Asset Maintenance"), function() { frm.add_custom_button(__("Asset Maintenance"), function() {
frm.trigger("create_asset_maintenance"); frm.trigger("create_asset_maintenance");
}, __("Make")); }, __('Create'));
} }
if (frm.doc.status != 'Fully Depreciated') { if (frm.doc.status != 'Fully Depreciated') {
frm.add_custom_button(__("Asset Value Adjustment"), function() { frm.add_custom_button(__("Asset Value Adjustment"), function() {
frm.trigger("create_asset_adjustment"); frm.trigger("create_asset_adjustment");
}, __("Make")); }, __('Create'));
} }
if (!frm.doc.calculate_depreciation) { if (!frm.doc.calculate_depreciation) {
frm.add_custom_button(__("Depreciation Entry"), function() { frm.add_custom_button(__("Depreciation Entry"), function() {
frm.trigger("make_journal_entry"); frm.trigger("make_journal_entry");
}, __("Make")); }, __('Create'));
} }
frm.page.set_inner_btn_group_as_primary(__("Make")); frm.page.set_inner_btn_group_as_primary(__('Create'));
frm.trigger("setup_chart"); frm.trigger("setup_chart");
} }

View File

@@ -203,12 +203,11 @@ def get_children(doctype, parent=None, location=None, is_root=False):
from from
`tab{doctype}` comp `tab{doctype}` comp
where where
ifnull(parent_location, "")="{parent}" ifnull(parent_location, "")={parent}
""".format( """.format(
doctype=frappe.db.escape(doctype), doctype=doctype,
parent=frappe.db.escape(parent) parent=frappe.db.escape(parent)
), as_dict=1) ), as_dict=1)
@frappe.whitelist() @frappe.whitelist()
def add_node(): def add_node():

View File

@@ -42,6 +42,7 @@ frappe.ui.form.on("Purchase Order", {
frm: frm, frm: frm,
child_docname: "items", child_docname: "items",
child_doctype: "Purchase Order Detail", child_doctype: "Purchase Order Detail",
cannot_add_row: false,
}) })
}); });
} }
@@ -119,7 +120,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
if(doc.docstatus == 1 && doc.status != "Closed") { if(doc.docstatus == 1 && doc.status != "Closed") {
if(flt(doc.per_received, 2) < 100 && allow_receipt) { if(flt(doc.per_received, 2) < 100 && allow_receipt) {
cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __("Make")); cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __('Create'));
if(doc.is_subcontracted==="Yes") { if(doc.is_subcontracted==="Yes") {
cur_frm.add_custom_button(__('Material to Supplier'), cur_frm.add_custom_button(__('Material to Supplier'),
@@ -129,24 +130,24 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
if(flt(doc.per_billed, 2) < 100) if(flt(doc.per_billed, 2) < 100)
cur_frm.add_custom_button(__('Invoice'), cur_frm.add_custom_button(__('Invoice'),
this.make_purchase_invoice, __("Make")); this.make_purchase_invoice, __('Create'));
if(flt(doc.per_billed)==0 && doc.status != "Delivered") { if(flt(doc.per_billed)==0 && doc.status != "Delivered") {
cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_payment_entry, __("Make")); cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_payment_entry, __('Create'));
} }
if(!doc.auto_repeat) { if(!doc.auto_repeat) {
cur_frm.add_custom_button(__('Subscription'), function() { cur_frm.add_custom_button(__('Subscription'), function() {
erpnext.utils.make_subscription(doc.doctype, doc.name) erpnext.utils.make_subscription(doc.doctype, doc.name)
}, __("Make")) }, __('Create'))
} }
if(flt(doc.per_billed)==0) { if(flt(doc.per_billed)==0) {
this.frm.add_custom_button(__('Payment Request'), this.frm.add_custom_button(__('Payment Request'),
function() { me.make_payment_request() }, __("Make")); function() { me.make_payment_request() }, __('Create'));
} }
cur_frm.page.set_inner_btn_group_as_primary(__("Make")); cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
} }
}, },

View File

@@ -298,7 +298,7 @@
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 1,
"label": "Date", "label": "Date",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,

View File

@@ -183,7 +183,7 @@ class PurchaseOrder(BuyingController):
def check_modified_date(self): def check_modified_date(self):
mod_db = frappe.db.sql("select modified from `tabPurchase Order` where name = %s", mod_db = frappe.db.sql("select modified from `tabPurchase Order` where name = %s",
self.name) self.name)
date_diff = frappe.db.sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.modified))) date_diff = frappe.db.sql("select '%s' - '%s' " % (mod_db[0][0], cstr(self.modified)))
if date_diff and date_diff[0][0]: if date_diff and date_diff[0][0]:
msgprint(_("{0} {1} has been modified. Please refresh.").format(self.doctype, self.name), msgprint(_("{0} {1} has been modified. Please refresh.").format(self.doctype, self.name),
@@ -296,7 +296,10 @@ class PurchaseOrder(BuyingController):
for item in self.items: for item in self.items:
received_qty += item.received_qty received_qty += item.received_qty
total_qty += item.qty total_qty += item.qty
self.db_set("per_received", flt(received_qty/total_qty) * 100, update_modified=False) if total_qty:
self.db_set("per_received", flt(received_qty/total_qty) * 100, update_modified=False)
else:
self.db_set("per_received", 0, update_modified=False)
def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor= 1.0): def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor= 1.0):
"""get last purchase rate for an item""" """get last purchase rate for an item"""

View File

@@ -31,7 +31,7 @@ frappe.ui.form.on("Request for Quotation",{
refresh: function(frm, cdt, cdn) { refresh: function(frm, cdt, cdn) {
if (frm.doc.docstatus === 1) { if (frm.doc.docstatus === 1) {
frm.add_custom_button(__("Make"), frm.add_custom_button(__('Create'),
function(){ frm.trigger("make_suppplier_quotation") }, __("Supplier Quotation")); function(){ frm.trigger("make_suppplier_quotation") }, __("Supplier Quotation"));
frm.add_custom_button(__("View"), frm.add_custom_button(__("View"),
@@ -147,7 +147,7 @@ frappe.ui.form.on("Request for Quotation",{
"fieldname": "supplier", "fieldname": "supplier",
"options": doc.suppliers.map(d => d.supplier), "options": doc.suppliers.map(d => d.supplier),
"reqd": 1 }, "reqd": 1 },
{ "fieldtype": "Button", "label": __("Make Supplier Quotation"), { "fieldtype": "Button", "label": __('Create Supplier Quotation'),
"fieldname": "make_supplier_quotation", "cssClass": "btn-primary" }, "fieldname": "make_supplier_quotation", "cssClass": "btn-primary" },
] ]
}); });

View File

@@ -47,11 +47,11 @@ frappe.ui.form.on("Supplier", {
frm.add_custom_button(__('Bank Account'), function () { frm.add_custom_button(__('Bank Account'), function () {
erpnext.utils.make_bank_account(frm.doc.doctype, frm.doc.name); erpnext.utils.make_bank_account(frm.doc.doctype, frm.doc.name);
}, __("Make")); }, __('Create'));
frm.add_custom_button(__('Pricing Rule'), function () { frm.add_custom_button(__('Pricing Rule'), function () {
erpnext.utils.make_pricing_rule(frm.doc.doctype, frm.doc.name); erpnext.utils.make_pricing_rule(frm.doc.doctype, frm.doc.name);
}, __("Make")); }, __('Create'));
// indicators // indicators
erpnext.utils.set_party_dashboard_indicators(frm); erpnext.utils.set_party_dashboard_indicators(frm);

View File

@@ -18,15 +18,15 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
this._super(); this._super();
if (this.frm.doc.docstatus === 1) { if (this.frm.doc.docstatus === 1) {
cur_frm.add_custom_button(__("Purchase Order"), this.make_purchase_order, cur_frm.add_custom_button(__("Purchase Order"), this.make_purchase_order,
__("Make")); __('Create'));
cur_frm.page.set_inner_btn_group_as_primary(__("Make")); cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
cur_frm.add_custom_button(__("Quotation"), this.make_quotation, cur_frm.add_custom_button(__("Quotation"), this.make_quotation,
__("Make")); __('Create'));
if(!this.frm.doc.auto_repeat) { if(!this.frm.doc.auto_repeat) {
cur_frm.add_custom_button(__('Subscription'), function() { cur_frm.add_custom_button(__('Subscription'), function() {
erpnext.utils.make_subscription(me.frm.doc.doctype, me.frm.doc.name) erpnext.utils.make_subscription(me.frm.doc.doctype, me.frm.doc.name)
}, __("Make")) }, __('Create'))
} }
} }
else if (this.frm.doc.docstatus===0) { else if (this.frm.doc.docstatus===0) {

View File

@@ -242,7 +242,7 @@ def get_data():
{ {
"type": "doctype", "type": "doctype",
"name": "Opening Invoice Creation Tool", "name": "Opening Invoice Creation Tool",
"description": _("Make Opening Sales and Purchase Invoices") "description": _("Create Opening Sales and Purchase Invoices")
}, },
] ]
}, },

View File

@@ -38,12 +38,10 @@ def get_data():
"link": "List/Employee" "link": "List/Employee"
}, },
{ {
"module_name": "Project", "module_name": "Projects",
"_doctype": "Project",
"color": "#8e44ad", "color": "#8e44ad",
"icon": "octicon octicon-rocket", "icon": "octicon octicon-rocket",
"type": "link", "type": "module",
"link": "List/Project"
}, },
{ {
"module_name": "Issue", "module_name": "Issue",
@@ -71,6 +69,7 @@ def get_data():
# old # old
{ {
"label": _("Accounting"),
"module_name": "Accounts", "module_name": "Accounts",
"color": "#3498db", "color": "#3498db",
"icon": "octicon octicon-repo", "icon": "octicon octicon-repo",
@@ -136,13 +135,6 @@ def get_data():
"link": "leaderboard", "link": "leaderboard",
"label": _("Leaderboard") "label": _("Leaderboard")
}, },
{
"module_name": "Projects",
"color": "#8e44ad",
"icon": "octicon octicon-rocket",
"type": "module",
"hidden": 1
},
{ {
"module_name": "Support", "module_name": "Support",
"color": "#2c3e50", "color": "#2c3e50",
@@ -151,12 +143,12 @@ def get_data():
"hidden": 1 "hidden": 1
}, },
{ {
"module_name": "Learn", "module_name": "Help",
"color": "#FF888B", "color": "#FF888B",
"icon": "octicon octicon-device-camera-video", "icon": "octicon octicon-device-camera-video",
"type": "module", "type": "module",
"is_help": True, "is_help": True,
"label": _("Learn"), "label": _("Help"),
"hidden": 1 "hidden": 1
}, },
{ {
@@ -573,5 +565,12 @@ def get_data():
"type": "module", "type": "module",
"label": _("Non Profit"), "label": _("Non Profit"),
"hidden": 1 "hidden": 1
},
{
"module_name": "Quality Management",
"color": "#1abc9c",
"icon": "fa fa-check-square-o",
"type": "module",
"label": _("Quality")
} }
] ]

View File

@@ -70,7 +70,7 @@ def get_data():
] ]
}, },
{ {
"label": _("Accounts"), "label": _("Accounting"),
"items": [ "items": [
{ {
"type": "help", "type": "help",

View File

@@ -0,0 +1,69 @@
from __future__ import unicode_literals
from frappe import _
def get_data():
return [
{
"label": _("Goal and Procedure"),
"items": [
{
"type": "doctype",
"name": "Quality Goal",
"description":_("Quality Goal."),
},
{
"type": "doctype",
"name": "Quality Procedure",
"description":_("Quality Procedure."),
},
{
"type": "doctype",
"name": "Quality Procedure",
"icon": "fa fa-sitemap",
"label": _("Tree of Procedures"),
"route": "Tree/Quality Procedure",
"description": _("Tree of Quality Procedures."),
},
]
},
{
"label": _("Review and Action"),
"items": [
{
"type": "doctype",
"name": "Quality Review",
"description":_("Quality Review"),
},
{
"type": "doctype",
"name": "Quality Action",
"description":_("Quality Action"),
}
]
},
{
"label": _("Meeting"),
"items": [
{
"type": "doctype",
"name": "Quality Meeting",
"description":_("Quality Meeting"),
}
]
},
{
"label": _("Feedback"),
"items": [
{
"type": "doctype",
"name": "Customer Feedback",
"description":_("Customer Feedback"),
},
{
"type": "doctype",
"name": "Customer Feedback Template",
"description":_("Customer Feedback Template"),
}
]
},
]

View File

@@ -109,7 +109,7 @@ def get_data():
] ]
for module, label, icon in ( for module, label, icon in (
("accounts", _("Accounts"), "fa fa-money"), ("accounts", _("Accounting"), "fa fa-money"),
("stock", _("Stock"), "fa fa-truck"), ("stock", _("Stock"), "fa fa-truck"),
("selling", _("Selling"), "fa fa-tag"), ("selling", _("Selling"), "fa fa-tag"),
("buying", _("Buying"), "fa fa-shopping-cart"), ("buying", _("Buying"), "fa fa-shopping-cart"),

View File

@@ -6,6 +6,7 @@ import frappe, erpnext
import json import json
from frappe import _, throw from frappe import _, throw
from frappe.utils import today, flt, cint, fmt_money, formatdate, getdate, add_days, add_months, get_last_day, nowdate from frappe.utils import today, flt, cint, fmt_money, formatdate, getdate, add_days, add_months, get_last_day, nowdate
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.setup.utils import get_exchange_rate from erpnext.setup.utils import get_exchange_rate
from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
from erpnext.utilities.transaction_base import TransactionBase from erpnext.utilities.transaction_base import TransactionBase
@@ -1072,12 +1073,56 @@ def get_supplier_block_status(party_name):
} }
return info return info
def set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, item_code):
"""
Returns a Sales Order Item child item containing the default values
"""
p_doctype = frappe.get_doc(parent_doctype, parent_doctype_name)
child_item = frappe.new_doc('Sales Order Item', p_doctype, child_docname)
item = frappe.get_doc("Item", item_code)
child_item.item_code = item.item_code
child_item.item_name = item.item_name
child_item.description = item.description
child_item.reqd_by_date = p_doctype.delivery_date
child_item.uom = item.stock_uom
child_item.conversion_factor = get_conversion_factor(item_code, item.stock_uom).get("conversion_factor") or 1.0
return child_item
def set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, item_code):
"""
Returns a Purchase Order Item child item containing the default values
"""
p_doctype = frappe.get_doc(parent_doctype, parent_doctype_name)
child_item = frappe.new_doc('Purchase Order Item', p_doctype, child_docname)
item = frappe.get_doc("Item", item_code)
child_item.item_code = item.item_code
child_item.item_name = item.item_name
child_item.description = item.description
child_item.schedule_date = p_doctype.schedule_date
child_item.uom = item.stock_uom
child_item.conversion_factor = get_conversion_factor(item_code, item.stock_uom).get("conversion_factor") or 1.0
child_item.base_rate = 1 # Initiallize value will update in parent validation
child_item.base_amount = 1 # Initiallize value will update in parent validation
return child_item
@frappe.whitelist() @frappe.whitelist()
def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name): def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, child_docname="items"):
data = json.loads(trans_items) data = json.loads(trans_items)
parent = frappe.get_doc(parent_doctype, parent_doctype_name)
for d in data: for d in data:
child_item = frappe.get_doc(parent_doctype + ' Item', d.get("docname")) new_child_flag = False
if not d.get("docname"):
new_child_flag = True
if parent_doctype == "Sales Order":
child_item = set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, d.get("item_code"))
if parent_doctype == "Purchase Order":
child_item = set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, d.get("item_code"))
else:
child_item = frappe.get_doc(parent_doctype + ' Item', d.get("docname"))
if parent_doctype == "Sales Order" and flt(d.get("qty")) < child_item.delivered_qty: if parent_doctype == "Sales Order" and flt(d.get("qty")) < child_item.delivered_qty:
frappe.throw(_("Cannot set quantity less than delivered quantity")) frappe.throw(_("Cannot set quantity less than delivered quantity"))
@@ -1093,42 +1138,45 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name):
else: else:
child_item.rate = flt(d.get("rate")) child_item.rate = flt(d.get("rate"))
child_item.flags.ignore_validate_update_after_submit = True child_item.flags.ignore_validate_update_after_submit = True
child_item.save() if new_child_flag:
child_item.idx = len(parent.items) + 1
child_item.insert()
else:
child_item.save()
p_doctype = frappe.get_doc(parent_doctype, parent_doctype_name) parent.reload()
parent.flags.ignore_validate_update_after_submit = True
parent.set_qty_as_per_stock_uom()
parent.calculate_taxes_and_totals()
frappe.get_doc('Authorization Control').validate_approving_authority(parent.doctype,
parent.company, parent.base_grand_total)
p_doctype.flags.ignore_validate_update_after_submit = True parent.set_payment_schedule()
p_doctype.set_qty_as_per_stock_uom()
p_doctype.calculate_taxes_and_totals()
frappe.get_doc('Authorization Control').validate_approving_authority(p_doctype.doctype,
p_doctype.company, p_doctype.base_grand_total)
p_doctype.set_payment_schedule()
if parent_doctype == 'Purchase Order': if parent_doctype == 'Purchase Order':
p_doctype.validate_minimum_order_qty() parent.validate_minimum_order_qty()
p_doctype.validate_budget() parent.validate_budget()
if p_doctype.is_against_so(): if parent.is_against_so():
p_doctype.update_status_updater() parent.update_status_updater()
else: else:
p_doctype.check_credit_limit() parent.check_credit_limit()
p_doctype.save() parent.save()
if parent_doctype == 'Purchase Order': if parent_doctype == 'Purchase Order':
update_last_purchase_rate(p_doctype, is_submit = 1) update_last_purchase_rate(parent, is_submit = 1)
p_doctype.update_prevdoc_status() parent.update_prevdoc_status()
p_doctype.update_requested_qty() parent.update_requested_qty()
p_doctype.update_ordered_qty() parent.update_ordered_qty()
p_doctype.update_ordered_and_reserved_qty() parent.update_ordered_and_reserved_qty()
p_doctype.update_receiving_percentage() parent.update_receiving_percentage()
if p_doctype.is_subcontracted == "Yes": if parent.is_subcontracted == "Yes":
p_doctype.update_reserved_qty_for_subcontract() parent.update_reserved_qty_for_subcontract()
else: else:
p_doctype.update_reserved_qty() parent.update_reserved_qty()
p_doctype.update_project() parent.update_project()
p_doctype.update_prevdoc_status('submit') parent.update_prevdoc_status('submit')
p_doctype.update_delivery_status() parent.update_delivery_status()
p_doctype.update_blanket_order() parent.update_blanket_order()
p_doctype.update_billing_percentage() parent.update_billing_percentage()
p_doctype.set_status() parent.set_status()

View File

@@ -761,7 +761,7 @@ def validate_item_type(doc, fieldname, message):
if not items: if not items:
return return
item_list = ", ".join(["'%s'" % frappe.db.escape(d) for d in items]) item_list = ", ".join(["%s" % frappe.db.escape(d) for d in items])
invalid_items = [d[0] for d in frappe.db.sql(""" invalid_items = [d[0] for d in frappe.db.sql("""
select item_code from tabItem where name in ({0}) and {1}=0 select item_code from tabItem where name in ({0}) and {1}=0

View File

@@ -119,7 +119,7 @@ def get_attribute_values(item):
return frappe.flags.attribute_values, frappe.flags.numeric_values return frappe.flags.attribute_values, frappe.flags.numeric_values
def find_variant(template, args, variant_item_code=None): def find_variant(template, args, variant_item_code=None):
conditions = ["""(iv_attribute.attribute="{0}" and iv_attribute.attribute_value="{1}")"""\ conditions = ["""(iv_attribute.attribute={0} and iv_attribute.attribute_value={1})"""\
.format(frappe.db.escape(key), frappe.db.escape(cstr(value))) for key, value in args.items()] .format(frappe.db.escape(key), frappe.db.escape(cstr(value))) for key, value in args.items()]
conditions = " or ".join(conditions) conditions = " or ".join(conditions)

View File

@@ -208,9 +208,8 @@ def bom(doctype, txt, searchfield, start, page_len, filters):
limit %(start)s, %(page_len)s """.format( limit %(start)s, %(page_len)s """.format(
fcond=get_filters_cond(doctype, filters, conditions), fcond=get_filters_cond(doctype, filters, conditions),
mcond=get_match_cond(doctype), mcond=get_match_cond(doctype),
key=frappe.db.escape(searchfield)), key=searchfield), {
{ 'txt': '%' + txt + '%',
'txt': "%%%s%%" % frappe.db.escape(txt),
'_txt': txt.replace("%", ""), '_txt': txt.replace("%", ""),
'start': start or 0, 'start': start or 0,
'page_len': page_len or 20 'page_len': page_len or 20
@@ -219,7 +218,7 @@ def bom(doctype, txt, searchfield, start, page_len, filters):
def get_project_name(doctype, txt, searchfield, start, page_len, filters): def get_project_name(doctype, txt, searchfield, start, page_len, filters):
cond = '' cond = ''
if filters.get('customer'): if filters.get('customer'):
cond = """(`tabProject`.customer = '%s' or cond = """(`tabProject`.customer = %s or
ifnull(`tabProject`.customer,"")="") and""" %(frappe.db.escape(filters.get("customer"))) ifnull(`tabProject`.customer,"")="") and""" %(frappe.db.escape(filters.get("customer")))
return frappe.db.sql("""select `tabProject`.name from `tabProject` return frappe.db.sql("""select `tabProject`.name from `tabProject`
@@ -353,7 +352,7 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters):
{condition} {match_condition} {condition} {match_condition}
order by idx desc, name""" order by idx desc, name"""
.format(condition=condition, match_condition=get_match_cond(doctype), key=searchfield), { .format(condition=condition, match_condition=get_match_cond(doctype), key=searchfield), {
'txt': "%%%s%%" % frappe.db.escape(txt), 'txt': '%' + txt + '%',
'company': filters.get("company", "") 'company': filters.get("company", "")
}) })
@@ -375,10 +374,10 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
and tabAccount.docstatus!=2 and tabAccount.docstatus!=2
and tabAccount.{key} LIKE %(txt)s and tabAccount.{key} LIKE %(txt)s
{condition} {match_condition}""" {condition} {match_condition}"""
.format(condition=condition, key=frappe.db.escape(searchfield), .format(condition=condition, key=searchfield,
match_condition=get_match_cond(doctype)), { match_condition=get_match_cond(doctype)), {
'company': filters.get("company", ""), 'company': filters.get("company", ""),
'txt': "%%%s%%" % frappe.db.escape(txt) 'txt': '%' + txt + '%'
}) })
@@ -398,7 +397,7 @@ def warehouse_query(doctype, txt, searchfield, start, page_len, filters):
CONCAT_WS(" : ", "Actual Qty", ifnull( ({sub_query}), 0) ) as actual_qty CONCAT_WS(" : ", "Actual Qty", ifnull( ({sub_query}), 0) ) as actual_qty
from `tabWarehouse` from `tabWarehouse`
where where
`tabWarehouse`.`{key}` like '{txt}' `tabWarehouse`.`{key}` like {txt}
{fcond} {mcond} {fcond} {mcond}
order by order by
`tabWarehouse`.name desc `tabWarehouse`.name desc
@@ -406,7 +405,7 @@ def warehouse_query(doctype, txt, searchfield, start, page_len, filters):
{start}, {page_len} {start}, {page_len}
""".format( """.format(
sub_query=sub_query, sub_query=sub_query,
key=frappe.db.escape(searchfield), key=searchfield,
fcond=get_filters_cond(doctype, filter_dict.get("Warehouse"), conditions), fcond=get_filters_cond(doctype, filter_dict.get("Warehouse"), conditions),
mcond=get_match_cond(doctype), mcond=get_match_cond(doctype),
start=start, start=start,
@@ -430,9 +429,9 @@ def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
query = """select batch_id from `tabBatch` query = """select batch_id from `tabBatch`
where disabled = 0 where disabled = 0
and (expiry_date >= CURDATE() or expiry_date IS NULL) and (expiry_date >= CURDATE() or expiry_date IS NULL)
and name like '{txt}'""".format(txt = frappe.db.escape('%{0}%'.format(txt))) and name like {txt}""".format(txt = frappe.db.escape('%{0}%'.format(txt)))
if filters and filters.get('item'): if filters and filters.get('item'):
query += " and item = '{item}'".format(item = frappe.db.escape(filters.get('item'))) query += " and item = {item}".format(item = frappe.db.escape(filters.get('item')))
return frappe.db.sql(query, filters) return frappe.db.sql(query, filters)

View File

@@ -244,6 +244,7 @@ def make_return_doc(doctype, source_name, target_doc=None):
def update_item(source_doc, target_doc, source_parent): def update_item(source_doc, target_doc, source_parent):
target_doc.qty = -1* source_doc.qty target_doc.qty = -1* source_doc.qty
default_return_warehouse = frappe.db.get_single_value("Stock Settings", "default_return_warehouse")
if doctype == "Purchase Receipt": if doctype == "Purchase Receipt":
target_doc.received_qty = -1* source_doc.received_qty target_doc.received_qty = -1* source_doc.received_qty
target_doc.rejected_qty = -1* source_doc.rejected_qty target_doc.rejected_qty = -1* source_doc.rejected_qty
@@ -268,6 +269,7 @@ def make_return_doc(doctype, source_name, target_doc=None):
target_doc.so_detail = source_doc.so_detail target_doc.so_detail = source_doc.so_detail
target_doc.si_detail = source_doc.si_detail target_doc.si_detail = source_doc.si_detail
target_doc.expense_account = source_doc.expense_account target_doc.expense_account = source_doc.expense_account
target_doc.warehouse = default_return_warehouse if default_return_warehouse else source_doc.warehouse
elif doctype == "Sales Invoice": elif doctype == "Sales Invoice":
target_doc.sales_order = source_doc.sales_order target_doc.sales_order = source_doc.sales_order
target_doc.delivery_note = source_doc.delivery_note target_doc.delivery_note = source_doc.delivery_note

View File

@@ -179,7 +179,7 @@ class SellingController(StockController):
last_valuation_rate = frappe.db.sql(""" last_valuation_rate = frappe.db.sql("""
SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s
AND warehouse = %s AND valuation_rate > 0 AND warehouse = %s AND valuation_rate > 0
ORDER BY posting_date DESC, posting_time DESC, name DESC LIMIT 1 ORDER BY posting_date DESC, posting_time DESC, creation DESC LIMIT 1
""", (it.item_code, it.warehouse)) """, (it.item_code, it.warehouse))
if last_valuation_rate: if last_valuation_rate:
last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] / (it.conversion_factor or 1) last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] / (it.conversion_factor or 1)

View File

@@ -308,7 +308,7 @@ class StatusUpdater(Document):
def _update_modified(self, args, update_modified): def _update_modified(self, args, update_modified):
args['update_modified'] = '' args['update_modified'] = ''
if update_modified: if update_modified:
args['update_modified'] = ', modified = now(), modified_by = "{0}"'\ args['update_modified'] = ', modified = now(), modified_by = {0}'\
.format(frappe.db.escape(frappe.session.user)) .format(frappe.db.escape(frappe.session.user))
def update_billing_status_for_zero_amount_refdoc(self, ref_dt): def update_billing_status_for_zero_amount_refdoc(self, ref_dt):

View File

@@ -416,7 +416,7 @@ def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, f
for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
from `tabStock Ledger Entry` sle from `tabStock Ledger Entry` sle
where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) {condition} where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) {condition}
order by timestamp(sle.posting_date, sle.posting_time) asc, name asc""".format(condition=condition), order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc""".format(condition=condition),
tuple([posting_date, posting_time] + values), as_dict=True): tuple([posting_date, posting_time] + values), as_dict=True):
future_stock_vouchers.append([d.voucher_type, d.voucher_no]) future_stock_vouchers.append([d.voucher_type, d.voucher_no])

View File

@@ -272,6 +272,8 @@ class calculate_taxes_and_totals(object):
elif tax.charge_type == "On Previous Row Total": elif tax.charge_type == "On Previous Row Total":
current_tax_amount = (tax_rate / 100.0) * \ current_tax_amount = (tax_rate / 100.0) * \
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item
elif tax.charge_type == "On Item Quantity":
current_tax_amount = tax_rate * item.stock_qty
self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount) self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)

View File

@@ -0,0 +1,94 @@
from __future__ import unicode_literals, print_function
import unittest
import frappe
from uuid import uuid4 as _uuid4
def uuid4():
return str(_uuid4())
class TestTaxes(unittest.TestCase):
def setUp(self):
self.company = frappe.get_doc({
'doctype': 'Company',
'company_name': uuid4(),
'abbr': ''.join(s[0] for s in uuid4().split('-')),
'default_currency': 'USD',
'country': 'United States',
}).insert()
self.account = frappe.get_doc({
'doctype': 'Account',
'account_name': uuid4(),
'account_type': 'Tax',
'company': self.company.name,
'parent_account': 'Duties and Taxes - {self.company.abbr}'.format(self=self)
}).insert()
self.item_group = frappe.get_doc({
'doctype': 'Item Group',
'item_group_name': uuid4(),
'parent_item_group': 'All Item Groups',
}).insert()
self.item = frappe.get_doc({
'doctype': 'Item',
'item_code': uuid4(),
'item_group': self.item_group.name,
'is_stock_item': 0,
'taxes': [
{
'tax_type': self.account.name,
'tax_rate': 2,
}
],
}).insert()
self.customer = frappe.get_doc({
'doctype': 'Customer',
'customer_name': uuid4(),
'customer_group': 'All Customer Groups',
}).insert()
self.supplier = frappe.get_doc({
'doctype': 'Supplier',
'supplier_name': uuid4(),
'supplier_group': 'All Supplier Groups',
}).insert()
def test_taxes(self):
self.created_docs = []
for dt in ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice',
'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']:
doc = frappe.get_doc({
'doctype': dt,
'company': self.company.name,
'supplier': self.supplier.name,
'schedule_date': frappe.utils.nowdate(),
'delivery_date': frappe.utils.nowdate(),
'customer': self.customer.name,
'buying_price_list' if dt.startswith('Purchase') else 'selling_price_list'
: 'Standard Buying' if dt.startswith('Purchase') else 'Standard Selling',
'items': [
{
'item_code': self.item.name,
'qty': 300,
'rate': 100,
}
],
'taxes': [
{
'charge_type': 'On Item Quantity',
'account_head': self.account.name,
'description': 'N/A',
'rate': 0,
},
],
})
doc.run_method('set_missing_values')
doc.run_method('calculate_taxes_and_totals')
doc.insert()
self.assertEqual(doc.taxes[0].tax_amount, 600)
self.created_docs.append(doc)
def tearDown(self):
for doc in self.created_docs:
doc.delete()
self.item.delete()
self.item_group.delete()
self.account.delete()
self.company.delete()

View File

@@ -30,9 +30,9 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
frappe.dynamic_link = {doc: doc, fieldname: 'name', doctype: 'Lead'} frappe.dynamic_link = {doc: doc, fieldname: 'name', doctype: 'Lead'}
if(!doc.__islocal && doc.__onload && !doc.__onload.is_customer) { if(!doc.__islocal && doc.__onload && !doc.__onload.is_customer) {
this.frm.add_custom_button(__("Customer"), this.create_customer, __("Make")); this.frm.add_custom_button(__("Customer"), this.create_customer, __('Create'));
this.frm.add_custom_button(__("Opportunity"), this.create_opportunity, __("Make")); this.frm.add_custom_button(__("Opportunity"), this.create_opportunity, __('Create'));
this.frm.add_custom_button(__("Quotation"), this.make_quotation, __("Make")); this.frm.add_custom_button(__("Quotation"), this.make_quotation, __('Create'));
} }
if(!this.frm.doc.__islocal) { if(!this.frm.doc.__islocal) {

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Lost Reason Detail', {
refresh: function() {
}
});

View File

@@ -0,0 +1,76 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2018-12-28 14:40:50.635495",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "lost_reason",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Opportunity Lost Reason",
"length": 0,
"no_copy": 0,
"options": "Opportunity Lost Reason",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-12-28 15:02:24.282772",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lost Reason Detail",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
from frappe.model.document import Document
class LostReasonDetail(Document):
pass

View File

@@ -1,6 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt // License: GNU General Public License v3. See license.txt
{% include 'erpnext/selling/sales_common.js' %}
frappe.provide("erpnext.crm"); frappe.provide("erpnext.crm");
cur_frm.email_field = "contact_email"; cur_frm.email_field = "contact_email";
@@ -47,15 +48,16 @@ frappe.ui.form.on("Opportunity", {
frm.add_custom_button(__('Supplier Quotation'), frm.add_custom_button(__('Supplier Quotation'),
function() { function() {
frm.trigger("make_supplier_quotation") frm.trigger("make_supplier_quotation")
}, __("Make")); }, __('Create'));
} }
frm.add_custom_button(__('Quotation'), frm.add_custom_button(__('Quotation'),
cur_frm.cscript.create_quotation, __("Make")); cur_frm.cscript.create_quotation, __('Create'));
if(doc.status!=="Quotation") { if(doc.status!=="Quotation") {
frm.add_custom_button(__('Lost'), frm.add_custom_button(__('Lost'), () => {
cur_frm.cscript['Declare Opportunity Lost']); frm.trigger('set_as_lost_dialog');
});
} }
} }
@@ -179,33 +181,3 @@ cur_frm.cscript.lead = function(doc, cdt, cdn) {
}); });
} }
cur_frm.cscript['Declare Opportunity Lost'] = function() {
var dialog = new frappe.ui.Dialog({
title: __("Set as Lost"),
fields: [
{"fieldtype": "Text", "label": __("Reason for losing"), "fieldname": "reason",
"reqd": 1 },
{"fieldtype": "Button", "label": __("Update"), "fieldname": "update"},
]
});
dialog.fields_dict.update.$input.click(function() {
var args = dialog.get_values();
if(!args) return;
return cur_frm.call({
doc: cur_frm.doc,
method: "declare_enquiry_lost",
args: args.reason,
callback: function(r) {
if(r.exc) {
frappe.msgprint(__("There were errors."));
} else {
dialog.hide();
cur_frm.refresh();
}
},
btn: this
})
});
dialog.show();
}

View File

@@ -351,38 +351,6 @@
"translatable": 0, "translatable": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.status===\"Lost\"",
"fieldname": "order_lost_reason",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Lost Reason",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
@@ -1312,6 +1280,38 @@
"translatable": 0, "translatable": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.status===\"Lost\"",
"fieldname": "order_lost_reason",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Detailed Reason",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
@@ -1447,6 +1447,39 @@
"translatable": 0, "translatable": 0,
"unique": 0, "unique": 0,
"width": "150px" "width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "lost_reasons",
"fieldtype": "Table MultiSelect",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Lost Reasons",
"length": 0,
"no_copy": 0,
"options": "Lost Reason Detail",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "has_web_view": 0,
@@ -1460,7 +1493,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-10-01 09:28:43.990999", "modified": "2018-12-29 18:38:37.270217",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "CRM", "module": "CRM",
"name": "Opportunity", "name": "Opportunity",
@@ -1516,5 +1549,5 @@
"title_field": "title", "title_field": "title",
"track_changes": 0, "track_changes": 0,
"track_seen": 1, "track_seen": 1,
"track_views": 0 "track_views": 1
} }

View File

@@ -91,10 +91,18 @@ class Opportunity(TransactionBase):
self.enquiry_from = "Lead" self.enquiry_from = "Lead"
self.lead = lead_name self.lead = lead_name
def declare_enquiry_lost(self,arg): def declare_enquiry_lost(self, lost_reasons_list, detailed_reason=None):
if not self.has_active_quotation(): if not self.has_active_quotation():
frappe.db.set(self, 'status', 'Lost') frappe.db.set(self, 'status', 'Lost')
frappe.db.set(self, 'order_lost_reason', arg)
if detailed_reason:
frappe.db.set(self, 'order_lost_reason', detailed_reason)
for reason in lost_reasons_list:
self.append('lost_reasons', reason)
self.save()
else: else:
frappe.throw(_("Cannot declare as lost, because Quotation has been made.")) frappe.throw(_("Cannot declare as lost, because Quotation has been made."))

View File

@@ -1,5 +1,7 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0, "allow_import": 0,
"allow_rename": 0, "allow_rename": 0,
"beta": 0, "beta": 0,
@@ -11,6 +13,8 @@
"engine": "InnoDB", "engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -39,9 +43,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -66,9 +73,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -96,9 +106,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -128,9 +141,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -159,9 +175,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -187,9 +206,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -218,9 +240,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -248,9 +273,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -279,10 +307,13 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0, "unique": 0,
"width": "300px" "width": "300px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -308,9 +339,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -338,9 +372,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -368,9 +405,12 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -399,20 +439,21 @@
"reqd": 0, "reqd": 0,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"translatable": 0,
"unique": 0 "unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0, "hide_heading": 0,
"hide_toolbar": 0, "hide_toolbar": 0,
"idx": 1, "idx": 1,
"image_view": 0, "image_view": 0,
"in_create": 0, "in_create": 0,
"is_submittable": 0, "is_submittable": 0,
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-02-17 17:03:05.528055", "modified": "2018-12-28 15:43:09.382012",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "CRM", "module": "CRM",
"name": "Opportunity Item", "name": "Opportunity Item",
@@ -423,5 +464,6 @@
"read_only_onload": 0, "read_only_onload": 0,
"show_name_in_global_search": 0, "show_name_in_global_search": 0,
"track_changes": 1, "track_changes": 1,
"track_seen": 0 "track_seen": 0,
"track_views": 0
} }

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Opportunity Lost Reason', {
refresh: function() {
}
});

View File

@@ -0,0 +1,153 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:lost_reason",
"beta": 0,
"creation": "2018-12-28 14:48:51.044975",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "lost_reason",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Lost Reason",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 1
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-12-28 14:49:43.336437",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity Lost Reason",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Master Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
from frappe.model.document import Document
class OpportunityLostReason(Document):
pass

View File

@@ -0,0 +1,27 @@
{
"add_total_row": 0,
"creation": "2018-12-31 16:30:57.188837",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"json": "{\"order_by\": \"`tabOpportunity`.`modified` desc\", \"filters\": [[\"Opportunity\", \"status\", \"=\", \"Lost\"]], \"fields\": [[\"name\", \"Opportunity\"], [\"enquiry_from\", \"Opportunity\"], [\"customer\", \"Opportunity\"], [\"lead\", \"Opportunity\"], [\"customer_name\", \"Opportunity\"], [\"opportunity_type\", \"Opportunity\"], [\"status\", \"Opportunity\"], [\"contact_by\", \"Opportunity\"], [\"docstatus\", \"Opportunity\"], [\"lost_reason\", \"Lost Reason Detail\"]], \"add_totals_row\": 0, \"add_total_row\": 0, \"page_length\": 20}",
"modified": "2018-12-31 16:33:08.083618",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lost Opportunity",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Opportunity",
"report_name": "Lost Opportunity",
"report_type": "Report Builder",
"roles": [
{
"role": "Sales User"
},
{
"role": "Sales Manager"
}
]
}

View File

@@ -64,7 +64,7 @@ def work():
report = "Material Requests for which Supplier Quotations are not created" report = "Material Requests for which Supplier Quotations are not created"
for row in query_report.run(report)["result"][:random.randint(1, 3)]: for row in query_report.run(report)["result"][:random.randint(1, 3)]:
if row[0] != "'Total'": if row[0] != "Total":
sq = frappe.get_doc(make_supplier_quotation(row[0])) sq = frappe.get_doc(make_supplier_quotation(row[0]))
sq.transaction_date = frappe.flags.current_date sq.transaction_date = frappe.flags.current_date
sq.supplier = supplier sq.supplier = supplier
@@ -79,7 +79,7 @@ def work():
from erpnext.stock.doctype.material_request.material_request import make_purchase_order from erpnext.stock.doctype.material_request.material_request import make_purchase_order
report = "Requested Items To Be Ordered" report = "Requested Items To Be Ordered"
for row in query_report.run(report)["result"][:how_many("Purchase Order")]: for row in query_report.run(report)["result"][:how_many("Purchase Order")]:
if row[0] != "'Total'": if row[0] != "Total":
try: try:
po = frappe.get_doc(make_purchase_order(row[0])) po = frappe.get_doc(make_purchase_order(row[0]))
po.supplier = supplier po.supplier = supplier

View File

@@ -25,7 +25,7 @@ def make_purchase_receipt():
if random.random() < 0.6: if random.random() < 0.6:
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
report = "Purchase Order Items To Be Received" report = "Purchase Order Items To Be Received"
po_list =list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="'Total'"]))[:random.randint(1, 10)] po_list =list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="Total"]))[:random.randint(1, 10)]
for po in po_list: for po in po_list:
pr = frappe.get_doc(make_purchase_receipt(po)) pr = frappe.get_doc(make_purchase_receipt(po))
@@ -49,7 +49,7 @@ def make_delivery_note():
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
report = "Ordered Items To Be Delivered" report = "Ordered Items To Be Delivered"
for so in list(set([r[0] for r in query_report.run(report)["result"] for so in list(set([r[0] for r in query_report.run(report)["result"]
if r[0]!="'Total'"]))[:random.randint(1, 3)]: if r[0]!="Total"]))[:random.randint(1, 3)]:
dn = frappe.get_doc(make_delivery_note(so)) dn = frappe.get_doc(make_delivery_note(so))
dn.posting_date = frappe.flags.current_date dn.posting_date = frappe.flags.current_date
for d in dn.get("items"): for d in dn.get("items"):

View File

@@ -117,9 +117,9 @@ def generate_fee(fee_schedule):
def get_students(student_group, academic_year, academic_term=None, student_category=None): def get_students(student_group, academic_year, academic_term=None, student_category=None):
conditions = "" conditions = ""
if student_category: if student_category:
conditions = " and pe.student_category='{}'".format(frappe.db.escape(student_category)) conditions = " and pe.student_category={}".format(frappe.db.escape(student_category))
if academic_term: if academic_term:
conditions = " and pe.academic_term='{}'".format(frappe.db.escape(academic_term)) conditions = " and pe.academic_term={}".format(frappe.db.escape(academic_term))
students = frappe.db.sql(""" students = frappe.db.sql("""
select pe.student, pe.student_name, pe.program, pe.student_batch_name select pe.student, pe.student_name, pe.program, pe.student_batch_name

View File

@@ -31,7 +31,7 @@ frappe.ui.form.on('Fee Structure', {
refresh: function(frm) { refresh: function(frm) {
if(frm.doc.docstatus === 1) { if(frm.doc.docstatus === 1) {
frm.add_custom_button(__("Make Fee Schedule"), function() { frm.add_custom_button(__('Create Fee Schedule'), function() {
frm.events.make_fee_schedule(frm); frm.events.make_fee_schedule(frm);
}); });
} }

View File

@@ -73,14 +73,14 @@ frappe.ui.form.on("Fees", {
if(frm.doc.docstatus===1 && frm.doc.outstanding_amount>0) { if(frm.doc.docstatus===1 && frm.doc.outstanding_amount>0) {
frm.add_custom_button(__("Payment Request"), function() { frm.add_custom_button(__("Payment Request"), function() {
frm.events.make_payment_request(frm); frm.events.make_payment_request(frm);
}, __("Make")); }, __('Create'));
frm.page.set_inner_btn_group_as_primary(__("Make")); frm.page.set_inner_btn_group_as_primary(__('Create'));
} }
if(frm.doc.docstatus===1 && frm.doc.outstanding_amount!=0) { if(frm.doc.docstatus===1 && frm.doc.outstanding_amount!=0) {
frm.add_custom_button(__("Payment"), function() { frm.add_custom_button(__("Payment"), function() {
frm.events.make_payment_entry(frm); frm.events.make_payment_entry(frm);
}, __("Make")); }, __('Create'));
frm.page.set_inner_btn_group_as_primary(__("Make")); frm.page.set_inner_btn_group_as_primary(__('Create'));
} }
}, },

View File

@@ -130,6 +130,13 @@ website_route_rules = [
{"from_route": "/admissions", "to_route": "Student Admission"}, {"from_route": "/admissions", "to_route": "Student Admission"},
{"from_route": "/boms", "to_route": "BOM"}, {"from_route": "/boms", "to_route": "BOM"},
{"from_route": "/timesheets", "to_route": "Timesheet"}, {"from_route": "/timesheets", "to_route": "Timesheet"},
{"from_route": "/material-requests", "to_route": "Material Request"},
{"from_route": "/material-requests/<path:name>", "to_route": "material_request_info",
"defaults": {
"doctype": "Material Request",
"parents": [{"label": _("Material Request"), "route": "material-requests"}]
}
},
] ]
standard_portal_menu_items = [ standard_portal_menu_items = [
@@ -152,6 +159,7 @@ standard_portal_menu_items = [
{"title": _("Newsletter"), "route": "/newsletters", "reference_doctype": "Newsletter"}, {"title": _("Newsletter"), "route": "/newsletters", "reference_doctype": "Newsletter"},
{"title": _("Admission"), "route": "/admissions", "reference_doctype": "Student Admission"}, {"title": _("Admission"), "route": "/admissions", "reference_doctype": "Student Admission"},
{"title": _("Certification"), "route": "/certification", "reference_doctype": "Certification Application"}, {"title": _("Certification"), "route": "/certification", "reference_doctype": "Certification Application"},
{"title": _("Material Request"), "route": "/material-requests", "reference_doctype": "Material Request", "role": "Customer"},
] ]
default_roles = [ default_roles = [
@@ -165,6 +173,7 @@ has_website_permission = {
"Quotation": "erpnext.controllers.website_list_for_contact.has_website_permission", "Quotation": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Sales Invoice": "erpnext.controllers.website_list_for_contact.has_website_permission", "Sales Invoice": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Supplier Quotation": "erpnext.controllers.website_list_for_contact.has_website_permission", "Supplier Quotation": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Material Request": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Delivery Note": "erpnext.controllers.website_list_for_contact.has_website_permission", "Delivery Note": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Issue": "erpnext.support.doctype.issue.issue.has_website_permission", "Issue": "erpnext.support.doctype.issue.issue.has_website_permission",
"Timesheet": "erpnext.controllers.website_list_for_contact.has_website_permission", "Timesheet": "erpnext.controllers.website_list_for_contact.has_website_permission",
@@ -228,6 +237,7 @@ scheduler_events = {
'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails', 'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',
"erpnext.accounts.doctype.subscription.subscription.process_all", "erpnext.accounts.doctype.subscription.subscription.process_all",
"erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details", "erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details",
"erpnext.accounts.doctype.gl_entry.gl_entry.rename_gle_sle_docs",
"erpnext.projects.doctype.project.project.hourly_reminder", "erpnext.projects.doctype.project.project.hourly_reminder",
"erpnext.projects.doctype.project.project.collect_project_status" "erpnext.projects.doctype.project.project.collect_project_status"
], ],
@@ -249,7 +259,8 @@ scheduler_events = {
"erpnext.assets.doctype.asset.asset.make_post_gl_entry", "erpnext.assets.doctype.asset.asset.make_post_gl_entry",
"erpnext.crm.doctype.contract.contract.update_status_for_contracts", "erpnext.crm.doctype.contract.contract.update_status_for_contracts",
"erpnext.projects.doctype.project.project.update_project_sales_billing", "erpnext.projects.doctype.project.project.update_project_sales_billing",
"erpnext.projects.doctype.project.project.send_project_status_email_to_users" "erpnext.projects.doctype.project.project.send_project_status_email_to_users",
"erpnext.quality_management.doctype.quality_review.quality_review.review"
], ],
"daily_long": [ "daily_long": [
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms" "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"

View File

@@ -4,7 +4,7 @@
frappe.ui.form.on('Hotel Room Reservation', { frappe.ui.form.on('Hotel Room Reservation', {
refresh: function(frm) { refresh: function(frm) {
if(frm.doc.docstatus == 1){ if(frm.doc.docstatus == 1){
frm.add_custom_button(__("Make Invoice"), ()=> { frm.add_custom_button(__('Create Invoice'), ()=> {
frm.trigger("make_invoice"); frm.trigger("make_invoice");
}); });
} }

View File

@@ -90,7 +90,7 @@ def get_room_rate(hotel_room_reservation):
def get_rooms_booked(room_type, day, exclude_reservation=None): def get_rooms_booked(room_type, day, exclude_reservation=None):
exclude_condition = '' exclude_condition = ''
if exclude_reservation: if exclude_reservation:
exclude_condition = 'and reservation.name != "{0}"'.format(frappe.db.escape(exclude_reservation)) exclude_condition = 'and reservation.name != {0}'.format(frappe.db.escape(exclude_reservation))
return frappe.db.sql(""" return frappe.db.sql("""
select sum(item.qty) select sum(item.qty)

View File

@@ -13,7 +13,7 @@ from frappe.utils import cstr
class Attendance(Document): class Attendance(Document):
def validate_duplicate_record(self): def validate_duplicate_record(self):
res = frappe.db.sql("""select name from `tabAttendance` where employee = %s and attendance_date = %s res = frappe.db.sql("""select name from `tabAttendance` where employee = %s and attendance_date = %s
and name != %s and docstatus = 1""", and name != %s and docstatus != 2""",
(self.employee, self.attendance_date, self.name)) (self.employee, self.attendance_date, self.name))
if res: if res:
frappe.throw(_("Attendance for employee {0} is already marked").format(self.employee)) frappe.throw(_("Attendance for employee {0} is already marked").format(self.employee))

View File

@@ -31,7 +31,7 @@ frappe.ui.form.on('Employee Advance', {
&& (flt(frm.doc.paid_amount) < flt(frm.doc.advance_amount)) && (flt(frm.doc.paid_amount) < flt(frm.doc.advance_amount))
&& frappe.model.can_create("Payment Entry")) { && frappe.model.can_create("Payment Entry")) {
frm.add_custom_button(__('Payment'), frm.add_custom_button(__('Payment'),
function() { frm.events.make_payment_entry(frm); }, __("Make")); function() { frm.events.make_payment_entry(frm); }, __('Create'));
} }
else if ( else if (
frm.doc.docstatus === 1 frm.doc.docstatus === 1
@@ -43,7 +43,7 @@ frappe.ui.form.on('Employee Advance', {
function() { function() {
frm.events.make_expense_claim(frm); frm.events.make_expense_claim(frm);
}, },
__("Make") __('Create')
); );
} }
}, },

View File

@@ -2,7 +2,28 @@
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Employee Grade', { frappe.ui.form.on('Employee Grade', {
refresh: function(frm) { refresh: function (frm) {
},
setup: function (frm) {
frm.set_query("default_salary_structure", function () {
return {
"filters": {
"docstatus": 1,
"is_active": "Yes"
}
};
});
frm.set_query("default_leave_policy", function () {
return {
"filters": {
"docstatus": 1
}
};
});
}
}
}); });

View File

@@ -15,6 +15,7 @@
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -47,6 +48,7 @@
}, },
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
@@ -88,7 +90,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-04-13 16:14:24.174138", "modified": "2018-09-18 17:17:45.617624",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "HR", "module": "HR",
"name": "Employee Grade", "name": "Employee Grade",
@@ -153,12 +155,13 @@
"write": 1 "write": 1
} }
], ],
"quick_entry": 1, "quick_entry": 0,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"show_name_in_global_search": 0, "show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"track_changes": 1, "track_changes": 1,
"track_seen": 0 "track_seen": 0,
"track_views": 0
} }

View File

@@ -46,7 +46,7 @@ frappe.ui.form.on('Employee Loan', {
refresh: function (frm) { refresh: function (frm) {
if (frm.doc.docstatus == 1 && (frm.doc.status == "Sanctioned" || frm.doc.status == "Partially Disbursed")) { if (frm.doc.docstatus == 1 && (frm.doc.status == "Sanctioned" || frm.doc.status == "Partially Disbursed")) {
frm.add_custom_button(__('Make Disbursement Entry'), function () { frm.add_custom_button(__('Create Disbursement Entry'), function () {
frm.trigger("make_jv"); frm.trigger("make_jv");
}) })
} }

View File

@@ -29,8 +29,8 @@ frappe.ui.form.on('Employee Onboarding', {
method: "erpnext.hr.doctype.employee_onboarding.employee_onboarding.make_employee", method: "erpnext.hr.doctype.employee_onboarding.employee_onboarding.make_employee",
frm: frm frm: frm
}); });
}, __("Make")); }, __('Create'));
frm.page.set_inner_btn_group_as_primary(__("Make")); frm.page.set_inner_btn_group_as_primary(__('Create'));
} }
if (frm.doc.docstatus === 1 && frm.doc.project) { if (frm.doc.docstatus === 1 && frm.doc.project) {
frappe.call({ frappe.call({

View File

@@ -192,7 +192,7 @@ frappe.ui.form.on("Expense Claim", {
&& (cint(frm.doc.total_amount_reimbursed) < cint(frm.doc.total_sanctioned_amount)) && (cint(frm.doc.total_amount_reimbursed) < cint(frm.doc.total_sanctioned_amount))
&& frappe.model.can_create("Payment Entry")) { && frappe.model.can_create("Payment Entry")) {
frm.add_custom_button(__('Payment'), frm.add_custom_button(__('Payment'),
function() { frm.events.make_payment_entry(frm); }, __("Make")); function() { frm.events.make_payment_entry(frm); }, __('Create'));
} }
}, },

Some files were not shown because too many files have changed in this diff Show More