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
commit 590491779a
351 changed files with 90358 additions and 77878 deletions

View File

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

3
.gitignore vendored
View File

@ -12,5 +12,6 @@ erpnext/docs/current
*.swo
__pycache__
*~
.idea/
.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

@ -144,4 +144,4 @@ def is_member():
last_membership = get_last_membership()
if last_membership and getdate(last_membership.to_date) > getdate():
return True
return False
return False

View File

@ -29,7 +29,7 @@ def validate_service_stop_date(doc):
if date_diff(item.service_stop_date, item.service_end_date) > 0:
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)))
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()});
}, __('View'));
// make
treeview.page.add_inner_button(__("Journal Entry"), function() {
frappe.new_doc('Journal Entry', {company: get_company()});
}, __('Make'));
}, __('Create'));
treeview.page.add_inner_button(__("New Company"), function() {
frappe.new_doc('Company');
}, __('Make'));
}, __('Create'));
// financial statements
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
rows = read_xlsx_file_from_attached_file(file_id=filename)
elif (filename.lower().endswith("csv")):
from frappe.utils.file_manager import get_file_path
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:
rows = read_csv_content(csvfile.read())
elif (filename.lower().endswith("xls")):
@ -428,8 +428,8 @@ def get_transaction_entries(filename, headers):
return transactions
def get_rows_from_xls_file(filename):
from frappe.utils.file_manager import get_file_path
filepath = get_file_path(filename)
_file = frappe.get_doc("File", {"file_name": filename})
filepath = _file.get_full_path()
import xlrd
book = xlrd.open_workbook(filepath)
sheets = book.sheets()

View File

@ -15,7 +15,7 @@ class DuplicateBudgetError(frappe.ValidationError): pass
class Budget(Document):
def autoname(self):
self.name = make_autoname(self.get(frappe.scrub(self.budget_against))
self.name = make_autoname(self.get(frappe.scrub(self.budget_against))
+ "/" + self.fiscal_year + "/.###")
def validate(self):
@ -89,7 +89,7 @@ def validate_expense_against_budget(args):
if args.get('company') and not args.fiscal_year:
args.fiscal_year = get_fiscal_year(args.get('posting_date'), company=args.get('company'))[0]
frappe.flags.exception_approver_role = frappe.get_cached_value('Company',
frappe.flags.exception_approver_role = frappe.get_cached_value('Company',
args.get('company'), 'exception_budget_approver_role')
if not args.account:
@ -106,12 +106,12 @@ def validate_expense_against_budget(args):
and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"})):
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"
elif args.cost_center and budget_against == 'cost_center':
cc_lft, cc_rgt = frappe.db.get_value("Cost Center", args.cost_center, ["lft", "rgt"])
condition = """and exists(select name from `tabCost Center`
condition = """and exists(select name from `tabCost Center`
where lft<=%s and rgt>=%s and name=b.cost_center)""" % (cc_lft, cc_rgt)
args.budget_against_field = "Cost Center"
@ -126,13 +126,13 @@ def validate_expense_against_budget(args):
b.action_if_annual_budget_exceeded, b.action_if_accumulated_monthly_budget_exceeded,
b.action_if_annual_budget_exceeded_on_mr, b.action_if_accumulated_monthly_budget_exceeded_on_mr,
b.action_if_annual_budget_exceeded_on_po, b.action_if_accumulated_monthly_budget_exceeded_on_po
from
from
`tabBudget` b, `tabBudget Account` ba
where
b.name=ba.parent and b.fiscal_year=%s
b.name=ba.parent and b.fiscal_year=%s
and ba.account=%s and b.docstatus=1
{condition}
""".format(condition=condition,
""".format(condition=condition,
budget_against_field=frappe.scrub(args.get("budget_against_field"))),
(args.fiscal_year, args.account), as_dict=True)
@ -151,12 +151,12 @@ def validate_budget_records(args, budget_records):
args["month_end_date"] = get_last_day(args.posting_date)
compare_expense_with_budget(args, budget_amount,
compare_expense_with_budget(args, budget_amount,
_("Accumulated Monthly"), monthly_action, budget.budget_against, amount)
if yearly_action in ("Stop", "Warn") and monthly_action != "Stop" \
and yearly_action != monthly_action:
compare_expense_with_budget(args, flt(budget.budget_amount),
compare_expense_with_budget(args, flt(budget.budget_amount),
_("Annual"), yearly_action, budget.budget_against, amount)
def compare_expense_with_budget(args, budget_amount, action_for, action, budget_against, amount=0):
@ -166,9 +166,9 @@ def compare_expense_with_budget(args, budget_amount, action_for, action, budget_
currency = frappe.get_cached_value('Company', args.company, 'default_currency')
msg = _("{0} Budget for Account {1} against {2} {3} is {4}. It will exceed by {5}").format(
_(action_for), frappe.bold(args.account), args.budget_against_field,
_(action_for), frappe.bold(args.account), args.budget_against_field,
frappe.bold(budget_against),
frappe.bold(fmt_money(budget_amount, currency=currency)),
frappe.bold(fmt_money(budget_amount, currency=currency)),
frappe.bold(fmt_money(diff, currency=currency)))
if (frappe.flags.exception_approver_role
@ -250,12 +250,12 @@ def get_actual_expense(args):
condition1 = " and gle.posting_date <= %(month_end_date)s" \
if args.get("month_end_date") else ""
if args.budget_against_field == "Cost Center":
lft_rgt = frappe.db.get_value(args.budget_against_field,
lft_rgt = frappe.db.get_value(args.budget_against_field,
args.budget_against, ["lft", "rgt"], as_dict=1)
args.update(lft_rgt)
condition2 = """and exists(select name from `tabCost Center`
condition2 = """and exists(select name from `tabCost Center`
where lft>=%(lft)s and rgt<=%(rgt)s and name=gle.cost_center)"""
elif args.budget_against_field == "Project":
condition2 = "and exists(select name from `tabProject` where name=gle.project and gle.project = %(budget_against)s)"

View File

@ -19,7 +19,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Cashier-closing-",
"default": "POS-CLO-",
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
@ -32,7 +32,7 @@
"label": "Series",
"length": 0,
"no_copy": 0,
"options": "Cashier-closing-\n",
"options": "POS-CLO-",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@ -230,6 +230,37 @@
"set_only_once": 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_on_submit": 0,
@ -364,7 +395,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-09-03 10:59:54.500567",
"modified": "2018-10-21 14:26:15.812416",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cashier Closing",
@ -400,4 +431,4 @@
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}
}

View File

@ -29,7 +29,7 @@ class CashierClosing(Document):
for i in self.payments:
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):
if self.from_time >= self.time:

View File

@ -21,7 +21,7 @@ frappe.ui.form.on('Exchange Rate Revaluation', {
refresh: function(frm) {
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);
});
}
@ -54,7 +54,7 @@ frappe.ui.form.on('Exchange Rate Revaluation', {
d.gain_loss = flt(d.new_balance_in_base_currency, precision("new_balance_in_base_currency", d)) - flt(d.balance_in_base_currency, precision("balance_in_base_currency", d));
total_gain_loss += flt(d.gain_loss, precision("gain_loss", d));
});
frm.set_value("total_gain_loss", flt(total_gain_loss, precision("total_gain_loss")));
frm.refresh_fields();
},

