Merge branch 'master' of github.com:webnotes/erpnext
This commit is contained in:
commit
8bf41ea461
@ -18,7 +18,11 @@
|
|||||||
<br>
|
<br>
|
||||||
<h5><a href="#Accounts Browser/Cost Center">Chart of Cost Centers</a></h5>
|
<h5><a href="#Accounts Browser/Cost Center">Chart of Cost Centers</a></h5>
|
||||||
<p class="help">Structure cost centers</p>
|
<p class="help">Structure cost centers</p>
|
||||||
<br>
|
</div>
|
||||||
|
<div style="clear: both"></div>
|
||||||
|
<hr>
|
||||||
|
<h4>Reports</h4>
|
||||||
|
<div style="width: 48%; float: left;">
|
||||||
<h5><a href="#general-ledger"
|
<h5><a href="#general-ledger"
|
||||||
data-role="Analytics, Accounts Manager, Accounts User">
|
data-role="Analytics, Accounts Manager, Accounts User">
|
||||||
General Ledger</a>
|
General Ledger</a>
|
||||||
@ -29,16 +33,16 @@
|
|||||||
data-role="Analytics, Accounts Manager, Accounts User">Trial Balance</a>
|
data-role="Analytics, Accounts Manager, Accounts User">Trial Balance</a>
|
||||||
</h5>
|
</h5>
|
||||||
<p class="help">Tree view of all Account balances</p>
|
<p class="help">Tree view of all Account balances</p>
|
||||||
<br>
|
</div>
|
||||||
|
<div style="width: 48%; float: right;">
|
||||||
<h5><a href="#financial-analytics"
|
<h5><a href="#financial-analytics"
|
||||||
data-role="Analytics, Accounts Manager, Accounts User">
|
data-role="Analytics, Accounts Manager, Accounts User">
|
||||||
Financial Analytics</a>
|
Financial Analytics</a>
|
||||||
</h5>
|
</h5>
|
||||||
<p class="help">Visual representation of financial trends</p>
|
<p class="help">Visual representation of financial trends</p>
|
||||||
</div>
|
</div>
|
||||||
<div style="clear: both"></div>
|
<div style="clear: both;"></div>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>Reports</h3>
|
|
||||||
<div class="reports-list"></div>
|
<div class="reports-list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-side-section">
|
<div class="layout-side-section">
|
||||||
|
|||||||
@ -128,8 +128,13 @@ class DocType(TransactionBase):
|
|||||||
# Validate
|
# Validate
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_fiscal_year()
|
self.validate_fiscal_year()
|
||||||
# Step 1:=> set status as "Draft"
|
|
||||||
webnotes.conn.set(self.doc, 'status', 'Draft')
|
if not self.doc.status:
|
||||||
|
self.doc.status = "Draft"
|
||||||
|
|
||||||
|
import utilities
|
||||||
|
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
|
||||||
|
"Cancelled"])
|
||||||
|
|
||||||
# Step 2:=> get Purchase Common Obj
|
# Step 2:=> get Purchase Common Obj
|
||||||
pc_obj = get_obj(dt='Purchase Common')
|
pc_obj = get_obj(dt='Purchase Common')
|
||||||
|
|||||||
@ -141,8 +141,12 @@ class DocType:
|
|||||||
self.validate_schedule_date()
|
self.validate_schedule_date()
|
||||||
self.validate_fiscal_year()
|
self.validate_fiscal_year()
|
||||||
|
|
||||||
# set status as "Draft"
|
if not self.doc.status:
|
||||||
webnotes.conn.set(self.doc, 'status', 'Draft')
|
self.doc.status = "Draft"
|
||||||
|
|
||||||
|
import utilities
|
||||||
|
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
|
||||||
|
"Cancelled"])
|
||||||
|
|
||||||
# Get Purchase Common Obj
|
# Get Purchase Common Obj
|
||||||
pc_obj = get_obj(dt='Purchase Common')
|
pc_obj = get_obj(dt='Purchase Common')
|
||||||
|
|||||||
@ -30,10 +30,16 @@ class DocType(TransactionBase):
|
|||||||
self.doc.name = make_autoname(self.doc.naming_series + ".#####")
|
self.doc.name = make_autoname(self.doc.naming_series + ".#####")
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
if not self.doc.status:
|
||||||
|
self.doc.status = "Draft"
|
||||||
|
|
||||||
|
import utilities
|
||||||
|
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
|
||||||
|
"Cancelled"])
|
||||||
|
|
||||||
self.validate_fiscal_year()
|
self.validate_fiscal_year()
|
||||||
self.validate_common()
|
self.validate_common()
|
||||||
self.set_in_words()
|
self.set_in_words()
|
||||||
self.doc.status = "Draft"
|
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
purchase_controller = webnotes.get_obj("Purchase Common")
|
purchase_controller = webnotes.get_obj("Purchase Common")
|
||||||
|
|||||||
@ -23,15 +23,20 @@
|
|||||||
<br>
|
<br>
|
||||||
<h5><a href="#List/Address">Address</a></h5>
|
<h5><a href="#List/Address">Address</a></h5>
|
||||||
<p class="help">Address Master</p>
|
<p class="help">Address Master</p>
|
||||||
<br>
|
</div>
|
||||||
|
<div style="clear: both"></div>
|
||||||
|
<hr>
|
||||||
|
<h4>Reports</h4>
|
||||||
|
<div style="width: 48%; float: left;">
|
||||||
<h5><a href="#purchase-analytics" data-role="Analytics, Purchase Manager">
|
<h5><a href="#purchase-analytics" data-role="Analytics, Purchase Manager">
|
||||||
Purchase Analytics</a>
|
Purchase Analytics</a>
|
||||||
</h5>
|
</h5>
|
||||||
<p class="help">Purchase trends based on Purchase Invoice</p>
|
<p class="help">Purchase trends based on Purchase Invoice</p>
|
||||||
</div>
|
</div>
|
||||||
<div style="clear: both"></div>
|
<div style="width: 48%; float: right;">
|
||||||
|
</div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>Reports</h3>
|
|
||||||
<div class="reports-list"></div>
|
<div class="reports-list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-side-section">
|
<div class="layout-side-section">
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
erpnext.updates = [
|
erpnext.updates = [
|
||||||
["28th December 2012", [
|
["28th December 2012", [
|
||||||
"Workflow: Added System for Multi-level approval before Submission. \
|
"Workflow: Added System for Multi-level approval before Submission. \
|
||||||
<br>See video at <a href='https://www.youtube.com/watch?v=zuGv59_wJKw' target='_blank'>https://www.youtube.com/watch?v=zuGv59_wJKw</a>.",
|
<br>See video at <a href='https://www.youtube.com/watch?v=zuGv59_wJKw' \
|
||||||
|
target='_blank'>https://www.youtube.com/watch?v=zuGv59_wJKw</a>.",
|
||||||
|
"Stock Level Report: New report to see available and estimated qty of stock",
|
||||||
]],
|
]],
|
||||||
["27th December 2012", [
|
["27th December 2012", [
|
||||||
"Website: Added auto-generated Contact Us and About Us Pages",
|
"Website: Added auto-generated Contact Us and About Us Pages",
|
||||||
|
|||||||
@ -57,6 +57,7 @@ class DocType:
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
if not self.doc.status:
|
if not self.doc.status:
|
||||||
self.doc.status = "Draft"
|
self.doc.status = "Draft"
|
||||||
|
|
||||||
self.validate_dates()
|
self.validate_dates()
|
||||||
self.validate_existing_appraisal()
|
self.validate_existing_appraisal()
|
||||||
self.calculate_total()
|
self.calculate_total()
|
||||||
|
|||||||
@ -8,11 +8,11 @@
|
|||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
@ -28,79 +28,81 @@ sql = webnotes.conn.sql
|
|||||||
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self, doc, doclist=[]):
|
def __init__(self, doc, doclist=[]):
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
#autoname function
|
#autoname function
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
self.doc.name = make_autoname(self.doc.naming_series+'.#####')
|
self.doc.name = make_autoname(self.doc.naming_series+'.#####')
|
||||||
|
|
||||||
#get employee name based on employee id selected
|
#get employee name based on employee id selected
|
||||||
def get_emp_name(self):
|
def get_emp_name(self):
|
||||||
emp_nm = sql("select employee_name from `tabEmployee` where name=%s", self.doc.employee)
|
emp_nm = sql("select employee_name from `tabEmployee` where name=%s", self.doc.employee)
|
||||||
|
|
||||||
#this is done because sometimes user entered wrong employee name while uploading employee attendance
|
#this is done because sometimes user entered wrong employee name while uploading employee attendance
|
||||||
webnotes.conn.set(self.doc, 'employee_name', emp_nm and emp_nm[0][0] or '')
|
webnotes.conn.set(self.doc, 'employee_name', emp_nm and emp_nm[0][0] or '')
|
||||||
|
|
||||||
ret = { 'employee_name' : emp_nm and emp_nm[0][0] or ''}
|
ret = { 'employee_name' : emp_nm and emp_nm[0][0] or ''}
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
#validation for duplicate record
|
#validation for duplicate record
|
||||||
def validate_duplicate_record(self):
|
def validate_duplicate_record(self):
|
||||||
res = sql("select name from `tabAttendance` where employee = '%s' and att_date = '%s' and not name = '%s' and docstatus = 1"%(self.doc.employee,self.doc.att_date, self.doc.name))
|
res = sql("select name from `tabAttendance` where employee = '%s' and att_date = '%s' and not name = '%s' and docstatus = 1"%(self.doc.employee,self.doc.att_date, self.doc.name))
|
||||||
if res:
|
if res:
|
||||||
msgprint("Employee's attendance already marked.")
|
msgprint("Employee's attendance already marked.")
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
|
|
||||||
#check for already record present in leave transaction for same date
|
#check for already record present in leave transaction for same date
|
||||||
def check_leave_record(self):
|
def check_leave_record(self):
|
||||||
if self.doc.status == 'Present':
|
if self.doc.status == 'Present':
|
||||||
chk = sql("select name from `tabLeave Application` where employee=%s and (from_date <= %s and to_date >= %s) and docstatus!=2", (self.doc.employee, self.doc.att_date, self.doc.att_date))
|
chk = sql("select name from `tabLeave Application` where employee=%s and (from_date <= %s and to_date >= %s) and docstatus!=2", (self.doc.employee, self.doc.att_date, self.doc.att_date))
|
||||||
if chk:
|
if chk:
|
||||||
msgprint("Leave Application created for employee "+self.doc.employee+" whom you are trying to mark as 'Present' ")
|
msgprint("Leave Application created for employee "+self.doc.employee+" whom you are trying to mark as 'Present' ")
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
|
|
||||||
def validate_fiscal_year(self):
|
def validate_fiscal_year(self):
|
||||||
fy=sql("select year_start_date from `tabFiscal Year` where name='%s'"% self.doc.fiscal_year)
|
fy=sql("select year_start_date from `tabFiscal Year` where name='%s'" % \
|
||||||
ysd=fy and fy[0][0] or ""
|
self.doc.fiscal_year)
|
||||||
yed=add_days(str(ysd),365)
|
ysd=fy and fy[0][0] or ""
|
||||||
if str(self.doc.att_date) < str(ysd) or str(self.doc.att_date) > str(yed):
|
yed=add_days(str(ysd),365)
|
||||||
msgprint("'%s' Not Within The Fiscal Year selected"%(self.doc.att_date))
|
if str(self.doc.att_date) < str(ysd) or str(self.doc.att_date) > str(yed):
|
||||||
raise Exception
|
msgprint("'%s' Not Within The Fiscal Year selected"%(self.doc.att_date))
|
||||||
|
raise Exception
|
||||||
|
|
||||||
def validate_att_date(self):
|
def validate_att_date(self):
|
||||||
import datetime
|
import datetime
|
||||||
if getdate(self.doc.att_date)>getdate(datetime.datetime.now().date().strftime('%Y-%m-%d')):
|
if getdate(self.doc.att_date)>getdate(datetime.datetime.now().date().strftime('%Y-%m-%d')):
|
||||||
msgprint("Attendance can not be marked for future dates")
|
msgprint("Attendance can not be marked for future dates")
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
# Validate employee
|
# Validate employee
|
||||||
#-------------------
|
#-------------------
|
||||||
def validate_employee(self):
|
def validate_employee(self):
|
||||||
emp = sql("select name, status from `tabEmployee` where name = '%s'" % self.doc.employee)
|
emp = sql("select name, status from `tabEmployee` where name = '%s'" % self.doc.employee)
|
||||||
if not emp:
|
if not emp:
|
||||||
msgprint("Employee: %s does not exists in the system" % self.doc.employee, raise_exception=1)
|
msgprint("Employee: %s does not exists in the system" % self.doc.employee, raise_exception=1)
|
||||||
elif emp[0][1] != 'Active':
|
elif emp[0][1] != 'Active':
|
||||||
msgprint("Employee: %s is not Active" % self.doc.employee, raise_exception=1)
|
msgprint("Employee: %s is not Active" % self.doc.employee, raise_exception=1)
|
||||||
|
|
||||||
# validate...
|
def validate(self):
|
||||||
def validate(self):
|
import utilities
|
||||||
self.validate_fiscal_year()
|
utilities.validate_status(self.doc.status, ["Present", "Absent", "Half Day"])
|
||||||
self.validate_att_date()
|
|
||||||
self.validate_duplicate_record()
|
|
||||||
#self.validate_status()
|
|
||||||
self.check_leave_record()
|
|
||||||
|
|
||||||
def on_update(self):
|
self.validate_fiscal_year()
|
||||||
#self.validate()
|
self.validate_att_date()
|
||||||
|
self.validate_duplicate_record()
|
||||||
|
self.check_leave_record()
|
||||||
|
|
||||||
#this is done because sometimes user entered wrong employee name while uploading employee attendance
|
def on_update(self):
|
||||||
x=self.get_emp_name()
|
#self.validate()
|
||||||
|
|
||||||
def on_submit(self):
|
#this is done because sometimes user entered wrong employee name while uploading employee attendance
|
||||||
#this is done because while uploading attendance chnage docstatus to 1 i.e. submit
|
x=self.get_emp_name()
|
||||||
webnotes.conn.set(self.doc,'docstatus',1)
|
|
||||||
pass
|
def on_submit(self):
|
||||||
|
#this is done because while uploading attendance chnage docstatus to 1 i.e. submit
|
||||||
|
webnotes.conn.set(self.doc,'docstatus',1)
|
||||||
|
pass
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import webnotes
|
|||||||
|
|
||||||
from webnotes.utils import getdate, validate_email_add
|
from webnotes.utils import getdate, validate_email_add
|
||||||
from webnotes.model.doc import make_autoname
|
from webnotes.model.doc import make_autoname
|
||||||
from webnotes import msgprint
|
from webnotes import msgprint, _
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
sql = webnotes.conn.sql
|
||||||
|
|
||||||
@ -40,6 +40,16 @@ class DocType:
|
|||||||
|
|
||||||
self.doc.employee = self.doc.name
|
self.doc.employee = self.doc.name
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
import utilities
|
||||||
|
utilities.validate_status(self.doc.status, ["Active", "Left"])
|
||||||
|
|
||||||
|
self.doc.employee = self.doc.name
|
||||||
|
self.validate_date()
|
||||||
|
self.validate_email()
|
||||||
|
self.validate_name()
|
||||||
|
self.validate_status()
|
||||||
|
|
||||||
def get_retirement_date(self):
|
def get_retirement_date(self):
|
||||||
import datetime
|
import datetime
|
||||||
ret = {}
|
ret = {}
|
||||||
@ -52,13 +62,6 @@ class DocType:
|
|||||||
ret_sal_struct=sql("select name from `tabSalary Structure` where employee='%s' and is_active = 'Yes' and docstatus!= 2"%nm)
|
ret_sal_struct=sql("select name from `tabSalary Structure` where employee='%s' and is_active = 'Yes' and docstatus!= 2"%nm)
|
||||||
return ret_sal_struct and ret_sal_struct[0][0] or ''
|
return ret_sal_struct and ret_sal_struct[0][0] or ''
|
||||||
|
|
||||||
def validate(self):
|
|
||||||
self.doc.employee = self.doc.name
|
|
||||||
self.validate_date()
|
|
||||||
self.validate_email()
|
|
||||||
self.validate_name()
|
|
||||||
self.validate_status()
|
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
self.update_user_default()
|
self.update_user_default()
|
||||||
|
|
||||||
|
|||||||
@ -33,9 +33,8 @@ class DocType:
|
|||||||
# if self.doc.exp_approver == self.doc.owner:
|
# if self.doc.exp_approver == self.doc.owner:
|
||||||
# webnotes.msgprint("""Self Approval is not allowed.""", raise_exception=1)
|
# webnotes.msgprint("""Self Approval is not allowed.""", raise_exception=1)
|
||||||
|
|
||||||
if self.doc.status not in ("Draft", "Approved", "Rejected"):
|
import utilities
|
||||||
webnotes.msgprint("Status must be one of 'Draft', 'Approved' or 'Rejected'",
|
utilities.validate_status(self.doc.status, ["Draft", "Approved", "Rejected"])
|
||||||
raise_exception=True)
|
|
||||||
|
|
||||||
self.validate_fiscal_year()
|
self.validate_fiscal_year()
|
||||||
self.validate_exp_details()
|
self.validate_exp_details()
|
||||||
|
|||||||
@ -33,9 +33,8 @@ class DocType:
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
# if self.doc.leave_approver == self.doc.owner:
|
# if self.doc.leave_approver == self.doc.owner:
|
||||||
# webnotes.msgprint("""Self Approval is not allowed.""", raise_exception=1)
|
# webnotes.msgprint("""Self Approval is not allowed.""", raise_exception=1)
|
||||||
if self.doc.status not in ("Open", "Approved", "Rejected"):
|
import utilities
|
||||||
webnotes.msgprint("Status must be one of 'Open', 'Approved' or 'Rejected'",
|
utilities.validate_status(self.doc.status, ["Open", "Approved", "Rejected"])
|
||||||
raise_exception=True)
|
|
||||||
|
|
||||||
self.validate_to_date()
|
self.validate_to_date()
|
||||||
self.validate_balance_leaves()
|
self.validate_balance_leaves()
|
||||||
|
|||||||
@ -8,11 +8,11 @@
|
|||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
@ -28,87 +28,86 @@ sql = webnotes.conn.sql
|
|||||||
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
#init function
|
#init function
|
||||||
def __init__(self,doc,doclist=[]):
|
def __init__(self,doc,doclist=[]):
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
#autoname function
|
#autoname function
|
||||||
#---------------------------------------------------------
|
#---------------------------------------------------------
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
self.doc.name = make_autoname(self.doc.employee + '/.SST' + '/.#####')
|
self.doc.name = make_autoname(self.doc.employee + '/.SST' + '/.#####')
|
||||||
|
|
||||||
#get employee details
|
#get employee details
|
||||||
#---------------------------------------------------------
|
#---------------------------------------------------------
|
||||||
def get_employee_details(self):
|
def get_employee_details(self):
|
||||||
ret = {}
|
ret = {}
|
||||||
det = sql("select employee_name, branch, designation, department, grade from `tabEmployee` where name = '%s'" %self.doc.employee)
|
det = sql("select employee_name, branch, designation, department, grade from `tabEmployee` where name = '%s'" %self.doc.employee)
|
||||||
if det:
|
if det:
|
||||||
ret = {
|
ret = {
|
||||||
'employee_name' : cstr(det[0][0]),
|
'employee_name': cstr(det[0][0]),
|
||||||
'branch' : cstr(det[0][1]),
|
'branch': cstr(det[0][1]),
|
||||||
'designation' : cstr(det[0][2]),
|
'designation': cstr(det[0][2]),
|
||||||
'department' : cstr(det[0][3]),
|
'department': cstr(det[0][3]),
|
||||||
'grade' : cstr(det[0][4]),
|
'grade': cstr(det[0][4]),
|
||||||
'backup_employee': cstr(self.doc.employee)
|
'backup_employee': cstr(self.doc.employee)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
# Set Salary structure field values
|
# Set Salary structure field values
|
||||||
#---------------------------------------------------------
|
#---------------------------------------------------------
|
||||||
def get_ss_values(self,employee):
|
def get_ss_values(self,employee):
|
||||||
basic_info = sql("select bank_name, bank_ac_no, esic_card_no, pf_number from `tabEmployee` where name ='%s'" % employee)
|
basic_info = sql("select bank_name, bank_ac_no, esic_card_no, pf_number from `tabEmployee` where name ='%s'" % employee)
|
||||||
ret = {'bank_name' : basic_info and basic_info[0][0] or '',
|
ret = {'bank_name': basic_info and basic_info[0][0] or '',
|
||||||
'bank_ac_no' : basic_info and basic_info[0][1] or '',
|
'bank_ac_no': basic_info and basic_info[0][1] or '',
|
||||||
'esic_no' : basic_info and basic_info[0][2] or '',
|
'esic_no': basic_info and basic_info[0][2] or '',
|
||||||
'pf_no' : basic_info and basic_info[0][3] or ''}
|
'pf_no': basic_info and basic_info[0][3] or ''}
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# Make earning and deduction table
|
# Make earning and deduction table
|
||||||
#---------------------------------------------------------
|
#---------------------------------------------------------
|
||||||
def make_table(self, doct_name, tab_fname, tab_name):
|
def make_table(self, doct_name, tab_fname, tab_name):
|
||||||
list1 = sql("select name from `tab%s` where docstatus != 2" % doct_name)
|
list1 = sql("select name from `tab%s` where docstatus != 2" % doct_name)
|
||||||
for li in list1:
|
for li in list1:
|
||||||
child = addchild(self.doc, tab_fname, tab_name, self.doclist)
|
child = addchild(self.doc, tab_fname, tab_name, self.doclist)
|
||||||
if(tab_fname == 'earning_details'):
|
if(tab_fname == 'earning_details'):
|
||||||
child.e_type = cstr(li[0])
|
child.e_type = cstr(li[0])
|
||||||
child.modified_value = 0
|
child.modified_value = 0
|
||||||
elif(tab_fname == 'deduction_details'):
|
elif(tab_fname == 'deduction_details'):
|
||||||
child.d_type = cstr(li[0])
|
child.d_type = cstr(li[0])
|
||||||
child.d_modified_amt = 0
|
child.d_modified_amt = 0
|
||||||
|
|
||||||
# add earning & deduction types to table
|
# add earning & deduction types to table
|
||||||
#---------------------------------------------------------
|
#---------------------------------------------------------
|
||||||
def make_earn_ded_table(self):
|
def make_earn_ded_table(self):
|
||||||
#Earning List
|
#Earning List
|
||||||
self.make_table('Earning Type','earning_details','Salary Structure Earning')
|
self.make_table('Earning Type','earning_details','Salary Structure Earning')
|
||||||
|
|
||||||
#Deduction List
|
#Deduction List
|
||||||
self.make_table('Deduction Type','deduction_details', 'Salary Structure Deduction')
|
self.make_table('Deduction Type','deduction_details',
|
||||||
|
'Salary Structure Deduction')
|
||||||
|
|
||||||
|
|
||||||
# Check if another active ss exists
|
# Check if another active ss exists
|
||||||
#---------------------------------------------------------
|
#---------------------------------------------------------
|
||||||
def check_existing(self):
|
def check_existing(self):
|
||||||
ret = sql("select name from `tabSalary Structure` where is_active = 'Yes' and employee = '%s' and name!='%s'" %(self.doc.employee,self.doc.name))
|
ret = sql("select name from `tabSalary Structure` where is_active = 'Yes' and employee = '%s' and name!='%s'" %(self.doc.employee,self.doc.name))
|
||||||
if ret and self.doc.is_active=='Yes':
|
if ret and self.doc.is_active=='Yes':
|
||||||
msgprint("Another Salary Structure '%s' is active for employee '%s'. Please make its status 'Inactive' to proceed."%(cstr(ret), self.doc.employee))
|
msgprint("Another Salary Structure '%s' is active for employee '%s'. Please make its status 'Inactive' to proceed."%(cstr(ret), self.doc.employee))
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
# Validate net pay
|
# Validate net pay
|
||||||
#---------------------------------------------------------
|
#---------------------------------------------------------
|
||||||
def validate_net_pay(self):
|
def validate_net_pay(self):
|
||||||
if flt(self.doc.net_pay) < 0:
|
if flt(self.doc.net_pay) < 0:
|
||||||
msgprint("Net pay can not be negative")
|
msgprint("Net pay can not be negative")
|
||||||
raise Exception
|
raise Exception
|
||||||
elif flt(self.doc.net_pay) > flt(self.doc.ctc):
|
elif flt(self.doc.net_pay) > flt(self.doc.ctc):
|
||||||
msgprint("Net pay can not be greater than CTC")
|
msgprint("Net pay can not be greater than CTC")
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
# Validate
|
def validate(self):
|
||||||
#---------------------------------------------------------
|
self.check_existing()
|
||||||
def validate(self):
|
self.validate_net_pay()
|
||||||
self.check_existing()
|
|
||||||
self.validate_net_pay()
|
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="clear: both"></div>
|
<div style="clear: both"></div>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>Reports</h3>
|
<h4>Reports</h4>
|
||||||
<div class="reports-list"></div>
|
<div class="reports-list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-side-section">
|
<div class="layout-side-section">
|
||||||
|
|||||||
@ -34,6 +34,10 @@ class DocType:
|
|||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
import utilities
|
||||||
|
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
|
||||||
|
"In Process", "Completed", "Cancelled"])
|
||||||
|
|
||||||
if self.doc.production_item :
|
if self.doc.production_item :
|
||||||
item_detail = sql("select name from `tabItem` where name = '%s' and docstatus != 2"
|
item_detail = sql("select name from `tabItem` where name = '%s' and docstatus != 2"
|
||||||
% self.doc.production_item, as_dict = 1)
|
% self.doc.production_item, as_dict = 1)
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="clear: both"></div>
|
<div style="clear: both"></div>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>Reports</h3>
|
<h4>Reports</h4>
|
||||||
<div class="reports-list"></div>
|
<div class="reports-list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-side-section">
|
<div class="layout-side-section">
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="clear: both"></div>
|
<div style="clear: both"></div>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>Reports</h3>
|
<h4>Reports</h4>
|
||||||
<div class="reports-list"></div>
|
<div class="reports-list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-side-section">
|
<div class="layout-side-section">
|
||||||
|
|||||||
@ -70,7 +70,7 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
|
|||||||
{fieldtype:"Select", label: "Brand", link:"Brand",
|
{fieldtype:"Select", label: "Brand", link:"Brand",
|
||||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||||
return val == opts.default_value || item.brand == val || item._show;
|
return val == opts.default_value || item.brand == val || item._show;
|
||||||
}},
|
}, link_formatter: {filter_input: "brand"}},
|
||||||
{fieldtype:"Select", label: "Warehouse", link:"Warehouse",
|
{fieldtype:"Select", label: "Warehouse", link:"Warehouse",
|
||||||
default_value: "Select Warehouse..."},
|
default_value: "Select Warehouse..."},
|
||||||
{fieldtype:"Date", label: "From Date"},
|
{fieldtype:"Date", label: "From Date"},
|
||||||
|
|||||||
@ -8,11 +8,11 @@
|
|||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
@ -30,178 +30,176 @@ sql = webnotes.conn.sql
|
|||||||
from utilities.transaction_base import TransactionBase
|
from utilities.transaction_base import TransactionBase
|
||||||
|
|
||||||
class DocType(TransactionBase):
|
class DocType(TransactionBase):
|
||||||
def __init__(self, doc, doclist=[]):
|
def __init__(self, doc, doclist=[]):
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
self.tname = 'Installation Note Item'
|
self.tname = 'Installation Note Item'
|
||||||
self.fname = 'installed_item_details'
|
self.fname = 'installed_item_details'
|
||||||
|
|
||||||
# Autoname
|
def autoname(self):
|
||||||
# ---------
|
self.doc.name = make_autoname(self.doc.naming_series+'.#####')
|
||||||
def autoname(self):
|
|
||||||
self.doc.name = make_autoname(self.doc.naming_series+'.#####')
|
def validate(self):
|
||||||
|
self.validate_fiscal_year()
|
||||||
|
self.validate_installation_date()
|
||||||
|
self.check_item_table()
|
||||||
|
sales_com_obj = get_obj(dt = 'Sales Common')
|
||||||
|
sales_com_obj.check_active_sales_items(self)
|
||||||
|
sales_com_obj.get_prevdoc_date(self)
|
||||||
|
self.validate_mandatory()
|
||||||
|
self.validate_reference_value()
|
||||||
|
|
||||||
|
|
||||||
#fetch delivery note details
|
#fetch delivery note details
|
||||||
#====================================
|
#====================================
|
||||||
def pull_delivery_note_details(self):
|
def pull_delivery_note_details(self):
|
||||||
self.validate_prev_docname()
|
self.validate_prev_docname()
|
||||||
self.doclist = get_obj('DocType Mapper', 'Delivery Note-Installation Note').dt_map('Delivery Note', 'Installation Note', self.doc.delivery_note_no, self.doc, self.doclist, "[['Delivery Note', 'Installation Note'],['Delivery Note Item', 'Installation Note Item']]")
|
self.doclist = get_obj('DocType Mapper', 'Delivery Note-Installation Note').dt_map('Delivery Note', 'Installation Note', self.doc.delivery_note_no, self.doc, self.doclist, "[['Delivery Note', 'Installation Note'],['Delivery Note Item', 'Installation Note Item']]")
|
||||||
|
|
||||||
# Validates that Delivery Note is not pulled twice
|
# Validates that Delivery Note is not pulled twice
|
||||||
#============================================
|
#============================================
|
||||||
def validate_prev_docname(self):
|
def validate_prev_docname(self):
|
||||||
for d in getlist(self.doclist, 'installed_item_details'):
|
for d in getlist(self.doclist, 'installed_item_details'):
|
||||||
if self.doc.delivery_note_no == d.prevdoc_docname:
|
if self.doc.delivery_note_no == d.prevdoc_docname:
|
||||||
msgprint(cstr(self.doc.delivery_note_no) + " delivery note details have already been pulled. ")
|
msgprint(cstr(self.doc.delivery_note_no) + " delivery note details have already been pulled. ")
|
||||||
raise Exception, "Validation Error. "
|
raise Exception, "Validation Error. "
|
||||||
|
|
||||||
#Fiscal Year Validation
|
#Fiscal Year Validation
|
||||||
#================================
|
#================================
|
||||||
def validate_fiscal_year(self):
|
def validate_fiscal_year(self):
|
||||||
get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.inst_date,'Installation Date')
|
get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.inst_date,'Installation Date')
|
||||||
|
|
||||||
# Validate Mandatory
|
# Validate Mandatory
|
||||||
#===============================
|
#===============================
|
||||||
def validate_mandatory(self):
|
def validate_mandatory(self):
|
||||||
# Amendment Date
|
# Amendment Date
|
||||||
if self.doc.amended_from and not self.doc.amendment_date:
|
if self.doc.amended_from and not self.doc.amendment_date:
|
||||||
msgprint("Please Enter Amendment Date")
|
msgprint("Please Enter Amendment Date")
|
||||||
raise Exception, "Validation Error. "
|
raise Exception, "Validation Error. "
|
||||||
|
|
||||||
# Validate values with reference document
|
# Validate values with reference document
|
||||||
#----------------------------------------
|
#----------------------------------------
|
||||||
def validate_reference_value(self):
|
def validate_reference_value(self):
|
||||||
get_obj('DocType Mapper', 'Delivery Note-Installation Note', with_children = 1).validate_reference_value(self, self.doc.name)
|
get_obj('DocType Mapper', 'Delivery Note-Installation Note', with_children = 1).validate_reference_value(self, self.doc.name)
|
||||||
|
|
||||||
#check if serial no added
|
#check if serial no added
|
||||||
#-----------------------------
|
#-----------------------------
|
||||||
def is_serial_no_added(self,item_code,serial_no):
|
def is_serial_no_added(self,item_code,serial_no):
|
||||||
ar_required = sql("select has_serial_no from tabItem where name = '%s'" % item_code)
|
ar_required = sql("select has_serial_no from tabItem where name = '%s'" % item_code)
|
||||||
ar_required = ar_required and ar_required[0][0] or ''
|
ar_required = ar_required and ar_required[0][0] or ''
|
||||||
if ar_required == 'Yes' and not serial_no:
|
if ar_required == 'Yes' and not serial_no:
|
||||||
msgprint("Serial No is mandatory for item: "+ item_code)
|
msgprint("Serial No is mandatory for item: "+ item_code)
|
||||||
raise Exception
|
raise Exception
|
||||||
elif ar_required != 'Yes' and cstr(serial_no).strip():
|
elif ar_required != 'Yes' and cstr(serial_no).strip():
|
||||||
msgprint("If serial no required, please select 'Yes' in 'Has Serial No' in Item :"+item_code)
|
msgprint("If serial no required, please select 'Yes' in 'Has Serial No' in Item :"+item_code)
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
#check if serial no exist in system
|
#check if serial no exist in system
|
||||||
#-------------------------------------
|
#-------------------------------------
|
||||||
def is_serial_no_exist(self, item_code, serial_no):
|
def is_serial_no_exist(self, item_code, serial_no):
|
||||||
for x in serial_no:
|
for x in serial_no:
|
||||||
chk = sql("select name from `tabSerial No` where name =%s", x)
|
chk = sql("select name from `tabSerial No` where name =%s", x)
|
||||||
if not chk:
|
if not chk:
|
||||||
msgprint("Serial No "+x+" does not exist in the system")
|
msgprint("Serial No "+x+" does not exist in the system")
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
#check if serial no already installed
|
#check if serial no already installed
|
||||||
#------------------------------------------
|
#------------------------------------------
|
||||||
def is_serial_no_installed(self,cur_s_no,item_code):
|
def is_serial_no_installed(self,cur_s_no,item_code):
|
||||||
for x in cur_s_no:
|
for x in cur_s_no:
|
||||||
status = sql("select status from `tabSerial No` where name = %s", x)
|
status = sql("select status from `tabSerial No` where name = %s", x)
|
||||||
status = status and status[0][0] or ''
|
status = status and status[0][0] or ''
|
||||||
|
|
||||||
if status == 'Installed':
|
if status == 'Installed':
|
||||||
msgprint("Item "+item_code+" with serial no. "+x+" already installed")
|
msgprint("Item "+item_code+" with serial no. "+x+" already installed")
|
||||||
raise Exception, "Validation Error."
|
raise Exception, "Validation Error."
|
||||||
|
|
||||||
#get list of serial no from previous_doc
|
#get list of serial no from previous_doc
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
def get_prevdoc_serial_no(self, prevdoc_detail_docname, prevdoc_docname):
|
def get_prevdoc_serial_no(self, prevdoc_detail_docname, prevdoc_docname):
|
||||||
from stock.doctype.stock_ledger.stock_ledger import get_sr_no_list
|
from stock.doctype.stock_ledger.stock_ledger import get_sr_no_list
|
||||||
|
|
||||||
res = sql("select serial_no from `tabDelivery Note Item` where name = '%s' and parent ='%s'" % (prevdoc_detail_docname, prevdoc_docname))
|
res = sql("select serial_no from `tabDelivery Note Item` where name = '%s' and parent ='%s'" % (prevdoc_detail_docname, prevdoc_docname))
|
||||||
return get_sr_no_list(res[0][0])
|
return get_sr_no_list(res[0][0])
|
||||||
|
|
||||||
#check if all serial nos from current record exist in resp delivery note
|
#check if all serial nos from current record exist in resp delivery note
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
def is_serial_no_match(self, cur_s_no, prevdoc_s_no, prevdoc_docname):
|
def is_serial_no_match(self, cur_s_no, prevdoc_s_no, prevdoc_docname):
|
||||||
for x in cur_s_no:
|
for x in cur_s_no:
|
||||||
if not(x in prevdoc_s_no):
|
if not(x in prevdoc_s_no):
|
||||||
msgprint("Serial No. "+x+" not present in the Delivery Note "+prevdoc_docname, raise_exception = 1)
|
msgprint("Serial No. "+x+" not present in the Delivery Note "+prevdoc_docname, raise_exception = 1)
|
||||||
raise Exception, "Validation Error."
|
raise Exception, "Validation Error."
|
||||||
|
|
||||||
#validate serial number
|
#validate serial number
|
||||||
#----------------------------------------
|
#----------------------------------------
|
||||||
def validate_serial_no(self):
|
def validate_serial_no(self):
|
||||||
cur_s_no, prevdoc_s_no, sr_list = [], [], []
|
cur_s_no, prevdoc_s_no, sr_list = [], [], []
|
||||||
from stock.doctype.stock_ledger.stock_ledger import get_sr_no_list
|
from stock.doctype.stock_ledger.stock_ledger import get_sr_no_list
|
||||||
|
|
||||||
for d in getlist(self.doclist, 'installed_item_details'):
|
for d in getlist(self.doclist, 'installed_item_details'):
|
||||||
self.is_serial_no_added(d.item_code, d.serial_no)
|
self.is_serial_no_added(d.item_code, d.serial_no)
|
||||||
|
|
||||||
if d.serial_no:
|
if d.serial_no:
|
||||||
|
|
||||||
sr_list = get_sr_no_list(d.serial_no, d.qty, d.item_code)
|
sr_list = get_sr_no_list(d.serial_no, d.qty, d.item_code)
|
||||||
self.is_serial_no_exist(d.item_code, sr_list)
|
self.is_serial_no_exist(d.item_code, sr_list)
|
||||||
|
|
||||||
prevdoc_s_no = self.get_prevdoc_serial_no(d.prevdoc_detail_docname, d.prevdoc_docname)
|
prevdoc_s_no = self.get_prevdoc_serial_no(d.prevdoc_detail_docname, d.prevdoc_docname)
|
||||||
if prevdoc_s_no:
|
if prevdoc_s_no:
|
||||||
self.is_serial_no_match(sr_list, prevdoc_s_no, d.prevdoc_docname)
|
self.is_serial_no_match(sr_list, prevdoc_s_no, d.prevdoc_docname)
|
||||||
|
|
||||||
self.is_serial_no_installed(sr_list, d.item_code)
|
self.is_serial_no_installed(sr_list, d.item_code)
|
||||||
return sr_list
|
return sr_list
|
||||||
|
|
||||||
#validate installation date
|
#validate installation date
|
||||||
#-------------------------------
|
#-------------------------------
|
||||||
def validate_installation_date(self):
|
def validate_installation_date(self):
|
||||||
for d in getlist(self.doclist, 'installed_item_details'):
|
for d in getlist(self.doclist, 'installed_item_details'):
|
||||||
if d.prevdoc_docname:
|
if d.prevdoc_docname:
|
||||||
d_date = sql("select posting_date from `tabDelivery Note` where name=%s", d.prevdoc_docname)
|
d_date = sql("select posting_date from `tabDelivery Note` where name=%s", d.prevdoc_docname)
|
||||||
d_date = d_date and d_date[0][0] or ''
|
d_date = d_date and d_date[0][0] or ''
|
||||||
|
|
||||||
if d_date > getdate(self.doc.inst_date):
|
if d_date > getdate(self.doc.inst_date):
|
||||||
msgprint("Installation Date can not be before Delivery Date "+cstr(d_date)+" for item "+d.item_code)
|
msgprint("Installation Date can not be before Delivery Date "+cstr(d_date)+" for item "+d.item_code)
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
def validate(self):
|
def check_item_table(self):
|
||||||
self.validate_fiscal_year()
|
if not(getlist(self.doclist, 'installed_item_details')):
|
||||||
self.validate_installation_date()
|
msgprint("Please fetch items from Delivery Note selected")
|
||||||
self.check_item_table()
|
raise Exception
|
||||||
sales_com_obj = get_obj(dt = 'Sales Common')
|
|
||||||
sales_com_obj.check_active_sales_items(self)
|
|
||||||
sales_com_obj.get_prevdoc_date(self)
|
|
||||||
self.validate_mandatory()
|
|
||||||
self.validate_reference_value()
|
|
||||||
|
|
||||||
def check_item_table(self):
|
def on_update(self):
|
||||||
if not(getlist(self.doclist, 'installed_item_details')):
|
webnotes.conn.set(self.doc, 'status', 'Draft')
|
||||||
msgprint("Please fetch items from Delivery Note selected")
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
def on_update(self):
|
def on_submit(self):
|
||||||
webnotes.conn.set(self.doc, 'status', 'Draft')
|
valid_lst = []
|
||||||
|
valid_lst = self.validate_serial_no()
|
||||||
|
|
||||||
def on_submit(self):
|
get_obj("Sales Common").update_prevdoc_detail(1,self)
|
||||||
valid_lst = []
|
|
||||||
valid_lst = self.validate_serial_no()
|
|
||||||
|
|
||||||
get_obj("Sales Common").update_prevdoc_detail(1,self)
|
for x in valid_lst:
|
||||||
|
wp = sql("select warranty_period from `tabSerial No` where name = '%s'"% x)
|
||||||
|
wp = wp and wp[0][0] or 0
|
||||||
|
if wp:
|
||||||
|
sql("update `tabSerial No` set maintenance_status = 'Under Warranty' where name = '%s'" % x)
|
||||||
|
|
||||||
for x in valid_lst:
|
sql("update `tabSerial No` set status = 'Installed' where name = '%s'" % x)
|
||||||
wp = sql("select warranty_period from `tabSerial No` where name = '%s'"% x)
|
|
||||||
wp = wp and wp[0][0] or 0
|
|
||||||
if wp:
|
|
||||||
sql("update `tabSerial No` set maintenance_status = 'Under Warranty' where name = '%s'" % x)
|
|
||||||
|
|
||||||
sql("update `tabSerial No` set status = 'Installed' where name = '%s'" % x)
|
webnotes.conn.set(self.doc, 'status', 'Submitted')
|
||||||
|
|
||||||
webnotes.conn.set(self.doc, 'status', 'Submitted')
|
|
||||||
|
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
cur_s_no = []
|
cur_s_no = []
|
||||||
sales_com_obj = get_obj(dt = 'Sales Common')
|
sales_com_obj = get_obj(dt = 'Sales Common')
|
||||||
sales_com_obj.update_prevdoc_detail(0,self)
|
sales_com_obj.update_prevdoc_detail(0,self)
|
||||||
|
|
||||||
for d in getlist(self.doclist, 'installed_item_details'):
|
for d in getlist(self.doclist, 'installed_item_details'):
|
||||||
if d.serial_no:
|
if d.serial_no:
|
||||||
#get current list of serial no
|
#get current list of serial no
|
||||||
cur_serial_no = d.serial_no.replace(' ', '')
|
cur_serial_no = d.serial_no.replace(' ', '')
|
||||||
cur_s_no = cur_serial_no.split(',')
|
cur_s_no = cur_serial_no.split(',')
|
||||||
|
|
||||||
for x in cur_s_no:
|
for x in cur_s_no:
|
||||||
sql("update `tabSerial No` set status = 'Delivered' where name = '%s'" % x)
|
sql("update `tabSerial No` set status = 'Delivered' where name = '%s'" % x)
|
||||||
|
|
||||||
webnotes.conn.set(self.doc, 'status', 'Cancelled')
|
webnotes.conn.set(self.doc, 'status', 'Cancelled')
|
||||||
|
|||||||
@ -179,6 +179,10 @@ class DocType(TransactionBase):
|
|||||||
# Validate
|
# Validate
|
||||||
# --------
|
# --------
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
import utilities
|
||||||
|
utilities.validate_status(self.doc.status, ["Draft", "Submitted",
|
||||||
|
"Order Confirmed", "Order Lost", "Cancelled"])
|
||||||
|
|
||||||
self.validate_fiscal_year()
|
self.validate_fiscal_year()
|
||||||
self.validate_mandatory()
|
self.validate_mandatory()
|
||||||
self.set_last_contact_date()
|
self.set_last_contact_date()
|
||||||
|
|||||||
@ -226,8 +226,13 @@ class DocType(TransactionBase):
|
|||||||
self.doc.in_words = sales_com_obj.get_total_in_words(dcc, self.doc.rounded_total)
|
self.doc.in_words = sales_com_obj.get_total_in_words(dcc, self.doc.rounded_total)
|
||||||
self.doc.in_words_export = sales_com_obj.get_total_in_words(self.doc.currency, self.doc.rounded_total_export)
|
self.doc.in_words_export = sales_com_obj.get_total_in_words(self.doc.currency, self.doc.rounded_total_export)
|
||||||
|
|
||||||
# set SO status
|
if not self.doc.status:
|
||||||
self.doc.status='Draft'
|
self.doc.status = "Draft"
|
||||||
|
|
||||||
|
import utilities
|
||||||
|
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
|
||||||
|
"Cancelled"])
|
||||||
|
|
||||||
if not self.doc.billing_status: self.doc.billing_status = 'Not Billed'
|
if not self.doc.billing_status: self.doc.billing_status = 'Not Billed'
|
||||||
if not self.doc.delivery_status: self.doc.delivery_status = 'Not Delivered'
|
if not self.doc.delivery_status: self.doc.delivery_status = 'Not Delivered'
|
||||||
|
|
||||||
|
|||||||
@ -29,15 +29,20 @@
|
|||||||
<br>
|
<br>
|
||||||
<h5><a href="#List/Address">Address</a></h5>
|
<h5><a href="#List/Address">Address</a></h5>
|
||||||
<p class="help">Address Master</p>
|
<p class="help">Address Master</p>
|
||||||
<br>
|
</div>
|
||||||
|
<div style="clear: both"></div>
|
||||||
|
<hr>
|
||||||
|
<h4>Reports</h4>
|
||||||
|
<div style="width: 48%; float: left;">
|
||||||
<h5><a href="#sales-analytics" data-role="Analytics, Sales Manager,
|
<h5><a href="#sales-analytics" data-role="Analytics, Sales Manager,
|
||||||
Maintenance Manager">Sales Analytics</a>
|
Maintenance Manager">Sales Analytics</a>
|
||||||
</h5>
|
</h5>
|
||||||
<p class="help">Sales trends based on Sales Invoice</p>
|
<p class="help">Sales trends based on Sales Invoice</p>
|
||||||
</div>
|
</div>
|
||||||
<div style="clear: both"></div>
|
<div style="width: 48%; float: right;">
|
||||||
|
</div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>Reports</h3>
|
|
||||||
<div class="reports-list"></div>
|
<div class="reports-list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-side-section">
|
<div class="layout-side-section">
|
||||||
|
|||||||
@ -100,6 +100,50 @@ data_map = {
|
|||||||
"conditions": ["docstatus=1"],
|
"conditions": ["docstatus=1"],
|
||||||
"order_by": "posting_date, posting_time, name",
|
"order_by": "posting_date, posting_time, name",
|
||||||
},
|
},
|
||||||
|
"Production Order": {
|
||||||
|
"columns": ["production_item as item_code",
|
||||||
|
"(ifnull(qty, 0) - ifnull(produced_qty, 0)) as qty",
|
||||||
|
"fg_warehouse as warehouse"],
|
||||||
|
"conditions": ["docstatus=1", "status != 'Stopped'", "ifnull(fg_warehouse, '')!=''",
|
||||||
|
"ifnull(qty, 0) > ifnull(produced_qty, 0)"],
|
||||||
|
"links": {
|
||||||
|
"item_code": ["Item", "name"],
|
||||||
|
"warehouse": ["Warehouse", "name"]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Purchase Request Item": {
|
||||||
|
"columns": ["item_code", "warehouse",
|
||||||
|
"(ifnull(qty, 0) - ifnull(ordered_qty, 0)) as qty"],
|
||||||
|
"from": "`tabPurchase Request Item` item, `tabPurchase Request` main",
|
||||||
|
"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'",
|
||||||
|
"ifnull(warehouse, '')!=''", "ifnull(qty, 0) > ifnull(ordered_qty, 0)"],
|
||||||
|
"links": {
|
||||||
|
"item_code": ["Item", "name"],
|
||||||
|
"warehouse": ["Warehouse", "name"]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Purchase Order Item": {
|
||||||
|
"columns": ["item_code", "warehouse",
|
||||||
|
"(ifnull(qty, 0) - ifnull(received_qty, 0)) as qty"],
|
||||||
|
"from": "`tabPurchase Order Item` item, `tabPurchase Order` main",
|
||||||
|
"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'",
|
||||||
|
"ifnull(warehouse, '')!=''", "ifnull(qty, 0) > ifnull(received_qty, 0)"],
|
||||||
|
"links": {
|
||||||
|
"item_code": ["Item", "name"],
|
||||||
|
"warehouse": ["Warehouse", "name"]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Sales Order Item": {
|
||||||
|
"columns": ["item_code", "(ifnull(qty, 0) - ifnull(delivered_qty, 0)) as qty",
|
||||||
|
"reserved_warehouse as warehouse"],
|
||||||
|
"from": "`tabSales Order Item` item, `tabSales Order` main",
|
||||||
|
"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'",
|
||||||
|
"ifnull(reserved_warehouse, '')!=''", "ifnull(qty, 0) > ifnull(delivered_qty, 0)"],
|
||||||
|
"links": {
|
||||||
|
"item_code": ["Item", "name"],
|
||||||
|
"warehouse": ["Warehouse", "name"]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
# Sales
|
# Sales
|
||||||
"Customer": {
|
"Customer": {
|
||||||
|
|||||||
@ -131,6 +131,9 @@ class DocType(TransactionBase):
|
|||||||
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
import utilities
|
||||||
|
utilities.validate_status(self.doc.status, ["Draft", "submitted", "Cancelled"])
|
||||||
|
|
||||||
self.so_required()
|
self.so_required()
|
||||||
self.validate_fiscal_year()
|
self.validate_fiscal_year()
|
||||||
self.validate_proj_cust()
|
self.validate_proj_cust()
|
||||||
|
|||||||
@ -148,7 +148,13 @@ class DocType(TransactionBase):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
self.po_required()
|
self.po_required()
|
||||||
self.validate_fiscal_year()
|
self.validate_fiscal_year()
|
||||||
webnotes.conn.set(self.doc, 'status', 'Draft') # set status as "Draft"
|
|
||||||
|
if not self.doc.status:
|
||||||
|
self.doc.status = "Draft"
|
||||||
|
|
||||||
|
import utilities
|
||||||
|
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Cancelled"])
|
||||||
|
|
||||||
self.validate_accepted_rejected_qty()
|
self.validate_accepted_rejected_qty()
|
||||||
self.validate_inspection() # Validate Inspection
|
self.validate_inspection() # Validate Inspection
|
||||||
get_obj('Stock Ledger').validate_serial_no(self, 'purchase_receipt_details')
|
get_obj('Stock Ledger').validate_serial_no(self, 'purchase_receipt_details')
|
||||||
|
|||||||
@ -65,6 +65,10 @@ class DocType(TransactionBase):
|
|||||||
# validate
|
# validate
|
||||||
# ---------
|
# ---------
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
# import utilities
|
||||||
|
# utilities.validate_status(self.doc.status, ["In Store", "Delivered",
|
||||||
|
# "Not in Use", "Purchase Returned"])
|
||||||
|
|
||||||
self.validate_warranty_status()
|
self.validate_warranty_status()
|
||||||
self.validate_amc_status()
|
self.validate_amc_status()
|
||||||
self.validate_warehouse()
|
self.validate_warehouse()
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
|
|
||||||
from webnotes.utils import cstr, cint, flt, getdate, now
|
from webnotes.utils import cstr, cint, flt, getdate, now, comma_or
|
||||||
from webnotes.model import db_exists, delete_doc
|
from webnotes.model import db_exists, delete_doc
|
||||||
from webnotes.model.doc import Document, addchild
|
from webnotes.model.doc import Document, addchild
|
||||||
from webnotes.model.wrapper import getlist, copy_doclist
|
from webnotes.model.wrapper import getlist, copy_doclist
|
||||||
@ -35,6 +35,8 @@ class DocType(TransactionBase):
|
|||||||
self.fname = 'mtn_details'
|
self.fname = 'mtn_details'
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
self.validate_purpose()
|
||||||
|
|
||||||
self.validate_serial_nos()
|
self.validate_serial_nos()
|
||||||
pro_obj = self.doc.production_order and \
|
pro_obj = self.doc.production_order and \
|
||||||
get_obj('Production Order', self.doc.production_order) or None
|
get_obj('Production Order', self.doc.production_order) or None
|
||||||
@ -58,6 +60,13 @@ class DocType(TransactionBase):
|
|||||||
# update Production Order
|
# update Production Order
|
||||||
self.update_production_order(0)
|
self.update_production_order(0)
|
||||||
|
|
||||||
|
def validate_purpose(self):
|
||||||
|
valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer",
|
||||||
|
"Manufacture/Repack", "Subcontract", "Sales Return", "Purchase Return"]
|
||||||
|
if self.doc.purpose not in valid_purposes:
|
||||||
|
msgprint(_("Purpose must be one of ") + comma_or(valid_purposes),
|
||||||
|
raise_exception=True)
|
||||||
|
|
||||||
def validate_serial_nos(self):
|
def validate_serial_nos(self):
|
||||||
sl_obj = get_obj("Stock Ledger")
|
sl_obj = get_obj("Stock Ledger")
|
||||||
sl_obj.scrub_serial_nos(self)
|
sl_obj.scrub_serial_nos(self)
|
||||||
|
|||||||
@ -63,7 +63,7 @@ erpnext.StockAgeing = erpnext.StockGridReport.extend({
|
|||||||
{fieldtype:"Select", label: "Brand", link:"Brand",
|
{fieldtype:"Select", label: "Brand", link:"Brand",
|
||||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||||
return val == opts.default_value || item.brand == val;
|
return val == opts.default_value || item.brand == val;
|
||||||
}},
|
}, link_formatter: {filter_input: "brand"}},
|
||||||
{fieldtype:"Select", label: "Plot By",
|
{fieldtype:"Select", label: "Plot By",
|
||||||
options: ["Average Age", "Earliest", "Latest"]},
|
options: ["Average Age", "Earliest", "Latest"]},
|
||||||
{fieldtype:"Date", label: "To Date"},
|
{fieldtype:"Date", label: "To Date"},
|
||||||
|
|||||||
@ -63,7 +63,7 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({
|
|||||||
{fieldtype:"Select", label: "Brand", link:"Brand",
|
{fieldtype:"Select", label: "Brand", link:"Brand",
|
||||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||||
return val == opts.default_value || item.brand == val || item._show;
|
return val == opts.default_value || item.brand == val || item._show;
|
||||||
}},
|
}, link_formatter: {filter_input: "brand"}},
|
||||||
{fieldtype:"Select", label: "Warehouse", link:"Warehouse",
|
{fieldtype:"Select", label: "Warehouse", link:"Warehouse",
|
||||||
default_value: "Select Warehouse..."},
|
default_value: "Select Warehouse..."},
|
||||||
{fieldtype:"Date", label: "From Date"},
|
{fieldtype:"Date", label: "From Date"},
|
||||||
|
|||||||
@ -23,7 +23,11 @@
|
|||||||
<br>
|
<br>
|
||||||
<h5><a href="#List/Warehouse">Warehouse</a></h5>
|
<h5><a href="#List/Warehouse">Warehouse</a></h5>
|
||||||
<p class="help">Warehouse is where items are stored</p>
|
<p class="help">Warehouse is where items are stored</p>
|
||||||
<br>
|
</div>
|
||||||
|
<div style="clear: both"></div>
|
||||||
|
<hr>
|
||||||
|
<h4>Reports</h4>
|
||||||
|
<div style="width: 48%; float: left;">
|
||||||
<h5><a href="#stock-ledger" data-role="Analytics, Material Manager,
|
<h5><a href="#stock-ledger" data-role="Analytics, Material Manager,
|
||||||
Material User">Stock Ledger</a>
|
Material User">Stock Ledger</a>
|
||||||
</h5>
|
</h5>
|
||||||
@ -34,6 +38,12 @@
|
|||||||
</h5>
|
</h5>
|
||||||
<p class="help">Inflow, outflow and balance of stock</p>
|
<p class="help">Inflow, outflow and balance of stock</p>
|
||||||
<br>
|
<br>
|
||||||
|
<h5><a href="#stock-level" data-role="Analytics, Material Manager">
|
||||||
|
Stock Level</a>
|
||||||
|
</h5>
|
||||||
|
<p class="help">Available and estimated qty of stock, as of now</p>
|
||||||
|
</div>
|
||||||
|
<div style="width: 48%; float: right;">
|
||||||
<h5><a href="#stock-analytics" data-role="Analytics, Material Manager">
|
<h5><a href="#stock-analytics" data-role="Analytics, Material Manager">
|
||||||
Stock Analytics</a>
|
Stock Analytics</a>
|
||||||
</h5>
|
</h5>
|
||||||
@ -44,9 +54,8 @@
|
|||||||
</h5>
|
</h5>
|
||||||
<p class="help">Analysis of slow moving stock</p>
|
<p class="help">Analysis of slow moving stock</p>
|
||||||
</div>
|
</div>
|
||||||
<div style="clear: both"></div>
|
<div style="clear: both;"></div>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>Reports</h3>
|
|
||||||
<div class="reports-list"></div>
|
<div class="reports-list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-side-section">
|
<div class="layout-side-section">
|
||||||
|
|||||||
@ -86,7 +86,7 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
|||||||
{fieldtype:"Select", label: "Brand", link:"Brand",
|
{fieldtype:"Select", label: "Brand", link:"Brand",
|
||||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||||
return val == opts.default_value || item.brand == val || item._show;
|
return val == opts.default_value || item.brand == val || item._show;
|
||||||
}},
|
}, link_formatter: {filter_input: "brand"}},
|
||||||
{fieldtype:"Data", label: "Voucher No",
|
{fieldtype:"Data", label: "Voucher No",
|
||||||
filter: function(val, item, opts) {
|
filter: function(val, item, opts) {
|
||||||
if(!val) return true;
|
if(!val) return true;
|
||||||
|
|||||||
0
stock/page/stock_level/__init__.py
Normal file
0
stock/page/stock_level/__init__.py
Normal file
225
stock/page/stock_level/stock_level.js
Normal file
225
stock/page/stock_level/stock_level.js
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
wn.pages['stock-level'].onload = function(wrapper) {
|
||||||
|
wn.ui.make_app_page({
|
||||||
|
parent: wrapper,
|
||||||
|
title: 'Stock Level',
|
||||||
|
single_column: true
|
||||||
|
});
|
||||||
|
|
||||||
|
new erpnext.StockLevel(wrapper);
|
||||||
|
|
||||||
|
wrapper.appframe.add_home_breadcrumb()
|
||||||
|
wrapper.appframe.add_module_breadcrumb("Stock")
|
||||||
|
wrapper.appframe.add_breadcrumb("icon-bar-chart");
|
||||||
|
}
|
||||||
|
|
||||||
|
wn.require("app/js/stock_grid_report.js");
|
||||||
|
|
||||||
|
erpnext.StockLevel = erpnext.StockGridReport.extend({
|
||||||
|
init: function(wrapper) {
|
||||||
|
var me = this;
|
||||||
|
|
||||||
|
this._super({
|
||||||
|
title: "Stock Level",
|
||||||
|
page: wrapper,
|
||||||
|
parent: $(wrapper).find('.layout-main'),
|
||||||
|
appframe: wrapper.appframe,
|
||||||
|
doctypes: ["Item", "Warehouse", "Stock Ledger Entry", "Production Order",
|
||||||
|
"Purchase Request Item", "Purchase Order Item", "Sales Order Item", "Brand"],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.wrapper.bind("make", function() {
|
||||||
|
wn.utils.set_footnote(me, me.wrapper.get(0),
|
||||||
|
"<ul> \
|
||||||
|
<li style='font-weight: bold;'> \
|
||||||
|
Projected Qty = Actual Qty + Planned Qty + Requested Qty \
|
||||||
|
+ Ordered Qty - Reserved Qty </li> \
|
||||||
|
<ul> \
|
||||||
|
<li>Actual Qty: Quantity available in the warehouse. </li> \
|
||||||
|
<li>Planned Qty: Quantity, for which, Production Order has been raised, \
|
||||||
|
but is pending to be manufactured. </li> \
|
||||||
|
<li>Requested Qty: Quantity requested for purchase, but not ordered. </li> \
|
||||||
|
<li>Ordered Qty: Quantity ordered for purchase, but not received.</li> \
|
||||||
|
<li>Reserved Qty: Quantity ordered for sale, but not delivered. </li> \
|
||||||
|
</ul> \
|
||||||
|
</ul>");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setup_columns: function() {
|
||||||
|
this.columns = [
|
||||||
|
{id: "item_code", name: "Item Code", field: "item_code", width: 160,
|
||||||
|
link_formatter: {
|
||||||
|
filter_input: "item_code",
|
||||||
|
open_btn: true,
|
||||||
|
doctype: '"Item"',
|
||||||
|
}},
|
||||||
|
{id: "warehouse", name: "Warehouse", field: "warehouse", width: 100,
|
||||||
|
link_formatter: {filter_input: "warehouse"}},
|
||||||
|
{id: "actual_qty", name: "Actual Qty",
|
||||||
|
field: "actual_qty", width: 80, formatter: this.currency_formatter},
|
||||||
|
{id: "planned_qty", name: "Planned Qty",
|
||||||
|
field: "planned_qty", width: 80, formatter: this.currency_formatter},
|
||||||
|
{id: "requested_qty", name: "Requested Qty",
|
||||||
|
field: "requested_qty", width: 80, formatter: this.currency_formatter},
|
||||||
|
{id: "ordered_qty", name: "Ordered Qty",
|
||||||
|
field: "ordered_qty", width: 80, formatter: this.currency_formatter},
|
||||||
|
{id: "reserved_qty", name: "Reserved Qty",
|
||||||
|
field: "reserved_qty", width: 80, formatter: this.currency_formatter},
|
||||||
|
{id: "projected_qty", name: "Projected Qty",
|
||||||
|
field: "projected_qty", width: 80, formatter: this.currency_formatter},
|
||||||
|
{id: "uom", name: "UOM", field: "uom", width: 60},
|
||||||
|
{id: "item_name", name: "Item Name", field: "item_name", width: 100,
|
||||||
|
formatter: this.text_formatter},
|
||||||
|
{id: "brand", name: "Brand", field: "brand", width: 100,
|
||||||
|
link_formatter: {filter_input: "brand"}},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
filters: [
|
||||||
|
{fieldtype:"Select", label: "Item Code", link:"Item", default_value: "Select Item...",
|
||||||
|
filter: function(val, item, opts) {
|
||||||
|
return item.item_code == val || val == opts.default_value;
|
||||||
|
}},
|
||||||
|
|
||||||
|
{fieldtype:"Select", label: "Warehouse", link:"Warehouse",
|
||||||
|
default_value: "Select Warehouse...", filter: function(val, item, opts) {
|
||||||
|
return item.warehouse == val || val == opts.default_value;
|
||||||
|
}},
|
||||||
|
|
||||||
|
{fieldtype:"Select", label: "Brand", link:"Brand",
|
||||||
|
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||||
|
return val == opts.default_value || item.brand == val;
|
||||||
|
}},
|
||||||
|
{fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"},
|
||||||
|
{fieldtype:"Button", label: "Reset Filters"}
|
||||||
|
],
|
||||||
|
|
||||||
|
setup_filters: function() {
|
||||||
|
var me = this;
|
||||||
|
this._super();
|
||||||
|
|
||||||
|
this.wrapper.bind("apply_filters_from_route", function() { me.toggle_enable_brand(); });
|
||||||
|
this.filter_inputs.item_code.change(function() { me.toggle_enable_brand(); });
|
||||||
|
|
||||||
|
this.trigger_refresh_on_change(["item_code", "warehouse", "brand"]);
|
||||||
|
},
|
||||||
|
|
||||||
|
toggle_enable_brand: function() {
|
||||||
|
if(this.filter_inputs.item_code.val() ==
|
||||||
|
this.filter_inputs.item_code.get(0).opts.default_value) {
|
||||||
|
this.filter_inputs.brand.removeAttr("disabled");
|
||||||
|
} else {
|
||||||
|
this.filter_inputs.brand
|
||||||
|
.val(this.filter_inputs.brand.get(0).opts.default_value)
|
||||||
|
.attr("disabled", "disabled");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
init_filter_values: function() {
|
||||||
|
this._super();
|
||||||
|
this.filter_inputs.warehouse.get(0).selectedIndex = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
prepare_data: function() {
|
||||||
|
var me = this;
|
||||||
|
|
||||||
|
if(!this._data) {
|
||||||
|
this._data = [];
|
||||||
|
this.item_warehouse_map = [];
|
||||||
|
this.item_by_name = this.make_name_map(wn.report_dump.data["Item"]);
|
||||||
|
var sorted_item_list = Object.keys(this.item_by_name).sort();
|
||||||
|
$.each(sorted_item_list, function(i, item_code) {
|
||||||
|
var item = me.item_by_name[item_code];
|
||||||
|
$.each(wn.report_dump.data["Warehouse"], function(i, warehouse) {
|
||||||
|
// a list of item warehouse combination objects
|
||||||
|
var row = {
|
||||||
|
item_code: item_code,
|
||||||
|
warehouse: warehouse.name,
|
||||||
|
brand: item.brand,
|
||||||
|
item_name: item.item_name || item.name,
|
||||||
|
uom: item.stock_uom,
|
||||||
|
id: item_code + ":" + warehouse.name,
|
||||||
|
}
|
||||||
|
me.reset_item_values(row);
|
||||||
|
me._data.push(row);
|
||||||
|
me.item_warehouse_map[row.id] = row;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.calculate_quantities();
|
||||||
|
|
||||||
|
// filter out rows with zero values
|
||||||
|
this._data = $.map(this._data, function(d) {
|
||||||
|
return me.apply_zero_filter(null, d, null, me) ? d : null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.data = [].concat(this._data);
|
||||||
|
this.data = $.map(this.data, function(d) {
|
||||||
|
return me.apply_filters(d) ? d : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.calculate_total();
|
||||||
|
},
|
||||||
|
|
||||||
|
calculate_quantities: function() {
|
||||||
|
var me = this;
|
||||||
|
$.each([
|
||||||
|
["Stock Ledger Entry", "actual_qty"],
|
||||||
|
["Production Order", "planned_qty"],
|
||||||
|
["Purchase Request Item", "requested_qty"],
|
||||||
|
["Purchase Order Item", "ordered_qty"],
|
||||||
|
["Sales Order Item", "reserved_qty"]],
|
||||||
|
function(i, v) {
|
||||||
|
$.each(wn.report_dump.data[v[0]], function(i, item) {
|
||||||
|
var row = me.item_warehouse_map[item.item_code + ":" + item.warehouse];
|
||||||
|
row[v[1]] += flt(item.qty);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$.each(this._data, function(i, row) {
|
||||||
|
row.projected_qty = row.actual_qty + row.planned_qty + row.requested_qty
|
||||||
|
+ row.ordered_qty - row.reserved_qty;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
calculate_total: function() {
|
||||||
|
var me = this;
|
||||||
|
// show total if a specific item is selected and warehouse is not filtered
|
||||||
|
if(this.is_default("warehouse") && !this.is_default("item_code")) {
|
||||||
|
var total = {
|
||||||
|
id: "_total",
|
||||||
|
item_code: "Total",
|
||||||
|
_style: "font-weight: bold",
|
||||||
|
_show: true
|
||||||
|
};
|
||||||
|
this.reset_item_values(total);
|
||||||
|
|
||||||
|
$.each(this.data, function(i, row) {
|
||||||
|
$.each(me.columns, function(i, col) {
|
||||||
|
if (col.formatter==me.currency_formatter) {
|
||||||
|
total[col.id] += row[col.id];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.data = this.data.concat([total]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
21
stock/page/stock_level/stock_level.txt
Normal file
21
stock/page/stock_level/stock_level.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"owner": "Administrator",
|
||||||
|
"docstatus": 0,
|
||||||
|
"creation": "2012-12-28 11:02:23",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"modified": "2012-12-28 11:02:23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "__common__",
|
||||||
|
"title": "Stock Level",
|
||||||
|
"doctype": "Page",
|
||||||
|
"module": "Stock",
|
||||||
|
"standard": "Yes",
|
||||||
|
"page_name": "stock-level"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stock-level",
|
||||||
|
"doctype": "Page"
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -41,9 +41,8 @@ class DocType(TransactionBase):
|
|||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if session['user'] != 'Guest' and not self.doc.customer:
|
if session['user'] != 'Guest' and not self.doc.customer:
|
||||||
msgprint("Please select Customer from whom issue is raised")
|
msgprint("Please select Customer from whom issue is raised",
|
||||||
raise Exception
|
raise_exception=True)
|
||||||
|
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
lst = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t2.prevdoc_docname = '%s' and t1.docstatus!=2"%(self.doc.name))
|
lst = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t2.prevdoc_docname = '%s' and t1.docstatus!=2"%(self.doc.name))
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="clear: both"></div>
|
<div style="clear: both"></div>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>Reports</h3>
|
<h4>Reports</h4>
|
||||||
<div class="reports-list"></div>
|
<div class="reports-list"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-side-section">
|
<div class="layout-side-section">
|
||||||
|
|||||||
@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
from webnotes.utils import cint
|
from webnotes import _, msgprint
|
||||||
|
from webnotes.utils import cint, comma_or
|
||||||
|
|
||||||
@webnotes.whitelist()
|
@webnotes.whitelist()
|
||||||
def get_sc_list(arg=None):
|
def get_sc_list(arg=None):
|
||||||
@ -53,3 +54,7 @@ def get_report_list():
|
|||||||
order by tabReport.name
|
order by tabReport.name
|
||||||
limit %s, %s""" % \
|
limit %s, %s""" % \
|
||||||
("%s", cint(limit_start), cint(limit_page_length)), (module,), as_dict=True)
|
("%s", cint(limit_start), cint(limit_page_length)), (module,), as_dict=True)
|
||||||
|
|
||||||
|
def validate_status(status, options):
|
||||||
|
if status not in options:
|
||||||
|
msgprint(_("Status must be one of ") + comma_or(options), raise_exception=True)
|
||||||
|
|||||||
@ -102,4 +102,5 @@ def get_parent_item_groups(item_group_name):
|
|||||||
|
|
||||||
def invalidate_cache_for(item_group):
|
def invalidate_cache_for(item_group):
|
||||||
for i in get_parent_item_groups(item_group):
|
for i in get_parent_item_groups(item_group):
|
||||||
delete_page_cache(i.page_name)
|
if i.page_name:
|
||||||
|
delete_page_cache(i.page_name)
|
||||||
@ -263,7 +263,8 @@ def clear_cache(page_name=None):
|
|||||||
webnotes.cache().delete_keys("page:")
|
webnotes.cache().delete_keys("page:")
|
||||||
|
|
||||||
def delete_page_cache(page_name):
|
def delete_page_cache(page_name):
|
||||||
webnotes.cache().delete_value("page:" + page_name)
|
if page_name:
|
||||||
|
webnotes.cache().delete_value("page:" + page_name)
|
||||||
|
|
||||||
def url_for_website(url):
|
def url_for_website(url):
|
||||||
if url and not url.lower().startswith("http"):
|
if url and not url.lower().startswith("http"):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user