493 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			493 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # ERPNext - web based ERP (http://erpnext.com)
 | |
| # Copyright (C) 2012 Web Notes Technologies Pvt Ltd
 | |
| # 
 | |
| # This program is free software: you can redistribute it and/or modify
 | |
| # it under the terms of the GNU General Public License as published by
 | |
| # the Free Software Foundation, either version 3 of the License, or
 | |
| # (at your option) any later version.
 | |
| # 
 | |
| # This program is distributed in the hope that it will be useful,
 | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| # GNU General Public License for more details.
 | |
| # 
 | |
| # You should have received a copy of the GNU General Public License
 | |
| # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| import unittest
 | |
| 
 | |
| import webnotes
 | |
| import webnotes.profile
 | |
| webnotes.user = webnotes.profile.Profile()
 | |
| 
 | |
| 
 | |
| from webnotes.model.doc import Document
 | |
| from webnotes.model.code import get_obj
 | |
| from webnotes.utils import cstr, flt
 | |
| from webnotes.model.doclist import getlist
 | |
| sql = webnotes.conn.sql
 | |
| 
 | |
| from sandbox.testdata.masters import *
 | |
| from sandbox.testdata import stock_entry
 | |
| #----------------------------------------------------------
 | |
| 
 | |
| 
 | |
| class TestStockEntry(unittest.TestCase):
 | |
| 	#===========================================================================
 | |
| 	def assertDoc(self, lst):
 | |
| 		"""assert all values"""
 | |
| 		for d in lst:
 | |
| 			cl, vl = [], []
 | |
| 			for k in d.keys():
 | |
| 				if k!='doctype':
 | |
| 					cl.append('%s=%s' % (k, '%s'))
 | |
| 					vl.append(d[k])
 | |
| 
 | |
| 			self.assertTrue(sql("select name from `tab%s` where %s limit 1" % (d['doctype'], ' and '.join(cl)), vl))
 | |
| 			
 | |
| 	#===========================================================================
 | |
| 	def assertCount(self, lst):
 | |
| 		"""assert all values"""
 | |
| 		for d in lst:
 | |
| 			cl, vl = [], []
 | |
| 			for k in d[0].keys():
 | |
| 				if k!='doctype':
 | |
| 					cl.append('%s=%s' % (k, '%s'))
 | |
| 					vl.append(d[0][k])
 | |
| 
 | |
| 			self.assertTrue(sql("select count(name) from `tab%s` where %s limit 1" % (d[0]['doctype'], ' and '.join(cl)), vl)[0][0] == d[1])
 | |
| 		
 | |
| 	#===========================================================================
 | |
| 	def setUp(self):
 | |
| 		print "====================================="
 | |
| 		webnotes.conn.begin()		
 | |
| 		create_master_records()
 | |
| 		print 'Master Data Created'
 | |
| 		
 | |
| 	#===========================================================================
 | |
| 	# Purpose: Material Receipt
 | |
| 	#===========================================================================
 | |
| 	def test_mr_onsubmit(self):
 | |
| 		print "Test Case: Material Receipt submission"
 | |
| 		self.save_stock_entry('Material Receipt')
 | |
| 
 | |
| 		mr = get_obj('Stock Entry', stock_entry.mr[0].name, with_children=1)
 | |
| 		self.submit_stock_entry(mr)
 | |
| 		
 | |
| 		# stock ledger entry
 | |
| 		print "Checking stock ledger entry........."
 | |
| 		self.assertDoc(self.get_expected_sle('mr_submit'))
 | |
| 		
 | |
| 		# bin qty
 | |
| 		print "Checking Bin qty........."
 | |
| 		self.assertDoc([{'doctype':'Bin', 'actual_qty':10, 'item_code':'it', 'warehouse':'wh1'}])
 | |
| 		
 | |
| 		# serial no
 | |
| 		self.assertCount([[{'doctype': 'Serial No', 'item_code': 'it', 'warehouse': 'wh1', 'status': 'In Store', 'docstatus': 0}, 10]])
 | |
| 
 | |
| 		
 | |
| 	#===========================================================================
 | |
| 	def test_mr_oncancel(self):
 | |
| 		print "Test Case: Material Receipt Cancellation"
 | |
| 		self.save_stock_entry('Material Receipt')
 | |
| 		
 | |
| 		mr = get_obj('Stock Entry', stock_entry.mr[0].name, with_children=1)
 | |
| 		self.cancel_stock_entry(mr)
 | |