File diff suppressed because it is too large Load Diff

View File

@ -6,14 +6,21 @@ import frappe, erpnext
from frappe import _
from frappe.utils import flt, fmt_money, getdate, formatdate
from frappe.model.document import Document
from frappe.model.naming import set_name_from_naming_options
from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled
from erpnext.accounts.utils import get_account_currency
from erpnext.accounts.utils import get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency
exclude_from_linked_with = True
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):
self.flags.ignore_submit_comment = True
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):
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))
else:
party_condition = ""
@ -230,3 +237,17 @@ def update_against_account(voucher_type, voucher_no):
if d.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
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.gl_entry.gl_entry import rename_gle_sle_docs
class TestGLEntry(unittest.TestCase):
def test_round_off_entry(self):
@ -23,3 +25,32 @@ class TestGLEntry(unittest.TestCase):
and debit = 0 and credit = '.01'""", jv.name)
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);
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() {
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();
var args = d.get_values();
frappe.call({
@ -92,10 +92,10 @@ frappe.ui.form.on("Journal Entry", {
multi_currency: function(frm) {
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
},
posting_date: function(frm) {
if(!frm.doc.multi_currency || !frm.doc.posting_date) return;
$.each(frm.doc.accounts || [], function(i, row) {
erpnext.journal_entry.set_exchange_rate(frm, row.doctype, row.name);
})
@ -382,7 +382,7 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
});
refresh_field("accounts");
}
if((!(doc.accounts || []).length) || ((doc.accounts || []).length==1 && !doc.accounts[0].account)) {
if(in_list(["Bank Entry", "Cash Entry"], doc.voucher_type)) {
return frappe.call({
@ -442,7 +442,7 @@ frappe.ui.form.on("Journal Entry Account", {
account: function(frm, dt, dn) {
erpnext.journal_entry.set_account_balance(frm, dt, dn);
},
debit_in_account_currency: function(frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
},

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
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.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))

View File

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

View File

@ -15,7 +15,7 @@ frappe.ui.form.on('Opening Invoice Creation Tool', {
refresh: function(frm) {
frm.disable_save();
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);
return frm.call({
doc: frm.doc,

View File

@ -560,7 +560,7 @@ def get_outstanding_reference_documents(args):
# Get positive outstanding sales /purchase invoices/ Fees
condition = ""
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"]))
# Add cost center condition

View File

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

View File

@ -13,18 +13,19 @@ class PaymentReconciliation(Document):
def get_unreconciled_entries(self):
self.get_nonreconciled_payment_entries()
self.get_invoice_entries()
def get_nonreconciled_payment_entries(self):
self.check_mandatory_to_fetch()
payment_entries = self.get_payment_entries()
journal_entries = self.get_jv_entries()
self.add_payment_entries(payment_entries + journal_entries)
def get_payment_entries(self):
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)
return payment_entries
@ -40,8 +41,8 @@ class PaymentReconciliation(Document):
journal_entries = frappe.db.sql("""
select
"Journal Entry" as reference_type, t1.name as reference_name,
t1.posting_date, t1.remark as remarks, t2.name as reference_row,
"Journal Entry" as reference_type, t1.name as reference_name,
t1.posting_date, t1.remark as remarks, t2.name as reference_row,
{dr_or_cr} as amount, t2.is_advance
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
@ -49,8 +50,8 @@ class PaymentReconciliation(Document):
t1.name = t2.parent and t1.docstatus = 1 and t2.docstatus = 1
and t2.party_type = %(party_type)s and t2.party = %(party)s
and t2.account = %(account)s and {dr_or_cr} > 0
and (t2.reference_type is null or t2.reference_type = '' or
(t2.reference_type in ('Sales Order', 'Purchase Order')
and (t2.reference_type is null or t2.reference_type = '' or
(t2.reference_type in ('Sales Order', 'Purchase Order')
and t2.reference_name is not null and t2.reference_name != ''))
and (CASE
WHEN t1.voucher_type in ('Debit Note', 'Credit Note')
@ -109,7 +110,7 @@ class PaymentReconciliation(Document):
self.validate_invoice()
dr_or_cr = ("credit_in_account_currency"
if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency")
lst = []
for e in self.get('payments'):
if e.invoice_number and e.allocated_amount:
@ -127,11 +128,11 @@ class PaymentReconciliation(Document):
'unadjusted_amount' : flt(e.amount),
'allocated_amount' : flt(e.allocated_amount)
}))
if lst:
from erpnext.accounts.utils import reconcile_against_document
reconcile_against_document(lst)
msgprint(_("Successfully Reconciled"))
self.get_unreconciled_entries()
@ -174,8 +175,8 @@ class PaymentReconciliation(Document):
frappe.throw(_("Please select Allocated Amount, Invoice Type and Invoice Number in atleast one row"))
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.to_date)) if self.to_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 ""
dr_or_cr = ("debit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable'
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") {
frm.add_custom_button(__('Make Payment Entry'), function(){
frm.add_custom_button(__('Create Payment Entry'), function(){
frappe.call({
method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_entry",
args: {"docname": frm.doc.name},

View File

@ -107,7 +107,7 @@ def get_item_groups(pos_profile):
if pos_profile.get('item_groups'):
# Get items based on the item groups defined in the POS profile
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))

View File

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

View File

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

View File

@ -15,6 +15,7 @@
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -44,10 +45,12 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -77,10 +80,12 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -99,7 +104,7 @@
"no_copy": 0,
"oldfieldname": "charge_type",
"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,
"print_hide": 0,
"print_hide_if_no_value": 0,
@ -109,10 +114,12 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -141,10 +148,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -172,10 +181,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -200,10 +211,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -232,10 +245,12 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -265,10 +280,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -297,11 +314,13 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "300px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -327,10 +346,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -358,10 +379,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -387,10 +410,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -419,10 +444,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -450,10 +477,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -482,10 +511,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -511,10 +542,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -542,10 +575,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -573,10 +608,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -604,10 +641,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -635,10 +674,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -666,6 +707,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
@ -679,7 +721,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-12-06 13:37:44.483509",
"modified": "2018-09-19 13:48:32.755198",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",
@ -690,5 +732,6 @@
"read_only_onload": 0,
"show_name_in_global_search": 0,
"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
&& !(cint(doc.is_return) && doc.return_against)) {
cur_frm.add_custom_button(__('Payment'),
this.make_payment_entry, __("Make"));
cur_frm.page.set_inner_btn_group_as_primary(__("Make"));
this.make_payment_entry, __('Create'));
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
}
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)) {
cur_frm.add_custom_button(__('Return / Credit Note'),
this.make_sales_return, __("Make"));
cur_frm.page.set_inner_btn_group_as_primary(__("Make"));
this.make_sales_return, __('Create'));
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
}
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) {
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)) {
cur_frm.add_custom_button(__('Payment Request'), function() {
me.make_payment_request();
}, __("Make"));
}, __('Create'));
}
if(!doc.auto_repeat) {
cur_frm.add_custom_button(__('Subscription'), function() {
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) {
me.frm.add_custom_button("Inter Company Invoice", function() {
me.make_inter_company_invoice();
}, __("Make"));
}, __('Create'));
}
});
}

