diff --git a/addons/base_crypt/i18n/pl.po b/addons/base_crypt/i18n/pl.po new file mode 100644 index 00000000000..4e4ff39a279 --- /dev/null +++ b/addons/base_crypt/i18n/pl.po @@ -0,0 +1,45 @@ +# Polish 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:36+0000\n" +"PO-Revision-Date: 2012-03-28 14:21+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Polish \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-29 04:35+0000\n" +"X-Generator: Launchpad (build 15032)\n" + +#. module: base_crypt +#: model:ir.model,name:base_crypt.model_res_users +msgid "res.users" +msgstr "" + +#. module: base_crypt +#: sql_constraint:res.users:0 +msgid "You can not have two users with the same login !" +msgstr "Nie może być dwóch użytkowników o tym samym loginie !" + +#. module: base_crypt +#: constraint:res.users:0 +msgid "The chosen company is not in the allowed companies for this user" +msgstr "Wybrana firma jest niedozwolona dla tego użytkownika" + +#. module: base_crypt +#: code:addons/base_crypt/crypt.py:140 +#, python-format +msgid "Please specify the password !" +msgstr "Proszę podać hasło!" + +#. module: base_crypt +#: code:addons/base_crypt/crypt.py:140 +#, python-format +msgid "Error" +msgstr "Błąd" diff --git a/addons/crm_caldav/i18n/pl.po b/addons/crm_caldav/i18n/pl.po new file mode 100644 index 00000000000..748beb9313f --- /dev/null +++ b/addons/crm_caldav/i18n/pl.po @@ -0,0 +1,33 @@ +# Polish 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:36+0000\n" +"PO-Revision-Date: 2012-03-28 14:18+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Polish \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-29 04:35+0000\n" +"X-Generator: Launchpad (build 15032)\n" + +#. module: crm_caldav +#: model:ir.actions.act_window,name:crm_caldav.action_caldav_browse +msgid "Caldav Browse" +msgstr "" + +#. module: crm_caldav +#: model:ir.ui.menu,name:crm_caldav.menu_caldav_browse +msgid "Synchronize This Calendar" +msgstr "Synchronizuj ten kalendarz" + +#. module: crm_caldav +#: model:ir.model,name:crm_caldav.model_crm_meeting +msgid "Meeting" +msgstr "Zebranie" 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 a0b956790af..0d72e16e7da 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. @@ -415,7 +484,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/mail/mail_message.py b/addons/mail/mail_message.py index e4e65c67edf..aef3aa24767 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -464,6 +464,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 @@ -521,16 +538,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/project_view.xml b/addons/project/project_view.xml index b27e9dcbd1d..9b3b3106fc5 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -181,54 +181,61 @@
- +
- - + -
-
-
- - Deadline -
-
-
+ +
+
+
+
+

...

- - + + + +
+
+ + + +
-
- - +
+ +
+ Deadline +
+
- +
- - + + + + +
+
hrs hrs
- - - -
diff --git a/addons/project/static/src/css/project.css b/addons/project/static/src/css/project.css index a17cadd45e3..9657edf43ad 100644 --- a/addons/project/static/src/css/project.css +++ b/addons/project/static/src/css/project.css @@ -17,9 +17,7 @@ .oe_project_desc{ width: 250px; } - .progress{ - text-align: left; width: auto; } .oe_project_font{ @@ -28,6 +26,7 @@ } .sequence { padding-bottom: 4px !important; + padding-top: 3px !important; border-bottom: groove; /*font-size: 20px;*/ text-align: center; @@ -48,9 +47,52 @@ text-align: center; } - +.project_table{ + width:350px; +} +.td_image{ + width:60px; + text-align:center; + vertical-align:top; +} +.avatar{ + height:40px; + width:40px; +} +.td_name{ + text-align:left; + vertical-align:middle; + width:220px; +} +.td_deadline{ + width:70px; + text-align:center; +} +.td_member{ + text-align:right; + vertical-align:bottom; + width:130px; + height:20px; +} +.td_member_img{ + height:22px; + width:22px; +} +.img_member{ + height:20px; + width:20px; +} +.td_hours{ + text-align:right; + vertical-align:bottom; + width:120px +} +.task{ + text-align:left; + vertical-align:middle; +} .invoiced{ - font-size: 9px; + font-size: 10px; } .oe_project { width: 55px; diff --git a/addons/project_timesheet/project_timesheet_view.xml b/addons/project_timesheet/project_timesheet_view.xml index 14924c2ce0f..43868f69037 100644 --- a/addons/project_timesheet/project_timesheet_view.xml +++ b/addons/project_timesheet/project_timesheet_view.xml @@ -46,9 +46,16 @@
- + -
+ +
+ Hours +
h
+
+ + +
-
- Hours -
-
-
+ 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 ""