[New Feature] Sample Retention from a Batch of item recieved (#11624)
This commit is contained in:
parent
5c62368a65
commit
f6aff3de96
BIN
erpnext/docs/assets/img/stock/material-receipt-sample.png
Normal file
BIN
erpnext/docs/assets/img/stock/material-receipt-sample.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 79 KiB |
BIN
erpnext/docs/assets/img/stock/material-transfer-sample.png
Normal file
BIN
erpnext/docs/assets/img/stock/material-transfer-sample.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 244 KiB |
BIN
erpnext/docs/assets/img/stock/retain-sample.png
Normal file
BIN
erpnext/docs/assets/img/stock/retain-sample.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
BIN
erpnext/docs/assets/img/stock/sample-warehouse.png
Normal file
BIN
erpnext/docs/assets/img/stock/sample-warehouse.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 88 KiB |
@ -16,3 +16,4 @@ purchase-return
|
||||
articles
|
||||
opening-stock
|
||||
stock-how-to
|
||||
retain-sample-stock
|
26
erpnext/docs/user/manual/en/stock/retain-sample-stock.md
Normal file
26
erpnext/docs/user/manual/en/stock/retain-sample-stock.md
Normal file
@ -0,0 +1,26 @@
|
||||
# Retain Sample Stock
|
||||
|
||||
A sample of a batch of starting material, packaging material or finished product is stored for the purpose of being analyzed should the need arise later.
|
||||
|
||||
### Set Sample Retention Warehouse in Stock Settings
|
||||
|
||||
It is advised to create a new warehouse just for retaining samples and not use it in production.
|
||||
|
||||
<img class="screenshot" alt="Sample Retention Warehouse" src="/docs/assets/img/stock/sample-warehouse.png">
|
||||
|
||||
### Enable Retain Sample in Item master
|
||||
|
||||
Check Retain Sample and Maximum allowed samples in Item Master for a batch. Please note that Retain Sample is based
|
||||
on Batch hence Has Batch No should be enabled as well.
|
||||
|
||||
<img class="screenshot" alt="Retain Sample" src="/docs/assets/img/stock/retain-sample.png">
|
||||
|
||||
### Stock Entry
|
||||
|
||||
Whenever a Stock Entry is created with the purpose as Material Receipt, for items which have Retain Sample enabled, the Sample Quantity can be set during that Stock Entry. Sample quantity cannot be more than the Maximum sample quantity set in Item Master.
|
||||
|
||||
<img class="screenshot" alt="Retain Sample" src="/docs/assets/img/stock/material-receipt-sample.png">
|
||||
|
||||
On submission of this Stock Entry, button 'Make Retention Stock Entry' will be available to make another Stock Entry for the transfer of sample items from the mentioned batch to the retention warehouse set in Stock Settings. On clicking this button it will direct you to new Stock Entry with all the information, verify the information and click Submit.
|
||||
|
||||
<img class="screenshot" alt="Retain Sample" src="/docs/assets/img/stock/material-transfer-sample.png">
|
@ -1183,6 +1183,38 @@
|
||||
"set_only_once": 1,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "has_batch_no",
|
||||
"description": "",
|
||||
"fieldname": "create_new_batch",
|
||||
"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": "Automatically Create New Batch",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -1221,8 +1253,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "has_batch_no",
|
||||
"description": "",
|
||||
"fieldname": "create_new_batch",
|
||||
"fieldname": "retain_sample",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@ -1231,7 +1262,39 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Automatically Create New Batch",
|
||||
"label": "Retain Sample",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval: (doc.retain_sample && doc.has_batch_no)",
|
||||
"description": "Maximum sample quantity that can be retained",
|
||||
"fieldname": "sample_quantity",
|
||||
"fieldtype": "Int",
|
||||
"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": "Max Sample Quantity",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -3360,7 +3423,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 1,
|
||||
"modified": "2017-11-20 12:18:07.259756",
|
||||
"modified": "2017-12-04 15:37:58.413290",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Item",
|
||||
|
@ -97,6 +97,7 @@ class Item(WebsiteGenerator):
|
||||
self.validate_website_image()
|
||||
self.make_thumbnail()
|
||||
self.validate_fixed_asset()
|
||||
self.validate_retain_sample()
|
||||
|
||||
if not self.get("__islocal"):
|
||||
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
|
||||
@ -256,6 +257,12 @@ class Item(WebsiteGenerator):
|
||||
if asset:
|
||||
frappe.throw(_('"Is Fixed Asset" cannot be unchecked, as Asset record exists against the item'))
|
||||
|
||||
def validate_retain_sample(self):
|
||||
if self.retain_sample and not frappe.db.get_single_value('Stock Settings', 'sample_retention_warehouse'):
|
||||
frappe.throw(_("Please select Sample Retention Warehouse in Stock Settings first"));
|
||||
if self.retain_sample and not self.has_batch_no:
|
||||
frappe.throw(_(" {0} Retain Sample is based on batch, please check Has Batch No to retain sample of item").format(self.item_code))
|
||||
|
||||
def get_context(self, context):
|
||||
context.show_search=True
|
||||
context.search_link = '/product_search'
|
||||
|
@ -98,6 +98,7 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
|
||||
if(flt(this.frm.doc.per_billed) < 100) {
|
||||
cur_frm.add_custom_button(__('Invoice'), this.make_purchase_invoice, __("Make"));
|
||||
}
|
||||
cur_frm.add_custom_button(__('Retention Stock Entry'), this.make_retention_stock_entry, __("Make"));
|
||||
|
||||
if(!this.frm.doc.subscription) {
|
||||
cur_frm.add_custom_button(__('Subscription'), function() {
|
||||
@ -137,7 +138,26 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
|
||||
|
||||
reopen_purchase_receipt: function() {
|
||||
cur_frm.cscript.update_status("Submitted");
|
||||
}
|
||||
},
|
||||
|
||||
make_retention_stock_entry: function() {
|
||||
frappe.call({
|
||||
method: "erpnext.stock.doctype.stock_entry.stock_entry.move_sample_to_retention_warehouse",
|
||||
args:{
|
||||
"company": cur_frm.doc.company,
|
||||
"items": cur_frm.doc.items
|
||||
},
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
var doc = frappe.model.sync(r.message)[0];
|
||||
frappe.set_route("Form", doc.doctype, doc.name);
|
||||
}
|
||||
else {
|
||||
frappe.msgprint(__("Retention Stock Entry already created or Sample Quantity not provided"));
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
@ -206,3 +226,36 @@ frappe.ui.form.on("Purchase Receipt", "is_subcontracted", function(frm) {
|
||||
}
|
||||
frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes");
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Purchase Receipt Item', {
|
||||
item_code: function(frm, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
frappe.db.get_value('Item', {name: d.item_code}, 'sample_quantity', (r) => {
|
||||
frappe.model.set_value(cdt, cdn, "sample_quantity", r.sample_quantity);
|
||||
});
|
||||
},
|
||||
sample_quantity: function(frm, cdt, cdn) {
|
||||
validate_sample_quantity(frm, cdt, cdn);
|
||||
},
|
||||
batch_no: function(frm, cdt, cdn) {
|
||||
validate_sample_quantity(frm, cdt, cdn);
|
||||
},
|
||||
});
|
||||
|
||||
var validate_sample_quantity = function(frm, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
if (d.sample_quantity) {
|
||||
frappe.call({
|
||||
method: 'erpnext.stock.doctype.stock_entry.stock_entry.validate_sample_quantity',
|
||||
args: {
|
||||
batch_no: d.batch_no,
|
||||
item_code: d.item_code,
|
||||
sample_quantity: d.sample_quantity,
|
||||
qty: d.qty
|
||||
},
|
||||
callback: (r) => {
|
||||
frappe.model.set_value(cdt, cdn, "sample_quantity", r.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
@ -607,6 +607,69 @@
|
||||
"unique": 0,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "retain_sample",
|
||||
"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": "Retain Sample",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "item_code.retain_sample",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "retain_sample",
|
||||
"fieldname": "sample_quantity",
|
||||
"fieldtype": "Int",
|
||||
"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": "Sample Quantity",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "item_code.sample_quantity",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -2227,7 +2290,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-30 14:19:14.276376",
|
||||
"modified": "2017-12-06 13:50:08.201145",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt Item",
|
||||
|
@ -86,6 +86,12 @@ frappe.ui.form.on('Stock Entry', {
|
||||
if(frm.doc.company) {
|
||||
frm.trigger("toggle_display_account_head");
|
||||
}
|
||||
|
||||
if(frm.doc.docstatus==1 && frm.doc.purpose == "Material Receipt") {
|
||||
frm.add_custom_button(__('Make Retention Stock Entry'), function () {
|
||||
frm.trigger("make_retention_stock_entry");
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
purpose: function(frm) {
|
||||
@ -122,6 +128,25 @@ frappe.ui.form.on('Stock Entry', {
|
||||
});
|
||||
},
|
||||
|
||||
make_retention_stock_entry: function(frm) {
|
||||
frappe.call({
|
||||
method: "erpnext.stock.doctype.stock_entry.stock_entry.move_sample_to_retention_warehouse",
|
||||
args:{
|
||||
"company": frm.doc.company,
|
||||
"items": frm.doc.items
|
||||
},
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
var doc = frappe.model.sync(r.message)[0];
|
||||
frappe.set_route("Form", doc.doctype, doc.name);
|
||||
}
|
||||
else {
|
||||
frappe.msgprint(__("Retention Stock Entry already created or Sample Quantity not provided"));
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
toggle_display_account_head: function(frm) {
|
||||
var enabled = erpnext.is_perpetual_inventory_enabled(frm.doc.company);
|
||||
frm.fields_dict["items"].grid.set_column_disp(["cost_center", "expense_account"], enabled);
|
||||
@ -327,9 +352,33 @@ frappe.ui.form.on('Stock Entry Detail', {
|
||||
},
|
||||
cost_center: function(frm, cdt, cdn) {
|
||||
erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "cost_center");
|
||||
}
|
||||
},
|
||||
sample_quantity: function(frm, cdt, cdn) {
|
||||
validate_sample_quantity(frm, cdt, cdn);
|
||||
},
|
||||
batch_no: function(frm, cdt, cdn) {
|
||||
validate_sample_quantity(frm, cdt, cdn);
|
||||
},
|
||||
});
|
||||
|
||||
var validate_sample_quantity = function(frm, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
if (d.sample_quantity && frm.doc.purpose == "Material Receipt") {
|
||||
frappe.call({
|
||||
method: 'erpnext.stock.doctype.stock_entry.stock_entry.validate_sample_quantity',
|
||||
args: {
|
||||
batch_no: d.batch_no,
|
||||
item_code: d.item_code,
|
||||
sample_quantity: d.sample_quantity,
|
||||
qty: d.transfer_qty
|
||||
},
|
||||
callback: (r) => {
|
||||
frappe.model.set_value(cdt, cdn, "sample_quantity", r.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
frappe.ui.form.on('Landed Cost Taxes and Charges', {
|
||||
amount: function(frm) {
|
||||
frm.events.calculate_amount(frm);
|
||||
@ -575,6 +624,8 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
||||
|
||||
this.frm.fields_dict["items"].grid.set_column_disp("s_warehouse", doc.purpose!='Material Receipt');
|
||||
this.frm.fields_dict["items"].grid.set_column_disp("t_warehouse", doc.purpose!='Material Issue');
|
||||
this.frm.fields_dict["items"].grid.set_column_disp("retain_sample", doc.purpose=='Material Receipt');
|
||||
this.frm.fields_dict["items"].grid.set_column_disp("sample_quantity", doc.purpose=='Material Receipt');
|
||||
|
||||
this.frm.cscript.toggle_enable_bom();
|
||||
|
||||
|
@ -9,13 +9,14 @@ from frappe.utils import cstr, cint, flt, comma_or, getdate, nowdate, formatdate
|
||||
from erpnext.stock.utils import get_incoming_rate
|
||||
from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError
|
||||
from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor
|
||||
from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos
|
||||
from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_batch_qty
|
||||
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
|
||||
import json
|
||||
|
||||
class IncorrectValuationRateError(frappe.ValidationError): pass
|
||||
class DuplicateEntryForProductionOrderError(frappe.ValidationError): pass
|
||||
class OperationsNotCompleteError(frappe.ValidationError): pass
|
||||
class MaxSampleAlreadyRetainedError(frappe.ValidationError): pass
|
||||
|
||||
from erpnext.controllers.stock_controller import StockController
|
||||
|
||||
@ -472,7 +473,7 @@ class StockEntry(StockController):
|
||||
def get_item_details(self, args=None, for_update=False):
|
||||
item = frappe.db.sql("""select stock_uom, description, image, item_name,
|
||||
expense_account, buying_cost_center, item_group, has_serial_no,
|
||||
has_batch_no
|
||||
has_batch_no, sample_quantity
|
||||
from `tabItem`
|
||||
where name = %s
|
||||
and disabled=0
|
||||
@ -499,7 +500,8 @@ class StockEntry(StockController):
|
||||
'basic_rate' : 0,
|
||||
'serial_no' : '',
|
||||
'has_serial_no' : item.has_serial_no,
|
||||
'has_batch_no' : item.has_batch_no
|
||||
'has_batch_no' : item.has_batch_no,
|
||||
'sample_quantity' : item.sample_quantity
|
||||
})
|
||||
for d in [["Account", "expense_account", "default_expense_account"],
|
||||
["Cost Center", "cost_center", "cost_center"]]:
|
||||
@ -803,6 +805,40 @@ class StockEntry(StockController):
|
||||
if getdate(self.posting_date) > getdate(expiry_date):
|
||||
frappe.throw(_("Batch {0} of Item {1} has expired.").format(item.batch_no, item.item_code))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def move_sample_to_retention_warehouse(company, items):
|
||||
if isinstance(items, basestring):
|
||||
items = json.loads(items)
|
||||
retention_warehouse = frappe.db.get_single_value('Stock Settings', 'sample_retention_warehouse')
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
stock_entry.company = company
|
||||
stock_entry.purpose = "Material Transfer"
|
||||
for item in items:
|
||||
if item.get('sample_quantity') and item.get('batch_no'):
|
||||
sample_quantity = validate_sample_quantity(item.get('item_code'), item.get('sample_quantity'), item.get('transfer_qty') or item.get('qty'), item.get('batch_no'))
|
||||
if sample_quantity:
|
||||
sample_serial_nos = ''
|
||||
if item.get('serial_no'):
|
||||
serial_nos = (item.get('serial_no')).split()
|
||||
if serial_nos and len(serial_nos) > item.get('sample_quantity'):
|
||||
serial_no_list = serial_nos[:-(len(serial_nos)-item.get('sample_quantity'))]
|
||||
sample_serial_nos = '\n'.join(serial_no_list)
|
||||
stock_entry.append("items", {
|
||||
"item_code": item.get('item_code'),
|
||||
"s_warehouse": item.get('t_warehouse'),
|
||||
"t_warehouse": retention_warehouse,
|
||||
"qty": item.get('sample_quantity'),
|
||||
"basic_rate": item.get('valuation_rate'),
|
||||
'uom': item.get('uom'),
|
||||
'stock_uom': item.get('stock_uom'),
|
||||
"conversion_factor": 1.0,
|
||||
"serial_no": sample_serial_nos,
|
||||
'batch_no': item.get('batch_no')
|
||||
})
|
||||
if stock_entry.get('items'):
|
||||
return stock_entry.as_dict()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_production_order_details(production_order):
|
||||
production_order = frappe.get_doc("Production Order", production_order)
|
||||
@ -893,5 +929,24 @@ def get_warehouse_details(args):
|
||||
"actual_qty" : get_previous_sle(args).get("qty_after_transaction") or 0,
|
||||
"basic_rate" : get_incoming_rate(args)
|
||||
}
|
||||
|
||||
return ret
|
||||
|
||||
@frappe.whitelist()
|
||||
def validate_sample_quantity(item_code, sample_quantity, qty, batch_no = None):
|
||||
if cint(qty) < cint(sample_quantity):
|
||||
frappe.throw(_("Sample quantity {0} cannot be more than received quantity {1}").format(sample_quantity, qty), alert=True)
|
||||
retention_warehouse = frappe.db.get_single_value('Stock Settings', 'sample_retention_warehouse')
|
||||
retainted_qty = 0
|
||||
if batch_no:
|
||||
retainted_qty = get_batch_qty(batch_no, retention_warehouse, item_code)
|
||||
max_retain_qty = frappe.get_value('Item', item_code, 'sample_quantity')
|
||||
if retainted_qty >= max_retain_qty:
|
||||
frappe.msgprint(_("Maximum Samples - {0} have already been retained for Batch {1} and Item {2} in Batch {3}.").
|
||||
format(retainted_qty, batch_no, item_code, batch_no), alert=True)
|
||||
sample_quantity = 0
|
||||
qty_diff = max_retain_qty-retainted_qty
|
||||
if cint(sample_quantity) > cint(qty_diff):
|
||||
frappe.msgprint(_("Maximum Samples - {0} can be retained for Batch {1} and Item {2}.").
|
||||
format(max_retain_qty, batch_no, item_code), alert=True)
|
||||
sample_quantity = qty_diff
|
||||
return sample_quantity
|
@ -15,6 +15,7 @@ from erpnext.stock.doctype.item.test_item import set_item_variant_settings, make
|
||||
from frappe.tests.test_permissions import set_user_permission_doctypes
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse
|
||||
|
||||
def get_sle(**args):
|
||||
condition, values = "", []
|
||||
@ -613,6 +614,61 @@ class TestStockEntry(unittest.TestCase):
|
||||
s2.submit()
|
||||
s2.cancel()
|
||||
|
||||
def test_retain_sample(self):
|
||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||
from erpnext.stock.doctype.batch.batch import get_batch_qty
|
||||
|
||||
create_warehouse("Test Warehouse for Sample Retention")
|
||||
frappe.db.set_value("Stock Settings", None, "sample_retention_warehouse", "Test Warehouse for Sample Retention - _TC")
|
||||
|
||||
item = frappe.new_doc("Item")
|
||||
item.item_code = "Retain Sample Item"
|
||||
item.item_name = "Retain Sample Item"
|
||||
item.description = "Retain Sample Item"
|
||||
item.item_group = "All Item Groups"
|
||||
item.is_stock_item = 1
|
||||
item.has_batch_no = 1
|
||||
item.create_new_batch = 1
|
||||
item.retain_sample = 1
|
||||
item.sample_quantity = 4
|
||||
item.save()
|
||||
|
||||
receipt_entry = frappe.new_doc("Stock Entry")
|
||||
receipt_entry.company = "_Test Company"
|
||||
receipt_entry.purpose = "Material Receipt"
|
||||
receipt_entry.append("items", {
|
||||
"item_code": item.item_code,
|
||||
"t_warehouse": "_Test Warehouse - _TC",
|
||||
"qty": 40,
|
||||
"basic_rate": 12,
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"sample_quantity": 4
|
||||
})
|
||||
receipt_entry.insert()
|
||||
receipt_entry.submit()
|
||||
|
||||
retention_data = move_sample_to_retention_warehouse(receipt_entry.company, receipt_entry.get("items"))
|
||||
retention_entry = frappe.new_doc("Stock Entry")
|
||||
retention_entry.company = retention_data.company
|
||||
retention_entry.purpose = retention_data.purpose
|
||||
retention_entry.append("items", {
|
||||
"item_code": item.item_code,
|
||||
"t_warehouse": "Test Warehouse for Sample Retention - _TC",
|
||||
"s_warehouse": "_Test Warehouse - _TC",
|
||||
"qty": 4,
|
||||
"basic_rate": 12,
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"batch_no": receipt_entry.get("items")[0].batch_no
|
||||
})
|
||||
retention_entry.insert()
|
||||
retention_entry.submit()
|
||||
|
||||
qty_in_usable_warehouse = get_batch_qty(receipt_entry.get("items")[0].batch_no, "_Test Warehouse - _TC", "_Test Item")
|
||||
qty_in_retention_warehouse = get_batch_qty(receipt_entry.get("items")[0].batch_no, "Test Warehouse for Sample Retention - _TC", "_Test Item")
|
||||
|
||||
self.assertEquals(qty_in_usable_warehouse, 36)
|
||||
self.assertEquals(qty_in_retention_warehouse, 4)
|
||||
|
||||
def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
|
||||
se = frappe.copy_doc(test_records[0])
|
||||
se.get("items")[0].item_code = item_code or "_Test Serialized Item With Series"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -140,9 +140,8 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "clean_description_html",
|
||||
"fieldtype": "Check",
|
||||
"fieldname": "sample_retention_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -150,9 +149,10 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Convert Item Description to Clean HTML",
|
||||
"label": "Sample Retention Warehouse",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -284,6 +284,37 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "clean_description_html",
|
||||
"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": "Convert Item Description to Clean HTML",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -648,7 +679,7 @@
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-14 16:19:50.274518",
|
||||
"modified": "2017-11-17 01:35:49.562613",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Stock Settings",
|
||||
|
Loading…
x
Reference in New Issue
Block a user