View File

@ -729,7 +729,7 @@ class TestSalesInvoice(unittest.TestCase):
# check gl entries
gl_entries = frappe.db.sql("""select account, debit, credit
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)
stock_in_hand = get_inventory_account('_Test Company')
@ -762,7 +762,7 @@ class TestSalesInvoice(unittest.TestCase):
set_perpetual_inventory(0)
frappe.db.sql("delete from `tabPOS Profile`")
def test_pos_si_without_payment(self):
set_perpetual_inventory()
make_pos_profile()

View File

@ -33,7 +33,7 @@
"no_copy": 0,
"oldfieldname": "charge_type",
"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,
"print_hide": 0,
"print_hide_if_no_value": 0,
@ -652,7 +652,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-08-21 16:15:51.518582",
"modified": "2018-09-19 13:48:59.341454",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",
@ -666,4 +666,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -17,7 +17,7 @@ frappe.ui.form.on('Share Transfer', {
};
});
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);
});
}

View File

@ -75,7 +75,7 @@ class TaxRule(Document):
for d in filters:
if conds:
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:
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)
conditions.append("ifnull({0}, '') in ('', {1})".format(key, customer_group_condition))
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`
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):
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:
condition = ",".join(['%s'] * len(customer_groups))%(tuple(customer_groups))
return condition

View File

@ -450,7 +450,7 @@ def get_timeline_data(doctype, name):
# fetch and append data from Activity Log
data += frappe.db.sql("""select {fields}
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}
{group_by} order by creation desc
""".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
from `tabSales Invoice` si, `tabPayment Schedule` ps
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
""" % (frappe.db.escape(self.filters.company), ','.join(['%s'] *len(voucher_nos))),
(tuple(voucher_nos)), as_dict = 1)

