Browse Source

[PRT] super_calendar: Ported to v8.0

pull/139/head
Alejandro Santana 9 years ago
parent
commit
5b136bd6ea
  1. 1
      __unported__/super_calendar/AUTHORS.txt
  2. 88
      __unported__/super_calendar/__openerp__.py
  3. 163
      __unported__/super_calendar/super_calendar.py
  4. 53
      super_calendar/README.rst
  5. 3
      super_calendar/__init__.py
  6. 49
      super_calendar/__openerp__.py
  7. 0
      super_calendar/data/cron_data.xml
  8. 0
      super_calendar/i18n/it.po
  9. 0
      super_calendar/i18n/ru.po
  10. 0
      super_calendar/i18n/super_calendar.pot
  11. 7
      super_calendar/models/__init__.py
  12. 235
      super_calendar/models/super_calendar.py
  13. 0
      super_calendar/security/ir.model.access.csv
  14. BIN
      super_calendar/static/description/meetings.png
  15. BIN
      super_calendar/static/description/month_calendar.png
  16. BIN
      super_calendar/static/description/phone_calls.png
  17. BIN
      super_calendar/static/description/week_calendar.png
  18. 65
      super_calendar/views/super_calendar_view.xml

1
__unported__/super_calendar/AUTHORS.txt

@ -1 +0,0 @@
Lorenzo Battistini <lorenzo.battistini@agilebg.com>

88
__unported__/super_calendar/__openerp__.py

@ -1,88 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
#
# 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 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/>.
#
##############################################################################
{
'name': "Super Calendar",
'version': '0.1',
'category': 'Generic Modules/Others',
'summary': 'This module allows to create configurable calendars.',
'description': """
This module allows to create configurable calendars.
Through the 'calendar configurator' object, you can specify which models have
to be merged in the super calendar. For each model, you have to define the
'description' and 'date_start' fields at least. Then you can define 'duration'
and the 'user_id' fields.
The 'super.calendar' object contains the the merged calendars. The
'super.calendar' can be updated by 'ir.cron' or manually.
Configuration
=============
After installing the module you can go to
Super calendar Configuration Configurators
and create a new configurator. For instance, if you want to see meetings and
phone calls, you can create the following lines
.. image:: http://planet.domsense.com/wp-content/uploads/2012/04/meetings.png
:width: 400 px
.. image:: http://planet.domsense.com/wp-content/uploads/2012/04/phone_calls.png
:width: 400 px
Then, you can use the Generate Calendar button or wait for the scheduled
action (Generate Calendar Records) to be run.
When the calendar is generated, you can visualize it by the super calendar main menu.
Here is a sample monthly calendar:
.. image:: http://planet.domsense.com/wp-content/uploads/2012/04/month_calendar.png
:width: 400 px
And here is the weekly one:
.. image:: http://planet.domsense.com/wp-content/uploads/2012/04/week_calendar.png
:width: 400 px
As you can see, several filters are available. A typical usage consists in
filtering by Configurator (if you have several configurators,
Scheduled calls and meetings can be one of them) and by your user.
Once you filtered, you can save the filter as Advanced filter or even
add it to a dashboard.
""",
'author': "Agile Business Group,Odoo Community Association (OCA)",
'website': 'http://www.agilebg.com',
'license': 'AGPL-3',
'depends': ['base'],
"data": [
'super_calendar_view.xml',
'cron_data.xml',
'security/ir.model.access.csv',
],
'demo': [],
'test': [],
'installable': False,
'application': True,
'auto_install': False,
}

163
__unported__/super_calendar/super_calendar.py

