Merge branch 'hotfix'

This commit is contained in:
Sahil Khan
2019-05-14 16:48:26 +05:30
44 changed files with 8013 additions and 7125 deletions

View File

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

View File

@@ -42,15 +42,14 @@ frappe.ui.form.on('Account', {
// show / hide convert buttons
frm.trigger('add_toolbar_buttons');
}
frm.add_custom_button(__('Update Account Name / Number'), function () {
frm.trigger("update_account_number");
});
}
if(!frm.doc.__islocal) {
frm.add_custom_button(__('Merge Account'), function () {
frm.trigger("merge_account");
});
if (frm.has_perm('write')) {
frm.add_custom_button(__('Update Account Name / Number'), function () {
frm.trigger("update_account_number");
});
frm.add_custom_button(__('Merge Account'), function () {
frm.trigger("merge_account");
});
}
}
},
account_type: function (frm) {

View File

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

View File

@@ -121,7 +121,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Settled",
"default": "Pending",
"fetch_if_empty": 0,
"fieldname": "status",
"fieldtype": "Select",
@@ -755,7 +755,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-04-26 14:32:16.437813",
"modified": "2019-05-11 05:27:55.244721",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Transaction",

View File

@@ -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, "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()
def clear_linked_payment_entries(self):

View File

@@ -167,7 +167,12 @@ def get_pricing_rule_for_item(args):
if args.transaction_type=="selling":
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:
args.customer_group, args.territory = customer

View File

@@ -402,9 +402,9 @@ class TestPurchaseInvoice(unittest.TestCase):
pi.save()
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[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))
pi.load_from_db()

View File

@@ -39,7 +39,9 @@ def add_payment_to_transaction(transaction, payment_entry, gl_entry):
"payment_entry": payment_entry.name,
"allocated_amount": allocated_amount
})
transaction.save()
transaction.update_allocations()
@frappe.whitelist()
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)
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:
return []
@@ -97,7 +103,8 @@ def check_matching_amount(bank_account, company, transaction):
journal_entries = frappe.db.sql("""
SELECT
'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
`tabJournal Entry Account` as jea
JOIN
@@ -107,12 +114,17 @@ def check_matching_amount(bank_account, company, transaction):
WHERE
(je.clearance_date is null or je.clearance_date='0000-00-00')
AND
jea.account = %s
jea.account = %(bank_account)s
AND
jea.credit_in_account_currency like %s
jea.credit_in_account_currency like %(txt)s
AND
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:
sales_invoices = frappe.db.sql("""
@@ -213,9 +225,14 @@ def get_matching_descriptions_data(company, transaction):
company_currency = get_company_currency(company)
for key, value in iteritems(links):
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":
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:
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
@@ -236,6 +253,9 @@ def check_amount_vs_description(amount_matching, description_matching):
if description_matching:
for am_match in amount_matching:
for des_match in description_matching:
if des_match.get("clearance_date"):
continue
if am_match["party"] == des_match["party"]:
if am_match not in result:
result.append(am_match)

View File

@@ -1957,6 +1957,12 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
}],
function(values){
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'))
}

View File