View File

@ -86,20 +86,20 @@ def get_columns(filters):
_("Total Variance") + ":Float:80"]
else:
return columns
def get_cost_centers(filters):
cond = "and 1=1"
if filters.get("budget_against") == "Cost Center":
cond = "order by lft"
return frappe.db.sql_list("""select name from `tab{tab}` where company=%s
return frappe.db.sql_list("""select name from `tab{tab}` where company=%s
{cond}""".format(tab=filters.get("budget_against"), cond=cond), filters.get("company"))
#Get cost center & target details
def get_cost_center_target_details(filters):
cond = ""
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("""
select b.{budget_against} as budget_against, b.monthly_distribution, ba.account, ba.budget_amount,b.fiscal_year
@ -159,7 +159,7 @@ def get_cost_center_account_month_map(filters):
for ccd in cost_center_target_details:
actual_details = get_actual_details(ccd.budget_against, filters)
for month_id in range(1, 13):
month = datetime.date(2013, month_id, 1).strftime('%B')
cam_map.setdefault(ccd.budget_against, {}).setdefault(ccd.account, {}).setdefault(ccd.fiscal_year,{})\
@ -172,7 +172,7 @@ def get_cost_center_account_month_map(filters):
if ccd.monthly_distribution else 100.0/12
tav_dict.target = flt(ccd.budget_amount) * month_percentage / 100
for ad in actual_details.get(ccd.account, []):
if ad.month_name == month:
tav_dict.actual += flt(ad.debit) - flt(ad.credit)

View File

@ -101,7 +101,7 @@ def get_income_expense_data(companies, fiscal_year, filters):
net_profit_loss = get_net_profit_loss(income, expense, companies, filters.company, company_currency, True)
return income, expense, net_profit_loss
def get_cash_flow_data(fiscal_year, companies, filters):
cash_flow_accounts = get_cash_flow_accounts()
@ -123,7 +123,7 @@ def get_cash_flow_data(fiscal_year, companies, filters):
# add first net income in operations section
if net_profit_loss:
net_profit_loss.update({
"indent": 1,
"indent": 1,
"parent_account": cash_flow_accounts[0]['section_header']
})
data.append(net_profit_loss)
@ -274,7 +274,8 @@ def get_companies(filters):
return all_companies, companies
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`
where lft >= {0} and rgt <= {1} order by lft, rgt""".format(lft, rgt))
@ -327,7 +328,7 @@ def set_gl_entries_by_account(from_date, to_date, root_lft, root_rgt, filters, g
accounts_by_name, ignore_closing_entries=False):
"""Returns a dict like { "account": [gl entries], ... }"""
company_lft, company_rgt = frappe.get_cached_value('Company',
company_lft, company_rgt = frappe.get_cached_value('Company',
filters.get('company'), ["lft", "rgt"])
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
@ -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"))
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))
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")))
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`
where lft >= %s and rgt <= %s""", (root_lft, root_rgt))
additional_conditions += " and account in ('{}')"\
.format("', '".join([frappe.db.escape(d) for d in accounts]))
additional_conditions += " and account in ({})"\
.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`
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"))
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))
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")))
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""

View File

@ -329,7 +329,7 @@ class GrossProfitGenerator(object):
where company=%(company)s
order by
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 = {}
for r in res:
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 = []
if date:
cond.append("posting_date <= '%s'" % frappe.db.escape(cstr(date)))
cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
else:
# get balance of all entries that exist
date = nowdate()
@ -127,7 +127,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
)""" % (cc.lft, cc.rgt))
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:
@ -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"):
in_account_currency = False
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:
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)))
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 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):
cond = []
if date:
cond.append("posting_date <= '%s'" % frappe.db.escape(cstr(date)))
cond.append("posting_date <= %s" % frappe.db.escape(cstr(date)))
else:
# get balance of all entries that exist
date = nowdate()
@ -218,7 +218,7 @@ def get_count_on(account, fieldname, date):
and ac.lft >= %s and ac.rgt <= %s
)""" % (acc.lft, acc.rgt))
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("""
SELECT name, posting_date, account, party_type, party,debit,credit,

