Merge branch 'develop' into supplier_items
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index cb88a11..2490f3b 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '11.1.39'
+__version__ = '12.0.8'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
index 5cea0d1..88b11dd 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
@@ -40,9 +40,16 @@
},
document_type: function(frm) {
+
frm.set_value('label', frm.doc.document_type);
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type));
+ if (frm.is_new()){
+ let row = frappe.model.add_child(frm.doc, "Accounting Dimension Detail", "dimension_defaults");
+ row.reference_document = frm.doc.document_type;
+ frm.refresh_fields("dimension_defaults");
+ }
+
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
if (r && r.document_type) {
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index f943b34..b8ebeba 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -45,12 +45,12 @@
def clear_linked_payment_entries(self):
for payment_entry in self.payment_entries:
allocated_amount = get_total_allocated_amount(payment_entry)
- paid_amount = get_paid_amount(payment_entry)
+ paid_amount = get_paid_amount(payment_entry, self.currency)
if paid_amount and allocated_amount:
if flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount):
frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).".format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount))))
- elif flt(allocated_amount[0]["allocated_amount"]) == flt(paid_amount):
+ else:
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
self.clear_simple_entry(payment_entry)
@@ -80,9 +80,17 @@
AND
bt.docstatus = 1""", (payment_entry.payment_document, payment_entry.payment_entry), as_dict=True)
-def get_paid_amount(payment_entry):
+def get_paid_amount(payment_entry, currency):
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
- return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "paid_amount")
+
+ paid_amount_field = "paid_amount"
+ if payment_entry.payment_document == 'Payment Entry':
+ doc = frappe.get_doc("Payment Entry", payment_entry.payment_entry)
+ paid_amount_field = ("base_paid_amount"
+ if doc.paid_to_account_currency == currency else "paid_amount")
+
+ return frappe.db.get_value(payment_entry.payment_document,
+ payment_entry.payment_entry, paid_amount_field)
elif payment_entry.payment_document == "Journal Entry":
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_credit")
diff --git a/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json b/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json
index 8d7ed74..04d6303 100644
--- a/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json
+++ b/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json
@@ -8,7 +8,8 @@
"customer",
"column_break_3",
"posting_date",
- "outstanding_amount"
+ "outstanding_amount",
+ "debit_to"
],
"fields": [
{
@@ -48,10 +49,18 @@
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "sales_invoice.debit_to",
+ "fieldname": "debit_to",
+ "fieldtype": "Link",
+ "label": "Debit to",
+ "options": "Account",
+ "read_only": 1
}
],
"istable": 1,
- "modified": "2019-05-30 19:27:29.436153",
+ "modified": "2019-08-07 15:13:55.808349",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Discounted Invoice",
diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js
index 5563f03..f1f88a8 100644
--- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js
+++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js
@@ -13,41 +13,57 @@
};
});
- frm.events.filter_accounts("bank_account", frm, {"account_type": "Bank"});
- frm.events.filter_accounts("bank_charges_account", frm, {"root_type": "Expense"});
- frm.events.filter_accounts("short_term_loan", frm, {"root_type": "Liability"});
- frm.events.filter_accounts("accounts_receivable_credit", frm, {"account_type": "Receivable"});
- frm.events.filter_accounts("accounts_receivable_discounted", frm, {"account_type": "Receivable"});
- frm.events.filter_accounts("accounts_receivable_unpaid", frm, {"account_type": "Receivable"});
+
+ frm.events.filter_accounts("bank_account", frm, [["account_type", "=", "Bank"]]);
+ frm.events.filter_accounts("bank_charges_account", frm, [["root_type", "=", "Expense"]]);
+ frm.events.filter_accounts("short_term_loan", frm, [["root_type", "=", "Liability"]]);
+ frm.events.filter_accounts("accounts_receivable_discounted", frm, [["account_type", "=", "Receivable"]]);
+ frm.events.filter_accounts("accounts_receivable_credit", frm, [["account_type", "=", "Receivable"]]);
+ frm.events.filter_accounts("accounts_receivable_unpaid", frm, [["account_type", "=", "Receivable"]]);
},
filter_accounts: (fieldname, frm, addl_filters) => {
- let filters = {
- "company": frm.doc.company,
- "is_group": 0
- };
- if(addl_filters) Object.assign(filters, addl_filters);
+ let filters = [
+ ["company", "=", frm.doc.company],
+ ["is_group", "=", 0]
+ ];
+ if(addl_filters){
+ filters = $.merge(filters , addl_filters);
+ }
frm.set_query(fieldname, () => { return { "filters": filters }; });
},
+ refresh_filters: (frm) =>{
+ let invoice_accounts = Object.keys(frm.doc.invoices).map(function(key) {
+ return frm.doc.invoices[key].debit_to;
+ });
+ let filters = [
+ ["account_type", "=", "Receivable"],
+ ["name", "not in", invoice_accounts]
+ ];
+ frm.events.filter_accounts("accounts_receivable_credit", frm, filters);
+ frm.events.filter_accounts("accounts_receivable_discounted", frm, filters);
+ frm.events.filter_accounts("accounts_receivable_unpaid", frm, filters);
+ },
+
refresh: (frm) => {
frm.events.show_general_ledger(frm);
- if(frm.doc.docstatus === 0) {
+ if (frm.doc.docstatus === 0) {
frm.add_custom_button(__('Get Invoices'), function() {
frm.events.get_invoices(frm);
});
}
- if(frm.doc.docstatus === 1 && frm.doc.status !== "Settled") {
- if(frm.doc.status == "Sanctioned") {
+ if (frm.doc.docstatus === 1 && frm.doc.status !== "Settled") {
+ if (frm.doc.status == "Sanctioned") {
frm.add_custom_button(__('Disburse Loan'), function() {
frm.events.create_disbursement_entry(frm);
}).addClass("btn-primary");
}
- if(frm.doc.status == "Disbursed") {
+ if (frm.doc.status == "Disbursed") {
frm.add_custom_button(__('Close Loan'), function() {
frm.events.close_loan(frm);
}).addClass("btn-primary");
@@ -64,7 +80,7 @@
},
set_end_date: (frm) => {
- if(frm.doc.loan_start_date && frm.doc.loan_period) {
+ if (frm.doc.loan_start_date && frm.doc.loan_period) {
let end_date = frappe.datetime.add_days(frm.doc.loan_start_date, frm.doc.loan_period);
frm.set_value("loan_end_date", end_date);
}
@@ -132,6 +148,7 @@
frm.doc.invoices = frm.doc.invoices.filter(row => row.sales_invoice);
let row = frm.add_child("invoices");
$.extend(row, v);
+ frm.events.refresh_filters(frm);
});
refresh_field("invoices");
}
@@ -190,8 +207,10 @@
frappe.ui.form.on('Discounted Invoice', {
sales_invoice: (frm) => {
frm.events.calculate_total_amount(frm);
+ frm.events.refresh_filters(frm);
},
invoices_remove: (frm) => {
frm.events.calculate_total_amount(frm);
+ frm.events.refresh_filters(frm);
}
-});
\ No newline at end of file
+});
diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
index 29475d5..36c2911 100644
--- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
+++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
@@ -12,6 +12,7 @@
class InvoiceDiscounting(AccountsController):
def validate(self):
self.validate_mandatory()
+ self.validate_invoices()
self.calculate_total_amount()
self.set_status()
self.set_end_date()
@@ -24,6 +25,15 @@
if self.docstatus == 1 and not (self.loan_start_date and self.loan_period):
frappe.throw(_("Loan Start Date and Loan Period are mandatory to save the Invoice Discounting"))
+ def validate_invoices(self):
+ discounted_invoices = [record.sales_invoice for record in
+ frappe.get_all("Discounted Invoice",fields = ["sales_invoice"], filters= {"docstatus":1})]
+
+ for record in self.invoices:
+ if record.sales_invoice in discounted_invoices:
+ frappe.throw("Row({0}): {1} is already discounted in {2}"
+ .format(record.idx, frappe.bold(record.sales_invoice), frappe.bold(record.parent)))
+
def calculate_total_amount(self):
self.total_amount = sum([flt(d.outstanding_amount) for d in self.invoices])
@@ -212,7 +222,8 @@
name as sales_invoice,
customer,
posting_date,
- outstanding_amount
+ outstanding_amount,
+ debit_to
from `tabSales Invoice` si
where
docstatus = 1
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 8098329..6bd8d29 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -624,8 +624,8 @@
data = negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
if not data:
- frappe.msgprint(_("No outstanding invoices found for the {0} <b>{1}</b> which qualify the filters you have specified.")
- .format(args.get("party_type").lower(), args.get("party")))
+ frappe.msgprint(_("No outstanding invoices found for the {0} {1} which qualify the filters you have specified.")
+ .format(args.get("party_type").lower(), frappe.bold(args.get("party"))))
return data
diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js
index f2f00ce..ce9cfe5 100644
--- a/erpnext/accounts/doctype/payment_order/payment_order.js
+++ b/erpnext/accounts/doctype/payment_order/payment_order.js
@@ -66,6 +66,7 @@
get_query_filters: {
bank: frm.doc.bank,
docstatus: 1,
+ payment_type: ("!=", "Receive"),
bank_account: frm.doc.company_bank_account,
paid_from: frm.doc.account,
payment_order_status: ["=", "Initiated"],
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index b74eed5..4665d75 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -93,7 +93,7 @@
and `tab{doc}`.is_return = 1 and `tabGL Entry`.against_voucher_type = %(voucher_type)s
and `tab{doc}`.docstatus = 1 and `tabGL Entry`.party = %(party)s
and `tabGL Entry`.party_type = %(party_type)s and `tabGL Entry`.account = %(account)s
- GROUP BY `tabSales Invoice`.name
+ GROUP BY `tab{doc}`.name
Having
amount > 0
""".format(doc=voucher_type, dr_or_cr=dr_or_cr, reconciled_dr_or_cr=reconciled_dr_or_cr), {
@@ -257,11 +257,8 @@
voucher_type = ('Credit Note'
if d.voucher_type == 'Sales Invoice' else 'Debit Note')
- dr_or_cr = ('credit_in_account_currency'
- if d.reference_type == 'Sales Invoice' else 'debit_in_account_currency')
-
reconcile_dr_or_cr = ('debit_in_account_currency'
- if dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
+ if d.dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
jv = frappe.get_doc({
"doctype": "Journal Entry",
@@ -272,8 +269,7 @@
'account': d.account,
'party': d.party,
'party_type': d.party_type,
- reconcile_dr_or_cr: (abs(d.allocated_amount)
- if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
+ d.dr_or_cr: abs(d.allocated_amount),
'reference_type': d.against_voucher_type,
'reference_name': d.against_voucher
},
@@ -281,7 +277,8 @@
'account': d.account,
'party': d.party,
'party_type': d.party_type,
- dr_or_cr: abs(d.allocated_amount),
+ reconcile_dr_or_cr: (abs(d.allocated_amount)
+ if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
'reference_type': d.voucher_type,
'reference_name': d.voucher_no
}
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index e2f99d6..e290b23 100755
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -307,7 +307,7 @@
# example: {'Consulting Services': {'Excise 12 - TS': '12.000'}}
itemwise_tax = {}
- taxes = frappe.db.sql(""" select parent, tax_type, tax_rate from `tabItem Tax`""", as_dict=1)
+ taxes = frappe.db.sql(""" select parent, tax_type, tax_rate from `tabItem Tax Template Detail`""", as_dict=1)
for tax in taxes:
if tax.parent not in itemwise_tax:
@@ -432,7 +432,6 @@
return cust_id
-
def make_customer_and_address(customers):
customers_list = []
for customer, data in iteritems(customers):
@@ -449,7 +448,6 @@
frappe.db.commit()
return customers_list
-
def add_customer(data):
customer = data.get('full_name') or data.get('customer')
if frappe.db.exists("Customer", customer.strip()):
@@ -466,21 +464,18 @@
frappe.db.commit()
return customer_doc.name
-
def get_territory(data):
if data.get('territory'):
return data.get('territory')
return frappe.db.get_single_value('Selling Settings','territory') or _('All Territories')
-
def get_customer_group(data):
if data.get('customer_group'):
return data.get('customer_group')
return frappe.db.get_single_value('Selling Settings', 'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name')
-
def make_contact(args, customer):
if args.get('email_id') or args.get('phone'):
name = frappe.db.get_value('Dynamic Link',
@@ -506,7 +501,6 @@
doc.flags.ignore_mandatory = True
doc.save(ignore_permissions=True)
-
def make_address(args, customer):
if not args.get('address_line1'):
return
@@ -521,7 +515,10 @@
address = frappe.get_doc('Address', name)
else:
address = frappe.new_doc('Address')
- address.country = frappe.get_cached_value('Company', args.get('company'), 'country')
+ if args.get('company'):
+ address.country = frappe.get_cached_value('Company',
+ args.get('company'), 'country')
+
address.append('links', {
'link_doctype': 'Customer',
'link_name': customer
@@ -533,7 +530,6 @@
address.flags.ignore_mandatory = True
address.save(ignore_permissions=True)
-
def make_email_queue(email_queue):
name_list = []
for key, data in iteritems(email_queue):
@@ -550,7 +546,6 @@
return name_list
-
def validate_item(doc):
for item in doc.get('items'):
if not frappe.db.exists('Item', item.get('item_code')):
@@ -569,7 +564,6 @@
item_doc.save(ignore_permissions=True)
frappe.db.commit()
-
def submit_invoice(si_doc, name, doc, name_list):
try:
si_doc.insert()
@@ -585,7 +579,6 @@
return name_list
-
def save_invoice(doc, name, name_list):
try:
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 8742300..95c5dd5 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -78,6 +78,7 @@
self.so_dn_required()
self.validate_proj_cust()
+ self.validate_pos_return()
self.validate_with_previous_doc()
self.validate_uom_is_integer("stock_uom", "stock_qty")
self.validate_uom_is_integer("uom", "qty")
@@ -199,6 +200,16 @@
if "Healthcare" in active_domains:
manage_invoice_submit_cancel(self, "on_submit")
+ def validate_pos_return(self):
+
+ if self.is_pos and self.is_return:
+ total_amount_in_payments = 0
+ for payment in self.payments:
+ total_amount_in_payments += payment.amount
+ invoice_total = self.rounded_total or self.grand_total
+ if total_amount_in_payments < invoice_total:
+ frappe.throw(_("Total payments amount can't be greater than {}".format(-invoice_total)))
+
def validate_pos_paid_amount(self):
if len(self.payments) == 0 and self.is_pos:
frappe.throw(_("At least one mode of payment is required for POS invoice."))
@@ -1499,4 +1510,4 @@
"outstanding_amount": invoice.outstanding_amount
})
- return invoice_discounting
\ No newline at end of file
+ return invoice_discounting
diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
index 36c9399..bd4b4d7 100644
--- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
@@ -124,8 +124,6 @@
'txt': '%%%s%%' % amount
}, as_dict=True)
- frappe.errprint(journal_entries)
-
if transaction.credit > 0:
sales_invoices = frappe.db.sql("""
SELECT
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index 3834c96..b5a02d0 100755
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -1762,18 +1762,11 @@
this.si_docs = this.get_submitted_invoice() || [];
this.email_queue_list = this.get_email_queue() || {};
this.customers_list = this.get_customers_details() || {};
- if(this.customer_doc) {
- this.freeze = this.customer_doc.display
- }
- freeze_screen = this.freeze_screen || false;
-
- if ((this.si_docs.length || this.email_queue_list || this.customers_list) && !this.freeze) {
- this.freeze = true;
-
+ if (this.si_docs.length || this.email_queue_list || this.customers_list) {
frappe.call({
method: "erpnext.accounts.doctype.sales_invoice.pos.make_invoice",
- freeze: freeze_screen,
+ freeze: true,
args: {
doc_list: me.si_docs,
email_queue_list: me.email_queue_list,
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 97e7104..0e4ee12 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -197,8 +197,10 @@
if self.filters.based_on_payment_terms and gl_entries_data:
self.payment_term_map = self.get_payment_term_detail(voucher_nos)
+ self.gle_inclusion_map = {}
for gle in gl_entries_data:
if self.is_receivable_or_payable(gle, self.dr_or_cr, future_vouchers, return_entries):
+ self.gle_inclusion_map[gle.name] = True
outstanding_amount, credit_note_amount, payment_amount = self.get_outstanding_amount(
gle,self.filters.report_date, self.dr_or_cr, return_entries)
temp_outstanding_amt = outstanding_amount
@@ -409,7 +411,9 @@
for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no):
if getdate(e.posting_date) <= report_date \
and (e.name!=gle.name or (e.voucher_no in return_entries and not return_entries.get(e.voucher_no))):
-
+ if e.name!=gle.name and self.gle_inclusion_map.get(e.name):
+ continue
+ self.gle_inclusion_map[e.name] = True
amount = flt(e.get(reverse_dr_or_cr), self.currency_precision) - flt(e.get(dr_or_cr), self.currency_precision)
if e.voucher_no not in return_entries:
payment_amount += amount
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 86fd108..ec3fb1f 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -119,19 +119,11 @@
select_fields = """, debit, credit, debit_in_account_currency,
credit_in_account_currency """
- group_by_statement = ''
order_by_statement = "order by posting_date, account"
if filters.get("group_by") == _("Group by Voucher"):
order_by_statement = "order by posting_date, voucher_type, voucher_no"
- if filters.get("group_by") == _("Group by Voucher (Consolidated)"):
- group_by_statement = "group by voucher_type, voucher_no, account, cost_center"
-
- select_fields = """, sum(debit) as debit, sum(credit) as credit,
- sum(debit_in_account_currency) as debit_in_account_currency,
- sum(credit_in_account_currency) as credit_in_account_currency"""
-
if filters.get("include_default_book_entries"):
filters['company_fb'] = frappe.db.get_value("Company",
filters.get("company"), 'default_finance_book')
@@ -144,11 +136,10 @@
against_voucher_type, against_voucher, account_currency,
remarks, against, is_opening {select_fields}
from `tabGL Entry`
- where company=%(company)s {conditions} {group_by_statement}
+ where company=%(company)s {conditions}
{order_by_statement}
""".format(
select_fields=select_fields, conditions=get_conditions(filters),
- group_by_statement=group_by_statement,
order_by_statement=order_by_statement
),
filters, as_dict=1)
@@ -185,7 +176,8 @@
if not (filters.get("account") or filters.get("party") or
filters.get("group_by") in ["Group by Account", "Group by Party"]):
conditions.append("posting_date >=%(from_date)s")
- conditions.append("posting_date <=%(to_date)s")
+
+ conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')")
if filters.get("project"):
conditions.append("project in %(project)s")
@@ -286,6 +278,7 @@
def get_accountwise_gle(filters, gl_entries, gle_map):
totals = get_totals_dict()
entries = []
+ consolidated_gle = OrderedDict()
group_by = group_by_field(filters.get('group_by'))
def update_value_in_dict(data, key, gle):
@@ -310,12 +303,20 @@
update_value_in_dict(totals, 'total', gle)
if filters.get("group_by") != _('Group by Voucher (Consolidated)'):
gle_map[gle.get(group_by)].entries.append(gle)
- else:
- entries.append(gle)
+ elif filters.get("group_by") == _('Group by Voucher (Consolidated)'):
+ key = (gle.get("voucher_type"), gle.get("voucher_no"),
+ gle.get("account"), gle.get("cost_center"))
+ if key not in consolidated_gle:
+ consolidated_gle.setdefault(key, gle)
+ else:
+ update_value_in_dict(consolidated_gle, key, gle)
update_value_in_dict(gle_map[gle.get(group_by)].totals, 'closing', gle)
update_value_in_dict(totals, 'closing', gle)
+ for key, value in consolidated_gle.items():
+ entries.append(value)
+
return totals, entries
def get_result_as_list(data, filters):
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index 2d78d26..c5cad73 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -303,14 +303,17 @@
},
set_depreciation_rate: function(frm, row) {
- if (row.total_number_of_depreciations && row.frequency_of_depreciation) {
+ if (row.total_number_of_depreciations && row.frequency_of_depreciation
+ && row.expected_value_after_useful_life) {
frappe.call({
method: "get_depreciation_rate",
doc: frm.doc,
args: row,
callback: function(r) {
if (r.message) {
- frappe.model.set_value(row.doctype, row.name, "rate_of_depreciation", r.message);
+ frappe.flags.dont_change_rate = true;
+ frappe.model.set_value(row.doctype, row.name,
+ "rate_of_depreciation", flt(r.message, precision("rate_of_depreciation", row)));
}
}
});
@@ -338,6 +341,14 @@
total_number_of_depreciations: function(frm, cdt, cdn) {
const row = locals[cdt][cdn];
frm.events.set_depreciation_rate(frm, row);
+ },
+
+ rate_of_depreciation: function(frm, cdt, cdn) {
+ if(!frappe.flags.dont_change_rate) {
+ frappe.model.set_value(cdt, cdn, "expected_value_after_useful_life", 0);
+ }
+
+ frappe.flags.dont_change_rate = false;
}
});
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index c398a73..ab37e91 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -6,7 +6,7 @@
import frappe, erpnext, math, json
from frappe import _
from six import string_types
-from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff
+from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff, add_days
from frappe.model.document import Document
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
from erpnext.assets.doctype.asset.depreciation \
@@ -101,97 +101,88 @@
def set_depreciation_rate(self):
for d in self.get("finance_books"):
- d.rate_of_depreciation = self.get_depreciation_rate(d, on_validate=True)
+ d.rate_of_depreciation = flt(self.get_depreciation_rate(d, on_validate=True),
+ d.precision("rate_of_depreciation"))
def make_depreciation_schedule(self):
- depreciation_method = [d.depreciation_method for d in self.finance_books]
-
- if 'Manual' not in depreciation_method:
+ if 'Manual' not in [d.depreciation_method for d in self.finance_books]:
self.schedules = []
- if not self.get("schedules") and self.available_for_use_date:
- total_depreciations = sum([d.total_number_of_depreciations for d in self.get('finance_books')])
+ if self.get("schedules") or not self.available_for_use_date:
+ return
- for d in self.get('finance_books'):
- self.validate_asset_finance_books(d)
+ for d in self.get('finance_books'):
+ self.validate_asset_finance_books(d)
- value_after_depreciation = (flt(self.gross_purchase_amount) -
- flt(self.opening_accumulated_depreciation))
+ value_after_depreciation = (flt(self.gross_purchase_amount) -
+ flt(self.opening_accumulated_depreciation))
- d.value_after_depreciation = value_after_depreciation
+ d.value_after_depreciation = value_after_depreciation
- no_of_depreciations = cint(d.total_number_of_depreciations - 1) - cint(self.number_of_depreciations_booked)
- end_date = add_months(d.depreciation_start_date,
- no_of_depreciations * cint(d.frequency_of_depreciation))
+ number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \
+ cint(self.number_of_depreciations_booked)
- total_days = date_diff(end_date, self.available_for_use_date)
- rate_per_day = (value_after_depreciation - d.get("expected_value_after_useful_life")) / total_days
+ has_pro_rata = self.check_is_pro_rata(d)
- number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \
- cint(self.number_of_depreciations_booked)
+ if has_pro_rata:
+ number_of_pending_depreciations += 1
- from_date = self.available_for_use_date
- if number_of_pending_depreciations:
- next_depr_date = getdate(add_months(self.available_for_use_date,
- number_of_pending_depreciations * 12))
- if (cint(frappe.db.get_value("Asset Settings", None, "schedule_based_on_fiscal_year")) == 1
- and getdate(d.depreciation_start_date) < next_depr_date):
+ skip_row = False
+ for n in range(number_of_pending_depreciations):
+ # If depreciation is already completed (for double declining balance)
+ if skip_row: continue
- number_of_pending_depreciations += 1
- for n in range(number_of_pending_depreciations):
- if n == list(range(number_of_pending_depreciations))[-1]:
- schedule_date = add_months(self.available_for_use_date, n * 12)
- previous_scheduled_date = add_months(d.depreciation_start_date, (n-1) * 12)
- depreciation_amount = \
- self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
- d, previous_scheduled_date, schedule_date)
+ depreciation_amount = self.get_depreciation_amount(value_after_depreciation,
+ d.total_number_of_depreciations, d)
- elif n == list(range(number_of_pending_depreciations))[0]:
- schedule_date = d.depreciation_start_date
- depreciation_amount = \
- self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
- d, self.available_for_use_date, schedule_date)
+ if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
+ schedule_date = add_months(d.depreciation_start_date,
+ n * cint(d.frequency_of_depreciation))
- else:
- schedule_date = add_months(d.depreciation_start_date, n * 12)
- depreciation_amount = \
- self.get_depreciation_amount_prorata_temporis(value_after_depreciation, d)
+ # For first row
+ if has_pro_rata and n==0:
+ depreciation_amount, days = get_pro_rata_amt(d, depreciation_amount,
+ self.available_for_use_date, d.depreciation_start_date)
+ # For last row
+ elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1:
+ to_date = add_months(self.available_for_use_date,
+ n * cint(d.frequency_of_depreciation))
- if value_after_depreciation != 0:
- value_after_depreciation -= flt(depreciation_amount)
+ depreciation_amount, days = get_pro_rata_amt(d,
+ depreciation_amount, schedule_date, to_date)
- self.append("schedules", {
- "schedule_date": schedule_date,
- "depreciation_amount": depreciation_amount,
- "depreciation_method": d.depreciation_method,
- "finance_book": d.finance_book,
- "finance_book_id": d.idx
- })
- else:
- for n in range(number_of_pending_depreciations):
- schedule_date = add_months(d.depreciation_start_date,
- n * cint(d.frequency_of_depreciation))
+ schedule_date = add_days(schedule_date, days)
- if d.depreciation_method in ("Straight Line", "Manual"):
- days = date_diff(schedule_date, from_date)
- if n == 0: days += 1
+ if not depreciation_amount: continue
+ value_after_depreciation -= flt(depreciation_amount,
+ self.precision("gross_purchase_amount"))
- depreciation_amount = days * rate_per_day
- from_date = schedule_date
- else:
- depreciation_amount = self.get_depreciation_amount(value_after_depreciation,
- d.total_number_of_depreciations, d)
+ # Adjust depreciation amount in the last period based on the expected value after useful life
+ if d.expected_value_after_useful_life and ((n == cint(number_of_pending_depreciations) - 1
+ and value_after_depreciation != d.expected_value_after_useful_life)
+ or value_after_depreciation < d.expected_value_after_useful_life):
+ depreciation_amount += (value_after_depreciation - d.expected_value_after_useful_life)
+ skip_row = True
- if depreciation_amount:
- value_after_depreciation -= flt(depreciation_amount)
+ if depreciation_amount > 0:
+ self.append("schedules", {
+ "schedule_date": schedule_date,
+ "depreciation_amount": depreciation_amount,
+ "depreciation_method": d.depreciation_method,
+ "finance_book": d.finance_book,
+ "finance_book_id": d.idx
+ })
- self.append("schedules", {
- "schedule_date": schedule_date,
- "depreciation_amount": depreciation_amount,
- "depreciation_method": d.depreciation_method,
- "finance_book": d.finance_book,
- "finance_book_id": d.idx
- })
+ def check_is_pro_rata(self, row):
+ has_pro_rata = False
+
+ days = date_diff(row.depreciation_start_date, self.available_for_use_date) + 1
+ total_days = get_total_days(row.depreciation_start_date, row.frequency_of_depreciation)
+
+ if days < total_days:
+ has_pro_rata = True
+
+ return has_pro_rata
def validate_asset_finance_books(self, row):
if flt(row.expected_value_after_useful_life) >= flt(self.gross_purchase_amount):
@@ -261,31 +252,20 @@
return flt(self.get('finance_books')[cint(idx)-1].value_after_depreciation)
def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
- if row.depreciation_method in ["Straight Line", "Manual"]:
- amt = (flt(self.gross_purchase_amount) - flt(row.expected_value_after_useful_life) -
- flt(self.opening_accumulated_depreciation))
-
- depreciation_amount = amt * row.rate_of_depreciation
- else:
- depreciation_amount = flt(depreciable_value) * (flt(row.rate_of_depreciation) / 100)
- value_after_depreciation = flt(depreciable_value) - depreciation_amount
- if value_after_depreciation < flt(row.expected_value_after_useful_life):
- depreciation_amount = flt(depreciable_value) - flt(row.expected_value_after_useful_life)
-
- return depreciation_amount
-
- def get_depreciation_amount_prorata_temporis(self, depreciable_value, row, start_date=None, end_date=None):
- if start_date and end_date:
- prorata_temporis = min(abs(flt(date_diff(str(end_date), str(start_date)))) / flt(frappe.db.get_value("Asset Settings", None, "number_of_days_in_fiscal_year")), 1)
- else:
- prorata_temporis = 1
+ precision = self.precision("gross_purchase_amount")
if row.depreciation_method in ("Straight Line", "Manual"):
+ depreciation_left = (cint(row.total_number_of_depreciations) - cint(self.number_of_depreciations_booked))
+
+ if not depreciation_left:
+ frappe.msgprint(_("All the depreciations has been booked"))
+ depreciation_amount = flt(row.expected_value_after_useful_life)
+ return depreciation_amount
+
depreciation_amount = (flt(row.value_after_depreciation) -
- flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) -
- cint(self.number_of_depreciations_booked)) * prorata_temporis
+ flt(row.expected_value_after_useful_life)) / depreciation_left
else:
- depreciation_amount = self.get_depreciation_amount(depreciable_value, row.total_number_of_depreciations, row)
+ depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100), precision)
return depreciation_amount
@@ -301,9 +281,12 @@
flt(accumulated_depreciation_after_full_schedule),
self.precision('gross_purchase_amount'))
- if row.expected_value_after_useful_life < asset_value_after_full_schedule:
+ if (row.expected_value_after_useful_life and
+ row.expected_value_after_useful_life < asset_value_after_full_schedule):
frappe.throw(_("Depreciation Row {0}: Expected value after useful life must be greater than or equal to {1}")
.format(row.idx, asset_value_after_full_schedule))
+ elif not row.expected_value_after_useful_life:
+ row.expected_value_after_useful_life = asset_value_after_full_schedule
def validate_cancellation(self):
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
@@ -412,15 +395,7 @@
if isinstance(args, string_types):
args = json.loads(args)
- number_of_depreciations_booked = 0
- if self.is_existing_asset:
- number_of_depreciations_booked = self.number_of_depreciations_booked
-
float_precision = cint(frappe.db.get_default("float_precision")) or 2
- tot_no_of_depreciation = flt(args.get("total_number_of_depreciations")) - flt(number_of_depreciations_booked)
-
- if args.get("depreciation_method") in ["Straight Line", "Manual"]:
- return 1.0 / tot_no_of_depreciation
if args.get("depreciation_method") == 'Double Declining Balance':
return 200.0 / args.get("total_number_of_depreciations")
@@ -600,3 +575,15 @@
def is_cwip_accounting_disabled():
return cint(frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting"))
+
+def get_pro_rata_amt(row, depreciation_amount, from_date, to_date):
+ days = date_diff(to_date, from_date)
+ total_days = get_total_days(to_date, row.frequency_of_depreciation)
+
+ return (depreciation_amount * flt(days)) / flt(total_days), days
+
+def get_total_days(date, frequency):
+ period_start_date = add_months(date,
+ cint(frequency) * -1)
+
+ return date_diff(date, period_start_date)
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index fceccfb..481ee7d 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -88,23 +88,23 @@
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
- asset.available_for_use_date = '2020-06-06'
- asset.purchase_date = '2020-06-06'
+ asset.available_for_use_date = '2030-01-01'
+ asset.purchase_date = '2030-01-01'
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
- "next_depreciation_date": "2020-12-31",
"depreciation_method": "Straight Line",
"total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-06-06"
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": "2030-12-31"
})
asset.save()
+
self.assertEqual(asset.status, "Draft")
expected_schedules = [
- ["2020-06-06", 147.54, 147.54],
- ["2021-04-06", 44852.46, 45000.0],
- ["2022-02-06", 45000.0, 90000.00]
+ ["2030-12-31", 30000.00, 30000.00],
+ ["2031-12-31", 30000.00, 60000.00],
+ ["2032-12-31", 30000.00, 90000.00]
]
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
@@ -118,20 +118,21 @@
asset.calculate_depreciation = 1
asset.number_of_depreciations_booked = 1
asset.opening_accumulated_depreciation = 40000
+ asset.available_for_use_date = "2030-06-06"
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
- "next_depreciation_date": "2020-12-31",
"depreciation_method": "Straight Line",
"total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-06-06"
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": "2030-12-31"
})
asset.insert()
self.assertEqual(asset.status, "Draft")
asset.save()
expected_schedules = [
- ["2020-06-06", 164.47, 40164.47],
- ["2021-04-06", 49835.53, 90000.00]
+ ["2030-12-31", 14246.58, 54246.58],
+ ["2031-12-31", 25000.00, 79246.58],
+ ["2032-06-06", 10753.42, 90000.00]
]
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount]
for d in asset.get("schedules")]
@@ -145,24 +146,23 @@
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
- asset.available_for_use_date = '2020-06-06'
- asset.purchase_date = '2020-06-06'
+ asset.available_for_use_date = '2030-01-01'
+ asset.purchase_date = '2030-01-01'
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
- "next_depreciation_date": "2020-12-31",
"depreciation_method": "Double Declining Balance",
"total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-06-06"
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": '2030-12-31'
})
asset.insert()
self.assertEqual(asset.status, "Draft")
asset.save()
expected_schedules = [
- ["2020-06-06", 66666.67, 66666.67],
- ["2021-04-06", 22222.22, 88888.89],
- ["2022-02-06", 1111.11, 90000.0]
+ ['2030-12-31', 66667.00, 66667.00],
+ ['2031-12-31', 22222.11, 88889.11],
+ ['2032-12-31', 1110.89, 90000.0]
]
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
@@ -177,23 +177,21 @@
asset.is_existing_asset = 1
asset.number_of_depreciations_booked = 1
asset.opening_accumulated_depreciation = 50000
+ asset.available_for_use_date = '2030-01-01'
+ asset.purchase_date = '2029-11-30'
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
- "next_depreciation_date": "2020-12-31",
"depreciation_method": "Double Declining Balance",
"total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-06-06"
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": "2030-12-31"
})
asset.insert()
self.assertEqual(asset.status, "Draft")
- asset.save()
-
- asset.save()
expected_schedules = [
- ["2020-06-06", 33333.33, 83333.33],
- ["2021-04-06", 6666.67, 90000.0]
+ ["2030-12-31", 33333.50, 83333.50],
+ ["2031-12-31", 6666.50, 90000.0]
]
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
@@ -209,25 +207,25 @@
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
- asset.purchase_date = '2020-01-30'
+ asset.purchase_date = '2030-01-30'
asset.is_existing_asset = 0
- asset.available_for_use_date = "2020-01-30"
+ asset.available_for_use_date = "2030-01-30"
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
"depreciation_method": "Straight Line",
"total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-12-31"
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": "2030-12-31"
})
asset.insert()
asset.save()
expected_schedules = [
- ["2020-12-31", 28000.0, 28000.0],
- ["2021-12-31", 30000.0, 58000.0],
- ["2022-12-31", 30000.0, 88000.0],
- ["2023-01-30", 2000.0, 90000.0]
+ ["2030-12-31", 27534.25, 27534.25],
+ ["2031-12-31", 30000.0, 57534.25],
+ ["2032-12-31", 30000.0, 87534.25],
+ ["2033-01-30", 2465.75, 90000.0]
]
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
@@ -266,8 +264,8 @@
self.assertEqual(asset.get("schedules")[0].journal_entry[:4], "DEPR")
expected_gle = (
- ("_Test Accumulated Depreciations - _TC", 0.0, 32129.24),
- ("_Test Depreciations - _TC", 32129.24, 0.0)
+ ("_Test Accumulated Depreciations - _TC", 0.0, 30000.0),
+ ("_Test Depreciations - _TC", 30000.0, 0.0)
)
gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
@@ -277,15 +275,15 @@
self.assertEqual(gle, expected_gle)
self.assertEqual(asset.get("value_after_depreciation"), 0)
- def test_depreciation_entry_for_wdv(self):
+ def test_depreciation_entry_for_wdv_without_pro_rata(self):
pr = make_purchase_receipt(item_code="Macbook Pro",
qty=1, rate=8000.0, location="Test Location")
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
- asset.available_for_use_date = '2030-06-06'
- asset.purchase_date = '2030-06-06'
+ asset.available_for_use_date = '2030-01-01'
+ asset.purchase_date = '2030-01-01'
asset.append("finance_books", {
"expected_value_after_useful_life": 1000,
"depreciation_method": "Written Down Value",
@@ -298,9 +296,41 @@
self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0)
expected_schedules = [
- ["2030-12-31", 4000.0, 4000.0],
- ["2031-12-31", 2000.0, 6000.0],
- ["2032-12-31", 1000.0, 7000.0],
+ ["2030-12-31", 4000.00, 4000.00],
+ ["2031-12-31", 2000.00, 6000.00],
+ ["2032-12-31", 1000.00, 7000.0],
+ ]
+
+ schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
+ for d in asset.get("schedules")]
+
+ self.assertEqual(schedules, expected_schedules)
+
+ def test_pro_rata_depreciation_entry_for_wdv(self):
+ pr = make_purchase_receipt(item_code="Macbook Pro",
+ qty=1, rate=8000.0, location="Test Location")
+
+ asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
+ asset = frappe.get_doc('Asset', asset_name)
+ asset.calculate_depreciation = 1
+ asset.available_for_use_date = '2030-06-06'
+ asset.purchase_date = '2030-01-01'
+ asset.append("finance_books", {
+ "expected_value_after_useful_life": 1000,
+ "depreciation_method": "Written Down Value",
+ "total_number_of_depreciations": 3,
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": "2030-12-31"
+ })
+ asset.save(ignore_permissions=True)
+
+ self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0)
+
+ expected_schedules = [
+ ["2030-12-31", 2279.45, 2279.45],
+ ["2031-12-31", 2860.28, 5139.73],
+ ["2032-12-31", 1430.14, 6569.87],
+ ["2033-06-06", 430.13, 7000.0],
]
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
@@ -346,18 +376,19 @@
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
- asset.available_for_use_date = '2020-06-06'
- asset.purchase_date = '2020-06-06'
+ asset.available_for_use_date = nowdate()
+ asset.purchase_date = nowdate()
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
"depreciation_method": "Straight Line",
"total_number_of_depreciations": 3,
"frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-06-06"
+ "depreciation_start_date": nowdate()
})
asset.insert()
asset.submit()
- post_depreciation_entries(date="2021-01-01")
+
+ post_depreciation_entries(date=add_months(nowdate(), 10))
scrap_asset(asset.name)
@@ -366,9 +397,9 @@
self.assertTrue(asset.journal_entry_for_scrap)
expected_gle = (
- ("_Test Accumulated Depreciations - _TC", 147.54, 0.0),
+ ("_Test Accumulated Depreciations - _TC", 30000.0, 0.0),
("_Test Fixed Asset - _TC", 0.0, 100000.0),
- ("_Test Gain/Loss on Asset Disposal - _TC", 99852.46, 0.0)
+ ("_Test Gain/Loss on Asset Disposal - _TC", 70000.0, 0.0)
)
gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
@@ -412,9 +443,9 @@
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold")
expected_gle = (
- ("_Test Accumulated Depreciations - _TC", 23051.47, 0.0),
+ ("_Test Accumulated Depreciations - _TC", 20392.16, 0.0),
("_Test Fixed Asset - _TC", 0.0, 100000.0),
- ("_Test Gain/Loss on Asset Disposal - _TC", 51948.53, 0.0),
+ ("_Test Gain/Loss on Asset Disposal - _TC", 54607.84, 0.0),
("Debtors - _TC", 25000.0, 0.0)
)
diff --git a/erpnext/assets/doctype/asset_settings/asset_settings.json b/erpnext/assets/doctype/asset_settings/asset_settings.json
index a3fee96..edc5ce1 100644
--- a/erpnext/assets/doctype/asset_settings/asset_settings.json
+++ b/erpnext/assets/doctype/asset_settings/asset_settings.json
@@ -54,75 +54,6 @@
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
- "fieldname": "schedule_based_on_fiscal_year",
- "fieldtype": "Check",
- "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": "Calculate Prorated Depreciation Schedule Based on Fiscal Year",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "360",
- "depends_on": "eval:doc.schedule_based_on_fiscal_year",
- "description": "This value is used for pro-rata temporis calculation",
- "fetch_if_empty": 0,
- "fieldname": "number_of_days_in_fiscal_year",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Number of Days in Fiscal Year",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "disable_cwip_accounting",
"fieldtype": "Check",
"hidden": 0,
@@ -159,7 +90,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
- "modified": "2019-03-08 10:44:41.924547",
+ "modified": "2019-05-26 18:31:19.930563",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Settings",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 8ad320e..e3e2f1e 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -484,7 +484,7 @@
'from_warehouse': rm_item_data["warehouse"],
'stock_uom': rm_item_data["stock_uom"],
'main_item_code': rm_item_data["item_code"],
- 'allow_alternative_item': item_wh[rm_item_code].get('allow_alternative_item')
+ 'allow_alternative_item': item_wh.get(rm_item_code, {}).get('allow_alternative_item')
}
}
stock_entry.add_to_stock_entry_detail(items_dict)
diff --git a/erpnext/change_log/v12/v12_0_0.md b/erpnext/change_log/v12/v12_0_0.md
new file mode 100644
index 0000000..c2f33a8
--- /dev/null
+++ b/erpnext/change_log/v12/v12_0_0.md
@@ -0,0 +1,41 @@
+# Version 12 Release Notes
+
+### Accounting
+1. [Accounting Dimensions](https://erpnext.com/docs/user/manual/en/accounts/accounting-dimensions)
+1. [Chart of Accounts Importer](https://erpnext.com/docs/user/manual/en/setting-up/chart-of-accounts-importer)
+1. [Invoice Discounting](https://erpnext.com/docs/user/manual/en/accounts/invoice_discounting)
+1. [Tally Migrator](https://github.com/frappe/erpnext/pull/17405)
+
+### Stock
+1. [Serialized & Batched Item Reconciliation](https://erpnext.com/docs/user/manual/en/setting-up/stock-reconciliation#12-for-serialized-items)
+1. [Auto Fetch Serialized Items](https://erpnext.com/version-12/release-notes/features#new-upload-dialog)
+1. [Item Tax Templates](https://erpnext.com/docs/user/manual/en/accounts/item-tax-template)
+
+### HR
+1. [Auto Attendance](https://erpnext.com/docs/user/manual/en/human-resources/auto-attendance)
+1. [Employee Skill Map](https://erpnext.com/docs/user/manual/en/human-resources/employee_skill_map)
+1. [Encrypted Salary Slips](https://erpnext.com/docs/user/manual/en/human-resources/hr-settings#24-encrypt-salary-slips-in-emails)
+1. [Leave Ledger](https://erpnext.com/docs/user/manual/en/human-resources/leave-ledger-entry)
+1. [Staffing Plan](https://erpnext.com/docs/user/manual/en/human-resources/staffing-plan)
+
+### CRM
+1. [Promotional Scheme](https://erpnext.com/docs/user/manual/en/accounts/promotional-schemes)
+1. [SLA](https://erpnext.com/docs/user/manual/en/support/service-level-agreement)
+1. [Exotel Call Integration](https://erpnext.com/docs/user/manual/en/erpnext_integration/exotel_integration)
+1. [Email Campaign](https://erpnext.com/docs/user/manual/en/CRM/email-campaign)
+
+### Domain Specific Features
+1. [Learning Management System](https://erpnext.com/docs/user/manual/en/education/setting-up-lms)
+1. [Quality Management System](https://erpnext.com/docs/user/manual/en/quality-management)
+1. [Production Planning Enhancements](https://erpnext.com/docs/user/manual/en/manufacturing/production-plan/planning-for-material-requests)
+1. [Project Template](https://erpnext.com/docs/user/manual/en/projects/project-template)
+
+### New Reports
+1. [Bank Remittance](https://erpnext.com/docs/user/manual/en/human-resources/human-resources-reports#bank-remittance-report)
+1. [BOM Explorer](https://erpnext.com/docs/user/manual/en/stock/articles/bom_explorer)
+1. [Billing Summary Report](https://erpnext.com/docs/user/manual/en/projects/reports/billing_summary_reports)
+1. [Procurement Tracker Report](docs/user/manual/en/buying/articles/procurement-tracker-report)
+1. [Loan Repayment](https://erpnext.com/docs/user/manual/en/human-resources/human-resources-reports#loan-repayment-report)
+1. [GSTR-3B](https://erpnext.com/docs/user/manual/en/regional/india/gst-3b-report)
+1. [Sales Partner](https://erpnext.com/docs/user/manual/en/selling/sales-partner#sales-partner-reports)
+1. [Sales Partner Target Variance based on Item Group](https://erpnext.com/docs/user/manual/en/selling/sales-partner#sales-partner-target-variance-based-on-item-group)
diff --git a/erpnext/communication/doctype/call_log/call_log.py b/erpnext/communication/doctype/call_log/call_log.py
index c9fdfbe..2343632 100644
--- a/erpnext/communication/doctype/call_log/call_log.py
+++ b/erpnext/communication/doctype/call_log/call_log.py
@@ -6,15 +6,13 @@
import frappe
from frappe import _
from frappe.model.document import Document
-from erpnext.crm.doctype.utils import get_scheduled_employees_for_popup
+from erpnext.crm.doctype.utils import get_scheduled_employees_for_popup, strip_number
from frappe.contacts.doctype.contact.contact import get_contact_with_phone_number
from erpnext.crm.doctype.lead.lead import get_lead_with_phone_number
class CallLog(Document):
def before_insert(self):
- # strip 0 from the start of the number for proper number comparisions
- # eg. 07888383332 should match with 7888383332
- number = self.get('from').lstrip('0')
+ number = strip_number(self.get('from'))
self.contact = get_contact_with_phone_number(number)
self.lead = get_lead_with_phone_number(number)
@@ -48,13 +46,14 @@
doc.add_comment('Comment', frappe.bold(_('Call Summary')) + '<br><br>' + summary)
def get_employees_with_number(number):
+ number = strip_number(number)
if not number: return []
employee_emails = frappe.cache().hget('employees_with_number', number)
if employee_emails: return employee_emails
employees = frappe.get_all('Employee', filters={
- 'cell_number': ['like', '%{}'.format(number.lstrip('0'))],
+ 'cell_number': ['like', '%{}%'.format(number)],
'user_id': ['!=', '']
}, fields=['user_id'])
@@ -64,23 +63,29 @@
return employee
def set_caller_information(doc, state):
- '''Called from hoooks on creation of Lead or Contact'''
+ '''Called from hooks on creation of Lead or Contact'''
if doc.doctype not in ['Lead', 'Contact']: return
numbers = [doc.get('phone'), doc.get('mobile_no')]
- for_doc = doc.doctype.lower()
+ # contact for Contact and lead for Lead
+ fieldname = doc.doctype.lower()
+
+ # contact_name or lead_name
+ display_name_field = '{}_name'.format(fieldname)
for number in numbers:
+ number = strip_number(number)
if not number: continue
- print(number)
+
filters = frappe._dict({
- 'from': ['like', '%{}'.format(number.lstrip('0'))],
- for_doc: ''
+ 'from': ['like', '%{}'.format(number)],
+ fieldname: ''
})
logs = frappe.get_all('Call Log', filters=filters)
for log in logs:
- call_log = frappe.get_doc('Call Log', log.name)
- call_log.set(for_doc, doc.name)
- call_log.save(ignore_permissions=True)
+ frappe.db.set_value('Call Log', log.name, {
+ fieldname: doc.name,
+ display_name_field: doc.get_title()
+ }, update_modified=False)
diff --git a/erpnext/config/crm.py b/erpnext/config/crm.py
index 70784f3..eba6c7a 100644
--- a/erpnext/config/crm.py
+++ b/erpnext/config/crm.py
@@ -41,6 +41,11 @@
"name": "Lead Source",
"description": _("Track Leads by Lead Source.")
},
+ {
+ "type": "doctype",
+ "name": "Contract",
+ "description": _("Helps you keep tracks of Contracts based on Supplier, Customer and Employee"),
+ },
]
},
{
diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py
index eae937c..4e5e903 100644
--- a/erpnext/config/hr.py
+++ b/erpnext/config/hr.py
@@ -168,6 +168,10 @@
},
{
"type": "doctype",
+ "name": "Payroll Period",
+ },
+ {
+ "type": "doctype",
"name": "Salary Component",
},
{
diff --git a/erpnext/config/manufacturing.py b/erpnext/config/manufacturing.py
index c79c5b8..2c18eeb 100644
--- a/erpnext/config/manufacturing.py
+++ b/erpnext/config/manufacturing.py
@@ -94,6 +94,13 @@
"name": "BOM Update Tool",
"description": _("Replace BOM and update latest price in all BOMs"),
},
+ {
+ "type": "page",
+ "label": _("BOM Comparison Tool"),
+ "name": "bom-comparison-tool",
+ "description": _("Compare BOMs for changes in Raw Materials and Operations"),
+ "data_doctype": "BOM"
+ },
]
},
{
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 588f74d..a7dc4c7 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -727,7 +727,7 @@
where
t2.parent = t1.name and t1.item = %s
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
- and t2.item_code = t3.name and t3.is_stock_item = 1""".format(doctype),
+ and t2.item_code = t3.name""".format(doctype),
(item_code, bom), as_dict=1)
if not bom_items:
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 57c063a..19ec053 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -371,7 +371,7 @@
return frappe.db.sql("""select tabAccount.name from `tabAccount`
where (tabAccount.report_type = "Profit and Loss"
- or tabAccount.account_type in ("Expense Account", "Fixed Asset", "Temporary", "Asset Received But Not Billed"))
+ or tabAccount.account_type in ("Expense Account", "Fixed Asset", "Temporary", "Asset Received But Not Billed", "Capital Work in Progress"))
and tabAccount.is_group=0
and tabAccount.docstatus!=2
and tabAccount.{key} LIKE %(txt)s
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index 28dd4ea..b713958 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -24,7 +24,9 @@
else:
ref_doc = frappe.get_doc(doc.doctype, doc.return_against)
- if ref_doc.company == doc.company and ref_doc.customer == doc.customer and ref_doc.docstatus == 1:
+ party_type = "customer" if doc.doctype in ("Sales Invoice", "Delivery Note") else "supplier"
+
+ if ref_doc.company == doc.company and ref_doc.get(party_type) == doc.get(party_type) and ref_doc.docstatus == 1:
# validate posting date time
return_posting_datetime = "%s %s" % (doc.posting_date, doc.get("posting_time") or "00:00:00")
ref_posting_datetime = "%s %s" % (ref_doc.posting_date, ref_doc.get("posting_time") or "00:00:00")
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 2cbe596..52d58dc 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -45,6 +45,7 @@
self.set_gross_profit()
set_default_income_account_for_item(self)
self.set_customer_address()
+ self.validate_for_duplicate_items()
def set_missing_values(self, for_validate=False):
@@ -381,6 +382,34 @@
if self.get(address_field):
self.set(address_display_field, get_address_display(self.get(address_field)))
+ def validate_for_duplicate_items(self):
+ check_list, chk_dupl_itm = [], []
+ if cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
+ return
+
+ for d in self.get('items'):
+ if self.doctype == "Sales Invoice":
+ e = [d.item_code, d.description, d.warehouse, d.sales_order or d.delivery_note, d.batch_no or '']
+ f = [d.item_code, d.description, d.sales_order or d.delivery_note]
+ elif self.doctype == "Delivery Note":
+ e = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
+ f = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
+ elif self.doctype == "Sales Order":
+ e = [d.item_code, d.description, d.warehouse, d.batch_no or '']
+ f = [d.item_code, d.description]
+
+ if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1:
+ if e in check_list:
+ frappe.throw(_("Note: Item {0} entered multiple times").format(d.item_code))
+ else:
+ check_list.append(e)
+ else:
+ if f in chk_dupl_itm:
+ frappe.throw(_("Note: Item {0} entered multiple times").format(d.item_code))
+ else:
+ chk_dupl_itm.append(f)
+
+
def validate_items(self):
# validate items to see if they have is_sales_item enabled
from erpnext.controllers.buying_controller import validate_item_type
diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py
index ed48fd1..0738fd5 100644
--- a/erpnext/controllers/website_list_for_contact.py
+++ b/erpnext/controllers/website_list_for_contact.py
@@ -21,42 +21,45 @@
def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20, order_by="modified"):
user = frappe.session.user
- key = None
+ ignore_permissions = False
if not filters: filters = []
if doctype == 'Supplier Quotation':
- filters.append((doctype, "docstatus", "<", 2))
+ filters.append((doctype, 'docstatus', '<', 2))
else:
- filters.append((doctype, "docstatus", "=", 1))
+ filters.append((doctype, 'docstatus', '=', 1))
- if (user != "Guest" and is_website_user()) or doctype == 'Request for Quotation':
+ if (user != 'Guest' and is_website_user()) or doctype == 'Request for Quotation':
parties_doctype = 'Request for Quotation Supplier' if doctype == 'Request for Quotation' else doctype
# find party for this contact
customers, suppliers = get_customers_suppliers(parties_doctype, user)
- if not customers and not suppliers: return []
-
- key, parties = get_party_details(customers, suppliers)
-
- if doctype == 'Request for Quotation':
- return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length)
-
- filters.append((doctype, key, "in", parties))
-
- if key:
- return post_process(doctype, get_list_for_transactions(doctype, txt,
- filters=filters, fields="name",limit_start=limit_start,
- limit_page_length=limit_page_length,ignore_permissions=True,
- order_by="modified desc"))
+ if customers:
+ if doctype == 'Quotation':
+ filters.append(('quotation_to', '=', 'Customer'))
+ filters.append(('party_name', 'in', customers))
+ else:
+ filters.append(('customer', 'in', customers))
+ elif suppliers:
+ filters.append(('supplier', 'in', suppliers))
else:
return []
- return post_process(doctype, get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length,
- fields="name", order_by="modified desc"))
+ if doctype == 'Request for Quotation':
+ parties = customers or suppliers
+ return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length)
+
+ # Since customers and supplier do not have direct access to internal doctypes
+ ignore_permissions = True
+
+ transactions = get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length,
+ fields='name', ignore_permissions=ignore_permissions, order_by='modified desc')
+
+ return post_process(doctype, transactions)
def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length=20,
- ignore_permissions=False,fields=None, order_by=None):
+ ignore_permissions=False, fields=None, order_by=None):
""" Get List of transactions like Invoices, Orders """
from frappe.www.list import get_list
meta = frappe.get_meta(doctype)
@@ -77,22 +80,12 @@
if or_filters:
for r in frappe.get_list(doctype, fields=fields,filters=filters, or_filters=or_filters,
- limit_start=limit_start, limit_page_length=limit_page_length,
+ limit_start=limit_start, limit_page_length=limit_page_length,
ignore_permissions=ignore_permissions, order_by=order_by):
data.append(r)
return data
-def get_party_details(customers, suppliers):
- if customers:
- key, parties = "customer", customers
- elif suppliers:
- key, parties = "supplier", suppliers
- else:
- key, parties = "customer", []
-
- return key, parties
-
def rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length):
data = frappe.db.sql("""select distinct parent as name, supplier from `tab{doctype}`
where supplier = '{supplier}' and docstatus=1 order by modified desc limit {start}, {len}""".
@@ -130,38 +123,56 @@
suppliers = []
meta = frappe.get_meta(doctype)
+ customer_field_name = get_customer_field_name(doctype)
+
+ has_customer_field = meta.has_field(customer_field_name)
+ has_supplier_field = meta.has_field('supplier')
+
if has_common(["Supplier", "Customer"], frappe.get_roles(user)):
contacts = frappe.db.sql("""
- select
+ select
`tabContact`.email_id,
`tabDynamic Link`.link_doctype,
`tabDynamic Link`.link_name
- from
+ from
`tabContact`, `tabDynamic Link`
where
`tabContact`.name=`tabDynamic Link`.parent and `tabContact`.email_id =%s
""", user, as_dict=1)
- customers = [c.link_name for c in contacts if c.link_doctype == 'Customer'] \
- if meta.get_field("customer") else None
- suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier'] \
- if meta.get_field("supplier") else None
+ customers = [c.link_name for c in contacts if c.link_doctype == 'Customer']
+ suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier']
elif frappe.has_permission(doctype, 'read', user=user):
- customers = [customer.name for customer in frappe.get_list("Customer")] \
- if meta.get_field("customer") else None
- suppliers = [supplier.name for supplier in frappe.get_list("Customer")] \
- if meta.get_field("supplier") else None
+ customer_list = frappe.get_list("Customer")
+ customers = suppliers = [customer.name for customer in customer_list]
- return customers, suppliers
+ return customers if has_customer_field else None, \
+ suppliers if has_supplier_field else None
def has_website_permission(doc, ptype, user, verbose=False):
doctype = doc.doctype
customers, suppliers = get_customers_suppliers(doctype, user)
if customers:
- return frappe.get_all(doctype, filters=[(doctype, "customer", "in", customers),
- (doctype, "name", "=", doc.name)]) and True or False
+ return frappe.db.exists(doctype, get_customer_filter(doc, customers))
elif suppliers:
fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier'
- return frappe.get_all(doctype, filters=[(doctype, fieldname, "in", suppliers),
- (doctype, "name", "=", doc.name)]) and True or False
+ return frappe.db.exists(doctype, filters={
+ 'name': doc.name,
+ fieldname: ["in", suppliers]
+ })
else:
return False
+
+def get_customer_filter(doc, customers):
+ doctype = doc.doctype
+ filters = frappe._dict()
+ filters.name = doc.name
+ filters[get_customer_field_name(doctype)] = ['in', customers]
+ if doctype == 'Quotation':
+ filters.quotation_to = 'Customer'
+ return filters
+
+def get_customer_field_name(doctype):
+ if doctype == 'Quotation':
+ return 'party_name'
+ else:
+ return 'customer'
\ No newline at end of file
diff --git a/erpnext/crm/doctype/utils.py b/erpnext/crm/doctype/utils.py
index 5553276..535458a 100644
--- a/erpnext/crm/doctype/utils.py
+++ b/erpnext/crm/doctype/utils.py
@@ -54,6 +54,8 @@
def get_scheduled_employees_for_popup(communication_medium):
+ if not communication_medium: return []
+
now_time = frappe.utils.nowtime()
weekday = frappe.utils.get_weekday()
@@ -73,3 +75,10 @@
employee_emails = set([employee.user_id for employee in employees])
return employee_emails
+
+def strip_number(number):
+ if not number: return
+ # strip 0 from the start of the number for proper number comparisions
+ # eg. 07888383332 should match with 7888383332
+ number = number.lstrip('0')
+ return number
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/leave_application_list.js b/erpnext/hr/doctype/leave_application/leave_application_list.js
index f69b182..cbb4b73 100644
--- a/erpnext/hr/doctype/leave_application/leave_application_list.js
+++ b/erpnext/hr/doctype/leave_application/leave_application_list.js
@@ -5,6 +5,8 @@
return [__("Approved"), "green", "status,=,Approved"];
} else if (doc.status === "Rejected") {
return [__("Rejected"), "red", "status,=,Rejected"];
+ } else {
+ return [__("Open"), "red", "status,=,Open"];
}
}
};
diff --git a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json
index c114222..771e706 100644
--- a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json
+++ b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json
@@ -27,6 +27,7 @@
"options": "Employee"
},
{
+ "fetch_from": "employee.employee_name",
"fieldname": "employee_name",
"fieldtype": "Data",
"label": "Employee Name"
@@ -101,7 +102,7 @@
],
"in_create": 1,
"is_submittable": 1,
- "modified": "2019-06-21 00:37:07.782810",
+ "modified": "2019-08-20 14:40:04.130799",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Ledger Entry",
diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.py b/erpnext/hr/doctype/payroll_entry/payroll_entry.py
index 9b988e0..97cfc84 100644
--- a/erpnext/hr/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.py
@@ -14,12 +14,12 @@
class PayrollEntry(Document):
def onload(self):
if not self.docstatus==1 or self.salary_slips_submitted:
- return
+ return
# check if salary slips were manually submitted
entries = frappe.db.count("Salary Slip", {'payroll_entry': self.name, 'docstatus': 1}, ['name'])
if cint(entries) == len(self.employees):
- self.set_onload("submitted_ss", True)
+ self.set_onload("submitted_ss", True)
def on_submit(self):
self.create_salary_slips()
diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
index 66e3614..22f0203 100644
--- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
+++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
@@ -97,16 +97,15 @@
def get_total_allocated_leaves(employee, leave_type, from_date, to_date):
''' Returns leave allocation between from date and to date '''
- filters= {
- 'from_date': ['between', (from_date, to_date)],
- 'to_date': ['between', (from_date, to_date)],
- 'docstatus': 1,
- 'is_expired': 0,
- 'leave_type': leave_type,
- 'employee': employee,
- 'transaction_type': 'Leave Allocation'
- }
-
- leave_allocation_records = frappe.db.get_all('Leave Ledger Entry', filters=filters, fields=['SUM(leaves) as leaves'])
+ leave_allocation_records = frappe.db.get_all('Leave Ledger Entry', filters={
+ 'docstatus': 1,
+ 'is_expired': 0,
+ 'leave_type': leave_type,
+ 'employee': employee,
+ 'transaction_type': 'Leave Allocation'
+ }, or_filters={
+ 'from_date': ['between', (from_date, to_date)],
+ 'to_date': ['between', (from_date, to_date)]
+ }, fields=['SUM(leaves) as leaves'])
return flt(leave_allocation_records[0].get('leaves')) if leave_allocation_records else flt(0)
\ No newline at end of file
diff --git a/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py b/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py
index e2989e2..e5622b7 100644
--- a/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py
+++ b/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py
@@ -23,7 +23,8 @@
_("Model") + ":data:50", _("Location") + ":data:100",
_("Log") + ":Link/Vehicle Log:100", _("Odometer") + ":Int:80",
_("Date") + ":Date:100", _("Fuel Qty") + ":Float:80",
- _("Fuel Price") + ":Float:100",_("Service Expense") + ":Float:100"
+ _("Fuel Price") + ":Float:100",_("Fuel Expense") + ":Float:100",
+ _("Service Expense") + ":Float:100"
]
return columns
@@ -32,7 +33,8 @@
data = frappe.db.sql("""select
vhcl.license_plate as "License", vhcl.make as "Make", vhcl.model as "Model",
vhcl.location as "Location", log.name as "Log", log.odometer as "Odometer",
- log.date as "Date", log.fuel_qty as "Fuel Qty", log.price as "Fuel Price"
+ log.date as "Date", log.fuel_qty as "Fuel Qty", log.price as "Fuel Price",
+ log.fuel_qty * log.price as "Fuel Expense"
from
`tabVehicle` vhcl,`tabVehicle Log` log
where
@@ -58,7 +60,7 @@
total_ser_exp=0
for row in data:
if row["Date"] <= period.to_date and row["Date"] >= period.from_date:
- total_fuel_exp+=flt(row["Fuel Price"])
+ total_fuel_exp+=flt(row["Fuel Expense"])
total_ser_exp+=flt(row["Service Expense"])
fueldata.append([period.key,total_fuel_exp])
servicedata.append([period.key,total_ser_exp])
@@ -84,4 +86,4 @@
}
}
chart["type"] = "line"
- return chart
\ No newline at end of file
+ return chart
diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json
index 7865a24..a0faeb5 100644
--- a/erpnext/manufacturing/doctype/bom/bom.json
+++ b/erpnext/manufacturing/doctype/bom/bom.json
@@ -1,2068 +1,528 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2013-01-22 15:11:38",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "allow_import": 1,
+ "creation": "2013-01-22 15:11:38",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "field_order": [
+ "item",
+ "item_name",
+ "image",
+ "uom",
+ "quantity",
+ "cb0",
+ "is_active",
+ "is_default",
+ "with_operations",
+ "inspection_required",
+ "allow_alternative_item",
+ "allow_same_item_multiple_times",
+ "set_rate_of_sub_assembly_item_based_on_bom",
+ "quality_inspection_template",
+ "currency_detail",
+ "company",
+ "transfer_material_against",
+ "conversion_rate",
+ "column_break_12",
+ "currency",
+ "rm_cost_as_per",
+ "buying_price_list",
+ "operations_section",
+ "routing",
+ "operations",
+ "materials_section",
+ "items",
+ "scrap_section",
+ "scrap_items",
+ "costing",
+ "operating_cost",
+ "raw_material_cost",
+ "scrap_material_cost",
+ "cb1",
+ "base_operating_cost",
+ "base_raw_material_cost",
+ "base_scrap_material_cost",
+ "total_cost_of_bom",
+ "total_cost",
+ "column_break_26",
+ "base_total_cost",
+ "more_info_section",
+ "project",
+ "amended_from",
+ "col_break23",
+ "section_break_25",
+ "description",
+ "column_break_27",
+ "section_break0",
+ "exploded_items",
+ "website_section",
+ "show_in_website",
+ "route",
+ "website_image",
+ "thumbnail",
+ "sb_web_spec",
+ "web_long_description",
+ "show_items",
+ "show_operations"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Item to be manufactured or repacked",
- "fetch_if_empty": 0,
- "fieldname": "item",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Item",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "item",
- "oldfieldtype": "Link",
- "options": "Item",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "description": "Item to be manufactured or repacked",
+ "fieldname": "item",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Item",
+ "oldfieldname": "item",
+ "oldfieldtype": "Link",
+ "options": "Item",
+ "reqd": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fetch_from": "item.item_name",
- "fetch_if_empty": 0,
- "fieldname": "item_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Item Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "item.item_name",
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "label": "Item Name",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "item.image",
- "fetch_if_empty": 0,
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Image",
- "length": 0,
- "no_copy": 0,
- "options": "image",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "item.image",
+ "fieldname": "image",
+ "fieldtype": "Attach Image",
+ "hidden": 1,
+ "label": "Image",
+ "options": "image",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "item.stock_uom",
- "fetch_if_empty": 0,
- "fieldname": "uom",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Item UOM",
- "length": 0,
- "no_copy": 0,
- "options": "UOM",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "item.stock_uom",
+ "fieldname": "uom",
+ "fieldtype": "Link",
+ "label": "Item UOM",
+ "options": "UOM",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "description": "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials",
- "fetch_if_empty": 0,
- "fieldname": "quantity",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Quantity",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "quantity",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "1",
+ "description": "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials",
+ "fieldname": "quantity",
+ "fieldtype": "Float",
+ "label": "Quantity",
+ "oldfieldname": "quantity",
+ "oldfieldtype": "Currency",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "cb0",
- "fieldtype": "Column Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- },
+ "fieldname": "cb0",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fetch_if_empty": 0,
- "fieldname": "is_active",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Is Active",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "is_active",
- "oldfieldtype": "Select",
- "permlevel": 0,
- "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_on_submit": 1,
+ "default": "1",
+ "fieldname": "is_active",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Is Active",
+ "no_copy": 1,
+ "oldfieldname": "is_active",
+ "oldfieldtype": "Select"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fetch_if_empty": 0,
- "fieldname": "is_default",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Is Default",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "is_default",
- "oldfieldtype": "Check",
- "permlevel": 0,
- "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_on_submit": 1,
+ "default": "1",
+ "fieldname": "is_default",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Is Default",
+ "no_copy": 1,
+ "oldfieldname": "is_default",
+ "oldfieldtype": "Check"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Manage cost of operations",
- "fetch_if_empty": 0,
- "fieldname": "with_operations",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "With Operations",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- },
+ "default": "0",
+ "description": "Manage cost of operations",
+ "fieldname": "with_operations",
+ "fieldtype": "Check",
+ "ignore_user_permissions": 1,
+ "label": "With Operations"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "inspection_required",
- "fieldtype": "Check",
- "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": "Inspection Required",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "inspection_required",
+ "fieldtype": "Check",
+ "label": "Inspection Required"
+ },
{
- "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_alternative_item",
- "fieldtype": "Check",
- "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": "Allow Alternative Item",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "allow_alternative_item",
+ "fieldtype": "Check",
+ "label": "Allow Alternative Item"
+ },
{
- "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_same_item_multiple_times",
- "fieldtype": "Check",
- "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": "Allow Same Item Multiple Times",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "allow_same_item_multiple_times",
+ "fieldtype": "Check",
+ "label": "Allow Same Item Multiple Times"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fetch_if_empty": 0,
- "fieldname": "set_rate_of_sub_assembly_item_based_on_bom",
- "fieldtype": "Check",
- "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": "Set rate of sub-assembly item based on BOM",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "default": "1",
+ "fieldname": "set_rate_of_sub_assembly_item_based_on_bom",
+ "fieldtype": "Check",
+ "label": "Set rate of sub-assembly item based on BOM"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "inspection_required",
- "fetch_if_empty": 0,
- "fieldname": "quality_inspection_template",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Quality Inspection Template",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Inspection Template",
- "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
- },
+ "depends_on": "inspection_required",
+ "fieldname": "quality_inspection_template",
+ "fieldtype": "Link",
+ "label": "Quality Inspection Template",
+ "options": "Quality Inspection Template"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "currency_detail",
- "fieldtype": "Section Break",
- "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": "",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "currency_detail",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 1,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company",
+ "remember_last_selected_value": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fetch_if_empty": 0,
- "fieldname": "transfer_material_against",
- "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": "Transfer Material Against",
- "length": 0,
- "no_copy": 0,
- "options": "\nWork Order\nJob Card",
- "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
- },
+ "fieldname": "transfer_material_against",
+ "fieldtype": "Select",
+ "label": "Transfer Material Against",
+ "options": "\nWork Order\nJob Card"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "conversion_rate",
- "fieldtype": "Float",
- "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": "Conversion Rate",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "9",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "conversion_rate",
+ "fieldtype": "Float",
+ "label": "Conversion Rate",
+ "precision": "9",
+ "reqd": 1
+ },
{
- "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_12",
- "fieldtype": "Column Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "currency",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Currency",
- "length": 0,
- "no_copy": 0,
- "options": "Currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "label": "Currency",
+ "options": "Currency",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Valuation Rate",
- "fetch_if_empty": 0,
- "fieldname": "rm_cost_as_per",
- "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": "Rate Of Materials Based On",
- "length": 0,
- "no_copy": 0,
- "options": "Valuation Rate\nLast Purchase Rate\nPrice List",
- "permlevel": 0,
- "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_on_submit": 1,
+ "default": "Valuation Rate",
+ "fieldname": "rm_cost_as_per",
+ "fieldtype": "Select",
+ "label": "Rate Of Materials Based On",
+ "options": "Valuation Rate\nLast Purchase Rate\nPrice List"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.rm_cost_as_per===\"Price List\"",
- "fetch_if_empty": 0,
- "fieldname": "buying_price_list",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Price List",
- "length": 0,
- "no_copy": 0,
- "options": "Price List",
- "permlevel": 0,
- "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_on_submit": 1,
+ "depends_on": "eval:doc.rm_cost_as_per===\"Price List\"",
+ "fieldname": "buying_price_list",
+ "fieldtype": "Link",
+ "label": "Price List",
+ "options": "Price List"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "operations_section",
- "fieldtype": "Section Break",
- "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": "Operations",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "permlevel": 0,
- "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
- },
+ "fieldname": "operations_section",
+ "fieldtype": "Section Break",
+ "label": "Operations",
+ "oldfieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "routing",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Routing",
- "length": 0,
- "no_copy": 0,
- "options": "Routing",
- "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
- },
+ "fieldname": "routing",
+ "fieldtype": "Link",
+ "label": "Routing",
+ "options": "Routing"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "operations",
- "fieldtype": "Table",
- "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": "Operations",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "bom_operations",
- "oldfieldtype": "Table",
- "options": "BOM Operation",
- "permlevel": 0,
- "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
- },
+ "fieldname": "operations",
+ "fieldtype": "Table",
+ "label": "Operations",
+ "oldfieldname": "bom_operations",
+ "oldfieldtype": "Table",
+ "options": "BOM Operation"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "materials_section",
- "fieldtype": "Section Break",
- "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": "Materials",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "permlevel": 0,
- "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
- },
+ "fieldname": "materials_section",
+ "fieldtype": "Section Break",
+ "label": "Materials",
+ "oldfieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "items",
- "fieldtype": "Table",
- "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": "Items",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "bom_materials",
- "oldfieldtype": "Table",
- "options": "BOM Item",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "items",
+ "fieldtype": "Table",
+ "label": "Items",
+ "oldfieldname": "bom_materials",
+ "oldfieldtype": "Table",
+ "options": "BOM Item",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "scrap_section",
- "fieldtype": "Section Break",
- "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": "Scrap",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "collapsible": 1,
+ "fieldname": "scrap_section",
+ "fieldtype": "Section Break",
+ "label": "Scrap"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "scrap_items",
- "fieldtype": "Table",
- "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": "Scrap Items",
- "length": 0,
- "no_copy": 0,
- "options": "BOM Scrap Item",
- "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
- },
+ "fieldname": "scrap_items",
+ "fieldtype": "Table",
+ "label": "Scrap Items",
+ "options": "BOM Scrap Item"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "costing",
- "fieldtype": "Section Break",
- "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": "Costing",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "permlevel": 0,
- "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
- },
+ "fieldname": "costing",
+ "fieldtype": "Section Break",
+ "label": "Costing",
+ "oldfieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "operating_cost",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Operating Cost",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "operating_cost",
+ "fieldtype": "Currency",
+ "label": "Operating Cost",
+ "options": "currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "raw_material_cost",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Raw Material Cost",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "raw_material_cost",
+ "fieldtype": "Currency",
+ "label": "Raw Material Cost",
+ "options": "currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "scrap_material_cost",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Scrap Material Cost",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "scrap_material_cost",
+ "fieldtype": "Currency",
+ "label": "Scrap Material Cost",
+ "options": "currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "cb1",
- "fieldtype": "Column Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- },
+ "fieldname": "cb1",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "base_operating_cost",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Operating Cost (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "base_operating_cost",
+ "fieldtype": "Currency",
+ "label": "Operating Cost (Company Currency)",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "base_raw_material_cost",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Raw Material Cost(Company Currency)",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "base_raw_material_cost",
+ "fieldtype": "Currency",
+ "label": "Raw Material Cost (Company Currency)",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "base_scrap_material_cost",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Scrap Material Cost(Company Currency)",
- "length": 0,
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "base_scrap_material_cost",
+ "fieldtype": "Data",
+ "label": "Scrap Material Cost(Company Currency)",
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "total_cost_of_bom",
- "fieldtype": "Section Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "total_cost_of_bom",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "total_cost",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Total Cost",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "total_cost",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Total Cost",
+ "options": "currency",
+ "read_only": 1
+ },
{
- "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_26",
- "fieldtype": "Column Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_26",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "base_total_cost",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Total Cost(Company Currency)",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "base_total_cost",
+ "fieldtype": "Currency",
+ "label": "Total Cost (Company Currency)",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "more_info_section",
- "fieldtype": "Section Break",
- "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": "",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- },
+ "fieldname": "more_info_section",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "project",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Project",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "project",
- "oldfieldtype": "Link",
- "options": "Project",
- "permlevel": 0,
- "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
- },
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "label": "Project",
+ "oldfieldname": "project",
+ "oldfieldtype": "Link",
+ "options": "Project"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Amended From",
- "length": 0,
- "no_copy": 1,
- "options": "BOM",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "BOM",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "col_break23",
- "fieldtype": "Column Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- },
+ "fieldname": "col_break23",
+ "fieldtype": "Column Break"
+ },
{
- "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_25",
- "fieldtype": "Section Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "section_break_25",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "item.description",
- "fetch_if_empty": 0,
- "fieldname": "description",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Item Description",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "item.description",
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Item Description",
+ "read_only": 1
+ },
{
- "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_27",
- "fieldtype": "Column Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_27",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:!doc.__islocal",
- "fetch_if_empty": 0,
- "fieldname": "section_break0",
- "fieldtype": "Section Break",
- "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": "Materials Required (Exploded)",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- },
+ "depends_on": "eval:!doc.__islocal",
+ "fieldname": "section_break0",
+ "fieldtype": "Section Break",
+ "label": "Materials Required (Exploded)"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "exploded_items",
- "fieldtype": "Table",
- "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": "Exploded_items",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "flat_bom_details",
- "oldfieldtype": "Table",
- "options": "BOM Explosion Item",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "exploded_items",
+ "fieldtype": "Table",
+ "label": "Exploded Items",
+ "no_copy": 1,
+ "oldfieldname": "flat_bom_details",
+ "oldfieldtype": "Table",
+ "options": "BOM Explosion Item",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "website_section",
- "fieldtype": "Section Break",
- "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": "Website",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "collapsible": 1,
+ "fieldname": "website_section",
+ "fieldtype": "Section Break",
+ "label": "Website"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fetch_if_empty": 0,
- "fieldname": "show_in_website",
- "fieldtype": "Check",
- "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": "Show in Website",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "default": "0",
+ "fieldname": "show_in_website",
+ "fieldtype": "Check",
+ "label": "Show in Website"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "route",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Route",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "fieldname": "route",
+ "fieldtype": "Small Text",
+ "label": "Route"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "show_in_website",
- "description": "Item Image (if not slideshow)",
- "fetch_if_empty": 0,
- "fieldname": "website_image",
- "fieldtype": "Attach Image",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Image",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "depends_on": "show_in_website",
+ "description": "Item Image (if not slideshow)",
+ "fieldname": "website_image",
+ "fieldtype": "Attach Image",
+ "label": "Image"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "thumbnail",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Thumbnail",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "fieldname": "thumbnail",
+ "fieldtype": "Data",
+ "label": "Thumbnail",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "website_items",
- "columns": 0,
- "depends_on": "show_in_website",
- "fetch_if_empty": 0,
- "fieldname": "sb_web_spec",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Website Specifications",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "collapsible": 1,
+ "collapsible_depends_on": "website_items",
+ "depends_on": "show_in_website",
+ "fieldname": "sb_web_spec",
+ "fieldtype": "Section Break",
+ "label": "Website Specifications"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "show_in_website",
- "fetch_if_empty": 0,
- "fieldname": "web_long_description",
- "fieldtype": "Text Editor",
- "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": "Website Description",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "depends_on": "show_in_website",
+ "fieldname": "web_long_description",
+ "fieldtype": "Text Editor",
+ "label": "Website Description"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "show_in_website",
- "fetch_if_empty": 0,
- "fieldname": "show_items",
- "fieldtype": "Check",
- "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": "Show Items",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "default": "0",
+ "depends_on": "show_in_website",
+ "fieldname": "show_items",
+ "fieldtype": "Check",
+ "label": "Show Items"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:(doc.show_in_website && doc.with_operations)",
- "fetch_if_empty": 0,
- "fieldname": "show_operations",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Show Operations",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "allow_on_submit": 1,
+ "default": "0",
+ "depends_on": "eval:(doc.show_in_website && doc.with_operations)",
+ "fieldname": "show_operations",
+ "fieldtype": "Check",
+ "label": "Show Operations"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-sitemap",
- "idx": 1,
- "image_field": "image",
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-05-01 16:36:05.197126",
- "modified_by": "Administrator",
- "module": "Manufacturing",
- "name": "BOM",
- "owner": "Administrator",
+ ],
+ "icon": "fa fa-sitemap",
+ "idx": 1,
+ "image_field": "image",
+ "is_submittable": 1,
+ "modified": "2019-07-30 17:00:09.665068",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "BOM",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Manufacturing Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Manufacturing Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Manufacturing User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Manufacturing User",
+ "share": 1,
+ "submit": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "search_fields": "item, item_name",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "search_fields": "item, item_name",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index a716293..22c2f69 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -9,6 +9,7 @@
from frappe.website.website_generator import WebsiteGenerator
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.stock.get_item_details import get_price_list_rate
+from frappe.core.doctype.version.version import get_diff
import functools
@@ -763,3 +764,52 @@
'description': name[0],
'amount': items.get(name[0])
})
+
+@frappe.whitelist()
+def get_bom_diff(bom1, bom2):
+ from frappe.model import table_fields
+
+ doc1 = frappe.get_doc('BOM', bom1)
+ doc2 = frappe.get_doc('BOM', bom2)
+
+ out = get_diff(doc1, doc2)
+ out.row_changed = []
+ out.added = []
+ out.removed = []
+
+ meta = doc1.meta
+
+ identifiers = {
+ 'operations': 'operation',
+ 'items': 'item_code',
+ 'scrap_items': 'item_code',
+ 'exploded_items': 'item_code'
+ }
+
+ for df in meta.fields:
+ old_value, new_value = doc1.get(df.fieldname), doc2.get(df.fieldname)
+
+ if df.fieldtype in table_fields:
+ identifier = identifiers[df.fieldname]
+ # make maps
+ old_row_by_identifier, new_row_by_identifier = {}, {}
+ for d in old_value:
+ old_row_by_identifier[d.get(identifier)] = d
+ for d in new_value:
+ new_row_by_identifier[d.get(identifier)] = d
+
+ # check rows for additions, changes
+ for i, d in enumerate(new_value):
+ if d.get(identifier) in old_row_by_identifier:
+ diff = get_diff(old_row_by_identifier[d.get(identifier)], d, for_child=True)
+ if diff and diff.changed:
+ out.row_changed.append((df.fieldname, i, d.get(identifier), diff.changed))
+ else:
+ out.added.append([df.fieldname, d.as_dict()])
+
+ # check for deletions
+ for d in old_value:
+ if not d.get(identifier) in new_row_by_identifier:
+ out.removed.append([df.fieldname, d.as_dict()])
+
+ return out
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 8334f6b..650ab13 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -320,7 +320,8 @@
'qty': data.get("stock_qty") * item.get("qty"),
'production_plan': self.name,
'company': self.company,
- 'fg_warehouse': item.get("fg_warehouse")
+ 'fg_warehouse': item.get("fg_warehouse"),
+ 'update_consumed_material_cost_in_project': 0
})
work_order = self.create_work_order(data)
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.json b/erpnext/manufacturing/doctype/work_order/work_order.json
index 1534b59..63c95e7 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.json
+++ b/erpnext/manufacturing/doctype/work_order/work_order.json
@@ -1,484 +1,504 @@
{
- "allow_import": 1,
- "autoname": "naming_series:",
- "creation": "2013-01-10 16:34:16",
- "doctype": "DocType",
- "document_type": "Setup",
- "field_order": [
- "item",
- "naming_series",
- "status",
- "production_item",
- "item_name",
- "image",
- "bom_no",
- "allow_alternative_item",
- "use_multi_level_bom",
- "skip_transfer",
- "column_break1",
- "company",
- "qty",
- "material_transferred_for_manufacturing",
- "produced_qty",
- "sales_order",
- "project",
- "from_wip_warehouse",
- "warehouses",
- "wip_warehouse",
- "fg_warehouse",
- "column_break_12",
- "scrap_warehouse",
- "required_items_section",
- "required_items",
- "time",
- "planned_start_date",
- "actual_start_date",
- "column_break_13",
- "planned_end_date",
- "actual_end_date",
- "expected_delivery_date",
- "operations_section",
- "transfer_material_against",
- "operations",
- "section_break_22",
- "planned_operating_cost",
- "actual_operating_cost",
- "additional_operating_cost",
- "column_break_24",
- "total_operating_cost",
- "more_info",
- "description",
- "stock_uom",
- "column_break2",
- "material_request",
- "material_request_item",
- "sales_order_item",
- "production_plan",
- "production_plan_item",
- "product_bundle_item",
- "amended_from"
- ],
- "fields": [
- {
- "fieldname": "item",
- "fieldtype": "Section Break",
- "options": "fa fa-gift"
- },
- {
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "label": "Series",
- "options": "MFG-WO-.YYYY.-",
- "print_hide": 1,
- "reqd": 1,
- "set_only_once": 1
- },
- {
- "default": "Draft",
- "depends_on": "eval:!doc.__islocal",
- "fieldname": "status",
- "fieldtype": "Select",
- "label": "Status",
- "no_copy": 1,
- "oldfieldname": "status",
- "oldfieldtype": "Select",
- "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled",
- "read_only": 1,
- "reqd": 1,
- "search_index": 1
- },
- {
- "fieldname": "production_item",
- "fieldtype": "Link",
- "in_global_search": 1,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Item To Manufacture",
- "oldfieldname": "production_item",
- "oldfieldtype": "Link",
- "options": "Item",
- "reqd": 1
- },
- {
- "depends_on": "eval:doc.production_item",
- "fieldname": "item_name",
- "fieldtype": "Data",
- "label": "Item Name",
- "read_only": 1
- },
- {
- "fetch_from": "production_item.image",
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "hidden": 1,
- "label": "Image",
- "options": "image",
- "print_hide": 1,
- "read_only": 1
- },
- {
- "fieldname": "bom_no",
- "fieldtype": "Link",
- "label": "BOM No",
- "oldfieldname": "bom_no",
- "oldfieldtype": "Link",
- "options": "BOM",
- "reqd": 1
- },
- {
- "default": "0",
- "fieldname": "allow_alternative_item",
- "fieldtype": "Check",
- "label": "Allow Alternative Item"
- },
- {
- "default": "1",
- "description": "Plan material for sub-assemblies",
- "fieldname": "use_multi_level_bom",
- "fieldtype": "Check",
- "label": "Use Multi-Level BOM",
- "print_hide": 1
- },
- {
- "default": "0",
- "description": "Check if material transfer entry is not required",
- "fieldname": "skip_transfer",
- "fieldtype": "Check",
- "label": "Skip Material Transfer to WIP Warehouse"
- },
- {
- "fieldname": "column_break1",
- "fieldtype": "Column Break",
- "oldfieldtype": "Column Break",
- "width": "50%"
- },
- {
- "fieldname": "company",
- "fieldtype": "Link",
- "label": "Company",
- "oldfieldname": "company",
- "oldfieldtype": "Link",
- "options": "Company",
- "remember_last_selected_value": 1,
- "reqd": 1
- },
- {
- "fieldname": "qty",
- "fieldtype": "Float",
- "label": "Qty To Manufacture",
- "oldfieldname": "qty",
- "oldfieldtype": "Currency",
- "reqd": 1
- },
- {
- "default": "0",
- "depends_on": "eval:doc.docstatus==1 && doc.skip_transfer==0",
- "fieldname": "material_transferred_for_manufacturing",
- "fieldtype": "Float",
- "label": "Material Transferred for Manufacturing",
- "no_copy": 1,
- "read_only": 1
- },
- {
- "default": "0",
- "depends_on": "eval:doc.docstatus==1",
- "fieldname": "produced_qty",
- "fieldtype": "Float",
- "label": "Manufactured Qty",
- "no_copy": 1,
- "oldfieldname": "produced_qty",
- "oldfieldtype": "Currency",
- "read_only": 1
- },
- {
- "allow_on_submit": 1,
- "fieldname": "sales_order",
- "fieldtype": "Link",
- "in_global_search": 1,
- "label": "Sales Order",
- "options": "Sales Order"
- },
- {
- "fieldname": "project",
- "fieldtype": "Link",
- "label": "Project",
- "oldfieldname": "project",
- "oldfieldtype": "Link",
- "options": "Project"
- },
- {
- "default": "0",
- "depends_on": "skip_transfer",
- "fieldname": "from_wip_warehouse",
- "fieldtype": "Check",
- "label": "Backflush Raw Materials From Work-in-Progress Warehouse"
- },
- {
- "fieldname": "warehouses",
- "fieldtype": "Section Break",
- "label": "Warehouses",
- "options": "fa fa-building"
- },
- {
- "fieldname": "wip_warehouse",
- "fieldtype": "Link",
- "label": "Work-in-Progress Warehouse",
- "options": "Warehouse"
- },
- {
- "fieldname": "fg_warehouse",
- "fieldtype": "Link",
- "label": "Target Warehouse",
- "options": "Warehouse"
- },
- {
- "fieldname": "column_break_12",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "scrap_warehouse",
- "fieldtype": "Link",
- "label": "Scrap Warehouse",
- "options": "Warehouse"
- },
- {
- "fieldname": "required_items_section",
- "fieldtype": "Section Break",
- "label": "Required Items"
- },
- {
- "fieldname": "required_items",
- "fieldtype": "Table",
- "label": "Required Items",
- "no_copy": 1,
- "options": "Work Order Item",
- "print_hide": 1
- },
- {
- "fieldname": "time",
- "fieldtype": "Section Break",
- "label": "Time",
- "options": "fa fa-time"
- },
- {
- "allow_on_submit": 1,
- "default": "now",
- "fieldname": "planned_start_date",
- "fieldtype": "Datetime",
- "label": "Planned Start Date",
- "reqd": 1
- },
- {
- "fieldname": "actual_start_date",
- "fieldtype": "Datetime",
- "label": "Actual Start Date",
- "read_only": 1
- },
- {
- "fieldname": "column_break_13",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "planned_end_date",
- "fieldtype": "Datetime",
- "label": "Planned End Date",
- "no_copy": 1,
- "read_only": 1
- },
- {
- "fieldname": "actual_end_date",
- "fieldtype": "Datetime",
- "label": "Actual End Date",
- "read_only": 1
- },
- {
- "allow_on_submit": 1,
- "fieldname": "expected_delivery_date",
- "fieldtype": "Date",
- "label": "Expected Delivery Date"
- },
- {
- "fieldname": "operations_section",
- "fieldtype": "Section Break",
- "label": "Operations",
- "options": "fa fa-wrench"
- },
- {
- "default": "Work Order",
- "depends_on": "operations",
- "fieldname": "transfer_material_against",
- "fieldtype": "Select",
- "label": "Transfer Material Against",
- "options": "\nWork Order\nJob Card"
- },
- {
- "fieldname": "operations",
- "fieldtype": "Table",
- "label": "Operations",
- "options": "Work Order Operation",
- "read_only": 1
- },
- {
- "depends_on": "operations",
- "fieldname": "section_break_22",
- "fieldtype": "Section Break",
- "label": "Operation Cost"
- },
- {
- "fieldname": "planned_operating_cost",
- "fieldtype": "Currency",
- "label": "Planned Operating Cost",
- "options": "Company:company:default_currency",
- "read_only": 1
- },
- {
- "fieldname": "actual_operating_cost",
- "fieldtype": "Currency",
- "label": "Actual Operating Cost",
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "read_only": 1
- },
- {
- "fieldname": "additional_operating_cost",
- "fieldtype": "Currency",
- "label": "Additional Operating Cost",
- "no_copy": 1,
- "options": "Company:company:default_currency"
- },
- {
- "fieldname": "column_break_24",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "total_operating_cost",
- "fieldtype": "Currency",
- "label": "Total Operating Cost",
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "read_only": 1
- },
- {
- "collapsible": 1,
- "fieldname": "more_info",
- "fieldtype": "Section Break",
- "label": "More Information",
- "options": "fa fa-file-text"
- },
- {
- "fieldname": "description",
- "fieldtype": "Small Text",
- "label": "Item Description",
- "read_only": 1
- },
- {
- "fieldname": "stock_uom",
- "fieldtype": "Link",
- "label": "Stock UOM",
- "oldfieldname": "stock_uom",
- "oldfieldtype": "Data",
- "options": "UOM",
- "read_only": 1
- },
- {
- "fieldname": "column_break2",
- "fieldtype": "Column Break",
- "width": "50%"
- },
- {
- "description": "Manufacture against Material Request",
- "fieldname": "material_request",
- "fieldtype": "Link",
- "label": "Material Request",
- "options": "Material Request"
- },
- {
- "fieldname": "material_request_item",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "Material Request Item",
- "read_only": 1
- },
- {
- "fieldname": "sales_order_item",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "Sales Order Item",
- "read_only": 1
- },
- {
- "fieldname": "production_plan",
- "fieldtype": "Link",
- "label": "Production Plan",
- "no_copy": 1,
- "options": "Production Plan",
- "print_hide": 1,
- "read_only": 1
- },
- {
- "fieldname": "production_plan_item",
- "fieldtype": "Data",
- "label": "Production Plan Item",
- "no_copy": 1,
- "print_hide": 1,
- "read_only": 1
- },
- {
- "fieldname": "product_bundle_item",
- "fieldtype": "Link",
- "label": "Product Bundle Item",
- "no_copy": 1,
- "options": "Item",
- "print_hide": 1,
- "read_only": 1
- },
- {
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "ignore_user_permissions": 1,
- "label": "Amended From",
- "no_copy": 1,
- "oldfieldname": "amended_from",
- "oldfieldtype": "Data",
- "options": "Work Order",
- "read_only": 1
- }
- ],
- "icon": "fa fa-cogs",
- "idx": 1,
- "image_field": "image",
- "is_submittable": 1,
- "modified": "2019-05-27 09:36:16.707719",
- "modified_by": "Administrator",
- "module": "Manufacturing",
- "name": "Work Order",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "import": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Manufacturing User",
- "set_user_permissions": 1,
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "read": 1,
- "report": 1,
- "role": "Stock User"
- }
- ],
- "sort_order": "ASC",
- "title_field": "production_item",
- "track_changes": 1,
- "track_seen": 1
- }
\ No newline at end of file
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "creation": "2013-01-10 16:34:16",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "item",
+ "naming_series",
+ "status",
+ "production_item",
+ "item_name",
+ "image",
+ "bom_no",
+ "column_break1",
+ "company",
+ "qty",
+ "material_transferred_for_manufacturing",
+ "produced_qty",
+ "sales_order",
+ "project",
+ "settings_section",
+ "allow_alternative_item",
+ "use_multi_level_bom",
+ "column_break_18",
+ "skip_transfer",
+ "from_wip_warehouse",
+ "update_consumed_material_cost_in_project",
+ "warehouses",
+ "wip_warehouse",
+ "fg_warehouse",
+ "column_break_12",
+ "scrap_warehouse",
+ "required_items_section",
+ "required_items",
+ "time",
+ "planned_start_date",
+ "actual_start_date",
+ "column_break_13",
+ "planned_end_date",
+ "actual_end_date",
+ "expected_delivery_date",
+ "operations_section",
+ "transfer_material_against",
+ "operations",
+ "section_break_22",
+ "planned_operating_cost",
+ "actual_operating_cost",
+ "additional_operating_cost",
+ "column_break_24",
+ "total_operating_cost",
+ "more_info",
+ "description",
+ "stock_uom",
+ "column_break2",
+ "material_request",
+ "material_request_item",
+ "sales_order_item",
+ "production_plan",
+ "production_plan_item",
+ "product_bundle_item",
+ "amended_from"
+ ],
+ "fields": [
+ {
+ "fieldname": "item",
+ "fieldtype": "Section Break",
+ "options": "fa fa-gift"
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "MFG-WO-.YYYY.-",
+ "print_hide": 1,
+ "reqd": 1,
+ "set_only_once": 1
+ },
+ {
+ "default": "Draft",
+ "depends_on": "eval:!doc.__islocal",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "label": "Status",
+ "no_copy": 1,
+ "oldfieldname": "status",
+ "oldfieldtype": "Select",
+ "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled",
+ "read_only": 1,
+ "reqd": 1,
+ "search_index": 1
+ },
+ {
+ "fieldname": "production_item",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Item To Manufacture",
+ "oldfieldname": "production_item",
+ "oldfieldtype": "Link",
+ "options": "Item",
+ "reqd": 1
+ },
+ {
+ "depends_on": "eval:doc.production_item",
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "read_only": 1
+ },
+ {
+ "fetch_from": "production_item.image",
+ "fieldname": "image",
+ "fieldtype": "Attach Image",
+ "hidden": 1,
+ "label": "Image",
+ "options": "image",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "bom_no",
+ "fieldtype": "Link",
+ "label": "BOM No",
+ "oldfieldname": "bom_no",
+ "oldfieldtype": "Link",
+ "options": "BOM",
+ "reqd": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "allow_alternative_item",
+ "fieldtype": "Check",
+ "label": "Allow Alternative Item"
+ },
+ {
+ "default": "1",
+ "description": "Plan material for sub-assemblies",
+ "fieldname": "use_multi_level_bom",
+ "fieldtype": "Check",
+ "label": "Use Multi-Level BOM",
+ "print_hide": 1
+ },
+ {
+ "default": "0",
+ "description": "Check if material transfer entry is not required",
+ "fieldname": "skip_transfer",
+ "fieldtype": "Check",
+ "label": "Skip Material Transfer to WIP Warehouse"
+ },
+ {
+ "fieldname": "column_break1",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break",
+ "width": "50%"
+ },
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "oldfieldname": "company",
+ "oldfieldtype": "Link",
+ "options": "Company",
+ "remember_last_selected_value": 1,
+ "reqd": 1
+ },
+ {
+ "fieldname": "qty",
+ "fieldtype": "Float",
+ "label": "Qty To Manufacture",
+ "oldfieldname": "qty",
+ "oldfieldtype": "Currency",
+ "reqd": 1
+ },
+ {
+ "default": "0",
+ "depends_on": "eval:doc.docstatus==1 && doc.skip_transfer==0",
+ "fieldname": "material_transferred_for_manufacturing",
+ "fieldtype": "Float",
+ "label": "Material Transferred for Manufacturing",
+ "no_copy": 1,
+ "read_only": 1
+ },
+ {
+ "default": "0",
+ "depends_on": "eval:doc.docstatus==1",
+ "fieldname": "produced_qty",
+ "fieldtype": "Float",
+ "label": "Manufactured Qty",
+ "no_copy": 1,
+ "oldfieldname": "produced_qty",
+ "oldfieldtype": "Currency",
+ "read_only": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "sales_order",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "label": "Sales Order",
+ "options": "Sales Order"
+ },
+ {
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "label": "Project",
+ "oldfieldname": "project",
+ "oldfieldtype": "Link",
+ "options": "Project"
+ },
+ {
+ "default": "0",
+ "depends_on": "skip_transfer",
+ "fieldname": "from_wip_warehouse",
+ "fieldtype": "Check",
+ "label": "Backflush Raw Materials From Work-in-Progress Warehouse"
+ },
+ {
+ "fieldname": "warehouses",
+ "fieldtype": "Section Break",
+ "label": "Warehouses",
+ "options": "fa fa-building"
+ },
+ {
+ "fieldname": "wip_warehouse",
+ "fieldtype": "Link",
+ "label": "Work-in-Progress Warehouse",
+ "options": "Warehouse"
+ },
+ {
+ "fieldname": "fg_warehouse",
+ "fieldtype": "Link",
+ "label": "Target Warehouse",
+ "options": "Warehouse"
+ },
+ {
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "scrap_warehouse",
+ "fieldtype": "Link",
+ "label": "Scrap Warehouse",
+ "options": "Warehouse"
+ },
+ {
+ "fieldname": "required_items_section",
+ "fieldtype": "Section Break",
+ "label": "Required Items"
+ },
+ {
+ "fieldname": "required_items",
+ "fieldtype": "Table",
+ "label": "Required Items",
+ "no_copy": 1,
+ "options": "Work Order Item",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "time",
+ "fieldtype": "Section Break",
+ "label": "Time",
+ "options": "fa fa-time"
+ },
+ {
+ "allow_on_submit": 1,
+ "default": "now",
+ "fieldname": "planned_start_date",
+ "fieldtype": "Datetime",
+ "label": "Planned Start Date",
+ "reqd": 1
+ },
+ {
+ "fieldname": "actual_start_date",
+ "fieldtype": "Datetime",
+ "label": "Actual Start Date",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_13",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "planned_end_date",
+ "fieldtype": "Datetime",
+ "label": "Planned End Date",
+ "no_copy": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "actual_end_date",
+ "fieldtype": "Datetime",
+ "label": "Actual End Date",
+ "read_only": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "expected_delivery_date",
+ "fieldtype": "Date",
+ "label": "Expected Delivery Date"
+ },
+ {
+ "fieldname": "operations_section",
+ "fieldtype": "Section Break",
+ "label": "Operations",
+ "options": "fa fa-wrench"
+ },
+ {
+ "default": "Work Order",
+ "depends_on": "operations",
+ "fieldname": "transfer_material_against",
+ "fieldtype": "Select",
+ "label": "Transfer Material Against",
+ "options": "\nWork Order\nJob Card"
+ },
+ {
+ "fieldname": "operations",
+ "fieldtype": "Table",
+ "label": "Operations",
+ "options": "Work Order Operation",
+ "read_only": 1
+ },
+ {
+ "depends_on": "operations",
+ "fieldname": "section_break_22",
+ "fieldtype": "Section Break",
+ "label": "Operation Cost"
+ },
+ {
+ "fieldname": "planned_operating_cost",
+ "fieldtype": "Currency",
+ "label": "Planned Operating Cost",
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
+ {
+ "fieldname": "actual_operating_cost",
+ "fieldtype": "Currency",
+ "label": "Actual Operating Cost",
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
+ {
+ "fieldname": "additional_operating_cost",
+ "fieldtype": "Currency",
+ "label": "Additional Operating Cost",
+ "no_copy": 1,
+ "options": "Company:company:default_currency"
+ },
+ {
+ "fieldname": "column_break_24",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "total_operating_cost",
+ "fieldtype": "Currency",
+ "label": "Total Operating Cost",
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "more_info",
+ "fieldtype": "Section Break",
+ "label": "More Information",
+ "options": "fa fa-file-text"
+ },
+ {
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Item Description",
+ "read_only": 1
+ },
+ {
+ "fieldname": "stock_uom",
+ "fieldtype": "Link",
+ "label": "Stock UOM",
+ "oldfieldname": "stock_uom",
+ "oldfieldtype": "Data",
+ "options": "UOM",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break2",
+ "fieldtype": "Column Break",
+ "width": "50%"
+ },
+ {
+ "description": "Manufacture against Material Request",
+ "fieldname": "material_request",
+ "fieldtype": "Link",
+ "label": "Material Request",
+ "options": "Material Request"
+ },
+ {
+ "fieldname": "material_request_item",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Material Request Item",
+ "read_only": 1
+ },
+ {
+ "fieldname": "sales_order_item",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Sales Order Item",
+ "read_only": 1
+ },
+ {
+ "fieldname": "production_plan",
+ "fieldtype": "Link",
+ "label": "Production Plan",
+ "no_copy": 1,
+ "options": "Production Plan",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "production_plan_item",
+ "fieldtype": "Data",
+ "label": "Production Plan Item",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "product_bundle_item",
+ "fieldtype": "Link",
+ "label": "Product Bundle Item",
+ "no_copy": 1,
+ "options": "Item",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Amended From",
+ "no_copy": 1,
+ "oldfieldname": "amended_from",
+ "oldfieldtype": "Data",
+ "options": "Work Order",
+ "read_only": 1
+ },
+ {
+ "fieldname": "settings_section",
+ "fieldtype": "Section Break",
+ "label": "Settings"
+ },
+ {
+ "fieldname": "column_break_18",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "1",
+ "fieldname": "update_consumed_material_cost_in_project",
+ "fieldtype": "Check",
+ "label": "Update Consumed Material Cost In Project"
+ }
+ ],
+ "icon": "fa fa-cogs",
+ "idx": 1,
+ "image_field": "image",
+ "is_submittable": 1,
+ "modified": "2019-07-31 00:13:38.218277",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Work Order",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "import": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Manufacturing User",
+ "set_user_permissions": 1,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "read": 1,
+ "report": 1,
+ "role": "Stock User"
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "title_field": "production_item",
+ "track_changes": 1,
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/page/bom_comparison_tool/__init__.py b/erpnext/manufacturing/page/bom_comparison_tool/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/manufacturing/page/bom_comparison_tool/__init__.py
diff --git a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js
new file mode 100644
index 0000000..7152d3d
--- /dev/null
+++ b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js
@@ -0,0 +1,213 @@
+frappe.pages['bom-comparison-tool'].on_page_load = function(wrapper) {
+ var page = frappe.ui.make_app_page({
+ parent: wrapper,
+ title: __('BOM Comparison Tool'),
+ single_column: true
+ });
+
+ new erpnext.BOMComparisonTool(page);
+}
+
+erpnext.BOMComparisonTool = class BOMComparisonTool {
+ constructor(page) {
+ this.page = page;
+ this.make_form();
+ }
+
+ make_form() {
+ this.form = new frappe.ui.FieldGroup({
+ fields: [
+ {
+ label: __('BOM 1'),
+ fieldname: 'name1',
+ fieldtype: 'Link',
+ options: 'BOM',
+ change: () => this.fetch_and_render()
+ },
+ {
+ fieldtype: 'Column Break'
+ },
+ {
+ label: __('BOM 2'),
+ fieldname: 'name2',
+ fieldtype: 'Link',
+ options: 'BOM',
+ change: () => this.fetch_and_render()
+ },
+ {
+ fieldtype: 'Section Break'
+ },
+ {
+ fieldtype: 'HTML',
+ fieldname: 'preview'
+ }
+ ],
+ body: this.page.body
+ });
+ this.form.make();
+ }
+
+ fetch_and_render() {
+ let { name1, name2 } = this.form.get_values();
+ if (!(name1 && name2)) {
+ this.form.get_field('preview').html('');
+ return;
+ }
+
+ // set working state
+ this.form.get_field('preview').html(`
+ <div class="text-muted margin-top">
+ ${__("Fetching...")}
+ </div>
+ `);
+
+ frappe.call('erpnext.manufacturing.doctype.bom.bom.get_bom_diff', {
+ bom1: name1,
+ bom2: name2
+ }).then(r => {
+ let diff = r.message;
+ frappe.model.with_doctype('BOM', () => {
+ this.render('BOM', name1, name2, diff);
+ });
+ });
+ }
+
+ render(doctype, name1, name2, diff) {
+
+ let change_html = (title, doctype, changed) => {
+ let values_changed = this.get_changed_values(doctype, changed)
+ .map(change => {
+ let [fieldname, value1, value2] = change;
+ return `
+ <tr>
+ <td>${frappe.meta.get_label(doctype, fieldname)}</td>
+ <td>${value1}</td>
+ <td>${value2}</td>
+ </tr>
+ `;
+ })
+ .join('');
+
+ return `
+ <h4 class="margin-top">${title}</h4>
+ <div>
+ <table class="table table-bordered">
+ <tr>
+ <th width="33%">${__('Field')}</th>
+ <th width="33%">${name1}</th>
+ <th width="33%">${name2}</th>
+ </tr>
+ ${values_changed}
+ </table>
+ </div>
+ `;
+ }
+
+ let value_changes = change_html(__('Values Changed'), doctype, diff.changed);
+
+ let row_changes_by_fieldname = group_items(diff.row_changed, change => change[0]);
+
+ let table_changes = Object.keys(row_changes_by_fieldname).map(fieldname => {
+ let changes = row_changes_by_fieldname[fieldname];
+ let df = frappe.meta.get_docfield(doctype, fieldname);
+
+ let html = changes.map(change => {
+ let [fieldname,, item_code, changes] = change;
+ let df = frappe.meta.get_docfield(doctype, fieldname);
+ let child_doctype = df.options;
+ let values_changed = this.get_changed_values(child_doctype, changes);
+
+ return values_changed.map((change, i) => {
+ let [fieldname, value1, value2] = change;
+ let th = i === 0
+ ? `<th rowspan="${values_changed.length}">${item_code}</th>`
+ : '';
+ return `
+ <tr>
+ ${th}
+ <td>${frappe.meta.get_label(child_doctype, fieldname)}</td>
+ <td>${value1}</td>
+ <td>${value2}</td>
+ </tr>
+ `;
+ }).join('');
+ }).join('');
+
+ return `
+ <h4 class="margin-top">${__('Changes in {0}', [df.label])}</h4>
+ <table class="table table-bordered">
+ <tr>
+ <th width="25%">${__('Item Code')}</th>
+ <th width="25%">${__('Field')}</th>
+ <th width="25%">${name1}</th>
+ <th width="25%">${name2}</th>
+ </tr>
+ ${html}
+ </table>
+ `;
+ }).join('');
+
+ let get_added_removed_html = (title, grouped_items) => {
+ return Object.keys(grouped_items).map(fieldname => {
+ let rows = grouped_items[fieldname];
+ let df = frappe.meta.get_docfield(doctype, fieldname);
+ let fields = frappe.meta.get_docfields(df.options)
+ .filter(df => df.in_list_view);
+
+ let html = rows.map(row => {
+ let [, doc] = row;
+ let cells = fields
+ .map(df => `<td>${doc[df.fieldname]}</td>`)
+ .join('');
+ return `<tr>${cells}</tr>`;
+ }).join('');
+
+ let header = fields.map(df => `<th>${df.label}</th>`).join('');
+ return `
+ <h4 class="margin-top">${$.format(title, [df.label])}</h4>
+ <table class="table table-bordered">
+ <tr>${header}</tr>
+ ${html}
+ </table>
+ `;
+ }).join('');
+ };
+
+ let added_by_fieldname = group_items(diff.added, change => change[0]);
+ let removed_by_fieldname = group_items(diff.removed, change => change[0]);
+
+ let added_html = get_added_removed_html(__('Rows Added in {0}'), added_by_fieldname);
+ let removed_html = get_added_removed_html(__('Rows Removed in {0}'), removed_by_fieldname);
+
+ let html = `
+ ${value_changes}
+ ${table_changes}
+ ${added_html}
+ ${removed_html}
+ `;
+
+ this.form.get_field('preview').html(html);
+ }
+
+ get_changed_values(doctype, changed) {
+ return changed.filter(change => {
+ let [fieldname, value1, value2] = change;
+ if (!value1) value1 = '';
+ if (!value2) value2 = '';
+ if (value1 === value2) return false;
+ let df = frappe.meta.get_docfield(doctype, fieldname);
+ if (!df) return false;
+ if (df.hidden) return false;
+ return true;
+ });
+ }
+};
+
+function group_items(array, fn) {
+ return array.reduce((acc, item) => {
+ let key = fn(item);
+ acc[key] = acc[key] || [];
+ acc[key].push(item);
+ return acc;
+ }, {});
+}
diff --git a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.json b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.json
new file mode 100644
index 0000000..067a106
--- /dev/null
+++ b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.json
@@ -0,0 +1,30 @@
+{
+ "content": null,
+ "creation": "2019-07-29 13:24:38.201981",
+ "docstatus": 0,
+ "doctype": "Page",
+ "idx": 0,
+ "modified": "2019-07-29 13:24:38.201981",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "bom-comparison-tool",
+ "owner": "Administrator",
+ "page_name": "BOM Comparison Tool",
+ "restrict_to_domain": "Manufacturing",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "Manufacturing User"
+ },
+ {
+ "role": "Manufacturing Manager"
+ }
+ ],
+ "script": null,
+ "standard": "Yes",
+ "style": null,
+ "system_page": 0,
+ "title": "BOM Comparison Tool"
+}
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/generate_leave_ledger_entries.py b/erpnext/patches/v12_0/generate_leave_ledger_entries.py
index 44b59bf..5e91449 100644
--- a/erpnext/patches/v12_0/generate_leave_ledger_entries.py
+++ b/erpnext/patches/v12_0/generate_leave_ledger_entries.py
@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
-from frappe.utils import getdate
+from frappe.utils import getdate, today
def execute():
""" Generates leave ledger entries for leave allocation/application/encashment
@@ -66,7 +66,8 @@
if not frappe.db.exists("Leave Ledger Entry", {'transaction_type': 'Leave Allocation', 'transaction_name': allocation.name, 'is_expired': 1}):
allocation.update(dict(doctype="Leave Allocation"))
allocation_obj = frappe.get_doc(allocation)
- expire_allocation(allocation_obj)
+ if allocation_obj.to_date <= getdate(today()):
+ expire_allocation(allocation_obj)
def get_allocation_records():
return frappe.get_all("Leave Allocation", filters={
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 0a363a0..ffc5e6a 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -60,7 +60,15 @@
var me = this;
$btn.on("click", function() {
- me.show_serial_batch_selector(grid_row.frm, grid_row.doc);
+ let callback = '';
+ let on_close = '';
+
+ if (grid_row.doc.serial_no) {
+ grid_row.doc.has_serial_no = true;
+ }
+
+ me.show_serial_batch_selector(grid_row.frm, grid_row.doc,
+ callback, on_close, true);
});
},
});
diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js
index e6c18a1..7abe4a7 100644
--- a/erpnext/public/js/utils/dimension_tree_filter.js
+++ b/erpnext/public/js/utils/dimension_tree_filter.js
@@ -73,6 +73,28 @@
var row = frappe.get_doc(cdt, cdn);
frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]);
});
+ },
+
+ company: function(frm) {
+ if(frm.doc.company) {
+ erpnext.dimension_filters.forEach((dimension) => {
+ frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
+ });
+ }
+ },
+
+ items_add: function(frm, cdt, cdn) {
+ erpnext.dimension_filters.forEach((dimension) => {
+ var row = frappe.get_doc(cdt, cdn);
+ frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]);
+ });
+ },
+
+ accounts_add: function(frm, cdt, cdn) {
+ erpnext.dimension_filters.forEach((dimension) => {
+ var row = frappe.get_doc(cdt, cdn);
+ frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]);
+ });
}
});
});
\ No newline at end of file
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 2da1085..c397133 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -156,33 +156,21 @@
if self.filters.get("type_of_business") == "B2B":
- customers = frappe.get_all("Customer",
- filters={
- "gst_category": ["in", ["Registered Regular", "Deemed Export", "SEZ"]]
- })
-
- if customers:
- conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1
- and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers]))
+ conditions += "and ifnull(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') and is_return != 1"
if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"):
b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit')
if not b2c_limit:
frappe.throw(_("Please set B2C Limit in GST Settings."))
- customers = frappe.get_all("Customer",
- filters={
- "gst_category": ["in", ["Unregistered"]]
- })
-
if self.filters.get("type_of_business") == "B2C Large" and customers:
conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2)
- and grand_total > {0} and is_return != 1 and customer in ({1})""".\
+ and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.\
format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
elif self.filters.get("type_of_business") == "B2C Small" and customers:
conditions += """ and (
SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2)
- or grand_total <= {0}) and is_return != 1 and customer in ({1})""".\
+ or grand_total <= {0}) and is_return != 1 and gst_category ='Unregistered' """.\
format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
elif self.filters.get("type_of_business") == "CDNR":
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index cc73e76..46009f4 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -34,7 +34,7 @@
self.with_items = 1
def validate_valid_till(self):
- if self.valid_till and self.valid_till < self.transaction_date:
+ if self.valid_till and getdate(self.valid_till) < getdate(self.transaction_date):
frappe.throw(_("Valid till date cannot be before transaction date"))
def has_sales_order(self):
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 09dc9a9..4342af5 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -72,9 +72,7 @@
frappe.msgprint(_("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format(so[0][0], self.po_no))
def validate_for_items(self):
- check_list = []
for d in self.get('items'):
- check_list.append(cstr(d.item_code))
# used for production plan
d.transaction_date = self.transaction_date
@@ -83,13 +81,6 @@
where item_code = %s and warehouse = %s", (d.item_code, d.warehouse))
d.projected_qty = tot_avail_qty and flt(tot_avail_qty[0][0]) or 0
- # check for same entry multiple times
- unique_chk_list = set(check_list)
- if len(unique_chk_list) != len(check_list) and \
- not cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
- frappe.msgprint(_("Same item has been entered multiple times"),
- title=_("Warning"), indicator='orange')
-
def product_bundle_has_stock_item(self, product_bundle):
"""Returns true if product bundle has stock item"""
ret = len(frappe.db.sql("""select i.name from tabItem i, `tabProduct Bundle Item` pbi
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 4b34dc1..584391e 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -252,7 +252,7 @@
def set_mode_of_payment_account(self):
cash = frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name')
if cash and self.default_cash_account \
- and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': cash}):
+ and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': cash}):
mode_of_payment = frappe.get_doc('Mode of Payment', cash)
mode_of_payment.append('accounts', {
'company': self.name,
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 2de9b97..f79d127 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -166,24 +166,7 @@
frappe.throw(_("Customer {0} does not belong to project {1}").format(self.customer, self.project))
def validate_for_items(self):
- check_list, chk_dupl_itm = [], []
- if cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
- return
-
for d in self.get('items'):
- e = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
- f = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
-
- if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1:
- if e in check_list:
- frappe.msgprint(_("Note: Item {0} entered multiple times").format(d.item_code))
- else:
- check_list.append(e)
- else:
- if f in chk_dupl_itm:
- frappe.msgprint(_("Note: Item {0} entered multiple times").format(d.item_code))
- else:
- chk_dupl_itm.append(f)
#Customer Provided parts will have zero valuation rate
if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'):
d.allow_zero_valuation_rate = 1
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 2a7760e..e5a2102 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -145,6 +145,10 @@
self.precision("transfer_qty", item))
def update_cost_in_project(self):
+ if (self.work_order and not frappe.db.get_value("Work Order",
+ self.work_order, "update_consumed_material_cost_in_project")):
+ return
+
if self.project:
amount = frappe.db.sql(""" select ifnull(sum(sed.amount), 0)
from
diff --git a/erpnext/templates/includes/product_page.js b/erpnext/templates/includes/product_page.js
index 65949bb..90a1d86 100644
--- a/erpnext/templates/includes/product_page.js
+++ b/erpnext/templates/includes/product_page.js
@@ -32,7 +32,7 @@
if(r.message.product_info.in_stock===0) {
$(".item-stock").html("<div style='color: red'> <i class='fa fa-close'></i> {{ _("Not in stock") }}</div>");
}
- else if(r.message.product_info.in_stock===1) {
+ else if(r.message.product_info.in_stock===1 && r.message.cart_settings.show_stock_availability) {
var qty_display = "{{ _("In stock") }}";
if (r.message.product_info.show_stock_qty) {
qty_display += " ("+r.message.product_info.stock_qty+")";
diff --git a/erpnext/templates/pages/rfq.py b/erpnext/templates/pages/rfq.py
index 62ec609..67679a1 100644
--- a/erpnext/templates/pages/rfq.py
+++ b/erpnext/templates/pages/rfq.py
@@ -5,8 +5,7 @@
import frappe
from frappe import _
from frappe.utils import formatdate
-from erpnext.controllers.website_list_for_contact import (get_customers_suppliers,
- get_party_details)
+from erpnext.controllers.website_list_for_contact import get_customers_suppliers
def get_context(context):
context.no_cache = 1
@@ -23,8 +22,8 @@
doctype = frappe.form_dict.doctype
parties_doctype = 'Request for Quotation Supplier' if doctype == 'Request for Quotation' else doctype
customers, suppliers = get_customers_suppliers(parties_doctype, frappe.session.user)
- key, parties = get_party_details(customers, suppliers)
- return parties[0] if key == 'supplier' else ''
+
+ return suppliers[0] if suppliers else ''
def check_supplier_has_docname_access(supplier):
status = True