stock entry cleanp

This commit is contained in:
Nabin Hait 2012-12-18 10:28:36 +05:30
parent 9ea22b75bd
commit 7c59c68434
17 changed files with 456 additions and 2040 deletions

View File

@ -1 +0,0 @@
from __future__ import unicode_literals

View File

@ -1,69 +0,0 @@
# 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/>.
from __future__ import unicode_literals
import unittest
import webnotes
import webnotes.profile
webnotes.user = webnotes.profile.Profile()
from webnotes.model.code import get_obj
sql = webnotes.conn.sql
from sandbox.testdata import leaves
#----------------------------------------------------------
class TestStockEntry(unittest.TestCase):
#===========================================================================
def setUp(self):
webnotes.conn.begin()
leaves.emp.save(new = 1, make_autoname = 0)
def test_leave_bal(self):
leaves.l_all.save(1)
leaves.l_app1.save(1)
leaves.l_app2.save(1)
la1 = get_obj('Leave Application', leaves.l_app1.name, with_children=1)
la1.validate()
la1.doc.docstatus = 1
la1.doc.save()
self.assertTrue(la1.doc.total_leave_days == 2)
la1.doc.half_day = 1
la1.validate()
la1.doc.save()
self.assertTrue(la1.doc.total_leave_days == .5)
print "Test case for leave applied no of days"
la2 = get_obj('Leave Application', leaves.l_app2.name, with_children=1)
la2.validate()
bal = la2.get_leave_balance()
self.assertTrue(bal, 18)
print "Test case for leave balance"
def tearDown(self):
webnotes.conn.rollback()

View File

@ -1,490 +0,0 @@
# 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/>.
from __future__ import unicode_literals
import unittest
import webnotes
import webnotes.profile
webnotes.user = webnotes.profile.Profile()
from webnotes.model.code import get_obj
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]

View File

@ -1,108 +0,0 @@
# 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/>.
from __future__ import unicode_literals
import unittest
import webnotes
import webnotes.profile
webnotes.user = webnotes.profile.Profile()
from webnotes.model.code import get_obj
sql = webnotes.conn.sql
from sandbox.testdata.masters import *
from sandbox.testdata.sle_data import sle, bin
from sandbox.testdata.stock_reco import *
#----------------------------------------------------------
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 setUp(self):
print "====================================="
webnotes.conn.begin()
create_master_records()
print 'Master Data Created'
for d in sle:
d.save(1)
print "Existing SLE created"
bin.save(1)
sreco.save(1)
print "Stock Reco saved"
#===========================================================================
def test_diff_in_both(self):
reco = get_obj('Stock Reconciliation', sreco.name)
reco.doc.docstatus = 1
reco.doc.save()
reco.validate()
reco.on_submit()
print "Stock Reco submitted"
print "Checking stock ledger entry........."
self.assertDoc(self.get_expected_sle('diff_in_both'))
#===========================================================================
def tearDown(self):
webnotes.conn.rollback()
# Expected Result Set
#===================================================================================================
def get_expected_sle(self, action):
expected_sle = {
'diff_in_both': [{
'doctype': 'Stock Ledger Entry',
'item_code':'it',
'warehouse':'wh1',
'voucher_type': 'Stock Reconciliation',
'voucher_no': sreco.name,
'actual_qty': 15,
'bin_aqat': 20,
'valuation_rate': 150,
#'stock_value': 3000,
'is_cancelled': 'No'
},{
'doctype': 'Stock Ledger Entry',
'posting_date': '2011-09-10',
'posting_time': '15:00',
'item_code': 'it',
'warehouse': 'wh1',
'actual_qty': 20,
'incoming_rate': 200,
'bin_aqat': 40,
'valuation_rate': 175,
#'stock_value': 4500,
'is_cancelled': 'No'
}
]
}
return expected_sle[action]

View File

@ -1 +0,0 @@
from __future__ import unicode_literals

View File

@ -1,71 +0,0 @@
# 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/>.
from __future__ import unicode_literals
from webnotes.model.doc import Document
emp = Document(
fielddata = {
'doctype': 'Employee',
'name': 'emp1',
'employee_name': 'Nijil',
'status': 'Active',
'date_of_joining': '2011-01-01'
}
)
l_all = Document(
fielddata = {
'doctype' : 'Leave Allocation',
'name': 'l_all',
'employee' : 'emp1',
'leave_type' : 'Casual Leave',
'posting_date': '2011-03-01',
'fiscal_year': '2011-2012',
'total_leaves_allocated': 20,
'docstatus': 1
}
)
l_app1 = Document(
fielddata = {
'doctype' : 'Leave Application',
'name': 'l_app1',
'employee' : 'emp1',
'leave_type' : 'Casual Leave',
'posting_date': '2011-03-01',
'fiscal_year': '2011-2012',
'from_date': '2011-08-01',
'to_date': '2011-08-02',
'total_leave_days': 2
}
)
l_app2 = Document(
fielddata = {
'doctype' : 'Leave Application',
'name': 'l_app2',
'employee' : 'emp1',
'leave_type' : 'Casual Leave',
'posting_date': '2011-03-01',
'fiscal_year': '2011-2012',
'from_date': '2011-08-15',
'to_date': '2011-08-17',
'total_leave_days': 3
}
)

View File

@ -1,299 +0,0 @@
# 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/>.
from __future__ import unicode_literals
"""
All master data in one place, can be created by 1 function call
"""
import webnotes
from webnotes.model.doc import Document
master_groups = {
# Company
#----------------------------------
'company': Document(
fielddata={
'doctype':'Company',
'abbr': 'co',
'company_name' : 'comp',
'name': 'comp'
}
),
# Customer Group
#----------------------------------
'customer_group': Document(
fielddata={
'doctype':'Customer Group',
'customer_group_name' : 'cg',
'name': 'cg',
'is_group': 'No',
'parent_customer_group':'',
'lft' : 1,
'rgt': 2
}
),
# Item Group
#----------------------------------
'item_group': Document(
fielddata = {
'doctype': 'Item Group',
'item_group_name': 'ig',
'lft': 1,
'rgt': 2,
'parent_item_group' : '',
'is_group': 'No',
'name': 'ig'
}
),
# Warehouse Type
#-----------------------------
'warehouse_type' : Document(
fielddata = {
'doctype' : 'Warehouse Type',
'name': 'normal',
'warehouse_type' : 'normal'
}
),
# Supplier Type
#-----------------------------
'supplier_type' : Document(
fielddata = {
'doctype': 'Supplier Type',
'supplier_type': 'stype'
}
)
}
main_masters = {
# Customer
#----------------------------------
'customer': Document(
fielddata={
'doctype':'Customer',
'docstatus':0,
'customer_name' : 'cust',
'company' : 'comp',
'customer_group' : '',
'name': 'cust'
}
),
# Supplier
#----------------------------------
'supplier': Document(
fielddata = {
'doctype': 'Supplier',
'supplier_name': 'supp',
'name': 'supp',
'supplier_type' : 'stype'
}
),
# Customer Account
#----------------------------------
'customer_acc': Document(
fielddata={
'doctype':'Account',
'docstatus':0,
'account_name' : 'cust',
'debit_or_credit': 'Debit',
'company' : 'comp',
'lft': 1,
'rgt': 2,
'group_or_ledger' : 'Ledger',
'is_pl_account': 'No',
'name' : 'cust - co'
}
),
# Customer Account
#----------------------------------
'supplier_acc': Document(
fielddata={
'doctype':'Account',
'docstatus':0,
'account_name' : 'supp',
'debit_or_credit': 'Credit',
'company' : 'comp',
'lft': 5,
'rgt': 6,
'group_or_ledger' : 'Ledger',
'is_pl_account': 'No',
'name' : 'supp - co'
}
),
# Bank Account
#----------------------------------
'bank_acc': Document(
fielddata={
'doctype':'Account',
'docstatus':0,
'account_name' : 'icici',
'parent_account': '',
'debit_or_credit': 'Debit',
'company' : 'comp',
'lft': 3,
'rgt': 4,
'group_or_ledger' : 'Ledger',
'is_pl_account': 'No',
'name' : 'icici - co'
}
),
# Income Account
#----------------------------------
'income_acc': Document(
fielddata={
'doctype':'Account',
'docstatus':0,
'account_name' : 'income',
'debit_or_credit': 'Credit',
'company' : 'comp',
'lft': 7,
'rgt': 8,
'group_or_ledger' : 'Ledger',
'is_pl_account': 'Yes',
'name' : 'income - co'
}
),
# Expense Account
#----------------------------------
'expense_acc': Document(
fielddata={
'doctype':'Account',
'docstatus':0,
'account_name' : 'expense',
'debit_or_credit': 'Debit',
'company' : 'comp',
'lft': 9,
'rgt': 10,
'group_or_ledger' : 'Ledger',
'is_pl_account': 'Yes',
'name' : 'expense - co'
}
),
# Cost Center
#----------------------------------
'cost_center': Document(
fielddata={
'doctype':'Cost Center',
'docstatus':0,
'cost_center_name' : 'cc',
'lft': 1,
'rgt': 2,
'group_or_ledger' : 'Ledger',
'name' : 'cc'
}
),
# Item
#----------------------------------
# Stock item / non-serialized
'item': [
Document(
fielddata = {
'doctype': 'Item',
'docstatus': 0,
'name': 'it',
'item_name': 'it',
'item_code': 'it',
'item_group': 'ig',
'is_stock_item': 'Yes',
'has_serial_no': 'Yes',
'stock_uom': 'Nos',
'is_sales_item': 'Yes',
'is_purchase_item': 'Yes',
'is_service_item': 'No',
'is_sub_contracted_item': 'No',
'is_pro_applicable': 'Yes',
'is_manufactured_item': 'Yes'
}
),
Document(
fielddata = {
'doctype': 'Item Price',
'parentfield': 'ref_rate_details',
'parenttype': 'Item',
'parent' : 'it',
'price_list_name': 'pl',
'ref_currency': 'INR',
'ref_rate': 100
}
),
Document(
fielddata = {
'doctype': 'Item Tax',
'parentfield': 'item_tax',
'parenttype': 'Item',
'parent' : 'it',
'tax_type' : 'Tax1',
'tax_rate': 10
}
)
],
# Warehouse
#-----------------------------
'warehouse': [
Document(
fielddata = {
'doctype': 'Warehouse',
'name' : 'wh1',
'warehouse_name' : 'wh1',
'warehouse_type': 'normal',
'company': 'comp'
}
),
Document(
fielddata = {
'doctype': 'Warehouse',
'name' : 'wh2',
'warehouse_name' : 'wh2',
'warehouse_type': 'normal',
'company': 'comp'
}
)
]
}
# Save all master records
#----------------------------------
def create_master_records():
for m in master_groups.keys():
master_groups[m].save(1)
for m in main_masters.keys():
if type(main_masters[m]) == list:
for each in main_masters[m]:
each.save(1)
else:
main_masters[m].save(1)