View File

@ -31,7 +31,7 @@ frappe.ui.form.on('Asset', {
}
};
});
frm.set_query("cost_center", function() {
return {
"filters": {
@ -81,26 +81,26 @@ frappe.ui.form.on('Asset', {
if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) {
frm.add_custom_button(__("Purchase Invoice"), function() {
frm.trigger("make_purchase_invoice");
}, __("Make"));
}, __('Create'));
}
if (frm.doc.maintenance_required && !frm.doc.maintenance_schedule) {
frm.add_custom_button(__("Asset Maintenance"), function() {
frm.trigger("create_asset_maintenance");
}, __("Make"));
}, __('Create'));
}
if (frm.doc.status != 'Fully Depreciated') {
frm.add_custom_button(__("Asset Value Adjustment"), function() {
frm.trigger("create_asset_adjustment");
}, __("Make"));
}, __('Create'));
}
if (!frm.doc.calculate_depreciation) {
frm.add_custom_button(__("Depreciation Entry"), function() {
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");
}

View File

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

View File

@ -42,6 +42,7 @@ frappe.ui.form.on("Purchase Order", {
frm: frm,
child_docname: "items",
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(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") {
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)
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") {
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) {
cur_frm.add_custom_button(__('Subscription'), function() {
erpnext.utils.make_subscription(doc.doctype, doc.name)
}, __("Make"))
}, __('Create'))
}
if(flt(doc.per_billed)==0) {
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'));
}
},

File diff suppressed because it is too large Load Diff

View File