@@ -4,6 +4,13 @@
frappe.query_reports["Inactive Sales Items"] = {
"filters": [
{
fieldname: "territory",
label: __("Territory"),
fieldtype: "Link",
options: "Territory",
reqd: 1,
},
{
fieldname: "item",
label: __("Item"),

View File

@@ -7,13 +7,11 @@ from frappe.utils import getdate, add_days, today, cint
from frappe import _
def execute(filters=None):
columns = get_columns()
data = get_data(filters)
return columns, data
def get_columns():
columns = [
{
"fieldname": "territory",
@@ -74,36 +72,39 @@ def get_columns():
def get_data(filters):
data = []
items = get_items(filters)
territories = get_territories(filters)
sales_invoice_data = get_sales_details(filters)
for item in items:
row = {
for territory in territories:
for item in items:
row = {
"territory": territory.name,
"item_group": item.item_group,
"item": item.name,
"item_name": item.item_name
}
}
if sales_invoice_data.get(item.name):
item_obj = sales_invoice_data[item.name]
if item_obj.days_since_last_order > cint(filters['days']):
row.update({
"territory": item_obj.territory,
"customer": item_obj.customer,
"last_order_date": item_obj.last_order_date,
"qty": item_obj.qty,
"days_since_last_order": item_obj.days_since_last_order
})
if sales_invoice_data.get((territory.name,item.name)):
item_obj = sales_invoice_data[(territory.name,item.name)]
if item_obj.days_since_last_order > cint(filters['days']):
row.update({
"territory": item_obj.territory,
"customer": item_obj.customer,
"last_order_date": item_obj.last_order_date,
"qty": item_obj.qty,
"days_since_last_order": item_obj.days_since_last_order
})
else:
continue
data.append(row)
data.append(row)
return data
def get_sales_details(filters):
data = []
item_details_map = {}
@@ -118,12 +119,21 @@ def get_sales_details(filters):
.format(date_field = date_field, doctype = filters['based_on']), as_dict=1)
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
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 = {
"disabled": 0,
"is_stock_item": 1

View File

@@ -137,7 +137,7 @@ def get_appropriate_company(filters):
return company
@frappe.whitelist()
def get_invoiced_item_gross_margin(sales_invoice=None, item_code=None, company=None):
def get_invoiced_item_gross_margin(sales_invoice=None, item_code=None, company=None, with_item_data=False):
from erpnext.accounts.report.gross_profit.gross_profit import GrossProfitGenerator
sales_invoice = sales_invoice or frappe.form_dict.get('sales_invoice')
@@ -152,5 +152,8 @@ def get_invoiced_item_gross_margin(sales_invoice=None, item_code=None, company=N
}
gross_profit_data = GrossProfitGenerator(filters)
result = gross_profit_data.grouped_data
if not with_item_data:
result = sum([d.gross_profit for d in result])
return gross_profit_data.grouped_data
return result

View File

@@ -763,6 +763,9 @@ class AccountsController(TransactionBase):
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
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 self.get("payment_terms_template"):
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"))
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"):
grand_total = grand_total - flt(self.write_off_amount)
if total != grand_total:

View File

@@ -351,10 +351,12 @@ class StockController(AccountsController):
frappe.throw(_("Row {0}: Quality Inspection rejected for item {1}")
.format(d.idx, d.item_code), QualityInspectionRejectedError)
elif qa_required :
frappe.msgprint(_("Quality Inspection required for Item {0}").format(d.item_code))
if self.docstatus==1:
raise QualityInspectionRequiredError
action = frappe.get_doc('Stock Settings').action_if_quality_inspection_is_not_submitted
if self.docstatus==1 and action == 'Stop':
frappe.throw(_("Quality Inspection required for Item {0} to submit").format(frappe.bold(d.item_code)),
exc=QualityInspectionRequiredError)
else:
frappe.msgprint(_("Create Quality Inspection for Item {0}").format(frappe.bold(d.item_code)))
def update_blanket_order(self):
blanket_orders = list(set([d.blanket_order for d in self.items if d.blanket_order]))

View File

@@ -5,79 +5,79 @@ frappe.provide("erpnext");
cur_frm.email_field = "email_id";
erpnext.LeadController = frappe.ui.form.Controller.extend({
setup: function() {
this.frm.fields_dict.customer.get_query = function(doc, cdt, cdn) {
return { query: "erpnext.controllers.queries.customer_query" } }
setup: function () {
this.frm.fields_dict.customer.get_query = function (doc, cdt, cdn) {
return { query: "erpnext.controllers.queries.customer_query" }
}
this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead);
},
onload: function() {
if(cur_frm.fields_dict.lead_owner.df.options.match(/^User/)) {
cur_frm.fields_dict.lead_owner.get_query = function(doc, cdt, cdn) {
onload: function () {
if (cur_frm.fields_dict.lead_owner.df.options.match(/^User/)) {
cur_frm.fields_dict.lead_owner.get_query = function (doc, cdt, cdn) {
return { query: "frappe.core.doctype.user.user.user_query" }
}
}
if(cur_frm.fields_dict.contact_by.df.options.match(/^User/)) {
cur_frm.fields_dict.contact_by.get_query = function(doc, cdt, cdn) {
return { query: "frappe.core.doctype.user.user.user_query" } }
if (cur_frm.fields_dict.contact_by.df.options.match(/^User/)) {
cur_frm.fields_dict.contact_by.get_query = function (doc, cdt, cdn) {
return { query: "frappe.core.doctype.user.user.user_query" }
}
}
},
refresh: function() {
refresh: function () {
var doc = this.frm.doc;
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(__("Opportunity"), this.create_opportunity, __("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);
} else {
frappe.contacts.clear_address_and_contact(cur_frm);
}
},
create_customer: function() {
create_customer: function () {
frappe.model.open_mapped_doc({
method: "erpnext.crm.doctype.lead.lead.make_customer",
frm: cur_frm
})
},
create_opportunity: function() {
create_opportunity: function () {
frappe.model.open_mapped_doc({
method: "erpnext.crm.doctype.lead.lead.make_opportunity",
frm: cur_frm
})
},
make_quotation: function() {
make_quotation: function () {
frappe.model.open_mapped_doc({
method: "erpnext.crm.doctype.lead.lead.make_quotation",
frm: cur_frm
})
},
organization_lead: function() {
if (this.frm.doc.organization_lead == 1) {
this.frm.set_df_property('company_name', 'reqd', 1);
} else {
this.frm.set_df_property('company_name', 'reqd', 0);
}
organization_lead: function () {
this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead);
this.frm.toggle_reqd("company_name", this.frm.doc.organization_lead);
},
company_name: function() {
company_name: function () {
if (this.frm.doc.organization_lead == 1) {
this.frm.set_value("lead_name", this.frm.doc.company_name);
}
},
contact_date: function() {
contact_date: function () {
if (this.frm.doc.contact_date) {
let d = moment(this.frm.doc.contact_date);
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 }));

View File

@@ -141,7 +141,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"reqd": 0,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
@@ -499,7 +499,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Lead Owner",
"length": 0,
@@ -1389,7 +1389,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-10-02 09:12:23.415379",
"modified": "2019-05-10 03:22:57.283628",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lead",

View File

@@ -102,14 +102,18 @@ class Lead(SellingController):
def has_lost_quotation(self):
return frappe.db.get_value("Quotation", {
"lead": self.name,
"party_name": self.name,
"docstatus": 1,
"status": "Lost"
})
def set_lead_name(self):
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()
def make_customer(source_name, target_doc=None):
@@ -163,7 +167,7 @@ def make_quotation(source_name, target_doc=None):
{"Lead": {
"doctype": "Quotation",
"field_map": {
"name": "lead"
"name": "party_name"
}
}}, target_doc)
target_doc.quotation_to = "Lead"
@@ -225,4 +229,4 @@ def make_lead_from_communication(communication, ignore_communication_links=False
lead_name = lead.name
link_communication_to_document(doc, "Lead", lead_name, ignore_communication_links)
return lead_name
return lead_name

View File

@@ -8,6 +8,9 @@ def get_data():
'Quotation': 'party_name',
'Opportunity': 'party_name'
},
'dynamic_links': {
'party_name': ['Lead', 'quotation_to']
},
'transactions': [
{
'items': ['Opportunity', 'Quotation']

View File

@@ -136,7 +136,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Customer/Lead",
"label": "Party",
"length": 0,
"no_copy": 0,
"oldfieldname": "customer",
@@ -1468,7 +1468,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-04-25 18:55:43.874656",
"modified": "2019-05-11 19:22:33.533487",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",

View File

@@ -17,5 +17,13 @@ frappe.listview_settings['Opportunity'] = {
listview.page.add_menu_item(__("Set as Closed"), function() {
listview.call_for_selected_items(method, {"status": "Closed"});
});
listview.page.fields_dict.opportunity_from.get_query = function() {
return {
"filters": {
"name": ["in", ["Customer", "Lead"]],
}
};
};
}
};

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": 0,
"beta": 0,
"creation": "2013-01-10 16:34:15",
@@ -21,6 +21,7 @@
"collapsible": 0,
"columns": 0,
"default": "Today",
"fetch_if_empty": 0,
"fieldname": "posting_date",
"fieldtype": "Date",
"hidden": 0,
@@ -53,6 +54,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
@@ -88,6 +90,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.employee_name",
"fetch_if_empty": 0,
"fieldname": "employee_name",
"fieldtype": "Read Only",
"hidden": 0,
@@ -123,6 +126,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.department",
"fetch_if_empty": 0,
"fieldname": "department",
"fieldtype": "Link",
"hidden": 0,
@@ -159,6 +163,7 @@
"columns": 0,
"depends_on": "eval:doc.designation",
"fetch_from": "employee.designation",
"fetch_if_empty": 0,
"fieldname": "designation",
"fieldtype": "Read Only",
"hidden": 0,
@@ -194,6 +199,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.branch",
"fetch_if_empty": 0,
"fieldname": "branch",
"fieldtype": "Link",
"hidden": 0,
@@ -228,6 +234,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"hidden": 0,
@@ -260,6 +267,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
@@ -293,6 +301,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "journal_entry",
"fieldtype": "Link",
"hidden": 0,
@@ -326,6 +335,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "payroll_entry",
"fieldtype": "Link",
"hidden": 0,
@@ -359,6 +369,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -391,6 +402,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "letter_head",
"fieldtype": "Link",
"hidden": 0,
@@ -423,6 +435,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_10",
"fieldtype": "Section Break",
"hidden": 0,
@@ -455,6 +468,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "salary_slip_based_on_timesheet",
"fieldtype": "Check",
"hidden": 0,
@@ -489,6 +503,7 @@
"collapsible": 0,
"columns": 0,
"default": "",
"fetch_if_empty": 0,
"fieldname": "start_date",
"fieldtype": "Date",
"hidden": 0,
@@ -523,6 +538,7 @@
"columns": 0,
"default": "",
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "end_date",
"fieldtype": "Date",
"hidden": 0,
@@ -555,6 +571,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_15",
"fieldtype": "Column Break",
"hidden": 0,
@@ -587,6 +604,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "salary_structure",
"fieldtype": "Link",
"hidden": 0,
@@ -622,6 +640,7 @@
"columns": 0,
"default": "",
"depends_on": "eval:(!doc.salary_slip_based_on_timesheet)",
"fetch_if_empty": 0,
"fieldname": "payroll_frequency",
"fieldtype": "Select",
"hidden": 0,
@@ -656,6 +675,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "total_working_days",
"fieldtype": "Float",
"hidden": 0,
@@ -690,6 +710,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "leave_without_pay",
"fieldtype": "Float",
"hidden": 0,
@@ -724,6 +745,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "payment_days",
"fieldtype": "Float",
"hidden": 0,
@@ -758,6 +780,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "hourly_wages",
"fieldtype": "Section Break",
"hidden": 0,
@@ -791,6 +814,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "timesheets",
"fieldtype": "Table",
"hidden": 0,
@@ -824,6 +848,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_20",
"fieldtype": "Column Break",
"hidden": 0,
@@ -855,6 +880,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_working_hours",
"fieldtype": "Float",
"hidden": 0,
@@ -887,6 +913,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "hour_rate",
"fieldtype": "Currency",
"hidden": 0,
@@ -921,6 +948,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "section_break_26",
"fieldtype": "Section Break",
"hidden": 0,
@@ -953,6 +981,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "bank_name",
"fieldtype": "Data",
"hidden": 0,
@@ -986,6 +1015,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "bank_account_no",
"fieldtype": "Data",
"hidden": 0,
@@ -1019,6 +1049,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_01",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1050,6 +1081,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -1084,6 +1116,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_32",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1115,6 +1148,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "deduct_tax_for_unclaimed_employee_benefits",
"fieldtype": "Check",
"hidden": 0,
@@ -1147,6 +1181,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "deduct_tax_for_unsubmitted_tax_exemption_proof",
"fieldtype": "Check",
"hidden": 0,
@@ -1179,6 +1214,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "earning_deduction",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1211,6 +1247,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "earning",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1245,6 +1282,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "earnings",
"fieldtype": "Table",
"hidden": 0,
@@ -1279,6 +1317,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "deduction",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1312,6 +1351,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "deductions",
"fieldtype": "Table",
"hidden": 0,
@@ -1346,6 +1386,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "totals",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1378,6 +1419,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "gross_pay",
"fieldtype": "Currency",
"hidden": 0,
@@ -1412,6 +1454,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_25",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1442,6 +1485,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_deduction",
"fieldtype": "Currency",
"hidden": 0,
@@ -1477,6 +1521,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "total_loan_repayment",
"fetch_if_empty": 0,
"fieldname": "loan_repayment",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1509,6 +1554,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "loans",
"fieldtype": "Table",
"hidden": 0,
@@ -1542,6 +1588,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_43",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1574,6 +1621,7 @@
"collapsible": 0,
"columns": 0,
"default": "0",
"fetch_if_empty": 0,
"fieldname": "total_principal_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -1608,6 +1656,7 @@
"collapsible": 0,
"columns": 0,
"default": "0",
"fetch_if_empty": 0,
"fieldname": "total_interest_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -1641,6 +1690,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_45",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1673,6 +1723,7 @@
"collapsible": 0,
"columns": 0,
"default": "0",
"fetch_if_empty": 0,
"fieldname": "total_loan_repayment",
"fieldtype": "Currency",
"hidden": 0,
@@ -1706,6 +1757,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "net_pay_info",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1739,6 +1791,7 @@
"collapsible": 0,
"columns": 0,
"description": "Gross Pay - Total Deduction - Loan Repayment",
"fetch_if_empty": 0,
"fieldname": "net_pay",
"fieldtype": "Currency",
"hidden": 0,
@@ -1773,6 +1826,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_53",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1804,6 +1858,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "rounded_total",
"fieldtype": "Currency",
"hidden": 0,
@@ -1836,6 +1891,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_55",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1868,6 +1924,7 @@
"collapsible": 0,
"columns": 0,
"description": "Net Pay (in words) will be visible once you save the Salary Slip.",
"fetch_if_empty": 0,
"fieldname": "total_in_words",
"fieldtype": "Data",
"hidden": 0,
@@ -1906,7 +1963,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-02-18 18:54:36.161027",
"modified": "2019-05-08 20:16:21.549386",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Slip",

View File

@@ -5,9 +5,19 @@
from __future__ import unicode_literals
import frappe
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
class TrainingEvent(Document):
def validate(self):
self.set_employee_emails()
self.validate_period()
def set_employee_emails(self):
self.employee_emails = ', '.join(get_employee_emails([d.employee
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'))

View File

@@ -592,9 +592,11 @@ 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.set_default_action_for_quality_inspection
erpnext.patches.v11_1.delete_bom_browser
erpnext.patches.v11_1.set_salary_details_submittable
erpnext.patches.v11_1.rename_depends_on_lwp
erpnext.patches.v11_1.set_missing_title_for_quotation
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

View File

@@ -0,0 +1,10 @@
# 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():
stock_settings = frappe.get_doc('Stock Settings')
stock_settings.action_if_quality_inspection_is_not_submitted = "Stop"
stock_settings.save()

View 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
""")

View File

@@ -442,16 +442,17 @@ def daily_reminder():
projects = get_projects_for_collect_progress("Daily", fields)
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)
def twice_daily_reminder():
fields = ["first_email", "second_email"]
projects = get_projects_for_collect_progress("Twice Daily", fields)
fields.remove("name")
for project in projects:
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)
def weekly_reminder():
@@ -463,14 +464,19 @@ def weekly_reminder():
if current_day != project.day_to_send:
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)
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`
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):
fields.extend(["name"])

View File

@@ -429,6 +429,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
set_warehouse: me.frm.doc.set_warehouse,
warehouse: item.warehouse,
customer: me.frm.doc.customer || me.frm.doc.party_name,
quotation_to: me.frm.doc.quotation_to,
supplier: me.frm.doc.supplier,
currency: me.frm.doc.currency,
update_stock: update_stock,

View File

@@ -10,6 +10,9 @@ def get_data():
'Quotation': 'party_name',
'Opportunity': 'party_name'
},
'dynamic_links': {
'party_name': ['Customer', 'quotation_to']
},
'transactions': [
{
'label': _('Pre Sales'),

View File

@@ -133,7 +133,7 @@
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"in_standard_filter": 1,
"label": "Quotation To",
"length": 0,
"no_copy": 0,
@@ -169,7 +169,7 @@
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"in_standard_filter": 1,
"label": "Party",
"length": 0,
"no_copy": 0,
@@ -3224,7 +3224,7 @@
"istable": 0,
"max_attachments": 1,
"menu_index": 0,
"modified": "2019-05-07 14:29:22.565474",
"modified": "2019-05-11 19:26:50.735628",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",

View File

@@ -1,6 +1,17 @@
frappe.listview_settings['Quotation'] = {
add_fields: ["customer_name", "base_grand_total", "status",
"company", "currency", 'valid_till'],
onload: function(listview) {
listview.page.fields_dict.quotation_to.get_query = function() {
return {
"filters": {
"name": ["in", ["Customer", "Lead"]],
}
};
};
},
get_indicator: function(doc) {
if(doc.status==="Submitted") {
if (doc.valid_till && doc.valid_till < frappe.datetime.nowdate()) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -122,6 +122,10 @@ class StockEntry(StockController):
if self.purpose not in valid_purposes:
frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes)))
if self.job_card and self.purpose != 'Material Transfer for Manufacture':
frappe.throw(_("For job card {0}, you can only make the 'Material Transfer for Manufacture' type stock entry")
.format(self.job_card))
def set_transfer_qty(self):
for item in self.get("items"):
if not flt(item.qty):

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -14,11 +15,13 @@
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Item Code",
"fetch_if_empty": 0,
"fieldname": "item_naming_by",
"fieldtype": "Select",
"hidden": 0,
@@ -41,15 +44,18 @@
"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,
"description": "",
"fetch_if_empty": 0,
"fieldname": "item_group",
"fieldtype": "Link",
"hidden": 0,
@@ -72,14 +78,17 @@
"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_if_empty": 0,
"fieldname": "stock_uom",
"fieldtype": "Link",
"hidden": 0,
@@ -102,14 +111,17 @@
"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_if_empty": 0,
"fieldname": "default_warehouse",
"fieldtype": "Link",
"hidden": 0,
@@ -133,14 +145,17 @@
"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_if_empty": 0,
"fieldname": "sample_retention_warehouse",
"fieldtype": "Link",
"hidden": 0,
@@ -164,14 +179,17 @@
"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_if_empty": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
@@ -192,14 +210,17 @@
"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_if_empty": 0,
"fieldname": "valuation_method",
"fieldtype": "Select",
"hidden": 0,
@@ -222,15 +243,18 @@
"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,
"description": "Percentage you are allowed to receive or deliver more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to receive 110 units.",
"fetch_if_empty": 0,
"fieldname": "tolerance",
"fieldtype": "Float",
"hidden": 0,
@@ -252,15 +276,53 @@
"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,
"default": "Stop",
"fetch_if_empty": 0,
"fieldname": "action_if_quality_inspection_is_not_submitted",
"fieldtype": "Select",
"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": "Action if Quality inspection is not submitted",
"length": 0,
"no_copy": 0,
"options": "Stop\nWarn",
"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,
"default": "1",
"fetch_if_empty": 0,
"fieldname": "show_barcode_field",
"fieldtype": "Check",
"hidden": 0,
@@ -283,15 +345,18 @@
"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,
"default": "1",
"fetch_if_empty": 0,
"fieldname": "clean_description_html",
"fieldtype": "Check",
"hidden": 0,
@@ -314,14 +379,17 @@
"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_if_empty": 0,
"fieldname": "section_break_7",
"fieldtype": "Section Break",
"hidden": 0,
@@ -343,14 +411,17 @@
"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_if_empty": 0,
"fieldname": "auto_insert_price_list_rate_if_missing",
"fieldtype": "Check",
"hidden": 0,
@@ -373,14 +444,17 @@
"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_if_empty": 0,
"fieldname": "allow_negative_stock",
"fieldtype": "Check",
"hidden": 0,
@@ -402,14 +476,17 @@
"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_if_empty": 0,
"fieldname": "column_break_10",
"fieldtype": "Column Break",
"hidden": 0,
@@ -431,15 +508,18 @@
"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,
"default": "1",
"fetch_if_empty": 0,
"fieldname": "automatically_set_serial_nos_based_on_fifo",
"fieldtype": "Check",
"hidden": 0,
@@ -462,15 +542,18 @@
"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,
"default": "1",
"fetch_if_empty": 0,
"fieldname": "set_qty_in_transactions_based_on_serial_no_input",
"fieldtype": "Check",
"hidden": 0,
@@ -493,14 +576,17 @@
"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_if_empty": 0,
"fieldname": "auto_material_request",
"fieldtype": "Section Break",
"hidden": 0,
@@ -522,14 +608,17 @@
"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_if_empty": 0,
"fieldname": "auto_indent",
"fieldtype": "Check",
"hidden": 0,
@@ -551,14 +640,17 @@
"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_if_empty": 0,
"fieldname": "reorder_email_notify",
"fieldtype": "Check",
"hidden": 0,
@@ -580,14 +672,17 @@
"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_if_empty": 0,
"fieldname": "freeze_stock_entries",
"fieldtype": "Section Break",
"hidden": 0,
@@ -609,14 +704,17 @@
"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_if_empty": 0,
"fieldname": "stock_frozen_upto",
"fieldtype": "Date",
"hidden": 0,
@@ -638,14 +736,17 @@
"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_if_empty": 0,
"fieldname": "stock_frozen_upto_days",
"fieldtype": "Int",
"hidden": 0,
@@ -667,14 +768,17 @@
"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_if_empty": 0,
"fieldname": "stock_auth_role",
"fieldtype": "Link",
"hidden": 0,
@@ -697,14 +801,17 @@
"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_if_empty": 0,
"fieldname": "batch_id_sb",
"fieldtype": "Section Break",
"hidden": 0,
@@ -727,15 +834,18 @@
"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,
"default": "0",
"fetch_if_empty": 0,
"fieldname": "use_naming_series",
"fieldtype": "Check",
"hidden": 0,
@@ -758,16 +868,19 @@
"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,
"default": "BATCH-",
"depends_on": "eval:doc.use_naming_series==1",
"fetch_if_empty": 0,
"fieldname": "naming_series_prefix",
"fieldtype": "Data",
"hidden": 0,
@@ -790,6 +903,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
@@ -804,7 +918,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2018-05-03 12:38:12.905394",
"modified": "2019-04-18 12:33:08.040078",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Settings",
@@ -812,7 +926,6 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
@@ -837,5 +950,6 @@
"show_name_in_global_search": 0,
"sort_order": "ASC",
"track_changes": 0,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe.utils import cint
from frappe.utils import cint, nowdate
from frappe import throw, _
from frappe.utils.nestedset import NestedSet
from erpnext.stock import get_warehouse_account
@@ -140,7 +140,7 @@ class Warehouse(NestedSet):
@frappe.whitelist()
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:
parent = ""
@@ -156,7 +156,7 @@ def get_children(doctype, parent=None, company=None, is_root=False):
# return 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:
wh["company_currency"] = frappe.db.get_value('Company', company, 'default_currency')
return warehouses

View File

@@ -573,6 +573,10 @@ def validate_conversion_rate(args, meta):
def get_party_item_code(args, item_doc, out):
if args.transaction_type=="selling" and args.customer:
out.customer_item_code = None
if args.quotation_to != 'Customer':
return
customer_item_code = item_doc.get("customer_items", {"customer_name": args.customer})
if customer_item_code:

View File

@@ -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
},
]
}

View File

@@ -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"
}
]
}

View File

@@ -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
}]

View File

@@ -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
},
]
}

View File

@@ -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"
}
]
}

View File

@@ -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
}]