@ -1,163 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
#
# 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 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 openerp.osv import fields, orm
from openerp.tools.translate import _
import logging
from mako.template import Template
from datetime import datetime
from openerp import tools
from openerp.tools.safe_eval import safe_eval
def _models_get(self, cr, uid, context=None):
obj = self.pool.get('ir.model')
ids = obj.search(cr, uid, [])
res = obj.read(cr, uid, ids, ['model', 'name'], context)
return [(r['model'], r['name']) for r in res]
class super_calendar_configurator(orm.Model):
_logger = logging.getLogger('super.calendar')
_name = 'super.calendar.configurator'
_columns = {
'name': fields.char('Name', size=64, required=True),
'line_ids': fields.one2many('super.calendar.configurator.line', 'configurator_id', 'Lines'),
}
def generate_calendar_records(self, cr, uid, ids, context=None):
configurator_ids = self.search(cr, uid, [])
super_calendar_pool = self.pool.get('super.calendar')
# removing old records
super_calendar_ids = super_calendar_pool.search(cr, uid, [], context=context)
super_calendar_pool.unlink(cr, uid, super_calendar_ids, context=context)
for configurator in self.browse(cr, uid, configurator_ids, context):
for line in configurator.line_ids:
current_pool = self.pool.get(line.name.model)
current_record_ids = current_pool.search(
cr,
uid,
line.domain and safe_eval(line.domain) or [],
context=context)
for current_record_id in current_record_ids:
current_record = current_pool.browse(cr, uid, current_record_id, context=context)
if (line.user_field_id and
current_record[line.user_field_id.name] and
current_record[line.user_field_id.name]._table_name != 'res.users'):
raise orm.except_orm(
_('Error'),
_("The 'User' field of record %s (%s) does not refer to res.users")
% (current_record[line.description_field_id.name], line.name.model))
if (((line.description_field_id and current_record[line.description_field_id.name]) or
line.description_code) and
current_record[line.date_start_field_id.name]):
duration = False
if (not line.duration_field_id and
line.date_stop_field_id and
current_record[line.date_start_field_id.name] and
current_record[line.date_stop_field_id.name]):
date_start = datetime.strptime(
current_record[line.date_start_field_id.name],
tools.DEFAULT_SERVER_DATETIME_FORMAT
)
date_stop = datetime.strptime(
current_record[line.date_stop_field_id.name],
tools.DEFAULT_SERVER_DATETIME_FORMAT
)
duration = (date_stop - date_start).total_seconds() / 3600
elif line.duration_field_id:
duration = current_record[line.duration_field_id.name]
if line.description_type != 'code':
name = current_record[line.description_field_id.name]
else:
parse_dict = {'o': current_record}
mytemplate = Template(line.description_code)
name = mytemplate.render(**parse_dict)
super_calendar_values = {
'name': name,
'model_description': line.description,
'date_start': current_record[line.date_start_field_id.name],
'duration': duration,
'user_id': (
line.user_field_id and
current_record[line.user_field_id.name] and
current_record[line.user_field_id.name].id or
False
),
'configurator_id': configurator.id,
'res_id': line.name.model+','+str(current_record['id']),
'model_id': line.name.id,
}
super_calendar_pool.create(cr, uid, super_calendar_values, context=context)
self._logger.info('Calendar generated')
return True
class super_calendar_configurator_line(orm.Model):
_name = 'super.calendar.configurator.line'
_columns = {
'name': fields.many2one('ir.model', 'Model', required=True),
'description': fields.char('Description', size=128, required=True),
'domain': fields.char('Domain', size=512),
'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'),
'description_type': fields.selection([
('field', 'Field'),
('code', 'Code'),
], string="Description Type"),
'description_field_id': fields.many2one(
'ir.model.fields', 'Description field',
domain="[('model_id', '=', name),('ttype', '=', 'char')]"),
'description_code': fields.text(
'Description field',
help="Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'"
),
'date_start_field_id': fields.many2one(
'ir.model.fields', 'Start date field',
domain="['&','|',('ttype', '=', 'datetime'),('ttype', '=', 'date'),('model_id', '=', name)]",
required=True),
'date_stop_field_id': fields.many2one(
'ir.model.fields', 'End date field',
domain="['&',('ttype', '=', 'datetime'),('model_id', '=', name)]"
),
'duration_field_id': fields.many2one(
'ir.model.fields', 'Duration field',
domain="['&',('ttype', '=', 'float'),('model_id', '=', name)]"),
'user_field_id': fields.many2one(
'ir.model.fields', 'User field',
domain="['&',('ttype', '=', 'many2one'),('model_id', '=', name)]"),
}
class super_calendar(orm.Model):
_name = 'super.calendar'
_columns = {
'name': fields.char('Description', size=512, required=True),
'model_description': fields.char('Model Description', size=128, required=True),
'date_start': fields.datetime('Start date', required=True),
'duration': fields.float('Duration'),
'user_id': fields.many2one('res.users', 'User'),
'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'),
'res_id': fields.reference('Resource', selection=_models_get, size=128),
'model_id': fields.many2one('ir.model', 'Model'),
}

53
super_calendar/README.rst