| 		
 | |
| 		# stock ledger entry
 | |
| 		print "Checking stock ledger entry........."
 | |
| 		self.assertDoc(self.get_expected_sle('mr_cancel'))
 | |
| 		
 | |
| 		# bin qty
 | |
| 		print "Checking Bin qty........."
 | |
| 		self.assertDoc([{'doctype':'Bin', 'actual_qty':0, 'item_code':'it', 'warehouse':'wh1'}])
 | |
| 		
 | |
| 		# serial no
 | |
| 		self.assertCount([[{'doctype': 'Serial No', 'item_code': 'it', 'warehouse': '', 'status': 'Not in Use', 'docstatus': 2}, 10]])
 | |
| 		
 | |
| 	#===========================================================================
 | |
| 	# Purpose: Material Transafer
 | |
| 	#===========================================================================
 | |
| 	def test_mtn_onsubmit(self):
 | |
| 		print "Test Case: Material Transfer Note submission"
 | |
| 		
 | |
| 		self.save_stock_entry('Material Receipt')
 | |
| 		mr = get_obj('Stock Entry', stock_entry.mr[0].name, with_children=1)
 | |
| 		mr = self.submit_stock_entry(mr)
 | |
| 		
 | |
| 		self.save_stock_entry('Material Transfer')
 | |
| 		mtn = get_obj('Stock Entry', stock_entry.mtn[0].name, with_children=1)
 | |
| 		mtn = self.submit_stock_entry(mtn)
 | |
| 		
 | |
| 		# stock ledger entry
 | |
| 		print "Checking stock ledger entry........."
 | |
| 		self.assertDoc(self.get_expected_sle('mtn_submit'))
 | |
| 		
 | |
| 		# bin qty
 | |
| 		print "Checking Bin qty........."
 | |
| 		self.assertDoc([
 | |
| 			{'doctype':'Bin', 'actual_qty':5, 'item_code':'it', 'warehouse':'wh1'},
 | |
| 			{'doctype':'Bin', 'actual_qty':5, 'item_code':'it', 'warehouse':'wh2'}
 | |
| 		])
 | |
| 		
 | |
| 		# serial no		
 | |
| 		self.assertCount([
 | |
| 			[{'doctype': 'Serial No', 'item_code': 'it', 'warehouse': 'wh1', 'status': 'In Store', 'docstatus': 0}, 5], 
 | |
| 			[{'doctype': 'Serial No', 'item_code': 'it', 'warehouse': 'wh2', 'status': 'In Store', 'docstatus': 0}, 5]
 | |
| 		])
 | |
| 		
 | |
| 	#===========================================================================
 | |
| 	def test_mtn_oncancel(self):
 | |
| 		print "Test Case: Material Transfer Note Cancellation"
 | |
| 		
 | |
| 		self.save_stock_entry('Material Receipt')
 | |
| 		mr = get_obj('Stock Entry', stock_entry.mr[0].name, with_children=1)
 | |
| 		mr = self.submit_stock_entry(mr)
 | |
| 		
 | |
| 		self.save_stock_entry('Material Transfer')
 | |
| 		mtn = get_obj('Stock Entry', stock_entry.mtn[0].name, with_children=1)
 | |
| 		self.cancel_stock_entry(mtn)
 | |
| 		
 | |
| 		# stock ledger entry
 | |
| 		print "Checking stock ledger entry........."
 | |
| 		self.assertDoc(self.get_expected_sle('mtn_cancel'))
 | |
| 		
 | |
| 		# bin qty
 | |
| 		print "Checking Bin qty........."
 | |
| 		self.assertDoc([
 | |
| 			{'doctype':'Bin', 'actual_qty':10, 'item_code':'it', 'warehouse':'wh1'},
 | |
| 			{'doctype':'Bin', 'actual_qty':0, 'item_code':'it', 'warehouse':'wh2'}
 | |
| 		])
 | |
| 		
 | |
| 		# serial no
 | |
| 		self.assertCount([[{'doctype': 'Serial No', 'item_code': 'it', 'warehouse': 'wh1', 'status': 'In Store', 'docstatus': 0}, 10]])
 | |
| 		
 | |
| #===========================================================================
 | |
| 	# Purpose: Material Issue
 | |
| 	#===========================================================================
 | |
| 	def test_mi_onsubmit(self):
 | |
| 		print "Test Case: Material Issue submission"
 | |
| 		
 | |
| 		self.save_stock_entry('Material Receipt')
 | |
