Merge pull request #18527 from netchampfaris/bom-comparison-tool
feat: BOM Comparison Tool
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 5e26693..260478f 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__ = '12.0.3'
+__version__ = '12.0.4'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/bank/bank_dashboard.py b/erpnext/accounts/doctype/bank/bank_dashboard.py
index 4324041..4a1dad8 100644
--- a/erpnext/accounts/doctype/bank/bank_dashboard.py
+++ b/erpnext/accounts/doctype/bank/bank_dashboard.py
@@ -10,9 +10,6 @@
{
'label': _('Bank Deatils'),
'items': ['Bank Account', 'Bank Guarantee']
- },
- {
- 'items': ['Payment Order']
}
]
}
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 3683898..da6b167 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -648,13 +648,18 @@
orders = []
if voucher_type:
- ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
+ if party_account_currency == company_currency:
+ grand_total_field = "base_grand_total"
+ rounded_total_field = "base_rounded_total"
+ else:
+ grand_total_field = "grand_total"
+ rounded_total_field = "rounded_total"
orders = frappe.db.sql("""
select
name as voucher_no,
- {ref_field} as invoice_amount,
- ({ref_field} - advance_paid) as outstanding_amount,
+ if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) as invoice_amount,
+ (if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) - advance_paid) as outstanding_amount,
transaction_date as posting_date
from
`tab{voucher_type}`
@@ -663,13 +668,14 @@
and docstatus = 1
and company = %s
and ifnull(status, "") != "Closed"
- and {ref_field} > advance_paid
+ and if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) > advance_paid
and abs(100 - per_billed) > 0.01
{condition}
order by
transaction_date, name
""".format(**{
- "ref_field": ref_field,
+ "rounded_total_field": rounded_total_field,
+ "grand_total_field": grand_total_field,
"voucher_type": voucher_type,
"party_type": scrub(party_type),
"condition": condition
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 1fe6895..74e9186 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -44,6 +44,10 @@
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
+ if (this.frm.doc.is_return) {
+ this.frm.return_print_format = "Sales Invoice Return";
+ }
+
this.show_general_ledger();
if(doc.update_stock) this.show_stock_ledger();
@@ -148,16 +152,24 @@
},
set_default_print_format: function() {
- // set default print format to POS type
+ // set default print format to POS type or Credit Note
if(cur_frm.doc.is_pos) {
if(cur_frm.pos_print_format) {
cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
cur_frm.meta.default_print_format = cur_frm.pos_print_format;
}
+ } else if(cur_frm.doc.is_return) {
+ if(cur_frm.return_print_format) {
+ cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
+ cur_frm.meta.default_print_format = cur_frm.return_print_format;
+ }
} else {
if(cur_frm.meta._default_print_format) {
cur_frm.meta.default_print_format = cur_frm.meta._default_print_format;
cur_frm.meta._default_print_format = null;
+ } else if(in_list([cur_frm.pos_print_format, cur_frm.return_print_format], cur_frm.meta.default_print_format)) {
+ cur_frm.meta.default_print_format = null;
+ cur_frm.meta._default_print_format = null;
}
}
},
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index 9a01484..be1448d 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -93,6 +93,7 @@
def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
if not from_repost:
validate_account_for_perpetual_inventory(gl_map)
+ validate_cwip_accounts(gl_map)
round_off_debit_credit(gl_map)
@@ -123,6 +124,16 @@
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
.format(entry.account), StockAccountInvalidTransaction)
+def validate_cwip_accounts(gl_map):
+ if not cint(frappe.db.get_value("Asset Settings", None, "disable_cwip_accounting")) \
+ and gl_map[0].voucher_type == "Journal Entry":
+ cwip_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
+ where account_type = 'Capital Work in Progress' and is_group=0""")]
+
+ for entry in gl_map:
+ if entry.account in cwip_accounts:
+ frappe.throw(_("Account: <b>{0}</b> is capital Work in progress and can not be updated by Journal Entry").format(entry.account))
+
def round_off_debit_credit(gl_map):
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency"))
diff --git a/erpnext/accounts/print_format/sales_invoice_return/__init__.py b/erpnext/accounts/print_format/sales_invoice_return/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/print_format/sales_invoice_return/__init__.py
diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html
new file mode 100644
index 0000000..889b7f7
--- /dev/null
+++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html
@@ -0,0 +1,129 @@
+{%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value, fieldmeta,
+ get_width, get_align_class -%}
+
+{%- macro render_currency(df, doc) -%}
+<div class="row {% if df.bold %}important{% endif %} data-field">
+ <div class="col-xs-{{ "9" if df.fieldtype=="Check" else "5" }}
+ {%- if doc._align_labels_right %} text-right{%- endif -%}">
+ <label>{{ _(df.label) }}</label>
+ </div>
+ <div class="col-xs-{{ "3" if df.fieldtype=="Check" else "7" }} value">
+ {% if doc.get(df.fieldname) != None -%}
+ {{ frappe.utils.fmt_money((doc[df.fieldname])|int|abs, currency=doc.currency) }}
+ {% endif %}
+ </div>
+</div>
+{%- endmacro -%}
+
+{%- macro render_taxes(df, doc) -%}
+ {%- set data = doc.get(df.fieldname)[df.start:df.end] -%}
+ <div class="row">
+ <div class="col-xs-6"></div>
+ <div class="col-xs-6">
+ {%- for charge in data -%}
+ {%- if (charge.tax_amount or doc.flags.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
+ <div class="row">
+ <div class="col-xs-5 {%- if doc._align_labels_right %} text-right{%- endif -%}">
+ <label>{{ charge.get_formatted("description") }}</label></div>
+ <div class="col-xs-7 text-right">
+ {{ frappe.utils.fmt_money((charge.tax_amount)|int|abs, currency=doc.currency) }}
+ </div>
+ </div>
+ {%- endif -%}
+ {%- endfor -%}
+ </div>
+ </div>
+{%- endmacro -%}
+
+{%- macro render_table(df, doc) -%}
+ {%- set table_meta = frappe.get_meta(df.options) -%}
+ {%- set data = doc.get(df.fieldname)[df.start:df.end] -%}
+ {%- if doc.print_templates and
+ doc.print_templates.get(df.fieldname) -%}
+ {% include doc.print_templates[df.fieldname] %}
+ {%- else -%}
+ {%- if data -%}
+ {%- set visible_columns = get_visible_columns(doc.get(df.fieldname),
+ table_meta, df) -%}
+ <div {{ fieldmeta(df) }}>
+ <table class="table table-bordered table-condensed">
+ <thead>
+ <tr>
+ <th style="width: 40px" class="table-sr">{{ _("Sr") }}</th>
+ {% for tdf in visible_columns %}
+ {% if (data and not data[0].flags.compact_item_print) or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %}
+ <th style="width: {{ get_width(tdf) }};" class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
+ {{ _(tdf.label) }}</th>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ </thead>
+ <tbody>
+ {% for d in data %}
+ <tr>
+ <td class="table-sr">{{ d.idx }}</td>
+ {% for tdf in visible_columns %}
+ {% if not d.flags.compact_item_print or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %}
+ <td class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
+ {% if tdf.fieldtype == 'Currency' %}
+ <div class="value">{{ frappe.utils.fmt_money((d[tdf.fieldname])|int|abs, currency=doc.currency) }}</div></td>
+ {% else %}
+ <div class="value">{{ print_value(tdf, d, doc, visible_columns) }}</div></td>
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div>
+ {%- endif -%}
+ {%- endif -%}
+{%- endmacro -%}
+
+{% for page in layout %}
+<div class="page-break">
+ <div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
+ {{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}
+ </div>
+
+ {% if print_settings.repeat_header_footer %}
+ <div id="footer-html" class="visible-pdf">
+ {% if not no_letterhead and footer %}
+ <div class="letter-head-footer">
+ {{ footer }}
+ </div>
+ {% endif %}
+ <p class="text-center small page-number visible-pdf">
+ {{ _("Page {0} of {1}").format('<span class="page"></span>', '<span class="topage"></span>') }}
+ </p>
+ </div>
+ {% endif %}
+
+ {% for section in page %}
+ <div class="row section-break">
+ {% if section.columns.fields %}
+ {%- if doc._line_breaks and loop.index != 1 -%}<hr>{%- endif -%}
+ {%- if doc._show_section_headings and section.label and section.has_data -%}
+ <h4 class='col-sm-12'>{{ _(section.label) }}</h4>
+ {% endif %}
+ {%- endif -%}
+ {% for column in section.columns %}
+ <div class="col-xs-{{ (12 / section.columns|len)|int }} column-break">
+ {% for df in column.fields %}
+ {% if df.fieldname == 'taxes' %}
+ {{ render_taxes(df, doc) }}
+ {% elif df.fieldtype == 'Currency' %}
+ {{ render_currency(df, doc) }}
+ {% elif df.fieldtype =='Table' %}
+ {{ render_table(df, doc)}}
+ {% elif doc[df.fieldname] %}
+ {{ render_field(df, doc) }}
+ {% endif %}
+ {% endfor %}
+ </div>
+ {% endfor %}
+ </div>
+ {% endfor %}
+</div>
+{% endfor %}
diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json
new file mode 100644
index 0000000..352b549
--- /dev/null
+++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json
@@ -0,0 +1,24 @@
+{
+ "align_labels_right": 1,
+ "creation": "2019-07-24 20:13:30.259953",
+ "custom_format": 0,
+ "default_print_language": "en-US",
+ "disabled": 0,
+ "doc_type": "Sales Invoice",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "",
+ "idx": 0,
+ "line_breaks": 1,
+ "modified": "2019-07-24 20:13:30.259953",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Sales Invoice Return",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 1,
+ "standard": "Yes"
+}
\ No newline at end of file
diff --git a/erpnext/buying/utils.py b/erpnext/buying/utils.py
index 981ee5d..8c0a1e5 100644
--- a/erpnext/buying/utils.py
+++ b/erpnext/buying/utils.py
@@ -30,7 +30,9 @@
# for it to be considered for latest purchase rate
if flt(d.conversion_factor):
last_purchase_rate = flt(d.base_rate) / flt(d.conversion_factor)
- else:
+ # Check if item code is present
+ # Conversion factor should not be mandatory for non itemized items
+ elif d.item_code:
frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx))
# update last purchsae rate
@@ -84,13 +86,13 @@
items = json.loads(items)
mr_list = []
for item in items:
- material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name,
- (mr_item.qty - mr_item.ordered_qty) AS qty,
+ material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name,
+ (mr_item.qty - mr_item.ordered_qty) AS qty,
mr_item.item_code AS item_code,
- mr_item.name AS mr_item
+ mr_item.name AS mr_item
FROM `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
WHERE mr.name = mr_item.parent
- AND mr_item.item_code = %(item)s
+ AND mr_item.item_code = %(item)s
AND mr.material_request_type = 'Purchase'
AND mr.per_ordered < 99.99
AND mr.docstatus = 1
@@ -98,6 +100,6 @@
ORDER BY mr_item.item_code ASC""",{"item": item}, as_dict=1)
if material_request:
mr_list.append(material_request)
-
+
return mr_list
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index ca59a39..4a89c5b 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -60,7 +60,9 @@
def validate(self):
- self.validate_qty_is_not_zero()
+ if not self.get('is_return'):
+ self.validate_qty_is_not_zero()
+
if self.get("_action") and self._action != "update_after_submit":
self.set_missing_values(for_validate=True)
@@ -1190,6 +1192,10 @@
.format(child_item.idx, child_item.item_code))
else:
child_item.rate = flt(d.get("rate"))
+ if child_item.price_list_rate:
+ child_item.discount_percentage = flt((1 - flt(child_item.rate) / flt(child_item.price_list_rate)) * 100.0, \
+ child_item.precision("discount_percentage"))
+
child_item.flags.ignore_validate_update_after_submit = True
if new_child_flag:
child_item.idx = len(parent.items) + 1
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 0b4d38c..588f74d 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -395,7 +395,9 @@
def set_qty_as_per_stock_uom(self):
for d in self.get("items"):
if d.meta.get_field("stock_qty"):
- if not d.conversion_factor:
+ # Check if item code is present
+ # Conversion factor should not be mandatory for non itemized items
+ if not d.conversion_factor and d.item_code:
frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx))
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 8d24e7a..d2db9d0 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -81,7 +81,12 @@
item.discount_amount = item.price_list_rate - item.rate
item.net_rate = item.rate
- item.amount = flt(item.rate * item.qty, item.precision("amount"))
+
+ if not item.qty and self.doc.get("is_return"):
+ item.amount = flt(-1 * item.rate, item.precision("amount"))
+ else:
+ item.amount = flt(item.rate * item.qty, item.precision("amount"))
+
item.net_amount = item.amount
self._set_in_company_currency(item, ["price_list_rate", "rate", "net_rate", "amount", "net_amount"])
diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py
index ed48fd1..187eaed 100644
--- a/erpnext/controllers/website_list_for_contact.py
+++ b/erpnext/controllers/website_list_for_contact.py
@@ -77,7 +77,7 @@
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)
@@ -130,38 +130,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, filters=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.party_type = '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/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index 1c8b5f9..7813da7 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -64,13 +64,20 @@
def update_claimed_amount(self):
claimed_amount = frappe.db.sql("""
- select sum(ifnull(allocated_amount, 0))
- from `tabExpense Claim Advance`
- where employee_advance = %s and docstatus=1 and allocated_amount > 0
+ SELECT sum(ifnull(allocated_amount, 0))
+ FROM `tabExpense Claim Advance` eca, `tabExpense Claim` ec
+ WHERE
+ eca.employee_advance = %s
+ AND ec.approval_status="Approved"
+ AND ec.name = eca.parent
+ AND ec.docstatus=1
+ AND eca.allocated_amount > 0
""", self.name)[0][0] or 0
- if claimed_amount:
- frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
+ frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
+ self.reload()
+ self.set_status()
+ frappe.db.set_value("Employee Advance", self.name, "status", self.status)
@frappe.whitelist()
def get_due_advance_amount(employee, posting_date):
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js
index 40bec6d..6d3a28e 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.js
@@ -183,7 +183,7 @@
refresh: function(frm) {
frm.trigger("toggle_fields");
- if(frm.doc.docstatus == 1) {
+ if(frm.doc.docstatus === 1 && frm.doc.approval_status !== "Rejected") {
frm.add_custom_button(__('Accounting Ledger'), function() {
frappe.route_options = {
voucher_no: frm.doc.name,
@@ -194,7 +194,7 @@
}, __("View"));
}
- if (frm.doc.docstatus===1
+ if (frm.doc.docstatus===1 && !cint(frm.doc.is_paid) && cint(frm.doc.grand_total) > 0
&& (cint(frm.doc.total_amount_reimbursed) < cint(frm.doc.total_sanctioned_amount))
&& frappe.model.can_create("Payment Entry")) {
frm.add_custom_button(__('Payment'),
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 3a77e2f..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)
@@ -430,7 +431,7 @@
continue
item_list.append(['', '', '', '', bin_dict.get('warehouse'),
- bin_dict.get('projected_qty'), bin_dict.get('actual_qty')])
+ bin_dict.get('projected_qty', 0), bin_dict.get('actual_qty', 0)])
build_csv_response(item_list, doc.name)
@@ -507,8 +508,8 @@
required_qty = 0
if ignore_existing_ordered_qty or bin_dict.get("projected_qty", 0) < 0:
required_qty = total_qty
- elif total_qty > bin_dict.get("projected_qty"):
- required_qty = total_qty - bin_dict.get("projected_qty")
+ elif total_qty > bin_dict.get("projected_qty", 0):
+ required_qty = total_qty - bin_dict.get("projected_qty", 0)
if required_qty > 0 and required_qty < row['min_order_qty']:
required_qty = row['min_order_qty']
item_group_defaults = get_item_group_defaults(row.item_code, company)
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/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 50557f1..492eabe 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -145,7 +145,7 @@
def populate_depends_on(self):
if self.parent_task:
- parent = frappe.get_cached_doc('Task', self.parent_task)
+ parent = frappe.get_doc('Task', self.parent_task)
if not self.name in [row.task for row in parent.depends_on]:
parent.append("depends_on", {
"doctype": "Task Depends On",
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 91800cd..7cf2181 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -92,7 +92,13 @@
$.each(this.frm.doc["items"] || [], function(i, item) {
frappe.model.round_floats_in(item);
item.net_rate = item.rate;
- item.amount = flt(item.rate * item.qty, precision("amount", item));
+
+ if ((!item.qty) && me.frm.doc.is_return) {
+ item.amount = flt(item.rate * -1, precision("amount", item));
+ } else {
+ item.amount = flt(item.rate * item.qty, precision("amount", item));
+ }
+
item.net_amount = item.amount;
item.item_tax_amount = 0.0;
item.total_weight = flt(item.weight_per_unit * item.stock_qty);
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/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 39dda92..2e5f255 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -255,27 +255,44 @@
});
return;
} else {
- var fields = [
- {fieldtype:'Table', fieldname: 'items',
- description: __('Select BOM and Qty for Production'),
- fields: [
- {fieldtype:'Read Only', fieldname:'item_code',
- label: __('Item Code'), in_list_view:1},
- {fieldtype:'Link', fieldname:'bom', options: 'BOM', reqd: 1,
- label: __('Select BOM'), in_list_view:1, get_query: function(doc) {
- return {filters: {item: doc.item_code}};
- }},
- {fieldtype:'Float', fieldname:'pending_qty', reqd: 1,
- label: __('Qty'), in_list_view:1},
- {fieldtype:'Data', fieldname:'sales_order_item', reqd: 1,
- label: __('Sales Order Item'), hidden:1}
- ],
- data: r.message,
- get_data: function() {
- return r.message
+ const fields = [{
+ label: 'Items',
+ fieldtype: 'Table',
+ fieldname: 'items',
+ description: __('Select BOM and Qty for Production'),
+ fields: [{
+ fieldtype: 'Read Only',
+ fieldname: 'item_code',
+ label: __('Item Code'),
+ in_list_view: 1
+ }, {
+ fieldtype: 'Link',
+ fieldname: 'bom',
+ options: 'BOM',
+ reqd: 1,
+ label: __('Select BOM'),
+ in_list_view: 1,
+ get_query: function (doc) {
+ return { filters: { item: doc.item_code } };
}
+ }, {
+ fieldtype: 'Float',
+ fieldname: 'pending_qty',
+ reqd: 1,
+ label: __('Qty'),
+ in_list_view: 1
+ }, {
+ fieldtype: 'Data',
+ fieldname: 'sales_order_item',
+ reqd: 1,
+ label: __('Sales Order Item'),
+ hidden: 1
+ }],
+ data: r.message,
+ get_data: () => {
+ return r.message
}
- ]
+ }]
var d = new frappe.ui.Dialog({
title: __('Select Items to Manufacture'),
fields: fields,
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
index 62bde42..0922f3d 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -251,13 +251,12 @@
if quotation:
qdoc = frappe.get_doc("Quotation", quotation[0].name)
else:
- [company, price_list] = frappe.db.get_value("Shopping Cart Settings", None, ["company", "price_list"])
+ company = frappe.db.get_value("Shopping Cart Settings", None, ["company"])
qdoc = frappe.get_doc({
"doctype": "Quotation",
"naming_series": get_shopping_cart_settings().quotation_series or "QTN-CART-",
"quotation_to": party.doctype,
"company": company,
- "selling_price_list": price_list,
"order_type": "Shopping Cart",
"status": "Draft",
"docstatus": 0,
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index b530332..6e81dd0 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/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index ff5b026..5fda2a4 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -363,8 +363,17 @@
self.stock_queue.append([0, sle.incoming_rate or sle.outgoing_rate or self.valuation_rate])
def check_if_allow_zero_valuation_rate(self, voucher_type, voucher_detail_no):
- ref_item_dt = voucher_type + (" Detail" if voucher_type == "Stock Entry" else " Item")
- return frappe.db.get_value(ref_item_dt, voucher_detail_no, "allow_zero_valuation_rate")
+ ref_item_dt = ""
+
+ if voucher_type == "Stock Entry":
+ ref_item_dt = voucher_type + " Detail"
+ elif voucher_type in ["Purchase Invoice", "Sales Invoice", "Delivery Note", "Purchase Receipt"]:
+ ref_item_dt = voucher_type + " Item"
+
+ if ref_item_dt:
+ return frappe.db.get_value(ref_item_dt, voucher_detail_no, "allow_zero_valuation_rate")
+ else:
+ return 0
def get_sle_before_datetime(self):
"""get previous stock ledger entry before current time-bucket"""
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index 48e341a..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "lockfileVersion": 1
-}