@ -0,0 +1,53 @@
SUPER CALENDAR
==============
This module allows to create configurable calendars.
Through the 'calendar configurator' object, you can specify which models have
to be merged in the super calendar. For each model, you have to define the
'description' and 'date_start' fields at least. Then you can define 'duration'
and the 'user_id' fields.
The 'super.calendar' object contains the the merged calendars. The
'super.calendar' can be updated by 'ir.cron' or manually.
Configuration
=============
After installing the module you can go to
*Super calendar > Configuration > Configurators*
and create a new configurator. For instance, if you want to see meetings and
phone calls, you can create the following lines
Meetings:
.. image:: super_calendar/static/description/meetings.png
:width: 400 px
Phonecalls:
.. image:: super_calendar/static/description/phone_calls.png
:width: 400 px
Then, you can use the 'Generate Calendar' button or wait for the scheduled
action (‘Generate Calendar Records’) to be run.
When the calendar is generated, you can visualize it by the 'super calendar' main menu.
Here is a sample monthly calendar:
.. image:: super_calendar/static/description/month_calendar.png
:width: 400 px
And here is the weekly one:
.. image:: super_calendar/static/description/week_calendar.png
:width: 400 px
As you can see, several filters are available. A typical usage consists in
filtering by 'Configurator' (if you have several configurators,
'Scheduled calls and meetings' can be one of them) and by your user.
Once you filtered, you can save the filter as 'Advanced filter' or even
add it to a dashboard.

3
__unported__/super_calendar/__init__.py → super_calendar/__init__.py

@ -18,4 +18,5 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import super_calendar
from . import models

49
super_calendar/__openerp__.py

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) All rights reserved:
# (c) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
# Lorenzo Battistini <lorenzo.battistini@agilebg.com>
# (c) 2012 Domsense srl (<http://www.domsense.com>)
# (c) 2015 Anubía, soluciones en la nube,SL (http://www.anubia.es)
# Alejandro Santana <alejandrosantana@anubia.es>
#
# 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
#
##############################################################################
{
'name': 'Super Calendar',
'version': '0.2',
'category': 'Generic Modules/Others',
'summary': 'This module allows to create configurable calendars.',
'author': ('Agile Business Group, '
'Alejandro Santana <alejandrosantana@anubia.es>, '
'Odoo Community Association (OCA)'),
'website': 'http://www.agilebg.com',
'license': 'AGPL-3',
'depends': [
'base',
'web_calendar',
],
'data': [
'views/super_calendar_view.xml',
'data/cron_data.xml',
'security/ir.model.access.csv',
],
'demo': [],
'test': [],
'installable': True,
'application': True,
'auto_install': False,
}

0
__unported__/super_calendar/cron_data.xml → super_calendar/data/cron_data.xml

0
__unported__/super_calendar/i18n/it.po → super_calendar/i18n/it.po

0
__unported__/super_calendar/i18n/ru.po → super_calendar/i18n/ru.po

0
__unported__/super_calendar/i18n/super_calendar.pot → super_calendar/i18n/super_calendar.pot

7
super_calendar/models/__init__.py

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
################################################################
# License, author and contributors information in: #
# __openerp__.py file at the root folder of this module. #
################################################################
from . import super_calendar

235
super_calendar/models/super_calendar.py