| 		mr = get_obj('Stock Entry', stock_entry.mr[0].name, with_children=1)
 | |
| 		mr = self.submit_stock_entry(mr)
 | |
| 		
 | |
| 		self.save_stock_entry('Material Issue')
 | |
| 		mi = get_obj('Stock Entry', stock_entry.mi[0].name, with_children=1)
 | |
| 		mi = self.submit_stock_entry(mi)
 | |
| 		
 | |
| 		# stock ledger entry
 | |
| 		print "Checking stock ledger entry........."
 | |
| 		self.assertDoc(self.get_expected_sle('mi_submit'))
 | |
| 		
 | |
| 		# bin qty
 | |
| 		print "Checking Bin qty........."
 | |
| 		self.assertDoc([
 | |
| 			{'doctype':'Bin', 'actual_qty':6, 'item_code':'it', 'warehouse':'wh1'}
 | |
| 		])
 | |
| 		
 | |
| 		# serial no		
 | |
| 		self.assertCount([
 | |
| 			[{'doctype': 'Serial No', 'item_code': 'it', 'warehouse': 'wh1', 'status': 'In Store', 'docstatus': 0}, 6]
 | |
| 		])
 | |
| 		
 | |
| 	#===========================================================================
 | |
| 	def test_mi_oncancel(self):
 | |
| 		print "Test Case: Material Issue Cancellation"
 | |
| 		
 | |
| 		self.save_stock_entry('Material Receipt')
 | |
| 		mr = get_obj('Stock Entry', stock_entry.mr[0].name, with_children=1)
 | |
| 		mr = self.submit_stock_entry(mr)
 | |
| 		
 | |
| 		self.save_stock_entry('Material Issue')
 | |
| 		mi = get_obj('Stock Entry', stock_entry.mi[0].name, with_children=1)
 | |
| 		self.cancel_stock_entry(mi)
 | |
| 		
 | |
| 		# stock ledger entry
 | |
| 		print "Checking stock ledger entry........."
 | |
| 		self.assertDoc(self.get_expected_sle('mi_cancel'))
 | |
| 		
 | |
| 		# bin qty
 | |
| 		print "Checking Bin qty........."
 | |
| 		self.assertDoc([
 | |
| 			{'doctype':'Bin', 'actual_qty':10, 'item_code':'it', 'warehouse':'wh1'}
 | |
| 		])
 | |
| 		
 | |
| 		# serial no
 | |
| 		self.assertCount([
 | |
| 			[{'doctype': 'Serial No', 'item_code': 'it', 'warehouse': 'wh1', 'status': 'In Store', 'docstatus': 0}, 10]
 | |
| 		])
 | |
| 
 | |
| 	#===========================================================================
 | |
| 	def test_entries_on_same_datetime(self):
 | |
| 		print "Test Case: Multiple entries on same datetime, cancel first one"
 | |
| 		
 | |
| 		# submitted 1st MR
 | |
| 		self.save_stock_entry('Material Receipt')
 | |
| 		mr = get_obj('Stock Entry', stock_entry.mr[0].name, with_children=1)
 | |
| 		mr = self.submit_stock_entry(mr)
 | |
| 		
 | |
| 		# submitted 2nd MR
 | |
| 		for each in stock_entry.mr1:
 | |
| 			each.save(1)
 | |
| 		for t in stock_entry.mr1[1:]:
 | |
| 			sql("update `tabStock Entry Detail` set parent = '%s' where name = '%s'" % (stock_entry.mr1[0].name, t.name))
 | |
| 		
 | |
| 		mr1 = get_obj('Stock Entry', stock_entry.mr1[0].name, with_children=1)
 | |
| 		mr1 = self.submit_stock_entry(mr1)
 | |
| 
 | |
| 		
 | |
| 		# submitted MTN
 | |
| 		self.save_stock_entry('Material Transfer')
 | |
| 		mtn = get_obj('Stock Entry', stock_entry.mtn[0].name, with_children=1)
 | |
| 		mtn = self.submit_stock_entry(mtn)
 | |
| 		
 | |
| 		# cancel prev MR
 | |
| 		mr.on_cancel()
 | |
| 		mr.doc.cancel_reason = "testing"
 | |
| 		mr.doc.docstatus = 2
 | |
| 		mr.doc.save()
 | |
| 		
 | |
| 		
 | |
| 		# stock ledger entry
 | |
| 		print "Checking stock ledger entry........."
 | |
