Merge branch 'hotfix' into copy_payment_schedule_from_quot_to_SO

This commit is contained in:
Nabin Hait
2019-05-02 01:00:04 +05:30
committed by GitHub
60 changed files with 3420 additions and 3015 deletions

View File

@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '11.1.22'
__version__ = '11.1.24'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -12,6 +12,11 @@ frappe.ui.form.on('Bank Account', {
}
};
});
frm.set_query("party_type", function() {
return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
};
});
},
refresh: function(frm) {
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank Account' }

View File

@@ -2,7 +2,7 @@
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "",
"beta": 0,
@@ -975,7 +975,7 @@
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"import": 1,
"permlevel": 0,
"print": 1,
"read": 1,

View File

@@ -2,7 +2,7 @@
// For license information, please see license.txt
frappe.ui.form.on('Bank Transaction', {
onload: function(frm) {
onload(frm) {
frm.set_query('payment_document', 'payment_entries', function() {
return {
"filters": {
@@ -12,3 +12,21 @@ frappe.ui.form.on('Bank Transaction', {
});
}
});
frappe.ui.form.on('Bank Transaction Payments', {
payment_entries_remove: function(frm, cdt, cdn) {
update_clearance_date(frm, cdt, cdn);
}
});
const update_clearance_date = (frm, cdt, cdn) => {
if (frm.doc.docstatus === 1) {
frappe.xcall('erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment',
{doctype: cdt, docname: cdn})
.then(e => {
if (e == "success") {
frappe.show_alert({message:__("Document {0} successfully uncleared", [e]), indicator:'green'});
}
});
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,32 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from erpnext.controllers.status_updater import StatusUpdater
from frappe.utils import flt
from six.moves import reduce
from frappe import _
class BankTransaction(Document):
class BankTransaction(StatusUpdater):
def after_insert(self):
self.unallocated_amount = abs(flt(self.credit) - flt(self.debit))
def on_submit(self):
self.clear_linked_payment_entries()
self.set_status()
def on_update_after_submit(self):
allocated_amount = reduce(lambda x, y: flt(x) + flt(y), [x.allocated_amount for x in self.payment_entries])
self.update_allocations()
self.clear_linked_payment_entries()
self.set_status(update=True)
def update_allocations(self):
if self.payment_entries:
allocated_amount = reduce(lambda x, y: flt(x) + flt(y), [x.allocated_amount for x in self.payment_entries])
else:
allocated_amount = 0
if allocated_amount:
frappe.db.set_value(self.doctype, self.name, "allocated_amount", flt(allocated_amount))
@@ -23,4 +36,67 @@ class BankTransaction(Document):
frappe.db.set_value(self.doctype, self.name, "allocated_amount", 0)
frappe.db.set_value(self.doctype, self.name, "unallocated_amount", abs(flt(self.credit) - flt(self.debit)))
self.reload()
self.reload()
def clear_linked_payment_entries(self):
for payment_entry in self.payment_entries:
allocated_amount = get_total_allocated_amount(payment_entry)
paid_amount = get_paid_amount(payment_entry)
if paid_amount and allocated_amount:
if flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount):
frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).".format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount))))
elif flt(allocated_amount[0]["allocated_amount"]) == flt(paid_amount):
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
self.clear_simple_entry(payment_entry)
elif payment_entry.payment_document == "Sales Invoice":
self.clear_sales_invoice(payment_entry)
def clear_simple_entry(self, payment_entry):
frappe.db.set_value(payment_entry.payment_document, payment_entry.payment_entry, "clearance_date", self.date)
def clear_sales_invoice(self, payment_entry):
frappe.db.set_value("Sales Invoice Payment", dict(parenttype=payment_entry.payment_document,
parent=payment_entry.payment_entry), "clearance_date", self.date)
def get_total_allocated_amount(payment_entry):
return frappe.db.sql("""
SELECT
SUM(btp.allocated_amount) as allocated_amount,
bt.name
FROM
`tabBank Transaction Payments` as btp
LEFT JOIN
`tabBank Transaction` bt ON bt.name=btp.parent
WHERE
btp.payment_document = %s
AND
btp.payment_entry = %s
AND
bt.docstatus = 1""", (payment_entry.payment_document, payment_entry.payment_entry), as_dict=True)
def get_paid_amount(payment_entry):
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "paid_amount")
elif payment_entry.payment_document == "Journal Entry":
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_credit")
elif payment_entry.payment_document == "Expense Claim":
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_amount_reimbursed")
else:
frappe.throw("Please reconcile {0}: {1} manually".format(payment_entry.payment_document, payment_entry.payment_entry))
@frappe.whitelist()
def unclear_reference_payment(doctype, docname):
if frappe.db.exists(doctype, docname):
doc = frappe.get_doc(doctype, docname)
if doctype == "Sales Invoice":
frappe.db.set_value("Sales Invoice Payment", dict(parenttype=doc.payment_document,
parent=doc.payment_entry), "clearance_date", None)
else:
frappe.db.set_value(doc.payment_document, doc.payment_entry, "clearance_date", None)
return doc.payment_entry

View File

@@ -6,7 +6,7 @@ frappe.listview_settings['Bank Transaction'] = {
get_indicator: function(doc) {
if(flt(doc.unallocated_amount)>0) {
return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
} else if(flt(doc.unallocated_amount)===0) {
} else if(flt(doc.unallocated_amount)<=0) {
return [__("Reconciled"), "green", "unallocated_amount,=,0"];
}
}

View File

@@ -36,7 +36,8 @@ def upload_bank_statement():
def create_bank_entries(columns, data, bank_account):
header_map = get_header_mapping(columns, bank_account)
count = 0
success = 0
errors = 0
for d in json.loads(data):
if all(item is None for item in d) is True:
continue
@@ -44,7 +45,6 @@ def create_bank_entries(columns, data, bank_account):
for key, value in iteritems(header_map):
fields.update({key: d[int(value)-1]})
try:
bank_transaction = frappe.get_doc({
"doctype": "Bank Transaction"
@@ -54,12 +54,12 @@ def create_bank_entries(columns, data, bank_account):
bank_transaction.bank_account = bank_account
bank_transaction.insert()
bank_transaction.submit()
count = count + 1
except Exception as e:
frappe.throw(e)
success += 1
except Exception:
frappe.log_error(frappe.get_traceback())
errors += 1
return count
return {"success": success, "errors": errors}
def get_header_mapping(columns, bank_account):
mapping = get_bank_mapping(bank_account)

View File

@@ -160,7 +160,7 @@ class PaymentEntry(AccountsController):
d.reference_name, self.party_account_currency)
for field, value in iteritems(ref_details):
if not d.get(field) or force:
if field == 'exchange_rate' or not d.get(field) or force:
d.set(field, value)
def validate_payment_type(self):

View File

@@ -191,7 +191,7 @@ erpnext.accounts.bankTransactionUpload = class bankTransactionUpload {
frappe.xcall('erpnext.accounts.doctype.bank_transaction.bank_transaction_upload.create_bank_entries',
{columns: this.datatable.datamanager.columns, data: this.datatable.datamanager.data, bank_account: me.parent.bank_account}
).then((result) => {
let result_title = __("{0} bank transaction(s) created", [result])
let result_title = result.errors == 0 ? __("{0} bank transaction(s) created", [result.success]) : __("{0} bank transaction(s) created and {1} errors", [result.success, result.errors])
let result_msg = `
<div class="flex justify-center align-center text-muted" style="height: 50vh; display: flex;">
<h5 class="text-muted">${result_title}</h5>
@@ -199,7 +199,11 @@ erpnext.accounts.bankTransactionUpload = class bankTransactionUpload {
me.parent.page.clear_primary_action();
me.parent.$main_section.empty();
me.parent.$main_section.append(result_msg);
frappe.show_alert({message:__("All bank transactions have been created"), indicator:'green'});
if (result.errors == 0) {
frappe.show_alert({message:__("All bank transactions have been created"), indicator:'green'});
} else {
frappe.show_alert({message:__("Please check the error log for details about the import errors"), indicator:'red'});
}
})
}
}
@@ -530,11 +534,13 @@ erpnext.accounts.ReconciliationRow = class ReconciliationRow {
.then(doc => {
let displayed_docs = []
if (dt === "Payment Entry") {
doc.currency = doc.payment_type == "Receive" ? doc.paid_to_account_currency : doc.paid_from_account_currency;
displayed_docs.push(doc);
payment.currency = doc.payment_type == "Receive" ? doc.paid_to_account_currency : doc.paid_from_account_currency;
payment.doctype = dt
displayed_docs.push(payment);
} else if (dt === "Journal Entry") {
doc.accounts.forEach(payment => {
if (payment.account === me.gl_account) {
payment.doctype = dt;
payment.posting_date = doc.posting_date;
payment.party = doc.pay_to_recd_from;
payment.reference_no = doc.cheque_no;
@@ -548,6 +554,7 @@ erpnext.accounts.ReconciliationRow = class ReconciliationRow {
} else if (dt === "Sales Invoice") {
doc.payments.forEach(payment => {
if (payment.clearance_date === null || payment.clearance_date === "") {
payment.doctype = dt;
payment.posting_date = doc.posting_date;
payment.party = doc.customer;
payment.reference_no = doc.remarks;

View File

@@ -28,7 +28,6 @@ def reconcile(bank_transaction, payment_doctype, payment_name):
frappe.throw(_("The selected payment entry should be linked with a creditor bank transaction"))
add_payment_to_transaction(transaction, payment_entry, gl_entry)
clear_payment_entry(transaction, payment_entry, gl_entry)
return 'reconciled'
@@ -42,40 +41,6 @@ def add_payment_to_transaction(transaction, payment_entry, gl_entry):
})
transaction.save()
def clear_payment_entry(transaction, payment_entry, gl_entry):
linked_bank_transactions = frappe.db.sql("""
SELECT
bt.credit, bt.debit
FROM
`tabBank Transaction Payments` as btp
LEFT JOIN
`tabBank Transaction` as bt on btp.parent=bt.name
WHERE
btp.payment_document = %s
AND
btp.payment_entry = %s
AND
bt.docstatus = 1
""", (payment_entry.doctype, payment_entry.name), as_dict=True)
amount_cleared = (flt(linked_bank_transactions[0].credit) - flt(linked_bank_transactions[0].debit))
amount_to_be_cleared = (flt(gl_entry.debit) - flt(gl_entry.credit))
if payment_entry.doctype in ("Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"):
clear_simple_entry(amount_cleared, amount_to_be_cleared, payment_entry, transaction)
elif payment_entry.doctype == "Sales Invoice":
clear_sales_invoice(amount_cleared, amount_to_be_cleared, payment_entry, transaction)
def clear_simple_entry(amount_cleared, amount_to_be_cleared, payment_entry, transaction):
if amount_cleared >= amount_to_be_cleared:
frappe.db.set_value(payment_entry.doctype, payment_entry.name, "clearance_date", transaction.date)
def clear_sales_invoice(amount_cleared, amount_to_be_cleared, payment_entry, transaction):
if amount_cleared >= amount_to_be_cleared:
frappe.db.set_value("Sales Invoice Payment", dict(parenttype=payment_entry.doctype,
parent=payment_entry.name), "clearance_date", transaction.date)
@frappe.whitelist()
def get_linked_payments(bank_transaction):
transaction = frappe.get_doc("Bank Transaction", bank_transaction)
@@ -250,7 +215,7 @@ def get_matching_descriptions_data(company, transaction):
if key == "Payment Entry":
data.extend(frappe.get_all("Payment Entry", filters=[["name", "in", value]], fields=["'Payment Entry' as doctype", "posting_date", "party", "reference_no", "reference_date", "paid_amount", "paid_to_account_currency as currency"]))
if key == "Journal Entry":
journal_entries = frappe.get_all("Journal Entry", filters=[["name", "in", value]], fields=["name", "'Journal Entry' as doctype", "posting_date", "paid_to_recd_from as party", "cheque_no as reference_no", "cheque_date as reference_date", "total_credit as paid_amount"])
journal_entries = frappe.get_all("Journal Entry", filters=[["name", "in", value]], fields=["name", "'Journal Entry' as doctype", "posting_date", "pay_to_recd_from as party", "cheque_no as reference_no", "cheque_date as reference_date", "total_credit as paid_amount"])
for journal_entry in journal_entries:
journal_entry_accounts = frappe.get_all("Journal Entry Account", filters={"parenttype": journal_entry["doctype"], "parent": journal_entry["name"]}, fields=["account_currency"])
journal_entry["currency"] = journal_entry_accounts[0]["account_currency"] if journal_entry_accounts else company_currency

View File

@@ -2,7 +2,7 @@
// For license information, please see license.txt
/* eslint-disable */
frappe.query_reports["Inactive Items"] = {
frappe.query_reports["Inactive Sales Items"] = {
"filters": [
{
fieldname: "item",

View File

@@ -1,21 +1,20 @@
{
"add_total_row": 0,
"creation": "2019-04-16 16:05:00.647308",
"creation": "2019-05-01 12:59:52.018850",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"letter_head": "Test Letter Head 1",
"modified": "2019-04-16 16:06:33.630043",
"modified": "2019-05-01 13:00:26.545278",
"modified_by": "Administrator",
"module": "Stock",
"name": "Inactive Items",
"module": "Accounts",
"name": "Inactive Sales Items",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Sales Invoice",
"report_name": "Inactive Items",
"report_name": "Inactive Sales Items",
"report_type": "Script Report",
"roles": [
{

View File

@@ -145,4 +145,3 @@ def get_items(filters):
items = frappe.get_all("Item", fields=["name", "item_group", "item_name"], filters=filters_dict, order_by="name")
return items

View File

@@ -95,6 +95,10 @@ status_map = {
["Ordered", "eval:self.status != 'Stopped' and self.per_ordered == 100 and self.docstatus == 1 and self.material_request_type == 'Purchase'"],
["Transferred", "eval:self.status != 'Stopped' and self.per_ordered == 100 and self.docstatus == 1 and self.material_request_type == 'Material Transfer'"],
["Issued", "eval:self.status != 'Stopped' and self.per_ordered == 100 and self.docstatus == 1 and self.material_request_type == 'Material Issue'"]
],
"Bank Transaction": [
["Unreconciled", "eval:self.docstatus == 1 and self.unallocated_amount>0"],
["Reconciled", "eval:self.docstatus == 1 and self.unallocated_amount<=0"]
]
}

View File

@@ -90,11 +90,11 @@ class Lead(SellingController):
return frappe.db.get_value("Customer", {"lead_name": self.name})
def has_opportunity(self):
return frappe.db.get_value("Opportunity", {"lead": self.name, "status": ["!=", "Lost"]})
return frappe.db.get_value("Opportunity", {"party_name": self.name, "status": ["!=", "Lost"]})
def has_quotation(self):
return frappe.db.get_value("Quotation", {
"lead": self.name,
"party_name": self.name,
"docstatus": 1,
"status": ["!=", "Lost"]

View File

@@ -9,15 +9,22 @@ frappe.ui.form.on("Opportunity", {
frm.custom_make_buttons = {
'Quotation': 'Quotation',
'Supplier Quotation': 'Supplier Quotation'
}
},
customer: function(frm) {
frm.trigger('set_contact_link');
erpnext.utils.get_party_details(frm);
},
frm.set_query("opportunity_from", function() {
return{
"filters": {
"name": ["in", ["Customer", "Lead"]],
}
}
});
},
lead: function(frm) {
frm.trigger('set_contact_link');
party_name: function(frm) {
if (frm.doc.opportunity_from == "Customer") {
frm.trigger('set_contact_link');
erpnext.utils.get_party_details(frm);
}
},
with_items: function(frm) {
@@ -30,15 +37,14 @@ frappe.ui.form.on("Opportunity", {
contact_person: erpnext.utils.get_contact_details,
enquiry_from: function(frm) {
frm.toggle_reqd("lead", frm.doc.enquiry_from==="Lead");
frm.toggle_reqd("customer", frm.doc.enquiry_from==="Customer");
opportunity_from: function(frm) {
frm.toggle_reqd("party_name", frm.doc.opportunity_from);
frm.trigger("set_dynamic_field_label");
},
refresh: function(frm) {
var doc = frm.doc;
frm.events.enquiry_from(frm);
frm.trigger('set_contact_link');
frm.events.opportunity_from(frm);
frm.trigger('toggle_mandatory');
erpnext.toggle_naming_series();
@@ -75,13 +81,20 @@ frappe.ui.form.on("Opportunity", {
},
set_contact_link: function(frm) {
if(frm.doc.customer) {
if(frm.doc.opportunity_from == "Customer" && frm.doc.party_name) {
frappe.dynamic_link = {doc: frm.doc, fieldname: 'customer', doctype: 'Customer'}
} else if(frm.doc.lead) {
} else if(frm.doc.opportunity_from == "Lead" && frm.doc.party_name) {
frappe.dynamic_link = {doc: frm.doc, fieldname: 'lead', doctype: 'Lead'}
}
},
set_dynamic_field_label: function(frm){
if (frm.doc.opportunity_from) {
frm.set_df_property("party_name", "label", frm.doc.opportunity_from);
}
},
make_supplier_quotation: function(frm) {
frappe.model.open_mapped_doc({
method: "erpnext.crm.doctype.opportunity.opportunity.make_supplier_quotation",
@@ -97,10 +110,6 @@ frappe.ui.form.on("Opportunity", {
// TODO commonify this code
erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
onload: function() {
if(!this.frm.doc.enquiry_from && this.frm.doc.customer)
this.frm.doc.enquiry_from = "Customer";
if(!this.frm.doc.enquiry_from && this.frm.doc.lead)
this.frm.doc.enquiry_from = "Lead";
if(!this.frm.doc.status)
set_multiple(this.frm.doc.doctype, this.frm.doc.name, { status:'Open' });
@@ -148,7 +157,7 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
$.extend(cur_frm.cscript, new erpnext.crm.Opportunity({frm: cur_frm}));
cur_frm.cscript.onload_post_render = function(doc, cdt, cdn) {
if(doc.enquiry_from == 'Lead' && doc.lead)
if(doc.opportunity_from == 'Lead' && doc.party_name)
cur_frm.cscript.lead(doc, cdt, cdn);
}
@@ -171,10 +180,10 @@ cur_frm.cscript.item_code = function(doc, cdt, cdn) {
}
cur_frm.cscript.lead = function(doc, cdt, cdn) {
cur_frm.toggle_display("contact_info", doc.customer || doc.lead);
cur_frm.toggle_display("contact_info", doc.party_name);
erpnext.utils.map_current_doc({
method: "erpnext.crm.doctype.lead.lead.make_opportunity",
source_name: cur_frm.doc.lead,
source_name: cur_frm.doc.party_name,
frm: cur_frm
});
}

View File

@@ -21,6 +21,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "from_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -54,6 +55,7 @@
"collapsible": 0,
"columns": 0,
"default": "",
"fetch_if_empty": 0,
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
@@ -88,8 +90,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "enquiry_from",
"fieldtype": "Select",
"fetch_if_empty": 0,
"fieldname": "opportunity_from",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -102,7 +105,7 @@
"no_copy": 0,
"oldfieldname": "enquiry_from",
"oldfieldtype": "Select",
"options": "\nLead\nCustomer",
"options": "DocType",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
@@ -122,9 +125,10 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.enquiry_from===\"Customer\"",
"fieldname": "customer",
"fieldtype": "Link",
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "party_name",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -132,54 +136,19 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Customer",
"label": "Customer/Lead",
"length": 0,
"no_copy": 0,
"oldfieldname": "customer",
"oldfieldtype": "Link",
"options": "Customer",
"options": "opportunity_from",
"permlevel": 0,
"print_hide": 1,
"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_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.enquiry_from===\"Lead\"",
"fieldname": "lead",
"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": 1,
"label": "Lead",
"length": 0,
"no_copy": 0,
"oldfieldname": "lead",
"oldfieldtype": "Link",
"options": "Lead",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
@@ -193,6 +162,8 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_from": "",
"fetch_if_empty": 0,
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 0,
@@ -224,6 +195,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break0",
"fieldtype": "Column Break",
"hidden": 0,
@@ -256,6 +228,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 1,
@@ -289,6 +262,7 @@
"collapsible": 0,
"columns": 0,
"default": "Sales",
"fetch_if_empty": 0,
"fieldname": "opportunity_type",
"fieldtype": "Link",
"hidden": 0,
@@ -324,6 +298,7 @@
"collapsible": 0,
"columns": 0,
"default": "Open",
"fetch_if_empty": 0,
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
@@ -359,6 +334,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.status===\"Lost\"",
"fetch_if_empty": 0,
"fieldname": "order_lost_reason",
"fieldtype": "Small Text",
"hidden": 0,
@@ -390,6 +366,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "mins_to_first_response",
"fieldtype": "Float",
"hidden": 0,
@@ -423,6 +400,7 @@
"collapsible": 1,
"collapsible_depends_on": "contact_by",
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "next_contact",
"fieldtype": "Section Break",
"hidden": 0,
@@ -456,6 +434,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "contact_by",
"fieldtype": "Link",
"hidden": 0,
@@ -492,6 +471,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "contact_date",
"fieldtype": "Datetime",
"hidden": 0,
@@ -525,6 +505,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break2",
"fieldtype": "Column Break",
"hidden": 0,
@@ -557,6 +538,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "to_discuss",
"fieldtype": "Small Text",
"hidden": 0,
@@ -590,6 +572,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_14",
"fieldtype": "Section Break",
"hidden": 0,
@@ -622,6 +605,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "currency",
"fieldtype": "Link",
"hidden": 0,
@@ -655,6 +639,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "opportunity_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -687,6 +672,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "with_items",
"fieldtype": "Check",
"hidden": 0,
@@ -719,6 +705,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_17",
"fieldtype": "Column Break",
"hidden": 0,
@@ -751,6 +738,7 @@
"collapsible": 0,
"columns": 0,
"default": "Prospecting",
"fetch_if_empty": 0,
"fieldname": "sales_stage",
"fieldtype": "Link",
"hidden": 0,
@@ -785,6 +773,7 @@
"collapsible": 0,
"columns": 0,
"default": "100",
"fetch_if_empty": 0,
"fieldname": "probability",
"fieldtype": "Percent",
"hidden": 0,
@@ -818,6 +807,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "with_items",
"fetch_if_empty": 0,
"fieldname": "items_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -852,6 +842,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "items",
"fieldtype": "Table",
"hidden": 0,
@@ -888,6 +879,7 @@
"collapsible_depends_on": "next_contact_by",
"columns": 0,
"depends_on": "eval:doc.lead || doc.customer",
"fetch_if_empty": 0,
"fieldname": "contact_info",
"fieldtype": "Section Break",
"hidden": 0,
@@ -921,6 +913,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.customer || doc.lead",
"fetch_if_empty": 0,
"fieldname": "customer_address",
"fieldtype": "Link",
"hidden": 0,
@@ -953,6 +946,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "address_display",
"fieldtype": "Small Text",
"hidden": 1,
@@ -988,6 +982,7 @@
"columns": 0,
"depends_on": "customer",
"description": "",
"fetch_if_empty": 0,
"fieldname": "territory",
"fieldtype": "Link",
"hidden": 0,
@@ -1022,6 +1017,7 @@
"columns": 0,
"depends_on": "customer",
"description": "",
"fetch_if_empty": 0,
"fieldname": "customer_group",
"fieldtype": "Link",
"hidden": 0,
@@ -1056,6 +1052,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break3",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1087,6 +1084,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.lead || doc.customer",
"fetch_if_empty": 0,
"fieldname": "contact_person",
"fieldtype": "Link",
"hidden": 0,
@@ -1120,6 +1118,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "customer",
"fetch_if_empty": 0,
"fieldname": "contact_display",
"fieldtype": "Small Text",
"hidden": 0,
@@ -1152,6 +1151,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.lead || doc.customer",
"fetch_if_empty": 0,
"fieldname": "contact_email",
"fieldtype": "Data",
"hidden": 0,
@@ -1184,6 +1184,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.lead || doc.customer",
"fetch_if_empty": 0,
"fieldname": "contact_mobile",
"fieldtype": "Small Text",
"hidden": 0,
@@ -1216,6 +1217,7 @@
"collapsible": 1,
"collapsible_depends_on": "",
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "more_info",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1249,6 +1251,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "source",
"fieldtype": "Link",
"hidden": 0,
@@ -1285,6 +1288,7 @@
"columns": 0,
"depends_on": "eval: doc.source==\"Campaign\"",
"description": "Enter name of campaign if source of enquiry is campaign",
"fetch_if_empty": 0,
"fieldname": "campaign",
"fieldtype": "Link",
"hidden": 0,
@@ -1319,6 +1323,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1351,6 +1356,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -1386,6 +1392,7 @@
"collapsible": 0,
"columns": 0,
"default": "Today",
"fetch_if_empty": 0,
"fieldname": "transaction_date",
"fieldtype": "Date",
"hidden": 0,
@@ -1420,6 +1427,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -1460,7 +1468,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-10-01 09:28:43.990999",
"modified": "2019-04-25 18:55:43.874656",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",
@@ -1508,11 +1516,11 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "status,transaction_date,customer,lead,opportunity_type,territory,company",
"search_fields": "status,transaction_date,party_name,opportunity_type,territory,company",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "customer",
"timeline_field": "party_name",
"title_field": "title",
"track_changes": 0,
"track_seen": 1,

View File

@@ -16,8 +16,8 @@ sender_field = "contact_email"
class Opportunity(TransactionBase):
def after_insert(self):
if self.lead:
frappe.get_doc("Lead", self.lead).set_status(update=True)
if self.opportunity_from == "Lead":
frappe.get_doc("Lead", self.party_name).set_status(update=True)
def validate(self):
self._prev = frappe._dict({
@@ -29,12 +29,8 @@ class Opportunity(TransactionBase):
self.make_new_lead_if_required()
if not self.enquiry_from:
frappe.throw(_("Opportunity From field is mandatory"))
self.validate_item_details()
self.validate_uom_is_integer("uom", "qty")
self.validate_lead_cust()
self.validate_cust_name()
if not self.title:
@@ -45,7 +41,7 @@ class Opportunity(TransactionBase):
def make_new_lead_if_required(self):
"""Set lead against new opportunity"""
if not (self.lead or self.customer) and self.contact_email:
if (not self.get("party_name")) and self.contact_email:
# check if customer is already created agains the self.contact_email
customer = frappe.db.sql("""select
distinct `tabDynamic Link`.link_name as customer
@@ -61,8 +57,8 @@ class Opportunity(TransactionBase):
`tabDynamic Link`.link_doctype='Customer'
""".format(self.contact_email), as_dict=True)
if customer and customer[0].customer:
self.customer = customer[0].customer
self.enquiry_from = "Customer"
self.party_name = customer[0].customer
self.opportunity_from = "Customer"
return
lead_name = frappe.db.get_value("Lead", {"email_id": self.contact_email})
@@ -89,8 +85,8 @@ class Opportunity(TransactionBase):
lead.insert(ignore_permissions=True)
lead_name = lead.name
self.enquiry_from = "Lead"
self.lead = lead_name
self.opportunity_from = "Lead"
self.party_name = lead_name
def declare_enquiry_lost(self,arg):
if not self.has_active_quotation():
@@ -137,10 +133,10 @@ class Opportunity(TransactionBase):
return True
def validate_cust_name(self):
if self.customer:
self.customer_name = frappe.db.get_value("Customer", self.customer, "customer_name")
elif self.lead:
lead_name, company_name = frappe.db.get_value("Lead", self.lead, ["lead_name", "company_name"])
if self.party_name and self.opportunity_from == 'Customer':
self.customer_name = frappe.db.get_value("Customer", self.party_name, "customer_name")
elif self.party_name and self.opportunity_from == 'Lead':
lead_name, company_name = frappe.db.get_value("Lead", self.party_name, ["lead_name", "company_name"])
self.customer_name = company_name or lead_name
def on_update(self):
@@ -153,16 +149,16 @@ class Opportunity(TransactionBase):
opts.description = ""
opts.contact_date = self.contact_date
if self.customer:
if self.party_name and self.opportunity_from == 'Customer':
if self.contact_person:
opts.description = 'Contact '+cstr(self.contact_person)
else:
opts.description = 'Contact customer '+cstr(self.customer)
elif self.lead:
opts.description = 'Contact customer '+cstr(self.party_name)
elif self.party_name and self.opportunity_from == 'Lead':
if self.contact_display:
opts.description = 'Contact '+cstr(self.contact_display)
else:
opts.description = 'Contact lead '+cstr(self.lead)
opts.description = 'Contact lead '+cstr(self.party_name)
opts.subject = opts.description
opts.description += '. By : ' + cstr(self.contact_by)
@@ -187,17 +183,6 @@ class Opportunity(TransactionBase):
for key in item_fields:
if not d.get(key): d.set(key, item.get(key))
def validate_lead_cust(self):
if self.enquiry_from == 'Lead':
if not self.lead:
frappe.throw(_("Lead must be set if Opportunity is made from Lead"))
else:
self.customer = None
elif self.enquiry_from == 'Customer':
if not self.customer:
msgprint(_("Customer is mandatory if 'Opportunity From' is selected as Customer"), raise_exception=1)
else:
self.lead = None
@frappe.whitelist()
def get_item_details(item_code):
@@ -219,8 +204,11 @@ def make_quotation(source_name, target_doc=None):
quotation = frappe.get_doc(target)
company_currency = frappe.get_cached_value('Company', quotation.company, "default_currency")
party_account_currency = get_party_account_currency("Customer", quotation.customer,
quotation.company) if quotation.customer else company_currency
if quotation.quotation_to == 'Customer' and quotation.party_name:
party_account_currency = get_party_account_currency("Customer", quotation.party_name, quotation.company)
else:
party_account_currency = company_currency
quotation.currency = party_account_currency or company_currency
@@ -246,7 +234,7 @@ def make_quotation(source_name, target_doc=None):
"Opportunity": {
"doctype": "Quotation",
"field_map": {
"enquiry_from": "quotation_to",
"opportunity_from": "quotation_to",
"opportunity_type": "order_type",
"name": "enq_no",
}

View File

@@ -1,5 +1,5 @@
frappe.listview_settings['Opportunity'] = {
add_fields: ["customer_name", "opportunity_type", "enquiry_from", "status"],
add_fields: ["customer_name", "opportunity_type", "opportunity_from", "status"],
get_indicator: function(doc) {
var indicator = [__(doc.status), frappe.utils.guess_colour(doc.status), "status,=," + doc.status];
if(doc.status=="Quotation") {

View File

@@ -6,7 +6,7 @@ QUnit.test("test: opportunity", function (assert) {
() => frappe.timeout(1),
() => frappe.click_button('New'),
() => frappe.timeout(1),
() => cur_frm.set_value('enquiry_from', 'Customer'),
() => cur_frm.set_value('opportunity_from', 'Customer'),
() => cur_frm.set_value('customer', 'Test Customer 1'),
// check items

View File

@@ -37,13 +37,13 @@ class TestOpportunity(unittest.TestCase):
# new lead should be created against the new.opportunity@example.com
opp_doc = frappe.get_doc(args).insert(ignore_permissions=True)
self.assertTrue(opp_doc.lead)
self.assertEqual(opp_doc.enquiry_from, "Lead")
self.assertEqual(frappe.db.get_value("Lead", opp_doc.lead, "email_id"),
self.assertTrue(opp_doc.party_name)
self.assertEqual(opp_doc.opportunity_from, "Lead")
self.assertEqual(frappe.db.get_value("Lead", opp_doc.party_name, "email_id"),
'new.opportunity@example.com')
# create new customer and create new contact against 'new.opportunity@example.com'
customer = make_customer(opp_doc.lead).insert(ignore_permissions=True)
customer = make_customer(opp_doc.party_name).insert(ignore_permissions=True)
frappe.get_doc({
"doctype": "Contact",
"email_id": "new.opportunity@example.com",
@@ -55,9 +55,9 @@ class TestOpportunity(unittest.TestCase):
}).insert(ignore_permissions=True)
opp_doc = frappe.get_doc(args).insert(ignore_permissions=True)
self.assertTrue(opp_doc.customer)
self.assertEqual(opp_doc.enquiry_from, "Customer")
self.assertEqual(opp_doc.customer, customer.name)
self.assertTrue(opp_doc.party_name)
self.assertEqual(opp_doc.opportunity_from, "Customer")
self.assertEqual(opp_doc.party_name, customer.name)
def make_opportunity(**args):
args = frappe._dict(args)
@@ -65,17 +65,17 @@ def make_opportunity(**args):
opp_doc = frappe.get_doc({
"doctype": "Opportunity",
"company": args.company or "_Test Company",
"enquiry_from": args.enquiry_from or "Customer",
"opportunity_from": args.opportunity_from or "Customer",
"opportunity_type": "Sales",
"with_items": args.with_items or 0,
"transaction_date": today()
})
if opp_doc.enquiry_from == 'Customer':
opp_doc.customer = args.customer or "_Test Customer"
if opp_doc.opportunity_from == 'Customer':
opp_doc.party_name= args.customer or "_Test Customer"
if opp_doc.enquiry_from == 'Lead':
opp_doc.customer = args.lead or "_T-Lead-00001"
if opp_doc.opportunity_from == 'Lead':
opp_doc.party_name = args.lead or "_T-Lead-00001"
if args.with_items:
opp_doc.append('items', {

View File

@@ -2,9 +2,9 @@
{
"doctype": "Opportunity",
"name": "_Test Opportunity 1",
"enquiry_from": "Lead",
"opportunity_from": "Lead",
"enquiry_type": "Sales",
"lead": "_T-Lead-00001",
"party_name": "_T-Lead-00001",
"transaction_date": "2013-12-12",
"items": [{
"item_name": "Test Item",

View File

@@ -66,7 +66,7 @@ def get_columns():
def get_communication_details(filters):
communication_count = None
communication_list = []
opportunities = frappe.db.get_values('Opportunity', {'enquiry_from': 'Lead'},\
opportunities = frappe.db.get_values('Opportunity', {'opportunity_from': 'Lead'},\
['name', 'customer_name', 'lead', 'contact_email'], as_dict=1)
for d in opportunities:

View File

@@ -56,7 +56,7 @@ def work(domain="Manufacturing"):
def make_opportunity(domain):
b = frappe.get_doc({
"doctype": "Opportunity",
"enquiry_from": "Customer",
"opportunity_from": "Customer",
"customer": get_random("Customer"),
"opportunity_type": "Sales",
"with_items": 1,

View File

@@ -186,7 +186,7 @@ def link_item(item_data,item_status):
item.item_name = str(item_data.get("name"))
item.item_code = "woocommerce - " + str(item_data.get("product_id"))
item.woocommerce_id = str(item_data.get("product_id"))
item.item_group = "WooCommerce Products"
item.item_group = _("WooCommerce Products")
item.stock_uom = woocommerce_settings.uom or _("Nos")
item.save()
frappe.db.commit()

View File

@@ -4,8 +4,8 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils.nestedset import get_root_of
from frappe.model.document import Document
from six.moves.urllib.parse import urlparse
@@ -62,10 +62,10 @@ class WoocommerceSettings(Document):
custom.read_only = 1
custom.save()
if not frappe.get_value("Item Group",{"name": "WooCommerce Products"}):
if not frappe.get_value("Item Group",{"name": _("WooCommerce Products")}):
item_group = frappe.new_doc("Item Group")
item_group.item_group_name = "WooCommerce Products"
item_group.parent_item_group = _("All Item Groups")
item_group.item_group_name = _("WooCommerce Products")
item_group.parent_item_group = get_root_of("Item Group")
item_group.save()
@@ -83,7 +83,7 @@ class WoocommerceSettings(Document):
for name in email_names:
frappe.delete_doc("Custom Field",name)
frappe.delete_doc("Item Group","WooCommerce Products")
frappe.delete_doc("Item Group", _("WooCommerce Products"))
frappe.db.commit()

View File

@@ -256,7 +256,7 @@ scheduler_events = {
"daily_long": [
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"
],
"monthly": [
"monthly_long": [
"erpnext.accounts.deferred_revenue.convert_deferred_revenue_to_income",
"erpnext.accounts.deferred_revenue.convert_deferred_expense_to_expense",
"erpnext.hr.utils.allocate_earned_leaves"

View File

@@ -78,7 +78,7 @@ class Employee(NestedSet):
def update_user_permissions(self):
if not self.create_user_permission: return
if not has_permission('User Permission', ptype='write'): return
if not has_permission('User Permission', ptype='write', raise_exception=False): return
employee_user_permission_exists = frappe.db.exists('User Permission', {
'allow': 'Employee',
@@ -237,7 +237,7 @@ def validate_employee_role(doc, method):
def update_user_permissions(doc, method):
# called via User hook
if "Employee" in [d.role for d in doc.get("roles")]:
if not has_permission('User Permission', ptype='write'): return
if not has_permission('User Permission', ptype='write', raise_exception=False): return
employee = frappe.get_doc("Employee", {"user_id": doc.name})
employee.update_user_permissions()

View File

@@ -177,9 +177,12 @@ def get_benefit_component_amount(employee, start_date, end_date, struct_row, sal
# Considering there is only one application for a year
benefit_application_name = frappe.db.sql("""
select name from `tabEmployee Benefit Application`
where payroll_period=%(payroll_period)s and employee=%(employee)s
and docstatus = 1
select name
from `tabEmployee Benefit Application`
where
payroll_period=%(payroll_period)s
and employee=%(employee)s
and docstatus = 1
""", {
'employee': employee,
'payroll_period': payroll_period
@@ -209,7 +212,8 @@ def get_benefit_pro_rata_ratio_amount(sal_struct, component_max):
total_pro_rata_max = 0
benefit_amount = 0
for sal_struct_row in sal_struct.get("earnings"):
pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component",
sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1:
total_pro_rata_max += max_benefit_amount
if total_pro_rata_max > 0:

View File

@@ -1,179 +1,179 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2018-04-13 16:56:23.333041",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2018-04-13 16:56:23.333041",
"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,
"fetch_if_empty": 0,
"fieldname": "exemption_sub_category",
"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": "Exemption Sub Category",
"length": 0,
"no_copy": 0,
"options": "Employee Tax Exemption Sub Category",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"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,
"fetch_if_empty": 0,
"fieldname": "exemption_sub_category",
"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": "Exemption Sub Category",
"length": 0,
"no_copy": 0,
"options": "Employee Tax Exemption Sub Category",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"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,
"columns": 0,
"fetch_from": "exemption_sub_category.exemption_category",
"fetch_if_empty": 0,
"fieldname": "exemption_category",
"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": "Exemption Category",
"length": 0,
"no_copy": 0,
"options": "Employee Tax Exemption Category",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"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,
"fetch_from": "exemption_sub_category.exemption_category",
"fetch_if_empty": 0,
"fieldname": "exemption_category",
"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": "Exemption Category",
"length": 0,
"no_copy": 0,
"options": "Employee Tax Exemption Category",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"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,
"columns": 0,
"fetch_from": "exemption_sub_category.max_amount",
"fetch_if_empty": 0,
"fieldname": "max_amount",
"fieldtype": "Currency",
"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": "Maximum Exemption Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"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,
"fetch_from": "exemption_sub_category.max_amount",
"fetch_if_empty": 0,
"fieldname": "max_amount",
"fieldtype": "Currency",
"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": "Maximum Exempted Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"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,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "amount",
"fieldtype": "Data",
"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": "Declared Amount",
"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": 1,
"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,
"fetch_if_empty": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"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": "Declared Amount",
"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": 1,
"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": "2019-04-25 15:45:11.279158",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Tax Exemption Declaration Category",
"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,
],
"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": "2019-04-26 11:28:14.023086",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Tax Exemption Declaration Category",
"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

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
@@ -20,6 +21,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -53,6 +55,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
@@ -84,6 +87,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "start_date",
"fieldtype": "Date",
"hidden": 0,
@@ -116,6 +120,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "end_date",
"fieldtype": "Date",
"hidden": 0,
@@ -148,6 +153,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_5",
"fieldtype": "Section Break",
"hidden": 1,
@@ -180,6 +186,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "periods",
"fieldtype": "Table",
"hidden": 0,
@@ -213,6 +220,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_7",
"fieldtype": "Section Break",
"hidden": 0,
@@ -245,6 +253,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "taxable_salary_slabs",
"fieldtype": "Table",
"hidden": 0,
@@ -270,6 +279,39 @@
"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,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "standard_tax_exemption_amount",
"fieldtype": "Currency",
"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": "Standard Tax Exemption Amount",
"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": 0
}
],
"has_web_view": 0,
@@ -282,7 +324,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-05-25 12:29:07.207927",
"modified": "2019-04-26 01:45:03.160929",
"modified_by": "Administrator",
"module": "HR",
"name": "Payroll Period",
@@ -354,5 +396,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

View File

@@ -5,10 +5,8 @@ frappe.ui.form.on('Salary Component', {
setup: function(frm) {
frm.set_query("default_account", "accounts", function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
var root_types = ["Expense", "Liability"];
return {
filters: {
"root_type": ["in", root_types],
"is_group": 0,
"company": d.company
}

View File

@@ -107,8 +107,8 @@ class SalarySlip(TransactionBase):
for d in self.get("earnings"):
if d.is_flexible_benefit == 1:
current_flexi_amount += d.amount
last_benefits = get_last_payroll_period_benefits(self.employee, self.start_date, self.end_date,\
current_flexi_amount, payroll_period, self._salary_structure_doc)
last_benefits = get_last_payroll_period_benefits(self.employee, self.start_date, self.end_date,
current_flexi_amount, payroll_period, self._salary_structure_doc)
if last_benefits:
for last_benefit in last_benefits:
last_benefit = frappe._dict(last_benefit)
@@ -118,7 +118,7 @@ class SalarySlip(TransactionBase):
def add_employee_flexi_benefits(self, struct_row):
if frappe.db.get_value("Salary Component", struct_row.salary_component, "pay_against_benefit_claim") != 1:
benefit_component_amount = get_benefit_component_amount(self.employee, self.start_date, self.end_date, \
struct_row, self._salary_structure_doc, self.total_working_days, self.payroll_frequency)
struct_row, self._salary_structure_doc, self.total_working_days, self.payroll_frequency)
if benefit_component_amount:
self.update_component_row(struct_row, benefit_component_amount, "earnings")
else:
@@ -418,7 +418,7 @@ class SalarySlip(TransactionBase):
for d in self.get(component_type):
if (self.salary_structure and
cint(d.depends_on_payment_days) and
cint(d.depends_on_payment_days) and cint(self.total_working_days) and
(not
self.salary_slip_based_on_timesheet or
getdate(self.start_date) < joining_date or
@@ -574,8 +574,8 @@ class SalarySlip(TransactionBase):
def calculate_variable_tax(self, tax_component, payroll_period):
annual_taxable_earning, period_factor = 0, 0
pro_rata_tax_paid, additional_tax_paid, benefit_tax_paid = 0, 0, 0
unclaimed_earning, unclaimed_benefit, additional_income = 0, 0, 0
pro_rata_tax_paid, additional_tax_paid, benefit_tax_paid = 0.0, 0.0, 0.0
unclaimed_earning, unclaimed_benefit, additional_income = 0.0, 0.0, 0.0
# get taxable_earning, additional_income in this slip
taxable_earning = self.get_taxable_earnings()
@@ -590,7 +590,7 @@ class SalarySlip(TransactionBase):
unclaimed_earning = self.calculate_unclaimed_taxable_earning(payroll_period, tax_component)
earning_in_period = taxable_earning["taxable_earning"] + unclaimed_earning
period_factor = self.get_period_factor(payroll_period.start_date, payroll_period.end_date,
payroll_period.start_date, self.end_date)
payroll_period.start_date, self.end_date)
annual_taxable_earning = earning_in_period * period_factor
additional_income += self.get_total_additional_income(payroll_period.start_date)
else:
@@ -604,6 +604,7 @@ class SalarySlip(TransactionBase):
{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
"total_exemption_amount")
annual_taxable_earning = annual_earning - exemption_amount
if self.deduct_tax_for_unclaimed_employee_benefits or self.deduct_tax_for_unsubmitted_tax_exemption_proof:
tax_detail = self.get_tax_paid_in_period(payroll_period, tax_component)
if tax_detail:
@@ -613,11 +614,17 @@ class SalarySlip(TransactionBase):
# add any additional income in this slip
additional_income += taxable_earning["additional_income"]
args = {"payroll_period": payroll_period.name, "tax_component": tax_component,
"annual_taxable_earning": annual_taxable_earning, "period_factor": period_factor,
"unclaimed_benefit": unclaimed_benefit, "additional_income": additional_income,
"pro_rata_tax_paid": pro_rata_tax_paid, "benefit_tax_paid": benefit_tax_paid,
"additional_tax_paid": additional_tax_paid}
args = {
"payroll_period": payroll_period.name,
"tax_component": tax_component,
"period_factor": period_factor,
"annual_taxable_earning": annual_taxable_earning,
"additional_income": additional_income,
"unclaimed_benefit": unclaimed_benefit,
"pro_rata_tax_paid": pro_rata_tax_paid,
"benefit_tax_paid": benefit_tax_paid,
"additional_tax_paid": additional_tax_paid
}
return self.calculate_tax(args)
def calculate_unclaimed_taxable_benefit(self, payroll_period):
@@ -664,27 +671,49 @@ class SalarySlip(TransactionBase):
return total_taxable_earning
def get_total_additional_income(self, from_date):
total_additional_pay = 0
sum_additional_earning = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail` sd join
`tabSalary Slip` ss on sd.parent=ss.name where sd.parentfield='earnings'
and sd.is_tax_applicable=1 and is_additional_component=1 and is_flexible_benefit=0
and ss.docstatus=1 and ss.employee='{0}' and ss.start_date between '{1}' and '{2}'
and ss.end_date between '{1}' and '{2}'""".format(self.employee,
from_date, self.start_date))
if sum_additional_earning and sum_additional_earning[0][0]:
total_additional_pay = sum_additional_earning[0][0]
return total_additional_pay
sum_additional_earning = frappe.db.sql("""
select sum(sd.amount)
from
`tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name
where
sd.parentfield='earnings'
and sd.is_tax_applicable=1 and is_additional_component=1
and is_flexible_benefit=0 and ss.docstatus=1
and ss.employee=%(employee)s
and ss.start_date between %(from_date)s and %(to_date)s
and ss.end_date between %(from_date)s and %(to_date)s
""", {
"employee": self.employee,
"from_date": from_date,
"to_date": self.start_date
})
return flt(sum_additional_earning[0][0]) if sum_additional_earning else 0
def get_tax_paid_in_period(self, payroll_period, tax_component, only_total=False):
# find total_tax_paid, tax paid for benefit, additional_salary
sum_tax_paid = frappe.db.sql("""select sum(sd.amount), sum(tax_on_flexible_benefit),
sum(tax_on_additional_salary) from `tabSalary Detail` sd join `tabSalary Slip`
ss on sd.parent=ss.name where sd.parentfield='deductions' and sd.salary_component='{3}'
and sd.variable_based_on_taxable_salary=1 and ss.docstatus=1 and ss.employee='{0}'
and ss.start_date between '{1}' and '{2}' and ss.end_date between '{1}' and
'{2}'""".format(self.employee, payroll_period.start_date, self.start_date, tax_component))
sum_tax_paid = frappe.db.sql("""
select
sum(sd.amount), sum(tax_on_flexible_benefit), sum(tax_on_additional_salary)
from
`tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name
where
sd.parentfield='deductions' and sd.salary_component=%(salary_component)s
and sd.variable_based_on_taxable_salary=1
and ss.docstatus=1 and ss.employee=%(employee)s
and ss.start_date between %(from_date)s and %(to_date)s
and ss.end_date between %(from_date)s and %(to_date)s
""", {
"salary_component": tax_component,
"employee": self.employee,
"from_date": payroll_period.start_date,
"to_date": self.start_date
})
if sum_tax_paid and sum_tax_paid[0][0]:
return {'total_tax_paid': sum_tax_paid[0][0], 'benefit_tax':sum_tax_paid[0][1], 'additional_tax': sum_tax_paid[0][2]}
return {
'total_tax_paid': sum_tax_paid[0][0],
'benefit_tax':sum_tax_paid[0][1],
'additional_tax': sum_tax_paid[0][2]
}
def get_taxable_earnings(self, include_flexi=0, only_flexi=0):
taxable_earning = 0
@@ -695,22 +724,22 @@ class SalarySlip(TransactionBase):
additional_income += earning.amount
continue
if only_flexi:
if earning.is_tax_applicable and earning.is_flexible_benefit:
if earning.is_flexible_benefit:
taxable_earning += earning.amount
continue
if include_flexi:
if earning.is_tax_applicable or (earning.is_tax_applicable and earning.is_flexible_benefit):
taxable_earning += earning.amount
else:
if earning.is_tax_applicable and not earning.is_flexible_benefit:
taxable_earning += earning.amount
return {"taxable_earning": taxable_earning, "additional_income": additional_income}
if include_flexi or not earning.is_flexible_benefit:
taxable_earning += earning.amount
return {
"taxable_earning": taxable_earning,
"additional_income": additional_income
}
def calculate_tax(self, args):
tax_amount, benefit_tax, additional_tax = 0, 0, 0
annual_taxable_earning = args.get("annual_taxable_earning")
benefit_to_tax = args.get("unclaimed_benefit")
additional_income = args.get("additional_income")
# Get tax calc by period
annual_tax = self.calculate_tax_by_tax_slab(args.get("payroll_period"), annual_taxable_earning)
@@ -741,8 +770,10 @@ class SalarySlip(TransactionBase):
def calculate_tax_by_tax_slab(self, payroll_period, annual_taxable_earning):
payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period)
annual_taxable_earning -= flt(payroll_period_obj.standard_tax_exemption_amount)
data = self.get_data_for_eval()
data.update({"annual_taxable_earning": annual_taxable_earning})
taxable_amount = 0
for slab in payroll_period_obj.taxable_salary_slabs:
if slab.condition and not self.eval_tax_slab_condition(slab.condition, data):

View File

@@ -159,21 +159,21 @@ class TestSalarySlip(unittest.TestCase):
month = "%02d" % getdate(nowdate()).month
m = get_month_details(fiscal_year, month)
for payroll_frequncy in ["Monthly", "Bimonthly", "Fortnightly", "Weekly", "Daily"]:
make_employee(payroll_frequncy + "_test_employee@salary.com")
ss = make_employee_salary_slip(payroll_frequncy + "_test_employee@salary.com", payroll_frequncy)
if payroll_frequncy == "Monthly":
for payroll_frequency in ["Monthly", "Bimonthly", "Fortnightly", "Weekly", "Daily"]:
make_employee(payroll_frequency + "_test_employee@salary.com")
ss = make_employee_salary_slip(payroll_frequency + "_test_employee@salary.com", payroll_frequency)
if payroll_frequency == "Monthly":
self.assertEqual(ss.end_date, m['month_end_date'])
elif payroll_frequncy == "Bimonthly":
elif payroll_frequency == "Bimonthly":
if getdate(ss.start_date).day <= 15:
self.assertEqual(ss.end_date, m['month_mid_end_date'])
else:
self.assertEqual(ss.end_date, m['month_end_date'])
elif payroll_frequncy == "Fortnightly":
elif payroll_frequency == "Fortnightly":
self.assertEqual(ss.end_date, add_days(nowdate(),13))
elif payroll_frequncy == "Weekly":
elif payroll_frequency == "Weekly":
self.assertEqual(ss.end_date, add_days(nowdate(),6))
elif payroll_frequncy == "Daily":
elif payroll_frequency == "Daily":
self.assertEqual(ss.end_date, nowdate())
def test_tax_for_payroll_period(self):

View File

@@ -57,11 +57,12 @@ class SalaryStructure(Document):
have_a_flexi = True
max_of_component = frappe.db.get_value("Salary Component", earning_component.salary_component, "max_benefit_amount")
flexi_amount += max_of_component
if have_a_flexi and flt(self.max_benefits) == 0:
frappe.throw(_("Max benefits should be greater than zero to dispense benefits"))
if have_a_flexi and flt(self.max_benefits) > flexi_amount:
frappe.throw(_("Total flexible benefit component amount {0} should not be less \
than max benefits {1}").format(flexi_amount, self.max_benefits))
if have_a_flexi and flexi_amount and flt(self.max_benefits) > flexi_amount:
frappe.throw(_("Total flexible benefit component amount {0} should not be less than max benefits {1}")
.format(flexi_amount, self.max_benefits))
if not have_a_flexi and flt(self.max_benefits) > 0:
frappe.throw(_("Salary Structure should have flexible benefit component(s) to dispense benefit amount"))

View File

@@ -28,7 +28,7 @@ def make_opportunity(buyer_name, email_id):
lead.save(ignore_permissions=True)
o = frappe.new_doc("Opportunity")
o.enquiry_from = "Lead"
o.opportunity_from = "Lead"
o.lead = frappe.get_all("Lead", filters={"email_id": email_id}, fields = ["name"])[0]["name"]
o.save(ignore_permissions=True)

View File

@@ -5,11 +5,6 @@ frappe.provide("erpnext.bom");
frappe.ui.form.on("BOM", {
setup: function(frm) {
frm.add_fetch("item", "description", "description");
frm.add_fetch("item", "image", "image");
frm.add_fetch("item", "item_name", "item_name");
frm.add_fetch("item", "stock_uom", "uom");
frm.set_query("bom_no", "items", function() {
return {
filters: {
@@ -413,8 +408,4 @@ frappe.ui.form.on("BOM", "with_operations", function(frm) {
frm.set_value("operations", []);
}
toggle_operations(frm);
});
cur_frm.cscript.image = function() {
refresh_field("image_view");
};
});

View File

@@ -20,6 +20,7 @@
"collapsible": 0,
"columns": 0,
"description": "Item to be manufactured or repacked",
"fetch_if_empty": 0,
"fieldname": "item",
"fieldtype": "Link",
"hidden": 0,
@@ -55,6 +56,8 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_from": "item.item_name",
"fetch_if_empty": 0,
"fieldname": "item_name",
"fieldtype": "Data",
"hidden": 0,
@@ -87,6 +90,43 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "item.image",
"fetch_if_empty": 0,
"fieldname": "image",
"fieldtype": "Attach Image",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Image",
"length": 0,
"no_copy": 0,
"options": "image",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"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,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "item.stock_uom",
"fetch_if_empty": 0,
"fieldname": "uom",
"fieldtype": "Link",
"hidden": 0,
@@ -121,6 +161,7 @@
"columns": 0,
"default": "1",
"description": "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials",
"fetch_if_empty": 0,
"fieldname": "quantity",
"fieldtype": "Float",
"hidden": 0,
@@ -154,6 +195,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "cb0",
"fieldtype": "Column Break",
"hidden": 0,
@@ -185,6 +227,7 @@
"collapsible": 0,
"columns": 0,
"default": "1",
"fetch_if_empty": 0,
"fieldname": "is_active",
"fieldtype": "Check",
"hidden": 0,
@@ -219,6 +262,7 @@
"collapsible": 0,
"columns": 0,
"default": "1",
"fetch_if_empty": 0,
"fieldname": "is_default",
"fieldtype": "Check",
"hidden": 0,
@@ -253,6 +297,7 @@
"collapsible": 0,
"columns": 0,
"description": "Manage cost of operations",
"fetch_if_empty": 0,
"fieldname": "with_operations",
"fieldtype": "Check",
"hidden": 0,
@@ -284,6 +329,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "inspection_required",
"fieldtype": "Check",
"hidden": 0,
@@ -316,6 +362,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "allow_alternative_item",
"fieldtype": "Check",
"hidden": 0,
@@ -348,6 +395,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "allow_same_item_multiple_times",
"fieldtype": "Check",
"hidden": 0,
@@ -381,6 +429,7 @@
"collapsible": 0,
"columns": 0,
"default": "1",
"fetch_if_empty": 0,
"fieldname": "set_rate_of_sub_assembly_item_based_on_bom",
"fieldtype": "Check",
"hidden": 0,
@@ -414,6 +463,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "inspection_required",
"fetch_if_empty": 0,
"fieldname": "quality_inspection_template",
"fieldtype": "Link",
"hidden": 0,
@@ -447,6 +497,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "currency_detail",
"fieldtype": "Section Break",
"hidden": 0,
@@ -479,6 +530,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -513,6 +565,7 @@
"collapsible": 0,
"columns": 0,
"default": "",
"fetch_if_empty": 0,
"fieldname": "transfer_material_against",
"fieldtype": "Select",
"hidden": 0,
@@ -546,6 +599,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "conversion_rate",
"fieldtype": "Float",
"hidden": 0,
@@ -578,6 +632,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"hidden": 0,
@@ -609,6 +664,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "currency",
"fieldtype": "Link",
"hidden": 0,
@@ -643,6 +699,7 @@
"collapsible": 0,
"columns": 0,
"default": "Valuation Rate",
"fetch_if_empty": 0,
"fieldname": "rm_cost_as_per",
"fieldtype": "Select",
"hidden": 0,
@@ -676,6 +733,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.rm_cost_as_per===\"Price List\"",
"fetch_if_empty": 0,
"fieldname": "buying_price_list",
"fieldtype": "Link",
"hidden": 0,
@@ -710,6 +768,7 @@
"columns": 0,
"depends_on": "",
"description": "",
"fetch_if_empty": 0,
"fieldname": "operations_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -742,6 +801,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "routing",
"fieldtype": "Link",
"hidden": 0,
@@ -775,6 +835,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "operations",
"fieldtype": "Table",
"hidden": 0,
@@ -809,6 +870,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "materials_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -841,6 +903,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "items",
"fieldtype": "Table",
"hidden": 0,
@@ -875,6 +938,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "scrap_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -907,6 +971,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "scrap_items",
"fieldtype": "Table",
"hidden": 0,
@@ -940,6 +1005,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "costing",
"fieldtype": "Section Break",
"hidden": 0,
@@ -972,6 +1038,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "operating_cost",
"fieldtype": "Currency",
"hidden": 0,
@@ -1004,6 +1071,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "raw_material_cost",
"fieldtype": "Currency",
"hidden": 0,
@@ -1036,6 +1104,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "scrap_material_cost",
"fieldtype": "Currency",
"hidden": 0,
@@ -1069,6 +1138,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "cb1",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1099,6 +1169,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_operating_cost",
"fieldtype": "Currency",
"hidden": 0,
@@ -1132,6 +1203,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_raw_material_cost",
"fieldtype": "Currency",
"hidden": 0,
@@ -1165,6 +1237,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_scrap_material_cost",
"fieldtype": "Data",
"hidden": 0,
@@ -1198,6 +1271,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_cost_of_bom",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1229,6 +1303,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_cost",
"fieldtype": "Currency",
"hidden": 0,
@@ -1261,6 +1336,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_26",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1292,6 +1368,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_total_cost",
"fieldtype": "Currency",
"hidden": 0,
@@ -1325,6 +1402,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "more_info_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1356,6 +1434,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "project",
"fieldtype": "Link",
"hidden": 0,
@@ -1390,6 +1469,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -1422,6 +1502,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_break23",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1452,6 +1533,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_25",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1483,6 +1565,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "item.description",
"fetch_if_empty": 0,
"fieldname": "description",
"fieldtype": "Small Text",
"hidden": 0,
@@ -1514,6 +1598,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_27",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1538,71 +1623,6 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "image",
"fieldtype": "Attach",
"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": "Image",
"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": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "image_view",
"fieldtype": "Image",
"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": "Image View",
"length": 0,
"no_copy": 0,
"options": "image",
"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_in_quick_entry": 0,
@@ -1611,6 +1631,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
"fetch_if_empty": 0,
"fieldname": "section_break0",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1642,6 +1663,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "exploded_items",
"fieldtype": "Table",
"hidden": 0,
@@ -1676,6 +1698,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "website_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1710,6 +1733,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "show_in_website",
"fieldtype": "Check",
"hidden": 0,
@@ -1742,6 +1766,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "route",
"fieldtype": "Small Text",
"hidden": 0,
@@ -1776,6 +1801,7 @@
"columns": 0,
"depends_on": "show_in_website",
"description": "Item Image (if not slideshow)",
"fetch_if_empty": 0,
"fieldname": "website_image",
"fieldtype": "Attach Image",
"hidden": 0,
@@ -1808,6 +1834,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "thumbnail",
"fieldtype": "Data",
"hidden": 0,
@@ -1842,6 +1869,7 @@
"collapsible_depends_on": "website_items",
"columns": 0,
"depends_on": "show_in_website",
"fetch_if_empty": 0,
"fieldname": "sb_web_spec",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1875,6 +1903,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "show_in_website",
"fetch_if_empty": 0,
"fieldname": "web_long_description",
"fieldtype": "Text Editor",
"hidden": 0,
@@ -1908,6 +1937,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "show_in_website",
"fetch_if_empty": 0,
"fieldname": "show_items",
"fieldtype": "Check",
"hidden": 0,
@@ -1941,6 +1971,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:(doc.show_in_website && doc.with_operations)",
"fetch_if_empty": 0,
"fieldname": "show_operations",
"fieldtype": "Check",
"hidden": 0,
@@ -1972,13 +2003,14 @@
"hide_toolbar": 0,
"icon": "fa fa-sitemap",
"idx": 1,
"image_field": "image",
"image_view": 0,
"in_create": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-30 16:39:34.353721",
"modified": "2019-05-01 16:36:05.197126",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM",
@@ -2026,7 +2058,7 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "item",
"search_fields": "item, item_name",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",

File diff suppressed because it is too large Load Diff

View File

@@ -571,7 +571,7 @@ execute:frappe.delete_doc_if_exists("Page", "sales-analytics")
execute:frappe.delete_doc_if_exists("Page", "purchase-analytics")
execute:frappe.delete_doc_if_exists("Page", "stock-analytics")
execute:frappe.delete_doc_if_exists("Page", "production-analytics")
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09 #2019-04-01
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09 #2019-04-01 #2019-04-26
erpnext.patches.v11_0.drop_column_max_days_allowed
erpnext.patches.v11_0.change_healthcare_desktop_icons
erpnext.patches.v10_0.update_user_image_in_employee
@@ -590,6 +590,7 @@ erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019
erpnext.patches.v11_1.make_job_card_time_logs
erpnext.patches.v11_1.set_variant_based_on
erpnext.patches.v11_1.move_customer_lead_to_dynamic_column
erpnext.patches.v11_1.woocommerce_set_creation_user
erpnext.patches.v11_1.delete_bom_browser
erpnext.patches.v11_1.set_salary_details_submittable

View File

@@ -0,0 +1,14 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doctype("Quotation")
frappe.db.sql(""" UPDATE `tabQuotation` set party_name = lead WHERE quotation_to = 'Lead' """)
frappe.db.sql(""" UPDATE `tabQuotation` set party_name = customer WHERE quotation_to = 'Customer' """)
frappe.reload_doctype("Opportunity")
frappe.db.sql(""" UPDATE `tabOpportunity` set party_name = lead WHERE opportunity_from = 'Lead' """)
frappe.db.sql(""" UPDATE `tabOpportunity` set party_name = customer WHERE opportunity_from = 'Customer' """)

View File

@@ -74,7 +74,7 @@ class Project(Document):
self.load_tasks()
self.validate_dates()
self.send_welcome_email()
self.update_percent_complete()
self.update_percent_complete(from_validate=True)
def validate_project_name(self):
if self.get("__islocal") and frappe.db.exists("Project", self.project_name):
@@ -198,7 +198,7 @@ class Project(Document):
if self.sales_order:
frappe.db.set_value("Sales Order", self.sales_order, "project", self.name)
def update_percent_complete(self):
def update_percent_complete(self, from_validate=False):
if not self.tasks: return
total = frappe.db.sql("""select count(name) from tabTask where project=%s""", self.name)[0][0]
if not total and self.percent_complete:
@@ -227,7 +227,9 @@ class Project(Document):
self.status = "Completed"
elif not self.status == "Cancelled":
self.status = "Open"
self.db_update()
if not from_validate:
self.db_update()
def update_costing(self):
from_time_sheet = frappe.db.sql("""select

View File

@@ -29,7 +29,7 @@
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"in_standard_filter": 1,
"label": "Subject",
"length": 0,
"no_copy": 0,
@@ -1396,7 +1396,7 @@
"istable": 0,
"max_attachments": 5,
"menu_index": 0,
"modified": "2019-04-18 22:33:03.798331",
"modified": "2019-04-24 23:10:00.014378",
"modified_by": "Administrator",
"module": "Projects",
"name": "Task",

View File

@@ -1154,6 +1154,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
"brand": d.brand,
"qty": d.qty,
"uom": d.uom,
"stock_uom": d.stock_uom,
"parenttype": d.parenttype,
"parent": d.parent,
"pricing_rule": d.pricing_rule,

View File

@@ -104,10 +104,6 @@ class Customer(TransactionBase):
if self.lead_name:
frappe.db.set_value('Lead', self.lead_name, 'status', 'Converted', update_modified=False)
for doctype in ('Opportunity', 'Quotation'):
for d in frappe.get_all(doctype, {'lead': self.lead_name}):
frappe.db.set_value(doctype, d.name, 'customer', self.name, update_modified=False)
def create_lead_address_contact(self):
if self.lead_name:
# assign lead address to customer (if already not set)

View File

@@ -6,6 +6,10 @@ def get_data():
'heatmap': True,
'heatmap_message': _('This is based on transactions against this Customer. See timeline below for details'),
'fieldname': 'customer',
'non_standard_fieldnames': {
'Quotation': 'party_name',
'Opportunity': 'party_name'
},
'transactions': [
{
'label': _('Pre Sales'),

View File

@@ -8,15 +8,27 @@ frappe.ui.form.on('Quotation', {
setup: function(frm) {
frm.custom_make_buttons = {
'Sales Order': 'Make Sales Order'
}
},
frm.set_query("quotation_to", function() {
return{
"filters": {
"name": ["in", ["Customer", "Lead"]],
}
}
});
},
refresh: function(frm) {
frm.trigger("set_label");
frm.trigger("set_dynamic_field_label");
},
quotation_to: function(frm) {
frm.trigger("set_label");
frm.trigger("toggle_reqd_lead_customer");
frm.trigger("set_dynamic_field_label");
},
set_label: function(frm) {
@@ -28,10 +40,6 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
onload: function(doc, dt, dn) {
var me = this;
this._super(doc, dt, dn);
if(doc.customer && !doc.quotation_to)
doc.quotation_to = "Customer";
else if(doc.lead && !doc.quotation_to)
doc.quotation_to = "Lead";
},
refresh: function(doc, dt, dn) {
@@ -97,25 +105,28 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
},
quotation_to: function() {
var me = this;
if (this.frm.doc.quotation_to == "Lead") {
this.frm.set_value("customer", null);
this.frm.set_value("contact_person", null);
} else if (this.frm.doc.quotation_to == "Customer") {
this.frm.set_value("lead", null);
set_dynamic_field_label: function(){
if (this.frm.doc.quotation_to == "Customer")
{
this.frm.set_df_property("party_name", "label", "Customer");
this.frm.fields_dict.party_name.get_query = null;
}
this.toggle_reqd_lead_customer();
if (this.frm.doc.quotation_to == "Lead")
{
this.frm.set_df_property("party_name", "label", "Lead");
this.frm.fields_dict.party_name.get_query = function() {
return{ query: "erpnext.controllers.queries.lead_query" }
}
}
},
toggle_reqd_lead_customer: function() {
var me = this;
this.frm.toggle_reqd("lead", this.frm.doc.quotation_to == "Lead");
this.frm.toggle_reqd("customer", this.frm.doc.quotation_to == "Customer");
// to overwrite the customer_filter trigger from queries.js
this.frm.toggle_reqd("party_name", this.frm.doc.quotation_to);
this.frm.set_query('customer_address', erpnext.queries.address_query);
this.frm.set_query('shipping_address_name', erpnext.queries.address_query);
},
@@ -163,10 +174,6 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
cur_frm.script_manager.make(erpnext.selling.QuotationController);
cur_frm.fields_dict.lead.get_query = function(doc,cdt,cdn) {
return{ query: "erpnext.controllers.queries.lead_query" }
}
cur_frm.cscript['Make Sales Order'] = function() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.quotation.quotation.make_sales_order",

View File

@@ -20,6 +20,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "customer_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -53,6 +54,7 @@
"collapsible": 0,
"columns": 0,
"default": "{customer_name}",
"fetch_if_empty": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 1,
@@ -86,6 +88,7 @@
"collapsible": 0,
"columns": 0,
"default": "",
"fetch_if_empty": 0,
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
@@ -121,8 +124,9 @@
"collapsible": 0,
"columns": 0,
"default": "Customer",
"fetch_if_empty": 0,
"fieldname": "quotation_to",
"fieldtype": "Select",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -135,7 +139,7 @@
"no_copy": 0,
"oldfieldname": "quotation_to",
"oldfieldtype": "Select",
"options": "\nLead\nCustomer",
"options": "DocType",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
@@ -155,9 +159,10 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.quotation_to == \"Customer\"",
"fieldname": "customer",
"fieldtype": "Link",
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "party_name",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -165,12 +170,12 @@
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Customer",
"label": "Customer/Lead",
"length": 0,
"no_copy": 0,
"oldfieldname": "customer",
"oldfieldtype": "Link",
"options": "Customer",
"options": "quotation_to",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
@@ -183,41 +188,6 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.quotation_to == \"Lead\"",
"fieldname": "lead",
"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": 1,
"label": "Lead",
"length": 0,
"no_copy": 0,
"oldfieldname": "lead",
"oldfieldtype": "Link",
"options": "Lead",
"permlevel": 0,
"print_hide": 1,
"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_in_quick_entry": 0,
@@ -226,6 +196,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "customer.customer_name",
"fetch_if_empty": 0,
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 1,
@@ -258,6 +229,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"hidden": 0,
@@ -290,6 +262,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -326,6 +299,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -362,6 +336,7 @@
"collapsible": 0,
"columns": 0,
"default": "Today",
"fetch_if_empty": 0,
"fieldname": "transaction_date",
"fieldtype": "Date",
"hidden": 0,
@@ -396,6 +371,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "valid_till",
"fieldtype": "Date",
"hidden": 0,
@@ -429,6 +405,7 @@
"collapsible": 0,
"columns": 0,
"default": "Sales",
"fetch_if_empty": 0,
"fieldname": "order_type",
"fieldtype": "Select",
"hidden": 0,
@@ -465,6 +442,7 @@
"collapsible_depends_on": "",
"columns": 0,
"depends_on": "eval:(doc.customer || doc.lead)",
"fetch_if_empty": 0,
"fieldname": "contact_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -497,6 +475,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "customer_address",
"fieldtype": "Link",
"hidden": 0,
@@ -529,6 +508,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "address_display",
"fieldtype": "Small Text",
"hidden": 0,
@@ -563,6 +543,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.customer",
"fetch_if_empty": 0,
"fieldname": "contact_person",
"fieldtype": "Link",
"hidden": 0,
@@ -597,6 +578,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "contact_display",
"fieldtype": "Small Text",
"hidden": 0,
@@ -628,6 +610,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "contact_mobile",
"fieldtype": "Small Text",
"hidden": 0,
@@ -659,6 +642,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "contact_email",
"fieldtype": "Data",
"hidden": 1,
@@ -692,6 +676,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "customer",
"fetch_if_empty": 0,
"fieldname": "col_break98",
"fieldtype": "Column Break",
"hidden": 0,
@@ -723,6 +708,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "shipping_address_name",
"fieldtype": "Link",
"hidden": 0,
@@ -755,6 +741,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "shipping_address",
"fieldtype": "Small Text",
"hidden": 0,
@@ -788,6 +775,7 @@
"columns": 0,
"depends_on": "customer",
"description": "",
"fetch_if_empty": 0,
"fieldname": "customer_group",
"fieldtype": "Link",
"hidden": 1,
@@ -823,6 +811,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
"fetch_if_empty": 0,
"fieldname": "territory",
"fieldtype": "Link",
"hidden": 0,
@@ -855,6 +844,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "currency_and_price_list",
"fieldtype": "Section Break",
"hidden": 0,
@@ -887,6 +877,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "currency",
"fieldtype": "Link",
"hidden": 0,
@@ -923,6 +914,7 @@
"collapsible": 0,
"columns": 0,
"description": "Rate at which customer's currency is converted to company's base currency",
"fetch_if_empty": 0,
"fieldname": "conversion_rate",
"fieldtype": "Float",
"hidden": 0,
@@ -958,6 +950,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break2",
"fieldtype": "Column Break",
"hidden": 0,
@@ -989,6 +982,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "selling_price_list",
"fieldtype": "Link",
"hidden": 0,
@@ -1024,6 +1018,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "price_list_currency",
"fieldtype": "Link",
"hidden": 0,
@@ -1057,6 +1052,7 @@
"collapsible": 0,
"columns": 0,
"description": "Rate at which Price list currency is converted to company's base currency",
"fetch_if_empty": 0,
"fieldname": "plc_conversion_rate",
"fieldtype": "Float",
"hidden": 0,
@@ -1089,6 +1085,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "ignore_pricing_rule",
"fieldtype": "Check",
"hidden": 0,
@@ -1120,6 +1117,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "items_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1153,6 +1151,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "items",
"fieldtype": "Table",
"hidden": 0,
@@ -1188,6 +1187,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "sec_break23",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1218,6 +1218,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_qty",
"fieldtype": "Float",
"hidden": 0,
@@ -1250,6 +1251,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -1283,6 +1285,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_net_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -1318,6 +1321,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_28",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1348,6 +1352,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total",
"fieldtype": "Currency",
"hidden": 0,
@@ -1381,6 +1386,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "net_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -1413,6 +1419,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_net_weight",
"fieldtype": "Float",
"hidden": 0,
@@ -1445,6 +1452,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "taxes_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1478,6 +1486,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
"hidden": 0,
@@ -1512,6 +1521,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_34",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1542,6 +1552,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "shipping_rule",
"fieldtype": "Link",
"hidden": 0,
@@ -1575,6 +1586,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_36",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1605,6 +1617,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "taxes",
"fieldtype": "Table",
"hidden": 0,
@@ -1639,6 +1652,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "sec_tax_breakup",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1671,6 +1685,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"hidden": 0,
@@ -1703,6 +1718,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_39",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1733,6 +1749,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_total_taxes_and_charges",
"fieldtype": "Currency",
"hidden": 0,
@@ -1767,6 +1784,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_42",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1797,6 +1815,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_taxes_and_charges",
"fieldtype": "Currency",
"hidden": 0,
@@ -1830,6 +1849,7 @@
"collapsible": 1,
"collapsible_depends_on": "discount_amount",
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_44",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1863,6 +1883,7 @@
"collapsible": 0,
"columns": 0,
"default": "Grand Total",
"fetch_if_empty": 0,
"fieldname": "apply_discount_on",
"fieldtype": "Select",
"hidden": 0,
@@ -1896,6 +1917,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -1929,6 +1951,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_46",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1960,6 +1983,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "additional_discount_percentage",
"fieldtype": "Float",
"hidden": 0,
@@ -1992,6 +2016,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "discount_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -2024,6 +2049,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "totals",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2057,6 +2083,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_grand_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -2092,6 +2119,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_rounding_adjustment",
"fieldtype": "Currency",
"hidden": 0,
@@ -2126,6 +2154,7 @@
"collapsible": 0,
"columns": 0,
"description": "In Words will be visible once you save the Quotation.",
"fetch_if_empty": 0,
"fieldname": "base_in_words",
"fieldtype": "Data",
"hidden": 0,
@@ -2160,6 +2189,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_rounded_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -2195,6 +2225,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break3",
"fieldtype": "Column Break",
"hidden": 0,
@@ -2227,6 +2258,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "grand_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -2262,6 +2294,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "rounding_adjustment",
"fieldtype": "Currency",
"hidden": 0,
@@ -2295,6 +2328,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "rounded_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -2330,6 +2364,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "in_words",
"fieldtype": "Data",
"hidden": 0,
@@ -2366,6 +2401,7 @@
"collapsible_depends_on": "",
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "payment_schedule_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2398,6 +2434,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "payment_terms_template",
"fieldtype": "Link",
"hidden": 0,
@@ -2431,6 +2468,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "payment_schedule",
"fieldtype": "Table",
"hidden": 0,
@@ -2465,6 +2503,7 @@
"collapsible": 1,
"collapsible_depends_on": "terms",
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "terms_section_break",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2498,6 +2537,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "tc_name",
"fieldtype": "Link",
"hidden": 0,
@@ -2532,6 +2572,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "terms",
"fieldtype": "Text Editor",
"hidden": 0,
@@ -2565,6 +2606,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "print_settings",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2597,6 +2639,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "letter_head",
"fieldtype": "Link",
"hidden": 0,
@@ -2631,6 +2674,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "group_same_items",
"fieldtype": "Check",
"hidden": 0,
@@ -2663,6 +2707,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_73",
"fieldtype": "Column Break",
"hidden": 0,
@@ -2694,6 +2739,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "select_print_heading",
"fieldtype": "Link",
"hidden": 0,
@@ -2728,6 +2774,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "language",
"fieldtype": "Data",
"hidden": 0,
@@ -2760,6 +2807,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "subscription_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2792,6 +2840,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "auto_repeat",
"fieldtype": "Link",
"hidden": 0,
@@ -2826,6 +2875,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval: doc.auto_repeat",
"fetch_if_empty": 0,
"fieldname": "update_auto_repeat_reference",
"fieldtype": "Button",
"hidden": 0,
@@ -2858,6 +2908,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "more_info",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2891,6 +2942,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "campaign",
"fieldtype": "Link",
"hidden": 0,
@@ -2925,6 +2977,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "source",
"fieldtype": "Link",
"hidden": 0,
@@ -2960,6 +3013,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.status===\"Lost\"",
"fetch_if_empty": 0,
"fieldname": "order_lost_reason",
"fieldtype": "Small Text",
"hidden": 0,
@@ -2993,6 +3047,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break4",
"fieldtype": "Column Break",
"hidden": 0,
@@ -3026,6 +3081,7 @@
"collapsible": 0,
"columns": 0,
"default": "Draft",
"fetch_if_empty": 0,
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
@@ -3060,6 +3116,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "enq_det",
"fieldtype": "Text",
"hidden": 1,
@@ -3093,6 +3150,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "supplier_quotation",
"fieldtype": "Link",
"hidden": 0,
@@ -3126,6 +3184,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "opportunity",
"fieldtype": "Link",
"hidden": 0,
@@ -3165,7 +3224,7 @@
"istable": 0,
"max_attachments": 1,
"menu_index": 0,
"modified": "2019-01-07 16:51:55.604845",
"modified": "2019-04-25 15:26:21.983298",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",
@@ -3331,11 +3390,11 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 1,
"search_fields": "status,transaction_date,customer,lead,order_type",
"search_fields": "status,transaction_date,party_name,order_type",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "customer",
"timeline_field": "party_name",
"title_field": "title",
"track_changes": 0,
"track_seen": 0,

View File

@@ -28,11 +28,10 @@ class Quotation(SellingController):
self.update_opportunity()
self.validate_order_type()
self.validate_uom_is_integer("stock_uom", "qty")
self.validate_quotation_to()
self.validate_valid_till()
if self.items:
self.with_items = 1
def validate_valid_till(self):
if self.valid_till and self.valid_till < self.transaction_date:
frappe.throw(_("Valid till date cannot be before transaction date"))
@@ -43,16 +42,9 @@ class Quotation(SellingController):
def validate_order_type(self):
super(Quotation, self).validate_order_type()
def validate_quotation_to(self):
if self.customer:
self.quotation_to = "Customer"
self.lead = None
elif self.lead:
self.quotation_to = "Lead"
def update_lead(self):
if self.lead:
frappe.get_doc("Lead", self.lead).set_status(update=True)
if self.quotation_to == "Lead" and self.party_name:
frappe.get_doc("Lead", self.party_name).set_status(update=True)
def update_opportunity(self):
for opportunity in list(set([d.prevdoc_docname for d in self.get("items")])):
@@ -213,12 +205,12 @@ def _make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
}
}, target_doc, set_missing_values, ignore_permissions=ignore_permissions)
return doclist
return doclist
def _make_customer(source_name, ignore_permissions=False):
quotation = frappe.db.get_value("Quotation", source_name, ["lead", "order_type", "customer"])
if quotation and quotation[0] and not quotation[2]:
lead_name = quotation[0]
quotation = frappe.db.get_value("Quotation", source_name, ["order_type", "party_name", "customer_name"])
if quotation and quotation[1] and not quotation[2]:
lead_name = quotation[1]
customer_name = frappe.db.get_value("Customer", {"lead_name": lead_name},
["name", "customer_name"], as_dict=True)
if not customer_name:
@@ -246,3 +238,5 @@ def _make_customer(source_name, ignore_permissions=False):
frappe.throw(_("Please create Customer from Lead {0}").format(lead_name))
else:
return customer_name
else:
return frappe.get_doc("Customer",quotation[2])

View File

@@ -203,15 +203,15 @@ class TestQuotation(unittest.TestCase):
test_records = frappe.get_test_records('Quotation')
def get_quotation_dict(customer=None, item_code=None):
if not customer:
customer = '_Test Customer'
def get_quotation_dict(party_name=None, item_code=None):
if not party_name:
party_name = '_Test Customer'
if not item_code:
item_code = '_Test Item'
return {
'doctype': 'Quotation',
'customer': customer,
'party_name': party_name,
'items': [
{
'item_code': item_code,
@@ -229,7 +229,7 @@ def make_quotation(**args):
qo.transaction_date = args.transaction_date
qo.company = args.company or "_Test Company"
qo.customer = args.customer or "_Test Customer"
qo.party_name = args.party_name or "_Test Customer"
qo.currency = args.currency or "INR"
if args.selling_price_list:
qo.selling_price_list = args.selling_price_list

View File

@@ -1,37 +1,37 @@
[
{
"company": "_Test Company",
"conversion_rate": 1.0,
"currency": "INR",
"customer": "_Test Customer",
"customer_group": "_Test Customer Group",
"customer_name": "_Test Customer",
"doctype": "Quotation",
"base_grand_total": 1000.0,
"grand_total": 1000.0,
"order_type": "Sales",
"plc_conversion_rate": 1.0,
"price_list_currency": "INR",
"items": [
{
"base_amount": 1000.0,
"base_rate": 100.0,
"description": "CPU",
"doctype": "Quotation Item",
"item_code": "_Test Item Home Desktop 100",
"item_name": "CPU",
"parentfield": "items",
"qty": 10.0,
"rate": 100.0,
"uom": "_Test UOM 1",
"stock_uom": "_Test UOM 1",
"conversion_factor": 1.0
}
],
"quotation_to": "Customer",
"selling_price_list": "_Test Price List",
"territory": "_Test Territory",
"transaction_date": "2013-02-21",
"valid_till": "2013-03-21"
}
{
"company": "_Test Company",
"conversion_rate": 1.0,
"currency": "INR",
"party_name": "_Test Customer",
"customer_group": "_Test Customer Group",
"customer_name": "_Test Customer",
"doctype": "Quotation",
"base_grand_total": 1000.0,
"grand_total": 1000.0,
"order_type": "Sales",
"plc_conversion_rate": 1.0,
"price_list_currency": "INR",
"items": [
{
"base_amount": 1000.0,
"base_rate": 100.0,
"description": "CPU",
"doctype": "Quotation Item",
"item_code": "_Test Item Home Desktop 100",
"item_name": "CPU",
"parentfield": "items",
"qty": 10.0,
"rate": 100.0,
"uom": "_Test UOM 1",
"stock_uom": "_Test UOM 1",
"conversion_factor": 1.0
}
],
"quotation_to": "Customer",
"selling_price_list": "_Test Price List",
"territory": "_Test Territory",
"transaction_date": "2013-02-21",
"valid_till": "2013-03-21"
}
]

View File

@@ -544,7 +544,7 @@ def make_project(source_name, target_doc=None):
"Sales Order Item": {
"doctype": "Project Task",
"field_map": {
"description": "title",
"item_code": "title",
},
}
}, target_doc, postprocess)

View File

@@ -33,7 +33,7 @@ def make_sample_data(domains, make_dependent = False):
def make_opportunity(items, customer):
b = frappe.get_doc({
"doctype": "Opportunity",
"enquiry_from": "Customer",
"opportunity_from": "Customer",
"customer": customer,
"opportunity_type": _("Sales"),
"with_items": 1

View File

@@ -196,7 +196,7 @@ def _get_cart_quotation(party=None):
party = get_party()
quotation = frappe.get_all("Quotation", fields=["name"], filters=
{party.doctype.lower(): party.name, "order_type": "Shopping Cart", "docstatus": 0},
{"party_name": party.name, "order_type": "Shopping Cart", "docstatus": 0},
order_by="modified desc", limit_page_length=1)
if quotation:
@@ -211,7 +211,7 @@ def _get_cart_quotation(party=None):
"status": "Draft",
"docstatus": 0,
"__islocal": 1,
(party.doctype.lower()): party.name
"party_name": party.name
})
qdoc.contact_person = frappe.db.get_value("Contact", {"email_id": frappe.session.user})
@@ -291,9 +291,9 @@ def _set_price_list(quotation, cart_settings):
# check if customer price list exists
selling_price_list = None
if quotation.customer:
if quotation.party_name:
from erpnext.accounts.party import get_default_price_list
selling_price_list = get_default_price_list(frappe.get_doc("Customer", quotation.customer))
selling_price_list = get_default_price_list(frappe.get_doc("Customer", quotation.party_name))
# else check for territory based price list
if not selling_price_list:
@@ -305,9 +305,9 @@ def set_taxes(quotation, cart_settings):
"""set taxes based on billing territory"""
from erpnext.accounts.party import set_taxes
customer_group = frappe.db.get_value("Customer", quotation.customer, "customer_group")
customer_group = frappe.db.get_value("Customer", quotation.party_name, "customer_group")
quotation.taxes_and_charges = set_taxes(quotation.customer, "Customer", \
quotation.taxes_and_charges = set_taxes(quotation.party_name, "Customer", \
quotation.transaction_date, quotation.company, customer_group, None, \
quotation.customer_address, quotation.shipping_address_name, 1)
#

View File

@@ -33,7 +33,6 @@ class TestShoppingCart(unittest.TestCase):
self.assertEqual(quotation.quotation_to, "Customer")
self.assertEqual(quotation.contact_person,
frappe.db.get_value("Contact", dict(email_id="test_cart_user@example.com")))
self.assertEqual(quotation.lead, None)
self.assertEqual(quotation.contact_email, frappe.session.user)
return quotation
@@ -44,8 +43,7 @@ class TestShoppingCart(unittest.TestCase):
# test if quotation with customer is fetched
quotation = _get_cart_quotation()
self.assertEqual(quotation.quotation_to, "Customer")
self.assertEqual(quotation.customer, "_Test Customer")
self.assertEqual(quotation.lead, None)
self.assertEqual(quotation.party_name, "_Test Customer")
self.assertEqual(quotation.contact_email, frappe.session.user)
return quotation
@@ -107,7 +105,7 @@ class TestShoppingCart(unittest.TestCase):
from erpnext.accounts.party import set_taxes
tax_rule_master = set_taxes(quotation.customer, "Customer", \
tax_rule_master = set_taxes(quotation.party_name, "Customer", \
quotation.transaction_date, quotation.company, None, None, \
quotation.customer_address, quotation.shipping_address_name, 1)
self.assertEqual(quotation.taxes_and_charges, tax_rule_master)
@@ -122,7 +120,7 @@ class TestShoppingCart(unittest.TestCase):
"doctype": "Quotation",
"quotation_to": "Customer",
"order_type": "Shopping Cart",
"customer": get_party(frappe.session.user).name,
"party_name": get_party(frappe.session.user).name,
"docstatus": 0,
"contact_email": frappe.session.user,
"selling_price_list": "_Test Price List Rest of the World",

View File

@@ -431,7 +431,7 @@ def insert_item_price(args):
def get_item_price(args, item_code, ignore_party=False):
"""
Get name, price_list_rate from Item Price based on conditions
Check if the Derised qty is within the increment of the packing list.
Check if the desired qty is within the increment of the packing list.
:param args: dict (or frappe._dict) with mandatory fields price_list, uom
optional fields min_qty, transaction_date, customer, supplier
:param item_code: str, Item Doctype field item_code
@@ -469,11 +469,11 @@ def get_price_list_rate_for(args, item_code):
for min_qty 9 and min_qty 20. It returns Item Price Rate for qty 9 as
the best fit in the range of avaliable min_qtyies
:param customer: link to Customer DocType
:param supplier: link to Supplier DocType
:param customer: link to Customer DocType
:param supplier: link to Supplier DocType
:param price_list: str (Standard Buying or Standard Selling)
:param item_code: str, Item Doctype field item_code
:param qty: Derised Qty
:param qty: Desired Qty
:param transaction_date: Date of the price
"""
item_price_args = {
@@ -498,7 +498,7 @@ def get_price_list_rate_for(args, item_code):
general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party"))
if not general_price_list_rate and args.get("uom") != args.get("stock_uom"):
item_price_args["args"] = args.get("stock_uom")
item_price_args["uom"] = args.get("stock_uom")
general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party"))
if general_price_list_rate:
@@ -514,11 +514,11 @@ def get_price_list_rate_for(args, item_code):
def check_packing_list(price_list_rate_name, desired_qty, item_code):
"""
Check if the Derised qty is within the increment of the packing list.
Check if the desired qty is within the increment of the packing list.
:param price_list_rate_name: Name of Item Price
:param desired_qty: Derised Qt
:param desired_qty: Desired Qt
:param item_code: str, Item Doctype field item_code
:param qty: Derised Qt
:param qty: Desired Qt
"""
flag = True

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
@@ -20,6 +21,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "subject_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -53,6 +55,7 @@
"collapsible": 0,
"columns": 0,
"default": "",
"fetch_if_empty": 0,
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
@@ -85,6 +88,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "subject",
"fieldtype": "Data",
"hidden": 0,
@@ -93,7 +97,7 @@
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"in_standard_filter": 1,
"label": "Subject",
"length": 0,
"no_copy": 0,
@@ -116,6 +120,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "issue_type",
"fieldtype": "Link",
"hidden": 0,
@@ -149,6 +154,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "cb00",
"fieldtype": "Column Break",
"hidden": 0,
@@ -180,6 +186,7 @@
"collapsible": 0,
"columns": 0,
"default": "Open",
"fetch_if_empty": 0,
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
@@ -215,6 +222,7 @@
"collapsible": 0,
"columns": 0,
"default": "Medium",
"fetch_if_empty": 0,
"fieldname": "priority",
"fieldtype": "Select",
"hidden": 0,
@@ -249,6 +257,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.__islocal",
"fetch_if_empty": 0,
"fieldname": "raised_by",
"fieldtype": "Data",
"hidden": 0,
@@ -283,6 +292,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "email_account",
"fieldtype": "Link",
"hidden": 0,
@@ -316,6 +326,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
@@ -350,6 +361,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_7",
"fieldtype": "Section Break",
"hidden": 0,
@@ -383,6 +395,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "description",
"fieldtype": "Text Editor",
"hidden": 0,
@@ -416,6 +429,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "response",
"fieldtype": "Section Break",
"hidden": 0,
@@ -448,6 +462,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "mins_to_first_response",
"fieldtype": "Float",
"hidden": 0,
@@ -480,6 +495,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "first_responded_on",
"fieldtype": "Datetime",
"hidden": 0,
@@ -511,6 +527,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "additional_info",
"fieldtype": "Section Break",
"hidden": 0,
@@ -543,6 +560,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "lead",
"fieldtype": "Link",
"hidden": 0,
@@ -575,6 +593,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "contact",
"fieldtype": "Link",
"hidden": 0,
@@ -607,6 +626,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_16",
"fieldtype": "Column Break",
"hidden": 0,
@@ -638,6 +658,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 0,
@@ -671,6 +692,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "project",
"fieldtype": "Link",
"hidden": 0,
@@ -704,6 +726,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -736,6 +759,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_19",
"fieldtype": "Section Break",
"hidden": 0,
@@ -769,6 +793,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
"fetch_if_empty": 0,
"fieldname": "resolution_details",
"fieldtype": "Text Editor",
"hidden": 0,
@@ -803,6 +828,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
"fetch_if_empty": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"hidden": 0,
@@ -835,6 +861,7 @@
"collapsible": 0,
"columns": 0,
"default": "Today",
"fetch_if_empty": 0,
"fieldname": "opening_date",
"fieldtype": "Date",
"hidden": 0,
@@ -868,6 +895,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "opening_time",
"fieldtype": "Time",
"hidden": 0,
@@ -902,6 +930,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
"fetch_if_empty": 0,
"fieldname": "resolution_date",
"fieldtype": "Datetime",
"hidden": 0,
@@ -935,6 +964,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "content_type",
"fieldtype": "Data",
"hidden": 1,
@@ -966,6 +996,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "attachment",
"fieldtype": "Attach",
"hidden": 1,
@@ -998,6 +1029,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "via_customer_portal",
"fieldtype": "Check",
"hidden": 0,
@@ -1035,7 +1067,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-08-21 14:44:27.615004",
"modified": "2019-04-24 23:09:48.711076",
"modified_by": "Administrator",
"module": "Support",
"name": "Issue",

View File

@@ -28,7 +28,7 @@ def send_message(subject="Website Query", message="", sender="", status="Open"):
opportunity = frappe.get_doc(dict(
doctype ='Opportunity',
enquiry_from = 'Customer' if customer else 'Lead',
opportunity_from = 'Customer' if customer else 'Lead',
status = 'Open',
title = subject,
contact_email = sender,