@ -183,7 +183,7 @@ class PurchaseOrder(BuyingController):
def check_modified_date(self):
mod_db = frappe.db.sql("select modified from `tabPurchase Order` where name = %s",
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]:
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:
received_qty += item.received_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):
"""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) {
if (frm.doc.docstatus === 1) {
frm.add_custom_button(__("Make"),
frm.add_custom_button(__('Create'),
function(){ frm.trigger("make_suppplier_quotation") }, __("Supplier Quotation"));
frm.add_custom_button(__("View"),
@ -147,7 +147,7 @@ frappe.ui.form.on("Request for Quotation",{
"fieldname": "supplier",
"options": doc.suppliers.map(d => d.supplier),
"reqd": 1 },
{ "fieldtype": "Button", "label": __("Make Supplier Quotation"),
{ "fieldtype": "Button", "label": __('Create Supplier Quotation'),
"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 () {
erpnext.utils.make_bank_account(frm.doc.doctype, frm.doc.name);
}, __("Make"));
}, __('Create'));
frm.add_custom_button(__('Pricing Rule'), function () {
erpnext.utils.make_pricing_rule(frm.doc.doctype, frm.doc.name);
}, __("Make"));
}, __('Create'));
// indicators
erpnext.utils.set_party_dashboard_indicators(frm);

View File

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

View File

@ -242,7 +242,7 @@ def get_data():
{
"type": "doctype",
"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"
},
{
"module_name": "Project",
"_doctype": "Project",
"module_name": "Projects",
"color": "#8e44ad",
"icon": "octicon octicon-rocket",
"type": "link",
"link": "List/Project"
"type": "module",
},
{
"module_name": "Issue",
@ -71,6 +69,7 @@ def get_data():
# old
{
"label": _("Accounting"),
"module_name": "Accounts",
"color": "#3498db",
"icon": "octicon octicon-repo",
@ -136,13 +135,6 @@ def get_data():
"link": "leaderboard",
"label": _("Leaderboard")
},
{
"module_name": "Projects",
"color": "#8e44ad",
"icon": "octicon octicon-rocket",
"type": "module",
"hidden": 1
},
{
"module_name": "Support",
"color": "#2c3e50",
@ -151,12 +143,12 @@ def get_data():
"hidden": 1
},
{
"module_name": "Learn",
"module_name": "Help",
"color": "#FF888B",
"icon": "octicon octicon-device-camera-video",
"type": "module",
"is_help": True,
"label": _("Learn"),
"label": _("Help"),
"hidden": 1
},
{
@ -573,5 +565,12 @@ def get_data():
"type": "module",
"label": _("Non Profit"),
"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": [
{
"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 (
("accounts", _("Accounts"), "fa fa-money"),
("accounts", _("Accounting"), "fa fa-money"),
("stock", _("Stock"), "fa fa-truck"),
("selling", _("Selling"), "fa fa-tag"),
("buying", _("Buying"), "fa fa-shopping-cart"),

View File

@ -6,6 +6,7 @@ import frappe, erpnext
import json
from frappe import _, throw
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.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
from erpnext.utilities.transaction_base import TransactionBase
@ -1072,12 +1073,56 @@ def get_supplier_block_status(party_name):
}
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()
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)
parent = frappe.get_doc(parent_doctype, parent_doctype_name)
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:
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:
child_item.rate = flt(d.get("rate"))
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
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()
parent.set_payment_schedule()
if parent_doctype == 'Purchase Order':
p_doctype.validate_minimum_order_qty()
p_doctype.validate_budget()
if p_doctype.is_against_so():
p_doctype.update_status_updater()
parent.validate_minimum_order_qty()
parent.validate_budget()
if parent.is_against_so():
parent.update_status_updater()
else:
p_doctype.check_credit_limit()
parent.check_credit_limit()
p_doctype.save()
parent.save()
if parent_doctype == 'Purchase Order':
update_last_purchase_rate(p_doctype, is_submit = 1)
p_doctype.update_prevdoc_status()
p_doctype.update_requested_qty()
p_doctype.update_ordered_qty()
p_doctype.update_ordered_and_reserved_qty()
p_doctype.update_receiving_percentage()
if p_doctype.is_subcontracted == "Yes":
p_doctype.update_reserved_qty_for_subcontract()
update_last_purchase_rate(parent, is_submit = 1)
parent.update_prevdoc_status()
parent.update_requested_qty()
parent.update_ordered_qty()
parent.update_ordered_and_reserved_qty()
parent.update_receiving_percentage()
if parent.is_subcontracted == "Yes":
parent.update_reserved_qty_for_subcontract()
else:
p_doctype.update_reserved_qty()
p_doctype.update_project()
p_doctype.update_prevdoc_status('submit')
p_doctype.update_delivery_status()
parent.update_reserved_qty()
parent.update_project()
parent.update_prevdoc_status('submit')
parent.update_delivery_status()
p_doctype.update_blanket_order()
p_doctype.update_billing_percentage()
p_doctype.set_status()
parent.update_blanket_order()
parent.update_billing_percentage()
parent.set_status()

View File

@ -761,7 +761,7 @@ def validate_item_type(doc, fieldname, message):
if not items:
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("""
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
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()]
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(
fcond=get_filters_cond(doctype, filters, conditions),
mcond=get_match_cond(doctype),
key=frappe.db.escape(searchfield)),
{
'txt': "%%%s%%" % frappe.db.escape(txt),
key=searchfield), {
'txt': '%' + txt + '%',
'_txt': txt.replace("%", ""),
'start': start or 0,
'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):
cond = ''
if filters.get('customer'):
cond = """(`tabProject`.customer = '%s' or
cond = """(`tabProject`.customer = %s or
ifnull(`tabProject`.customer,"")="") and""" %(frappe.db.escape(filters.get("customer")))
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}
order by idx desc, name"""
.format(condition=condition, match_condition=get_match_cond(doctype), key=searchfield), {
'txt': "%%%s%%" % frappe.db.escape(txt),
'txt': '%' + txt + '%',
'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.{key} LIKE %(txt)s
{condition} {match_condition}"""
.format(condition=condition, key=frappe.db.escape(searchfield),
.format(condition=condition, key=searchfield,
match_condition=get_match_cond(doctype)), {
'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
from `tabWarehouse`
where
`tabWarehouse`.`{key}` like '{txt}'
`tabWarehouse`.`{key}` like {txt}
{fcond} {mcond}
order by
`tabWarehouse`.name desc
@ -406,7 +405,7 @@ def warehouse_query(doctype, txt, searchfield, start, page_len, filters):
{start}, {page_len}
""".format(
sub_query=sub_query,
key=frappe.db.escape(searchfield),
key=searchfield,
fcond=get_filters_cond(doctype, filter_dict.get("Warehouse"), conditions),
mcond=get_match_cond(doctype),
start=start,
@ -430,9 +429,9 @@ def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
query = """select batch_id from `tabBatch`
where disabled = 0
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'):
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)

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):
target_doc.qty = -1* source_doc.qty
default_return_warehouse = frappe.db.get_single_value("Stock Settings", "default_return_warehouse")
if doctype == "Purchase Receipt":
target_doc.received_qty = -1* source_doc.received_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.si_detail = source_doc.si_detail
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":
target_doc.sales_order = source_doc.sales_order
target_doc.delivery_note = source_doc.delivery_note

View File

@ -179,7 +179,7 @@ class SellingController(StockController):
last_valuation_rate = frappe.db.sql("""
SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s
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))
if last_valuation_rate:
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):
args['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))
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
from `tabStock Ledger Entry` sle
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):
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":
current_tax_amount = (tax_rate / 100.0) * \
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)

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'}
if(!doc.__islocal && doc.__onload && !doc.__onload.is_customer) {
this.frm.add_custom_button(__("Customer"), this.create_customer, __("Make"));
this.frm.add_custom_button(__("Opportunity"), this.create_opportunity, __("Make"));
this.frm.add_custom_button(__("Quotation"), this.make_quotation, __("Make"));
this.frm.add_custom_button(__("Customer"), this.create_customer, __('Create'));
this.frm.add_custom_button(__("Opportunity"), this.create_opportunity, __('Create'));
this.frm.add_custom_button(__("Quotation"), this.make_quotation, __('Create'));
}
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
// License: GNU General Public License v3. See license.txt
{% include 'erpnext/selling/sales_common.js' %}
frappe.provide("erpnext.crm");
cur_frm.email_field = "contact_email";
@ -47,15 +48,16 @@ frappe.ui.form.on("Opportunity", {
frm.add_custom_button(__('Supplier Quotation'),
function() {
frm.trigger("make_supplier_quotation")
}, __("Make"));
}, __('Create'));
}
frm.add_custom_button(__('Quotation'),
cur_frm.cscript.create_quotation, __("Make"));
cur_frm.cscript.create_quotation, __('Create'));
if(doc.status!=="Quotation") {
frm.add_custom_button(__('Lost'),
cur_frm.cscript['Declare Opportunity Lost']);
frm.add_custom_button(__('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,
"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_in_quick_entry": 0,
@ -1312,6 +1280,38 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.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_in_quick_entry": 0,
@ -1447,6 +1447,39 @@
"translatable": 0,
"unique": 0,
"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,
@ -1460,7 +1493,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-10-01 09:28:43.990999",
"modified": "2018-12-29 18:38:37.270217",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",
@ -1516,5 +1549,5 @@
"title_field": "title",
"track_changes": 0,
"track_seen": 1,
"track_views": 0
"track_views": 1
}

View File

@ -91,10 +91,18 @@ class Opportunity(TransactionBase):
self.enquiry_from = "Lead"
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():
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:
frappe.throw(_("Cannot declare as lost, because Quotation has been made."))

View File

@ -1,5 +1,7 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@ -11,6 +13,8 @@
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -39,9 +43,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -66,9 +73,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -96,9 +106,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -128,9 +141,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -159,9 +175,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -187,9 +206,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -218,9 +240,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -248,9 +273,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -279,10 +307,13 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "300px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -308,9 +339,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -338,9 +372,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -368,9 +405,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -399,20 +439,21 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-02-17 17:03:05.528055",
"modified": "2018-12-28 15:43:09.382012",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity Item",
@ -423,5 +464,6 @@
"read_only_onload": 0,
"show_name_in_global_search": 0,
"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"
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.transaction_date = frappe.flags.current_date
sq.supplier = supplier
@ -79,7 +79,7 @@ def work():
from erpnext.stock.doctype.material_request.material_request import make_purchase_order
report = "Requested Items To Be Ordered"
for row in query_report.run(report)["result"][:how_many("Purchase Order")]:
if row[0] != "'Total'":
if row[0] != "Total":
try:
po = frappe.get_doc(make_purchase_order(row[0]))
po.supplier = supplier

View File

@ -25,7 +25,7 @@ def make_purchase_receipt():
if random.random() < 0.6:
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
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:
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
report = "Ordered Items To Be Delivered"
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.posting_date = frappe.flags.current_date
for d in dn.get("items"):

View File

@ -117,14 +117,14 @@ def generate_fee(fee_schedule):
def get_students(student_group, academic_year, academic_term=None, student_category=None):
conditions = ""
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:
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("""
select pe.student, pe.student_name, pe.program, pe.student_batch_name
from `tabStudent Group Student` sgs, `tabProgram Enrollment` pe
where
where
pe.student = sgs.student and pe.academic_year = %s
and sgs.parent = %s and sgs.active = 1
{conditions}

View File

@ -31,7 +31,7 @@ frappe.ui.form.on('Fee Structure', {
refresh: function(frm) {
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);
});
}

View File

@ -73,14 +73,14 @@ frappe.ui.form.on("Fees", {
if(frm.doc.docstatus===1 && frm.doc.outstanding_amount>0) {
frm.add_custom_button(__("Payment Request"), function() {
frm.events.make_payment_request(frm);
}, __("Make"));
frm.page.set_inner_btn_group_as_primary(__("Make"));
}, __('Create'));
frm.page.set_inner_btn_group_as_primary(__('Create'));
}
if(frm.doc.docstatus===1 && frm.doc.outstanding_amount!=0) {
frm.add_custom_button(__("Payment"), function() {
frm.events.make_payment_entry(frm);
}, __("Make"));
frm.page.set_inner_btn_group_as_primary(__("Make"));
}, __('Create'));
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": "/boms", "to_route": "BOM"},
{"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 = [
@ -152,6 +159,7 @@ standard_portal_menu_items = [
{"title": _("Newsletter"), "route": "/newsletters", "reference_doctype": "Newsletter"},
{"title": _("Admission"), "route": "/admissions", "reference_doctype": "Student Admission"},
{"title": _("Certification"), "route": "/certification", "reference_doctype": "Certification Application"},
{"title": _("Material Request"), "route": "/material-requests", "reference_doctype": "Material Request", "role": "Customer"},
]
default_roles = [
@ -165,6 +173,7 @@ has_website_permission = {
"Quotation": "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",
"Material Request": "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",
"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.accounts.doctype.subscription.subscription.process_all",
"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.collect_project_status"
],
@ -249,7 +259,8 @@ scheduler_events = {
"erpnext.assets.doctype.asset.asset.make_post_gl_entry",
"erpnext.crm.doctype.contract.contract.update_status_for_contracts",
"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": [
"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', {
refresh: function(frm) {
if(frm.doc.docstatus == 1){
frm.add_custom_button(__("Make Invoice"), ()=> {
frm.add_custom_button(__('Create Invoice'), ()=> {
frm.trigger("make_invoice");
});
}

View File

@ -59,15 +59,15 @@ class HotelRoomReservation(Document):
if not d.item:
continue
day_rate = frappe.db.sql("""
select
item.rate
from
select
item.rate
from
`tabHotel Room Pricing Item` item,
`tabHotel Room Pricing` pricing
where
item.parent = pricing.name
and item.item = %s
and %s between pricing.from_date
and %s between pricing.from_date
and pricing.to_date""", (d.item, day))
if day_rate:
@ -90,7 +90,7 @@ def get_room_rate(hotel_room_reservation):
def get_rooms_booked(room_type, day, exclude_reservation=None):
exclude_condition = ''
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("""
select sum(item.qty)
@ -105,5 +105,5 @@ def get_rooms_booked(room_type, day, exclude_reservation=None):
and reservation.docstatus = 1
{exclude_condition}
and %s between reservation.from_date
and reservation.to_date""".format(exclude_condition=exclude_condition),
and reservation.to_date""".format(exclude_condition=exclude_condition),
(room_type, day))[0][0] or 0

View File

@ -13,7 +13,7 @@ from frappe.utils import cstr
class Attendance(Document):
def validate_duplicate_record(self):
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))
if res:
frappe.throw(_("Attendance for employee {0} is already marked").format(self.employee))
@ -89,4 +89,4 @@ def add_attendance(events, start, end, conditions=None):
"docstatus": d.docstatus
}
if e not in events:
events.append(e)
events.append(e)

View File

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

View File

@ -2,7 +2,28 @@
// For license information, please see license.txt
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,150 +15,153 @@
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "default_leave_policy",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Default Leave Policy",
"length": 0,
"no_copy": 0,
"options": "Leave Policy",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "default_leave_policy",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Default Leave Policy",
"length": 0,
"no_copy": 0,
"options": "Leave Policy",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "default_salary_structure",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Default Salary Structure",
"length": 0,
"no_copy": 0,
"options": "Salary Structure",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "default_salary_structure",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Default Salary Structure",
"length": 0,
"no_copy": 0,
"options": "Salary Structure",
"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": 0,
"max_attachments": 0,
"modified": "2018-04-13 16:14:24.174138",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Grade",
"name_case": "",
"owner": "Administrator",
],
"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-09-18 17:17:45.617624",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Grade",
"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,
"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": "HR Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"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": "HR 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": "HR User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"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": "HR User",
"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": 1,
"track_seen": 0
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@ -46,7 +46,7 @@ frappe.ui.form.on('Employee Loan', {
refresh: function (frm) {
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");
})
}

View File

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

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