diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 6804d5116f1..8d13ec9dc8f 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -1381,8 +1381,8 @@ class account_invoice_line(osv.osv): 'origin': fields.char('Source Document', size=256, help="Reference of the document that produced this invoice."), 'sequence': fields.integer('Sequence', help="Gives the sequence of this line when displaying the invoice."), 'invoice_id': fields.many2one('account.invoice', 'Invoice Reference', ondelete='cascade', select=True), - 'uos_id': fields.many2one('product.uom', 'Unit of Measure', ondelete='set null'), - 'product_id': fields.many2one('product.product', 'Product', ondelete='set null'), + 'uos_id': fields.many2one('product.uom', 'Unit of Measure', ondelete='set null', select=True), + 'product_id': fields.many2one('product.product', 'Product', ondelete='set null', select=True), 'account_id': fields.many2one('account.account', 'Account', required=True, domain=[('type','<>','view'), ('type', '<>', 'closed')], help="The income or expense account related to the selected product."), 'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price')), 'price_subtotal': fields.function(_amount_line, string='Subtotal', type="float", diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index 7732d8d8cb0..53983551f72 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -1238,7 +1238,7 @@ - + diff --git a/addons/account/report/account_invoice_report.py b/addons/account/report/account_invoice_report.py index 68eaedb20a6..a001b6b4f52 100644 --- a/addons/account/report/account_invoice_report.py +++ b/addons/account/report/account_invoice_report.py @@ -98,150 +98,124 @@ class account_invoice_report(osv.osv): 'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account',readonly=True), 'residual': fields.float('Total Residual', readonly=True), 'user_currency_residual': fields.function(_compute_amounts_in_user_currency, string="Total Residual", type='float', digits_compute=dp.get_precision('Account'), multi="_compute_amounts"), - 'delay_to_pay': fields.float('Avg. Delay To Pay', readonly=True, group_operator="avg"), - 'due_delay': fields.float('Avg. Due Delay', readonly=True, group_operator="avg"), } _order = 'date desc' - def _select(self): select_str = """ - SELECT min(ail.id) as id, - ai.date_invoice as date, - to_char(ai.date_invoice, 'YYYY') as year, - to_char(ai.date_invoice, 'MM') as month, - to_char(ai.date_invoice, 'YYYY-MM-DD') as day, - ail.product_id, - ai.partner_id as partner_id, - ai.payment_term as payment_term, - ai.period_id as period_id, - (case when u.uom_type not in ('reference') then - (select name from product_uom where uom_type='reference' and active and category_id=u.category_id LIMIT 1) - else - u.name - end) as uom_name, - ai.currency_id as currency_id, - ai.journal_id as journal_id, - ai.fiscal_position as fiscal_position, - ai.user_id as user_id, - ai.company_id as company_id, - count(ail.*) as nbr, - ai.type as type, - ai.state, - pt.categ_id, - ai.date_due as date_due, - ai.account_id as account_id, - ail.account_id as account_line_id, - ai.partner_bank_id as partner_bank_id, - sum(case when ai.type in ('out_refund','in_invoice') then - -ail.quantity / u.factor - else - ail.quantity / u.factor - end) as product_qty, - - sum(case when ai.type in ('out_refund','in_invoice') then - -ail.price_subtotal - else - ail.price_subtotal - end) / cr.rate as price_total, - - (case when ai.type in ('out_refund','in_invoice') then - sum(-ail.price_subtotal) - else - sum(ail.price_subtotal) - end) / (CASE WHEN sum(ail.quantity/u.factor) <> 0 - THEN - (case when ai.type in ('out_refund','in_invoice') - then sum(-ail.quantity/u.factor) - else sum(ail.quantity/u.factor) end) - ELSE 1 - END) - / cr.rate as price_average, - - cr.rate as currency_rate, - sum((select extract(epoch from avg(date_trunc('day',aml.date_created)-date_trunc('day',l.create_date)))/(24*60*60)::decimal(16,2) - from account_move_line as aml - left join account_invoice as a ON (a.move_id=aml.move_id) - left join account_invoice_line as l ON (a.id=l.invoice_id) - where a.id=ai.id)) as delay_to_pay, - sum((select extract(epoch from avg(date_trunc('day',a.date_due)-date_trunc('day',a.date_invoice)))/(24*60*60)::decimal(16,2) - from account_move_line as aml - left join account_invoice as a ON (a.move_id=aml.move_id) - left join account_invoice_line as l ON (a.id=l.invoice_id) - where a.id=ai.id)) as due_delay, - (case when ai.type in ('out_refund','in_invoice') then - -ai.residual - else - ai.residual - end)/ (CASE WHEN - (select count(l.id) from account_invoice_line as l - left join account_invoice as a ON (a.id=l.invoice_id) - where a.id=ai.id) <> 0 - THEN - (select count(l.id) from account_invoice_line as l - left join account_invoice as a ON (a.id=l.invoice_id) - where a.id=ai.id) - ELSE 1 - END) / cr.rate as residual + SELECT sub.id, sub.date, sub.year, sub.month, sub.day, sub.product_id, sub.partner_id, + sub.payment_term, sub.period_id, sub.uom_name, sub.currency_id, sub.journal_id, + sub.fiscal_position, sub.user_id, sub.company_id, sub.nbr, sub.type, sub.state, + sub.categ_id, sub.date_due, sub.account_id, sub.account_line_id, sub.partner_bank_id, + sub.product_qty, sub.price_total / cr.rate as price_total, sub.price_average /cr.rate as price_average, + cr.rate as currency_rate, sub.residual / cr.rate as residual """ return select_str - def _where(self): - where_str = """ - WHERE cr.id in (select id from res_currency_rate cr2 where (cr2.currency_id = ai.currency_id) - and ((ai.date_invoice is not null and cr.name <= ai.date_invoice) or (ai.date_invoice is null and cr.name <= NOW())) order by name desc limit 1) + def _sub_select(self): + select_str = """ + SELECT min(ail.id) AS id, + ai.date_invoice AS date, + to_char(ai.date_invoice::timestamp with time zone, 'YYYY'::text) AS year, + to_char(ai.date_invoice::timestamp with time zone, 'MM'::text) AS month, + to_char(ai.date_invoice::timestamp with time zone, 'YYYY-MM-DD'::text) AS day, + ail.product_id, ai.partner_id, ai.payment_term, ai.period_id, + CASE + WHEN u.uom_type::text <> 'reference'::text + THEN ( SELECT product_uom.name + FROM product_uom + WHERE product_uom.uom_type::text = 'reference'::text + AND product_uom.active + AND product_uom.category_id = u.category_id LIMIT 1) + ELSE u.name + END AS uom_name, + ai.currency_id, ai.journal_id, ai.fiscal_position, ai.user_id, ai.company_id, + count(ail.*) AS nbr, + ai.type, ai.state, pt.categ_id, ai.date_due, ai.account_id, ail.account_id AS account_line_id, + ai.partner_bank_id, + SUM(CASE + WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text]) + THEN (- ail.quantity) / u.factor + ELSE ail.quantity / u.factor + END) AS product_qty, + SUM(CASE + WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text]) + THEN - ail.price_subtotal + ELSE ail.price_subtotal + END) AS price_total, + CASE + WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text]) + THEN SUM(- ail.price_subtotal) + ELSE SUM(ail.price_subtotal) + END / CASE + WHEN SUM(ail.quantity / u.factor) <> 0::numeric + THEN CASE + WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text]) + THEN SUM((- ail.quantity) / u.factor) + ELSE SUM(ail.quantity / u.factor) + END + ELSE 1::numeric + END AS price_average, + CASE + WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text]) + THEN - ai.residual + ELSE ai.residual + END / CASE + WHEN (( SELECT count(l.id) AS count + FROM account_invoice_line l + LEFT JOIN account_invoice a ON a.id = l.invoice_id + WHERE a.id = ai.id)) <> 0 + THEN ( SELECT count(l.id) AS count + FROM account_invoice_line l + LEFT JOIN account_invoice a ON a.id = l.invoice_id + WHERE a.id = ai.id) + ELSE 1::bigint + END::numeric AS residual """ - return where_str + return select_str def _from(self): from_str = """ - FROM account_invoice_line as ail - left join account_invoice as ai ON (ai.id=ail.invoice_id) - left join product_product pr on (pr.id=ail.product_id) - left join product_template pt on (pt.id=pr.product_tmpl_id) - left join product_uom u on (u.id=ail.uos_id), - res_currency_rate cr + FROM account_invoice_line ail + JOIN account_invoice ai ON ai.id = ail.invoice_id + LEFT JOIN product_product pr ON pr.id = ail.product_id + left JOIN product_template pt ON pt.id = pr.product_tmpl_id + LEFT JOIN product_uom u ON u.id = ail.uos_id """ return from_str def _group_by(self): group_by_str = """ - GROUP BY ail.product_id, - ai.date_invoice, - ai.id, - cr.rate, - to_char(ai.date_invoice, 'YYYY'), - to_char(ai.date_invoice, 'MM'), - to_char(ai.date_invoice, 'YYYY-MM-DD'), - ai.partner_id, - ai.payment_term, - ai.period_id, - u.name, - ai.currency_id, - ai.journal_id, - ai.fiscal_position, - ai.user_id, - ai.company_id, - ai.type, - ai.state, - pt.categ_id, - ai.date_due, - ai.account_id, - ail.account_id, - ai.partner_bank_id, - ai.residual, - ai.amount_total, - u.uom_type, - u.category_id + GROUP BY ail.product_id, ai.date_invoice, ai.id, + to_char(ai.date_invoice::timestamp with time zone, 'YYYY'::text), + to_char(ai.date_invoice::timestamp with time zone, 'MM'::text), + to_char(ai.date_invoice::timestamp with time zone, 'YYYY-MM-DD'::text), + ai.partner_id, ai.payment_term, ai.period_id, u.name, ai.currency_id, ai.journal_id, + ai.fiscal_position, ai.user_id, ai.company_id, ai.type, ai.state, pt.categ_id, + ai.date_due, ai.account_id, ail.account_id, ai.partner_bank_id, ai.residual, + ai.amount_total, u.uom_type, u.category_id """ return group_by_str def init(self, cr): # self._table = account_invoice_report tools.drop_view_if_exists(cr, self._table) - cr.execute("CREATE or REPLACE VIEW %s as (%s %s %s %s)" % ( + cr.execute("""CREATE or REPLACE VIEW %s as ( + %s + FROM ( + %s %s %s + ) AS sub + JOIN res_currency_rate cr ON (cr.currency_id = sub.currency_id) + WHERE + cr.id IN (SELECT id + FROM res_currency_rate cr2 + WHERE (cr2.currency_id = sub.currency_id) + AND ((sub.date IS NOT NULL AND cr.name <= sub.date) + OR (sub.date IS NULL AND cr.name <= NOW())) + ORDER BY name DESC LIMIT 1) + )""" % ( self._table, - self._select(), self._from(), self._where(), self._group_by())) + self._select(), self._sub_select(), self._from(), self._group_by())) account_invoice_report() diff --git a/addons/account/report/account_invoice_report_view.xml b/addons/account/report/account_invoice_report_view.xml index 289db376e5d..66e17560bde 100644 --- a/addons/account/report/account_invoice_report_view.xml +++ b/addons/account/report/account_invoice_report_view.xml @@ -30,8 +30,6 @@ - - @@ -93,7 +91,7 @@ tree,graph {'search_default_period':1,'search_default_current':1, 'search_default_year': 1, 'search_default_category_product':1, 'search_default_customer':1, 'group_by':[], 'group_by_no_leaf':1,} - From this report, you can have an overview of the amount invoiced to your customer as well as payment delays. The tool search can also be used to personalise your Invoices reports and so, match this analysis to your needs. + From this report, you can have an overview of the amount invoiced to your customer. The tool search can also be used to personalise your Invoices reports and so, match this analysis to your needs. diff --git a/addons/account_analytic_analysis/__init__.py b/addons/account_analytic_analysis/__init__.py index 429aa011f31..9aae723c5cf 100644 --- a/addons/account_analytic_analysis/__init__.py +++ b/addons/account_analytic_analysis/__init__.py @@ -21,6 +21,7 @@ import account_analytic_analysis import cron_account_analytic_account +import res_config # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_analytic_analysis/__openerp__.py b/addons/account_analytic_analysis/__openerp__.py index 7675ef9f38e..53ebf225de1 100644 --- a/addons/account_analytic_analysis/__openerp__.py +++ b/addons/account_analytic_analysis/__openerp__.py @@ -40,6 +40,7 @@ Adds menu to show relevant information to each manager.You can also view the rep 'account_analytic_analysis_view.xml', 'account_analytic_analysis_menu.xml', 'account_analytic_analysis_cron.xml', + 'res_config_view.xml', ], 'css': [ 'static/src/css/analytic.css' diff --git a/addons/account_analytic_analysis/account_analytic_analysis_view.xml b/addons/account_analytic_analysis/account_analytic_analysis_view.xml index be2a504658f..2ece3a38652 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis_view.xml +++ b/addons/account_analytic_analysis/account_analytic_analysis_view.xml @@ -147,6 +147,18 @@ + + account.analytic.account.form.template.required + account.analytic.account + + + + + {'required': [('type','=','contract')], 'invisible': [('type','in',['view', 'normal','template'])]} + + + + Template of Contract ir.actions.act_window diff --git a/addons/account_analytic_analysis/res_config.py b/addons/account_analytic_analysis/res_config.py new file mode 100644 index 00000000000..94fe769fdd4 --- /dev/null +++ b/addons/account_analytic_analysis/res_config.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (C) 2004-2012 OpenERP S.A. (). +# +# 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 . +# +############################################################################## + +from osv import fields, osv + +class sale_configuration(osv.osv_memory): + _inherit = 'sale.config.settings' + + _columns = { + 'group_template_required': fields.boolean("Mandatory use of templates.", + implied_group='account_analytic_analysis.group_template_required', + help="Allows you to set the template field as required when creating an analytic account or a contract."), + } diff --git a/addons/account_analytic_analysis/res_config_view.xml b/addons/account_analytic_analysis/res_config_view.xml new file mode 100644 index 00000000000..9c7881f2a9e --- /dev/null +++ b/addons/account_analytic_analysis/res_config_view.xml @@ -0,0 +1,21 @@ + + + + + + sale settings + sale.config.settings + + + +
+ +
+
+
+
+ +
+
+ diff --git a/addons/account_analytic_analysis/security/account_analytic_analysis_security.xml b/addons/account_analytic_analysis/security/account_analytic_analysis_security.xml index 8bcc7f2d7f0..948c390e039 100644 --- a/addons/account_analytic_analysis/security/account_analytic_analysis_security.xml +++ b/addons/account_analytic_analysis/security/account_analytic_analysis_security.xml @@ -6,5 +6,12 @@
+ + Mandatory use of templates in contracts + + the field template of the analytic accounts and contracts will be required. + + + - \ No newline at end of file + diff --git a/addons/account_bank_statement_extensions/account_bank_statement_view.xml b/addons/account_bank_statement_extensions/account_bank_statement_view.xml index adc2963c803..d64eb68bc99 100644 --- a/addons/account_bank_statement_extensions/account_bank_statement_view.xml +++ b/addons/account_bank_statement_extensions/account_bank_statement_view.xml @@ -43,10 +43,10 @@ - - + + - + diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml index 4dc753deedc..1e1481c3f2b 100644 --- a/addons/account_voucher/account_voucher_view.xml +++ b/addons/account_voucher/account_voucher_view.xml @@ -213,7 +213,7 @@ - + diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py index 708f9b3b196..542acb1e88c 100644 --- a/addons/analytic/analytic.py +++ b/addons/analytic/analytic.py @@ -20,8 +20,10 @@ ############################################################################## import time +from datetime import datetime from osv import fields, osv +import tools from tools.translate import _ import decimal_precision as dp @@ -199,9 +201,14 @@ class account_analytic_account(osv.osv): return {} res = {'value':{}} template = self.browse(cr, uid, template_id, context=context) - res['value']['date_start'] = template.date_start - res['value']['date'] = template.date + if template.date_start and template.date: + from_dt = datetime.strptime(template.date_start, tools.DEFAULT_SERVER_DATE_FORMAT) + to_dt = datetime.strptime(template.date, tools.DEFAULT_SERVER_DATE_FORMAT) + timedelta = to_dt - from_dt + res['value']['date'] = datetime.strftime(datetime.now() + timedelta, tools.DEFAULT_SERVER_DATE_FORMAT) + res['value']['date_start'] = fields.date.today() res['value']['quantity_max'] = template.quantity_max + res['value']['parent_id'] = template.parent_id and template.parent_id.id or False res['value']['description'] = template.description return res diff --git a/addons/analytic/analytic_view.xml b/addons/analytic/analytic_view.xml index 1277d25de71..0faca841a0f 100644 --- a/addons/analytic/analytic_view.xml +++ b/addons/analytic/analytic_view.xml @@ -26,10 +26,10 @@ - - + + diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js index a6b401a4c7b..241c2406d56 100644 --- a/addons/auth_signup/static/src/js/auth_signup.js +++ b/addons/auth_signup/static/src/js/auth_signup.js @@ -52,6 +52,8 @@ openerp.auth_signup = function(instance) { if (result.token) { // switch to signup mode, set user name and login this.$el.addClass("oe_login_signup"); + self.$(".oe_signup_show").show(); + self.$(".oe_signup_hide").hide(); this.$("form input[name=name]").val(result.name).attr("readonly", "readonly"); if (result.login) { this.$("form input[name=login]").val(result.login).attr("readonly", "readonly"); diff --git a/addons/crm/report/crm_lead_report.py b/addons/crm/report/crm_lead_report.py index da5167da1e6..25598abc3ea 100644 --- a/addons/crm/report/crm_lead_report.py +++ b/addons/crm/report/crm_lead_report.py @@ -81,7 +81,6 @@ class crm_lead_report(osv.osv): 'type_id':fields.many2one('crm.case.resource.type', 'Campaign', readonly=True), 'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True), 'company_id': fields.many2one('res.company', 'Company', readonly=True), - 'email': fields.integer('# Emails', size=128, readonly=True), 'probability': fields.float('Probability',digits=(16,2),readonly=True, group_operator="avg"), 'planned_revenue': fields.float('Planned Revenue',digits=(16,2),readonly=True), 'probable_revenue': fields.float('Probable Revenue', digits=(16,2),readonly=True), @@ -137,7 +136,6 @@ class crm_lead_report(osv.osv): c.planned_revenue, c.planned_revenue*(c.probability/100) as probable_revenue, 1 as nbr, - (SELECT count(id) FROM mail_message WHERE model='crm.lead' AND res_id=c.id AND email_from is not null) AS email, date_trunc('day',c.create_date) as create_date, extract('epoch' from (c.date_closed-c.create_date))/(3600*24) as delay_close, abs(extract('epoch' from (c.date_deadline - c.date_closed))/(3600*24)) as delay_expected, diff --git a/addons/crm/report/crm_lead_report_view.xml b/addons/crm/report/crm_lead_report_view.xml index a17633d0ef6..0e5df8837f1 100644 --- a/addons/crm/report/crm_lead_report_view.xml +++ b/addons/crm/report/crm_lead_report_view.xml @@ -25,7 +25,6 @@ - @@ -148,7 +147,6 @@ - @@ -167,7 +165,7 @@ {'search_default_year': 1,'search_default_lead': 1, "search_default_user":1, "search_default_this_month":1, 'group_by_no_leaf':1, 'group_by':[]} tree,graph [] - Leads Analysis allows you to check different CRM related information. Check for treatment delays, number of responses given and emails sent. You can sort out your leads analysis by different groups to get accurate grained analysis. + Leads Analysis allows you to check different CRM related information like the treatment delays or number of leads per state. You can sort out your leads analysis by different groups to get accurate grained analysis. diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index ba6d101541c..3273870f5e0 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -206,6 +206,14 @@ class mail_message(osv.Model): new_is_favorite = not (uid in message.get('favorite_user_ids')) if new_is_favorite: self.write(cr, SUPERUSER_ID, message.get('id'), {'favorite_user_ids': [(4, uid)]}, context=context) + # when setting a favorite, set the related notification as unread, or create an unread notification if not existing + notification_obj = self.pool.get('mail.notification') + pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=None)['partner_id'][0] + notif_id = notification_obj.search(cr, SUPERUSER_ID, [('message_id', '=', message.get('id')), ('partner_id', '=', pid)], context=context) + if notif_id: + notification_obj.write(cr, SUPERUSER_ID, notif_id, {'read': False}, context=context) + else: + notification_obj.create(cr, SUPERUSER_ID, {'message_id': message.get('id'), 'partner_id': pid, 'read': False}, context=context) else: self.write(cr, SUPERUSER_ID, message.get('id'), {'favorite_user_ids': [(3, uid)]}, context=context) return new_is_favorite or False diff --git a/addons/mail/mail_thread_view.xml b/addons/mail/mail_thread_view.xml index a232aa12642..4106eb2e024 100644 --- a/addons/mail/mail_thread_view.xml +++ b/addons/mail/mail_thread_view.xml @@ -42,7 +42,8 @@ + 'read_action': 'read', + 'show_compose_message': False }""/>

No private message. @@ -64,7 +65,8 @@ + 'read_action': 'read', + 'compose_as_todo': True }""/>

No todo. @@ -84,7 +86,8 @@ } + 'view_mailbox': True, + 'show_compose_message': False }""/>

No message found and no message sent yet. diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 94a5c2d1f41..638d016921b 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -48,7 +48,7 @@ .openerp .oe_mail .oe_msg{ position: relative; - background: #F4F5FA; + background: #EDEDF6; border-radius: 2px; margin-bottom: 2px; min-height: 42px; @@ -70,7 +70,7 @@ margin-left: 40px; } .openerp .oe_mail .oe_msg .oe_msg_footer{ - padding-left: 4px; + margin-left: 4px; padding-top: 3px; overflow: hidden; margin-bottom: 4px; @@ -94,6 +94,10 @@ .openerp .oe_mail .oe_msg .oe_msg_content .oe_msg_body p { margin-bottom: 0px; } +.openerp .oe_mail .oe_msg .oe_msg_content .oe_msg_body * { + text-overflow:ellipsis; + word-wrap: break-word; +} /* a) Indented Messages */ @@ -380,6 +384,10 @@ line-height: 12px; vertical-align: middle; } +.openerp .oe_mail .oe_msg_footer button.oe_post{ + position: relative; + z-index: 2; +} .openerp .oe_mail .oe_msg_footer button.oe_attach{ width: 24px; overflow: hidden; @@ -387,8 +395,9 @@ } .openerp .oe_mail .oe_msg_footer button.oe_attach .oe_e{ position: relative; - top: -1px; - left: -9px; + top: -4px; + margin-left: -9px; + vertical-align: middle; filter:none; } .openerp .oe_mail .oe_hidden_input_file, .openerp .oe_mail .oe_hidden_input_file form{ @@ -402,8 +411,9 @@ } .openerp .oe_mail .oe_msg_footer button.oe_full .oe_e{ position: relative; - top: -1px; - left: -9px; + top: -4px; + margin-left: -9px; + vertical-align: middle; filter:none; } .openerp .oe_mail button.oe_attach, .openerp .oe_mail button.oe_full{ @@ -418,13 +428,17 @@ color: #7C7BAD; margin-left: -3px; } +.openerp .oe_mail .oe_msg_footer .oe_attachment_file{ + cursor: pointer; +} .openerp .oe_mail .oe_msg_footer .oe_attachment_file .oe_form_binary_file{ display: inline-block; - margin-left: -47px; - height: 28px; - width: 52px; - margin-top: -6px; + margin-left: -122px; + height: 22px; + width: 128px; + margin-top: -4px; filter:none; + cursor: pointer; } .openerp .oe_mail .oe_mail_list_recipients{ font-size: 12px; diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 6b056500c7a..a5beaac229f 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -204,7 +204,7 @@ openerp.mail = function (session) { this.subject = datasets.subject || false, this.name = datasets.name || false, this.record_name = datasets.record_name || false, - this.body = datasets.body || false, + this.body = datasets.body || '', this.vote_nb = datasets.vote_nb || 0, this.has_voted = datasets.has_voted || false, this.is_favorite = datasets.is_favorite || false, @@ -508,7 +508,6 @@ openerp.mail = function (session) { res_model: 'mail.compose.message', view_mode: 'form', view_type: 'form', - action_from: 'mail.ThreadComposeMessage', views: [[false, 'form']], target: 'new', context: context, @@ -574,12 +573,7 @@ openerp.mail = function (session) { var message = thread.create_message_object( data[0] ); // insert the message on dom thread.insert_message( message, root ? undefined : self.$el, root ); - if (thread.parent_message) { - self.$el.remove(); - self.parent_thread.compose_message = null; - } else { - self.on_cancel(); - } + self.on_cancel(); }); //session.web.unblockUI(); }); @@ -591,11 +585,11 @@ openerp.mail = function (session) { */ on_compose_expandable: function (event) { - if (!this.stay_open && (!this.show_composer || !this.$('textarea:not(.oe_compact)').val().match(/\S+/))) { + if ((!this.stay_open || (event && event.type == 'click')) && (!this.show_composer || !this.$('textarea:not(.oe_compact)').val().match(/\S+/))) { this.show_composer = !this.show_composer || this.stay_open; this.reinit(); } - if (!this.stay_open && this.show_composer) { + if (!this.stay_open && this.show_composer && (!event || event.type != 'blur')) { this.$('textarea:not(.oe_compact):first').focus(); } return true; @@ -725,7 +719,7 @@ openerp.mail = function (session) { on_message_reply:function (event) { event.stopPropagation(); this.create_thread(); - this.thread.on_compose_message(); + this.thread.on_compose_message(event); return false; }, @@ -833,9 +827,10 @@ openerp.mail = function (session) { return false; }, - /*The selected thread and all childs (messages/thread) became read - * @param {object} mouse envent - */ + /* Set the selected thread and all childs as read or unread, based on + * read parameter. + * @param {boolean} read_value + */ on_message_read_unread: function (read_value) { var self = this; var messages = [this].concat(this.get_childs()); @@ -958,7 +953,7 @@ openerp.mail = function (session) { this.options = options.options; this.options.root_thread = (options.options.root_thread != undefined ? options.options.root_thread : this); - this.options.show_compose_message = this.options.show_compose_message && (this.options.display_indented_thread >= this.thread_level || !this.thread_level); + this.options.show_compose_message = this.options.show_compose_message && !this.thread_level; // record options and data this.parent_message= parent.thread!= undefined ? parent : false ; @@ -995,7 +990,7 @@ openerp.mail = function (session) { // add message composition form view if (!this.compose_message) { this.compose_message = new mail.ThreadComposeMessage(this, this, { - 'context': this.context, + 'context': this.options.compose_as_todo && !this.thread_level ? _.extend(this.context, { 'default_favorite_user_ids': [this.session.uid] }) : this.context, 'options': this.options, }); if (!this.thread_level || this.thread_level > this.options.display_indented_thread) { @@ -1136,9 +1131,9 @@ openerp.mail = function (session) { * Call the on_compose_expandable method to allow the user to write his message. * (Is call when a user click on "Reply" button) */ - on_compose_message: function () { + on_compose_message: function (event) { this.instantiate_compose_message(); - this.compose_message.on_compose_expandable(); + this.compose_message.on_compose_expandable(event); return false; }, @@ -1241,6 +1236,7 @@ openerp.mail = function (session) { } else { message.appendTo(self.$el); } + message.$el.hide().fadeIn(500); return message }, @@ -1262,6 +1258,9 @@ openerp.mail = function (session) { // insert the message on dom thread.insert_message( message, typeof dom_insert_after == 'object' ? dom_insert_after : false); }); + if (!records.length && this.options.root_thread == this) { + this.no_message(); + } }, /** @@ -1291,8 +1290,10 @@ openerp.mail = function (session) { var messages = _.sortBy( this.messages, function (val) { return val.id; }); var it = _.indexOf( messages, message ); - var msg_up = messages[it-1]; - var msg_down = messages[it+1]; + var msg_up = message.$el.prev('.oe_msg'); + var msg_down = message.$el.next('.oe_msg'); + var msg_up = msg_up.hasClass('oe_msg_expandable') ? _.find( this.messages, function (val) { return val.$el[0] == msg_up[0]; }) : false; + var msg_down = msg_down.hasClass('oe_msg_expandable') ? _.find( this.messages, function (val) { return val.$el[0] == msg_down[0]; }) : false; var message_dom = [ ["id", "=", message.id] ]; @@ -1397,6 +1398,8 @@ openerp.mail = function (session) { *... @param {Array} [message_ids] List of ids to fetch by the root thread. * When you use this option, the domain is not used for the fetch root. * @param {String} [no_message] Message to display when there are no message + * @param {Boolean} [show_link_partner] Display partner (authors, followers...) on link or not + * @param {Boolean} [compose_as_todo] The root composer mark automatically the message as todo */ init: function (parent, action) { this._super(parent, action); @@ -1414,8 +1417,10 @@ openerp.mail = function (session) { 'show_compose_message' : false, 'show_compact_message' : false, 'compose_placeholder': false, + 'show_link_partner': true, 'view_inbox': false, 'message_ids': undefined, + 'compose_as_todo' : false, }, this.action.params); this.action.params.help = this.action.help || false; @@ -1441,7 +1446,6 @@ openerp.mail = function (session) { }); this.thread.appendTo( this.$el ); - this.thread.no_message(); if (this.action.params.show_compose_message) { this.thread.instantiate_compose_message(); diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index bb787c9a21b..cca908a5d98 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -34,14 +34,14 @@ - +