| 		self.assertDoc(self.get_expected_sle('entries_on_same_datetime'))
 | |
| 		
 | |
| 		# bin qty
 | |
| 		print "Checking Bin qty........."
 | |
| 		self.assertDoc([
 | |
| 			{'doctype':'Bin', 'actual_qty':0, 'item_code':'it', 'warehouse':'wh1'},
 | |
| 			{'doctype':'Bin', 'actual_qty':5, 'item_code':'it', 'warehouse':'wh2'}
 | |
| 		])
 | |
| 		
 | |
| 		# serial no		
 | |
| 		self.assertCount([
 | |
| 			[{'doctype': 'Serial No', 'item_code': 'it', 'warehouse': 'wh1', 'status': 'In Store', 'docstatus': 0}, 0], 
 | |
| 			[{'doctype': 'Serial No', 'item_code': 'it', 'warehouse': 'wh2', 'status': 'In Store', 'docstatus': 0}, 5]
 | |
| 		])
 | |
| 		
 | |
| 	#===========================================================================
 | |
| 	def save_stock_entry(self, t):
 | |
| 		if t == 'Material Receipt':
 | |
| 			data = stock_entry.mr
 | |
| 		elif t == 'Material Transfer':
 | |
| 			data = stock_entry.mtn
 | |
| 		elif t == 'Material Issue':
 | |
| 			data = stock_entry.mi
 | |
| 			
 | |
| 		for each in data:
 | |
| 			each.save(1)
 | |
| 
 | |
| 		for t in data[1:]:
 | |
| 			sql("update `tabStock Entry Detail` set parent = '%s' where name = '%s'" % (data[0].name, t.name))
 | |
| 		print "Stock Entry Created"
 | |
| 		
 | |
| 		
 | |
| 	#===========================================================================
 | |
| 	def submit_stock_entry(self, ste):
 | |
| 		ste.validate()
 | |
| 		ste.on_submit()
 | |
| 		
 | |
| 		ste.doc.docstatus = 1
 | |
| 		ste.doc.save()
 | |
| 
 | |
| 		print "Stock Entry Submitted"
 | |
| 		return ste
 | |
| 			
 | |
| 	#===========================================================================
 | |
| 	def cancel_stock_entry(self, ste):
 | |
| 		ste = self.submit_stock_entry(ste)
 | |
| 		
 | |
| 		ste.on_cancel()
 | |
| 		
 | |
| 		ste.doc.cancel_reason = "testing"
 | |
| 		ste.doc.docstatus = 2
 | |
| 		ste.doc.save()
 | |
| 		
 | |
| 		print "Stock Entry Cancelled"
 | |
| 		return ste
 | |
| 		
 | |
| 	#===========================================================================
 | |
| 	def tearDown(self):
 | |
| 		webnotes.conn.rollback()
 | |
| 
 | |
| 
 | |
| 	# Expected Result Set
 | |
| 	#===================================================================================================
 | |
| 	def get_expected_sle(self, action):
 | |
