diff --git a/addons/crm/doc/crm_kanban_avatar.rst b/addons/crm/doc/crm_kanban_avatar.rst deleted file mode 100644 index 90998b0b1b9..00000000000 --- a/addons/crm/doc/crm_kanban_avatar.rst +++ /dev/null @@ -1,4 +0,0 @@ -CRM kanban avatar specs -======================= - -Kanban view of opportunities has been updated to use the newly-introduced avatar_mini field of res.users. The avatar is placed in the right-side of the containing kanban box. diff --git a/addons/crm/doc/index.rst b/addons/crm/doc/index.rst deleted file mode 100644 index b67e59ac1e5..00000000000 --- a/addons/crm/doc/index.rst +++ /dev/null @@ -1,6 +0,0 @@ -:orphan: - -CRM module documentation -======================== - -.. include:: index.rst.inc diff --git a/addons/crm/doc/index.rst.inc b/addons/crm/doc/index.rst.inc deleted file mode 100644 index 42b8c576854..00000000000 --- a/addons/crm/doc/index.rst.inc +++ /dev/null @@ -1,8 +0,0 @@ - -CRM Module -'''''''''' - -.. toctree:: - :maxdepth: 1 - - crm_kanban_avatar diff --git a/addons/event/__openerp__.py b/addons/event/__openerp__.py index 06252001c83..ea0e4316ef5 100644 --- a/addons/event/__openerp__.py +++ b/addons/event/__openerp__.py @@ -53,6 +53,7 @@ Note that: ], 'demo_xml': ['event_demo.xml'], 'test': ['test/process/event_draft2done.yml'], + 'css': ['static/src/css/event.css'], 'installable': True, 'application': True, 'auto_install': False, diff --git a/addons/event/event.py b/addons/event/event.py index 133d29281f1..ce72dadb2cc 100644 --- a/addons/event/event.py +++ b/addons/event/event.py @@ -148,9 +148,28 @@ class event_event(osv.osv): number = reg_done elif field == 'register_prospect': number = reg_draft + elif field == 'register_avail': + #the number of ticket is unlimited if the event.register_max field is not set. + #In that cas we arbitrary set it to 9999, it is used in the kanban view to special case the display of the 'subscribe' button + number = event.register_max - reg_open if event.register_max != 0 else 9999 res[event.id][field] = number return res + def _subscribe_fnc(self, cr, uid, ids, fields, args, context=None): + """This functional fields compute if the current user (uid) is already subscribed or not to the event passed in parameter (ids) + """ + register_pool = self.pool.get('event.registration') + res = {} + for event in self.browse(cr, uid, ids, context=context): + res[event.id] = False + curr_reg_id = register_pool.search(cr, uid, [('user_id', '=', uid), ('event_id', '=' ,event.id)]) + if curr_reg_id: + for reg in register_pool.browse(cr, uid, curr_reg_id, context=context): + if reg.state in ('open','done'): + res[event.id]= True + continue + return res + _columns = { 'name': fields.char('Name', size=64, required=True, translate=True, readonly=False, states={'done': [('readonly', True)]}), 'user_id': fields.many2one('res.users', 'Responsible User', readonly=False, states={'done': [('readonly', True)]}), @@ -158,13 +177,14 @@ class event_event(osv.osv): 'register_max': fields.integer('Maximum Registrations', help="You can for each event define a maximum registration level. If you have too much registrations you are not able to confirm your event. (put 0 to ignore this rule )", readonly=True, states={'draft': [('readonly', False)]}), 'register_min': fields.integer('Minimum Registrations', help="You can for each event define a minimum registration level. If you do not enough registrations you are not able to confirm your event. (put 0 to ignore this rule )", readonly=True, states={'draft': [('readonly', False)]}), 'register_current': fields.function(_get_register, string='Confirmed Registrations', multi='register_numbers'), + 'register_avail': fields.function(_get_register, string='Available Registrations', multi='register_numbers',type='integer'), 'register_prospect': fields.function(_get_register, string='Unconfirmed Registrations', multi='register_numbers'), 'register_attended': fields.function(_get_register, string='Attended Registrations', multi='register_numbers'), 'registration_ids': fields.one2many('event.registration', 'event_id', 'Registrations', readonly=False, states={'done': [('readonly', True)]}), 'date_begin': fields.datetime('Start Date', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'date_end': fields.datetime('End Date', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'state': fields.selection([ - ('draft', 'Draft'), + ('draft', 'Unconfirmed'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], @@ -182,6 +202,7 @@ class event_event(osv.osv): type='many2one', relation='res.country', string='Country', readonly=False, states={'done': [('readonly', True)]}), 'note': fields.text('Description', readonly=False, states={'done': [('readonly', True)]}), 'company_id': fields.many2one('res.company', 'Company', required=False, change_default=True, readonly=False, states={'done': [('readonly', True)]}), + 'is_subscribed' : fields.function(_subscribe_fnc, type="boolean", string='Subscribed'), } _defaults = { @@ -190,6 +211,22 @@ class event_event(osv.osv): 'user_id': lambda obj, cr, uid, context: uid, } + def subscribe_to_event(self, cr, uid, ids, context=None): + register_pool = self.pool.get('event.registration') + user_pool = self.pool.get('res.users') + user = user_pool.browse(cr, uid, uid, context=context) + curr_reg_ids = register_pool.search(cr, uid, [('user_id', '=', user.id), ('event_id', '=' , ids[0])]) + #the subscription is done with UID = 1 because in case we share the kanban view, we want anyone to be able to subscribe + if not curr_reg_ids: + curr_reg_ids = [register_pool.create(cr, 1, {'event_id': ids[0] ,'email': user.user_email, 'name':user.name, 'user_id': user.id,})] + return register_pool.confirm_registration(cr, 1, curr_reg_ids, context=context) + + def unsubscribe_to_event(self, cr, uid, ids, context=None): + register_pool = self.pool.get('event.registration') + #the unsubscription is done with UID = 1 because in case we share the kanban view, we want anyone to be able to unsubscribe + curr_reg_ids = register_pool.search(cr, 1, [('user_id', '=', uid), ('event_id', '=', ids[0])]) + return register_pool.button_reg_cancel(cr, 1, curr_reg_ids, context=context) + def _check_closing_date(self, cr, uid, ids, context=None): for event in self.browse(cr, uid, ids, context=context): if event.date_end < event.date_begin: @@ -233,19 +270,18 @@ class event_registration(osv.osv): 'log_ids': fields.one2many('mail.message', 'res_id', 'Logs', domain=[('email_from', '=', False),('model','=',_name)]), 'event_end_date': fields.related('event_id','date_end', type='datetime', string="Event End Date", readonly=True), 'event_begin_date': fields.related('event_id', 'date_begin', type='datetime', string="Event Start Date", readonly=True), - 'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}), + 'user_id': fields.many2one('res.users', 'Attendee', states={'done': [('readonly', True)]}), 'company_id': fields.related('event_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True, states={'draft':[('readonly',False)]}), 'state': fields.selection([('draft', 'Unconfirmed'), ('open', 'Confirmed'), ('cancel', 'Cancelled'), ('done', 'Attended')], 'State', - size=16, readonly=True) + size=16, readonly=True), } _defaults = { 'nb_register': 1, 'state': 'draft', - 'user_id': lambda self, cr, uid, ctx: uid, } _order = 'name, create_date desc' diff --git a/addons/event/event_demo.xml b/addons/event/event_demo.xml index 0dfbbf6de18..b76055cd0ff 100644 --- a/addons/event/event_demo.xml +++ b/addons/event/event_demo.xml @@ -32,7 +32,6 @@ Concert of Bon Jovi - 500 @@ -42,17 +41,15 @@ - 50 350 - Conference on ERP Buisness + Conference on ERP Business 200 - diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml index d93ba4cada9..d55a7980c3f 100644 --- a/addons/event/event_view.xml +++ b/addons/event/event_view.xml @@ -63,7 +63,7 @@ - + @@ -156,6 +156,71 @@ + + + + + event.event.kanban + event.event + kanban + + + + + + + + + + + + + +
+ +
+
+ + +
+
+
+
+

+

+ @
+ Organized by
+ Only + No ticket available. + + + + tickets + ticket + available. + + +

+ + + + + + + + +
+
+
+
+
+
+
@@ -199,6 +264,10 @@ + @@ -229,8 +298,8 @@ ir.actions.act_window event.event form - tree,form,calendar,graph - {"search_default_section_id": section_id} + kanban,calendar,tree,form,graph + {"search_default_upcoming":1} Event is the low level object used by meeting and others documents that should be synchronized with mobile devices or calendar applications through caldav. Most of the users should work in the Calendar menu, and not in the list of events. @@ -417,7 +486,7 @@ + action="action_registration" groups="event.group_event_manager,event.group_event_user"/> diff --git a/addons/event/security/event_security.xml b/addons/event/security/event_security.xml index e7a84337bac..fb29fffcca9 100644 --- a/addons/event/security/event_security.xml +++ b/addons/event/security/event_security.xml @@ -2,12 +2,21 @@ - - Event Manager + + Event + Helps you manage your Events. + 3 + + + + User + - - Event User + + Manager + + diff --git a/addons/event/static/src/css/event.css b/addons/event/static/src/css/event.css new file mode 100644 index 00000000000..a0f738e6323 --- /dev/null +++ b/addons/event/static/src/css/event.css @@ -0,0 +1,118 @@ +.oe_event_date{ + border-top-left-radius:3px; + border-top-right-radius:3px; + font-size: 48px; + height: auto; + font-weight: bold; + text-align: center; + margin-bottom:-7px; + color: #FFFFFF; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); + background-color: #8A89BA; +} +.oe_event_time{ + border-bottom-left-radius:3px; + border-bottom-right-radius:3px; + font-size: 12px; + text-align: center; + font-weight: bold; + color: #8A89BA; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); + background-color: #FFFFFF; +} +.oe_event_month_year{ + border-bottom-left-radius:3px; + border-bottom-right-radius:3px; + font-size: 12px; + text-align: center; + font-weight: bold; + color: #FFFFFF; + background-color: #8A89BA; +} +div.oe_fold_column{ + padding:0px !important; +} +.oe_event_button_subscribe { + display: inline-block; + border: 1px solid #ababab; + color: #404040; + font-size: 12px; + padding: 3px 10px; + text-align: center; + -o-background-size: 100% 100%; + -moz-background-size: 100% 100%; + -webkit-background-size: auto auto !important; + background-size: 100% 100%; + background: #d8d8d8 none; + background: none, -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#d8d8d8)); + background: none, -webkit-linear-gradient(#efefef, #d8d8d8); + background: none, -moz-linear-gradient(#efefef, #d8d8d8); + background: none, -o-linear-gradient(top, #efefef, #d8d8d8); + background: none, -khtml-gradient(linear, left top, left bottom, from(#efefef), to(#d8d8d8)); + background: -ms-linear-gradient(top, #efefef, #d8d8d8); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#efefef', endColorstr='#d8d8d8',GradientType=0 ); + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + -o-border-radius: 3px; + -ms-border-radius: 3px; + border-radius: 3px; + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; + -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); + -webkit-font-smoothing: antialiased; + outline: none; +} +.oe_event_button_unsubscribe { + display: inline-block; + border: 1px solid #AAA; + color: #404040; + font-size: 12px; + padding: 3px 10px; + text-align: center; + -o-background-size: 100% 100%; + -moz-background-size: 100% 100%; + -webkit-background-size: auto auto !important; + background-size: 100% 100%; + background: #AAA none; + background: none, -webkit-gradient(linear, left top, left bottom, from(#AAA), to(#AAA)); + background: none, -webkit-linear-gradient(#AAA, #AAA); + background: none, -moz-linear-gradient(#AAA, #AAA); + background: none, -o-linear-gradient(top, #AAA, #AAA); + background: none, -khtml-gradient(linear, left top, left bottom, from(#AAA), to(#AAA)); + background: -ms-linear-gradient(top, #AAA, #AAA); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#AAA, endColorstr='#AAA',GradientType=0 ); + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + -o-border-radius: 3px; + -ms-border-radius: 3px; + border-radius: 3px; + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; + -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); + -webkit-font-smoothing: antialiased; + outline: none; +} +.oe_event_button_subscribe:hover { + cursor: pointer; + background-size: 100% 100%; + /*background: #DC5F59 none;*/ + +} +.oe_event_button_unsubscribe:hover { + cursor: pointer; + background-size: 100% 100%; + background: #DC5F59 none; + } + .unsubscribe, .unsubscribe_button:hover span { + display: none; + background-color: #DC5F59 + } + .unsubscribe_button:hover .unsubscribe { + display: inline; + background-color: #DC5F59; + } + diff --git a/addons/event_sale/__openerp__.py b/addons/event_sale/__openerp__.py index f92a9eb5617..d8f689986e2 100644 --- a/addons/event_sale/__openerp__.py +++ b/addons/event_sale/__openerp__.py @@ -37,8 +37,8 @@ It defines a new kind of service products that offers you the possibility to cho 'depends': ['event','sale','sale_crm'], 'update_xml': [ 'event_sale_view.xml', - 'event_demo.xml', ], + 'demo_xml': ['event_demo.xml'], 'test':['test/confirm.yml'], 'installable': True, 'active': False, diff --git a/addons/hr/doc/hr_employee_img.rst b/addons/hr/doc/hr_employee_img.rst deleted file mode 100644 index 7c231b75fda..00000000000 --- a/addons/hr/doc/hr_employee_img.rst +++ /dev/null @@ -1,9 +0,0 @@ -HR photo specs -============== - -This revision modifies the photo for HR employees. Two fields now exist in the hr.employee model: - - photo_big, a binary field holding the image. It is base-64 encoded, and PIL-supported. It is automatically resized as an 540x450 px image. - - photo, a functional binary field holding an automatically resized version of the photo. Dimensions of the resized photo are 180x150. This field is used as an inteface to get and set the employee photo. -When changing the photo through the photo function field, the new image is automatically resized to 540x450, and stored in the photo_big field. This triggers the function field, that will compute a 180x150 resized version of the image. - -Employee photo should be used only when dealing with employees, using the photo field. When dealing with users, use the res.users avatar field instead. diff --git a/addons/hr/doc/index.rst b/addons/hr/doc/index.rst deleted file mode 100644 index 0a7d4a7132d..00000000000 --- a/addons/hr/doc/index.rst +++ /dev/null @@ -1,6 +0,0 @@ -:orphan: - -HR module documentation -======================= - -.. include:: index.rst.inc diff --git a/addons/hr/doc/index.rst.inc b/addons/hr/doc/index.rst.inc deleted file mode 100644 index 9e5d4c277c8..00000000000 --- a/addons/hr/doc/index.rst.inc +++ /dev/null @@ -1,8 +0,0 @@ - -HR Module -''''''''' - -.. toctree:: - :maxdepth: 1 - - hr_employee_img diff --git a/addons/hr/hr.py b/addons/hr/hr.py index c08afcaa825..6b568367e14 100644 --- a/addons/hr/hr.py +++ b/addons/hr/hr.py @@ -19,12 +19,12 @@ # ############################################################################## -from osv import fields, osv -import logging import addons - -import io, StringIO +import io +import logging +from osv import fields, osv from PIL import Image +import StringIO class hr_employee_category(osv.osv): diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index dbc086e1746..3b58a986782 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -510,6 +510,23 @@ class mail_message(osv.osv): msg['sub_type'] = msg['subtype'] or 'plain' return msg + def _postprocess_sent_message(self, cr, uid, message, context=None): + """Perform any post-processing necessary after sending ``message`` + successfully, including deleting it completely along with its + attachment if the ``auto_delete`` flag of the message was set. + Overridden by subclasses for extra post-processing behaviors. + + :param browse_record message: the message that was just sent + :return: True + """ + if message.auto_delete: + self.pool.get('ir.attachment').unlink(cr, uid, + [x.id for x in message.attachment_ids \ + if x.res_model == self._name and \ + x.res_id == message.id], + context=context) + message.unlink() + return True def send(self, cr, uid, ids, auto_commit=False, context=None): """Sends the selected emails immediately, ignoring their current @@ -567,16 +584,9 @@ class mail_message(osv.osv): message.write({'state':'sent', 'message_id': res}) else: message.write({'state':'exception'}) - - # if auto_delete=True then delete that sent messages as well as attachments message.refresh() - if message.state == 'sent' and message.auto_delete: - self.pool.get('ir.attachment').unlink(cr, uid, - [x.id for x in message.attachment_ids \ - if x.res_model == self._name and \ - x.res_id == message.id], - context=context) - message.unlink() + if message.state == 'sent': + self._postprocess_sent_message(cr, uid, message, context=context) except Exception: _logger.exception('failed sending mail.message %s', message.id) message.write({'state':'exception'}) diff --git a/addons/project/doc/index.rst b/addons/project/doc/index.rst deleted file mode 100644 index d3e68870773..00000000000 --- a/addons/project/doc/index.rst +++ /dev/null @@ -1,6 +0,0 @@ -:orphan: - -Project module documentation -============================ - -.. include:: index.rst.inc diff --git a/addons/project/doc/index.rst.inc b/addons/project/doc/index.rst.inc deleted file mode 100644 index 4d9fcc34b5b..00000000000 --- a/addons/project/doc/index.rst.inc +++ /dev/null @@ -1,8 +0,0 @@ - -Project Module -'''''''''''''' - -.. toctree:: - :maxdepth: 1 - - task_kanban_avatar diff --git a/addons/project/doc/task_kanban_avatar.rst b/addons/project/doc/task_kanban_avatar.rst deleted file mode 100644 index af0a460f51c..00000000000 --- a/addons/project/doc/task_kanban_avatar.rst +++ /dev/null @@ -1,4 +0,0 @@ -Task kanban avatar specs -======================== - -Kanban view of tasks has been updated to use the newly-introduced avatar_mini field of res.users. The avatar is placed in the right-side of the containing kanban box. diff --git a/addons/purchase_double_validation/i18n/pt.po b/addons/purchase_double_validation/i18n/pt.po new file mode 100644 index 00000000000..4dd263e1652 --- /dev/null +++ b/addons/purchase_double_validation/i18n/pt.po @@ -0,0 +1,70 @@ +# Portuguese translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-02-08 00:37+0000\n" +"PO-Revision-Date: 2012-03-29 11:26+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Portuguese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-03-30 04:34+0000\n" +"X-Generator: Launchpad (build 15032)\n" + +#. module: purchase_double_validation +#: view:purchase.double.validation.installer:0 +msgid "Purchase Application Configuration" +msgstr "" + +#. module: purchase_double_validation +#: view:purchase.double.validation.installer:0 +msgid "Define minimum amount after which puchase is needed to be validated." +msgstr "" + +#. module: purchase_double_validation +#: view:purchase.double.validation.installer:0 +msgid "title" +msgstr "" + +#. module: purchase_double_validation +#: field:purchase.double.validation.installer,config_logo:0 +msgid "Image" +msgstr "" + +#. module: purchase_double_validation +#: model:ir.actions.act_window,name:purchase_double_validation.action_config_purchase_limit_amount +#: view:purchase.double.validation.installer:0 +msgid "Configure Limit Amount for Purchase" +msgstr "" + +#. module: purchase_double_validation +#: view:board.board:0 +#: model:ir.actions.act_window,name:purchase_double_validation.purchase_waiting +msgid "Purchase Order Waiting Approval" +msgstr "" + +#. module: purchase_double_validation +#: view:purchase.double.validation.installer:0 +msgid "res_config_contents" +msgstr "" + +#. module: purchase_double_validation +#: help:purchase.double.validation.installer,limit_amount:0 +msgid "Maximum amount after which validation of purchase is required." +msgstr "" + +#. module: purchase_double_validation +#: model:ir.model,name:purchase_double_validation.model_purchase_double_validation_installer +msgid "purchase.double.validation.installer" +msgstr "" + +#. module: purchase_double_validation +#: field:purchase.double.validation.installer,limit_amount:0 +msgid "Maximum Purchase Amount" +msgstr ""