View File

@ -1,102 +0,0 @@
# 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/>.
from __future__ import unicode_literals
from webnotes.model.doc import Document
# Existing SLE data
#---------------------------
sle = [
Document(
fielddata = {
'doctype': 'Stock Ledger Entry',
'name': 'sle1',
'posting_date': '2011-09-01',
'posting_time': '12:00',
'item_code': 'it',
'warehouse': 'wh1',
'actual_qty': 10,
'incoming_rate': 100,
'bin_aqat': 10,
'valuation_rate': 100,
'fcfs_stack': '',
'stock_value': 1000,
'is_cancelled': 'No'
}
),
Document(
fielddata = {
'doctype': 'Stock Ledger Entry',
'name': 'sle2',
'posting_date': '2011-09-01',
'posting_time': '12:00',
'item_code': 'it',
'warehouse': 'wh1',
'actual_qty': -5,
'incoming_rate': 100,
'bin_aqat': 5,
'valuation_rate': 100,
'fcfs_stack': '',
'stock_value': 500,
'is_cancelled': 'No'
}
),
Document(
fielddata = {
'doctype': 'Stock Ledger Entry',
'name': 'sle3',
'posting_date': '2011-09-10',
'posting_time': '15:00',
'item_code': 'it',
'warehouse': 'wh1',
'actual_qty': 20,
'incoming_rate': 200,
'bin_aqat': 25,
'valuation_rate': 180,
'fcfs_stack': '',
'stock_value': 4500,
'is_cancelled': 'No'
}
),
Document(
fielddata = {
'doctype': 'Stock Ledger Entry',
'name': 'sle4',
'posting_date': '2011-09-15',
'posting_time': '09:30',
'item_code': 'it',
'warehouse': 'wh1',
'actual_qty': -5,
'incoming_rate': 180,
'bin_aqat': 20,
'valuation_rate': 180,
'fcfs_stack': '',
'stock_value': 3600,
'is_cancelled': 'No'
}
)
]
bin = Document(
fielddata = {
'doctype': 'Bin',
'name': 'bin01',
'item_code': 'it',
'warehouse': 'wh1',
'actual_qty': 20,
}
)

View File

@ -1,153 +0,0 @@
# 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/>.
from __future__ import unicode_literals
from webnotes.model.doc import Document
# Material Receipt
#-----------------------
mr = [
Document(
fielddata = {
'doctype': 'Stock Entry',
'posting_date': '2011-09-01',
'transfer_date': '2011-09-01',
'posting_time': '12:00',
'company': 'comp',
'fiscal_year' : '2011-2012',
'purpose': 'Material Receipt',
'name': 'mr'
}
),
Document(
fielddata ={
'doctype': 'Stock Entry Detail',
'parenttype': 'Stock Entry',
'parentfield' : 'mtn_details',
'parent' : 'mr',
'item_code' : 'it',
't_warehouse' : 'wh1',
'qty' : 10,
'transfer_qty' : 10,
'incoming_rate': 100,
'stock_uom': 'Nos',
'conversion_factor': 1,
'serial_no': 'srno1, srno2, srno3, srno4, srno5, srno6, srno7, srno8, srno9, srno10'
}
)
]
mr1 = [
Document(
fielddata = {
'doctype': 'Stock Entry',
'posting_date': '2011-09-01',
'transfer_date': '2011-09-01',
'posting_time': '12:00',
'company': 'comp',
'fiscal_year' : '2011-2012',
'purpose': 'Material Receipt',
'name': 'mr1'
}
),
Document(
fielddata ={
'doctype': 'Stock Entry Detail',
'parenttype': 'Stock Entry',
'parentfield' : 'mtn_details',
'parent' : 'mr1',
'item_code' : 'it',
't_warehouse' : 'wh1',
'qty' : 5,
'transfer_qty' : 5,
'incoming_rate': 400,
'stock_uom': 'Nos',
'conversion_factor': 1,
'serial_no': 'srno11, srno12, srno13, srno14, srno15'
}
)
]
# Material Transfer
#--------------------
mtn = [
Document(
fielddata = {
'doctype': 'Stock Entry',
'posting_date': '2011-09-01',
'transfer_date': '2011-09-01',
'posting_time': '12:00',
'company': 'comp',
'fiscal_year' : '2011-2012',
'purpose': 'Material Transfer',
'name': 'mtn'
}
),
Document(
fielddata ={
'doctype': 'Stock Entry Detail',
'parenttype': 'Stock Entry',
'parentfield' : 'mtn_details',
'parent' : 'mtn',
'item_code' : 'it',
's_warehouse' : 'wh1',
't_warehouse' : 'wh2',
'qty' : 5,
'transfer_qty' : 5,
'incoming_rate': 100,
'stock_uom': 'Nos',
'conversion_factor': 1,
'serial_no': 'srno1, srno2, srno3, srno4, srno5'
}
)
]
# Material Issue
#--------------------
mi = [
Document(
fielddata = {
'doctype': 'Stock Entry',
'posting_date': '2011-09-01',
'transfer_date': '2011-09-01',
'posting_time': '14:00',
'company': 'comp',
'fiscal_year' : '2011-2012',
'purpose': 'Material Issue',
'name': 'mi'
}
),
Document(
fielddata ={
'doctype': 'Stock Entry Detail',
'parenttype': 'Stock Entry',
'parentfield' : 'mtn_details',
'parent' : 'mi',
'item_code' : 'it',
's_warehouse' : 'wh1',
'qty' : 4,
'transfer_qty' : 4,
'incoming_rate': 100,
'stock_uom': 'Nos',
'conversion_factor': 1,
'serial_no': 'srno1, srno2, srno3, srno4'
}
)
]

