Merge branch 'hotfix' of https://github.com/frappe/erpnext into quotation-filter-fixes
This commit is contained in:
@@ -42,15 +42,14 @@ frappe.ui.form.on('Account', {
|
|||||||
// show / hide convert buttons
|
// show / hide convert buttons
|
||||||
frm.trigger('add_toolbar_buttons');
|
frm.trigger('add_toolbar_buttons');
|
||||||
}
|
}
|
||||||
frm.add_custom_button(__('Update Account Name / Number'), function () {
|
if (frm.has_perm('write')) {
|
||||||
frm.trigger("update_account_number");
|
frm.add_custom_button(__('Update Account Name / Number'), function () {
|
||||||
});
|
frm.trigger("update_account_number");
|
||||||
}
|
});
|
||||||
|
frm.add_custom_button(__('Merge Account'), function () {
|
||||||
if(!frm.doc.__islocal) {
|
frm.trigger("merge_account");
|
||||||
frm.add_custom_button(__('Merge Account'), function () {
|
});
|
||||||
frm.trigger("merge_account");
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
account_type: function (frm) {
|
account_type: function (frm) {
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ def update_account_number(name, account_name, account_number=None):
|
|||||||
|
|
||||||
new_name = get_account_autoname(account_number, account_name, account.company)
|
new_name = get_account_autoname(account_number, account_name, account.company)
|
||||||
if name != new_name:
|
if name != new_name:
|
||||||
frappe.rename_doc("Account", name, new_name, ignore_permissions=1)
|
frappe.rename_doc("Account", name, new_name, force=1)
|
||||||
return new_name
|
return new_name
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@@ -287,7 +287,7 @@ def merge_account(old, new, is_group, root_type, company):
|
|||||||
frappe.db.set_value("Account", new, "parent_account",
|
frappe.db.set_value("Account", new, "parent_account",
|
||||||
frappe.db.get_value("Account", old, "parent_account"))
|
frappe.db.get_value("Account", old, "parent_account"))
|
||||||
|
|
||||||
frappe.rename_doc("Account", old, new, merge=1, ignore_permissions=1)
|
frappe.rename_doc("Account", old, new, merge=1, force=1)
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "Settled",
|
"default": "Pending",
|
||||||
"fetch_if_empty": 0,
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
@@ -755,7 +755,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2019-04-26 14:32:16.437813",
|
"modified": "2019-05-11 05:27:55.244721",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Transaction",
|
"name": "Bank Transaction",
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ class BankTransaction(StatusUpdater):
|
|||||||
frappe.db.set_value(self.doctype, self.name, "allocated_amount", 0)
|
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)))
|
frappe.db.set_value(self.doctype, self.name, "unallocated_amount", abs(flt(self.credit) - flt(self.debit)))
|
||||||
|
|
||||||
|
amount = self.debit or self.credit
|
||||||
|
if amount == self.allocated_amount:
|
||||||
|
frappe.db.set_value(self.doctype, self.name, "status", "Reconciled")
|
||||||
|
|
||||||
self.reload()
|
self.reload()
|
||||||
|
|
||||||
def clear_linked_payment_entries(self):
|
def clear_linked_payment_entries(self):
|
||||||
|
|||||||
@@ -167,7 +167,12 @@ def get_pricing_rule_for_item(args):
|
|||||||
|
|
||||||
if args.transaction_type=="selling":
|
if args.transaction_type=="selling":
|
||||||
if args.customer and not (args.customer_group and args.territory):
|
if args.customer and not (args.customer_group and args.territory):
|
||||||
customer = frappe.get_cached_value("Customer", args.customer, ["customer_group", "territory"])
|
|
||||||
|
if args.quotation_to and args.quotation_to != 'Customer':
|
||||||
|
customer = frappe._dict()
|
||||||
|
else:
|
||||||
|
customer = frappe.get_cached_value("Customer", args.customer, ["customer_group", "territory"])
|
||||||
|
|
||||||
if customer:
|
if customer:
|
||||||
args.customer_group, args.territory = customer
|
args.customer_group, args.territory = customer
|
||||||
|
|
||||||
|
|||||||
@@ -402,9 +402,9 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
pi.save()
|
pi.save()
|
||||||
pi.submit()
|
pi.submit()
|
||||||
self.assertEqual(pi.payment_schedule[0].payment_amount, 756.15)
|
self.assertEqual(pi.payment_schedule[0].payment_amount, 606.15)
|
||||||
self.assertEqual(pi.payment_schedule[0].due_date, pi.posting_date)
|
self.assertEqual(pi.payment_schedule[0].due_date, pi.posting_date)
|
||||||
self.assertEqual(pi.payment_schedule[1].payment_amount, 756.15)
|
self.assertEqual(pi.payment_schedule[1].payment_amount, 606.15)
|
||||||
self.assertEqual(pi.payment_schedule[1].due_date, add_days(pi.posting_date, 30))
|
self.assertEqual(pi.payment_schedule[1].due_date, add_days(pi.posting_date, 30))
|
||||||
|
|
||||||
pi.load_from_db()
|
pi.load_from_db()
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ def add_payment_to_transaction(transaction, payment_entry, gl_entry):
|
|||||||
"payment_entry": payment_entry.name,
|
"payment_entry": payment_entry.name,
|
||||||
"allocated_amount": allocated_amount
|
"allocated_amount": allocated_amount
|
||||||
})
|
})
|
||||||
|
|
||||||
transaction.save()
|
transaction.save()
|
||||||
|
transaction.update_allocations()
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_linked_payments(bank_transaction):
|
def get_linked_payments(bank_transaction):
|
||||||
@@ -56,7 +58,11 @@ def get_linked_payments(bank_transaction):
|
|||||||
return check_amount_vs_description(amount_matching, description_matching)
|
return check_amount_vs_description(amount_matching, description_matching)
|
||||||
|
|
||||||
elif description_matching:
|
elif description_matching:
|
||||||
return sorted(description_matching, key = lambda x: x["posting_date"], reverse=True)
|
description_matching = filter(lambda x: not x.get('clearance_date'), description_matching)
|
||||||
|
if not description_matching:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return sorted(list(description_matching), key = lambda x: x["posting_date"], reverse=True)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
@@ -97,7 +103,8 @@ def check_matching_amount(bank_account, company, transaction):
|
|||||||
journal_entries = frappe.db.sql("""
|
journal_entries = frappe.db.sql("""
|
||||||
SELECT
|
SELECT
|
||||||
'Journal Entry' as doctype, je.name, je.posting_date, je.cheque_no as reference_no,
|
'Journal Entry' as doctype, je.name, je.posting_date, je.cheque_no as reference_no,
|
||||||
je.pay_to_recd_from as party, je.cheque_date as reference_date, jea.credit_in_account_currency as paid_amount
|
jea.account_currency as currency, je.pay_to_recd_from as party, je.cheque_date as reference_date,
|
||||||
|
jea.credit_in_account_currency as paid_amount
|
||||||
FROM
|
FROM
|
||||||
`tabJournal Entry Account` as jea
|
`tabJournal Entry Account` as jea
|
||||||
JOIN
|
JOIN
|
||||||
@@ -107,12 +114,17 @@ def check_matching_amount(bank_account, company, transaction):
|
|||||||
WHERE
|
WHERE
|
||||||
(je.clearance_date is null or je.clearance_date='0000-00-00')
|
(je.clearance_date is null or je.clearance_date='0000-00-00')
|
||||||
AND
|
AND
|
||||||
jea.account = %s
|
jea.account = %(bank_account)s
|
||||||
AND
|
AND
|
||||||
jea.credit_in_account_currency like %s
|
jea.credit_in_account_currency like %(txt)s
|
||||||
AND
|
AND
|
||||||
je.docstatus = 1
|
je.docstatus = 1
|
||||||
""", (bank_account, amount), as_dict=True)
|
""", {
|
||||||
|
'bank_account': bank_account,
|
||||||
|
'txt': '%%%s%%' % amount
|
||||||
|
}, as_dict=True, debug=1)
|
||||||
|
|
||||||
|
frappe.errprint(journal_entries)
|
||||||
|
|
||||||
if transaction.credit > 0:
|
if transaction.credit > 0:
|
||||||
sales_invoices = frappe.db.sql("""
|
sales_invoices = frappe.db.sql("""
|
||||||
@@ -213,9 +225,14 @@ def get_matching_descriptions_data(company, transaction):
|
|||||||
company_currency = get_company_currency(company)
|
company_currency = get_company_currency(company)
|
||||||
for key, value in iteritems(links):
|
for key, value in iteritems(links):
|
||||||
if key == "Payment Entry":
|
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"]))
|
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", "clearance_date"]))
|
||||||
if key == "Journal Entry":
|
if key == "Journal Entry":
|
||||||
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"])
|
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", "clearance_date"])
|
||||||
for journal_entry in journal_entries:
|
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_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
|
journal_entry["currency"] = journal_entry_accounts[0]["account_currency"] if journal_entry_accounts else company_currency
|
||||||
@@ -236,6 +253,9 @@ def check_amount_vs_description(amount_matching, description_matching):
|
|||||||
if description_matching:
|
if description_matching:
|
||||||
for am_match in amount_matching:
|
for am_match in amount_matching:
|
||||||
for des_match in description_matching:
|
for des_match in description_matching:
|
||||||
|
if des_match.get("clearance_date"):
|
||||||
|
continue
|
||||||
|
|
||||||
if am_match["party"] == des_match["party"]:
|
if am_match["party"] == des_match["party"]:
|
||||||
if am_match not in result:
|
if am_match not in result:
|
||||||
result.append(am_match)
|
result.append(am_match)
|
||||||
|
|||||||
@@ -1957,6 +1957,12 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
|||||||
}],
|
}],
|
||||||
function(values){
|
function(values){
|
||||||
me.item_batch_no[me.items[0].item_code] = values.batch;
|
me.item_batch_no[me.items[0].item_code] = values.batch;
|
||||||
|
const item = me.frm.doc.items.find(
|
||||||
|
({ item_code }) => item_code === me.items[0].item_code
|
||||||
|
);
|
||||||
|
if (item) {
|
||||||
|
item.batch_no = values.batch;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
__('Select Batch No'))
|
__('Select Batch No'))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
|
|
||||||
frappe.query_reports["Inactive Sales Items"] = {
|
frappe.query_reports["Inactive Sales Items"] = {
|
||||||
"filters": [
|
"filters": [
|
||||||
|
{
|
||||||
|
fieldname: "territory",
|
||||||
|
label: __("Territory"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Territory",
|
||||||
|
reqd: 1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldname: "item",
|
fieldname: "item",
|
||||||
label: __("Item"),
|
label: __("Item"),
|
||||||
|
|||||||
@@ -7,13 +7,11 @@ from frappe.utils import getdate, add_days, today, cint
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
|
|
||||||
columns = get_columns()
|
columns = get_columns()
|
||||||
data = get_data(filters)
|
data = get_data(filters)
|
||||||
return columns, data
|
return columns, data
|
||||||
|
|
||||||
def get_columns():
|
def get_columns():
|
||||||
|
|
||||||
columns = [
|
columns = [
|
||||||
{
|
{
|
||||||
"fieldname": "territory",
|
"fieldname": "territory",
|
||||||
@@ -74,36 +72,39 @@ def get_columns():
|
|||||||
|
|
||||||
|
|
||||||
def get_data(filters):
|
def get_data(filters):
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
items = get_items(filters)
|
items = get_items(filters)
|
||||||
|
territories = get_territories(filters)
|
||||||
sales_invoice_data = get_sales_details(filters)
|
sales_invoice_data = get_sales_details(filters)
|
||||||
|
|
||||||
for item in items:
|
for territory in territories:
|
||||||
row = {
|
for item in items:
|
||||||
|
row = {
|
||||||
|
"territory": territory.name,
|
||||||
"item_group": item.item_group,
|
"item_group": item.item_group,
|
||||||
"item": item.name,
|
"item": item.name,
|
||||||
"item_name": item.item_name
|
"item_name": item.item_name
|
||||||
}
|
}
|
||||||
|
|
||||||
if sales_invoice_data.get(item.name):
|
if sales_invoice_data.get((territory.name,item.name)):
|
||||||
item_obj = sales_invoice_data[item.name]
|
item_obj = sales_invoice_data[(territory.name,item.name)]
|
||||||
if item_obj.days_since_last_order > cint(filters['days']):
|
if item_obj.days_since_last_order > cint(filters['days']):
|
||||||
row.update({
|
row.update({
|
||||||
"territory": item_obj.territory,
|
"territory": item_obj.territory,
|
||||||
"customer": item_obj.customer,
|
"customer": item_obj.customer,
|
||||||
"last_order_date": item_obj.last_order_date,
|
"last_order_date": item_obj.last_order_date,
|
||||||
"qty": item_obj.qty,
|
"qty": item_obj.qty,
|
||||||
"days_since_last_order": item_obj.days_since_last_order
|
"days_since_last_order": item_obj.days_since_last_order
|
||||||
})
|
})
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def get_sales_details(filters):
|
def get_sales_details(filters):
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
item_details_map = {}
|
item_details_map = {}
|
||||||
|
|
||||||
@@ -118,12 +119,21 @@ def get_sales_details(filters):
|
|||||||
.format(date_field = date_field, doctype = filters['based_on']), as_dict=1)
|
.format(date_field = date_field, doctype = filters['based_on']), as_dict=1)
|
||||||
|
|
||||||
for d in sales_data:
|
for d in sales_data:
|
||||||
item_details_map.setdefault(d.item_name, d)
|
item_details_map.setdefault((d.territory,d.item_name), d)
|
||||||
|
|
||||||
return item_details_map
|
return item_details_map
|
||||||
|
|
||||||
def get_items(filters):
|
def get_territories(filters):
|
||||||
|
|
||||||
|
filter_dict = {}
|
||||||
|
if filters.get("territory"):
|
||||||
|
filter_dict.update({'name': filters['territory']})
|
||||||
|
|
||||||
|
territories = frappe.get_all("Territory", fields=["name"], filters=filter_dict)
|
||||||
|
|
||||||
|
return territories
|
||||||
|
|
||||||
|
def get_items(filters):
|
||||||
filters_dict = {
|
filters_dict = {
|
||||||
"disabled": 0,
|
"disabled": 0,
|
||||||
"is_stock_item": 1
|
"is_stock_item": 1
|
||||||
|
|||||||
@@ -763,6 +763,9 @@ class AccountsController(TransactionBase):
|
|||||||
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||||
grand_total = grand_total - flt(self.write_off_amount)
|
grand_total = grand_total - flt(self.write_off_amount)
|
||||||
|
|
||||||
|
if self.get("total_advance"):
|
||||||
|
grand_total -= self.get("total_advance")
|
||||||
|
|
||||||
if not self.get("payment_schedule"):
|
if not self.get("payment_schedule"):
|
||||||
if self.get("payment_terms_template"):
|
if self.get("payment_terms_template"):
|
||||||
data = get_payment_terms(self.payment_terms_template, posting_date, grand_total)
|
data = get_payment_terms(self.payment_terms_template, posting_date, grand_total)
|
||||||
@@ -808,6 +811,9 @@ class AccountsController(TransactionBase):
|
|||||||
total = flt(total, self.precision("grand_total"))
|
total = flt(total, self.precision("grand_total"))
|
||||||
|
|
||||||
grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total'))
|
grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total'))
|
||||||
|
if self.get("total_advance"):
|
||||||
|
grand_total -= self.get("total_advance")
|
||||||
|
|
||||||
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||||
grand_total = grand_total - flt(self.write_off_amount)
|
grand_total = grand_total - flt(self.write_off_amount)
|
||||||
if total != grand_total:
|
if total != grand_total:
|
||||||
|
|||||||
@@ -5,79 +5,79 @@ frappe.provide("erpnext");
|
|||||||
cur_frm.email_field = "email_id";
|
cur_frm.email_field = "email_id";
|
||||||
|
|
||||||
erpnext.LeadController = frappe.ui.form.Controller.extend({
|
erpnext.LeadController = frappe.ui.form.Controller.extend({
|
||||||
setup: function() {
|
setup: function () {
|
||||||
this.frm.fields_dict.customer.get_query = function(doc, cdt, cdn) {
|
this.frm.fields_dict.customer.get_query = function (doc, cdt, cdn) {
|
||||||
return { query: "erpnext.controllers.queries.customer_query" } }
|
return { query: "erpnext.controllers.queries.customer_query" }
|
||||||
|
}
|
||||||
|
|
||||||
|
this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead);
|
||||||
},
|
},
|
||||||
|
|
||||||
onload: function() {
|
onload: function () {
|
||||||
|
if (cur_frm.fields_dict.lead_owner.df.options.match(/^User/)) {
|
||||||
if(cur_frm.fields_dict.lead_owner.df.options.match(/^User/)) {
|
cur_frm.fields_dict.lead_owner.get_query = function (doc, cdt, cdn) {
|
||||||
cur_frm.fields_dict.lead_owner.get_query = function(doc, cdt, cdn) {
|
|
||||||
return { query: "frappe.core.doctype.user.user.user_query" }
|
return { query: "frappe.core.doctype.user.user.user_query" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cur_frm.fields_dict.contact_by.df.options.match(/^User/)) {
|
if (cur_frm.fields_dict.contact_by.df.options.match(/^User/)) {
|
||||||
cur_frm.fields_dict.contact_by.get_query = function(doc, cdt, cdn) {
|
cur_frm.fields_dict.contact_by.get_query = function (doc, cdt, cdn) {
|
||||||
return { query: "frappe.core.doctype.user.user.user_query" } }
|
return { query: "frappe.core.doctype.user.user.user_query" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function() {
|
refresh: function () {
|
||||||
var doc = this.frm.doc;
|
var doc = this.frm.doc;
|
||||||
erpnext.toggle_naming_series();
|
erpnext.toggle_naming_series();
|
||||||
frappe.dynamic_link = {doc: doc, fieldname: 'name', doctype: 'Lead'}
|
frappe.dynamic_link = { doc: doc, fieldname: 'name', doctype: 'Lead' }
|
||||||
|
|
||||||
if(!doc.__islocal && doc.__onload && !doc.__onload.is_customer) {
|
if (!doc.__islocal && doc.__onload && !doc.__onload.is_customer) {
|
||||||
this.frm.add_custom_button(__("Customer"), this.create_customer, __("Make"));
|
this.frm.add_custom_button(__("Customer"), this.create_customer, __("Make"));
|
||||||
this.frm.add_custom_button(__("Opportunity"), this.create_opportunity, __("Make"));
|
this.frm.add_custom_button(__("Opportunity"), this.create_opportunity, __("Make"));
|
||||||
this.frm.add_custom_button(__("Quotation"), this.make_quotation, __("Make"));
|
this.frm.add_custom_button(__("Quotation"), this.make_quotation, __("Make"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.frm.doc.__islocal) {
|
if (!this.frm.doc.__islocal) {
|
||||||
frappe.contacts.render_address_and_contact(cur_frm);
|
frappe.contacts.render_address_and_contact(cur_frm);
|
||||||
} else {
|
} else {
|
||||||
frappe.contacts.clear_address_and_contact(cur_frm);
|
frappe.contacts.clear_address_and_contact(cur_frm);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
create_customer: function() {
|
create_customer: function () {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.crm.doctype.lead.lead.make_customer",
|
method: "erpnext.crm.doctype.lead.lead.make_customer",
|
||||||
frm: cur_frm
|
frm: cur_frm
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
create_opportunity: function() {
|
create_opportunity: function () {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.crm.doctype.lead.lead.make_opportunity",
|
method: "erpnext.crm.doctype.lead.lead.make_opportunity",
|
||||||
frm: cur_frm
|
frm: cur_frm
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
make_quotation: function() {
|
make_quotation: function () {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.crm.doctype.lead.lead.make_quotation",
|
method: "erpnext.crm.doctype.lead.lead.make_quotation",
|
||||||
frm: cur_frm
|
frm: cur_frm
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
organization_lead: function() {
|
organization_lead: function () {
|
||||||
if (this.frm.doc.organization_lead == 1) {
|
this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead);
|
||||||
this.frm.set_df_property('company_name', 'reqd', 1);
|
this.frm.toggle_reqd("company_name", this.frm.doc.organization_lead);
|
||||||
} else {
|
|
||||||
this.frm.set_df_property('company_name', 'reqd', 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
company_name: function() {
|
company_name: function () {
|
||||||
if (this.frm.doc.organization_lead == 1) {
|
if (this.frm.doc.organization_lead == 1) {
|
||||||
this.frm.set_value("lead_name", this.frm.doc.company_name);
|
this.frm.set_value("lead_name", this.frm.doc.company_name);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
contact_date: function() {
|
contact_date: function () {
|
||||||
if (this.frm.doc.contact_date) {
|
if (this.frm.doc.contact_date) {
|
||||||
let d = moment(this.frm.doc.contact_date);
|
let d = moment(this.frm.doc.contact_date);
|
||||||
d.add(1, "hours");
|
d.add(1, "hours");
|
||||||
@@ -86,4 +86,4 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$.extend(cur_frm.cscript, new erpnext.LeadController({frm: cur_frm}));
|
$.extend(cur_frm.cscript, new erpnext.LeadController({ frm: cur_frm }));
|
||||||
|
|||||||
@@ -141,7 +141,7 @@
|
|||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 0,
|
||||||
"search_index": 1,
|
"search_index": 1,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
@@ -499,7 +499,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Lead Owner",
|
"label": "Lead Owner",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
@@ -1389,7 +1389,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-10-02 09:12:23.415379",
|
"modified": "2019-05-10 03:22:57.283628",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "CRM",
|
"module": "CRM",
|
||||||
"name": "Lead",
|
"name": "Lead",
|
||||||
|
|||||||
@@ -102,14 +102,18 @@ class Lead(SellingController):
|
|||||||
|
|
||||||
def has_lost_quotation(self):
|
def has_lost_quotation(self):
|
||||||
return frappe.db.get_value("Quotation", {
|
return frappe.db.get_value("Quotation", {
|
||||||
"lead": self.name,
|
"party_name": self.name,
|
||||||
"docstatus": 1,
|
"docstatus": 1,
|
||||||
"status": "Lost"
|
"status": "Lost"
|
||||||
})
|
})
|
||||||
|
|
||||||
def set_lead_name(self):
|
def set_lead_name(self):
|
||||||
if not self.lead_name:
|
if not self.lead_name:
|
||||||
frappe.db.set_value("Lead", self.name, "lead_name", self.company_name)
|
# Check for leads being created through data import
|
||||||
|
if not self.company_name:
|
||||||
|
frappe.throw(_("A Lead requires either a person's name or an organization's name"))
|
||||||
|
|
||||||
|
self.lead_name = self.company_name
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_customer(source_name, target_doc=None):
|
def make_customer(source_name, target_doc=None):
|
||||||
@@ -163,7 +167,7 @@ def make_quotation(source_name, target_doc=None):
|
|||||||
{"Lead": {
|
{"Lead": {
|
||||||
"doctype": "Quotation",
|
"doctype": "Quotation",
|
||||||
"field_map": {
|
"field_map": {
|
||||||
"name": "lead"
|
"name": "party_name"
|
||||||
}
|
}
|
||||||
}}, target_doc)
|
}}, target_doc)
|
||||||
target_doc.quotation_to = "Lead"
|
target_doc.quotation_to = "Lead"
|
||||||
@@ -225,4 +229,4 @@ def make_lead_from_communication(communication, ignore_communication_links=False
|
|||||||
lead_name = lead.name
|
lead_name = lead.name
|
||||||
|
|
||||||
link_communication_to_document(doc, "Lead", lead_name, ignore_communication_links)
|
link_communication_to_document(doc, "Lead", lead_name, ignore_communication_links)
|
||||||
return lead_name
|
return lead_name
|
||||||
|
|||||||
@@ -5,9 +5,19 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils import time_diff_in_seconds
|
||||||
from erpnext.hr.doctype.employee.employee import get_employee_emails
|
from erpnext.hr.doctype.employee.employee import get_employee_emails
|
||||||
|
|
||||||
class TrainingEvent(Document):
|
class TrainingEvent(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
self.set_employee_emails()
|
||||||
|
self.validate_period()
|
||||||
|
|
||||||
|
def set_employee_emails(self):
|
||||||
self.employee_emails = ', '.join(get_employee_emails([d.employee
|
self.employee_emails = ', '.join(get_employee_emails([d.employee
|
||||||
for d in self.employees]))
|
for d in self.employees]))
|
||||||
|
|
||||||
|
def validate_period(self):
|
||||||
|
if time_diff_in_seconds(self.end_time, self.start_time) <= 0:
|
||||||
|
frappe.throw(_('End time cannot be before start time'))
|
||||||
@@ -598,4 +598,5 @@ erpnext.patches.v11_1.set_salary_details_submittable
|
|||||||
erpnext.patches.v11_1.rename_depends_on_lwp
|
erpnext.patches.v11_1.rename_depends_on_lwp
|
||||||
erpnext.patches.v11_1.set_missing_title_for_quotation
|
erpnext.patches.v11_1.set_missing_title_for_quotation
|
||||||
execute:frappe.delete_doc("Report", "Inactive Items")
|
execute:frappe.delete_doc("Report", "Inactive Items")
|
||||||
erpnext.patches.v11_1.delete_scheduling_tool
|
erpnext.patches.v11_1.delete_scheduling_tool
|
||||||
|
erpnext.patches.v11_1.update_bank_transaction_status
|
||||||
15
erpnext/patches/v11_1/update_bank_transaction_status.py
Normal file
15
erpnext/patches/v11_1/update_bank_transaction_status.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# 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_doc("accounts", "doctype", "bank_transaction")
|
||||||
|
|
||||||
|
frappe.db.sql(""" UPDATE `tabBank Transaction`
|
||||||
|
SET status = 'Reconciled'
|
||||||
|
WHERE
|
||||||
|
status = 'Settled' and (debit = allocated_amount or credit = allocated_amount)
|
||||||
|
and ifnull(allocated_amount, 0) > 0
|
||||||
|
""")
|
||||||
@@ -442,16 +442,17 @@ def daily_reminder():
|
|||||||
projects = get_projects_for_collect_progress("Daily", fields)
|
projects = get_projects_for_collect_progress("Daily", fields)
|
||||||
|
|
||||||
for project in projects:
|
for project in projects:
|
||||||
if not check_project_update_exists(project.name, project.get("daily_time_to_send")):
|
if allow_to_make_project_update(project.name, project.get("daily_time_to_send"), "Daily"):
|
||||||
send_project_update_email_to_users(project.name)
|
send_project_update_email_to_users(project.name)
|
||||||
|
|
||||||
def twice_daily_reminder():
|
def twice_daily_reminder():
|
||||||
fields = ["first_email", "second_email"]
|
fields = ["first_email", "second_email"]
|
||||||
projects = get_projects_for_collect_progress("Twice Daily", fields)
|
projects = get_projects_for_collect_progress("Twice Daily", fields)
|
||||||
|
fields.remove("name")
|
||||||
|
|
||||||
for project in projects:
|
for project in projects:
|
||||||
for d in fields:
|
for d in fields:
|
||||||
if not check_project_update_exists(project.name, project.get(d)):
|
if allow_to_make_project_update(project.name, project.get(d), "Twicely"):
|
||||||
send_project_update_email_to_users(project.name)
|
send_project_update_email_to_users(project.name)
|
||||||
|
|
||||||
def weekly_reminder():
|
def weekly_reminder():
|
||||||
@@ -463,14 +464,19 @@ def weekly_reminder():
|
|||||||
if current_day != project.day_to_send:
|
if current_day != project.day_to_send:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not check_project_update_exists(project.name, project.get("weekly_time_to_send")):
|
if allow_to_make_project_update(project.name, project.get("weekly_time_to_send"), "Weekly"):
|
||||||
send_project_update_email_to_users(project.name)
|
send_project_update_email_to_users(project.name)
|
||||||
|
|
||||||
def check_project_update_exists(project, time):
|
def allow_to_make_project_update(project, time, frequency):
|
||||||
data = frappe.db.sql(""" SELECT name from `tabProject Update`
|
data = frappe.db.sql(""" SELECT name from `tabProject Update`
|
||||||
WHERE project = %s and date = %s and time >= %s """, (project, today(), time))
|
WHERE project = %s and date = %s """, (project, today()))
|
||||||
|
|
||||||
return True if data and data[0][0] else False
|
# len(data) > 1 condition is checked for twicely frequency
|
||||||
|
if data and (frequency in ['Daily', 'Weekly'] or len(data) > 1):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if get_time(nowtime()) >= get_time(time):
|
||||||
|
return True
|
||||||
|
|
||||||
def get_projects_for_collect_progress(frequency, fields):
|
def get_projects_for_collect_progress(frequency, fields):
|
||||||
fields.extend(["name"])
|
fields.extend(["name"])
|
||||||
|
|||||||
@@ -429,6 +429,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
set_warehouse: me.frm.doc.set_warehouse,
|
set_warehouse: me.frm.doc.set_warehouse,
|
||||||
warehouse: item.warehouse,
|
warehouse: item.warehouse,
|
||||||
customer: me.frm.doc.customer || me.frm.doc.party_name,
|
customer: me.frm.doc.customer || me.frm.doc.party_name,
|
||||||
|
quotation_to: me.frm.doc.quotation_to,
|
||||||
supplier: me.frm.doc.supplier,
|
supplier: me.frm.doc.supplier,
|
||||||
currency: me.frm.doc.currency,
|
currency: me.frm.doc.currency,
|
||||||
update_stock: update_stock,
|
update_stock: update_stock,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, erpnext
|
import frappe, erpnext
|
||||||
from frappe.utils import cint
|
from frappe.utils import cint, nowdate
|
||||||
from frappe import throw, _
|
from frappe import throw, _
|
||||||
from frappe.utils.nestedset import NestedSet
|
from frappe.utils.nestedset import NestedSet
|
||||||
from erpnext.stock import get_warehouse_account
|
from erpnext.stock import get_warehouse_account
|
||||||
@@ -140,7 +140,7 @@ class Warehouse(NestedSet):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_children(doctype, parent=None, company=None, is_root=False):
|
def get_children(doctype, parent=None, company=None, is_root=False):
|
||||||
from erpnext.stock.utils import get_stock_value_from_bin
|
from erpnext.stock.utils import get_stock_value_on
|
||||||
|
|
||||||
if is_root:
|
if is_root:
|
||||||
parent = ""
|
parent = ""
|
||||||
@@ -156,7 +156,7 @@ def get_children(doctype, parent=None, company=None, is_root=False):
|
|||||||
|
|
||||||
# return warehouses
|
# return warehouses
|
||||||
for wh in warehouses:
|
for wh in warehouses:
|
||||||
wh["balance"] = get_stock_value_from_bin(warehouse=wh.value)
|
wh["balance"] = get_stock_value_on(warehouse=wh.value, posting_date=nowdate())
|
||||||
if company:
|
if company:
|
||||||
wh["company_currency"] = frappe.db.get_value('Company', company, 'default_currency')
|
wh["company_currency"] = frappe.db.get_value('Company', company, 'default_currency')
|
||||||
return warehouses
|
return warehouses
|
||||||
|
|||||||
@@ -573,6 +573,10 @@ def validate_conversion_rate(args, meta):
|
|||||||
def get_party_item_code(args, item_doc, out):
|
def get_party_item_code(args, item_doc, out):
|
||||||
if args.transaction_type=="selling" and args.customer:
|
if args.transaction_type=="selling" and args.customer:
|
||||||
out.customer_item_code = None
|
out.customer_item_code = None
|
||||||
|
|
||||||
|
if args.quotation_to != 'Customer':
|
||||||
|
return
|
||||||
|
|
||||||
customer_item_code = item_doc.get("customer_items", {"customer_name": args.customer})
|
customer_item_code = item_doc.get("customer_items", {"customer_name": args.customer})
|
||||||
|
|
||||||
if customer_item_code:
|
if customer_item_code:
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
frappe.query_reports["Delayed Order Item Summary"] = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
fieldname: "company",
|
||||||
|
label: __("Company"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Company",
|
||||||
|
default: frappe.defaults.get_default("company"),
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"from_date",
|
||||||
|
label: __("From Date"),
|
||||||
|
fieldtype: "Date",
|
||||||
|
default: frappe.datetime.month_start(),
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"to_date",
|
||||||
|
label: __("To Date"),
|
||||||
|
fieldtype: "Date",
|
||||||
|
default: frappe.datetime.now_date(),
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"sales_order",
|
||||||
|
label: __("Sales Order"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Sales Order",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"customer",
|
||||||
|
label: __("Customer"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Customer",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"customer_group",
|
||||||
|
label: __("Customer Group"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Customer Group",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"item_group",
|
||||||
|
label: __("Item Group"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Item Group",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"based_on",
|
||||||
|
label: __("Based On"),
|
||||||
|
fieldtype: "Select",
|
||||||
|
options: ["Delivery Note", "Sales Invoice"],
|
||||||
|
default: "Sales Invoice",
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"creation": "2019-05-12 13:05:39.162734",
|
||||||
|
"disable_prepared_report": 0,
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"letter_head": "Gadgets International",
|
||||||
|
"modified": "2019-05-12 13:05:39.162734",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Stock",
|
||||||
|
"name": "Delayed Order Item Summary",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"prepared_report": 0,
|
||||||
|
"ref_doctype": "Delivery Note",
|
||||||
|
"report_name": "Delayed Order Item Summary",
|
||||||
|
"report_type": "Script Report",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "Stock User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Sales Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Maintenance User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Accounts User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Sales User"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils import date_diff
|
||||||
|
|
||||||
|
def execute(filters=None, consolidated = False):
|
||||||
|
data, columns = DelayedOrderItemSummary(filters).run()
|
||||||
|
|
||||||
|
return data, columns
|
||||||
|
|
||||||
|
class DelayedOrderItemSummary(object):
|
||||||
|
def __init__(self, filters=None):
|
||||||
|
self.filters = frappe._dict(filters or {})
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
return self.get_columns(), self.get_data() or []
|
||||||
|
|
||||||
|
def get_data(self, consolidated=False):
|
||||||
|
conditions = ""
|
||||||
|
|
||||||
|
doctype = self.filters.get("based_on")
|
||||||
|
child_doc= "%s Item" % doctype
|
||||||
|
|
||||||
|
if doctype == "Sales Invoice":
|
||||||
|
conditions = " and `tabSales Invoice`.update_stock = 1 and `tabSales Invoice`.is_pos = 0"
|
||||||
|
|
||||||
|
if self.filters.get("item_group"):
|
||||||
|
conditions += " and `tab%s`.item_group = '%s'" % (child_doc,
|
||||||
|
frappe.db.escape(self.filters.get("item_group")))
|
||||||
|
|
||||||
|
for field in ["customer", "customer_group", "company"]:
|
||||||
|
if self.filters.get(field):
|
||||||
|
conditions += " and `tab%s`.%s = '%s'" % (doctype,
|
||||||
|
field, frappe.db.escape(self.filters.get(field)))
|
||||||
|
|
||||||
|
sales_order_field = "against_sales_order"
|
||||||
|
if doctype == "Sales Invoice":
|
||||||
|
sales_order_field = "sales_order"
|
||||||
|
|
||||||
|
if self.filters.get("sales_order"):
|
||||||
|
conditions = " and `tab%s`.%s = '%s'" %(child_doc, sales_order_field, self.filters.get("sales_order"))
|
||||||
|
|
||||||
|
self.transactions = frappe.db.sql(""" SELECT `tab{child_doc}`.item_code, `tab{child_doc}`.item_name,
|
||||||
|
`tab{child_doc}`.item_group, `tab{child_doc}`.qty, `tab{child_doc}`.rate, `tab{child_doc}`.amount,
|
||||||
|
`tab{child_doc}`.so_detail, `tab{child_doc}`.{so_field} as sales_order,
|
||||||
|
`tab{doctype}`.customer, `tab{doctype}`.posting_date, `tab{doctype}`.name, `tab{doctype}`.grand_total
|
||||||
|
FROM `tab{child_doc}`, `tab{doctype}`
|
||||||
|
WHERE
|
||||||
|
`tab{child_doc}`.parent = `tab{doctype}`.name and `tab{doctype}`.docstatus = 1 and
|
||||||
|
`tab{doctype}`.posting_date between %(from_date)s and %(to_date)s and
|
||||||
|
`tab{child_doc}`.{so_field} is not null and `tab{child_doc}`.{so_field} != '' {cond}
|
||||||
|
""".format(cond=conditions, doctype=doctype, child_doc=child_doc, so_field=sales_order_field), {
|
||||||
|
'from_date': self.filters.get('from_date'),
|
||||||
|
'to_date': self.filters.get('to_date')
|
||||||
|
}, as_dict=1)
|
||||||
|
|
||||||
|
if self.transactions:
|
||||||
|
self.filter_transactions_data(consolidated)
|
||||||
|
|
||||||
|
return self.transactions
|
||||||
|
|
||||||
|
def filter_transactions_data(self, consolidated=False):
|
||||||
|
sales_orders = [d.sales_order for d in self.transactions]
|
||||||
|
doctype = "Sales Order"
|
||||||
|
filters = {'name': ('in', sales_orders)}
|
||||||
|
|
||||||
|
if not consolidated:
|
||||||
|
sales_order_items = [d.so_detail for d in self.transactions]
|
||||||
|
doctype = "Sales Order Item"
|
||||||
|
filters = {'parent': ('in', sales_orders), 'name': ('in', sales_order_items)}
|
||||||
|
|
||||||
|
so_data = {}
|
||||||
|
for d in frappe.get_all(doctype, filters = filters,
|
||||||
|
fields = ["delivery_date", "parent", "name"]):
|
||||||
|
key = d.name if consolidated else (d.parent, d.name)
|
||||||
|
if key not in so_data:
|
||||||
|
so_data.setdefault(key, d.delivery_date)
|
||||||
|
|
||||||
|
for row in self.transactions:
|
||||||
|
key = row.sales_order if consolidated else (row.sales_order, row.so_detail)
|
||||||
|
row.update({
|
||||||
|
'delivery_date': so_data.get(key),
|
||||||
|
'delay_days': date_diff(row.posting_date, so_data.get(key))
|
||||||
|
})
|
||||||
|
|
||||||
|
return self.transactions
|
||||||
|
|
||||||
|
def get_columns(self):
|
||||||
|
based_on = self.filters.get("based_on")
|
||||||
|
|
||||||
|
return [{
|
||||||
|
"label": _(based_on),
|
||||||
|
"fieldname": "name",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": based_on,
|
||||||
|
"width": 100
|
||||||
|
},{
|
||||||
|
"label": _("Customer"),
|
||||||
|
"fieldname": "customer",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Customer",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Expected Delivery Date"),
|
||||||
|
"fieldname": "delivery_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Actual Delivery Date"),
|
||||||
|
"fieldname": "posting_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Item Code"),
|
||||||
|
"fieldname": "item_code",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Item",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Item Name"),
|
||||||
|
"fieldname": "item_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Quantity"),
|
||||||
|
"fieldname": "qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Rate"),
|
||||||
|
"fieldname": "rate",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Amount"),
|
||||||
|
"fieldname": "amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Delay Days"),
|
||||||
|
"fieldname": "delay_days",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Sales Order"),
|
||||||
|
"fieldname": "sales_order",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Sales Order",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Customer PO"),
|
||||||
|
"fieldname": "po_no",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"width": 100
|
||||||
|
}]
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
frappe.query_reports["Delayed Order Summary"] = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
fieldname: "company",
|
||||||
|
label: __("Company"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Company",
|
||||||
|
default: frappe.defaults.get_default("company"),
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"from_date",
|
||||||
|
label: __("From Date"),
|
||||||
|
fieldtype: "Date",
|
||||||
|
default: frappe.datetime.month_start(),
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"to_date",
|
||||||
|
label: __("To Date"),
|
||||||
|
fieldtype: "Date",
|
||||||
|
default: frappe.datetime.now_date(),
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"sales_order",
|
||||||
|
label: __("Sales Order"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Sales Order",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"customer",
|
||||||
|
label: __("Customer"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Customer",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"customer_group",
|
||||||
|
label: __("Customer Group"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Customer Group",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"item_group",
|
||||||
|
label: __("Item Group"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Item Group",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"based_on",
|
||||||
|
label: __("Based On"),
|
||||||
|
fieldtype: "Select",
|
||||||
|
options: ["Delivery Note", "Sales Invoice"],
|
||||||
|
default: "Sales Invoice",
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"creation": "2019-05-12 12:38:44.907187",
|
||||||
|
"disable_prepared_report": 0,
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"letter_head": "Gadgets International",
|
||||||
|
"modified": "2019-05-12 12:39:16.378341",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Stock",
|
||||||
|
"name": "Delayed Order Summary",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"prepared_report": 0,
|
||||||
|
"ref_doctype": "Delivery Note",
|
||||||
|
"report_name": "Delayed Order Summary",
|
||||||
|
"report_type": "Script Report",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "Stock User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Sales Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Maintenance User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Accounts User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Sales User"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
from erpnext.stock.report.delayed_order_item_summary.delayed_order_item_summary import DelayedOrderItemSummary
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
columns, data = [], []
|
||||||
|
|
||||||
|
columns, data = DelayedOrderSummary(filters).run()
|
||||||
|
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
class DelayedOrderSummary(DelayedOrderItemSummary):
|
||||||
|
def run(self):
|
||||||
|
return self.get_columns(), self.get_data(consolidated=True) or []
|
||||||
|
|
||||||
|
def get_data(self, consolidated=False):
|
||||||
|
data = super(DelayedOrderSummary, self).get_data(consolidated) or []
|
||||||
|
|
||||||
|
so_list = []
|
||||||
|
result = []
|
||||||
|
for d in data:
|
||||||
|
if d.sales_order not in so_list:
|
||||||
|
so_list.append(d.sales_order)
|
||||||
|
result.append(d)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_columns(self):
|
||||||
|
based_on = self.filters.get("based_on")
|
||||||
|
|
||||||
|
return [{
|
||||||
|
"label": _(based_on),
|
||||||
|
"fieldname": "name",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": based_on,
|
||||||
|
"width": 100
|
||||||
|
},{
|
||||||
|
"label": _("Customer"),
|
||||||
|
"fieldname": "customer",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Customer",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Expected Delivery Date"),
|
||||||
|
"fieldname": "delivery_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Actual Delivery Date"),
|
||||||
|
"fieldname": "posting_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Amount"),
|
||||||
|
"fieldname": "grand_total",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Delay Days"),
|
||||||
|
"fieldname": "delay_days",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Sales Order"),
|
||||||
|
"fieldname": "sales_order",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Sales Order",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Customer PO"),
|
||||||
|
"fieldname": "po_no",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"width": 100
|
||||||
|
}]
|
||||||
Reference in New Issue
Block a user