| 		expected_sle = {
 | |
| 			'mr_submit': [{
 | |
| 							'doctype': 'Stock Ledger Entry',
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1', 
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mr[0].name,
 | |
| 							'actual_qty': 10,
 | |
| 							'bin_aqat': 10,
 | |
| 							'valuation_rate': 100,
 | |
| 							'is_cancelled': 'No'
 | |
| 						}],
 | |
| 			'mr_cancel': [{
 | |
| 							'doctype': 'Stock Ledger Entry', 
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mr[0].name,
 | |
| 							'actual_qty': 10,
 | |
| 							'bin_aqat': 10,
 | |
| 							'valuation_rate': 100,
 | |
| 							'is_cancelled': 'Yes'
 | |
| 						},{
 | |
| 							'doctype': 'Stock Ledger Entry', 
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mr[0].name,
 | |
| 							'actual_qty': -10,
 | |
| 							'ifnull(bin_aqat, 0)': 0,
 | |
| 							'ifnull(valuation_rate, 0)': 0,
 | |
| 							"ifnull(is_cancelled, 'No')": 'Yes'
 | |
| 						}],
 | |
| 			'mtn_submit': [{
 | |
| 							'doctype': 'Stock Ledger Entry',
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mtn[0].name,
 | |
| 							'actual_qty': -5,
 | |
| 							'bin_aqat': 5,
 | |
| 							'valuation_rate': 100,
 | |
| 							'is_cancelled': 'No'
 | |
| 						}, {
 | |
| 							'doctype': 'Stock Ledger Entry',
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh2',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mtn[0].name,
 | |
| 							'actual_qty': 5,
 | |
| 							'bin_aqat': 5,
 | |
| 							'valuation_rate': 100,
 | |
| 							'is_cancelled': 'No'
 | |
| 						}],
 | |
| 			'mtn_cancel': [{
 | |
| 							'doctype': 'Stock Ledger Entry',
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mtn[0].name,
 | |
| 							'actual_qty': -5,
 | |
| 							'bin_aqat': 5,
 | |
| 							'is_cancelled': 'Yes'
 | |
| 						}, {
 | |
| 							'doctype': 'Stock Ledger Entry',
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh2',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mtn[0].name,
 | |
| 							'actual_qty': 5,
 | |
| 							'bin_aqat': 5,
 | |
| 							'valuation_rate': 100,
 | |
| 							'is_cancelled': 'Yes'
 | |
| 						}, {
 | |
| 							'doctype': 'Stock Ledger Entry',
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mtn[0].name,
 | |
| 							'actual_qty': 5,
 | |
| 							'is_cancelled': 'Yes'
 | |
| 						}, {
 | |
| 							'doctype': 'Stock Ledger Entry',
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh2',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mtn[0].name,
 | |
| 							'actual_qty': -5,
 | |
| 							'is_cancelled': 'Yes'
 | |
| 						}],
 | |
| 			'mi_submit': [{'doctype': 'Stock Ledger Entry',
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1', 
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mi[0].name,
 | |
| 							'actual_qty': -4,
 | |
| 							'bin_aqat': 6,
 | |
| 							'valuation_rate': 100,
 | |
| 							'is_cancelled': 'No'
 | |
| 						}],
 | |
| 			'mi_cancel': [{
 | |
| 							'doctype': 'Stock Ledger Entry', 
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mi[0].name,
 | |
| 							'actual_qty': -4,
 | |
| 							'bin_aqat': 6,
 | |
| 							'valuation_rate': 100,
 | |
| 							'is_cancelled': 'Yes'
 | |
| 						},{
 | |
| 							'doctype': 'Stock Ledger Entry', 
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mi[0].name,
 | |
| 							'actual_qty': 4,
 | |
| 							'ifnull(bin_aqat, 0)': 0,
 | |
| 							'ifnull(valuation_rate, 0)': 0,
 | |
| 							"ifnull(is_cancelled, 'No')": 'Yes'
 | |
| 						}],
 | |
| 			'entries_on_same_datetime': [{
 | |
| 							'doctype': 'Stock Ledger Entry', 
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mr[0].name,
 | |
| 							'actual_qty': 10,
 | |
| 							'bin_aqat': 10,
 | |
| 							'valuation_rate': 100,
 | |
| 							'is_cancelled': 'Yes'
 | |
| 						}, {
 | |
| 							'doctype': 'Stock Ledger Entry', 
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mr[0].name,
 | |
| 							'actual_qty': -10,
 | |
| 							'ifnull(bin_aqat, 0)': 0,
 | |
| 							'ifnull(valuation_rate, 0)': 0,
 | |
| 							"ifnull(is_cancelled, 'No')": 'Yes'
 | |
| 						}, {
 | |
| 							'doctype': 'Stock Ledger Entry', 
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mr1[0].name,
 | |
| 							'actual_qty': 5,
 | |
| 							'bin_aqat': 5,
 | |
| 							'valuation_rate': 400,
 | |
| 							'is_cancelled': 'No'
 | |
| 						}, {
 | |
| 							'doctype': 'Stock Ledger Entry',
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh1',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mtn[0].name,
 | |
| 							'actual_qty': -5,
 | |
| 							'bin_aqat': 0,
 | |
| 							'valuation_rate': 400,
 | |
| 							'is_cancelled': 'No'
 | |
| 						}, {
 | |
| 							'doctype': 'Stock Ledger Entry',
 | |
| 							'item_code':'it',
 | |
| 							'warehouse':'wh2',
 | |
| 							'voucher_type': 'Stock Entry',
 | |
| 							'voucher_no': stock_entry.mtn[0].name,
 | |
| 							'actual_qty': 5,
 | |
| 							'bin_aqat': 5,
 | |
| 							'valuation_rate': 100,
 | |
| 							'is_cancelled': 'No'
 | |
| 						}]
 | |
| 		}
 | |
| 		
 | |
| 		return expected_sle[action]
 |