Merge branch 'develop' into healthcare_refactor
This commit is contained in:
commit
9f6bf71b95
@ -4,15 +4,17 @@
|
|||||||
// attach required files
|
// attach required files
|
||||||
{% include 'erpnext/public/js/controllers/buying.js' %};
|
{% include 'erpnext/public/js/controllers/buying.js' %};
|
||||||
|
|
||||||
frappe.ui.form.on('Suppier Quotation', {
|
|
||||||
setup: function(frm) {
|
|
||||||
frm.custom_make_buttons = {
|
|
||||||
'Purchase Order': 'Purchase Order'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
|
erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
|
||||||
|
setup: function() {
|
||||||
|
this.frm.custom_make_buttons = {
|
||||||
|
'Purchase Order': 'Purchase Order',
|
||||||
|
'Quotation': 'Quotation',
|
||||||
|
'Subscription': 'Subscription'
|
||||||
|
}
|
||||||
|
|
||||||
|
this._super();
|
||||||
|
},
|
||||||
|
|
||||||
refresh: function() {
|
refresh: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
this._super();
|
this._super();
|
||||||
|
|||||||
@ -135,10 +135,17 @@ class Lead(SellingController):
|
|||||||
|
|
||||||
# do not create an address if no fields are available,
|
# do not create an address if no fields are available,
|
||||||
# skipping country since the system auto-sets it from system defaults
|
# skipping country since the system auto-sets it from system defaults
|
||||||
if not any([self.get(field) for field in address_fields if field != "country"]):
|
address = frappe.new_doc("Address")
|
||||||
|
|
||||||
|
mandatory_fields = [ df.fieldname for df in address.meta.fields if df.reqd ]
|
||||||
|
|
||||||
|
if not all([self.get(field) for field in mandatory_fields]):
|
||||||
|
frappe.msgprint(_('Missing mandatory fields in address. \
|
||||||
|
{0} to create address' ).format("<a href='desk#Form/Address/New Address 1' \
|
||||||
|
> Click here </a>"),
|
||||||
|
alert=True, indicator='yellow')
|
||||||
return
|
return
|
||||||
|
|
||||||
address = frappe.new_doc("Address")
|
|
||||||
address.update({addr_field: self.get(addr_field) for addr_field in address_fields})
|
address.update({addr_field: self.get(addr_field) for addr_field in address_fields})
|
||||||
address.update({info_field: self.get(info_field) for info_field in info_fields})
|
address.update({info_field: self.get(info_field) for info_field in info_fields})
|
||||||
address.insert()
|
address.insert()
|
||||||
|
|||||||
@ -43,8 +43,7 @@ frappe.ui.form.on("BOM", {
|
|||||||
|
|
||||||
frm.set_query("item_code", "items", function() {
|
frm.set_query("item_code", "items", function() {
|
||||||
return {
|
return {
|
||||||
query: "erpnext.controllers.queries.item_query",
|
query: "erpnext.controllers.queries.item_query"
|
||||||
filters: [["Item", "name", "!=", cur_frm.doc.item]]
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -114,10 +114,6 @@ class BOM(WebsiteGenerator):
|
|||||||
child = self.append('operations', d)
|
child = self.append('operations', d)
|
||||||
child.hour_rate = flt(d.hour_rate / self.conversion_rate, 2)
|
child.hour_rate = flt(d.hour_rate / self.conversion_rate, 2)
|
||||||
|
|
||||||
def validate_rm_item(self, item):
|
|
||||||
if (item[0]['name'] in [it.item_code for it in self.items]) and item[0]['name'] == self.item:
|
|
||||||
frappe.throw(_("BOM #{0}: Raw material cannot be same as main Item").format(self.name))
|
|
||||||
|
|
||||||
def set_bom_material_details(self):
|
def set_bom_material_details(self):
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
self.validate_bom_currecny(item)
|
self.validate_bom_currecny(item)
|
||||||
@ -147,7 +143,6 @@ class BOM(WebsiteGenerator):
|
|||||||
args = json.loads(args)
|
args = json.loads(args)
|
||||||
|
|
||||||
item = self.get_item_det(args['item_code'])
|
item = self.get_item_det(args['item_code'])
|
||||||
self.validate_rm_item(item)
|
|
||||||
|
|
||||||
args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or ''
|
args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or ''
|
||||||
args['transfer_for_manufacture'] = (cstr(args.get('include_item_in_manufacturing', '')) or
|
args['transfer_for_manufacture'] = (cstr(args.get('include_item_in_manufacturing', '')) or
|
||||||
|
|||||||
@ -144,7 +144,7 @@ class ProductionPlan(Document):
|
|||||||
item_condition = " and mr_item.item_code ={0}".format(frappe.db.escape(self.item_code))
|
item_condition = " and mr_item.item_code ={0}".format(frappe.db.escape(self.item_code))
|
||||||
|
|
||||||
items = frappe.db.sql("""select distinct parent, name, item_code, warehouse, description,
|
items = frappe.db.sql("""select distinct parent, name, item_code, warehouse, description,
|
||||||
(qty - ordered_qty) as pending_qty
|
(qty - ordered_qty) * conversion_factor as pending_qty
|
||||||
from `tabMaterial Request Item` mr_item
|
from `tabMaterial Request Item` mr_item
|
||||||
where parent in (%s) and docstatus = 1 and qty > ordered_qty
|
where parent in (%s) and docstatus = 1 and qty > ordered_qty
|
||||||
and exists (select name from `tabBOM` bom where bom.item=mr_item.item_code
|
and exists (select name from `tabBOM` bom where bom.item=mr_item.item_code
|
||||||
|
|||||||
@ -552,24 +552,33 @@ class WorkOrder(Document):
|
|||||||
d.db_set('transferred_qty', flt(transferred_qty), update_modified = False)
|
d.db_set('transferred_qty', flt(transferred_qty), update_modified = False)
|
||||||
|
|
||||||
def update_consumed_qty_for_required_items(self):
|
def update_consumed_qty_for_required_items(self):
|
||||||
'''update consumed qty from submitted stock entries for that item against
|
'''
|
||||||
the work order'''
|
Update consumed qty from submitted stock entries
|
||||||
|
against a work order for each stock item
|
||||||
|
'''
|
||||||
|
|
||||||
for d in self.required_items:
|
for item in self.required_items:
|
||||||
consumed_qty = frappe.db.sql('''select sum(qty)
|
consumed_qty = frappe.db.sql('''
|
||||||
from `tabStock Entry` entry, `tabStock Entry Detail` detail
|
SELECT
|
||||||
where
|
SUM(qty)
|
||||||
|
FROM
|
||||||
|
`tabStock Entry` entry,
|
||||||
|
`tabStock Entry Detail` detail
|
||||||
|
WHERE
|
||||||
entry.work_order = %(name)s
|
entry.work_order = %(name)s
|
||||||
and (entry.purpose = "Material Consumption for Manufacture"
|
AND (entry.purpose = "Material Consumption for Manufacture"
|
||||||
or entry.purpose = "Manufacture")
|
OR entry.purpose = "Manufacture")
|
||||||
and entry.docstatus = 1
|
AND entry.docstatus = 1
|
||||||
and detail.parent = entry.name
|
AND detail.parent = entry.name
|
||||||
and (detail.item_code = %(item)s or detail.original_item = %(item)s)''', {
|
AND detail.s_warehouse IS NOT null
|
||||||
|
AND (detail.item_code = %(item)s
|
||||||
|
OR detail.original_item = %(item)s)
|
||||||
|
''', {
|
||||||
'name': self.name,
|
'name': self.name,
|
||||||
'item': d.item_code
|
'item': item.item_code
|
||||||
})[0][0]
|
})[0][0]
|
||||||
|
|
||||||
d.db_set('consumed_qty', flt(consumed_qty), update_modified = False)
|
item.db_set('consumed_qty', flt(consumed_qty), update_modified=False)
|
||||||
|
|
||||||
def make_bom(self):
|
def make_bom(self):
|
||||||
data = frappe.db.sql(""" select sed.item_code, sed.qty, sed.s_warehouse
|
data = frappe.db.sql(""" select sed.item_code, sed.qty, sed.s_warehouse
|
||||||
|
|||||||
@ -496,7 +496,7 @@ def close_or_unclose_sales_orders(names, status):
|
|||||||
|
|
||||||
def get_requested_item_qty(sales_order):
|
def get_requested_item_qty(sales_order):
|
||||||
return frappe._dict(frappe.db.sql("""
|
return frappe._dict(frappe.db.sql("""
|
||||||
select sales_order_item, sum(stock_qty)
|
select sales_order_item, sum(qty)
|
||||||
from `tabMaterial Request Item`
|
from `tabMaterial Request Item`
|
||||||
where docstatus = 1
|
where docstatus = 1
|
||||||
and sales_order = %s
|
and sales_order = %s
|
||||||
@ -507,16 +507,12 @@ def get_requested_item_qty(sales_order):
|
|||||||
def make_material_request(source_name, target_doc=None):
|
def make_material_request(source_name, target_doc=None):
|
||||||
requested_item_qty = get_requested_item_qty(source_name)
|
requested_item_qty = get_requested_item_qty(source_name)
|
||||||
|
|
||||||
def postprocess(source, doc):
|
|
||||||
doc.material_request_type = "Purchase"
|
|
||||||
|
|
||||||
def update_item(source, target, source_parent):
|
def update_item(source, target, source_parent):
|
||||||
# qty is for packed items, because packed items don't have stock_qty field
|
# qty is for packed items, because packed items don't have stock_qty field
|
||||||
qty = source.get("stock_qty") or source.get("qty")
|
qty = source.get("qty")
|
||||||
target.project = source_parent.project
|
target.project = source_parent.project
|
||||||
target.qty = qty - requested_item_qty.get(source.name, 0)
|
target.qty = qty - requested_item_qty.get(source.name, 0)
|
||||||
target.conversion_factor = 1
|
target.stock_qty = flt(target.qty) * flt(target.conversion_factor)
|
||||||
target.stock_qty = qty - requested_item_qty.get(source.name, 0)
|
|
||||||
|
|
||||||
doc = get_mapped_doc("Sales Order", source_name, {
|
doc = get_mapped_doc("Sales Order", source_name, {
|
||||||
"Sales Order": {
|
"Sales Order": {
|
||||||
@ -537,14 +533,12 @@ def make_material_request(source_name, target_doc=None):
|
|||||||
"doctype": "Material Request Item",
|
"doctype": "Material Request Item",
|
||||||
"field_map": {
|
"field_map": {
|
||||||
"name": "sales_order_item",
|
"name": "sales_order_item",
|
||||||
"parent": "sales_order",
|
"parent": "sales_order"
|
||||||
"stock_uom": "uom",
|
|
||||||
"stock_qty": "qty"
|
|
||||||
},
|
},
|
||||||
"condition": lambda doc: not frappe.db.exists('Product Bundle', doc.item_code) and doc.stock_qty > requested_item_qty.get(doc.name, 0),
|
"condition": lambda doc: not frappe.db.exists('Product Bundle', doc.item_code) and doc.stock_qty > requested_item_qty.get(doc.name, 0),
|
||||||
"postprocess": update_item
|
"postprocess": update_item
|
||||||
}
|
}
|
||||||
}, target_doc, postprocess)
|
}, target_doc)
|
||||||
|
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
|||||||
@ -64,29 +64,39 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p
|
|||||||
for d in item_prices_data:
|
for d in item_prices_data:
|
||||||
item_prices[d.item_code] = d
|
item_prices[d.item_code] = d
|
||||||
|
|
||||||
|
# prepare filter for bin query
|
||||||
if display_items_in_stock:
|
bin_filters = {'item_code': ['in', items]}
|
||||||
filters = {'actual_qty': [">", 0], 'item_code': ['in', items]}
|
|
||||||
|
|
||||||
if warehouse:
|
if warehouse:
|
||||||
filters['warehouse'] = warehouse
|
bin_filters['warehouse'] = warehouse
|
||||||
|
if display_items_in_stock:
|
||||||
|
bin_filters['actual_qty'] = [">", 0]
|
||||||
|
|
||||||
bin_data = frappe._dict(
|
# query item bin
|
||||||
frappe.get_all("Bin", fields = ["item_code", "sum(actual_qty) as actual_qty"],
|
bin_data = frappe.get_all(
|
||||||
filters = filters, group_by = "item_code")
|
'Bin', fields=['item_code', 'sum(actual_qty) as actual_qty'],
|
||||||
|
filters=bin_filters, group_by='item_code'
|
||||||
)
|
)
|
||||||
|
|
||||||
for item in items_data:
|
# convert list of dict into dict as {item_code: actual_qty}
|
||||||
row = {}
|
bin_dict = {}
|
||||||
|
for b in bin_data:
|
||||||
|
bin_dict[b.get('item_code')] = b.get('actual_qty')
|
||||||
|
|
||||||
|
for item in items_data:
|
||||||
|
item_code = item.item_code
|
||||||
|
item_price = item_prices.get(item_code) or {}
|
||||||
|
item_stock_qty = bin_dict.get(item_code)
|
||||||
|
|
||||||
|
if display_items_in_stock and not item_stock_qty:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
row = {}
|
||||||
row.update(item)
|
row.update(item)
|
||||||
item_price = item_prices.get(item.item_code) or {}
|
|
||||||
row.update({
|
row.update({
|
||||||
'price_list_rate': item_price.get('price_list_rate'),
|
'price_list_rate': item_price.get('price_list_rate'),
|
||||||
'currency': item_price.get('currency'),
|
'currency': item_price.get('currency'),
|
||||||
'actual_qty': bin_data.get('actual_qty')
|
'actual_qty': item_stock_qty,
|
||||||
})
|
})
|
||||||
|
|
||||||
result.append(row)
|
result.append(row)
|
||||||
|
|
||||||
res = {
|
res = {
|
||||||
|
|||||||
@ -501,7 +501,7 @@ def raise_work_orders(material_request):
|
|||||||
wo_order = frappe.new_doc("Work Order")
|
wo_order = frappe.new_doc("Work Order")
|
||||||
wo_order.update({
|
wo_order.update({
|
||||||
"production_item": d.item_code,
|
"production_item": d.item_code,
|
||||||
"qty": d.qty - d.ordered_qty,
|
"qty": d.stock_qty - d.ordered_qty,
|
||||||
"fg_warehouse": d.warehouse,
|
"fg_warehouse": d.warehouse,
|
||||||
"wip_warehouse": default_wip_warehouse,
|
"wip_warehouse": default_wip_warehouse,
|
||||||
"description": d.description,
|
"description": d.description,
|
||||||
|
|||||||
@ -238,7 +238,7 @@ class StockEntry(StockController):
|
|||||||
if self.purpose == "Manufacture" and self.work_order:
|
if self.purpose == "Manufacture" and self.work_order:
|
||||||
production_item = frappe.get_value('Work Order', self.work_order, 'production_item')
|
production_item = frappe.get_value('Work Order', self.work_order, 'production_item')
|
||||||
for item in self.items:
|
for item in self.items:
|
||||||
if item.item_code == production_item and item.qty != self.fg_completed_qty:
|
if item.item_code == production_item and item.t_warehouse and item.qty != self.fg_completed_qty:
|
||||||
frappe.throw(_("Finished product quantity <b>{0}</b> and For Quantity <b>{1}</b> cannot be different")
|
frappe.throw(_("Finished product quantity <b>{0}</b> and For Quantity <b>{1}</b> cannot be different")
|
||||||
.format(item.qty, self.fg_completed_qty))
|
.format(item.qty, self.fg_completed_qty))
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user