bzr revid: apa@tinyerp.com-20100323133440-o5g4jwd01u74esk5
This commit is contained in:
apa-tiny
2010-03-23 19:04:40 +05:30
116 changed files with 1378 additions and 941 deletions
+6 -2
View File
@@ -25,15 +25,19 @@
"version" : "1.1",
"depends" : ["product", "analytic", "process"],
"author" : "Tiny",
"category": 'Generic Modules/Accounting',
"description": """Financial and accounting module that covers:
General accounting
General accountings
Cost / Analytic accounting
Third party accounting
Taxes management
Budgets
Customer and Supplier Invoices
Bank statements
Account Balance Report
The processes like maintaining of general ledger is done through the defined financial Journals (entry move line or
grouping is maintained through journal) for a particular financial year and for preparation of vouchers there is a
module named account_voucherss
""",
'website': 'http://www.openerp.com',
'init_xml': [],
+1
View File
@@ -2182,6 +2182,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
#create all the tax code
children_tax_code_template = self.pool.get('account.tax.code.template').search(cr, uid, [('parent_id','child_of',[tax_code_root_id])], order='id')
children_tax_code_template.sort()
for tax_code_template in self.pool.get('account.tax.code.template').browse(cr, uid, children_tax_code_template):
vals={
'name': (tax_code_root_id == tax_code_template.id) and obj_multi.company_id.name or tax_code_template.name,
+10 -5
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -24,9 +24,14 @@
'name': 'report_account_analytic',
'version': '1.0',
'category': 'Generic Modules/Accounting',
'description': """Modify account analytic view to show
important data for project manager of services companies.
Add menu to show relevant information for each manager.""",
'description': """
This module is for modifying account analytic view to show
important data to project manager of services companies.
Adds menu to show relevant information to each manager..
You can also view the report of account analytic summary
user-wise as well as month wise.
""",
"version" : "1.1",
"author" : "Camptocamp",
"category" : "Generic Modules/Accounting",
+4 -2
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -51,6 +51,8 @@ Plan2:
So when this line of invoice will be confirmed, it will generate 3 analytic lines,
for one account entry.
The analytic plan validates the minimum and maximum percentage at the time of creation
of distribution models.
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
@@ -95,6 +95,18 @@ class account_analytic_plan_instance(osv.osv):
'account6_ids':one2many_mod2('account.analytic.plan.instance.line','plan_id','Account6 Id'),
'plan_id':fields.many2one('account.analytic.plan', "Model's Plan"),
}
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
if context.get('journal_id', False):
journal = self.pool.get('account.journal').browse(cr, user, [context['journal_id']], context=context)[0]
analytic_journal = journal.analytic_journal_id and journal.analytic_journal_id.id or False
args.append('|')
args.append(('journal_id', '=', analytic_journal))
args.append(('journal_id', '=', False))
res = super(account_analytic_plan_instance, self).search(cr, user, args, offset=offset, limit=limit, order=order,
context=context, count=count)
return res
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
@@ -24,7 +24,7 @@
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<field name="analytic_account_id" position="replace">
<field name="analytics_id" />
<field name="analytics_id" context="{'journal_id':journal_id}"/>
</field>
</field>
</record>
@@ -45,7 +45,7 @@
<field name="inherit_id" ref="account.view_move_line_form"/>
<field name="arch" type="xml">
<field name="move_id" position="after">
<field name="analytics_id" />
<field name="analytics_id" context="{'journal_id':journal_id}" />
</field>
</field>
</record>
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -38,7 +38,7 @@ class wizard_report(wizard.interface):
states = {
'init': {
'actions': [],
'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel'),('report','Print')]}
'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel', 'gtk-cancel'),('report','Print', 'gtk-print', True)]}
},
'report': {
'actions': [],
@@ -47,7 +47,7 @@ class wizard_report(wizard.interface):
states = {
'init': {
'actions': [_default],
'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel'),('report','Print')]}
'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel', 'gtk-cancel'),('report','Print', 'gtk-print', True)]}
},
'report': {
'actions': [],
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -43,7 +43,7 @@ class wizard_budget_spread(wizard.interface):
states = {
'init': {
'actions': [],
'result': {'type':'form', 'arch':_spread_form, 'fields':_spread_fields, 'state':[('end','Cancel'),('spread','Spread')]}
'result': {'type':'form', 'arch':_spread_form, 'fields':_spread_fields, 'state':[('end','Cancel'),('spread','Spread','',True)]}
},
'spread': {
'actions': [_spread],
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -43,7 +43,7 @@ class wizard_report(wizard.interface):
states = {
'init': {
'actions': [_default],
'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel'),('report','Print')]}
'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel', 'gtk-cancel'),('report','Print', 'gtk-print', True)]}
},
'report': {
'actions': [],
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -42,7 +42,7 @@ class wizard_report_summary(wizard.interface):
states = {
'init': {
'actions': [_default],
'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel'),('report','Print')]}
'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[('end','Cancel', 'gtk-cancel'),('report','Print', 'gtk-print', True)]}
},
'report': {
'actions': [],
+14 -9
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -24,20 +24,25 @@
"version" : "1.0",
"author" : 'Tiny & Axelor',
"description": """
India Accounting module includes all the basic requirenment of
Basic Accounting, like
* Bank Payment, Receipt
* Cash Payent, Receipt
India Accounting module includes all the basic requirenment of
Basic Accounting, plus new things which available are
* Indian Account Chart
* New Invoice - (Local, Retail)
* Invoice Report
* Tax structure
* Journals
* VAT Declaration report
* Accounting Periods
""",
"category" : "Generic Modules/Indian Accounting",
"category" : "Generic Modules/Accounting",
"website" : "http://tinyerp.com",
"depends" : ["base", "account"],
"init_xml" : [
],
"demo_xml" : [
],
"update_xml" : [
"security/ir.model.access.csv",
"voucher_sequence.xml",
+3 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -24,7 +24,7 @@
'name': 'Association profile',
'version': '0.1',
'category': 'Profile',
'description': """Profile for Associates""",
'description': """This module is to create Profile for Associates""",
'author': 'Tiny',
'depends': ['membership', 'board_association'],
'update_xml': ['security/ir.model.access.csv', 'profile_association.xml'],
+10 -6
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -24,10 +24,14 @@
'name': 'Auction Management',
'version': '1.0',
'category': 'Generic Modules/Auction',
'description': """This module provides functionality to
manage artists, articles, sellers, buyers and auction.
Manage bids, track of sold, paid and unpaid objects.
Delivery Management.
'description': """
This module manages the records of the artists,
the articles to be put up for auction,the buyers and
sellers.
It completely manages an auction such as managing bids,
keeping track of the sold articles along with the paid
and unpaid objects including delivery of the articles.
""",
'author': 'Tiny',
'depends': ['base', 'account', 'hr_attendance'],
+10 -4
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -24,8 +24,14 @@
'name': 'Audit Trail',
'version': '1.0',
'category': 'Generic Modules/Others',
'description': """Allows the administrator to track every user operations on all objects of the system.
Subscribe Rules for read, write, create and delete on objects and check logs""",
'description': """
This module gives the administrator the right
to track every user operation on all the objects
of the system.
Administrator can subscribe rules for read,write and
delete on objects and can check logs.
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
'depends': ['base'],
+17 -17
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,36 +15,36 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
{
"name" : "Basic Calendar Functionality",
"version" : "1.0",
"name" : "Basic Calendar Functionality",
"version" : "1.0",
"depends" : [
"base",
],
"base",
],
'description': """
Full featured calendar system that support:
- Alerts (create requests)
- Recurring events (*)
- Invitations to others people
""",
"author" : "Tiny",
'category': 'Generic Modules/Others',
'website': 'http://www.openerp.com',
- Invitations to other people
""",
"author" : "Tiny",
'category': 'Generic Modules/Others',
'website': 'http://www.openerp.com',
"init_xml" : [
'base_calendar_data.xml'
],
"demo_xml" : [],
],
"demo_xml" : [],
"update_xml" : [
'security/ir.model.access.csv',
'security/ir.model.access.csv',
'base_calendar_view.xml'
],
"installable" : True,
"active" : False,
],
"installable" : True,
"active" : False,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+3 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -25,7 +25,7 @@
'version': '1.0',
'category': 'Generic Modules/Base',
'description': """
This module install the base for IBAN bank accounts.
This module install the base for IBAN (International Bank Account Number) bank accounts and checks for its validity
""",
'author': 'Tiny',
+64 -74
View File
@@ -72,6 +72,40 @@ def doc_createXElement(xdoc, tagName):
e.ownerDocument = xdoc
return e
import yaml
class record(yaml.YAMLObject):
yaml_tag = u'!record'
def __init__(self, model, id=None, attrs={}):
self.model = model
self.id = id
self.attrs=attrs
def __repr__(self):
return '!record {model: %s, id: %s}:' % (str(self.model,), str(self.id,))
class workflow(yaml.YAMLObject):
yaml_tag = u'!workflow'
def __init__(self, model, action, ref=None):
self.model = model
self.ref = ref
self.action=action
def __repr__(self):
return '!workflow {model: %s, action: %s, ref: %s}' % (str(self.model,), str(self.action,), str(self.ref,))
class ref(yaml.YAMLObject):
yaml_tag = u'!ref'
def __init__(self, expr="False"):
self.expr = expr
def __repr__(self):
return 'ref(%s)' % (str(self.expr,))
class eval(yaml.YAMLObject):
yaml_tag = u'!eval'
def __init__(self, expr="False"):
self.expr = expr
def __repr__(self):
return 'eval(%s)' % (str(self.expr,))
class base_module_record(osv.osv):
_name = "ir.module.record"
_columns = {
@@ -105,7 +139,7 @@ class base_module_record(osv.osv):
dt = self.pool.get('ir.model.data')
dtids = dt.search(cr, uid, [('model','=',model), ('res_id','=',id)])
if not dtids:
return None, None
return False, None
obj = dt.browse(cr, uid, dtids[0])
self.depends[obj.module] = True
return obj.module+'.'+obj.name, obj.noupdate
@@ -379,6 +413,10 @@ class base_module_record(osv.osv):
data['action'] = rec[3]
data['ref'] = id
return data
if self.mode=="write":
id,update = self._get_id(cr, uid, rec[2],rec[4][0])
record = self._create_yaml_record(cr, uid, rec[2], rec[5], id)
return record
data=self.get_copy_data(cr,uid,rec[2],rec[4],rec[5])
copy_rec=(rec[0],rec[1],rec[2],rec[3],rec[4],data,rec[5])
rec=copy_rec
@@ -429,44 +467,13 @@ class base_module_record(osv.osv):
def generate_yaml(self, cr, uid):
self.ids = {}
if len(self.recording_data):
strg='''import yaml
class record(yaml.YAMLObject):
yaml_tag = u'!record'
def __init__(self, model, id=None, attrs={}):
self.model = model
self.id = id
self.attrs=attrs
def __repr__(self):
return '!record {model: %s, id: %s}:' % (str(self.model,), str(self.id,))
class workflow(yaml.YAMLObject):
yaml_tag = u'!workflow'
def __init__(self, model, action, ref=None):
self.model = model
self.ref = ref
self.action=action
def __repr__(self):
return '!workflow {model: %s, action: %s, ref: %s}' % (str(self.model,), str(self.action,), str(self.ref,))
class ref(yaml.YAMLObject):
yaml_tag = u'!ref'
def __init__(self, expr="False"):
self.expr = expr
def __repr__(self):
return 'ref(%s)' % (str(self.expr,))
class eval(yaml.YAMLObject):
yaml_tag = u'!eval'
def __init__(self, expr="False"):
self.expr = expr
def __repr__(self):
return 'eval(%s)' % (str(self.expr,))
\n'''
yaml_file='''\n'''
for rec in self.recording_data:
if rec[1][3] == 'create':
self.mode="create"
elif rec[1][3] == 'write':
self.mode="write"
elif rec[1][3] == 'copy':
self.mode="copy"
elif rec[0] == 'workflow':
@@ -475,47 +482,30 @@ class eval(yaml.YAMLObject):
continue
if self.mode == "workflow":
record= self._generate_object_yaml(cr, uid, rec[1],rec[0])
strg+="object=yaml.load(unicode('''\n !workflow %s \n''','iso-8859-1'))"%record
strg+='''
print object
'''
object=yaml.load(unicode('''\n !workflow %s \n'''%record,'iso-8859-1'))
yaml_file += str(object) + '''\n'''
else:
record= self._generate_object_yaml(cr, uid, rec[1],rec[3])
strg+="object=yaml.load(unicode('''\n !record %s \n''','iso-8859-1'))"%record
strg+='''
print object
attrs=yaml.dump(object.attrs, default_flow_style=False)
print attrs \n\n'''
import os
py_path = os.path.join(os.getcwd(), 'records.py')
txt_path = os.path.join(os.getcwd(), 'records.txt')
f = open(py_path, 'w')
f.write(strg)
f.close()
os.system('python %s > %s'%(py_path,txt_path))
f = open(txt_path, 'r+')
lines=f.readlines()
f.seek(0)
for line in lines:
line=line.replace("''","'")
if line.find('!record') == 0:
line = "- \n" + " " + line
elif line.find('!workflow') == 0:
line = "- \n" + " " + line
elif line.find('- -') != -1:
line=line.replace('- -',' -')
line = " " + line
else:
line = " " + line
f.write(line)
f.close()
f = open(txt_path, 'r')
strg = ''.join(f.readlines())
f.close()
os.system('rm %s'%py_path)
os.system('rm %s'%txt_path)
return strg
object= yaml.load(unicode('''\n !record %s \n'''%record,'iso-8859-1'))
yaml_file += str(object) + '''\n'''
attrs=yaml.dump(object.attrs, default_flow_style=False)
yaml_file += attrs + '''\n\n'''
yaml_result=''''''
for line in yaml_file.split('\n'):
line=line.replace("''","'")
if line.find('!record') == 0:
line = "- \n" + " " + line
elif line.find('!workflow') == 0:
line = "- \n" + " " + line
elif line.find('- -') != -1:
line=line.replace('- -',' -')
line = " " + line
else:
line = " " + line
yaml_result += line + '''\n'''
return yaml_result
base_module_record()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+9 -4
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -25,8 +25,13 @@
'version': '0.1',
'category': 'Generic Modules/Base',
'description': """
This module adds wizards to import/export documents to be edited in
OpenOffice.
This module is used along with openerp OpenOffice plugin.
You have to first install the plugin which is available at
http://www.openerp.com
This module adds wizards to import/export .SXW report that
you can modify in OpenOffice.Once you have modified it you can
upload the report using the same wizard.
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
+8 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -24,7 +24,12 @@
'name': 'Base VAT - To check VAT number validity',
'version': '1.0',
'category': 'Generic Modules/Base',
'description': """Enable the VAT Number for the partner. Check the validity of that VAT Number.""",
'description': """
Enable the VAT Number for the partner. Check the validity of that VAT Number.
This module follows the methods stated at http://sima-pc.com/nif.php for
checking the validity of VAT Number assinged to partners in European countries.
""",
'author': 'Tiny',
'depends': ['base', 'account'],
'update_xml': ['base_vat_data.xml'],
+8 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -25,7 +25,12 @@
'version': '1.0',
'category': 'Board/Associations',
'description': """
This module implements a dashboard for associations.
This module implements a dashboard for associations that includes:
* New Members (graph)
* Registration by Events (graph)
* Next Events (list)
* My Tasks (list)
* Unpaid Invoices (list)
""",
'author': 'Tiny',
'depends': ['event', 'membership', 'board', 'project'],
+6 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -26,7 +26,10 @@
'category': 'Board/Auction',
'description': """
This module creates a dashboards for auction that includes:
* My Latest Objects (list)
* My Latest Deposits (list)
* Objects Statistics (list)
* My Objects By Day (list)
""",
'author': 'Tiny',
'depends': ['board', 'auction'],
+7 -1
View File
@@ -24,7 +24,13 @@
'name': 'Dashboard for Document Management',
'version': '1.0',
'category': 'Board/Document',
'description': """ This module implements a dashboard for Document """,
'description': """
This module implements a dashboard for Document that includes:
* New Files (list)
* Files by Resource Type (graph)
* Files by Partner (graph)
* Files by Month (graph)
""",
'author': 'Tiny',
'depends': ['board', 'document'],
'update_xml': ['board_document_view.xml'],
+1 -1
View File
@@ -23,7 +23,7 @@
{
'name': 'Board for Human Reasources Management',
'version': '1.0',
'category': '',
'category': 'Board/Human Resources',
'description': """
This module implements a dashboard for human resource management that includes:
* My Current Timesheet
+6 -5
View File
@@ -1,6 +1,6 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@@ -23,8 +23,9 @@
"name": "Decimal Precision Configuration",
"description": """
This module allows to configure the price accuracy you need for different kind
of usage: accounting, sales, purchases, ... The decimal precision is configured
per company.
of usage: accounting, sales, purchases, ...
The decimal precision is configured per company.
""",
"author": "Tiny",
"version": "0.1",
@@ -32,8 +33,8 @@ per company.
"category" : "Generic Modules/Others",
"init_xml": [],
"update_xml": [
'decimal_precision_view.xml',
'security/ir.model.access.csv',
'decimal_precision_view.xml',
'security/ir.model.access.csv',
],
"demo_xml": [],
"installable": True,
+5 -1
View File
@@ -24,7 +24,11 @@
'name': 'Carriers and deliveries',
'version': '1.0',
'category': 'Generic Modules/Sales & Purchases',
'description': """Allows you to add delivery methods in sales orders and picking. You can define your own carrier and delivery grids for prices. When creating invoices from picking, Open ERP is able to add and compute the shipping line.""",
'description': """Allows you to add delivery methods in sales orders and picking.
You can define your own carrier and delivery grids for prices.
When creating invoices from picking, Open ERP is able to add and compute the shipping line.
""",
'author': 'Tiny',
'depends': ['sale', 'purchase', 'stock'],
'init_xml': ['delivery_data.xml'],
+6 -4
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -24,7 +24,9 @@
'name': 'Integrated FTP Server with Document Management System',
'version': '1.99',
'category': 'Generic Modules/Others',
'description': """This is a support FTP Interface with document management system:
'description': """This is a support FTP Interface with document management system.
With this module you would not only be able to access documents through open erp
also you would be able to connect with them through the file system using the FTP protocol.
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
@@ -32,7 +34,7 @@
'init_xml': [],
'update_xml': [
'document_ftp_view.xml',
'security/ir.model.access.csv'
'security/ir.model.access.csv'
],
'demo_xml': [],
'installable': True,
+3 -2
View File
@@ -34,8 +34,9 @@
"author" : "Tiny",
"category" : "Generic Modules/Others",
"website": "http://www.openerp.com",
"description": """ With this module, the WebDAV server for the documents is activated. You can then use any compatible browser to remotely see the attachments of OpenObject.
"description": """ With this module, the WebDAV server for the documents is activated.
You can then use any compatible browser to remotely see the attachments of OpenObject.
After installation, the webDAV server can be controlled by a [webdav] section in the server's config.
""",
"depends" : ["base", "document"],
+5 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -45,7 +45,9 @@
'event_view.xml',
'event_sequence.xml',
'security/event_security.xml',
'security/ir.model.access.csv'
'security/ir.model.access.csv',
'wizard/event_registration_view.xml',
'wizard/event_registrations_partner.xml',
],
'demo_xml': ['event_demo.xml'],
'installable': True,
+5 -5
View File
@@ -2,17 +2,17 @@
<openerp>
<data>
<wizard
<!-- <wizard
string="Registrations"
model="event.event"
name="wizard_event_registration"
id="wizard_event_registration"/>
id="wizard_event_registration"/> -->
<wizard
<!-- <wizard
string="List Register Partners"
model="event.event"
name="event.event_reg_partners"
id="wizard_event_reg_partners"/>
id="wizard_event_reg_partners"/> -->
<wizard string="Make Invoice"
model="event.registration"
@@ -21,7 +21,7 @@
menu="True"
/>
<wizard string="Confirm Registration"
<wizard string="Confirm Registration"
model="event.registration"
name="event.confirm_registration"
id="event_confirm_registration"
+4 -5
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,13 +15,12 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
import event_registration
import make_invoice
import event_registrations_partner
import confirm_registration
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+20 -31
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,40 +15,29 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
import wizard
import pooler
from osv import fields, osv
def _event_registration(self, cr, uid, data, context):
event_id = data['id']
cr.execute('SELECT section_id FROM event_event WHERE id = %s', (event_id, ))
res = cr.fetchone()
value = {
'domain': [('section_id', '=', res[0])],
'name': 'Event registration',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'event.registration',
'context': { },
'type': 'ir.actions.act_window'
}
return value
class event_registration_list(osv.osv_memory):
""" List Event Registration """
_name = "event.registration.list"
_description = "List Event Registrations"
class wizard_event_registration(wizard.interface):
states = {
'init': {
'actions': [],
'result': {
'type': 'action',
'action': _event_registration,
'state': 'end'
}
},
}
wizard_event_registration("wizard_event_registration")
def open_registration(self, cr, uid, ids, context={}):
cr.execute('SELECT section_id FROM event_event WHERE id = %s', (context['active_id'],))
res = cr.fetchone()
return {
'domain': [('section_id', '=', res[0])],
'name': 'Event Registrations',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'event.registration',
'type': 'ir.actions.act_window'
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
event_registration_list()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_event_registration" model="ir.ui.view">
<field name="name">List Event Registrations</field>
<field name="model">event.registration.list</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="">
<button special="cancel" string="Cancel" icon="gtk-cancel"/>
<button name="open_registration" string="Open Registrations" type="object" icon="gtk-open"/>
</form>
</field>
</record>
<record id="action_event_registration" model="ir.actions.act_window">
<field name="name">Registrations</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">event.registration.list</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_event_registration"/>
<field name="context">{'record_id' : active_id}</field>
<field name="target">new</field>
</record>
<record model="ir.values" id="event_registration_values">
<field name="model_id" ref="event.model_event_event" />
<field name="object" eval="1" />
<field name="name">Event Registrations</field>
<field name="key2">client_action_multi</field>
<field name="value" eval="'ir.actions.act_window,' + str(ref('action_event_registration'))" />
<field name="key">action</field>
<field name="model">event.event</field>
</record>
</data>
</openerp>
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,57 +15,41 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
import wizard
import pooler
from osv import fields, osv
from tools.translate import _
def _list_partners(self, cr, uid, data, context):
class event_partners_list(osv.osv_memory):
""" Event Partners """
_name = "event.partners.list"
_description = "List Event Partners"
def list_partners(self, cr, uid, ids, context={}):
obj_reg = self.pool.get('event.registration')
mod_obj = self.pool.get('ir.model.data')
list_partner = []
pool_obj=pooler.get_pool(cr.dbname)
obj_reg=pool_obj.get('event.registration')
reg_ids = obj_reg.search(cr, uid, [('event_id','in',data['ids'])])
data_reg = obj_reg.browse(cr, uid, reg_ids)
reg_ids = obj_reg.search(cr, uid, [('event_id','in',context['active_ids'])], context=context)
data_reg = obj_reg.browse(cr, uid, reg_ids, context=context)
for reg in data_reg:
if not reg.partner_id.id in list_partner:
list_partner.append(reg.partner_id.id)
data['partner_ids'] = list_partner
return {}
class event_partners(wizard.interface):
def _reg_partners(self, cr, uid, data, context):
pool_obj = pooler.get_pool(cr.dbname)
mod_obj = pool_obj.get('ir.model.data')
result = mod_obj._get_id(cr, uid, 'base', 'view_res_partner_filter')
id = mod_obj.read(cr, uid, result, ['res_id'])
model_data_ids = pool_obj.get('ir.model.data').search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_partner_form')])
resource_id = pool_obj.get('ir.model.data').read(cr,uid,model_data_ids,fields=['res_id'])[0]['res_id']
id = mod_obj.read(cr, uid, result, ['res_id'], context=context)
model_data_ids = mod_obj.search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_partner_form')], context=context)
resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
return {
'domain': "[('id','in', ["+','.join(map(str,data['partner_ids']))+"])]",
'name': 'Partners',
'domain': "[('id','in', ["+','.join(map(str, list_partner))+"])]",
'name': _('Event Partners'),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'res.partner',
'views': [(False,'tree'),(resource_id,'form')],
'type': 'ir.actions.act_window',
'search_view_id': id['res_id']
'search_view_id': id['res_id']
}
return {}
states = {
'init' : {
'actions' : [_list_partners],
'result': {'type': 'action' , 'action':_reg_partners, 'state':'end'}
},
}
event_partners("event.event_reg_partners")
event_partners_list()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_event_partners" model="ir.ui.view">
<field name="name">Event Partners</field>
<field name="model">event.partners.list</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Event Partners">
<button special="cancel" string="Cancel" icon="gtk-cancel"/>
<button name="list_partners" string="Open Partners" type="object" icon="gtk-open"/>
</form>
</field>
</record>
<record id="action_event_partners" model="ir.actions.act_window">
<field name="name">List Register Partners</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">event.partners.list</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_event_partners"/>
<field name="context">{'record_id' : active_id}</field>
<field name="target">new</field>
</record>
<record model="ir.values" id="event_partner_values">
<field name="model_id" ref="event.model_event_event" />
<field name="object" eval="1" />
<field name="name">Event Partners</field>
<field name="key2">client_action_multi</field>
<field name="value" eval="'ir.actions.act_window,' + str(ref('action_event_partners'))"/>
<field name="key">action</field>
<field name="model">event.event</field>
</record>
</data>
</openerp>
+8 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -24,7 +24,12 @@
'name': 'Attendances Of Employees',
'version': '1.1',
'category': 'Generic Modules/Human Resources',
'description': """This module aims to manage employee's attendances.""",
'description': """
This module aims to manage employee's attendances.
Keeps account of the attendances of the employees on the basis of the
actions(Sign in/Sign out) performed by them.
""",
'author': 'Tiny',
'depends': ['base', 'hr'],
'update_xml': [
+1 -1
View File
@@ -20,8 +20,8 @@
##############################################################################
import hr_evaluation
import wizard
import report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+10 -1
View File
@@ -26,12 +26,21 @@
"category" : "Generic Modules/Human Resources",
"website" : "http://www.openerp.com",
"depends" : ["hr",'hr_recruitment','survey'],
"description": "Ability to create employees evaluation.",
"description": """
Ability to create employees evaluation.
An evaluation can be created by employee for subordinates
juniors as well as his manager.The evaluation is done under a plan
in which various surveys can be created and it can be defined which
level of employee hierarchy fills what and final review and evaluation
is done by the manager.Every evaluation filled by the employees can be viewed
in the form of """,
"init_xml" : [],
"demo_xml" : ["hr_evaluation_demo.xml"],
"update_xml" : [
"security/ir.model.access.csv",
"wizard/hr_evaluation_mail_view.xml",
"hr_evaluation_view.xml",
"hr_evaluation_demo.xml",
"report/hr_evaluation_report_view.xml"],
"active": False,
"installable": True
+120 -46
View File
@@ -20,8 +20,9 @@
##############################################################################
import time
from osv import fields, osv
from mx import DateTime as dt
from osv import fields, osv
import tools
from tools.translate import _
@@ -31,7 +32,7 @@ class hr_evaluation_plan(osv.osv):
_columns = {
'name': fields.char("Evaluation Plan", size=64, required=True),
'company_id': fields.many2one('res.company', 'Company', required=True),
'phase_ids' : fields.one2many('hr_evaluation.plan.phase', 'plan_id', 'Evaluation Phases'),
'phase_ids': fields.one2many('hr_evaluation.plan.phase', 'plan_id', 'Evaluation Phases'),
'month_first': fields.integer('First Evaluation After'),
'month_next': fields.integer('Next Evaluation After'),
'active': fields.boolean('Active')
@@ -66,31 +67,74 @@ class hr_evaluation_plan_phase(osv.osv):
help="Send an anonymous summary to the employee"),
'wait': fields.boolean('Wait Previous Phases',
help="Check this box if you want to wait that all preceeding phases " +
"are finished before launching this phase.")
"are finished before launching this phase."),
'mail_feature': fields.boolean('Send mail for this phase',help="Check this box if you want to send mail to employees"+
"coming under this phase"),
'mail_body': fields.text('Email'),
'email_subject':fields.text('char')
}
_defaults = {
'sequence' : lambda *a: 1,
'email_subject':_('''Regarding '''),
'mail_body' : lambda *a:_('''
Date : %(date)s
Dear %(employee_name)s,
I am doing an evaluation regarding %(eval_name)s.
Kindly submit your response.
Thanks,
--
%(user_signature)s
'''),
}
hr_evaluation_plan_phase()
class hr_employee(osv.osv):
_name = "hr.employee"
_inherit="hr.employee"
_columns = {
'evaluation_plan_id': fields.many2one('hr_evaluation.plan', 'Evaluation Plan'),
'evaluation_date': fields.date('Next Evaluation', help="Date of the next evaluation"),
}
def onchange_evaluation_plan_id(self,cr,uid,ids,evaluation_plan_id,context={}):
evaluation_date = self.browse(cr, uid, ids)[0].evaluation_date or ''
def run_employee_evaluation(self, cr, uid, automatic=False, use_new_cursor=False, context=None):
for id in self.browse(cr, uid, self.search(cr, uid, [],context=context),context=context):
if id.evaluation_plan_id and id.evaluation_date:
if (dt.ISO.ParseAny(id.evaluation_date) + dt.RelativeDateTime(months = int(id.evaluation_plan_id.month_next))).strftime('%Y-%m-%d') <= time.strftime("%Y-%m-%d"):
self.write(cr, uid, id.id, {'evaluation_date' : (dt.ISO.ParseAny(id.evaluation_date) + dt.RelativeDateTime(months =+ int(id.evaluation_plan_id.month_next))).strftime('%Y-%m-%d')},context=context)
self.pool.get("hr_evaluation.evaluation").create(cr, uid, {'employee_id' : id.id, 'plan_id': id.evaluation_plan_id},context)
return True
def onchange_evaluation_plan_id(self, cr, uid, ids, evaluation_plan_id, evaluation_date, context={}):
evaluation_date = evaluation_date or False
evaluation_plan_obj=self.pool.get('hr_evaluation.plan')
if evaluation_plan_id:
for evaluation_plan in evaluation_plan_obj.browse(cr,uid,[evaluation_plan_id]):
if not evaluation_date:
evaluation_date=(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d'))+ dt.RelativeDateTime(months=+evaluation_plan.month_first)).strftime('%Y-%m-%d')
else:
evaluation_date=(dt.ISO.ParseAny(evaluation_date)+ dt.RelativeDateTime(months=+evaluation_plan.month_next)).strftime('%Y-%m-%d')
flag = False
evaluation_plan = evaluation_plan_obj.browse(cr, uid, [evaluation_plan_id],context=context)[0]
if not evaluation_date:
evaluation_date=(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d'))+ dt.RelativeDateTime(months=+evaluation_plan.month_first)).strftime('%Y-%m-%d')
flag = True
else:
if (dt.ISO.ParseAny(evaluation_date) + dt.RelativeDateTime(months = int(evaluation_plan.month_next))).strftime('%Y-%m-%d') <= time.strftime("%Y-%m-%d"):
evaluation_date=(dt.ISO.ParseAny(evaluation_date)+ dt.RelativeDateTime(months=+evaluation_plan.month_next)).strftime('%Y-%m-%d')
flag = True
if ids and flag:
self.pool.get("hr_evaluation.evaluation").create(cr, uid, {'employee_id' : ids[0], 'plan_id': evaluation_plan_id},context=context)
return {'value': {'evaluation_date':evaluation_date}}
def create(self, cr, uid, vals, context={}):
id = super(hr_employee, self).create(cr, uid, vals, context=context)
if vals.get('evaluation_plan_id', False):
self.pool.get("hr_evaluation.evaluation").create(cr, uid, {'employee_id' : id, 'plan_id': vals['evaluation_plan_id']},context=context)
return id
hr_employee()
class hr_evaluation(osv.osv):
@@ -132,18 +176,20 @@ class hr_evaluation(osv.osv):
employee_obj=self.pool.get('hr.employee')
evaluation_plan_id=''
if employee_id:
for employee in employee_obj.browse(cr,uid,[employee_id]):
for employee in employee_obj.browse(cr,uid,[employee_id],context=context):
if employee and employee.evaluation_plan_id and employee.evaluation_plan_id.id:
evaluation_plan_id=employee.evaluation_plan_id.id
employee_ids=employee_obj.search(cr,uid,[('parent_id','=',employee.id)])
employee_ids=employee_obj.search(cr,uid,[('parent_id','=',employee.id)],context=context)
return {'value': {'plan_id':evaluation_plan_id}}
def button_plan_in_progress(self,cr, uid, ids, context):
def button_plan_in_progress(self,cr, uid, ids, context={}):
user_obj = self.pool.get('res.users')
employee_obj = self.pool.get('hr.employee')
hr_eval_inter_obj = self.pool.get('hr.evaluation.interview')
survey_request_obj = self.pool.get('survey.request')
curr_employee=self.browse(cr,uid, ids)[0].employee_id
child_employees=employee_obj.browse(cr,uid, employee_obj.search(cr,uid,[('parent_id','=',curr_employee.id)]))
hr_eval_plan_obj = self.pool.get('hr_evaluation.plan.phase')
curr_employee=self.browse(cr,uid, ids, context=context)[0].employee_id
child_employees=employee_obj.browse(cr,uid, employee_obj.search(cr,uid,[('parent_id','=',curr_employee.id)],context=context))
manager_employee=curr_employee.parent_id
for evaluation in self.browse(cr,uid,ids):
if evaluation and evaluation.plan_id:
@@ -151,57 +197,82 @@ class hr_evaluation(osv.osv):
for phase in evaluation.plan_id.phase_ids:
if phase.action == "bottom-up":
for child in child_employees:
user = False
if child.user_id:
user = child.user_id.id
id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id ,'user_id' : user,'survey_id' : phase.survey_id.id, 'user_to_review_id' : child.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')})
id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id ,'user_id' : user,'survey_id' : phase.survey_id.id, 'user_to_review_id' : child.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')},context=context)
if not phase.wait:
hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context)
hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context=context)
if phase.mail_feature:
src = tools.config.options['email_from']
user_obj_id = user_obj.browse(cr,uid,uid)
val = {
'employee_name':child.name,
'user_signature':curr_employee.name,
# 'company_name':user_obj_id.company_id.name,
'eval_name':phase.survey_id.title,
'date':time.strftime('%Y-%m-%d'),
}
mailbody = hr_eval_plan_obj.read(cr,uid,phase.id,['mail_body','email_subject'],context=context)
body = mailbody['mail_body']%val
sub = mailbody['email_subject']+phase.survey_id.title
dest=[child.work_email]
if dest:
tools.email_send(src,dest,sub,body)
apprai_id.append(id)
elif phase.action == "top-down":
if manager_employee:
user = False
if manager_employee.user_id:
user = manager_employee.user_id.id
id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id,'user_id': user ,'survey_id' : phase.survey_id.id, 'user_to_review_id' :manager_employee.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')})
id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id,'user_id': user ,'survey_id' : phase.survey_id.id, 'user_to_review_id' :manager_employee.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')},context=context)
if not phase.wait:
hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context)
hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context=context)
if phase.mail_feature:
val.update({'employee_name':manager_employee.name})
mailbody = hr_eval_plan_obj.read(cr,uid,phase.id,['mail_body'],context=context)
body = mailbody['mail_body']%val
dest = [manager_employee.work_email]
if dest:
tools.email_send(src,dest,sub,body)
apprai_id.append(id)
elif phase.action == "self":
if curr_employee:
user = False
if curr_employee.user_id:
user = curr_employee.user_id.id
id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id,'user_id' : user, 'survey_id' : phase.survey_id.id, 'user_to_review_id' :curr_employee.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')})
id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id,'user_id' : user, 'survey_id' : phase.survey_id.id, 'user_to_review_id' :curr_employee.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')},context=context)
if not phase.wait:
hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context)
hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context=context)
apprai_id.append(id)
elif phase.action == "final":
if manager_employee:
user = False
if manager_employee.user_id:
user = manager_employee.user_id.id
id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id,'user_id' : user, 'survey_id' : phase.survey_id.id, 'user_to_review_id' :manager_employee.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')})
id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id,'user_id' : user, 'survey_id' : phase.survey_id.id, 'user_to_review_id' :manager_employee.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')},context=context)
if not phase.wait:
hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context)
hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context=context)
apprai_id.append(id)
self.write(cr, uid, evaluation.id, {'survey_request_ids':[[6, 0, apprai_id]]})
self.write(cr,uid,ids,{'state':'wait'})
self.write(cr,uid,ids,{'state':'wait'},context=context)
return True
def button_final_validation(self,cr, uid, ids, context):
def button_final_validation(self,cr, uid, ids, context={}):
self.write(cr,uid,ids,{'state':'progress'})
request_obj = self.pool.get('hr.evaluation.interview')
for id in self.browse(cr, uid ,ids):
if len(id.survey_request_ids) != len(request_obj.search(cr, uid, [('evaluation_id', '=', id.id),('state', '=', 'done')])):
for id in self.browse(cr, uid ,ids,context=context):
if len(id.survey_request_ids) != len(request_obj.search(cr, uid, [('evaluation_id', '=', id.id),('state', '=', 'done')],context=context)):
raise osv.except_osv(_('Warning !'),_("You cannot change state, because some appraisal in waiting answer or draft state"))
return True
def button_done(self,cr, uid, ids, context):
self.write(cr,uid,ids,{'state':'done', 'date_close': time.strftime('%Y-%m-%d')})
def button_done(self,cr, uid, ids, context={}):
self.write(cr,uid,ids,{'state':'done', 'date_close': time.strftime('%Y-%m-%d')}, context=context)
return True
def button_cancel(self,cr, uid, ids, context):
self.write(cr,uid,ids,{'state':'cancel'})
def button_cancel(self,cr, uid, ids, context={}):
self.write(cr,uid,ids,{'state':'cancel'}, context=context)
return True
hr_evaluation()
@@ -211,6 +282,7 @@ class survey_request(osv.osv):
_columns = {
'is_evaluation':fields.boolean('Is Evaluation?'),
}
survey_request()
class hr_evaluation_interview(osv.osv):
@@ -218,7 +290,6 @@ class hr_evaluation_interview(osv.osv):
_inherits={'survey.request':'request_id'}
_description='Evaluation Interview'
_columns = {
'request_id': fields.many2one('survey.request','Request_id', ondelete='cascade'),
'user_to_review_id': fields.many2one('hr.employee', 'Employee'),
'evaluation_id' : fields.many2one('hr_evaluation.evaluation', 'Evaluation'),
@@ -227,23 +298,24 @@ class hr_evaluation_interview(osv.osv):
'is_evaluation': lambda *a: True,
}
def survey_req_waiting_answer(self, cr, uid, ids, context):
def survey_req_waiting_answer(self, cr, uid, ids, context={}):
self.write(cr, uid, ids, { 'state' : 'waiting_answer'})
# for id in self.browse(cr, uid, ids):
# if id.user_id and id.user_id.address_id and id.user_id.address_id and id.user_id.address_id.email:
# msg = " Hello %s, \n\n We are inviting you for %s survey. \n\n Thanks," %(id.user_id.name, id.survey_id.title)
# tools.email_send(tools.config['email_from'], [id.user_id.address_id.email],\
# print"id",id
# if id.user_to_review_id and id.user_to_review_id.work_email:
# msg = " Hello %s, \n\n We are inviting you for %s survey. \n\n Thanks," %(id.user_to_review_id.name, id.survey_id.title)
# tools.email_send(tools.config['email_from'], [id.user_to_review_id.work_email],\
# 'Invite to fill up Survey', msg)
return True
def survey_req_done(self, cr, uid, ids, context):
def survey_req_done(self, cr, uid, ids, context={}):
self.write(cr, uid, ids, { 'state' : 'done'})
hr_eval_obj = self.pool.get('hr_evaluation.evaluation')
for id in self.browse(cr, uid, ids):
for id in self.browse(cr, uid, ids,context=context):
flag = False
wating_id = 0
tot_done_req = 0
records = self.pool.get("hr_evaluation.evaluation").browse(cr, uid, [id.evaluation_id.id])[0].survey_request_ids
records = self.pool.get("hr_evaluation.evaluation").browse(cr, uid, [id.evaluation_id.id],context=context)[0].survey_request_ids
for child in records:
if child.state == "draft" :
wating_id = child.id
@@ -254,15 +326,17 @@ class hr_evaluation_interview(osv.osv):
tot_done_req += 1
if not flag and wating_id:
self.survey_req_waiting_answer(cr, uid, [wating_id], context)
hr_eval_obj.write(cr, uid, [id.evaluation_id.id], {'progress' :tot_done_req * 100 / len(records)})
hr_eval_obj.write(cr, uid, [id.evaluation_id.id], {'progress' :tot_done_req * 100 / len(records)}, context=context)
return True
def survey_req_draft(self, cr, uid, ids, arg):
self.write(cr, uid, ids, { 'state' : 'draft'})
def survey_req_draft(self, cr, uid, ids, context={}):
self.write(cr, uid, ids, { 'state' : 'draft'}, context=context)
return True
def survey_req_cancel(self, cr, uid, ids, context):
self.write(cr, uid, ids, { 'state' : 'cancel'})
def survey_req_cancel(self, cr, uid, ids, context={}):
self.write(cr, uid, ids, { 'state' : 'cancel'}, context=context)
return True
hr_evaluation_interview()
hr_evaluation_interview()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:1
+36 -9
View File
@@ -44,8 +44,8 @@
</record>
<menuitem name="Evaluations" parent="hr.menu_hr_root" id="menu_eval_hr" sequence="3"/>
<menuitem
name="Evaluations" parent="hr.menu_hr_configuration" id="menu_eval_hr_config" sequence="3"/>
<menuitem
name="Periodic Evaluations" parent="hr.menu_hr_configuration" id="menu_eval_hr_config" sequence="3"/>
<menuitem
parent="menu_eval_hr_config"
id="menu_open_view_hr_evaluation_plan_tree"
@@ -57,6 +57,8 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Evaluation Plan Phase">
<notebook>
<page string="General">
<field name="plan_id" invisible="1"/>
<group col="6" colspan="4">
<field name="name"/>
@@ -84,6 +86,21 @@
<field name="send_anonymous_employee"/>
</group>
</group>
</page>
<page string="Mail Settings">
<field name="mail_feature" colspan="4"/>
<newline/>
<separator string="Mail Body"/>
<newline/>
<field name="mail_body" colspan="4" nolabel="1"/>
<newline/>
<separator string="Legend" colspan ="4"/>
<label string=" (employee_name)s: Partner name" colspan="2"/>
<label string="(user_signature)s: User name" colspan="2"/>
<label string="(date)s: Current Date" colspan="2"/>
<label string="(eval_name)s:Evaluation Name" colspan="2"/>
</page>
</notebook>
</form>
</field>
</record>
@@ -109,7 +126,7 @@
<field name="arch" type="xml">
<notebook position="inside">
<page string="Evaluation">
<field name="evaluation_plan_id" on_change="onchange_evaluation_plan_id(evaluation_plan_id)"/>
<field name="evaluation_plan_id" on_change="onchange_evaluation_plan_id(evaluation_plan_id, evaluation_date)"/>
<field name="evaluation_date"/>
</page>
</notebook>
@@ -201,6 +218,12 @@
<field name="employee_id" widget="selection" select="1"/>
<field name="plan_id" widget="selection" select="1"/>
<field name="rating"/>
<newline/>
<group col='8' colspan='15' expand='1' string='Group by...'>
<filter string='Plan' icon="terp-stock" domain="[]" context="{'group_by' : 'plan_id'}" />
<filter string='state' icon="terp-stock" domain="[]" context="{'group_by' : 'state'}" />
</group>
</group>
</search>
</field>
@@ -226,9 +249,9 @@
<group col="4" colspan="4">
<field name="survey_id" colspan="3"/>
<group colspan="1">
<button name="%(survey.action_view_survey_question_message)d" string="Interview Question" type="action"
<button name="%(survey.action_view_survey_question_message)d" string="Interview Question" type="action" states="waiting_answer,done,cancel"
icon="gtk-execute" context="{'survey_id': survey_id, 'response_id': [response], 'response_no':0, 'active' : response,'request' : True, 'object' : 'hr.evaluation.interview', 'cur_id' : active_id}" attrs="{'readonly':[('survey_id','=',False)]}"/>
<button name="%(survey.survey_browse_response)d" string="Print Interview" type="action"
<button name="%(survey.survey_browse_response)d" string="Print Interview" type="action" states="done"
icon="gtk-print" context="{'survey_id': survey_id, 'response_id' : [response], 'response_no':0,}" attrs="{'readonly':[('response','=',False)]}" />
</group>
</group>
@@ -242,10 +265,10 @@
<separator string="State" colspan="4"/>
<group colspan="4" col="6">
<field name="state"/>
<button name="survey_req_draft" string="Set to Draft" states="cancel,done" type="object" icon="gtk-new"/>
<button name="survey_req_waiting_answer" string="Watting Answer" states="draft" type="object" icon="gtk-new"/>
<!--<button name="survey_req_draft" string="Set to Draft" states="cancel,done" type="object" icon="gtk-new"/>
<button name="survey_req_waiting_answer" string="Waiting Answer" states="draft" type="object" icon="gtk-new"/>
<button name="survey_req_done" string="Done" states="waiting_answer" type="object" icon="gtk-ok"/>
<button name="survey_req_cancel" string="Cancelled" states="waiting_answer" type="object" icon="gtk-cancel"/>
<button name="survey_req_cancel" string="Cancelled" states="waiting_answer" type="object" icon="gtk-cancel"/>-->
</group>
</form>
</field>
@@ -263,7 +286,7 @@
<field name="response" readonly="1" invisible="True"/>
<button name="%(survey.action_view_survey_question_message)d" string="Interview Question" type="action" states="waiting_answer,done,cancel"
icon="gtk-execute" context="{'survey_id': survey_id, 'response_id': [response], 'response_no':0, 'active' : response, 'request' : True, 'object' : 'hr.evaluation.interview', 'cur_id' : active_id}" attrs="{'readonly':[('survey_id','=',False)]}"/>
<button name="%(survey.survey_browse_response)d" string="Print Interview" type="action" states="waiting_answer,done,cancel"
<button name="%(survey.survey_browse_response)d" string="Print Interview" type="action" states="done"
icon="gtk-print" context="{'survey_id': survey_id, 'response_id' : [response], 'response_no':0}" attrs="{'readonly':[('response','=',False)]}" />
<field name="state"/>
</tree>
@@ -303,5 +326,9 @@
id="menu_open_hr_evaluation_interview_requests"
action="action_hr_evaluation_interview_tree"/>
<menuitem name="Evaluation Reminders" parent="menu_eval_hr"
id="menu_eval_send_mail"
action="action_hr_evaluation_send_mail"
sequence="45"/>
</data>
</openerp>
+3 -1
View File
@@ -18,4 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import hr_evaluation_report
import hr_evaluation_report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -18,11 +18,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import tools
from osv import fields,osv
class hr_evaluation_report(osv.osv):
_name = "hr.evaluation.report"
_description = "Evaluations Statistics"
+25
View File
@@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import hr_evaluation_mail
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,43 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields, osv
import tools
class hr_evaluation_reminder(osv.osv_memory):
_name = "hr.evaluation.reminder"
_description = "Sends Reminders to employess to fill the evaluations"
_columns = {
'evaluation_id': fields.many2one('hr_evaluation.evaluation', 'Evaluations', required=True)
}
def send_mail(self, cr, uid, ids, context={}):
hr_evaluation_obj = self.pool.get('hr_evaluation.evaluation')
evaluation_data = self.read(cr, uid, ids, context=context)[0]
for waiting_id in hr_evaluation_obj.browse(cr, uid, evaluation_data['evaluation_id'], context=context).survey_request_ids:
if waiting_id.state == "waiting_answer" and waiting_id.user_to_review_id.work_email :
msg = " Hello %s, \n\n Kindly post your response for %s survey. \n\n Thanks," %(waiting_id.user_to_review_id.name, waiting_id.survey_id.title)
tools.email_send(tools.config['email_from'], [waiting_id.user_to_review_id.work_email],\
'Reminder to fill up Survey', msg)
return {'type': 'ir.actions.act_window_close'}
hr_evaluation_reminder()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_hr_evaluation_send_mail" model="ir.ui.view">
<field name="name">hr.evaluation.send.mail</field>
<field name="model">hr.evaluation.reminder</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Evaluation Reminders">
<field name="evaluation_id"/>
<newline/>
<button special="cancel" string="Cancel" />
<button name="send_mail" string="Send Mail" type="object"/>
</form>
</field>
</record>
<record id="action_hr_evaluation_send_mail" model="ir.actions.act_window">
<field name="name">Evaluation Send Mail</field>
<field name="res_model">hr.evaluation.reminder</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_hr_evaluation_send_mail"/>
<field name="context">{'record_id':active_id}</field>
<field name="target">new</field>
</record>
</data>
</openerp>
+3 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,11 +15,11 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
import hr
import hr_holidays
import report
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+2 -2
View File
@@ -51,8 +51,8 @@
'init_xml': [],
'update_xml': [
'security/ir.model.access.csv',
'hr_workflow.xml',
'hr_view.xml',
'hr_holidays_workflow.xml',
'hr_holidays_view.xml',
'hr_holidays_wizard.xml',
'hr_holidays_report.xml',
'report/hr_holidays_report_view.xml',
+48
View File
@@ -0,0 +1,48 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<!-- Casual leave -->
<record model="hr.holidays.status" id="holiday_status_cl">
<field name="name">Casual Leave</field>
<field name="color_name">red</field>
</record>
<record model="hr.holidays.per.user" id="holiday_user_employee1_cl">
<field name="employee_id" ref="hr.employee1"/>
<field name="holiday_status" ref="holiday_status_cl"/>
<field name="max_leaves">12</field>
</record>
<record model="hr.holidays" id="hr_holidays_employee1_cl">
<field name="name">Going For Tour</field>
<field name="holiday_status_id" ref="holiday_status_cl"/>
<field name="date_from">2010-01-01 08:00</field>
<field name="date_to">2010-01-03 18:00</field>
<field name="number_of_days_temp">3</field>
<field name="employee_id" ref="hr.employee1"/>
</record>
<!-- Sick leave -->
<record model="hr.holidays.status" id="holiday_status_sl">
<field name="name">Sickness Leave</field>
<field name="color_name">black</field>
</record>
<record model="hr.holidays.per.user" id="holiday_user_employee1_sl">
<field name="employee_id" ref="hr.employee1"/>
<field name="holiday_status" ref="holiday_status_sl"/>
<field name="max_leaves">6</field>
</record>
<record model="hr.holidays" id="hr_holidays_employee1_sl">
<field name="name">Sickness</field>
<field name="holiday_status_id" ref="holiday_status_sl"/>
<field name="date_from">2010-02-01 00:00</field>
<field name="date_to">2010-02-03 08:00</field>
<field name="number_of_days_temp">3</field>
<field name="employee_id" ref="hr.employee1"/>
</record>
</data>
</openerp>
@@ -10,15 +10,15 @@
<group col='8' colspan='4'>
<filter icon="terp-hr" domain="[('state','=','draft')]" string="To Confirm"/>
<filter icon="terp-hr" domain="[('state','=','confirm')]" string="To Validate"/>
<separator orientation="vertical"/>
<separator orientation="vertical"/>
<field name="name" select='1'/>
<field name="state" select="1">
<filter icon="terp-hr" domain="[('state','=','refuse')]" help="Refused Holidays"/>
<filter icon="terp-hr" domain="[('state','=','validate')]" help="Validated Holidays"/>
</field>
</field>
<field name="user_id" select="1" widget="selection">
<filter icon="gtk-execute" help="My Leaves" domain="[('user_id','=',uid)]" />
</field>
<filter icon="gtk-execute" help="My Leaves" domain="[('user_id','=',uid)]" />
</field>
<field name="department_id" select="1" widget="selection">
<filter icon="gtk-execute" domain="[('department_id','=',context.get('department_id',False))]"
help="My Departments Leaves"/>
+1 -1
View File
@@ -21,7 +21,7 @@
##############################################################################
import hr_hr
import hr_recruitment
import report
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+9 -8
View File
@@ -23,7 +23,7 @@
{
'name': 'HR - Recruitement',
'version': '1.0',
'category': 'Generic Modules/HR',
'category': 'Generic Modules/Human Resources',
'description': """
Manages job positions and the recruitement process. It's integrated with the
survey module to allows you to define interview for different jobs.
@@ -36,19 +36,20 @@ system to store and search in your CV base.
'website': 'http://www.openerp.com',
'depends': ['hr','survey','crm'],
'init_xml': [
'hr_hr_data.xml'
'hr_recruitment_data.xml'
],
'update_xml': [
'hr_hr_wizard.xml',
'hr_hr_view.xml',
'hr_hr_menu.xml',
'security/hr_hr_security.xml',
'hr_recruitment_wizard.xml',
'hr_recruitment_view.xml',
'hr_recruitment_menu.xml',
# 'report_hr_recruitment_view.xml',
'security/hr_recruitment_security.xml',
'security/ir.model.access.csv',
'board_hr_hr_statistical_view.xml',
'board_hr_recruitment_statistical_view.xml',
'report/hr_recruitment_report_view.xml'
],
'demo_xml': [
'hr_hr_demo.xml'
'hr_recruitment_demo.xml'
],
'installable': True,
'active': False,
@@ -21,7 +21,7 @@
import tools
from osv import fields,osv
from hr_recruitment import hr_hr
from hr_recruitment import hr_recruitment
class hr_recruitment_report(osv.osv):
_name = "hr.recruitment.report"
@@ -35,7 +35,7 @@ class hr_recruitment_report(osv.osv):
'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'hr.applicant')]",readonly=True),
'type_id': fields.many2one('crm.case.resource.type', 'Degree', domain="[('section_id','=',section_id),('object_id.model', '=', 'hr.applicant')]"),
'department_id':fields.many2one('hr.department','Department',readonly=True),
'priority': fields.selection(hr_hr.AVAILABLE_PRIORITIES, 'Appreciation'),
'priority': fields.selection(hr_recruitment.AVAILABLE_PRIORITIES, 'Appreciation'),
}
_order = 'date desc'
+3 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@@ -15,12 +15,12 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
import hr_hr_wizard
import hr_recruitment_wizard
+17 -18
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,11 +15,12 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
import time
from osv import fields
from osv import osv
from osv.orm import except_orm
@@ -84,7 +85,7 @@ class hr_analytic_timesheet(osv.osv):
emp_obj = self.pool.get('hr.employee')
emp_id = emp_obj.search(cr, uid, [('user_id', '=', context.get('user_id', uid))])
if emp_id:
emp = self.pool.get('hr.employee').browse(cr, uid, emp_id[0], context=context)
emp = emp_obj.browse(cr, uid, emp_id[0], context=context)
if bool(emp.product_id):
a = emp.product_id.product_tmpl_id.property_account_expense.id
if not a:
@@ -97,7 +98,7 @@ class hr_analytic_timesheet(osv.osv):
emp_obj = self.pool.get('hr.employee')
emp_id = emp_obj.search(cr, uid, [('user_id', '=', context.get('user_id', uid))])
if emp_id:
emp = self.pool.get('hr.employee').browse(cr, uid, emp_id[0], context=context)
emp = emp_obj.browse(cr, uid, emp_id[0], context=context)
if emp.journal_id:
return emp.journal_id.id
return False
@@ -113,7 +114,7 @@ class hr_analytic_timesheet(osv.osv):
}
def on_change_account_id(self, cr, uid, ids, account_id):
return {'value':{}}
def on_change_date(self, cr, uid, ids, date):
if ids:
new_date = self.read(cr,uid,ids[0],['date'])['date']
@@ -121,20 +122,18 @@ class hr_analytic_timesheet(osv.osv):
warning = {'title':'User Alert!','message':'Changing the date will let this entry appear in the timesheet of the new date.'}
return {'value':{},'warning':warning}
return {'value':{}}
def create(self, cr, uid, vals, context={}):
try:
res = super(hr_analytic_timesheet, self).create(cr, uid, vals, context)
return res
except Exception,e:
if '"journal_id" viol' in e.args[0]:
raise except_orm(_('ValidateError'),
_('No analytic journal available for this employee.\nDefine an employee for the selected user and assign an analytic journal.'))
elif '"account_id" viol' in e.args[0]:
raise except_orm(_('ValidateError'),
_('No analytic account defined on the project.\nPlease set one or we can not automatically fill the timesheet.'))
else:
raise except_orm(_('UnknownError'), str(e))
emp_obj = self.pool.get('hr.employee')
emp_id = emp_obj.search(cr, uid, [('user_id', '=', context.get('user_id', uid))], context=context)
ename = ''
if emp_id:
ename = emp_obj.browse(cr, uid, emp_id[0], context=context).name
if not vals.get('journal_id',False):
raise osv.except_osv(_('Warning !'), _('Analytic journal is not defined for employee %s \nDefine an employee for the selected user and assign an analytic journal!')%(ename,))
if not vals.get('account_id',False):
raise osv.except_osv(_('Warning !'), _('No analytic account defined on the project.\nPlease set one or we can not automatically fill the timesheet.'))
return super(hr_analytic_timesheet, self).create(cr, uid, vals, context=context)
def on_change_user_id(self, cr, uid, ids, user_id):
if not user_id:
+10 -4
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -24,7 +24,13 @@
'name': 'Idea Manager',
'version': '0.1',
'category': 'Tools',
'description': """This module allows your user to easily and efficiently participate in the innovation of the enterprise. It allows everybody to express ideas about different subjects. Then, others users can comment these ideas and vote for particular ideas. Each idea as a score based on the different votes. The managers can obtain an easy view on best ideas from all the users. Once installed, check the menu 'Ideas' in the 'Tools' main menu.""",
'description': """
This module allows your user to easily and efficiently participate in the innovation of the enterprise.
It allows everybody to express ideas about different subjects.
Then, others users can comment these ideas and vote for particular ideas.
Each idea as a score based on the different votes.
The managers can obtain an easy view on best ideas from all the users.
Once installed, check the menu 'Ideas' in the 'Tools' main menu.""",
'author': 'Tiny',
'website': 'http://openerp.com',
'depends': ['base'],
@@ -34,7 +40,7 @@
'idea_view.xml',
'idea_workflow.xml',
'security/idea_security.xml',
'security/ir.model.access.csv',
'security/ir.model.access.csv',
],
'demo_xml': [],
'installable': True,
+1 -1
View File
@@ -33,7 +33,7 @@
"l10n_ch"
],
"author" : "Camptocamp",
"description": "Swiws account chart that add also tax template definition",
"description": "Swiss account chart that also add tax template definition",
"website" : "camptocamp.com",
"category" : "Localisation/Account Charts",
"init_xml" : [
+11 -5
View File
@@ -1,6 +1,6 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@@ -15,21 +15,27 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
{
"name": "Lunch Module",
"author": "Tiny",
"Description": """
The lunch module is for keeping record of the order placing and payment of the orders.
The products are defined under categories and the payment records are maintained user wise
Every user has a cashbox which keeps track of the amount paid for a particular order.
""",
"version": "0.1",
"depends": ["base"],
"category" : "Generic Modules/Others",
"init_xml": [],
"update_xml": [
'security/ir.model.access.csv',
'lunch_wizard.xml',
'lunch_view.xml',
'security/ir.model.access.csv',
'lunch_wizard.xml',
'lunch_view.xml',
'lunch_report.xml',
#'process/lunch_process.xml'
],
+4 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -41,8 +41,9 @@ invoice and send propositions for membership renewal.
'init_xml': ['membership_data.xml'],
'update_xml': [
'security/ir.model.access.csv',
'wizard/membership_invoice_view.xml',
'membership_view.xml',
'membership_wizard.xml',
'wizard/membership_unpaid_invoice_view.xml',
'process/membership_process.xml'
],
'demo_xml': ['membership_demo.xml'],
+2 -1
View File
@@ -151,13 +151,14 @@
<menuitem name="Members" parent="menu_member" id="menu_members" sequence="2" action="action_membership_members"/>
<!-- PARTNERS -->
<!--
<wizard
string="Invoice Membership"
model="res.partner"
name="wizard_invoice_membership"
id="wizard_invoice_membership"
/>
-->
<record model="ir.ui.view" id="view_partner_tree">
-17
View File
@@ -1,17 +0,0 @@
<?xml version="1.0" ?>
<openerp>
<data>
<wizard name="wizard.invoice.membership.unpaid"
id="invoice_membership_unpaid"
model="res.partner"
keyword="client_action_multi"
string="List Unpaid Partners"
menu="False" />
<menuitem name="List Unpaid Partners" id="menu_unpaid_membership"
action="invoice_membership_unpaid" type="wizard"
parent="menu_member" />
</data>
</openerp>
+3 -4
View File
@@ -19,7 +19,6 @@
#
##############################################################################
import invoice_membership
import unpaid_partner_invoice
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
import membership_invoice
import membership_unpaid_invoice
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,141 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields
import wizard
import pooler
import time
from tools.translate import _
def _invoice_membership(self, cr, uid, data, context):
partner_ids = data['ids']
product_id = data['form']['product']
pool = pooler.get_pool(cr.dbname)
cr.execute('''
SELECT partner_id, id, type
FROM res_partner_address
WHERE partner_id =ANY(%s)''',(partner_ids,))
fetchal = cr.fetchall()
if not fetchal:
raise wizard.except_wizard(_('Error !'), _('No Address defined for this partner'))
partner_address_ids = {}
for x in range(len(fetchal)):
pid = fetchal[x][0]
id = fetchal[x][1]
type = fetchal[x][2]
if partner_address_ids.has_key(pid) and partner_address_ids[pid]['type'] == 'invoice':
continue
partner_address_ids[pid] = {'id': id, 'type': type}
invoice_list= []
invoice_obj = pool.get('account.invoice')
partner_obj = pool.get('res.partner')
product_obj = pool.get('product.product')
invoice_line_obj = pool.get(('account.invoice.line'))
invoice_tax_obj = pool.get(('account.invoice.tax'))
product = product_obj.read(cr, uid, product_id, ['uom_id'])
for partner_id in partner_ids:
account_id = partner_obj.read(cr, uid, partner_id, ['property_account_receivable'])['property_account_receivable'][0]
read_fpos = partner_obj.read(cr, uid, partner_id, ['property_account_position'])
fpos_id = read_fpos['property_account_position'] and read_fpos['property_account_position'][0]
line_value = {
'product_id' : product_id,
}
quantity = 1
line_dict = invoice_line_obj.product_id_change(cr, uid, {}, product_id, product['uom_id'][0], quantity, '', 'out_invoice', partner_id, fpos_id, context=context)
line_value.update(line_dict['value'])
if line_value['invoice_line_tax_id']:
tax_tab = [(6, 0, line_value['invoice_line_tax_id'])]
line_value['invoice_line_tax_id'] = tax_tab
invoice_id = invoice_obj.create(cr, uid, {
'partner_id' : partner_id,
'address_invoice_id': partner_address_ids[partner_id]['id'],
'account_id': account_id,
'fiscal_position': fpos_id or False
}
)
line_value['invoice_id'] = invoice_id
invoice_line_id = invoice_line_obj.create(cr, uid, line_value, context)
invoice_obj.write(cr, uid, invoice_id, {'invoice_line':[(6,0,[invoice_line_id])]})
invoice_list.append(invoice_id)
if line_value['invoice_line_tax_id']:
tax_value = invoice_tax_obj.compute(cr, uid, invoice_id).values()
for tax in tax_value:
invoice_tax_obj.create(cr, uid, tax, context=context)
result = pool.get('ir.model.data')._get_id(cr, uid, 'account', 'view_account_invoice_filter')
res = pool.get('ir.model.data').read(cr, uid, result, ['res_id'])
value = {
'domain': [
('id', 'in', invoice_list),
],
'name': 'Membership invoice',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'account.invoice',
'type': 'ir.actions.act_window',
'res_id' : invoice_list,
'search_view_id' : res['res_id']
}
return value
wizard_arch= """<?xml version="1.0"?>
<form string="Choose invoice details">
<field
name="product"
domain="[('membership','=','True')]"
context="product='membership_product'"
/>
</form>"""
class wizard_invoice_membership(wizard.interface):
states = {
'init' : {
'actions' : [],
'result' : {
'type' : 'form',
'arch' : wizard_arch,
'fields' : {
'product': {
'string': 'Membership product',
'type': 'many2one',
'relation': 'product.product',
'required': True
},
},
'state' : [('end', 'Cancel'),('ok', 'Confirm') ]}
},
'ok' : {
'actions' : [],
'result' : {'type' : 'action',
'action': _invoice_membership,
'state' : 'end'
},
},
}
wizard_invoice_membership("wizard_invoice_membership")
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,102 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
from osv import fields, osv
from tools.translate import _
import tools
class membership_invoice(osv.osv_memory):
_name = "membership.invoice"
_description = "Membership Invoice From Partner"
_columns ={
'product_id': fields.many2one('product.product','Membership Product', required=True),
}
def membership_invoice(self, cr, uid, ids, context={}):
invoice_obj = self.pool.get('account.invoice')
partner_obj = self.pool.get('res.partner')
product_obj = self.pool.get('product.product')
invoice_line_obj = self.pool.get(('account.invoice.line'))
invoice_tax_obj = self.pool.get(('account.invoice.tax'))
partner_ids = context['active_ids']
for data in self.read(cr, uid, ids, context=context):
product_id = data['product_id']
cr.execute('''
SELECT partner_id, id, type
FROM res_partner_address
WHERE partner_id =ANY(%s)''',(partner_ids,))
fetchal = cr.fetchall()
if not fetchal:
raise osv.except_osv(_('Error !'), _('No Address defined for this partner'))
partner_address_ids = {}
for x in range(len(fetchal)):
pid = fetchal[x][0]
id = fetchal[x][1]
type = fetchal[x][2]
if partner_address_ids.has_key(pid) and partner_address_ids[pid]['type'] == 'invoice':
continue
partner_address_ids[pid] = {'id': id, 'type': type}
invoice_list= []
product = product_obj.read(cr, uid, product_id, ['uom_id'], context=context)
for partner_id in partner_ids:
account_id = partner_obj.read(cr, uid, partner_id, ['property_account_receivable'], context=context)['property_account_receivable'][0]
read_fpos = partner_obj.read(cr, uid, partner_id, ['property_account_position'], context=context)
fpos_id = read_fpos['property_account_position'] and read_fpos['property_account_position'][0]
line_value = {
'product_id' : product_id,
}
quantity = 1
line_dict = invoice_line_obj.product_id_change(cr, uid, {}, product_id, product['uom_id'][0], quantity, '', 'out_invoice', partner_id, fpos_id, context=context)
line_value.update(line_dict['value'])
if line_value['invoice_line_tax_id']:
tax_tab = [(6, 0, line_value['invoice_line_tax_id'])]
line_value['invoice_line_tax_id'] = tax_tab
invoice_id = invoice_obj.create(cr, uid, {
'partner_id' : partner_id,
'address_invoice_id': partner_address_ids[partner_id]['id'],
'account_id': account_id,
'fiscal_position': fpos_id or False
}
)
line_value['invoice_id'] = invoice_id
invoice_line_id = invoice_line_obj.create(cr, uid, line_value, context=context)
invoice_obj.write(cr, uid, invoice_id, {'invoice_line':[(6,0,[invoice_line_id])]}, context=context)
invoice_list.append(invoice_id)
if line_value['invoice_line_tax_id']:
tax_value = invoice_tax_obj.compute(cr, uid, invoice_id).values()
for tax in tax_value:
invoice_tax_obj.create(cr, uid, tax, context=context)
return {
'domain': [('id', 'in', invoice_list)],
'name': 'Membership Invoice',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'account.invoice',
'type': 'ir.actions.act_window',
}
membership_invoice()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_membership_invoice_view" model="ir.ui.view">
<field name="name">membership.invoice.view.form</field>
<field name="model">membership.invoice</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Membership Invoice">
<group colspan="4" >
<field name="product_id" context="{'product':membership_product}" domain="[('membership','=',True)]"/>
</group>
<group colspan="4" col="6">
<button icon="gtk-cancel" special="cancel" string="Cancel"/>
<button icon="gtk-ok" string="Confirm" name="membership_invoice" type="object"/>
</group>
</form>
</field>
</record>
<record id="action_membership_invoice_view" model="ir.actions.act_window">
<field name="name">Membership Invoice</field>
<field name="res_model">membership.invoice</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_membership_invoice_view"/>
<field name="target">new</field>
</record>
<record id="action_idea_post_vote_values" model="ir.values">
<field name="model_id" ref="base.model_res_partner" />
<field name="object" eval="1" />
<field name="name">vote</field>
<field name="key2">client_action_multi</field>
<field name="value" eval="'ir.actions.act_window,' + str(ref('action_membership_invoice_view'))"/>
<field name="key">action</field>
<field name="model">res.partner</field>
</record>
</data>
</openerp>
@@ -18,32 +18,32 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
import wizard
import pooler
from osv import fields, osv
wizard_arch= """<?xml version="1.0"?>
<form string="Choose invoice details">
<field
name="product"
domain="[('membership','=','True')]"
context="product='membership_product'"
/>
</form>"""
class member_unpaid_invoice(osv.osv_memory):
_name = "membership.unpaid.invoice"
_description = "List of Unpaid Partner"
_columns ={
'product': fields.many2one('product.product','Membership product', size=64,required=True, help='Select Membership product'),
}
def _invoice_membership(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
partners = []
cr.execute('''select p.id from res_partner as p \
def _invoice_membership(self, cr, uid, ids, context):
model_obj = self.pool.get('ir.model.data')
partners = []
result = model_obj._get_id(cr, uid, 'base', 'view_res_partner_filter')
res = model_obj.read(cr, uid, result, ['res_id'], context=context)
for data in self.read(cr, uid, ids, context=context):
cr.execute('''select p.id from res_partner as p \
left join account_invoice as i on p.id=i.partner_id \
left join account_invoice_line as il on i.id=il.invoice_id \
left join product_product as pr on pr.id=il.product_id \
where i.state = 'open' and pr.id=%s \
group by p.id''' % (data['form']['product']))
map(lambda x: partners.append(x[0]),cr.fetchall())
result = pool.get('ir.model.data')._get_id(cr, uid, 'base', 'view_res_partner_filter')
res = pool.get('ir.model.data').read(cr, uid, result, ['res_id'])
value = {
group by p.id''' % (data['product']))
map(lambda x: partners.append(x[0]),cr.fetchall())
return {
'domain': [('id', 'in', partners)],
'name': 'Unpaid Partners',
'view_type': 'form',
@@ -53,34 +53,7 @@ def _invoice_membership(self, cr, uid, data, context):
'res_id' : partners,
'search_view_id' : res['res_id']
}
return value
class wizard_unpaid_inv(wizard.interface):
member_unpaid_invoice()
states = {
'init' : {
'actions' : [],
'result' : {
'type' : 'form',
'arch' : wizard_arch,
'fields' : {
'product': {
'string': 'Membership product',
'type': 'many2one',
'relation': 'product.product',
'help': 'Select Membership product',
'required': True
},
},
'state' : [('end', 'Cancel'),('ok', 'Unpaid Partners') ]}
},
'ok' : {
'actions' : [],
'result' : {'type' : 'action', 'action': _invoice_membership, 'state' : 'end'},
},
}
wizard_unpaid_inv("wizard.invoice.membership.unpaid")
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_unpaid_invoice_view" model="ir.ui.view">
<field name="name">unpaid.invoice.view.form</field>
<field name="model">membership.unpaid.invoice</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="List Unpaid Partners">
<group colspan="4" >
<field name="product" context="{'product':membership_product}" domain="[('membership','=',True)]"/>
</group>
<group colspan="4" col="6">
<button icon="gtk-cancel" special="cancel" string="Cancel"/>
<button icon="gtk-ok" string="Unpaid Partners" name="_invoice_membership" type="object"/>
</group>
</form>
</field>
</record>
<record id="action_unpaid_invoice_view" model="ir.actions.act_window">
<field name="name">List Unpaid Partners</field>
<field name="res_model">membership.unpaid.invoice</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_unpaid_invoice_view"/>
<field name="target">new</field>
</record>
<menuitem name="List Unpaid Partners" id="menu_unpaid_invoice"
action="action_unpaid_invoice_view"
parent="menu_member" />
</data>
</openerp>
+5 -4
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -24,8 +24,9 @@
'name': 'Multi Company',
'version': '1.0',
'category': 'Custom',
'description': """This module add the possibility to easily manage
the default value for each object
'description': """
Multicompany module is for managing a multicompany environment.
This module is the base module for other multicompany modules.
""",
'author': 'Tiny,SYLEAM',
'website': 'http://www.openerp.com/',
+6 -1
View File
@@ -6,7 +6,12 @@
"depends" : ["base"],
"category" : "Generic Modules/Olap",
"description": """
Base module to manage Olap schemas. Cube designer.
Olap module is used to install BI module in client. Olap provides Online
Analytical Process with the mdx query. BI provides Cube Browsing and
Cube Designing. After installing Olap Module you will get Cube Browser
and Cube Desinger in Reporting Menu. Cube Browser is used to generate
the reports with table view (mdx view) of mdx query. and Cube designer
is used to make cubes in BI..
""",
"init_xml" : ["data/olap_data.xml"],
"update_xml" : [
+1 -1
View File
@@ -27,7 +27,7 @@
"depends" : ["olap"],
"category" : "Generic Modules/Olap",
"description": """
Sale module will load the data in olap tables
CRM module will load the data in olap tables
""",
"init_xml" : ['olap_data.xml'],
"update_xml" :[],
+9 -3
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -25,7 +25,13 @@
'version': '1.0',
'category': 'Generic Modules/Base',
'description': """
This module allows you to manage your process for the end-users.
This module shows the basic processes involved
in the selected modules and in the sequence these
occur
Note: This applies to the modules containing modulename_process_xml
for e.g product/process/product_process_xml
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
+3 -1
View File
@@ -25,7 +25,9 @@
"version" : "1.0",
"depends" : ["base"],
"author" : "Tiny",
"description": """Installer for various interesting tools
"category" : "Tools",
"description": """Installs tools for lunch,survey,subscription and audittrail
module
""",
'website': 'http://www.openerp.com',
'init_xml': [],
+4 -6
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,12 +15,11 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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 osv import fields
from osv import osv
from osv import fields, osv
class res_company(osv.osv):
_inherit = 'res.company'
@@ -29,10 +28,9 @@ class res_company(osv.osv):
help='This will set the unit of measure used in projects and tasks.\n' \
"If you use the timesheet linked to projects (project_timesheet module), don't " \
"forget to setup the right unit of measure in your employees.",
),
}
res_company()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+56 -35
View File
@@ -18,14 +18,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from lxml import etree
import mx.DateTime
import datetime
import time
from tools.translate import _
from osv import fields, osv
from tools.translate import _
class project_task_type(osv.osv):
_name = 'project.task.type'
@@ -47,11 +46,9 @@ class project(osv.osv):
_description = "Project"
_inherits = {'account.analytic.account':"category_id"}
def search(self, cr, user, args, offset=0, limit=None, order=None,
context=None, count=False):
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
if user == 1:
return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order,
context=context, count=count)
return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
if context and context.has_key('user_prefence') and context['user_prefence']:
cr.execute("""SELECT project.id FROM project_project project
LEFT JOIN account_analytic_account account ON account.id = project.category_id
@@ -62,7 +59,7 @@ class project(osv.osv):
return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order,
context=context, count=count)
def _complete_name(self, cr, uid, ids, name, args, context):
def _complete_name(self, cr, uid, ids, name, args, context={}):
res = {}
for m in self.browse(cr, uid, ids, context=context):
res[m.id] = (m.parent_id and (m.parent_id.name + '/') or '') + m.name
@@ -72,20 +69,21 @@ class project(osv.osv):
return super(project, self).check_recursion(cursor, user, ids,
parent=parent)
def onchange_partner_id(self, cr, uid, ids, part):
def onchange_partner_id(self, cr, uid, ids, part, context={}):
partner_obj = self.pool.get('res.partner')
if not part:
return {'value':{'contact_id': False, 'pricelist_id': False}}
addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['contact'])
addr = partner_obj.address_get(cr, uid, [part], ['contact'])
pricelist = partner_obj.read(cr, uid, part, ['property_product_pricelist'], context=context)
pricelist_id = pricelist.get('property_product_pricelist', False) and pricelist.get('property_product_pricelist')[0] or False
return {'value':{'contact_id': addr['contact'], 'pricelist_id': pricelist_id}}
pricelist = self.pool.get('res.partner').browse(cr, uid, part).property_product_pricelist.id
return {'value':{'contact_id': addr['contact'], 'pricelist_id': pricelist}}
def _progress_rate(self, cr, uid, ids, names, arg, context=None):
def _progress_rate(self, cr, uid, ids, names, arg, context={}):
res = {}.fromkeys(ids, 0.0)
progress = {}
if not ids:
return res
ids2 = self.search(cr, uid, [('parent_id','child_of',ids)])
ids2 = self.search(cr, uid, [('parent_id','child_of',ids)], context=context)
if ids2:
cr.execute('''SELECT
project_id, sum(planned_hours), sum(total_hours), sum(effective_hours)
@@ -96,15 +94,15 @@ class project(osv.osv):
state<>'cancelled'
GROUP BY
project_id''',(ids2,))
progress = dict(map(lambda x: (x[0], (x[1],x[2],x[3])), cr.fetchall()))
progress = dict(map(lambda x: (x[0], (x[1], x[2], x[3])), cr.fetchall()))
for project in self.browse(cr, uid, ids, context=context):
s = [0.0,0.0,0.0]
s = [0.0, 0.0, 0.0]
tocompute = [project]
while tocompute:
p = tocompute.pop()
tocompute += p.child_ids
for i in range(3):
s[i] += progress.get(p.id, (0.0,0.0,0.0))[i]
s[i] += progress.get(p.id, (0.0, 0.0, 0.0))[i]
res[project.id] = {
'planned_hours': s[0],
'effective_hours': s[2],
@@ -177,7 +175,7 @@ class project(osv.osv):
res = self.setActive(cr, uid, ids,value=True, context=context)
return res
def copy(self, cr, uid, id, default={},context={}):
def copy(self, cr, uid, id, default={}, context={}):
proj = self.browse(cr, uid, id, context=context)
default = default or {}
context['active_test'] = False
@@ -190,34 +188,37 @@ class project(osv.osv):
cr.execute('update project_task set active=True where project_id =ANY(%s)',(ids,))
return res
def duplicate_template(self, cr, uid, ids,context={}):
def duplicate_template(self, cr, uid, ids, context={}):
project_obj = self.pool.get('project.project')
task_obj = self.pool.get('project.task')
result = []
for proj in self.browse(cr, uid, ids):
for proj in self.browse(cr, uid, ids, context=context):
parent_id = context.get('parent_id',False)
new_id = self.pool.get('project.project').copy(cr, uid, proj.id, default = {
new_id = project_obj.copy(cr, uid, proj.id, default = {
'name': proj.name +_(' (copy)'),
'state':'open',
'parent_id':parent_id})
'parent_id':parent_id}, context=context)
result.append(new_id)
cr.execute('select id from project_task where project_id=%s', (proj.id,))
res = cr.fetchall()
for (tasks_id,) in res:
self.pool.get('project.task').copy(cr, uid, tasks_id, default = {
task_obj.copy(cr, uid, tasks_id, default = {
'project_id': new_id,
'active':True}, context=context)
child_ids = self.search(cr, uid, [('parent_id','=', proj.id)])
child_ids = self.search(cr, uid, [('parent_id','=', proj.id)], context=context)
if child_ids:
self.duplicate_template(cr, uid, child_ids, context={'parent_id':new_id})
self.duplicate_template(cr, uid, child_ids, context={'parent_id': new_id})
return result
# set active value for a project, its sub projects and its tasks
def setActive(self, cr, uid, ids, value=True, context={}):
task_obj = self.pool.get('project.task')
for proj in self.browse(cr, uid, ids, context):
self.write(cr, uid, [proj.id], {'state': value and 'open' or 'template'}, context)
cr.execute('select id from project_task where project_id=%s', (proj.id,))
tasks_id = [x[0] for x in cr.fetchall()]
if tasks_id:
self.pool.get('project.task').write(cr, uid, tasks_id, {'active': value}, context)
task_obj.write(cr, uid, tasks_id, {'active': value}, context=context)
child_ids = self.search(cr, uid, [('parent_id','=', proj.id)])
if child_ids:
self.setActive(cr, uid, child_ids, value, context)
@@ -253,7 +254,7 @@ class task(osv.osv):
return res
def onchange_planned(self, cr, uid, ids, planned = 0.0, effective = 0.0):
return {'value':{'remaining_hours' : planned - effective}}
return {'value':{'remaining_hours' : planned - effective}}
def _default_project(self, cr, uid, context={}):
if 'project_id' in context and context['project_id']:
@@ -269,8 +270,8 @@ class task(osv.osv):
default['work_ids'] = []
return super(task, self).copy_data(cr, uid, id, default, context)
def _check_dates(self, cr, uid, ids):
task = self.read(cr, uid, ids[0],['date_start','date_end'])
def _check_dates(self, cr, uid, ids, context={}):
task = self.read(cr, uid, ids[0],['date_start', 'date_end'])
if task['date_start'] and task['date_end']:
if task['date_start'] > task['date_end']:
return False
@@ -309,7 +310,7 @@ class task(osv.osv):
'company_id': fields.many2one('res.company', 'Company'),
}
_defaults = {
'user_id': lambda obj,cr,uid,context: uid,
'user_id': lambda obj, cr, uid, context: uid,
'state': lambda *a: 'draft',
'priority': lambda *a: '2',
'progress': lambda *a: 0,
@@ -317,7 +318,7 @@ class task(osv.osv):
'active': lambda *a: True,
'date_start': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'project_id': _default_project,
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c)
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c)
}
_order = "sequence, priority, date_start, id"
@@ -328,7 +329,8 @@ class task(osv.osv):
# Override view according to the company definition
#
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
obj_tm = self.pool.get('res.users').browse(cr, uid, uid, context).company_id.project_time_mode_id
users_obj = self.pool.get('res.users')
obj_tm = users_obj.browse(cr, uid, uid, context).company_id.project_time_mode_id
tm = obj_tm and obj_tm.name or 'Hours'
res = super(task, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu=submenu)
@@ -470,7 +472,7 @@ class project_work(osv.osv):
'company_id': fields.related('task_id','company_id',type='many2one',relation='res.company',string='Company',store=True)
}
_defaults = {
'user_id': lambda obj,cr,uid,context: uid,
'user_id': lambda obj, cr, uid, context: uid,
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S')
}
_order = "date desc"
@@ -498,8 +500,9 @@ project_work()
class config_compute_remaining(osv.osv_memory):
_name='config.compute.remaining'
def _get_remaining(self,cr, uid, ctx):
task_obj = self.pool.get('project.task')
if 'active_id' in ctx:
return self.pool.get('project.task').browse(cr,uid,ctx['active_id']).remaining_hours
return task_obj.browse(cr,uid,ctx['active_id'],context=ctx).remaining_hours
return False
_columns = {
@@ -511,12 +514,30 @@ class config_compute_remaining(osv.osv_memory):
}
def compute_hours(self, cr, uid, ids, context=None):
task_obj = self.pool.get('project.task')
request = self.pool.get('res.request')
if 'active_id' in context:
remaining_hrs=self.browse(cr,uid,ids)[0].remaining_hours
self.pool.get('project.task').write(cr,uid,context['active_id'],{'remaining_hours':remaining_hrs})
task_obj.write(cr,uid,context['active_id'],{'remaining_hours':remaining_hrs})
if context.get('button_reactivate', False):
tasks = task_obj.browse(cr, uid, [context['active_id']], context=context)
for task in tasks:
project = task.project_id
if project and project.warn_manager and project.user_id.id and (project.user_id.id != uid):
request.create(cr, uid, {
'name': _("Task '%s' set in progress") % task.name,
'state': 'waiting',
'act_from': uid,
'act_to': project.user_id.id,
'ref_partner_id': task.partner_id.id,
'ref_doc1': 'project.task,%d' % task.id,
'ref_doc2': 'project.project,%d' % project.id,
})
task_obj.write(cr, uid, [task.id], {'state': 'open'})
return {
'type': 'ir.actions.act_window_close',
}
config_compute_remaining()
class message(osv.osv):
+5 -4
View File
@@ -268,7 +268,7 @@
<field name="state" select="1"/>
<button name="do_draft" states="open" string="Draft" type="object" icon="gtk-indent"/>
<button name="do_open" states="pending,draft" string="Start Task" type="object" icon="gtk-execute"/>
<button name="do_reopen" states="done,cancelled" string="Reactivate" type="object" icon="gtk-convert"/>
<button name="%(action_config_compute_remaining)d" states="done,cancelled" string="Reactivate" type="action" icon="gtk-convert" context="{'button_reactivate':True}" />
<button name="do_pending" states="open" string="Pending" type="object" icon="gtk-media-pause"/>
<button groups="base.group_extended" name="%(wizard_delegate_task)d" states="pending,open" string="Delegate" type="action" icon="gtk-sort-descending"/>
<button name="%(wizard_close_task)d" states="pending,open" string="Done" type="action" icon="gtk-jump-to"/>
@@ -329,10 +329,11 @@
<tree colors="grey:state in ('cancelled','done');blue:remaining_hours&lt;0;red:bool(date_deadline) and (date_deadline&lt;current_date) and (state in ('draft','open'));black:state not in ('cancelled','done')" string="Tasks">
<field name="sequence" invisible="1"/>
<field name="name"/>
<field name="planned_hours" widget="float_time" on_change="onchange_planned(planned_hours, effective_hours)" invisible="not context.get('set_visible',False)"/>
<field name="project_id" icon="gtk-indent" domain="['|',('user_id','=',uid),('members','=',uid)]"/>
<field name="user_id"/>
<field name="delegated_user_id" invisible="context.get('show_delegated', True)"/>
<field name="planned_hours" widget="float_time" />
<field name="total_hours" widget="float_time"/>
<field name="remaining_hours" widget="float_time" sum="Remaining Hours" invisible="context.get('set_visible',False)"/>
<field name="date_deadline" invisible="context.get('set_visible',False)"/>
<field name="type" groups="base.group_extended" invisible="context.get('set_visible',False)"/>
@@ -601,7 +602,7 @@
<group col="20" colspan="4">
<filter domain="[('date','&gt;=',time.strftime('%%Y-%%m-01'))]" icon="terp-project" string="This Month" />
<filter domain="[('date', '=', time.strftime('%%Y-%%m-%%d'))]" icon="terp-project" string="Today" />
<separator orientation="vertical"/>
<field name="subject"/>
<field name="project_id" select="1" widget="selection"/>
@@ -610,7 +611,7 @@
</field>
</group>
<newline/>
<group expand="1" string="Group By..." colspan="4" col="20">
<group expand="1" string="Group By..." colspan="4" col="20">
<filter string="Project" icon="terp-project" domain="[]" context="{'group_by':'project_id'}"/>
<filter string="User" icon="terp-project" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Date" icon="terp-project" domain="[]" context="{'group_by':'date'}"/>
+6 -6
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
@@ -37,7 +37,8 @@ mail_fields = {
}
def email_send(cr, uid, ids, to_adr, description, context={}):
for task in pooler.get_pool(cr.dbname).get('project.task').browse(cr, uid, ids, context):
pool = pooler.get_pool(cr.dbname)
for task in pool.get('project.task').browse(cr, uid, ids, context=context):
project = task.project_id
subject = "Task '%s' closed" % task.name
if task.user_id and task.user_id.address_id and task.user_id.address_id.email:
@@ -45,7 +46,6 @@ def email_send(cr, uid, ids, to_adr, description, context={}):
signature = task.user_id.signature
else:
raise wizard.except_wizard(_('Error'), _("Couldn't send mail because your email address is not configured!"))
if to_adr:
val = {
'name': task.name,
@@ -75,8 +75,8 @@ class wizard_close(wizard.interface):
partner_id = task.partner_id or task.project_id.partner_id
if partner_id and partner_id.address[0].email:
email = partner_id.address[0].email
return {'description': task.description, 'email':email}
return {'description': task.description or task.name, 'email':email}
def _data_send(self, cr, uid, data, context):
task_obj = pooler.get_pool(cr.dbname).get('project.task')
if data['form']['email']:
+4 -5
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@@ -15,12 +15,11 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero 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/>.
#
##############################################################################
import project
import project_long_term
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+15 -8
View File
@@ -18,8 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name" : "Long Term Project Management",
"version": "1.1",
@@ -27,15 +25,24 @@
"website" : "http://www.openerp.com",
"category" : "Generic Modules/Projects & Services",
"depends" : ["project", "resource"],
"description": """Long Term Project management module that track planning, scheduling, resources allocation.
"description": """
Long Term Project management module that track planning, scheduling, resources allocation.
Mainly used with Big project management.
- Project Phases will be maintain by Manager of the project
- Compute Phase Scheduling: Compute start date and end date of the phases which are in draft,open and pending state of the project given.
If no project given then all the draft,open and pending states phases will be taken
- Compute Task Scheduling: This works same as the scheduler button on project.phase. It takes the project as arguement and computes all the open,draft and pending tasks
- Schedule Tasks: All the tasks which are in draft,pending and open states are scheduled with taking the phase's start date
""",
"init_xml" : [],
"demo_xml" : ["project_demo.xml"],
"demo_xml" : ["project_long_term_demo.xml"],
"update_xml": [
#"security/ir.model.access.csv",
"project_wizard.xml" ,
"project_view.xml",
"project_workflow.xml"
"security/ir.model.access.csv",
"project_long_term_wizard.xml" ,
"project_long_term_view.xml",
"project_long_term_workflow.xml"
],
'installable': True,
'active': False,
@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record forcecreate="True" id="ir_cron_scheduler_action" model="ir.cron">
<field name="name">Calculate Project Task Length Scheduler</field>
<field eval="False" name="active"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall"/>
<field eval="True" name="active"/>
<field eval="'project.project'" name="model"/>
<field eval="'compute_date'" name="function"/>
<!--<field model="project.project" search="[]" name="args"/>
<field eval="select id from project.project" name="args"/>-->
</record>
</data>
</openerp>
@@ -18,24 +18,23 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from lxml import etree
import mx.DateTime
import time
from tools.translate import _
from osv import fields, osv
class project_phase(osv.osv):
_name = "project.phase"
_description = "Project Phase"
def _check_recursion(self, cr, uid, ids):
obj_self = self.browse(cr, uid, ids[0])
prev_ids = obj_self.previous_phase_ids
next_ids = obj_self.next_phase_ids
def _check_recursion(self, cr, uid, ids, context={}):
data_phase = self.browse(cr, uid, ids[0], context=context)
prev_ids = data_phase.previous_phase_ids
next_ids = data_phase.next_phase_ids
# it should nither be in prev_ids nor in next_ids
if (obj_self in prev_ids) or (obj_self in next_ids):
if (data_phase in prev_ids) or (data_phase in next_ids):
return False
ids = [id for id in prev_ids if id in next_ids]
# both prev_ids and next_ids must be unique
@@ -48,7 +47,7 @@ class project_phase(osv.osv):
while prev_ids:
cr.execute('select distinct prv_phase_id from project_phase_rel where next_phase_id in ('+','.join(map(str, prev_ids))+')')
prv_phase_ids = filter(None, map(lambda x: x[0], cr.fetchall()))
if obj_self.id in prv_phase_ids:
if data_phase.id in prv_phase_ids:
return False
ids = [id for id in prv_phase_ids if id in next_ids]
if ids:
@@ -58,7 +57,7 @@ class project_phase(osv.osv):
while next_ids:
cr.execute('select distinct next_phase_id from project_phase_rel where prv_phase_id in ('+','.join(map(str, next_ids))+')')
next_phase_ids = filter(None, map(lambda x: x[0], cr.fetchall()))
if obj_self.id in next_phase_ids:
if data_phase.id in next_phase_ids:
return False
ids = [id for id in next_phase_ids if id in prev_ids]
if ids:
@@ -66,33 +65,30 @@ class project_phase(osv.osv):
next_ids = next_phase_ids
return True
def _check_dates(self, cr, uid, ids):
phase = self.read(cr, uid, ids[0], ['date_start', 'date_end'])
if phase['date_start'] and phase['date_end']:
if phase['date_start'] > phase['date_end']:
return False
def _check_dates(self, cr, uid, ids, context={}):
phase = self.read(cr, uid, ids[0], ['date_start', 'date_end'], context=context)
if phase['date_start'] and phase['date_end'] and phase['date_start'] > phase['date_end']:
return False
return True
def _check_constraint_start(self, cr, uid, ids):
phase = self.read(cr, uid, ids[0], ['date_start', 'constraint_date_start'])
if phase['date_start'] and phase['constraint_date_start']:
if phase['date_start'] < phase['constraint_date_start']:
return False
def _check_constraint_start(self, cr, uid, ids, context={}):
phase = self.read(cr, uid, ids[0], ['date_start', 'constraint_date_start'], context=context)
if phase['date_start'] and phase['constraint_date_start'] and phase['date_start'] < phase['constraint_date_start']:
return False
return True
def _check_constraint_end(self, cr, uid, ids):
phase = self.read(cr, uid, ids[0], ['date_end', 'constraint_date_end'])
if phase['date_end'] and phase['constraint_date_end']:
if phase['date_end'] > phase['constraint_date_end']:
return False
def _check_constraint_end(self, cr, uid, ids, context={}):
phase = self.read(cr, uid, ids[0], ['date_end', 'constraint_date_end'], context=context)
if phase['date_end'] and phase['constraint_date_end'] and phase['date_end'] > phase['constraint_date_end']:
return False
return True
_columns = {
'name': fields.char("Phase Name", size=64, required=True),
'date_start': fields.datetime('Starting Date'),
'date_end': fields.datetime('End Date'),
'constraint_date_start': fields.datetime('Constraint Starting Date'),
'constraint_date_end': fields.datetime('Constraint End Date'),
'constraint_date_start': fields.datetime('Start Date', help='force the phase to start after this date'),
'constraint_date_end': fields.datetime('End Date', help='force the phase to finish before this date'),
'project_id': fields.many2one('project.project', 'Project', required=True),
'next_phase_ids': fields.many2many('project.phase', 'project_phase_rel', 'prv_phase_id', 'next_phase_id', 'Next Phases'),
'previous_phase_ids': fields.many2many('project.phase', 'project_phase_rel', 'next_phase_id', 'prv_phase_id', 'Previous Phases'),
@@ -120,73 +116,73 @@ class project_phase(osv.osv):
(_check_constraint_end, 'Error! Phase must end-before Constraint End Date.', ['date_end', 'constraint_date_end']),
]
def onchange_project(self, cr, uid, ids, project):
def onchange_project(self, cr, uid, ids, project, context={}):
result = {}
project_obj = self.pool.get('project.project')
if project:
project_obj = self.pool.get('project.project')
project_id = project_obj.browse(cr, uid, project)
if project_id.date_start:
result['date_start'] = mx.DateTime.strptime(project_id.date_start, "%Y-%m-%d").strftime('%Y-%m-%d %H:%M:%S')
return {'value': result}
project_id = project_obj.browse(cr, uid, project, context=context)
if project_id.date_start:
result['date_start'] = mx.DateTime.strptime(project_id.date_start, "%Y-%m-%d").strftime('%Y-%m-%d %H:%M:%S')
return {'value': result}
return {'value': {'date_start': []}}
def _check_date_start(self, cr, uid, phase, date_end, context=None):
def _check_date_start(self, cr, uid, phase, date_end, context={}):
"""
Check And Compute date_end of phase if change in date_start < older time.
"""
resource_calendar_obj = self.pool.get('resource.calendar')
uom_obj = self.pool.get('product.uom')
resource_obj = self.pool.get('resource.resource')
calendar_id = phase.project_id.resource_calendar_id.id
cal_obj = self.pool.get('resource.calendar')
calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)])
if resource_id:
cal_id = resource_obj.browse(cr, uid, resource_id[0]).calendar_id.id
# cal_id = resource_obj.browse(cr, uid, resource_id[0], context=context).calendar_id.id
res = resource_obj.read(cr, uid, resource_id[0], ['calendar_id'], context=context)[0]
cal_id = res.get('calendar_id', False) and res.get('calendar_id')[0] or False
if cal_id:
calendar_id = cal_id
default_uom_id = uom_obj.search(cr, uid, [('name', '=', 'Hour')])[0]
default_uom_id = uom_obj.search(cr, uid, [('name', '=', 'Hour')], context=context)[0]
avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id or False, date_end, avg_hours or 0.0, resource_id or False)
work_times = cal_obj.interval_min_get(cr, uid, calendar_id, date_end, avg_hours or 0.0, resource_id and resource_id[0] or False)
dt_start = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S')
self.write(cr, uid, [phase.id], {'date_start': dt_start, 'date_end': date_end.strftime('%Y-%m-%d %H:%M:%S')})
self.write(cr, uid, [phase.id], {'date_start': dt_start, 'date_end': date_end.strftime('%Y-%m-%d %H:%M:%S')}, context=context)
def _check_date_end(self, cr, uid, phase, date_start, context=None):
def _check_date_end(self, cr, uid, phase, date_start, context={}):
"""
Check And Compute date_end of phase if change in date_end > older time.
"""
resource_calendar_obj = self.pool.get('resource.calendar')
uom_obj = self.pool.get('product.uom')
resource_obj = self.pool.get('resource.resource')
calendar_id = phase.project_id.resource_calendar_id.id
resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)])
cal_obj = self.pool.get('resource.calendar')
calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)], context=context)
if resource_id:
cal_id = resource_obj.browse(cr, uid, resource_id[0]).calendar_id.id
# cal_id = resource_obj.browse(cr, uid, resource_id[0], context=context).calendar_id.id
res = resource_obj.read(cr, uid, resource_id[0], ['calendar_id'], context=context)[0]
cal_id = res.get('calendar_id', False) and res.get('calendar_id')[0] or False
if cal_id:
calendar_id = cal_id
default_uom_id = uom_obj.search(cr, uid, [('name', '=', 'Hour')])[0]
default_uom_id = uom_obj.search(cr, uid, [('name', '=', 'Hour')], context=context)[0]
avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id or False, date_start, avg_hours or 0.0, resource_id or False)
work_times = cal_obj.interval_get(cr, uid, calendar_id, date_start, avg_hours or 0.0, resource_id and resource_id[0] or False)
dt_end = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
self.write(cr, uid, [phase.id], {'date_start': date_start.strftime('%Y-%m-%d %H:%M:%S'), 'date_end': dt_end})
self.write(cr, uid, [phase.id], {'date_start': date_start.strftime('%Y-%m-%d %H:%M:%S'), 'date_end': dt_end}, context=context)
def write(self, cr, uid, ids, vals, context=None):
if not context:
context = {}
if context.get('scheduler',False):
return super(project_phase, self).write(cr, uid, ids, vals, context=context)
# Consider calendar and efficiency if the phase is performed by a resource
# otherwise consider the project's working calendar
phase = self.browse(cr, uid, ids[0])
def write(self, cr, uid, ids, vals, context={}):
resource_calendar_obj = self.pool.get('resource.calendar')
resource_obj = self.pool.get('resource.resource')
uom_obj = self.pool.get('product.uom')
resource_id = False
calendar_id = phase.project_id.resource_calendar_id.id
resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)])
if not context:
context = {}
if context.get('scheduler',False):
return super(project_phase, self).write(cr, uid, ids, vals, context=context)
# Consider calendar and efficiency if the phase is performed by a resource
# otherwise consider the project's working calendar
phase = self.browse(cr, uid, ids[0], context=context)
calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)],context=context)
if resource_id:
cal_id = resource_obj.browse(cr, uid, resource_id[0]).calendar_id.id
cal_id = resource_obj.browse(cr, uid, resource_id[0], context=context).calendar_id.id
if cal_id:
calendar_id = cal_id
default_uom_id = uom_obj.search(cr, uid, [('name', '=', 'Hour')])[0]
@@ -194,25 +190,20 @@ class project_phase(osv.osv):
# Change the date_start and date_end
# for previous and next phases respectively based on valid condition
if vals.get('date_start'):
if vals['date_start'] < phase.date_start:
if vals.get('date_start', False) and vals['date_start'] < phase.date_start:
dt_start = mx.DateTime.strptime(vals['date_start'],'%Y-%m-%d %H:%M:%S')
work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id or False, dt_start, avg_hours or 0.0, resource_id or False)
vals['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
super(project_phase, self).write(cr, uid, ids, vals, context=context)
work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id, dt_start, avg_hours or 0.0, resource_id and resource_id[0] or False)
if work_times:
vals['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
for prv_phase in phase.previous_phase_ids:
self._check_date_start(cr, uid, prv_phase, dt_start)
if vals.get('date_end'):
if vals['date_end'] > phase.date_end:
self._check_date_start(cr, uid, prv_phase, dt_start, context=context)
if vals.get('date_end', False) and vals['date_end'] > phase.date_end:
dt_end = mx.DateTime.strptime(vals['date_end'],'%Y-%m-%d %H:%M:%S')
work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id or False, dt_end, avg_hours or 0.0, resource_id or False)
vals['date_start'] = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S')
super(project_phase, self).write(cr, uid, ids, vals, context=context)
work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id, dt_end, avg_hours or 0.0, resource_id and resource_id[0] or False)
if work_times:
vals['date_start'] = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S')
for next_phase in phase.next_phase_ids:
self._check_date_end(cr, uid, next_phase, dt_end)
self._check_date_end(cr, uid, next_phase, dt_end, context=context)
return super(project_phase, self).write(cr, uid, ids, vals, context=context)
def set_draft(self, cr, uid, ids, *args):
@@ -276,66 +267,70 @@ class task(osv.osv):
def onchange_planned(self, cr, uid, ids, project, user_id=False, planned=0.0, effective=0.0, date_start=None, occupation_rate=0.0):
result = {}
resource = False
resource_obj = self.pool.get('resource.resource')
project_pool = self.pool.get('project.project')
resource_calendar = self.pool.get('resource.calendar')
if not project:
return {'value' : result}
if date_start:
resource_obj = self.pool.get('resource.resource')
project_pool = self.pool.get('project.project')
hrs = float(planned / float(occupation_rate))
calendar_id = project_pool.browse(cr, uid, project).resource_calendar_id.id
resource_calendar = self.pool.get('resource.calendar')
dt_start = mx.DateTime.strptime(date_start, '%Y-%m-%d %H:%M:%S')
resource_id = resource_obj.search(cr, uid, [('user_id','=',user_id)])
if resource_id:
resource = resource_obj.browse(cr, uid, resource_id)[0]
hrs = planned / (float(occupation_rate) * resource.time_efficiency)
if resource.calendar_id.id:
calendar_id = resource.calendar_id.id
work_times = resource_calendar.interval_get(cr, uid, calendar_id or False, dt_start, hrs or 0.0, resource_id or False)
result['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
resource_data = resource_obj.browse(cr, uid, resource_id)[0]
resource = resource_data.id
hrs = planned / (float(occupation_rate) * resource_data.time_efficiency)
if resource_data.calendar_id.id:
calendar_id = resource_data.calendar_id.id
work_times = resource_calendar.interval_get(cr, uid, calendar_id, dt_start, hrs or 0.0, resource or False)
if work_times:
result['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
result['remaining_hours'] = planned - effective
return {'value' : result}
def _check_date_start(self, cr, uid, task, date_end, context=None):
def _check_date_start(self, cr, uid, task, date_end, context={}):
"""
Check And Compute date_end of task if change in date_start < older time.
"""
resource_calendar_obj = self.pool.get('resource.calendar')
resource_obj = self.pool.get('resource.resource')
calendar_id = task.project_id.resource_calendar_id.id
calendar_id = task.project_id.resource_calendar_id and task.project_id.resource_calendar_id.id or False
hours = task.planned_hours / task.occupation_rate
resource_id = resource_obj.search(cr, uid, [('user_id', '=', task.user_id.id)])
resource_id = resource_obj.search(cr, uid, [('user_id', '=', task.user_id.id)], context=context)
if resource_id:
resource = resource_obj.browse(cr, uid, resource_id[0])
resource = resource_obj.browse(cr, uid, resource_id[0], context=context)
if resource.calendar_id.id:
calendar_id = resource.calendar_id.id
calendar_id = resource.calendar_id and resource.calendar_id.id or False
hours = task.planned_hours / (float(task.occupation_rate) * resource.time_efficiency)
work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id or False, date_end, hours or 0.0, resource_id or False)
work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id, date_end, hours or 0.0, resource_id and resource_id[0] or False)
dt_start = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S')
self.write(cr, uid, [task.id], {'date_start' : dt_start,'date_end' : date_end.strftime('%Y-%m-%d %H:%M:%S')})
def _check_date_end(self, cr, uid, task, date_start, context=None):
def _check_date_end(self, cr, uid, task, date_start, context={}):
"""
Check And Compute date_end of task if change in date_end > older time.
"""
resource_calendar_obj = self.pool.get('resource.calendar')
resource_obj = self.pool.get('resource.resource')
calendar_id = task.project_id.resource_calendar_id.id
calendar_id = task.project_id.resource_calendar_id and task.project_id.resource_calendar_id.id or False
hours = task.planned_hours / task.occupation_rate
resource_id = resource_obj.search(cr,uid,[('user_id', '=', task.user_id.id)])
resource_id = resource_obj.search(cr,uid,[('user_id', '=', task.user_id.id)], context=context)
if resource_id:
resource = resource_obj.browse(cr, uid, resource_id[0])
resource = resource_obj.browse(cr, uid, resource_id[0], context=context)
if resource.calendar_id.id:
calendar_id = resource.calendar_id.id
calendar_id = resource.calendar_id and resource.calendar_id.id or False
hours = task.planned_hours / (float(task.occupation_rate) * resource.time_efficiency)
work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id or False, date_start, hours or 0.0, resource_id or False)
work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id, date_start, hours or 0.0, resource_id and resource_id[0] or False)
dt_end = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
self.write(cr, uid, [task.id], {'date_start' : date_start.strftime('%Y-%m-%d %H:%M:%S'),'date_end' : dt_end})
def write(self, cr, uid, ids, vals, context=None):
self.write(cr, uid, [task.id], {'date_start': date_start.strftime('%Y-%m-%d %H:%M:%S'),'date_end' : dt_end}, context=context)
def write(self, cr, uid, ids, vals, context={}):
resource_calendar_obj = self.pool.get('resource.calendar')
resource_obj = self.pool.get('resource.resource')
if not context:
context = {}
if context.get('scheduler',False):
return super(task, self).write(cr, uid, ids, vals, context=context)
@@ -345,40 +340,33 @@ class task(osv.osv):
if isinstance(ids, list):
task_id = ids[0]
task_rec = self.browse(cr, uid, task_id, context=context)
resource_calendar_obj = self.pool.get('resource.calendar')
resource_obj = self.pool.get('resource.resource')
calendar_id = task_rec.project_id.resource_calendar_id.id
calendar_id = task_rec.project_id.resource_calendar_id and task_rec.project_id.resource_calendar_id.id or False
hrs = task_rec.planned_hours / task_rec.occupation_rate
resource_id = resource_obj.search(cr, uid, [('user_id', '=', task_rec.user_id.id)])
resource_id = resource_obj.search(cr, uid, [('user_id', '=', task_rec.user_id.id)], context=context)
if resource_id:
resource = resource_obj.browse(cr, uid, resource_id[0])
resource = resource_obj.browse(cr, uid, resource_id[0], context=context)
if resource.calendar_id.id:
calendar_id = resource.calendar_id.id
calendar_id = resource.calendar_id and resource.calendar_id.id or False
hrs = task_rec.planned_hours / (float(task_rec.occupation_rate) * resource.time_efficiency)
# Change the date_start and date_end
# for previous and next tasks respectively based on valid condition
if vals.get('date_start'):
if vals['date_start'] < task_rec.date_start:
dt_start = mx.DateTime.strptime(vals['date_start'], '%Y-%m-%d %H:%M:%S')
work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id or False, dt_start, hrs or 0.0, resource_id or False)
if vals.get('date_start', False) and vals['date_start'] < task_rec.date_start:
dt_start = mx.DateTime.strptime(vals['date_start'], '%Y-%m-%d %H:%M:%S')
work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id, dt_start, hrs or 0.0, resource.id or False)
if work_times:
vals['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
super(task, self).write(cr, uid, ids, vals, context=context)
for prv_task in task_rec.parent_ids:
self._check_date_start(cr, uid, prv_task, dt_start)
if vals.get('date_end'):
if vals['date_end'] > task_rec.date_end:
dt_end = mx.DateTime.strptime(vals['date_end'], '%Y-%m-%d %H:%M:%S')
work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id or False, dt_end, hrs or 0.0, resource_id or False)
for prv_task in task_rec.parent_ids:
self._check_date_start(cr, uid, prv_task, dt_start)
if vals.get('date_end', False) and vals['date_end'] > task_rec.date_end:
dt_end = mx.DateTime.strptime(vals['date_end'], '%Y-%m-%d %H:%M:%S')
work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id, dt_end, hrs or 0.0, resource.id or False)
if work_times:
vals['date_start'] = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S')
super(task, self).write(cr, uid, ids, vals, context=context)
for next_task in task_rec.child_ids:
self._check_date_end(cr, uid, next_task, dt_end)
for next_task in task_rec.child_ids:
self._check_date_end(cr, uid, next_task, dt_end)
return super(task, self).write(cr, uid, ids, vals, context=context)
task()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!--
Requests Links
-->
<!-- Requests Links -->
<record id="req_link_project" model="res.request.link">
<field name="name">Project</field>
<field name="object">project.project</field>
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<report auto="False" id="report_project_task_gantt" model="project.task" name="project.tasks.gantt" string="Gantt Representation"/>
<report auto="False" id="report_project_project_gantt" model="project.project" name="project.project.gantt" string="Gantt Representation"/>
</data>
@@ -48,7 +48,7 @@
<field name="responsible_id"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="duration"/>
<field name="duration" widget="float_time"/>
<field name="product_uom"/>
</group>
<notebook colspan="4">
@@ -68,9 +68,9 @@
<field name="state" select="1"/>
<button string="Draft" name="set_draft" states="open" icon="gtk-indent"/>
<button string="Start Phase" name="set_open" states="pending,draft" icon="gtk-execute"/>
<button string="Cancel" name="set_cancel" states="draft,open,pending" icon="gtk-cancel"/>
<button string="Done" name="set_done" states="draft,pending,open" icon="gtk-jump-to"/>
<button string="Pending" name="set_pending" states="open" icon="gtk-media-pause"/>
<button string="Cancel" name="set_cancel" states="draft,open,pending" icon="gtk-cancel"/>
</group>
</page>
<page string="Other Info">
@@ -83,10 +83,10 @@
<separator string="Scheduling" colspan="2"/>
<field name="sequence"/>
</group>
<separator colspan="4" string="Next Phases"/>
<field colspan="4" name="next_phase_ids" nolabel="1"/>
<separator colspan="4" string="Previous Phases"/>
<field colspan="4" name="previous_phase_ids" nolabel="1"/>
<separator colspan="4" string="Next Phases"/>
<field colspan="4" name="next_phase_ids" nolabel="1"/>
</page>
<page string="Task Detail">
<separator colspan="4" string="Project's Tasks"/>
@@ -149,9 +149,10 @@
<field name="project_id" on_change="onchange_project(project_id)"/>
<field name="responsible_id"/>
<field name="date_start"/>
<field name="date_end"/>
<!--<field name="date_end"/>
<field name="duration"/>
<field name="product_uom"/>
<field name="product_uom"/>-->
<field name="state"/>
</tree>
</field>
</record>
@@ -190,17 +191,23 @@
<field name="arch" type="xml">
<search string="Project Phases">
<group colspan="4" col="20">
<filter string="Current" domain="[('state','in',('open','draft'))]" help="Draft, Open and Pending Phases" icon="terp-project" default="1"/>
<filter string="In Progress" domain="[('state','=','open')]" help="Open Phases" icon="terp-project"/>
<filter string="Pending" domain="[('state','=','pending')]" help="Pending Phases" icon="terp-project"/>
<field name="name"/>
<field name="project_id" widget="selection"/>
<field name="responsible_id">
<field name="project_id" widget="selection">
<filter domain="[('project_id.user_id','=',uid)]" help="My Projects" icon="terp-project"/>
</field>
<field name="responsible_id" widget="selection">
<filter domain="[('responsible_id','=',uid)]" help="My Phase" icon="gtk-execute" default="1"/>
</field>
<field name="date_start"/>
<field name="date_end"/>
<!--<field name="date_end"/>-->
</group>
<newline/>
<group expand="1" string="Group By..." colspan="4" col="20">
<filter string="Project" icon="terp-project" domain="[]" context="{'group_by':'project_id'}"/>
<filter string="State" icon="terp-project" domain="[]" context="{'group_by':'state'}"/>
<filter string="User" icon="terp-project" domain="[]" context="{'group_by':'responsible_id'}"/>
<filter string="Start Date" icon="terp-project" domain="[]" context="{'group_by':'date_start'}"/>
</group>
@@ -209,7 +216,7 @@
</record>
<record id="act_project_phase" model="ir.actions.act_window">
<field name="name">Project phases</field>
<field name="name">Project Phases</field>
<field name="res_model">project.phase</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form,calendar,gantt</field>
@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<wizard id="wizard_compute_phase" menu="False" model="project.phase" name="wizard.compute.phases" string="Compute Phase Scheduling"/>
<wizard id="wizard_schedule_task" menu="False" model="project.phase" name="phase.schedule.tasks" string="Schedule Tasks"/>
<wizard id="wizard_compute_task" model="project.task" menu="False" name="wizard.compute.tasks" string="Compute Task Scheduling"/>
<menuitem icon="terp-project" id="base.menu_main" name="Project Management" sequence="1"/>
<menuitem id="base.menu_pm_planning" name="Planning" parent="base.menu_main" sequence="3"/>
<menuitem
@@ -19,5 +21,6 @@
parent="base.menu_pm_planning"
type="wizard"
sequence="1"/>
</data>
</openerp>
@@ -18,14 +18,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import datetime
from resource.faces import *
from new import classobj
import wizard
import pooler
from tools.translate import _
import datetime
from resource.faces import *
from new import classobj
import working_calendar as wkcal
@@ -37,7 +36,7 @@ compute_form = """<?xml version="1.0" ?>
</form>"""
compute_fields = {
'project_id': {'string':'Project', 'type':'many2one', 'relation':'project.project'},
'project_id': {'string':'Project', 'type':'many2one', 'relation':'project.project', 'help': 'If you do not specify project then it will take All projects with state=draft, open, pending'},
}
@@ -50,7 +49,6 @@ class wizard_compute_phases(wizard.interface):
calendar_id -- working calendar of the project
"""
pool = pooler.get_pool(cr.dbname)
phase_obj = pool.get('project.phase')
resource_obj = pool.get('resource.resource')
@@ -60,13 +58,14 @@ class wizard_compute_phases(wizard.interface):
leaves = []
time_efficiency = 1.0
resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)])
if resource_id:
# Create a new resource object with
# all the attributes of the Resource Class
resource = resource_obj.browse(cr, uid, resource_id, context=context)[0]
time_efficiency = resource.time_efficiency
leaves = wkcal.compute_leaves(cr, uid, calendar_id or False , resource_id, resource.calendar_id.id)
phase_resource_obj = classobj(str(phase.responsible_id.name), (Resource,),
leaves = wkcal.compute_leaves(cr, uid, calendar_id , resource.id, resource.calendar_id.id)
phase_resource_obj = classobj((phase.responsible_id.name.encode('utf8')), (Resource,),
{'__doc__': phase.responsible_id.name,
'__name__': phase.responsible_id.name,
'vacation': tuple(leaves),
@@ -83,7 +82,7 @@ class wizard_compute_phases(wizard.interface):
# If project has working calendar then that
# else the default one would be considered
if calendar_id:
working_days = wkcal.compute_working_calendar(cr, uid, calendar_id)
working_days = wkcal.compute_working_calendar(cr, uid, calendar_id, context=context)
vacation = tuple(wkcal.compute_leaves(cr, uid, calendar_id))
def phase():
@@ -105,18 +104,20 @@ class wizard_compute_phases(wizard.interface):
end_date = e_date
date_start = end_date
# Write the calculated dates back
ctx = context.copy()
ctx.update({'scheduler': True})
phase_obj.write(cr, uid, [phase.id], {'date_start': start_date.strftime('%Y-%m-%d %H:%M:%S'),
'date_end': end_date.strftime('%Y-%m-%d %H:%M:%S')},
context={'scheduler': True
})
context=ctx)
# Recursive call till all the next phases scheduled
for phase in phase.next_phase_ids:
if phase.state in ['draft','open','pending']:
self._phase_schedule(cr, uid, phase, date_start, phase.project_id.resource_calendar_id.id or False)
id_cal = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
self._phase_schedule(cr, uid, phase, date_start, id_cal, context=context)
else:
continue
def _compute_date(self, cr, uid, data, context):
def _compute_date(self, cr, uid, data, context={}):
"""
Compute the phases for scheduling.
"""
@@ -132,24 +133,25 @@ class wizard_compute_phases(wizard.interface):
else: # Else take all the draft,open,pending states phases
phase_ids = phase_obj.search(cr, uid,[('state', 'in', ['draft', 'open', 'pending']),
('previous_phase_ids', '=', False)
])
], context=context)
phase_ids.sort()
phase_objs = phase_obj.browse(cr, uid, phase_ids, context=context)
for phase in phase_objs:
phases = phase_obj.browse(cr, uid, phase_ids, context=context)
for phase in phases:
start_date = phase.project_id.date_start
if not phase.project_id.date_start:
start_date = datetime.datetime.now().strftime("%Y-%m-%d")
start_dt = datetime.datetime.strftime((datetime.datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d %H:%M")
calendar_id = phase.project_id.resource_calendar_id.id
self._phase_schedule(cr, uid, phase, start_dt, calendar_id or False)
calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
self._phase_schedule(cr, uid, phase, start_dt, calendar_id, context=context)
return {}
def _open_phases_list(self, cr, uid, data, context):
"""
Return the scheduled phases list.
"""
mod_obj = pooler.get_pool(cr.dbname).get('ir.model.data')
act_obj = pooler.get_pool(cr.dbname).get('ir.actions.act_window')
pool = pooler.get_pool(cr.dbname)
mod_obj = pool.get('ir.model.data')
act_obj = pool.get('ir.actions.act_window')
result = mod_obj._get_id(cr, uid, 'project_long_term', 'act_project_phase')
id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id']
result = act_obj.read(cr, uid, [id], context=context)[0]
@@ -162,7 +164,7 @@ class wizard_compute_phases(wizard.interface):
states = {
'init': {
'actions': [],
'result': {'type':'form', 'arch':compute_form, 'fields':compute_fields, 'state':[
'result': {'type': 'form', 'arch': compute_form, 'fields': compute_fields, 'state':[
('end', 'Cancel'),
('compute', 'Compute')
@@ -170,7 +172,7 @@ class wizard_compute_phases(wizard.interface):
},
'compute': {
'actions': [_compute_date],
'result': {'type': 'action', 'action':_open_phases_list, 'state':'end'},
'result': {'type': 'action', 'action': _open_phases_list, 'state': 'end'},
},
}
wizard_compute_phases('wizard.compute.phases')
@@ -18,18 +18,17 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import wizard
import pooler
from tools.translate import _
import datetime
from resource.faces import *
from new import classobj
import operator
import working_calendar as wkcal
import wizard
import pooler
from tools.translate import _
compute_form = """<?xml version="1.0" ?>
<form string="Compute Scheduling of Tasks">
<field name="project_id" colspan="4"/>
@@ -41,7 +40,7 @@ success_msg = """<?xml version="1.0" ?>
</form>"""
compute_fields = {
'project_id': {'string':'Project', 'type':'many2one', 'relation':'project.project', 'required':'True'},
'project_id': {'string':'Project', 'type':'many2one', 'relation':'project.project', 'required':True},
}
class wizard_compute_tasks(wizard.interface):
@@ -62,8 +61,8 @@ class wizard_compute_tasks(wizard.interface):
])
if task_ids:
task_ids.sort()
task_objs = task_pool.browse(cr, uid, task_ids, context=context)
calendar_id = project.resource_calendar_id.id
tasks = task_pool.browse(cr, uid, task_ids, context=context)
calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
start_date = project.date_start
if not project.date_start:
start_date = datetime.datetime.now().strftime("%Y-%m-%d")
@@ -73,12 +72,13 @@ class wizard_compute_tasks(wizard.interface):
for user in project.members:
leaves = []
time_efficiency = 1.0
resource_id = resource_obj.search(cr, uid, [('user_id', '=', user.id)])
resource_id = resource_obj.search(cr, uid, [('user_id', '=', user.id)], context=context)
if resource_id:
resource = resource_obj.browse(cr, uid, resource_id, context=context)[0]
leaves = wkcal.compute_leaves(cr, uid, calendar_id or False , resource_id, resource.calendar_id.id)
time_efficiency = resource.time_efficiency
resources.append(classobj(str(user.name), (Resource,), {'__doc__': user.name,
# resource = resource_obj.browse(cr, uid, resource_id, context=context)[0]
resource = resource_obj.read(cr, uid, resource_id, ['calendar_id','time_efficiency'], context=context)[0]
leaves = wkcal.compute_leaves(cr, uid, calendar_id , resource_id[0], resource.get('calendar_id')[0])
time_efficiency = resource.get('time_efficiency')
resources.append(classobj((user.name.encode('utf8')), (Resource,), {'__doc__': user.name,
'__name__': user.name,
'vacation': tuple(leaves),
'efficiency': time_efficiency
@@ -105,20 +105,20 @@ class wizard_compute_tasks(wizard.interface):
try:
resource = reduce(operator.or_, resources)
except:
raise wizard.except_wizard(_('MemberError'), _('Project must have members assigned !'))
raise wizard.except_wizard(_('Error'), _('Project must have members assigned !'))
minimum_time_unit = 1
if calendar_id: # If project has calendar
working_days = wkcal.compute_working_calendar(cr, uid, calendar_id)
vacation = tuple(wkcal.compute_leaves(cr, uid, calendar_id))
# Dynamic Creation of tasks
i = 0
for each_task in task_objs:
for each_task in tasks:
hours = str(each_task.planned_hours / each_task.occupation_rate)+ 'H'
if each_task.priority in priority_dict.keys():
priorty = priority_dict[each_task.priority]
if each_task.user_id:
for resource in resources:
if resource.__name__ == each_task.user_id.name:
if resource.__name__ == each_task.user_id.name: # check me!!
task = create_tasks(i, hours, priorty, resource)
else:
task = create_tasks(i, hours, priorty)
@@ -131,29 +131,30 @@ class wizard_compute_tasks(wizard.interface):
s_date = t.start.to_datetime()
e_date = t.end.to_datetime()
if loop_no == 0:
project_obj.write(cr, uid, [project_id], {'date' : e_date})
project_obj.write(cr, uid, [project_id], {'date' : e_date}, context=context)
else:
ctx = context.copy()
ctx.update({'scheduler': True})
user_id = user_obj.search(cr, uid, [('name', '=', t.booked_resource[0].__name__)])
task_pool.write(cr, uid, [task_objs[loop_no-1].id], {'date_start': s_date.strftime('%Y-%m-%d %H:%M:%S'),
task_pool.write(cr, uid, [tasks[loop_no-1].id], {'date_start': s_date.strftime('%Y-%m-%d %H:%M:%S'),
'date_deadline': e_date.strftime('%Y-%m-%d %H:%M:%S'),
'user_id': user_id[0]},
context={'scheduler': True
})
context=ctx)
loop_no +=1
return {}
states = {
'init': {
'actions': [],
'result': {'type':'form', 'arch':compute_form, 'fields':compute_fields, 'state':[
'result': {'type': 'form', 'arch': compute_form, 'fields': compute_fields, 'state': [
('end', 'Cancel'),
('compute', 'Compute')
]},
},
'compute': {
'actions': [_compute_date],
'result': {'type':'form','arch':success_msg,'fields':{}, 'state':[('end', 'Ok')]},
'result': {'type': 'form','arch': success_msg,'fields': {}, 'state': [('end', 'Ok')]},
}
}
wizard_compute_tasks('wizard.compute.tasks')
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -18,18 +18,17 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import wizard
import pooler
from tools.translate import _
import datetime
from resource.faces import *
from new import classobj
import operator
import working_calendar as wkcal
import wizard
import pooler
from tools.translate import _
success_msg = """<?xml version="1.0" ?>
<form string="Compute Scheduling of Tasks">
<label string="Task Scheduling completed successfully."/>
@@ -48,8 +47,9 @@ class wizard_schedule_task(wizard.interface):
resource_eff = res.time_efficiency
resource_cal = res.calendar_id.id
if resource_cal:
leaves = wkcal.compute_leaves(cr, uid, phase.project_id.resource_calendar_id.id or False, res.id, resource_cal)
resource_objs.append(classobj(str(res.user_id.name), (Resource,),
cal_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
leaves = wkcal.compute_leaves(cr, uid, cal_id, res.id, resource_cal, context=context)
resource_objs.append(classobj(res.user_id.name.encode('utf8'), (Resource,),
{'__doc__': res.user_id.name,
'__name__': res.user_id.name,
'vacation': tuple(leaves),
@@ -57,7 +57,7 @@ class wizard_schedule_task(wizard.interface):
}))
return resource_objs
def _compute_date(self, cr, uid, data, context):
def _compute_date(self, cr, uid, data, context={}):
"""
Schedule the tasks according to resource available and priority.
"""
@@ -101,7 +101,7 @@ class wizard_schedule_task(wizard.interface):
try:
resource = reduce(operator.or_, resources)
except:
raise wizard.except_wizard(_('ResourceError'), _('Phase must have resources assigned !'))
raise wizard.except_wizard(_('Error'), _('Phase must have resources assigned !'))
minimum_time_unit = 1
if calendar_id: # If project has working calendar
working_days = wkcal.compute_working_calendar(cr, uid, calendar_id)
@@ -127,12 +127,13 @@ class wizard_schedule_task(wizard.interface):
s_date = t.start.to_datetime()
e_date = t.end.to_datetime()
if loop_no > 0:
ctx = context.copy()
ctx.update({'scheduler': True})
user_id = user_obj.search(cr, uid, [('name', '=', t.booked_resource[0].__name__)])
task_obj.write(cr, uid, [tasks[loop_no-1].id], {'date_start': s_date.strftime('%Y-%m-%d %H:%M:%S'),
'date_deadline': e_date.strftime('%Y-%m-%d %H:%M:%S'),
'user_id': user_id[0]},
context={'scheduler': True
})
context=ctx)
loop_no +=1
return {}
states = {
@@ -18,9 +18,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import datetime
import pooler
import datetime
def convert_timeformat(cr, uid, time_string, context={}):
""" Convert input time string: 8.5 to output time string 8:30."""
@@ -32,7 +32,7 @@ def convert_timeformat(cr, uid, time_string, context={}):
converted_string = hour_part + ':' + str(round_mins)[0:2]
return converted_string
def compute_leaves(cr, uid, calendar_id, resource_id=False, resource_calendar=False):
def compute_leaves(cr, uid, calendar_id, resource_id=False, resource_calendar=False, context={}):
"""Compute the leaves from the working calendar of the resource.
@@ -49,21 +49,21 @@ def compute_leaves(cr, uid, calendar_id, resource_id=False, resource_calendar=Fa
leave_ids = resource_calendar_leaves_obj.search(cr, uid, ['|', ('calendar_id', '=', calendar_id),
('calendar_id', '=', resource_calendar),
('resource_id', '=', resource_id)
])
], context=context)
else:
leave_ids = resource_calendar_leaves_obj.search(cr, uid, [('calendar_id', '=', calendar_id),
('resource_id', '=', False)
])
leaves = resource_calendar_leaves_obj.read(cr, uid, leave_ids, ['date_from', 'date_to'])
], context=context)
leaves = resource_calendar_leaves_obj.read(cr, uid, leave_ids, ['date_from', 'date_to'], context=context)
for i in range(len(leaves)):
dt_start = datetime.datetime.strptime(leaves[i]['date_from'], '%Y-%m-%d %H:%M:%S')
dt_end = datetime.datetime.strptime(leaves[i]['date_to'], '%Y-%m-%d %H:%M:%S')
no = dt_end - dt_start
[leave_list.append((dt_start + datetime.timedelta(days=x)).strftime('%Y-%m-%d')) for x in range(int(no.days + 1))]
leave_list.sort()
dt_start = datetime.datetime.strptime(leaves[i]['date_from'], '%Y-%m-%d %H:%M:%S')
dt_end = datetime.datetime.strptime(leaves[i]['date_to'], '%Y-%m-%d %H:%M:%S')
no = dt_end - dt_start
[leave_list.append((dt_start + datetime.timedelta(days=x)).strftime('%Y-%m-%d')) for x in range(int(no.days + 1))]
leave_list.sort()
return leave_list
def compute_working_calendar(cr, uid, calendar_id):
def compute_working_calendar(cr, uid, calendar_id, context={}):
"""Change the format of working calendar from 'Openerp' format to bring it into 'Faces' format.
@@ -80,8 +80,8 @@ def compute_working_calendar(cr, uid, calendar_id):
wk_time = {}
wktime_list = []
wktime_cal = []
week_ids = resource_week_obj.search(cr, uid, [('calendar_id', '=', calendar_id)])
weeks = resource_week_obj.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'])
week_ids = resource_week_obj.search(cr, uid, [('calendar_id', '=', calendar_id)], context=context)
weeks = resource_week_obj.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'], context=context)
# Convert time formats into appropriate format required
# and create a list like [('mon', '8:00-12:00'), ('mon', '13:00-18:00')]
for week in weeks:

Some files were not shown because too many files have changed in this diff Show More