[MERGE]with parent
bzr revid: dusan@ubuntu-20121129174503-8dctjtx0mbs6q1qi
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -1238,7 +1238,7 @@
|
||||
<separator/>
|
||||
<filter string="Next Partner to Reconcile" help="Next Partner Entries to reconcile" name="next_partner" context="{'next_partner_only': 1}" icon="terp-gtk-jump-to-ltr" domain="[('account_id.reconcile','=',True),('reconcile_id','=',False)]"/>
|
||||
<field name="move_id" string="Number (Move)"/>
|
||||
<field name="account_id"/>
|
||||
<field name="account_id" filter_domain="['|', ('name', 'ilike', self), ('code', 'ilike', self)]"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="journal_id" context="{'journal_id':self}" widget="selection"/> <!-- it's important to keep widget='selection' in this filter viewbecause without that the value passed in the context is not the ID but the textual value (name) of the selected journal -->
|
||||
<field name="period_id" context="{'period_id':self}" widget="selection"/> <!-- it's important to keep the widget='selection' in this field, for the same reason as explained above -->
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
<!-- <field name="reconciled" sum="# Reconciled"/> -->
|
||||
<field name="user_currency_price_total" sum="Total Without Tax"/>
|
||||
<field name="user_currency_residual" sum="Total Residual" invisible="context.get('residual_invisible',False)"/>
|
||||
<field name="due_delay" sum="Avg. Due Delay" invisible="context.get('residual_invisible',False)"/>
|
||||
<field name="delay_to_pay" sum="Avg. Delay To Pay" invisible="context.get('residual_invisible',False)"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -93,7 +91,7 @@
|
||||
<field name="view_mode">tree,graph</field>
|
||||
<field name="context">{'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,}</field>
|
||||
<field name="search_view_id" ref="view_account_invoice_report_search"/>
|
||||
<field name="help">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.</field>
|
||||
<field name="help">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.</field>
|
||||
|
||||
</record>
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -147,6 +147,18 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_analytic_account_template_required" model="ir.ui.view">
|
||||
<field name="name">account.analytic.account.form.template.required</field>
|
||||
<field name="model">account.analytic.account</field>
|
||||
<field name="groups_id" eval="[(6, 0, [ref('group_template_required')])]"/>
|
||||
<field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="template_id" position="attributes">
|
||||
<attribute name="attrs">{'required': [('type','=','contract')], 'invisible': [('type','in',['view', 'normal','template'])]}</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="template_of_contract_action" model="ir.actions.act_window">
|
||||
<field name="name">Template of Contract</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
|
||||
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."),
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_sales_config" model="ir.ui.view">
|
||||
<field name="name">sale settings</field>
|
||||
<field name="model">sale.config.settings</field>
|
||||
<field name="inherit_id" ref="sale.view_sales_config"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='module_analytic_user_function']" position="inside">
|
||||
<div>
|
||||
<field name="group_template_required" class="oe_inline"/>
|
||||
<label for="group_template_required"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -6,5 +6,12 @@
|
||||
<field eval="[(4,ref('sale.group_analytic_accounting'))]" name="groups_id"/>
|
||||
</record>
|
||||
|
||||
<record id="group_template_required" model="res.groups">
|
||||
<field name="name">Mandatory use of templates in contracts</field>
|
||||
<field name="category_id" ref="base.module_category_sales_management"/>
|
||||
<field name="comment">the field template of the analytic accounts and contracts will be required.</field>
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</openerp>
|
||||
|
||||
@@ -43,10 +43,10 @@
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="//page[@name='statement_line_ids']/field[@name='line_ids']/tree/field[@name='date']" position="after">
|
||||
<field name="val_date"/>
|
||||
</xpath>
|
||||
<field name="val_date" invisible="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='statement_line_ids']/field[@name='line_ids']/tree/field[@name='amount']" position="after">
|
||||
<field name="globalisation_id" string="Glob. Id"/>
|
||||
<field name="globalisation_id" string="Glob. Id" invisible="1"/>
|
||||
<field name="state" invisible="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='statement_line_ids']/field[@name='line_ids']/form/group/field[@name='date']" position="after">
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
<field name="inherit_id" ref="account.view_bank_statement_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[@name='statement_line_ids']/field[@name='line_ids']/tree/field[@name='amount']" position="after">
|
||||
<field name="voucher_id" widget="many2onebutton" options="{'label':{'create':'Reconcile','edit':'Edit Reconciliation'}}" context="{'line_type': type, 'default_type': amount < 0 and 'payment' or 'receipt', 'type': amount < 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name, 'default_active': False}"/>
|
||||
<field name="voucher_id" string="" widget="many2onebutton" options="{'label':{'create':'Reconcile','edit':'Edit Reconciliation'}}" context="{'line_type': type, 'default_type': amount < 0 and 'payment' or 'receipt', 'type': amount < 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name, 'default_active': False}"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='statement_line_ids']/field[@name='line_ids']/form/group/field[@name='sequence']" position="before">
|
||||
<field name="voucher_id" widget="many2onebutton" options="{'label':{'create':'Reconcile','edit':'Edit Reconciliation'}}" context="{'line_type': type, 'default_type': amount < 0 and 'payment' or 'receipt', 'type': amount < 0 and 'payment' or 'receipt', 'default_partner_id': partner_id, 'default_journal_id': parent.journal_id, 'default_amount': abs(amount), 'default_reference': ref, 'default_date': date, 'default_name': name, 'default_active': False}"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@
|
||||
<field name="currency_id" attrs="{'invisible': ['|',('type', '<>', 'view'), ('company_id', '<>', False)]}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="code"/>
|
||||
<field name="type" invisible="context.get('default_type', False)"/>
|
||||
<field name="parent_id" on_change="on_change_parent(parent_id)" attrs="{'invisible': [('type','in',['contract','template'])]}"/>
|
||||
<field name="template_id" on_change="on_change_template(template_id,context)" domain="[('type','=','template')]" attrs="{'invisible': [('type','in',['view', 'normal','template'])]}" context="{'default_type' : 'template'}"/>
|
||||
<field name="code"/>
|
||||
<field name="parent_id" on_change="on_change_parent(parent_id)" attrs="{'invisible': [('type','in',['contract'])]}"/>
|
||||
<field name="company_id" on_change="on_change_company(company_id)" widget="selection" groups="base.group_multi_company" attrs="{'required': [('type','<>','view')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
<field name="partner_id" invisible="1"/>
|
||||
<field name="country_id" invisible="1"/>
|
||||
<field name="nbr" sum="# Leads"/>
|
||||
<field name="email" sum="# Mails"/>
|
||||
<field name="delay_open"/>
|
||||
<field name="delay_close"/>
|
||||
<field name="planned_revenue"/>
|
||||
@@ -148,7 +147,6 @@
|
||||
<field name="company_id" invisible="1" groups="base.group_multi_company"/>
|
||||
<field name="nbr" string="#Opportunities" sum="#Opportunities"/>
|
||||
<field name="planned_revenue" sum="Planned Revenues"/>
|
||||
<field name="email" sum="# of Emails"/>
|
||||
<field name="delay_open" sum='Delay to open'/>
|
||||
<field name="delay_close" sum='Delay to close'/>
|
||||
<field name="delay_expected"/>
|
||||
@@ -167,7 +165,7 @@
|
||||
<field name="context">{'search_default_year': 1,'search_default_lead': 1, "search_default_user":1, "search_default_this_month":1, 'group_by_no_leaf':1, 'group_by':[]}</field>
|
||||
<field name="view_mode">tree,graph</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="help">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.</field>
|
||||
<field name="help">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.</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_report_crm_lead_tree">
|
||||
<field name="sequence" eval="1"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
<field name="params" eval=""{
|
||||
'domain': [('partner_ids.user_ids', 'in', [uid])],
|
||||
'view_mailbox': True,
|
||||
'read_action': 'read', }""/>
|
||||
'read_action': 'read',
|
||||
'show_compose_message': False }""/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
<b>No private message.</b>
|
||||
@@ -64,7 +65,8 @@
|
||||
<field name="params" eval=""{
|
||||
'domain': [('favorite_user_ids', 'in', [uid])],
|
||||
'view_mailbox': True,
|
||||
'read_action': 'read', }""/>
|
||||
'read_action': 'read',
|
||||
'compose_as_todo': True }""/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
<b>No todo.</b>
|
||||
@@ -84,7 +86,8 @@
|
||||
}</field>
|
||||
<field name="params" eval=""{
|
||||
'domain': ['|', ('notification_ids.partner_id.user_ids', 'in', [uid]), ('author_id.user_ids', 'in', [uid])],
|
||||
'view_mailbox': True, }""/>
|
||||
'view_mailbox': True,
|
||||
'show_compose_message': False }""/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
No message found and no message sent yet.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -34,14 +34,14 @@
|
||||
<button class="oe_post">Post</button>
|
||||
<t t-call="mail.compose_message.add_attachment"/>
|
||||
<!--<a class="oe_cancel oe_e">X</a>-->
|
||||
<button class="oe_full"><span class='oe_e'>&ograve</span></button>
|
||||
<button class="oe_full" title="Open the full mail composer"><span class='oe_e'>&ograve</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="widget.show_compact_message and !widget.show_composer" t-attf-class="oe_msg oe_msg_composer_compact #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''}">
|
||||
<textarea t-if="widget.options.compose_placeholder" class="field_text oe_compact" t-att-placeholder="widget.options.compose_placeholder"/>
|
||||
<textarea t-if="!widget.options.compose_placeholder and !widget.options.view_mailbox" class="field_text oe_compact" placeholder="Write an internal note..."/>
|
||||
<textarea t-if="!widget.options.compose_placeholder and widget.options.view_mailbox" class="field_text oe_compact" placeholder="Share to my followers..."/>
|
||||
<textarea t-if="!widget.options.compose_placeholder and !widget.options.view_mailbox" class="field_text oe_compact" placeholder="Write to the followers of this document..."/>
|
||||
<textarea t-if="!widget.options.compose_placeholder and widget.options.view_mailbox" class="field_text oe_compact" placeholder="Share with my followers..."/>
|
||||
</div>
|
||||
<span t-if="!(widget.show_compact_message and !widget.show_composer) and !widget.show_composer" class="oe_placeholder_compose"></span>
|
||||
</t>
|
||||
@@ -75,9 +75,11 @@
|
||||
<t t-foreach='widget.attachment_ids' t-as='attachment'>
|
||||
<t t-if="attachment.filetype !== 'webimage'">
|
||||
<div t-attf-class="oe_attachment #{attachment.upload ? 'oe_uploading' : ''}">
|
||||
<a t-att-href='attachment.url'><img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.filetype + '.png'"></img></a>
|
||||
<a t-att-href='attachment.url'>
|
||||
<img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.filetype + '.png'"></img>
|
||||
<div class='oe_name'><t t-raw='attachment.name' /></div>
|
||||
</a>
|
||||
<div class='oe_delete oe_e' title="Delete this attachment" t-attf-data-id="{attachment.id}">[</div>
|
||||
<div class='oe_name'><t t-raw='attachment.name' /></div>
|
||||
<div class='oe_progress_bar'>
|
||||
uploading
|
||||
</div>
|
||||
@@ -85,9 +87,11 @@
|
||||
</t>
|
||||
<t t-if="attachment.filetype === 'webimage'">
|
||||
<div t-attf-class="oe_attachment oe_preview #{attachment.upload ? 'oe_uploading' : ''}">
|
||||
<a t-att-href='attachment.url'><img t-att-src="widget.attachments_resize_image(attachment.id, [100,80])"></img></a>
|
||||
<a t-att-href='attachment.url'>
|
||||
<img t-att-src="widget.attachments_resize_image(attachment.id, [100,80])"></img>
|
||||
<div class='oe_name'><t t-raw='attachment.name' /></div>
|
||||
</a>
|
||||
<div class='oe_delete oe_e'>[</div>
|
||||
<div class='oe_name'><t t-raw='attachment.name' /></div>
|
||||
<div class='oe_progress_bar'>
|
||||
uploading
|
||||
</div>
|
||||
@@ -111,7 +115,11 @@
|
||||
</t>
|
||||
<t t-if="!widget.is_private and widget.partner_ids.length"> and </t>
|
||||
<t t-set="inc" t-value="0"/>
|
||||
<t t-if="widget.partner_ids.length" t-foreach="widget.partner_ids" t-as="partner"><span t-attf-class="oe_partner_follower #{inc>=3?'oe_hidden':''}"><t t-if="inc" t-raw="', '"/><a t-attf-href="#model=res.partner&id=#{partner[0]}"><t t-raw="partner[1]"/></a></span><t t-set="inc" t-value="inc+1"/>
|
||||
<t t-if="widget.partner_ids.length" t-foreach="widget.partner_ids" t-as="partner">
|
||||
<span t-attf-class="oe_partner_follower #{inc>=3?'oe_hidden':''}"><t t-if="inc" t-raw="', '"/>
|
||||
<a t-if="widget.options.show_link_partner" t-attf-href="#model=res.partner&id=#{partner[0]}"><t t-raw="partner[1]"/></a>
|
||||
<t t-if="!widget.options.show_link_partner" t-raw="partner[1]"/>
|
||||
</span><t t-set="inc" t-value="inc+1"/>
|
||||
</t>
|
||||
<t t-if="widget.partner_ids.length>=3">
|
||||
<span class="oe_more">, <a><t t-raw="widget.partner_ids.length-3"/> others...</a></span>
|
||||
@@ -148,7 +156,7 @@
|
||||
</td>
|
||||
<td><div class="oe_view_manager_view_search" t-opentag="true"/></td>
|
||||
</tr>
|
||||
<tr class="oe_header_row" t-if="widget.action.params.view_inbox" >
|
||||
<tr class="oe_header_row" t-if="widget.action.params.view_inbox and widget.action.params.show_compose_message" >
|
||||
<td colspan="2">
|
||||
<button type="button" class="oe_write_full oe_highlight">
|
||||
Compose a new message
|
||||
@@ -190,14 +198,15 @@
|
||||
<div t-attf-class="oe_msg #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''} oe_msg_#{widget.type}">
|
||||
|
||||
<div class='oe_msg_left'>
|
||||
<a t-attf-href="#model=res.partner&id=#{widget.author_id[0]}" t-att-title="widget.author_id[1]">
|
||||
<a t-if="widget.options.show_link_partner" t-attf-href="#model=res.partner&id=#{widget.author_id[0]}" t-att-title="widget.author_id[1]">
|
||||
<img class="oe_msg_icon" t-att-src="widget.avatar"/>
|
||||
</a>
|
||||
<img t-if="!widget.options.show_link_partner" class="oe_msg_icon" t-att-src="widget.avatar"/>
|
||||
</div>
|
||||
|
||||
<div class="oe_msg_center">
|
||||
<div class='oe_msg_icons'>
|
||||
<span class='oe_read' t-if="widget.options.show_read"><a title="Done" class="oe_e">X</a></span>
|
||||
<span class='oe_read' t-if="widget.options.show_read"><a title="Done" class="oe_e">W</a></span>
|
||||
<span class='oe_unread' t-if="widget.is_favorite and widget.options.show_unread"><a title="Set back to Todo" class="oe_e">v</a></span>
|
||||
<span class='oe_unread' t-if="!widget.is_favorite and widget.options.show_unread"><a title="Set back to Inbox" class="oe_e">v</a></span>
|
||||
<span class='oe_reply' t-if="widget.options.show_reply_button"><a title="Reply" class="oe_e">(</a></span>
|
||||
@@ -217,7 +226,8 @@
|
||||
<t t-if="widget.attachment_ids.length > 0">
|
||||
<div class="oe_msg_attachment_list"></div>
|
||||
</t>
|
||||
<a t-if="widget.author_id" t-attf-href="#model=res.partner&id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a>
|
||||
<a t-if="widget.author_id and widget.options.show_link_partner" t-attf-href="#model=res.partner&id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a>
|
||||
<span t-if="widget.author_id and !widget.options.show_link_partner"><t t-raw="widget.author_id[1]"/></span>
|
||||
<span class='oe_subtle'>•</span>
|
||||
<span t-att-title="widget.date"><t t-raw="widget.timerelative"/></span>
|
||||
<span class='oe_subtle'>•</span>
|
||||
|
||||
@@ -6,10 +6,5 @@
|
||||
<field name="name">Notes / Fancy mode</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
<record id="base.group_user" model="res.groups">
|
||||
<field name="implied_ids" eval="[(4, ref('group_note_fancy'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -546,7 +546,7 @@ class product_product(osv.osv):
|
||||
'default_code' : fields.char('Internal Reference', size=64, select=True),
|
||||
'active': fields.boolean('Active', help="If unchecked, it will allow you to hide the product without removing it."),
|
||||
'variants': fields.char('Variants', size=64),
|
||||
'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete="cascade"),
|
||||
'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete="cascade", select=True),
|
||||
'ean13': fields.char('EAN13 Barcode', size=13, help="International Article Number used for product identification."),
|
||||
'packaging' : fields.one2many('product.packaging', 'product_id', 'Logistical Units', help="Gives the different ways to package the same product. This has no impact on the picking order and is mainly used if you use the EDI module."),
|
||||
'price_extra': fields.float('Variant Price Extra', digits_compute=dp.get_precision('Product Price')),
|
||||
|
||||
@@ -49,11 +49,17 @@ class project_task_type(osv.osv):
|
||||
'fold': fields.boolean('Hide in views if empty',
|
||||
help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
|
||||
}
|
||||
def _get_default_project_id(self, cr, uid, ctx={}):
|
||||
proj = ctx.get('default_project_id', False)
|
||||
if type(proj) is int:
|
||||
return [proj]
|
||||
return proj
|
||||
_defaults = {
|
||||
'sequence': 1,
|
||||
'state': 'open',
|
||||
'fold': False,
|
||||
'case_default': True,
|
||||
'project_ids': _get_default_project_id
|
||||
}
|
||||
_order = 'sequence'
|
||||
|
||||
@@ -603,18 +609,13 @@ class task(base_stage, osv.osv):
|
||||
stage_obj = self.pool.get('project.task.type')
|
||||
order = stage_obj._order
|
||||
access_rights_uid = access_rights_uid or uid
|
||||
# lame way to allow reverting search, should just work in the trivial case
|
||||
if read_group_order == 'stage_id desc':
|
||||
order = '%s desc' % order
|
||||
# retrieve section_id from the context and write the domain
|
||||
# - ('id', 'in', 'ids'): add columns that should be present
|
||||
# - OR ('case_default', '=', True), ('fold', '=', False): add default columns that are not folded
|
||||
# - OR ('project_ids', 'in', project_id), ('fold', '=', False) if project_id: add project columns that are not folded
|
||||
search_domain = []
|
||||
project_id = self._resolve_project_id_from_context(cr, uid, context=context)
|
||||
if project_id:
|
||||
search_domain += ['|', ('project_ids', '=', project_id)]
|
||||
search_domain += ['|', ('id', 'in', ids), ('case_default', '=', True)]
|
||||
search_domain += [('id', 'in', ids)]
|
||||
stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context)
|
||||
result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
|
||||
# restore order of the search
|
||||
@@ -750,7 +751,7 @@ class task(base_stage, osv.osv):
|
||||
'priority': fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Important'), ('0','Very important')], 'Priority', select=True),
|
||||
'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of tasks."),
|
||||
'stage_id': fields.many2one('project.task.type', 'Stage',
|
||||
domain="['&', ('fold', '=', False), '|', ('project_ids', '=', project_id), ('case_default', '=', True)]"),
|
||||
domain="['&', ('fold', '=', False), ('project_ids', '=', project_id)]"),
|
||||
'state': fields.related('stage_id', 'state', type="selection", store=True,
|
||||
selection=_TASK_STATE, string="Status", readonly=True,
|
||||
help='The status is set to \'Draft\', when a case is created.\
|
||||
@@ -936,14 +937,11 @@ class task(base_stage, osv.osv):
|
||||
for task in cases:
|
||||
if task.project_id:
|
||||
section_ids.append(task.project_id.id)
|
||||
# OR all section_ids and OR with case_default
|
||||
search_domain = []
|
||||
if section_ids:
|
||||
search_domain += [('|')] * len(section_ids)
|
||||
search_domain = [('|')] * (len(section_ids)-1)
|
||||
for section_id in section_ids:
|
||||
search_domain.append(('project_ids', '=', section_id))
|
||||
search_domain.append(('case_default', '=', True))
|
||||
# AND with the domain in parameter
|
||||
search_domain += list(domain)
|
||||
# perform search, return the first found
|
||||
stage_ids = self.pool.get('project.task.type').search(cr, uid, search_domain, order=order, context=context)
|
||||
|
||||
@@ -36,7 +36,11 @@
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="description">Implement new website for Sale and Warehouse Management for a customer.</field>
|
||||
<field name="alias_model">project.task</field>
|
||||
<field name="type_ids" eval="[(6, 0, [ref('project_tt_analysis'),ref('project_tt_specification'),ref('project_tt_development'),ref('project_tt_testing'),ref('project_tt_deployment')])]"/>
|
||||
</record>
|
||||
|
||||
<!-- We assign after so that default values applies -->
|
||||
<record id="project_project_1" model="project.project">
|
||||
<field name="type_ids" eval="[(4, ref('project_tt_analysis')) ,(4,ref('project_tt_specification')), (4,ref('project_tt_development')), (4,ref('project_tt_testing')), (4,ref('project_tt_deployment'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="project_project_2" model="project.project">
|
||||
@@ -45,7 +49,11 @@
|
||||
<field name="privacy_visibility">public</field>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="alias_model">project.task</field>
|
||||
<field name="type_ids" eval="[(6, 0, [ref('project_tt_specification'),ref('project_tt_development'),ref('project_tt_testing'),ref('project_tt_merge'),ref('project_tt_deployment')])]"/>
|
||||
</record>
|
||||
|
||||
<!-- We assign after so that default values applies -->
|
||||
<record id="project_project_2" model="project.project">
|
||||
<field name="type_ids" eval="[(4, ref('project_tt_specification')),(4,ref('project_tt_development')),(4,ref('project_tt_testing')),(4,ref('project_tt_merge')),(4,ref('project_tt_deployment'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="project_project_3" model="project.project">
|
||||
@@ -55,10 +63,11 @@
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="alias_model">project.task</field>
|
||||
<field name="privacy_visibility">public</field>
|
||||
<field name="members" eval="[(6, 0, [
|
||||
ref('base.user_root'),
|
||||
ref('base.user_demo')])]"/>
|
||||
<field name="type_ids" eval="[(6, 0, [ref('project_tt_specification'),ref('project_tt_development'),ref('project_tt_testing'),ref('project_tt_merge'),ref('project_tt_deployment')])]"/>
|
||||
<field name="members" eval="[(4, ref('base.user_root')), (4, ref('base.user_demo'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="project_project_3" model="project.project">
|
||||
<field name="type_ids" eval="[(4, ref('project_tt_specification')),(4,ref('project_tt_development')),(4,ref('project_tt_testing')),(4,ref('project_tt_merge')),(4,ref('project_tt_deployment'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="project_project_4" model="project.project">
|
||||
@@ -67,10 +76,11 @@
|
||||
<field name="name">Website Design Templates</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="alias_model">project.task</field>
|
||||
<field name="type_ids" eval="[(6, 0, [ref('project_tt_design'),ref('project_tt_development'),ref('project_tt_testing')])]"/>
|
||||
<field name="members" eval="[(6, 0, [
|
||||
ref('base.user_root'),
|
||||
ref('base.user_demo')])]"/>
|
||||
<field name="members" eval="[(4, ref('base.user_root')), (4,ref('base.user_demo'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="project_project_4" model="project.project">
|
||||
<field name="type_ids" eval="[(4, ref('project_tt_design')),(4,ref('project_tt_development')),(4,ref('project_tt_testing'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="project_project_5" model="project.project">
|
||||
@@ -79,12 +89,15 @@
|
||||
<field name="partner_id" ref="base.res_partner_7"/>
|
||||
<field name="name">Data Import/Export Plugin</field>
|
||||
<field name="alias_model">project.task</field>
|
||||
<field name="type_ids" eval="[(6, 0, [ref('project_tt_development')])]"/>
|
||||
<field name="members" eval="[(6, 0, [
|
||||
ref('base.user_root'),
|
||||
ref('base.user_demo')])]"/>
|
||||
</record>
|
||||
|
||||
<record id="project_project_5" model="project.project">
|
||||
<field name="type_ids" eval="[(4, ref('project_tt_development'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Tasks -->
|
||||
<record id="project_task_1" model="project.task">
|
||||
|
||||
@@ -89,7 +89,7 @@ class project_issue(base_stage, osv.osv):
|
||||
project_id = self._resolve_project_id_from_context(cr, uid, context=context)
|
||||
if project_id:
|
||||
search_domain += ['|', ('project_ids', '=', project_id)]
|
||||
search_domain += ['|', ('id', 'in', ids), ('case_default', '=', True)]
|
||||
search_domain += [('id', 'in', ids)]
|
||||
# perform search
|
||||
stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context)
|
||||
result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
|
||||
@@ -225,7 +225,7 @@ class project_issue(base_stage, osv.osv):
|
||||
Define Responsible user and Email account for mail gateway.'),
|
||||
'partner_id': fields.many2one('res.partner', 'Contact', select=1),
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
'description': fields.text('Description'),
|
||||
'description': fields.text('Private Note'),
|
||||
'state': fields.related('stage_id', 'state', type="selection", store=True,
|
||||
selection=_ISSUE_STATE, string="Status", readonly=True,
|
||||
help='The status is set to \'Draft\', when a case is created.\
|
||||
@@ -244,7 +244,7 @@ class project_issue(base_stage, osv.osv):
|
||||
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True),
|
||||
'version_id': fields.many2one('project.issue.version', 'Version'),
|
||||
'stage_id': fields.many2one ('project.task.type', 'Stage',
|
||||
domain="['&', ('fold', '=', False), '|', ('project_ids', '=', project_id), ('case_default', '=', True)]"),
|
||||
domain="['&', ('fold', '=', False), ('project_ids', '=', project_id)]"),
|
||||
'project_id':fields.many2one('project.project', 'Project'),
|
||||
'duration': fields.float('Duration'),
|
||||
'task_id': fields.many2one('project.task', 'Task', domain="[('project_id','=',project_id)]"),
|
||||
@@ -442,11 +442,9 @@ class project_issue(base_stage, osv.osv):
|
||||
# OR all section_ids and OR with case_default
|
||||
search_domain = []
|
||||
if section_ids:
|
||||
search_domain += [('|')] * len(section_ids)
|
||||
search_domain += [('|')] * (len(section_ids)-1)
|
||||
for section_id in section_ids:
|
||||
search_domain.append(('project_ids', '=', section_id))
|
||||
search_domain.append(('case_default', '=', True))
|
||||
# AND with the domain in parameter
|
||||
search_domain += list(domain)
|
||||
# perform search, return the first found
|
||||
stage_ids = self.pool.get('project.task.type').search(cr, uid, search_domain, order=order, context=context)
|
||||
|
||||
@@ -111,26 +111,26 @@
|
||||
<field name="user_id"/>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id, email_from)"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="priority" groups="base.group_user"/>
|
||||
<label for="project_id" groups="base.group_user"/>
|
||||
<div groups="base.group_user">
|
||||
<field name="project_id" on_change="on_change_project(project_id)" class="oe_inline" context="{'default_use_issues':1}"/>
|
||||
<button name="case_escalate" string="Escalate" type="object" states="draft,open,pending" class="oe_inline"/>
|
||||
<button name="case_escalate" string="⇒ Escalate" type="object" states="draft,open,pending" class="oe_link"/>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<field name="categ_ids" widget="many2many_tags"/>
|
||||
<field name="version_id" groups="base.group_user"/>
|
||||
<field name="priority" groups="base.group_user"/>
|
||||
<label for="task_id" groups="base.group_user"/>
|
||||
<div groups="base.group_user">
|
||||
<field name="task_id" on_change="onchange_task_id(task_id)" class="oe_inline" context="{'default_project_id':project_id}"/>
|
||||
<field name="progress" widget="progressbar" attrs="{'invisible':[('task_id','=',False)]}" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="categ_ids" widget="many2many_tags"/>
|
||||
<field name="version_id" groups="base.group_user"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Description">
|
||||
<field name="description" placeholder="Add a description..."/>
|
||||
<field name="description" placeholder="Add an internal note..." groups="base.group_user"/>
|
||||
</page>
|
||||
<page string="Extra Info" groups="base.group_no_one">
|
||||
<group col="4" colspan="4">
|
||||
|
||||
@@ -86,13 +86,13 @@
|
||||
your customer.
|
||||
</p>
|
||||
<group>
|
||||
<label for="id" string="Contract Feature"/>
|
||||
<label for="id" string="Contract Features"/>
|
||||
<div>
|
||||
<div>
|
||||
<field name="module_account_analytic_analysis" on_change="onchange_timesheet(module_account_analytic_analysis)" class="oe_inline"/>
|
||||
<label for="module_account_analytic_analysis"/>
|
||||
</div>
|
||||
<div attrs="{'invisible':[('module_account_analytic_analysis','=',False)]}">
|
||||
<div name="module_analytic_user_function" attrs="{'invisible':[('module_account_analytic_analysis','=',False)]}">
|
||||
<field name="module_analytic_user_function" class="oe_inline"/>
|
||||
<label for="module_analytic_user_function"/>
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,10 @@ class account_invoice_report(osv.osv):
|
||||
}
|
||||
|
||||
def _select(self):
|
||||
return super(account_invoice_report, self)._select() + ", ai.section_id as section_id"
|
||||
return super(account_invoice_report, self)._select() + ", sub.section_id as section_id"
|
||||
|
||||
def _sub_select(self):
|
||||
return super(account_invoice_report, self)._sub_select() + ", ai.section_id as section_id"
|
||||
|
||||
def _group_by(self):
|
||||
return super(account_invoice_report, self)._group_by() + ", ai.section_id"
|
||||
|
||||
Reference in New Issue
Block a user