View File

@ -1,60 +0,0 @@
# 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/>.
from __future__ import unicode_literals
from webnotes.model.doc import Document
# Stock Reconciliation
#---------------------------
sreco = Document(
fielddata = {
'doctype': 'Stock Reconciliation',
'name': 'sreco',
'reconciliation_date': '2011-09-08',
'reconciliation_time': '20:00',
}
)
# diff in both
csv_data1 = [
['Item', 'Warehouse', 'Quantity', 'Rate'],
['it', 'wh1', 20, 150]
]
# diff in qty, no rate
csv_data2 = [
['Item', 'Warehouse', 'Quantity'],
['it', 'wh1', 20]
]
# diff in rate, no qty
csv_data3 = [
['Item', 'Warehouse', 'Rate'],
['it', 'wh1', 200]
]
# diff in rate, same qty
csv_data4 = [
['Item', 'Warehouse', 'Quantity', 'Rate'],
['it', 'wh1', 5, 200]
]
# no diff
csv_data1 = [
['Item', 'Warehouse', 'Quantity', 'Rate'],
['it', 'wh1', 5, 100]
]

View File

@ -2,9 +2,9 @@
{
"owner": "Administrator",
"docstatus": 0,
"creation": "2012-07-03 13:30:00",
"creation": "2012-12-14 14:27:06",
"modified_by": "Administrator",
"modified": "2012-12-12 10:42:42"
"modified": "2012-12-17 17:59:54"
},
{
"autoname": "AR.####",
@ -58,7 +58,7 @@
"fieldname": "transaction",
"fieldtype": "Select",
"reqd": 1,
"options": "\nDelivery Note\nPurchase Invoice\nPurchase Order\nPurchase Receipt\nQuotation\nSales Invoice\nSales Order\nStock Entry\nAppraisal"
"options": "\nDelivery Note\nPurchase Invoice\nPurchase Order\nPurchase Receipt\nQuotation\nSales Invoice\nSales Order\nAppraisal"
},
{
"oldfieldtype": "Select",

View File

@ -14,28 +14,33 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.onload = function(doc, cdt, cdn) {
if (!doc.posting_date) doc.posting_date = dateutil.obj_to_str(new Date());
if (!doc.transfer_date) doc.transfer_date = dateutil.obj_to_str(new Date());
if(!doc.purpose) set_multiple(cdt, cdn, {purpose:'Material Issue'});
cfn_set_fields(doc, cdt, cdn);
cur_frm.cscript.refresh = function(doc) {
erpnext.hide_naming_series();
cur_frm.cscript.toggle_related_fields(doc);
}
var cfn_set_fields = function(doc, cdt, cdn) {
lst = ['supplier', 'supplier_name', 'supplier_address',
'customer', 'customer_name', 'customer_address'];
if (in_list(['Material Issue', 'Material Transfer', 'Material Receipt', 'Sales Return',
'Purchase Return', 'Production Order', 'Subcontracting', 'Other'], doc.purpose)) {
hide_field(lst);
$(cur_frm.fields_dict.contact_section.row.wrapper).toggle(false);
} else unhide_field(lst);
cur_frm.cscript.toggle_related_fields = function(doc) {
if(doc.purpose.startswith("Production Order") || doc.purpose == "Other") {
}
if (doc.purpose == 'Production Order' || doc.purpose == 'Other') {
unhide_field('get_items');
hide_field(['from_warehouse', 'to_warehouse','purchase_receipt_no',
'delivery_note_no', 'sales_invoice_no','warehouse_html',
'transporter', 'is_excisable_goods', 'excisable_goods']);
'delivery_note_no', 'sales_invoice_no','warehouse_html']);
if (doc.purpose=='Production Order') unhide_field(['production_order', 'process']);
else {
doc.production_order = doc.process = '';
@ -81,16 +86,6 @@ var cfn_set_fields = function(doc, cdt, cdn) {
refresh_many(lst);
}
//Refresh
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
erpnext.hide_naming_series();
//India related
excise_flds = ['is_excisable_goods', 'excisable_goods', 'under_rule'];
if(wn.control_panel.country == 'India') unhide_field(excise_flds);
else hide_field(excise_flds);
}
cur_frm.cscript.delivery_note_no = function(doc,cdt,cdn){
if(doc.delivery_note_no) get_server_fields('get_cust_values','','',doc,cdt,cdn,1);
}
@ -117,11 +112,11 @@ cur_frm.fields_dict['production_order'].get_query = function(doc) {
}
cur_frm.cscript.purpose = function(doc, cdt, cdn) {
cfn_set_fields(doc, cdt, cdn);
cur_frm.cscript.toggle_related_fields(doc, cdt, cdn);
}
cur_frm.cscript.process = function(doc, cdt, cdn) {
cfn_set_fields(doc, cdt, cdn);
cur_frm.cscript.toggle_related_fields(doc, cdt, cdn);
}
// item code - only if quantity present in source warehosue

View File

@ -22,7 +22,7 @@ from webnotes.model import db_exists, delete_doc
from webnotes.model.doc import Document, addchild
from webnotes.model.wrapper import getlist, copy_doclist
from webnotes.model.code import get_obj
from webnotes import msgprint
from webnotes import msgprint, _
sql = webnotes.conn.sql
@ -34,7 +34,161 @@ class DocType(TransactionBase):
self.doclist = doclist
self.item_dict = {}
self.fname = 'mtn_details'
def validate(self):
self.validate_serial_nos()
pro_obj = self.doc.production_order and \
get_obj('Production Order', self.doc.production_order) or None
self.validate_warehouse(pro_obj)
self.validate_production_order(pro_obj)
self.get_stock_and_rate()
self.validate_incoming_rate()
self.validate_bom()
self.validate_finished_goods()
def validate_serial_nos(self):
sl_obj = get_obj("Stock Ledger")
sl_obj.scrub_serial_nos(self)
sl_obj.validate_serial_no(self, 'mtn_details')
def validate_warehouse(self, pro_obj):
"""perform various (sometimes conditional) validations on warehouse"""
source_mandatory = ["Material Issue", "Material Transfer",
"Production Order - Material Transfer", "Purchase Return"]
target_mandatory = ["Material Receipt", "Material Transfer",
"Production Order - Material Transfer", "Sales Return"]
fg_qty = 0
for d in getlist(self.doclist, 'mtn_details'):
if not d.s_warehouse and not d.t_warehouse:
d.s_warehouse = self.doc.from_warehouse
d.t_warehouse = self.doc.to_warehouse
if not (d.s_warehouse or d.t_warehouse):
msgprint(_("Atleast one warehouse is mandatory"), raise_exception=1)
if d.s_warehouse == d.t_warehouse:
msgprint(_("Source and Target Warehouse cannot be same"), raise_exception=1)
if self.doc.purpose in source_mandatory:
if not d.s_warehouse:
msgprint(_("Row # ") + "%s: " % cint(d.idx)
+ _("Source Warehouse") + _(" is mandatory"), raise_exception=1)
if self.doc.purpose not in target_mandatory:
d.t_warehouse = None
if self.doc.purpose in target_mandatory:
if not d.t_warehouse:
msgprint(_("Row # ") + "%s: " % cint(d.idx)
+ _("Target Warehouse") + _(" is mandatory"), raise_exception=1)
if self.doc.purpose not in source_mandatory:
d.s_warehouse = None
if self.doc.purpose == "Production Order - Update Finished Goods":
if d.item_code == pro_obj.doc.item:
d.s_warehouse = None
if cstr(d.t_warehouse) != pro_obj.doc.fg_warehouse:
msgprint(_("Row # ") + "%s: " % cint(d.idx)
+ _("Target Warehouse") + _(" should be same as that in ")
+ _("Production Order"), raise_exception=1)
else:
d.t_warehouse = None
if not d.s_warehouse:
msgprint(_("Row # ") + "%s: " % cint(d.idx)
+ _("Source Warehouse") + _(" is mandatory"), raise_exception=1)
# if self.doc.fg_completed_qty and flt(self.doc.fg_completed_qty) != flt(fg_qty):
# msgprint("The Total of FG Qty %s in Stock Entry Detail do not match with FG Completed Qty %s" % (flt(fg_qty), flt(self.doc.fg_completed_qty)))
# raise Exception
def validate_production_order(self, pro_obj=None):
if not pro_obj:
pro_obj = get_obj('Production Order', self.doc.production_order)
if self.doc.purpose == "Production Order - Material Transfer":
self.doc.fg_completed_qty = 0
elif self.doc.purpose == "Production Order - Update Finished Goods":
if not flt(self.doc.fg_completed_qty):
msgprint(_("Manufacturing Quantity") + _(" is mandatory"), raise_exception=1)
if flt(pro_obj.doc.qty) < (flt(pro_obj.doc.produced_qty)
+ flt(self.doc.fg_completed_qty)):
# do not allow manufacture of qty > production order qty
msgprint(_("For Item ") + pro_obj.doc.production_item
+ _("Quantity already manufactured")
+ " = %s." % flt(pro_obj.doc.produced_qty)
+ _("Hence, maximum allowed Manufacturing Quantity")
+ " = %s." % flt(pro_obj.doc.qty) - flt(pro_obj.doc.produced_qty),
raise_exception=1)
else:
self.doc.production_order = None
def get_stock_and_rate(self):
"""get stock and incoming rate on posting date"""
for d in getlist(self.doclist, 'mtn_details'):
# get actual stock at source warehouse
d.actual_qty = self.get_as_on_stock(d.item_code, d.s_warehouse or d.t_warehouse,
self.doc.posting_date, self.doc.posting_time)
# get incoming rate
if not flt(d.incoming_rate):
d.incoming_rate = self.get_incoming_rate(d.item_code,
d.s_warehouse or d.t_warehouse, self.doc.posting_date,
self.doc.posting_time, d.transfer_qty, d.serial_no, d.bom_no)
def get_as_on_stock(self, item_code, warehouse, posting_date, posting_time):
"""Get stock qty on any date"""
bin = sql("select name from tabBin where item_code = %s and warehouse = %s",
(item_code, warehouse))
if bin:
prev_sle = get_obj('Bin', bin[0][0]).get_prev_sle(posting_date, posting_time)
return flt(prev_sle["bin_aqat"])
else:
return 0
def get_incoming_rate(self, item_code=None, warehouse=None,
posting_date=None, posting_time=None, qty=0, serial_no=None, bom_no=None):
in_rate = 0
if bom_no:
result = flt(webnotes.conn.sql("""select ifnull(total_cost, 0) / ifnull(quantity, 1)
from `tabBOM` where name = %s and docstatus=1""", bom_no))
in_rate = result and result[0][0] or 0
elif warehouse:
in_rate = get_obj("Valuation Control").get_incoming_rate(posting_date, posting_time,
item_code, warehouse, qty, serial_no)
return in_rate
def validate_incoming_rate(self):
for d in getlist(self.doclist, 'mtn_details'):
if not flt(d.incoming_rate) and d.t_warehouse:
msgprint("Rate is mandatory for Item: %s at row %s" % (d.item_code, d.idx),
raise_exception=1)
def validate_bom(self):
for d in getlist(self.doclist, 'mtn_details'):
if d.bom_no and not webnotes.conn.sql("""select name from `tabBOM`
where item = %s and name = %s and docstatus = 1 and is_active = 1""",
(d.item_code, d.bom_no)):
msgprint(_("Item") + " %s: " % cstr(d.item_code)
+ _("does not belong to BOM: ") + cstr(d.bom_no)
+ _(" or the BOM is cancelled or inactive"), raise_exception=1)
def validate_finished_goods(self):
for d in getlist(self.doclist, 'mtn_details'):
if d.bom_no and flt(d.transfer_qty) != flt(self.doc.fg_completed_qty):
def get_item_details(self, arg):
import json
arg, actual_qty, in_rate = json.loads(arg), 0, 0
@ -87,50 +241,6 @@ class DocType(TransactionBase):
return ret
def get_stock_and_rate(self, bom_no = ''):
""" get stock and incoming rate on posting date"""
for d in getlist(self.doclist, 'mtn_details'):
# assign parent warehouse
d.s_warehouse = cstr(d.s_warehouse) or self.doc.purpose != 'Production Order' \
and self.doc.from_warehouse or ''
d.t_warehouse = cstr(d.t_warehouse) or self.doc.purpose != 'Production Order' \
and self.doc.to_warehouse or ''
# get current stock at source warehouse
d.actual_qty = self.get_as_on_stock(d.item_code, d.s_warehouse or d.t_warehouse,
self.doc.posting_date, self.doc.posting_time) or 0
# get incoming rate
if not flt(d.incoming_rate):
d.incoming_rate = self.get_incoming_rate(d.item_code,
d.s_warehouse or d.t_warehouse, self.doc.posting_date,
self.doc.posting_time, d.transfer_qty, d.serial_no,
d.fg_item, d.bom_no or bom_no)
def get_as_on_stock(self, item, wh, dt, tm):
"""Get stock qty on any date"""
bin = sql("select name from tabBin where item_code = %s and warehouse = %s", (item, wh))
bin_id = bin and bin[0][0] or ''
prev_sle = bin_id and get_obj('Bin', bin_id).get_prev_sle(dt, tm) or {}
qty = flt(prev_sle.get('bin_aqat', 0))
return qty
def get_incoming_rate(self, item, wh, dt, tm, qty=0, serial_no='', fg_item=0, bom_no=''):
in_rate = 0
if fg_item and bom_no:
in_rate = webnotes.conn.sql("""select ifnull(total_cost, 0) / ifnull(quantity, 1)
from `tabBOM` where name = %s and docstatus=1""", bom_no, debug=1)
in_rate = in_rate and in_rate[0][0] or 0
elif wh:
in_rate = get_obj('Valuation Control').get_incoming_rate(dt, tm,
item, wh, qty, serial_no)
return in_rate
def make_items_dict(self, items_list):
"""makes dict of unique items with it's qty"""
for i in items_list:
@ -144,9 +254,12 @@ class DocType(TransactionBase):
def update_only_remaining_qty(self):
""" Only pending raw material to be issued to shop floor """
already_issued_item = {}
for t in sql("""select t1.item_code, sum(t1.qty) from `tabStock Entry Detail` t1, `tabStock Entry` t2
where t1.parent = t2.name and t2.production_order = %s and t2.process = 'Material Transfer'
and t2.docstatus = 1 group by t1.item_code""", self.doc.production_order):
result = sql("""select t1.item_code, sum(t1.qty)
from `tabStock Entry Detail` t1, `tabStock Entry` t2
where t1.parent = t2.name and t2.production_order = %s
and t2.purpose = 'Production Order - Material Transfer'
and t2.docstatus = 1 group by t1.item_code""", self.doc.production_order)
for t in result:
already_issued_item[t[0]] = flt(t[1])
for d in self.item_dict.keys():
@ -190,7 +303,7 @@ class DocType(TransactionBase):
self.make_items_dict(fl_bom_sa_items)
# Update only qty remaining to be issued for production
if self.doc.process == 'Material Transfer':
if self.doc.purpose == 'Production Order - Material Transfer':
self.update_only_remaining_qty()
@ -211,40 +324,49 @@ class DocType(TransactionBase):
se_child.conversion_factor = 1.00
if fg_item: se_child.bom_no = bom_no
def validate_bom_no(self):
if self.doc.bom_no:
if not webnotes.conn.sql("""select name from tabBOM where name = %s and docstatus = 1
and is_active = 1""", self.doc.bom_no):
msgprint("""BOM: %s not found, may be it has been cancelled or inactivated""" %
self.doc.bom_no, raise_exception=1)
if not self.doc.fg_completed_qty:
msgprint("Please enter FG Completed Qty", raise_exception=1)
def get_items(self):
if self.doc.purpose == 'Production Order':
pro_obj = self.doc.production_order and get_obj('Production Order', self.doc.production_order) or ''
self.validate_for_production_order(pro_obj)
bom_no = self.doc.bom_no
fg_qty = self.doc.fg_completed_qty
if self.doc.purpose.startswith('Production Order'):
if not self.doc.production_order:
webnotes.msgprint(_("Please specify Production Order"), raise_exception=1)
# common validations
pro_obj = get_obj('Production Order', self.doc.production_order)
if pro_obj:
self.validate_production_order(pro_obj)
bom_no = pro_obj.doc.bom_no
fg_qty = (self.doc.process == 'Backflush') and flt(self.doc.fg_completed_qty) \
or flt(pro_obj.doc.qty)
use_multi_level_bom = pro_obj.doc.use_multi_level_bom
elif self.doc.purpose == 'Other':
self.validate_bom_no()
bom_no = self.doc.bom_no
fg_qty = self.doc.fg_completed_qty
use_multi_level_bom = self.doc.use_multi_level_bom
bom_no = pro_obj.doc.bom_no
fg_qty = (self.doc.purpose == 'Production Order - Update Finished Goods') \
and flt(self.doc.fg_completed_qty) or flt(pro_obj.doc.qty)
self.get_raw_materials(bom_no, fg_qty, use_multi_level_bom)
self.get_raw_materials(bom_no, fg_qty, self.doc.use_multi_level_bom)
self.doclist = self.doc.clear_table(self.doclist, 'mtn_details', 1)
sw = (self.doc.process == 'Backflush') and cstr(pro_obj.doc.wip_warehouse) or ''
tw = (self.doc.process == 'Material Transfer') and cstr(pro_obj.doc.wip_warehouse) or ''
self.add_to_stock_entry_detail(sw, tw, self.item_dict)
# add raw materials to Stock Entry Detail table
self.add_to_stock_entry_detail(self.doc.from_warehouse, self.doc.to_warehouse,
self.item_dict)
# add finished good item to Stock Entry Detail table
if self.doc.production_order:
self.add_to_stock_entry_detail(None, pro_obj.doc.fg_warehouse, {
cstr(pro_obj.doc.production_item):
[self.doc.fg_completed_qty, pro_obj.doc.description, pro_obj.doc.stock_uom]
})
elif self.doc.bom_no:
item = webnotes.conn.sql("""select item, description, uom from `tabBOM`
where name=%s""", (self.doc.bom_no,), as_dict=1)
self.add_to_stock_entry_detail(None, None, {
item[0]["item"] :
[self.doc.fg_completed_qty, item[0]["description"], item[0]["uom"]]
})
fg_item_dict = {}
if self.doc.process == 'Backflush':
if self.doc.purpose == 'Production Order - Update Finished Goods':
sw = ''
tw = cstr(pro_obj.doc.fg_warehouse)
fg_item_dict = {
@ -264,28 +386,17 @@ class DocType(TransactionBase):
self.get_stock_and_rate()
def validate_transfer_qty(self):
def validate_qty_as_per_stock_uom(self):
for d in getlist(self.doclist, 'mtn_details'):
if flt(d.transfer_qty) <= 0:
msgprint("Transfer Quantity can not be less than or equal to zero \
at Row No " + cstr(d.idx), raise_exception=1)
def calc_amount(self):
total_amount = 0
for d in getlist(self.doclist, 'mtn_details'):
d.amount = flt(d.transfer_qty) * flt(d.incoming_rate)
total_amount += flt(d.amount)
self.doc.total_amount = flt(total_amount)
msgprint("Row No #%s: Qty as per Stock UOM can not be less than \
or equal to zero" % cint(d.idx), raise_exception=1)
def add_to_values(self, d, wh, qty, is_cancelled):
self.values.append({
'item_code' : d.item_code,
'warehouse' : wh,
'transaction_date' : self.doc.transfer_date,
'posting_date' : self.doc.posting_date,
'posting_time' : self.doc.posting_time,
'voucher_type' : 'Stock Entry',
@ -295,10 +406,9 @@ class DocType(TransactionBase):
'incoming_rate' : flt(d.incoming_rate) or 0,
'stock_uom' : d.stock_uom,
'company' : self.doc.company,
'fiscal_year' : self.doc.fiscal_year,
'is_cancelled' : (is_cancelled ==1) and 'Yes' or 'No',
'batch_no' : d.batch_no,
'serial_no' : d.serial_no
'serial_no' : d.serial_no
})
@ -311,139 +421,6 @@ class DocType(TransactionBase):
self.add_to_values(d, cstr(d.t_warehouse), flt(d.transfer_qty), is_cancelled)
get_obj('Stock Ledger', 'Stock Ledger').update_stock(self.values, self.doc.amended_from and 'Yes' or 'No')
def validate_for_production_order(self, pro_obj):
if self.doc.purpose == 'Production Order' or self.doc.process or self.doc.production_order:
if self.doc.purpose != 'Production Order':
msgprint("Purpose should be 'Production Order'.")
raise Exception
if not self.doc.process:
msgprint("Process Field is mandatory.")
raise Exception
if self.doc.process == 'Backflush' and not flt(self.doc.fg_completed_qty):
msgprint("FG Completed Qty is mandatory as the process selected is 'Backflush'")
raise Exception
if self.doc.process == 'Material Transfer' and flt(self.doc.fg_completed_qty):
msgprint("FG Completed Qty should be zero. As the Process selected is 'Material Transfer'.")
raise Exception
if not self.doc.production_order:
msgprint("Production Order field is mandatory")
raise Exception
if flt(pro_obj.doc.qty) < flt(pro_obj.doc.produced_qty) + flt(self.doc.fg_completed_qty) :
msgprint("error:Already Produced Qty for %s is %s and maximum allowed Qty is %s" % (pro_obj.doc.production_item, cstr(pro_obj.doc.produced_qty) or 0.00 , cstr(pro_obj.doc.qty)))
raise Exception
def validate(self):
sl_obj = get_obj("Stock Ledger", "Stock Ledger")
sl_obj.scrub_serial_nos(self)
sl_obj.validate_serial_no(self, 'mtn_details')
pro_obj = ''
if self.doc.production_order:
pro_obj = get_obj('Production Order', self.doc.production_order)
self.validate_for_production_order(pro_obj)
self.get_stock_and_rate(pro_obj and pro_obj.doc.bom_no or '')
self.validate_warehouse(pro_obj)
self.validate_incoming_rate()
self.validate_bom_belongs_to_item()
self.calc_amount()
get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,
self.doc.posting_date, 'Posting Date')
if self.doc.purpose == 'Other':
self.validate_bom_no()
# If target warehouse exists, incoming rate is mandatory
# --------------------------------------------------------
def validate_incoming_rate(self):
for d in getlist(self.doclist, 'mtn_details'):
if not flt(d.incoming_rate) and d.t_warehouse:
msgprint("Rate is mandatory for Item: %s at row %s" % (d.item_code, d.idx), raise_exception=1)
def validate_bom_belongs_to_item(self):
for d in getlist(self.doclist, 'mtn_details'):
if d.bom_no and not webnotes.conn.sql("""\
SELECT name FROM `tabBOM`
WHERE item = %s and name = %s
""", (d.item_code, d.bom_no)):
msgprint("BOM %s does not belong to Item: %s at row %s" % (d.bom_no, d.item_code, d.idx), raise_exception=1)
# Validate warehouse
# -----------------------------------
def validate_warehouse(self, pro_obj):
fg_qty = 0
for d in getlist(self.doclist, 'mtn_details'):
if not d.s_warehouse and not d.t_warehouse:
d.s_warehouse = self.doc.from_warehouse
d.t_warehouse = self.doc.to_warehouse
if not (d.s_warehouse or d.t_warehouse):
msgprint("Atleast one warehouse is mandatory for Stock Entry")
raise Exception
if d.s_warehouse and not sql("select name from tabWarehouse where name = '%s'" % d.s_warehouse):
msgprint("Invalid Warehouse: %s" % self.doc.s_warehouse)
raise Exception
if d.t_warehouse and not sql("select name from tabWarehouse where name = '%s'" % d.t_warehouse):
msgprint("Invalid Warehouse: %s" % self.doc.t_warehouse)
raise Exception
if d.s_warehouse == d.t_warehouse:
msgprint("Source and Target Warehouse Cannot be Same.")
raise Exception
if self.doc.purpose == 'Material Issue':
if not cstr(d.s_warehouse):
msgprint("Source Warehouse is Mandatory for Purpose => 'Material Issue'")
raise Exception
if cstr(d.t_warehouse):
msgprint("Target Warehouse is not Required for Purpose => 'Material Issue'")
raise Exception
if self.doc.purpose == 'Material Transfer':
if not cstr(d.s_warehouse) or not cstr(d.t_warehouse):
msgprint("Source Warehouse and Target Warehouse both are Mandatory for Purpose => 'Material Transfer'")
raise Exception
if self.doc.purpose == 'Material Receipt':
if not cstr(d.t_warehouse):
msgprint("Target Warehouse is Mandatory for Purpose => 'Material Receipt'")
raise Exception
if cstr(d.s_warehouse):
msgprint("Source Warehouse is not Required for Purpose => 'Material Receipt'")
raise Exception
if self.doc.process == 'Material Transfer':
if cstr(d.t_warehouse) != (pro_obj.doc.wip_warehouse):
msgprint(" Target Warehouse should be same as WIP Warehouse %s in Production Order %s at Row No %s" % (cstr(pro_obj.doc.wip_warehouse), cstr(pro_obj.doc.name), cstr(d.idx)) )
raise Exception
if not cstr(d.s_warehouse):
msgprint("Please Enter Source Warehouse at Row No %s." % (cstr(d.idx)))
raise Exception
if self.doc.process == 'Backflush':
if flt(d.fg_item):
if cstr(pro_obj.doc.production_item) != cstr(d.item_code):
msgprint("Item %s in Stock Entry Detail as Row No %s do not match with Item %s in Production Order %s" % (cstr(d.item_code), cstr(d.idx), cstr(pro_obj.doc.production_item), cstr(pro_obj.doc.name)))
raise Exception
if cstr(d.t_warehouse) != cstr(pro_obj.doc.fg_warehouse):
msgprint("As Item %s is FG Item. Target Warehouse should be same as FG Warehouse %s in Production Order %s, at Row No %s. " % ( cstr(d.item_code), cstr(pro_obj.doc.fg_warehouse), cstr(pro_obj.doc.name), cstr(d.idx)))
raise Exception
if cstr(d.s_warehouse):
msgprint("As Item %s is a FG Item. There should be no Source Warehouse at Row No %s" % (cstr(d.item_code), cstr(d.idx)))
raise Exception
if not flt(d.fg_item):
if cstr(d.t_warehouse):
msgprint("As Item %s is not a FG Item. There should no Tareget Warehouse at Row No %s" % (cstr(d.item_code), cstr(d.idx)))
raise Exception
if cstr(d.s_warehouse) != cstr(pro_obj.doc.wip_warehouse):
msgprint("As Item %s is Raw Material. Source Warehouse should be same as WIP Warehouse %s in Production Order %s, at Row No %s. " % ( cstr(d.item_code), cstr(pro_obj.doc.wip_warehouse), cstr(pro_obj.doc.name), cstr(d.idx)))
raise Exception
if d.fg_item and (self.doc.purpose == 'Other' or self.doc.process == 'Backflush'):
fg_qty = flt(fg_qty) + flt(d.transfer_qty)
d.save()
if self.doc.fg_completed_qty and flt(self.doc.fg_completed_qty) != flt(fg_qty):
msgprint("The Total of FG Qty %s in Stock Entry Detail do not match with FG Completed Qty %s" % (flt(fg_qty), flt(self.doc.fg_completed_qty)))
raise Exception
def update_production_order(self, is_submit):
if self.doc.production_order:
pro_obj = get_obj("Production Order", self.doc.production_order)
@ -460,7 +437,7 @@ class DocType(TransactionBase):
msgprint("""Posting Date of Stock Entry cannot be before Posting Date of
Production Order: %s"""% cstr(self.doc.production_order), raise_exception=1)
if self.doc.process == 'Backflush':
if self.doc.purpose == "Production Order - Update Finished Goods":
pro_obj.doc.produced_qty = flt(pro_obj.doc.produced_qty) + \
(is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty)
args = {
@ -469,8 +446,6 @@ class DocType(TransactionBase):
"planned_qty": (is_submit and -1 or 1 ) * flt(self.doc.fg_completed_qty)
}
get_obj('Warehouse', pro_obj.doc.fg_warehouse).update_bin(args)
elif self.doc.process == 'Material Transfer':
pass
pro_obj.doc.status = (flt(pro_obj.doc.qty)==flt(pro_obj.doc.produced_qty)) \
and 'Completed' or 'In Process'
@ -503,9 +478,7 @@ class DocType(TransactionBase):
def on_submit(self):
self.validate_transfer_qty()
# Check for Approving Authority
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.total_amount)
self.validate_qty_as_per_stock_uom()
self.update_serial_no(1)
self.update_stock_ledger(0)
# update Production Order

View File

@ -2,9 +2,9 @@
{
"owner": "Administrator",
"docstatus": 0,
"creation": "2012-11-28 11:26:22",
"creation": "2012-12-17 11:42:09",
"modified_by": "Administrator",
"modified": "2012-12-10 18:30:00"
"modified": "2012-12-17 18:19:44"
},
{
"is_submittable": 1,
@ -59,7 +59,6 @@
"description": "To manage multiple series please go to Setup > Manage Series",
"no_copy": 1,
"oldfieldtype": "Select",
"colour": "White:FFF",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Series",
@ -75,223 +74,24 @@
"report_hide": 0
},
{
"permlevel": 0,
"print_hide": 0,
"no_copy": 0,
"oldfieldtype": "Select",
"colour": "White:FFF",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Purpose",
"oldfieldname": "purpose",
"permlevel": 0,
"trigger": "Client",
"default": "Material Issue",
"fieldname": "purpose",
"fieldtype": "Select",
"search_index": 0,
"reqd": 1,
"hidden": 0,
"options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nSales Return\nPurchase Return\nSubcontracting\nProduction Order\nOther",
"options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nSales Return\nPurchase Return\nSubcontracting\nProduction Order - Material Transfer\nProduction Order - Update Finished Goods\nOther",
"report_hide": 0,
"in_filter": 1
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Link",
"colour": "White:FFF",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Delivery Note No",
"oldfieldname": "delivery_note_no",
"permlevel": 0,
"trigger": "Client",
"fieldname": "delivery_note_no",
"fieldtype": "Link",
"search_index": 1,
"reqd": 0,
"hidden": 1,
"options": "Delivery Note",
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Link",
"colour": "White:FFF",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Purchase Receipt No",
"oldfieldname": "purchase_receipt_no",
"permlevel": 0,
"trigger": "Client",
"fieldname": "purchase_receipt_no",
"fieldtype": "Link",
"search_index": 1,
"reqd": 0,
"hidden": 1,
"options": "Purchase Receipt",
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"doctype": "DocField",
"label": "Sales Invoice No",
"options": "Sales Invoice",
"fieldname": "sales_invoice_no",
"fieldtype": "Link",
"hidden": 1,
"permlevel": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Select",
"colour": "White:FFF",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Process",
"oldfieldname": "process",
"permlevel": 0,
"trigger": "Client",
"fieldname": "process",
"fieldtype": "Select",
"search_index": 0,
"reqd": 0,
"hidden": 1,
"options": "\nMaterial Transfer\nBackflush",
"report_hide": 0,
"in_filter": 1
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Link",
"colour": "White:FFF",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Production Order",
"oldfieldname": "production_order",
"permlevel": 0,
"trigger": "Client",
"fieldname": "production_order",
"fieldtype": "Link",
"search_index": 1,
"reqd": 0,
"hidden": 1,
"options": "Production Order",
"report_hide": 0,
"in_filter": 1
},
{
"depends_on": "eval:doc.purpose == 'Other'",
"doctype": "DocField",
"label": "BOM No",
"options": "BOM",
"fieldname": "bom_no",
"fieldtype": "Link",
"permlevel": 0
},
{
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
"depends_on": "eval:doc.purpose == 'Other'",
"colour": "White:FFF",
"doctype": "DocField",
"label": "Use Multi-Level BOM",
"fieldname": "use_multi_level_bom",
"fieldtype": "Check",
"permlevel": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Currency",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "FG Completed Qty",
"oldfieldname": "fg_completed_qty",
"trigger": "Client",
"fieldname": "fg_completed_qty",
"fieldtype": "Currency",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"permlevel": 0,
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Button",
"colour": "White:FFF",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Get Items",
"permlevel": 0,
"fieldname": "get_items",
"fieldtype": "Button",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"options": "get_items",
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "HTML",
"colour": "White:FFF",
"doctype": "DocField",
"label": "Warehouse HTML",
"options": "<div class='columnHeading'>Warehouse</div>",
"fieldname": "warehouse_html",
"fieldtype": "HTML",
"permlevel": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Link",
"colour": "White:FFF",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Source Warehouse",
"oldfieldname": "from_warehouse",
"permlevel": 0,
"trigger": "Client",
"fieldname": "from_warehouse",
"fieldtype": "Link",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"options": "Warehouse",
"report_hide": 0,
"in_filter": 0
},
{
"no_copy": 0,
"oldfieldtype": "Link",
"oldfieldname": "to_warehouse",
"reqd": 0,
"in_filter": 0,
"print_hide": 1,
"label": "Target Warehouse",
"trigger": "Client",
"hidden": 0,
"permlevel": 0,
"description": "<b>Notes:</b> Either Source or Target is Mandatory",
"search_index": 0,
"allow_on_submit": 0,
"colour": "White:FFF",
"doctype": "DocField",
"fieldname": "to_warehouse",
"fieldtype": "Link",
"options": "Warehouse",
"report_hide": 0
},
{
"oldfieldtype": "Column Break",
"doctype": "DocField",
@ -303,12 +103,13 @@
{
"print_hide": 1,
"description": "The date at which current entry will get or has actually executed.",
"no_copy": 1,
"default": "Today",
"oldfieldtype": "Date",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Posting Date",
"oldfieldname": "posting_date",
"no_copy": 1,
"fieldname": "posting_date",
"fieldtype": "Date",
"search_index": 1,
@ -335,23 +136,6 @@
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"no_copy": 1,
"oldfieldtype": "Text",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Remarks",
"oldfieldname": "remarks",
"fieldname": "remarks",
"fieldtype": "Text",
"search_index": 0,
"reqd": 1,
"hidden": 0,
"permlevel": 0,
"report_hide": 0,
"in_filter": 0
},
{
"oldfieldtype": "Section Break",
"doctype": "DocField",
@ -360,11 +144,59 @@
"fieldtype": "Section Break",
"permlevel": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Link",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Default Source Warehouse",
"oldfieldname": "from_warehouse",
"permlevel": 0,
"fieldname": "from_warehouse",
"fieldtype": "Link",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"options": "Warehouse",
"report_hide": 0,
"in_filter": 0
},
{
"doctype": "DocField",
"fieldname": "cb0",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Link",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Default Target Warehouse",
"oldfieldname": "to_warehouse",
"permlevel": 0,
"fieldname": "to_warehouse",
"fieldtype": "Link",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"options": "Warehouse",
"report_hide": 0,
"in_filter": 0
},
{
"doctype": "DocField",
"options": "Simple",
"fieldname": "sb0",
"fieldtype": "Section Break",
"permlevel": 0
},
{
"print_hide": 0,
"no_copy": 0,
"oldfieldtype": "Table",
"colour": "White:FFF",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "MTN Details",
@ -379,43 +211,10 @@
"report_hide": 0,
"in_filter": 0
},
{
"oldfieldtype": "Section Break",
"doctype": "DocField",
"options": "Simple",
"fieldname": "item_section",
"fieldtype": "Section Break",
"permlevel": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Currency",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Total Amount",
"oldfieldname": "total_amount",
"fieldname": "total_amount",
"fieldtype": "Currency",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"permlevel": 1,
"report_hide": 0,
"in_filter": 0
},
{
"oldfieldtype": "Column Break",
"doctype": "DocField",
"fieldname": "col3",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"print_hide": 1,
"description": "Get valuation rate and available stock at source/target warehouse on mentioned posting date-time. If serialized item, please press this button after entering serial nos.",
"oldfieldtype": "Button",
"colour": "White:FFF",
"doctype": "DocField",
"label": "Get Stock and Rate",
"options": "get_stock_and_rate",
@ -424,6 +223,139 @@
"permlevel": 0
},
{
"doctype": "DocField",
"label": "Reference",
"fieldname": "sb1",
"fieldtype": "Section Break",
"permlevel": 0
},
{
"print_hide": 1,
"depends_on": "eval:doc.purpose.startsWith(\"Production Order\")",
"no_copy": 0,
"search_index": 1,
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Production Order",
"oldfieldname": "production_order",
"permlevel": 0,
"fieldname": "production_order",
"fieldtype": "Link",
"oldfieldtype": "Link",
"reqd": 0,
"hidden": 1,
"options": "Production Order",
"report_hide": 0,
"in_filter": 1
},
{
"depends_on": "eval:!doc.purpose.startsWith(\"Production Order\")",
"doctype": "DocField",
"label": "BOM No",
"options": "BOM",
"fieldname": "bom_no",
"fieldtype": "Link",
"permlevel": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Currency",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Manufacturing Quantity",
"oldfieldname": "fg_completed_qty",
"fieldname": "fg_completed_qty",
"fieldtype": "Currency",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"permlevel": 0,
"report_hide": 0,
"in_filter": 0
},
{
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
"doctype": "DocField",
"label": "Use Multi-Level BOM",
"fieldname": "use_multi_level_bom",
"fieldtype": "Check",
"permlevel": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Button",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Get Items",
"permlevel": 0,
"fieldname": "get_items",
"fieldtype": "Button",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"options": "get_items",
"report_hide": 0,
"in_filter": 0
},
{
"doctype": "DocField",
"fieldname": "cb1",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"print_hide": 1,
"depends_on": "eval:doc.purpose==\"Sales Return\"",
"no_copy": 0,
"search_index": 1,
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Delivery Note No",
"oldfieldname": "delivery_note_no",
"permlevel": 0,
"fieldname": "delivery_note_no",
"fieldtype": "Link",
"oldfieldtype": "Link",
"reqd": 0,
"hidden": 1,
"options": "Delivery Note",
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"depends_on": "eval:doc.purpose==\"Sales Return\"",
"doctype": "DocField",
"label": "Sales Invoice No",
"options": "Sales Invoice",
"fieldname": "sales_invoice_no",
"fieldtype": "Link",
"hidden": 1,
"permlevel": 0
},
{
"print_hide": 1,
"depends_on": "eval:doc.purpose==\"Purchase Return\"",
"no_copy": 0,
"search_index": 1,
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Purchase Receipt No",
"oldfieldname": "purchase_receipt_no",
"permlevel": 0,
"fieldname": "purchase_receipt_no",
"fieldtype": "Link",
"oldfieldtype": "Link",
"reqd": 0,
"hidden": 1,
"options": "Purchase Receipt",
"report_hide": 0,
"in_filter": 0
},
{
"depends_on": "eval:(doc.purpose==\"Sales Return\" || doc.purpose==\"Purchase Return\")",
"doctype": "DocField",
"label": "Contact Info",
"fieldname": "contact_section",
@ -432,18 +364,17 @@
},
{
"print_hide": 1,
"depends_on": "eval:doc.purpose==\"Purchase Return\"",
"no_copy": 0,
"oldfieldtype": "Link",
"colour": "White:FFF",
"search_index": 0,
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Supplier",
"oldfieldname": "supplier",
"permlevel": 0,
"trigger": "Client",
"fieldname": "supplier",
"fieldtype": "Link",
"search_index": 0,
"oldfieldtype": "Link",
"reqd": 0,
"hidden": 0,
"options": "Supplier",
@ -452,15 +383,16 @@
},
{
"print_hide": 0,
"depends_on": "eval:doc.purpose==\"Purchase Return\"",
"no_copy": 0,
"oldfieldtype": "Data",
"search_index": 0,
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Supplier Name",
"oldfieldname": "supplier_name",
"fieldname": "supplier_name",
"fieldtype": "Data",
"search_index": 0,
"oldfieldtype": "Data",
"reqd": 0,
"hidden": 0,
"permlevel": 1,
@ -469,17 +401,16 @@
},
{
"print_hide": 0,
"depends_on": "eval:doc.purpose==\"Purchase Return\"",
"no_copy": 0,
"oldfieldtype": "Small Text",
"colour": "White:FFF",
"search_index": 0,
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Supplier Address",
"oldfieldname": "supplier_address",
"trigger": "Client",
"fieldname": "supplier_address",
"fieldtype": "Small Text",
"search_index": 0,
"oldfieldtype": "Small Text",
"reqd": 0,
"hidden": 0,
"permlevel": 0,
@ -488,18 +419,17 @@
},
{
"print_hide": 1,
"depends_on": "eval:doc.purpose==\"Sales Return\"",
"no_copy": 0,
"oldfieldtype": "Link",
"colour": "White:FFF",
"search_index": 0,
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Customer",
"oldfieldname": "customer",
"permlevel": 0,
"trigger": "Client",
"fieldname": "customer",
"fieldtype": "Link",
"search_index": 0,
"oldfieldtype": "Link",
"reqd": 0,
"hidden": 0,
"options": "Customer",
@ -508,15 +438,16 @@
},
{
"print_hide": 0,
"depends_on": "eval:doc.purpose==\"Sales Return\"",
"no_copy": 0,
"oldfieldtype": "Data",
"search_index": 0,
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Customer Name",
"oldfieldname": "customer_name",
"fieldname": "customer_name",
"fieldtype": "Data",
"search_index": 0,
"oldfieldtype": "Data",
"reqd": 0,
"hidden": 0,
"permlevel": 1,
@ -525,15 +456,16 @@
},
{
"print_hide": 0,
"depends_on": "eval:doc.purpose==\"Sales Return\"",
"no_copy": 0,
"oldfieldtype": "Small Text",
"search_index": 0,
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Customer Address",
"oldfieldname": "customer_address",
"fieldname": "customer_address",
"fieldtype": "Small Text",
"search_index": 0,
"oldfieldtype": "Small Text",
"reqd": 0,
"hidden": 0,
"permlevel": 0,
@ -584,119 +516,6 @@
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"no_copy": 1,
"oldfieldtype": "Data",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Cancel Reason",
"oldfieldname": "cancel_reason",
"fieldname": "cancel_reason",
"fieldtype": "Data",
"search_index": 0,
"reqd": 0,
"hidden": 1,
"permlevel": 1,
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 0,
"no_copy": 1,
"oldfieldtype": "Date",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Transfer Date",
"oldfieldname": "transfer_date",
"default": "Today",
"fieldname": "transfer_date",
"fieldtype": "Date",
"search_index": 0,
"reqd": 1,
"hidden": 0,
"permlevel": 0,
"report_hide": 0,
"in_filter": 1
},
{
"doctype": "DocField",
"width": "50%",
"fieldname": "col5",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Select",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Is Excisable Goods",
"oldfieldname": "is_excisable_goods",
"permlevel": 0,
"fieldname": "is_excisable_goods",
"fieldtype": "Select",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"options": "\nYes\nNo",
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Select",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Excisable Goods",
"oldfieldname": "excisable_goods",
"permlevel": 0,
"fieldname": "excisable_goods",
"fieldtype": "Select",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"options": "\nReturnable\nNon-Returnable",
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Select",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Under Rule",
"oldfieldname": "under_rule",
"permlevel": 0,
"fieldname": "under_rule",
"fieldtype": "Select",
"search_index": 0,
"reqd": 0,
"hidden": 1,
"options": "\nOrdinary\n57 AC (5) a\n57 F (2) Non-Exc.",
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Data",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Transporter",
"oldfieldname": "transporter",
"fieldname": "transporter",
"fieldtype": "Data",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"permlevel": 0,
"report_hide": 0,
"in_filter": 0
},
{
"print_hide": 1,
"no_copy": 0,
@ -716,22 +535,11 @@
"in_filter": 1
},
{
"print_hide": 1,
"no_copy": 0,
"oldfieldtype": "Select",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Fiscal Year",
"oldfieldname": "fiscal_year",
"permlevel": 0,
"fieldname": "fiscal_year",
"fieldtype": "Select",
"search_index": 0,
"reqd": 1,
"hidden": 0,
"options": "link:Fiscal Year",
"report_hide": 0,
"in_filter": 0
"width": "50%",
"fieldname": "col5",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"print_hide": 1,
@ -753,21 +561,20 @@
},
{
"print_hide": 1,
"description": "The date at which current entry is corrected in the system.",
"no_copy": 1,
"oldfieldtype": "Date",
"oldfieldtype": "Text",
"allow_on_submit": 0,
"doctype": "DocField",
"label": "Amendment Date",
"oldfieldname": "amendment_date",
"fieldname": "amendment_date",
"fieldtype": "Date",
"label": "Remarks",
"oldfieldname": "remarks",
"fieldname": "remarks",
"fieldtype": "Text",
"search_index": 0,
"reqd": 0,
"hidden": 0,
"in_filter": 0,
"permlevel": 0,
"report_hide": 0
"report_hide": 0,
"in_filter": 0
},
{
"amend": 1,

View File

@ -4,7 +4,7 @@
"docstatus": 0,
"creation": "2012-07-03 13:29:47",
"modified_by": "Administrator",
"modified": "2012-12-03 11:37:17"
"modified": "2012-12-17 16:12:42"
},
{
"istable": 1,
@ -14,6 +14,7 @@
"module": "Stock"
},
{
"read_only": 0,
"name": "__common__",
"parent": "Stock Entry Detail",
"doctype": "DocField",
@ -52,7 +53,6 @@
"label": "Item Code",
"oldfieldname": "item_code",
"permlevel": 0,
"trigger": "Client",
"fieldname": "item_code",
"fieldtype": "Link",
"search_index": 1,
@ -75,7 +75,6 @@
"doctype": "DocField",
"label": "Qty",
"oldfieldname": "qty",
"trigger": "Client",
"fieldname": "qty",
"fieldtype": "Currency",
"reqd": 1,
@ -83,15 +82,13 @@
},
{
"oldfieldtype": "Link",
"colour": "White:FFF",
"doctype": "DocField",
"label": "UOM",
"oldfieldname": "uom",
"trigger": "Client",
"options": "UOM",
"fieldname": "uom",
"fieldtype": "Link",
"reqd": 1,
"options": "UOM",
"permlevel": 0
},
{
@ -130,10 +127,9 @@
"doctype": "DocField",
"label": "Batch No",
"oldfieldname": "batch_no",
"trigger": "Client",
"options": "Batch",
"fieldname": "batch_no",
"fieldtype": "Link",
"options": "Batch",
"permlevel": 0
},
{
@ -174,7 +170,7 @@
{
"oldfieldtype": "Currency",
"doctype": "DocField",
"label": "Stock Qty",
"label": "Qty as per Stock UOM",
"oldfieldname": "transfer_qty",
"fieldname": "transfer_qty",
"fieldtype": "Currency",
@ -186,12 +182,12 @@
"doctype": "DocField",
"label": "Stock UOM",
"oldfieldname": "stock_uom",
"options": "UOM",
"permlevel": 1,
"fieldname": "stock_uom",
"fieldtype": "Link",
"search_index": 0,
"reqd": 1,
"permlevel": 1,
"options": "UOM",
"in_filter": 0
},
{

View File

@ -125,7 +125,6 @@ class DocType:
s.modified_by = session['user']
s.serial_no = serial_no
s.sle_exists = 1
s.fiscal_year = obj.doc.fiscal_year
s.company = obj.doc.company
s.save(new_rec)

View File

@ -44,7 +44,7 @@ class DocType:
def validate_mandatory(self):
mandatory = ['warehouse','transaction_date','posting_date','voucher_type','voucher_no','actual_qty','company','fiscal_year']
mandatory = ['warehouse','transaction_date','posting_date','voucher_type','voucher_no','actual_qty','company']
for k in mandatory:
if self.doc.fields.get(k)==None:
msgprint("Stock Ledger Entry: '%s' is mandatory" % k, raise_exception = 1)