@ -0,0 +1,235 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Odoo, Open Source Management Solution
#
# Copyright (c) All rights reserved:
# (c) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
# (c) 2012 Domsense srl (<http://www.domsense.com>)
# (c) 2015 Anubía, soluciones en la nube,SL (http://www.anubia.es)
# Alejandro Santana <alejandrosantana@anubia.es>
#
# 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 openerp import models, fields, api
from openerp.tools.translate import _
from mako.template import Template
from datetime import datetime
from openerp import tools
from openerp.tools.safe_eval import safe_eval
import logging
def _models_get(self):
model_obj = self.env['ir.model']
model_ids = model_obj.search([])
return [(model.model, model.name) for model in model_ids]
class super_calendar_configurator(models.Model):
_logger = logging.getLogger(__name__)
_name = 'super.calendar.configurator'
name = fields.Char(
string='Name',
size=64,
required=True,
)
line_ids = fields.One2many(
comodel_name='super.calendar.configurator.line',
inverse_name='configurator_id',
string='Lines',
)
@api.multi
def generate_calendar_records(self):
configurator_ids = self.search([])
super_calendar_pool = self.env['super.calendar']
# Remove old records
super_calendar_ids = super_calendar_pool.search([])
super_calendar_ids.unlink()
# Rebuild all calendar records
for configurator in configurator_ids:
for line in configurator.line_ids:
current_pool = self.env[line.name.model]
domain = line.domain and safe_eval(line.domain) or []
current_record_ids = current_pool.search(domain)
for cur_rec in current_record_ids:
f_user = line.user_field_id and line.user_field_id.name
f_descr = (line.description_field_id and
line.description_field_id.name)
f_date_start = (line.date_start_field_id and
line.date_start_field_id.name)
f_date_stop = (line.date_stop_field_id and
line.date_stop_field_id.name)
f_duration = (line.duration_field_id and
line.duration_field_id.name)
if (f_user and
cur_rec[f_user] and
cur_rec[f_user]._model._name != 'res.users'):
raise orm.except_orm(
_('Error'),
_("The 'User' field of record %s (%s) "
"does not refer to res.users")
% (cur_rec[f_descr], line.name.model))
if (((f_descr and cur_rec[f_descr]) or
line.description_code) and
cur_rec[f_date_start]):
duration = False
if (not line.duration_field_id and
line.date_stop_field_id and
cur_rec[f_date_start] and
cur_rec[f_date_stop]):
date_start = datetime.strptime(
cur_rec[f_date_start],
tools.DEFAULT_SERVER_DATETIME_FORMAT
)
date_stop = datetime.strptime(
cur_rec[f_date_stop],
tools.DEFAULT_SERVER_DATETIME_FORMAT
)
date_diff = (date_stop - date_start)
duration = date_diff.total_seconds() / 3600
elif line.duration_field_id:
duration = cur_rec[f_duration]
if line.description_type != 'code':
name = cur_rec[f_descr]
else:
parse_dict = {'o': cur_rec}
mytemplate = Template(line.description_code)
name = mytemplate.render(**parse_dict)
super_calendar_values = {
'name': name,
'model_description': line.description,
'date_start': cur_rec[f_date_start],
'duration': duration,
'user_id': (
f_user and
cur_rec[f_user] and
cur_rec[f_user].id or
False
),
'configurator_id': configurator.id,
'res_id': line.name.model+','+str(cur_rec['id']),
'model_id': line.name.id,
}
super_calendar_pool.create(super_calendar_values)
self._logger.info('Calendar generated')
return True
class super_calendar_configurator_line(models.Model):
_name = 'super.calendar.configurator.line'
name = fields.Many2one(
comodel_name='ir.model',
string='Model',
required=True,
)
description = fields.Char(
string='Description',
size=128,
required=True,
)
domain = fields.Char(
string='Domain',
size=512,
)
configurator_id = fields.Many2one(
comodel_name='super.calendar.configurator',
string='Configurator',
)
description_type = fields.Selection(
[('field', 'Field'),
('code', 'Code')],
string="Description Type",
)
description_field_id = fields.Many2one(
comodel_name='ir.model.fields',
string='Description field',
domain="[('model_id', '=', name), ('ttype', '=', 'char')]",
)
description_code = fields.Text(
string='Description field',
help=("Use '${o}' to refer to the involved object. "
"E.g.: '${o.project_id.name}'"),
)
date_start_field_id = fields.Many2one(
comodel_name='ir.model.fields',
string='Start date field',
domain=("['&','|',('ttype', '=', 'datetime'),('ttype', '=', 'date'),"
"('model_id', '=', name)]"),
required=True,
)
date_stop_field_id = fields.Many2one(
comodel_name='ir.model.fields',
string='End date field',
domain="['&',('ttype', '=', 'datetime'),('model_id', '=', name)]"
)
duration_field_id = fields.Many2one(
comodel_name='ir.model.fields',
string='Duration field',
domain="['&',('ttype', '=', 'float'), ('model_id', '=', name)]",
)
user_field_id = fields.Many2one(
comodel_name='ir.model.fields',
string='User field',
domain="['&', ('ttype', '=', 'many2one'), ('model_id', '=', name)]",
)
class super_calendar(models.Model):
_name = 'super.calendar'
name = fields.Char(
string='Description',
size=512,
required=True,
)
model_description = fields.Char(
string='Model Description',
size=128,
required=True,
)
date_start = fields.Datetime(
string='Start date',
required=True,
)
duration = fields.Float(
string='Duration'
)
user_id = fields.Many2one(
comodel_name='res.users',
string='User',
)
configurator_id = fields.Many2one(
comodel_name='super.calendar.configurator',
string='Configurator',
)
res_id = fields.Reference(
selection=_models_get,
string='Resource',
size=128,
)
model_id = fields.Many2one(
comodel_name='ir.model',
string='Model',
)

0
__unported__/super_calendar/security/ir.model.access.csv → super_calendar/security/ir.model.access.csv

BIN
super_calendar/static/description/meetings.png

After

Width: 962  |  Height: 374  |  Size: 25 KiB

BIN
super_calendar/static/description/month_calendar.png

After

Width: 1064  |  Height: 536  |  Size: 70 KiB

BIN
super_calendar/static/description/phone_calls.png

After

Width: 960  |  Height: 322  |  Size: 26 KiB

BIN
super_calendar/static/description/week_calendar.png

After

Width: 1062  |  Height: 566  |  Size: 78 KiB

65
__unported__/super_calendar/super_calendar_view.xml → super_calendar/views/super_calendar_view.xml

@ -2,7 +2,7 @@
<openerp>
<data>
<!-- configurator -->
<!-- Configurator -->
<record model="ir.ui.view" id="super_calendar_configurator_tree">
<field name="name">super_calendar_configurator_tree</field>
@ -24,24 +24,33 @@
<field name="line_ids" nolabel="1" colspan="4">
<tree string="Lines">
<field name="name"/>
<field name="description"/>
<field name="domain"/>
</tree>
<form string="Line">
<field name="name"/>
<field name="description"/>
<field name="domain"/>
<field name="date_start_field_id"/>
<field name="duration_field_id"/>
<field name="date_stop_field_id" attrs="{'readonly':[('duration_field_id','!=',False)]}"/>
<field name="user_field_id"/>
<separator string="Description" colspan="4" />
<field name="description_type"/>
<newline/>
<field name="description_field_id" attrs="{'required':[('description_type','!=','code')], 'invisible':[('description_type','==','code')]}"/>
<group colspan="4" col="1" attrs="{'invisible':[('description_type','!=','code')]}">
<label string="Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'" />
<field name="description_code" nolabel="1" attrs="{'required':[('description_type','==','code')]}"/>
<group>
<group>
<field name="name"/>
<field name="description"/>
<field name="domain"/>
<field name="user_field_id"/>
</group>
<group>
<field name="date_start_field_id"/>
<field name="duration_field_id"/>
<field name="date_stop_field_id" attrs="{'readonly':[('duration_field_id','!=',False)]}"/>
</group>
</group>
<group string="Description">
<field name="description_type"/>
<newline/>
<field name="description_field_id" attrs="{'required':[('description_type','!=','code')], 'invisible':[('description_type','==','code')]}"/>
<group colspan="4" col="1" attrs="{'invisible':[('description_type','!=','code')]}">
<label string="Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'" />
<field name="description_code" nolabel="1" attrs="{'required':[('description_type','==','code')]}"/>
</group>
</group>
</form>
</field>
<newline/>
@ -58,7 +67,7 @@
<field name="view_id" ref="super_calendar_configurator_tree"/>
</record>
<!-- calendar -->
<!-- Calendar -->
<record model="ir.ui.view" id="super_calendar_tree">
<field name="name">super_calendar_tree</field>
@ -81,16 +90,20 @@
<field name="name">super_calendar_form</field>
<field name="model">super.calendar</field>
<field name="arch" type="xml">
<form string="Configurator">
<field name="name" readonly="1"/>
<field name="date_start" readonly="1"/>
<!--<field name="date_stop" readonly="1"/>-->
<field name="duration" readonly="1"/>
<field name="user_id" readonly="1"/>
<field name="configurator_id" readonly="1"/>
<field name="model_id" readonly="1"/>
<field name="model_description" readonly="1"/>
<field name="res_id"/>
<form string="Calendar">
<sheet>
<group>
<field name="name" readonly="1"/>
<field name="date_start" readonly="1"/>
<!--<field name="date_stop" readonly="1"/>-->
<field name="duration" readonly="1"/>
<field name="user_id" readonly="1"/>
<field name="configurator_id" readonly="1"/>
<field name="model_id" readonly="1"/>
<field name="model_description" readonly="1"/>
<field name="res_id"/>
</group>
</sheet>
</form>
</field>
</record>
Loading…
Cancel
Save