[MERGE] from chm
bzr revid: fva@openerp.com-20121024095015-9wa4n5br1ps1ijc4
This commit is contained in:
@@ -1431,6 +1431,9 @@ class account_move(osv.osv):
|
||||
if 'line_id' in vals:
|
||||
c = context.copy()
|
||||
c['novalidate'] = True
|
||||
c['period_id'] = vals['period_id']
|
||||
c['journal_id'] = vals['journal_id']
|
||||
c['date'] = vals['date']
|
||||
result = super(account_move, self).create(cr, uid, vals, c)
|
||||
self.validate(cr, uid, [result], context)
|
||||
else:
|
||||
|
||||
@@ -143,13 +143,11 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Supplier Invoice" version="7.0">
|
||||
<header>
|
||||
<span groups="base.group_user">
|
||||
<button name="invoice_open" states="draft,proforma2" string="Validate" class="oe_highlight"/>
|
||||
<button name="%(action_account_invoice_refund)d" type='action' string='Ask Refund' states='open,paid' />
|
||||
<button name="invoice_open" states="draft,proforma2" string="Validate" class="oe_highlight" groups="account.group_account_invoice"/>
|
||||
<button name="%(action_account_invoice_refund)d" type='action' string='Ask Refund' states='open,paid' groups="account.group_account_invoice"/>
|
||||
<button name="invoice_cancel" states="draft,proforma2,sale,open" string="Cancel" groups="base.group_no_one"/>
|
||||
<button name="action_cancel_draft" states="cancel" string="Set to Draft" type="object"/>
|
||||
<button name="action_cancel_draft" states="cancel" string="Set to Draft" type="object" groups="account.group_account_invoice"/>
|
||||
<button name='%(action_account_state_open)d' type='action' string='Re-Open' groups="account.group_account_invoice" attrs="{'invisible':['|', ('state','<>','paid'), ('reconciled', '=', True)]}" help="This button only appears when the state of the invoice is 'paid' (showing that it has been fully reconciled) and auto-computed boolean 'reconciled' is False (depicting that it's not the case anymore). In other words, the invoice has been dereconciled and it does not fit anymore the 'paid' state. You should press this button to re-open it and let it continue its normal process after having resolved the eventual exceptions it may have created."/>
|
||||
</span>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,open,paid" statusbar_colors='{"proforma":"blue","proforma2":"blue"}'/>
|
||||
</header>
|
||||
<sheet string="Supplier Invoice">
|
||||
@@ -291,20 +289,18 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Invoice" version="7.0">
|
||||
<header>
|
||||
<span groups="base.group_user">
|
||||
<button name="action_invoice_sent" type="object" string="Send by Email" attrs="{'invisible':['|',('sent','=',True), ('state', '!=', 'open')]}" class="oe_highlight"/>
|
||||
<button name="invoice_print" string="Print Invoice" type="object" attrs="{'invisible':['|',('sent','=',True), ('state', '!=', 'open')]}" class="oe_highlight"/>
|
||||
<button name="action_invoice_sent" type="object" string="Send by Email" attrs="{'invisible':['|',('sent','=',False), ('state', '!=', 'open')]}"/>
|
||||
<button name="invoice_print" string="Print Invoice" type="object" attrs="{'invisible':['|',('sent','=',False), ('state', '!=', 'open')]}"/>
|
||||
<button name="invoice_open" states="draft" string="Validate" class="oe_highlight"/>
|
||||
<button name="invoice_open" states="proforma2" string="Validate"/>
|
||||
<button name="invoice_proforma2" states="draft" string="PRO-FORMA" groups="account.group_proforma_invoices"/>
|
||||
<button name="%(action_account_invoice_refund)d" type='action' string='Refund Invoice' states='open,proforma2,paid'/>
|
||||
<button name="invoice_cancel" states="draft,proforma2,open" string="Cancel" groups="base.group_no_one"/>
|
||||
<button name="action_cancel_draft" states="cancel" string="Reset to Draft" type="object"/>
|
||||
<button name='%(action_account_state_open)d' type='action' string='Re-Open' groups="account.group_account_invoice" attrs="{'invisible':['|', ('state','<>','paid'), ('reconciled', '=', True)]}" help="This button only appears when the state of the invoice is 'paid' (showing that it has been fully reconciled) and auto-computed boolean 'reconciled' is False (depicting that it's not the case anymore). In other words, the invoice has been dereconciled and it does not fit anymore the 'paid' state. You should press this button to re-open it and let it continue its normal process after having resolved the eventual exceptions it may have created."/>
|
||||
<!--button name="%(account_invoices)d" string="Print Invoice" type="action" states="open,paid,proforma,sale,proforma2"/-->
|
||||
</span>
|
||||
<button name="action_invoice_sent" type="object" string="Send by Email" attrs="{'invisible':['|',('sent','=',True), ('state', '!=', 'open')]}" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="invoice_print" string="Print Invoice" type="object" attrs="{'invisible':['|',('sent','=',True), ('state', '!=', 'open')]}" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="action_invoice_sent" type="object" string="Send by Email" attrs="{'invisible':['|',('sent','=',False), ('state', '!=', 'open')]}" groups="base.group_user"/>
|
||||
<button name="invoice_print" string="Print Invoice" type="object" attrs="{'invisible':['|',('sent','=',False), ('state', '!=', 'open')]}" groups="base.group_user"/>
|
||||
<button name="invoice_open" states="draft" string="Validate" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="invoice_open" states="proforma2" string="Validate" groups="base.group_user"/>
|
||||
<button name="invoice_proforma2" states="draft" string="PRO-FORMA" groups="account.group_proforma_invoices"/>
|
||||
<button name="%(action_account_invoice_refund)d" type='action' string='Refund Invoice' states='open,proforma2,paid' groups="base.group_user"/>
|
||||
<button name="invoice_cancel" states="draft,proforma2,open" string="Cancel" groups="base.group_no_one"/>
|
||||
<button name="action_cancel_draft" states="cancel" string="Reset to Draft" type="object" groups="base.group_user"/>
|
||||
<button name='%(action_account_state_open)d' type='action' string='Re-Open' groups="account.group_account_invoice" attrs="{'invisible':['|', ('state','<>','paid'), ('reconciled', '=', True)]}" help="This button only appears when the state of the invoice is 'paid' (showing that it has been fully reconciled) and auto-computed boolean 'reconciled' is False (depicting that it's not the case anymore). In other words, the invoice has been dereconciled and it does not fit anymore the 'paid' state. You should press this button to re-open it and let it continue its normal process after having resolved the eventual exceptions it may have created."/>
|
||||
<!--button name="%(account_invoices)d" string="Print Invoice" type="action" states="open,paid,proforma,sale,proforma2"/-->
|
||||
<field name="state" widget="statusbar" nolabel="1" statusbar_visible="draft,open,paid" statusbar_colors='{"proforma":"blue","proforma2":"blue"}'/>
|
||||
</header>
|
||||
<sheet string="Invoice">
|
||||
|
||||
@@ -1234,16 +1234,16 @@ class account_move_line(osv.osv):
|
||||
vals['company_id'] = company_id[0]
|
||||
if ('account_id' in vals) and not account_obj.read(cr, uid, vals['account_id'], ['active'])['active']:
|
||||
raise osv.except_osv(_('Bad Account!'), _('You cannot use an inactive account.'))
|
||||
if 'journal_id' in vals:
|
||||
if 'journal_id' in vals and vals['journal_id']:
|
||||
context['journal_id'] = vals['journal_id']
|
||||
if 'period_id' in vals:
|
||||
if 'period_id' in vals and vals['period_id']:
|
||||
context['period_id'] = vals['period_id']
|
||||
if ('journal_id' not in context) and ('move_id' in vals) and vals['move_id']:
|
||||
m = move_obj.browse(cr, uid, vals['move_id'])
|
||||
context['journal_id'] = m.journal_id.id
|
||||
context['period_id'] = m.period_id.id
|
||||
#we need to treat the case where a value is given in the context for period_id as a string
|
||||
if 'period_id' not in context or not isinstance(context.get('period_id', ''), (int, long)):
|
||||
if 'period_id' in context and not isinstance(context.get('period_id', ''), (int, long)):
|
||||
period_candidate_ids = self.pool.get('account.period').name_search(cr, uid, name=context.get('period_id',''))
|
||||
if len(period_candidate_ids) != 1:
|
||||
raise osv.except_osv(_('Error!'), _('No period found or more than one period found for the given date.'))
|
||||
@@ -1253,6 +1253,9 @@ class account_move_line(osv.osv):
|
||||
self._update_journal_check(cr, uid, context['journal_id'], context['period_id'], context)
|
||||
move_id = vals.get('move_id', False)
|
||||
journal = journal_obj.browse(cr, uid, context['journal_id'], context=context)
|
||||
vals['journal_id'] = vals.get('journal_id') or context.get('journal_id')
|
||||
vals['period_id'] = vals.get('period_id') or context.get('period_id')
|
||||
vals['date'] = vals.get('date') or context.get('date')
|
||||
if not move_id:
|
||||
if journal.centralisation:
|
||||
#Check for centralisation
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
</div>
|
||||
</group>
|
||||
<group string="Product Information">
|
||||
<field name="product_id"/>
|
||||
<field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id, journal_id)"/>
|
||||
<label for="unit_amount"/>
|
||||
<div>
|
||||
<field name="unit_amount" class="oe_inline"/>
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_default_9">[[ o.title.name or '' ]] [[ o.name ]]</para>
|
||||
<para style="terp_default_9">[[ display_address(o.partner_id) ]]</para>
|
||||
<para style="terp_default_9">[[ display_address(o) ]]</para>
|
||||
<para style="terp_default_9">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
|
||||
@@ -11,7 +11,7 @@ openerp.account = function (instance) {
|
||||
this._super.apply(this, arguments);
|
||||
var self = this;
|
||||
this.current_partner = null;
|
||||
this.do_select.add(function() {
|
||||
this.on('record_selected', this, function() {
|
||||
if (self.get_selected_ids().length === 0) {
|
||||
self.$(".oe_account_recon_reconcile").attr("disabled", "");
|
||||
} else {
|
||||
@@ -19,7 +19,7 @@ openerp.account = function (instance) {
|
||||
}
|
||||
});
|
||||
},
|
||||
on_loaded: function() {
|
||||
load_list: function() {
|
||||
var self = this;
|
||||
var tmp = this._super.apply(this, arguments);
|
||||
if (this.partners) {
|
||||
@@ -102,7 +102,6 @@ openerp.account = function (instance) {
|
||||
action_id: result[1],
|
||||
context: additional_context
|
||||
}).then(function (result) {
|
||||
result = result.result;
|
||||
result.context = _.extend(result.context || {}, additional_context);
|
||||
result.flags = result.flags || {};
|
||||
result.flags.new_window = true;
|
||||
@@ -121,6 +120,10 @@ openerp.account = function (instance) {
|
||||
self.do_search(self.last_domain, self.last_context, self.last_group_by);
|
||||
});
|
||||
},
|
||||
do_select: function (ids, records) {
|
||||
this.trigger('record_selected')
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
@@ -11,21 +11,18 @@
|
||||
-
|
||||
!record {model: account.move, id: account_move_0}:
|
||||
date: !eval time.strftime('%Y-%m-%d')
|
||||
period_id: account.period_6
|
||||
journal_id: account.bank_journal
|
||||
line_id:
|
||||
- account_id: account.cash
|
||||
amount_currency: 0.0
|
||||
credit: 2000.0
|
||||
date: !eval time.strftime('%Y-%m-%d')
|
||||
debit: 0.0
|
||||
journal_id: account.bank_journal
|
||||
name: Basic Computer
|
||||
partner_id: base.res_partner_12
|
||||
period_id: account.period_6
|
||||
ref: '2011010'
|
||||
tax_amount: 0.0
|
||||
name: /
|
||||
period_id: account.period_6
|
||||
ref: '2011010'
|
||||
state: draft
|
||||
-
|
||||
@@ -110,4 +107,4 @@
|
||||
partial_reconcile = self.trans_rec_reconcile_partial_reconcile(cr, uid, [ref('account_move_line_reconcile0')], {'lang': u'en_US',
|
||||
'active_model': 'account.move.line', 'active_ids': ids, 'tz': False, 'active_id': ids[0]})
|
||||
move_line = move_line_obj.browse(cr, uid, ids)
|
||||
assert move_line[0].reconcile_partial_id, "Partial reconcilation is not done"
|
||||
assert move_line[0].reconcile_partial_id, "Partial reconcilation is not done"
|
||||
|
||||
@@ -1,38 +1,23 @@
|
||||
# Spanish translation for openobject-addons
|
||||
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
|
||||
# Spanish (Mexico) 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 <EMAIL@ADDRESS>, 2010.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
|
||||
"PO-Revision-Date: 2010-11-23 09:43+0000\n"
|
||||
"Last-Translator: Jordi Esteve (www.zikzakmedia.com) "
|
||||
"<jesteve@zikzakmedia.com>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"POT-Creation-Date: 2012-02-08 00:35+0000\n"
|
||||
"PO-Revision-Date: 2012-10-22 17:44+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Spanish (Mexico) <es_MX@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-09-05 05:48+0000\n"
|
||||
"X-Generator: Launchpad (build 13830)\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-23 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16179)\n"
|
||||
|
||||
#. module: account_cancel
|
||||
#: model:ir.module.module,description:account_cancel.module_meta_information
|
||||
msgid ""
|
||||
"\n"
|
||||
" Module adds 'Allow cancelling entries' field on form view of account "
|
||||
"journal. If set to true it allows user to cancel entries & invoices.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Este módulo añade el campo 'Permitir la cancelación de asientos' en la "
|
||||
"vista de formulario de los diarios contables. Si está marcado, permite a los "
|
||||
"usuarios cancelar los asientos y las facturas.\n"
|
||||
" "
|
||||
|
||||
#. module: account_cancel
|
||||
#: model:ir.module.module,shortdesc:account_cancel.module_meta_information
|
||||
msgid "Account Cancel"
|
||||
msgstr "Cancelar asientos/facturas"
|
||||
#: view:account.invoice:0
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
@@ -1422,7 +1422,7 @@ class account_voucher_line(osv.osv):
|
||||
}
|
||||
|
||||
def onchange_reconcile(self, cr, uid, ids, reconcile, amount, amount_unreconciled, context=None):
|
||||
vals = { 'amount': 0.0}
|
||||
vals = {'amount': 0.0}
|
||||
if reconcile:
|
||||
vals = { 'amount': amount_unreconciled}
|
||||
return {'value': vals}
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
account_id: account.cash
|
||||
amount: 1000.0
|
||||
company_id: base.main_company
|
||||
currency_id: base.EUR
|
||||
journal_id: account.bank_journal
|
||||
name: Voucher Axelor
|
||||
narration: PC Assemble SC234
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
'account_id': ref('account.cash'),
|
||||
'amount': 450.0,
|
||||
'company_id': ref('base.main_company'),
|
||||
'currency_id': ref('base.EUR'),
|
||||
'journal_id': ref('account.bank_journal'),
|
||||
'partner_id': ref('base.res_partner_19'),
|
||||
'period_id': ref('account.period_8'),
|
||||
@@ -53,6 +52,10 @@
|
||||
}
|
||||
if not res['value']['line_cr_ids']:
|
||||
res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}]
|
||||
#clients aren't sending value of readonly fields in the view, and there is a good reason for that, so here the
|
||||
#create should only use values of fields that are not readonly. That's why i'm removing some of these values
|
||||
del(res['value']['line_cr_ids'][0]['date_original'])
|
||||
del(res['value']['line_cr_ids'][0]['date_due'])
|
||||
res['value']['line_cr_ids'][0]['amount'] = 450.0
|
||||
vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']]
|
||||
id = self.create(cr, uid, vals)
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
'account_id': ref('account.cash'),
|
||||
'amount': 30000.0,
|
||||
'company_id': ref('base.main_company'),
|
||||
'currency_id': ref('base.EUR'),
|
||||
'journal_id': ref('account.bank_journal'),
|
||||
'partner_id': ref('base.res_partner_19'),
|
||||
'period_id': ref('account.period_8'),
|
||||
|
||||
@@ -32,13 +32,23 @@ import datetime
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
|
||||
from itertools import groupby
|
||||
from operator import itemgetter
|
||||
|
||||
|
||||
FIELD_STATES = [('clear', 'Clear'), ('anonymized', 'Anonymized'), ('not_existing', 'Not Existing')]
|
||||
ANONYMIZATION_STATES = FIELD_STATES + [('unstable', 'Unstable')]
|
||||
WIZARD_ANONYMIZATION_STATES = [('clear', 'Clear'), ('anonymized', 'Anonymized'), ('unstable', 'Unstable')]
|
||||
ANONYMIZATION_HISTORY_STATE = [('started', 'Started'), ('done', 'Done'), ('in_exception', 'Exception occured')]
|
||||
ANONYMIZATION_DIRECTION = [('clear -> anonymized', 'clear -> anonymized'), ('anonymized -> clear', 'anonymized -> clear')]
|
||||
|
||||
|
||||
def group(lst, cols):
|
||||
if isinstance(cols, basestring):
|
||||
cols = [cols]
|
||||
return dict((k, [v for v in itr]) for k, itr in groupby(sorted(lst, key=itemgetter(*cols)), itemgetter(*cols)))
|
||||
|
||||
|
||||
class ir_model_fields_anonymization(osv.osv):
|
||||
_name = 'ir.model.fields.anonymization'
|
||||
_rec_name = 'field_id'
|
||||
@@ -207,8 +217,6 @@ class ir_model_fields_anonymization(osv.osv):
|
||||
'state': lambda *a: 'clear',
|
||||
}
|
||||
|
||||
ir_model_fields_anonymization()
|
||||
|
||||
|
||||
class ir_model_fields_anonymization_history(osv.osv):
|
||||
_name = 'ir.model.fields.anonymization.history'
|
||||
@@ -223,8 +231,6 @@ class ir_model_fields_anonymization_history(osv.osv):
|
||||
'filepath': fields.char(string='File path', size=256, readonly=True),
|
||||
}
|
||||
|
||||
ir_model_fields_anonymization_history()
|
||||
|
||||
|
||||
class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
||||
_name = 'ir.model.fields.anonymize.wizard'
|
||||
@@ -250,8 +256,8 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
||||
'name': fields.char(size=64, string='File Name'),
|
||||
'summary': fields.function(_get_summary, type='text', string='Summary'),
|
||||
'file_export': fields.binary(string='Export'),
|
||||
'file_import': fields.binary(string='Import'),
|
||||
'state': fields.function(_get_state, string='Status', type='selection', selection=ANONYMIZATION_STATES, readonly=False),
|
||||
'file_import': fields.binary(string='Import', help="This is the file created by the anonymization process. It should have the '.pickle' extention."),
|
||||
'state': fields.function(_get_state, string='Status', type='selection', selection=WIZARD_ANONYMIZATION_STATES, readonly=False),
|
||||
'msg': fields.text(string='Message'),
|
||||
}
|
||||
|
||||
@@ -319,6 +325,7 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
||||
# clicked in the menu and the fields are already anonymized
|
||||
placeholder.addnext(etree.Element('newline'))
|
||||
placeholder.addnext(etree.Element('field', {'name': 'file_import', 'required': "1"}))
|
||||
placeholder.addnext(etree.Element('label', {'string': 'Anonymization file'}))
|
||||
eview.remove(placeholder)
|
||||
elif step == 'just_anonymized':
|
||||
# we just ran the anonymization process, we need the file export field
|
||||
@@ -500,7 +507,6 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
||||
|
||||
def reverse_anonymize_database(self, cr, uid, ids, context=None):
|
||||
"""Set the 'clear' state to defined fields"""
|
||||
|
||||
ir_model_fields_anonymization_model = self.pool.get('ir.model.fields.anonymization')
|
||||
anonymization_history_model = self.pool.get('ir.model.fields.anonymization.history')
|
||||
|
||||
@@ -524,23 +530,46 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
||||
wizards = self.browse(cr, uid, ids, context=context)
|
||||
for wizard in wizards:
|
||||
if not wizard.file_import:
|
||||
msg = "It is not possible to reverse the anonymization process without supplying anonymization export file."
|
||||
msg = "It is not possible to reverse the anonymization process without supplying the anonymization export file."
|
||||
self._raise_after_history_update(cr, uid, history_id, 'Error !', msg)
|
||||
|
||||
# reverse the anonymization:
|
||||
# load the pickle file content into a data structure:
|
||||
data = pickle.loads(base64.decodestring(wizard.file_import))
|
||||
|
||||
migration_fix_obj = self.pool.get('ir.model.fields.anonymization.migration.fix')
|
||||
fix_ids = migration_fix_obj.search(cr, uid, [('target_version', '=', '7.0')])
|
||||
fixes = migration_fix_obj.read(cr, uid, fix_ids, ['model_name', 'field_name', 'query', 'query_type', 'sequence'])
|
||||
fixes = group(fixes, ('model_name', 'field_name'))
|
||||
|
||||
for line in data:
|
||||
table_name = self.pool.get(line['model_id'])._table
|
||||
sql = "update %(table)s set %(field)s = %%(value)s where id = %%(id)s" % {
|
||||
'table': table_name,
|
||||
'field': line['field_id'],
|
||||
}
|
||||
cr.execute(sql, {
|
||||
'value': line['value'],
|
||||
'id': line['id']
|
||||
})
|
||||
|
||||
# check if custom sql exists:
|
||||
key = (line['model_id'], line['field_id'])
|
||||
custom_updates = fixes.get(key)
|
||||
if custom_updates:
|
||||
custom_updates.sort(itemgetter('sequence'))
|
||||
queries = [(record['query'], record['query_type']) for record in custom_updates if record['query_type']]
|
||||
else:
|
||||
queries = [("update %(table)s set %(field)s = %%(value)s where id = %%(id)s" % {
|
||||
'table': table_name,
|
||||
'field': line['field_id'],
|
||||
}, 'sql')]
|
||||
|
||||
for query in queries:
|
||||
if query[1] == 'sql':
|
||||
sql = query[0]
|
||||
cr.execute(sql, {
|
||||
'value': line['value'],
|
||||
'id': line['id']
|
||||
})
|
||||
elif query[1] == 'python':
|
||||
raw_code = query[0]
|
||||
code = raw_code % line
|
||||
eval(code)
|
||||
else:
|
||||
raise Exception("Unknown query type '%s'. Valid types are: sql, python." % (query['query_type'], ))
|
||||
|
||||
# update the anonymization fields:
|
||||
ir_model_fields_anonymization_model = self.pool.get('ir.model.fields.anonymization')
|
||||
@@ -589,7 +618,19 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
||||
res = None
|
||||
return res
|
||||
|
||||
ir_model_fields_anonymize_wizard()
|
||||
|
||||
class ir_model_fields_anonymization_migration_fix(osv.osv):
|
||||
_name = 'ir.model.fields.anonymization.migration.fix'
|
||||
_order = "sequence"
|
||||
|
||||
_columns = {
|
||||
'target_version': fields.char('Target Version'),
|
||||
'model_name': fields.char('Model'),
|
||||
'field_name': fields.char('Field'),
|
||||
'query': fields.text('Query'),
|
||||
'query_type': fields.selection(string='Query', selection=[('sql', 'sql'), ('python', 'python')]),
|
||||
'sequence': fields.integer('Sequence'),
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
<field name="model_id" on_change="onchange_model_id(model_id)" />
|
||||
<field name="model_name" on_change="onchange_model_name(model_name)" />
|
||||
<field name="field_id"
|
||||
|
||||
on_change="onchange_field_id(field_id, model_name)"
|
||||
domain="[('model_id','=',model_id), ('ttype', 'not in', ['function', 'binary', 'many2many', 'many2one', 'one2many', 'reference'])]" />
|
||||
<field name="field_name" on_change="onchange_field_name(field_name, model_name)" />
|
||||
|
||||
@@ -14,8 +14,8 @@ msgstr ""
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-22 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16165)\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-23 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16179)\n"
|
||||
|
||||
#. module: anonymization
|
||||
#: model:ir.model,name:anonymization.model_ir_model_fields_anonymize_wizard
|
||||
|
||||
@@ -19,15 +19,16 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields, osv, orm
|
||||
from tools.translate import _
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
import re
|
||||
import time
|
||||
|
||||
from osv import fields, osv, orm
|
||||
from tools.translate import _
|
||||
from tools.safe_eval import safe_eval
|
||||
from tools import ustr
|
||||
import pooler
|
||||
import re
|
||||
import time
|
||||
import tools
|
||||
|
||||
|
||||
@@ -48,32 +49,21 @@ class base_action_rule(osv.osv):
|
||||
_description = 'Action Rules'
|
||||
|
||||
def _state_get(self, cr, uid, context=None):
|
||||
""" Get State
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
""" Get State """
|
||||
return self.state_get(cr, uid, context=context)
|
||||
|
||||
def state_get(self, cr, uid, context=None):
|
||||
""" Get State
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
""" Get State """
|
||||
return [('', '')]
|
||||
|
||||
def priority_get(self, cr, uid, context=None):
|
||||
""" Get Priority
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
""" Get Priority """
|
||||
return [('', '')]
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Rule Name', size=64, required=True),
|
||||
'model_id': fields.many2one('ir.model', 'Object', required=True),
|
||||
'model_id': fields.many2one('ir.model', 'Related Document Model', required=True, domain=[('osv_memory','=', False)]),
|
||||
'model': fields.related('model_id', 'model', type="char", size=256, string='Model'),
|
||||
'create_date': fields.datetime('Create Date', readonly=1),
|
||||
'active': fields.boolean('Active', help="If the active field is set to False,\
|
||||
it will allow you to hide the rule without removing it."),
|
||||
@@ -82,6 +72,7 @@ when displaying a list of rules."),
|
||||
'trg_date_type': fields.selection([
|
||||
('none', 'None'),
|
||||
('create', 'Creation Date'),
|
||||
('write', 'Last Modified Date'),
|
||||
('action_last', 'Last Action Date'),
|
||||
('date', 'Date'),
|
||||
('deadline', 'Deadline'),
|
||||
@@ -98,78 +89,39 @@ trigger date, like sending a reminder 15 minutes before a meeting."),
|
||||
'trg_state_from': fields.selection(_state_get, 'Status', size=16),
|
||||
'trg_state_to': fields.selection(_state_get, 'Button Pressed', size=16),
|
||||
|
||||
'act_method': fields.char('Call Object Method', size=64),
|
||||
'act_user_id': fields.many2one('res.users', 'Set Responsible to'),
|
||||
'act_state': fields.selection(_state_get, 'Set State to', size=16),
|
||||
'act_email_cc': fields.char('Add Watchers (Cc)', size=250, help="\
|
||||
These people will receive a copy of the future communication between partner \
|
||||
and users by email"),
|
||||
'act_remind_partner': fields.boolean('Remind Partner', help="Check \
|
||||
this if you want the rule to send a reminder by email to the partner."),
|
||||
'act_remind_user': fields.boolean('Remind Responsible', help="Check \
|
||||
this if you want the rule to send a reminder by email to the user."),
|
||||
'act_reply_to': fields.char('Reply-To', size=64),
|
||||
'act_remind_attach': fields.boolean('Remind with Attachment', help="Check this if you want that all documents attached to the object be attached to the reminder email sent."),
|
||||
'act_mail_to_user': fields.boolean('Mail to Responsible', help="Check\
|
||||
this if you want the rule to send an email to the responsible person."),
|
||||
'act_mail_to_watchers': fields.boolean('Mail to Watchers (CC)',
|
||||
help="Check this if you want \
|
||||
the rule to mark CC(mail to any other person defined in actions)."),
|
||||
'act_mail_to_email': fields.char('Mail to these Emails', size=128, \
|
||||
help="Email-id of the persons whom mail is to be sent"),
|
||||
'act_mail_body': fields.text('Mail body', help="Content of mail"),
|
||||
'act_followers': fields.many2many("res.partner", string="Set Followers"),
|
||||
'regex_name': fields.char('Regex on Resource Name', size=128, help="Regular expression for matching name of the resource\
|
||||
\ne.g.: 'urgent.*' will search for records having name starting with the string 'urgent'\
|
||||
\nNote: This is case sensitive search."),
|
||||
'server_action_id': fields.many2one('ir.actions.server', 'Server Action', help="Describes the action name.\neg:on which object which action to be taken on basis of which condition"),
|
||||
'filter_id':fields.many2one('ir.filters', 'Filter', required=False),
|
||||
'act_email_from' : fields.char('Email From', size=64, required=False,
|
||||
help="Use a python expression to specify the right field on which one than we will use for the 'From' field of the header"),
|
||||
'act_email_to' : fields.char('Email To', size=64, required=False,
|
||||
help="Use a python expression to specify the right field on which one than we will use for the 'To' field of the header"),
|
||||
'server_action_ids': fields.one2many('ir.actions.server', 'action_rule_id', 'Server Action', help="Define Server actions.\neg:Email Reminders, Call Object Service, etc.."), #TODO: set domain [('model_id','=',model_id)]
|
||||
'filter_id':fields.many2one('ir.filters', 'Filter', required=False), #TODO: set domain [('model_id','=',model_id.model)]
|
||||
'last_run': fields.datetime('Last Run', readonly=1),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'active': lambda *a: True,
|
||||
'trg_date_type': lambda *a: 'none',
|
||||
'trg_date_range_type': lambda *a: 'day',
|
||||
'act_mail_to_user': lambda *a: 0,
|
||||
'act_remind_partner': lambda *a: 0,
|
||||
'act_remind_user': lambda *a: 0,
|
||||
'act_mail_to_watchers': lambda *a: 0,
|
||||
'active': True,
|
||||
'trg_date_type': 'none',
|
||||
'trg_date_range_type': 'day',
|
||||
}
|
||||
|
||||
_order = 'sequence'
|
||||
|
||||
def onchange_model_id(self, cr, uid, ids, name):
|
||||
#This is not a good solution as it will affect the domain only on onchange
|
||||
res = {'domain':{'filter_id':[]}}
|
||||
if name:
|
||||
model_name = self.pool.get('ir.model').read(cr, uid, [name], ['model'])
|
||||
if model_name:
|
||||
mod_name = model_name[0]['model']
|
||||
res['domain'] = {'filter_id': [('model_id','=',mod_name)]}
|
||||
else:
|
||||
res['value'] = {'filter_id':False}
|
||||
return res
|
||||
|
||||
def post_action(self, cr, uid, ids, model, context=None):
|
||||
# Searching for action rules
|
||||
cr.execute("SELECT model.model, rule.id FROM base_action_rule rule \
|
||||
LEFT JOIN ir_model model on (model.id = rule.model_id) \
|
||||
WHERE active")
|
||||
WHERE active and model = %s", (model,))
|
||||
res = cr.fetchall()
|
||||
# Check if any rule matching with current object
|
||||
for obj_name, rule_id in res:
|
||||
if not (model == obj_name):
|
||||
continue # TODO add this condition in the WHERE clause above.
|
||||
else:
|
||||
obj = self.pool.get(obj_name)
|
||||
# If the rule doesn't involve a time condition, run it immediately
|
||||
# Otherwise we let the scheduler run the action
|
||||
if self.browse(cr, uid, rule_id, context=context).trg_date_type == 'none':
|
||||
self._action(cr, uid, [rule_id], obj.browse(cr, uid, ids, context=context), context=context)
|
||||
obj = self.pool.get(obj_name)
|
||||
# If the rule doesn't involve a time condition, run it immediately
|
||||
# Otherwise we let the scheduler run the action
|
||||
if self.browse(cr, uid, rule_id, context=context).trg_date_type == 'none':
|
||||
self._action(cr, uid, [rule_id], obj.browse(cr, uid, ids, context=context), context=context)
|
||||
return True
|
||||
|
||||
def _create(self, old_create, model, context=None):
|
||||
@@ -232,24 +184,30 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
"""
|
||||
This Function is call by scheduler.
|
||||
"""
|
||||
rule_pool = self.pool.get('base.action.rule')
|
||||
rule_ids = rule_pool.search(cr, uid, [], context=context)
|
||||
rule_ids = self.search(cr, uid, [], context=context)
|
||||
self._register_hook(cr, uid, rule_ids, context=context)
|
||||
|
||||
rules = self.browse(cr, uid, rule_ids, context=context)
|
||||
for rule in rules:
|
||||
if context is None:
|
||||
context = {}
|
||||
for rule in self.browse(cr, uid, rule_ids, context=context):
|
||||
model = rule.model_id.model
|
||||
model_pool = self.pool.get(model)
|
||||
last_run = False
|
||||
if rule.last_run:
|
||||
last_run = get_datetime(rule.last_run)
|
||||
now = datetime.now()
|
||||
for obj_id in model_pool.search(cr, uid, [], context=context):
|
||||
obj = model_pool.browse(cr, uid, obj_id, context=context)
|
||||
ctx = dict(context)
|
||||
if rule.filter_id and rule.model_id.model == rule.filter_id.model_id:
|
||||
ctx.update(eval(rule.filter_id.context))
|
||||
obj_ids = model_pool.search(cr, uid, eval(rule.filter_id.domain), context=ctx)
|
||||
else:
|
||||
obj_ids = model_pool.search(cr, uid, [], context=ctx)
|
||||
for obj in model_pool.browse(cr, uid, obj_ids, context=ctx):
|
||||
# Calculate when this action should next occur for this object
|
||||
base = False
|
||||
if rule.trg_date_type=='create' and hasattr(obj, 'create_date'):
|
||||
base = obj.create_date
|
||||
elif rule.trg_date_type=='write' and hasattr(obj, 'write_date'):
|
||||
base = obj.write_date
|
||||
elif (rule.trg_date_type=='action_last'
|
||||
and hasattr(obj, 'create_date')):
|
||||
if hasattr(obj, 'date_action_last') and obj.date_action_last:
|
||||
@@ -275,73 +233,25 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
delay = fnct[rule.trg_date_range_type](rule.trg_date_range)
|
||||
action_date = base + delay
|
||||
if (not last_run or (last_run <= action_date < now)):
|
||||
self._action(cr, uid, [rule.id], [obj], context=context)
|
||||
rule_pool.write(cr, uid, [rule.id], {'last_run': now},
|
||||
context=context)
|
||||
|
||||
def format_body(self, body):
|
||||
""" Foramat Action rule's body
|
||||
@param self: The object pointer """
|
||||
return body and tools.ustr(body) or ''
|
||||
|
||||
def format_mail(self, obj, body):
|
||||
data = {
|
||||
'object_id': obj.id,
|
||||
'object_subject': hasattr(obj, 'name') and obj.name or False,
|
||||
'object_date': hasattr(obj, 'date') and obj.date or False,
|
||||
'object_description': hasattr(obj, 'description') and obj.description or False,
|
||||
'object_user': hasattr(obj, 'user_id') and (obj.user_id and obj.user_id.name) or '/',
|
||||
'object_user_email': hasattr(obj, 'user_id') and (obj.user_id and \
|
||||
obj.user_id.email) or '/',
|
||||
'object_user_phone': hasattr(obj, 'partner_address_id') and (obj.partner_address_id and \
|
||||
obj.partner_address_id.phone) or '/',
|
||||
'partner': hasattr(obj, 'partner_id') and (obj.partner_id and obj.partner_id.name) or '/',
|
||||
'partner_email': hasattr(obj, 'partner_address_id') and (obj.partner_address_id and\
|
||||
obj.partner_address_id.email) or '/',
|
||||
}
|
||||
return self.format_body(body % data)
|
||||
|
||||
def email_send(self, cr, uid, obj, emails, body, emailfrom=None, context=None):
|
||||
if not emailfrom:
|
||||
emailfrom = tools.config.get('email_from')
|
||||
body = self.format_mail(obj, body)
|
||||
if not emailfrom and hasattr(obj, 'user_id') and obj.user_id and obj.user_id.email:
|
||||
emailfrom = obj.user_id.email
|
||||
emailfrom = tools.ustr(emailfrom)
|
||||
reply_to = emailfrom
|
||||
if not emailfrom:
|
||||
raise osv.except_osv(_('Error!'),
|
||||
_("Missing default email address or missing email on responsible user"))
|
||||
return self.pool.get('mail.mail').create(cr, uid,
|
||||
{ 'email_from': emailfrom,
|
||||
'email_to': emails.join(','),
|
||||
'reply_to': reply_to,
|
||||
'state': 'outgoing',
|
||||
'subject': '[%d] %s' % (obj.id, tools.ustr(obj.name)),
|
||||
'body_html': '<pre>%s</pre>' % body,
|
||||
'res_id': obj.id,
|
||||
'model': obj._table_name,
|
||||
'auto_delete': True
|
||||
}, context=context)
|
||||
|
||||
try:
|
||||
self._action(cr, uid, [rule.id], obj, context=ctx)
|
||||
self.write(cr, uid, [rule.id], {'last_run': now}, context=context)
|
||||
except Exception, e:
|
||||
import traceback
|
||||
print traceback.format_exc()
|
||||
|
||||
|
||||
|
||||
def do_check(self, cr, uid, action, obj, context=None):
|
||||
""" check Action
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
""" check Action """
|
||||
if context is None:
|
||||
context = {}
|
||||
ok = True
|
||||
if action.filter_id:
|
||||
if action.model_id.model == action.filter_id.model_id:
|
||||
context.update(eval(action.filter_id.context))
|
||||
obj_ids = obj._table.search(cr, uid, eval(action.filter_id.domain), context=context)
|
||||
if not obj.id in obj_ids:
|
||||
ok = False
|
||||
else:
|
||||
ok = False
|
||||
if action.filter_id and action.model_id.model == action.filter_id.model_id:
|
||||
ctx = dict(context)
|
||||
ctx.update(eval(action.filter_id.context))
|
||||
obj_ids = self.pool.get(action.model_id.model).search(cr, uid, eval(action.filter_id.domain), context=ctx)
|
||||
ok = ok and obj.id in obj_ids
|
||||
if getattr(obj, 'user_id', False):
|
||||
ok = ok and (not action.trg_user_id.id or action.trg_user_id.id==obj.user_id.id)
|
||||
if getattr(obj, 'partner_id', False):
|
||||
@@ -372,120 +282,62 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
ok = ok and regex_n
|
||||
return ok
|
||||
|
||||
def do_action(self, cr, uid, action, model_obj, obj, context=None):
|
||||
""" Do Action
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param action: pass action
|
||||
@param model_obj: pass Model object
|
||||
@param context: A standard dictionary for contextual values """
|
||||
def do_action(self, cr, uid, action, obj, context=None):
|
||||
""" Do Action """
|
||||
if context is None:
|
||||
context = {}
|
||||
ctx = dict(context)
|
||||
model_obj = self.pool.get(action.model_id.model)
|
||||
action_server_obj = self.pool.get('ir.actions.server')
|
||||
if action.server_action_ids:
|
||||
ctx.update({'active_model': action.model_id.model, 'active_id':obj.id, 'active_ids':[obj.id]})
|
||||
action_server_obj.run(cr, uid, [x.id for x in action.server_action_ids], context=ctx)
|
||||
|
||||
if action.server_action_id:
|
||||
context.update({'active_id':obj.id, 'active_ids':[obj.id]})
|
||||
self.pool.get('ir.actions.server').run(cr, uid, [action.server_action_id.id], context)
|
||||
write = {}
|
||||
|
||||
if hasattr(obj, 'user_id') and action.act_user_id:
|
||||
obj.user_id = action.act_user_id
|
||||
write['user_id'] = action.act_user_id.id
|
||||
if hasattr(obj, 'date_action_last'):
|
||||
write['date_action_last'] = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
if hasattr(obj, 'state') and action.act_state:
|
||||
obj.state = action.act_state
|
||||
write['state'] = action.act_state
|
||||
|
||||
if hasattr(obj, 'categ_id') and action.act_categ_id:
|
||||
obj.categ_id = action.act_categ_id
|
||||
write['categ_id'] = action.act_categ_id.id
|
||||
|
||||
|
||||
model_obj.write(cr, uid, [obj.id], write, context)
|
||||
|
||||
if hasattr(model_obj, 'remind_user') and action.act_remind_user:
|
||||
model_obj.remind_user(cr, uid, [obj.id], context, attach=action.act_remind_attach)
|
||||
if hasattr(model_obj, 'remind_partner') and action.act_remind_partner:
|
||||
model_obj.remind_partner(cr, uid, [obj.id], context, attach=action.act_remind_attach)
|
||||
if action.act_method:
|
||||
getattr(model_obj, 'act_method')(cr, uid, [obj.id], action, context)
|
||||
|
||||
emails = []
|
||||
if hasattr(obj, 'user_id') and action.act_mail_to_user:
|
||||
if obj.user_id:
|
||||
emails.append(obj.user_id.email)
|
||||
|
||||
if action.act_mail_to_watchers:
|
||||
emails += (action.act_email_cc or '').split(',')
|
||||
if action.act_mail_to_email:
|
||||
emails += (action.act_mail_to_email or '').split(',')
|
||||
|
||||
locals_for_emails = {
|
||||
'user' : self.pool.get('res.users').browse(cr, uid, uid, context=context),
|
||||
'obj' : obj,
|
||||
}
|
||||
|
||||
if action.act_email_to:
|
||||
emails.append(safe_eval(action.act_email_to, {}, locals_for_emails))
|
||||
|
||||
emails = filter(None, emails)
|
||||
if len(emails) and action.act_mail_body:
|
||||
emails = list(set(emails))
|
||||
email_from = safe_eval(action.act_email_from, {}, locals_for_emails)
|
||||
emails = tools.email_split(','.join(filter(None, emails)))
|
||||
email_froms = tools.email_split(email_from)
|
||||
if email_froms:
|
||||
self.email_send(cr, uid, obj, emails, action.act_mail_body, emailfrom=email_froms[0])
|
||||
if hasattr(obj, 'state') and hasattr(obj, 'message_post') and action.act_state:
|
||||
model_obj.message_post(cr, uid, [obj], _(action.act_state), context=context)
|
||||
|
||||
if hasattr(obj, 'message_subscribe') and action.act_followers:
|
||||
exits_followers = [x.id for x in obj.message_follower_ids]
|
||||
new_followers = [x.id for x in action.act_followers if x.id not in exits_followers]
|
||||
if new_followers:
|
||||
model_obj.message_subscribe(cr, uid, [obj.id], new_followers, context=context)
|
||||
return True
|
||||
|
||||
def _action(self, cr, uid, ids, objects, scrit=None, context=None):
|
||||
""" Do Action
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Basic Action Rule’s IDs,
|
||||
@param objects: pass objects
|
||||
@param context: A standard dictionary for contextual values """
|
||||
""" Do Action """
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
context.update({'action': True})
|
||||
if not scrit:
|
||||
scrit = []
|
||||
|
||||
if not isinstance(objects, list):
|
||||
objects = [objects]
|
||||
for action in self.browse(cr, uid, ids, context=context):
|
||||
for obj in objects:
|
||||
if self.do_check(cr, uid, action, obj, context=context):
|
||||
model_obj = self.pool.get(action.model_id.model)
|
||||
self.do_action(cr, uid, action, model_obj, obj, context=context)
|
||||
self.do_action(cr, uid, action, obj, context=context)
|
||||
|
||||
context.update({'action': False})
|
||||
return True
|
||||
|
||||
def _check_mail(self, cr, uid, ids, context=None):
|
||||
""" Check Mail
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Action Rule’s IDs
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
empty = orm.browse_null()
|
||||
rule_obj = self.pool.get('base.action.rule')
|
||||
for rule in self.browse(cr, uid, ids, context=context):
|
||||
if rule.act_mail_body:
|
||||
try:
|
||||
rule_obj.format_mail(empty, rule.act_mail_body)
|
||||
except (ValueError, KeyError, TypeError):
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_mail, 'Error ! The mail is not well formated.', ['act_mail_body']),
|
||||
]
|
||||
|
||||
base_action_rule()
|
||||
|
||||
class actions_server(osv.osv):
|
||||
_inherit = 'ir.actions.server'
|
||||
_columns = {
|
||||
'action_rule_id': fields.many2one("base.action.rule", string="Action Rule")
|
||||
}
|
||||
actions_server()
|
||||
|
||||
class ir_cron(osv.osv):
|
||||
_inherit = 'ir.cron'
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
<sheet>
|
||||
<group col="4">
|
||||
<field name="name"/>
|
||||
<field name="model_id" on_change="onchange_model_id(model_id)"/>
|
||||
<field name="filter_id" />
|
||||
<field name="model_id"/>
|
||||
<field name="model" invisible="1"/>
|
||||
<field name="filter_id" domain="[('model_id','=',model)]" context="{'default_model_id': model}"/>
|
||||
<field name="sequence"/>
|
||||
<field name="active"/>
|
||||
</group>
|
||||
@@ -31,62 +32,40 @@
|
||||
<field name="trg_partner_id"/>
|
||||
<field name="trg_partner_categ_id"/>
|
||||
</group>
|
||||
<group string="Conditions on States">
|
||||
<group name="state" string="Conditions on Status">
|
||||
<field name="trg_state_from"/>
|
||||
<field name="trg_state_to"/>
|
||||
</group>
|
||||
<group string="Conditions on Timing">
|
||||
<group name="timing" string="Conditions on Timing">
|
||||
<field name="trg_date_type"/>
|
||||
<group attrs="{'invisible': [('trg_date_type', '=', 'none')]}">
|
||||
<field name="trg_date_range" string="Delay After Trigger Date"/>
|
||||
<field name="trg_date_range_type"/>
|
||||
</group>
|
||||
<field name="trg_date_range" string="Delay After Trigger Date" attrs="{'invisible': [('trg_date_type', '=', 'none')]}"/>
|
||||
<field name="trg_date_range_type" attrs="{'invisible': [('trg_date_type', '=', 'none')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<separator string="Note"/>
|
||||
<label string="The rule uses the AND operator. The model must match all non-empty fields so that the rule executes the action described in the 'Actions' tab." />
|
||||
<group string="Note">
|
||||
<label string="The rule uses the AND operator. The model must match all non-empty fields so that the rule executes the action described in the 'Actions' tab." />
|
||||
</group>
|
||||
</page>
|
||||
<page string="Actions">
|
||||
<group string="Fields to Change" col="4">
|
||||
<group name="action_followers">
|
||||
<field name="act_followers" widget="many2many_tags"/>
|
||||
</group>
|
||||
<group name="action_field" col="4" string="Fields to Change">
|
||||
<field name="act_user_id"/>
|
||||
<field name="act_state"/>
|
||||
</group>
|
||||
<group col="2" string="Server Action to be Triggered">
|
||||
<field name="server_action_id"/>
|
||||
<group name="action_server" string="Server Actions to be Triggered (eg. Email Reminder, Call Object Method, etc...)" >
|
||||
<field name="server_action_ids" domain="[('model_id','=', model_id)]" nolabel="1" context="{'default_model_id': model_id}">
|
||||
<tree string="Server Actions">
|
||||
<field name="sequence"/>
|
||||
<field name="name"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Email Actions">
|
||||
<group col="4">
|
||||
<separator colspan="4" string="Email Reminders"/>
|
||||
<field name="act_remind_partner"/>
|
||||
<field name="act_remind_attach"/>
|
||||
<field name="act_remind_user"/>
|
||||
<group col="2" colspan="2" attrs="{'invisible': [('act_remind_user','=',False)]}">
|
||||
<field name="act_reply_to" attrs="{'required':[('act_remind_user','=',True)]}"/>
|
||||
</group>
|
||||
<separator colspan="4" string="Email Information"/>
|
||||
<field name="act_email_from" />
|
||||
<field name="act_email_to" />
|
||||
<field name="act_mail_to_user"/>
|
||||
<field colspan="4" name="act_mail_to_email"/>
|
||||
<field name="act_mail_to_watchers"/>
|
||||
<field colspan="4" name="act_email_cc"/>
|
||||
<separator colspan="4" string="Email Body"/>
|
||||
<field colspan="4" name="act_mail_body" height="250"
|
||||
nolabel="1" attrs="{'required':[('act_remind_user','=',True)]}" />
|
||||
<separator colspan="4" string="Special Keywords to be Used in the Body"/>
|
||||
<label align="0.0" string="%%(object_id)s = Object ID" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_subject)s = Object subject" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_description)s = Object description" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_date)s = Creation date" colspan="2"/>
|
||||
<label align="0.0" string="%%(partner)s = Partner name" colspan="2"/>
|
||||
<label align="0.0" string="%%(partner_email)s = Partner Email" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_user)s = Responsible name" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_user_email)s = Responsible Email" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_user_phone)s = Responsible phone" colspan="2"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
|
||||
@@ -1,121 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- Attendee form view -->
|
||||
<record id="base_calendar_attendee_form_view" model="ir.ui.view">
|
||||
<field name="name">calendar.attendee.form</field>
|
||||
<field name="model">calendar.attendee</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Invitation details" version="7.0">
|
||||
<header>
|
||||
<button name="do_tentative" states="needs-action,declined,accepted" string="Uncertain" type="object" class="oe_highlight"/>
|
||||
<button name="do_accept" string="Accept" states="needs-action,tentative,declined" type="object" class="oe_highlight"/>
|
||||
<button name="do_decline" string="Decline" states="needs-action,tentative,accepted" type="object" class="oe_highlight"/>
|
||||
<field name="state" widget="statusbar"
|
||||
statusbar_visible="tentative,needs-action,accepted" statusbar_colors='{"proforma":"blue"}'/>
|
||||
</header>
|
||||
<sheet>
|
||||
|
||||
<div class="oe_title">
|
||||
<label for="email" string="Invitation To" class="oe_edit_only"/>
|
||||
<h1>
|
||||
<field name="email" class="oe_inline"/>
|
||||
(<field name="language" class="oe_inline"/>)
|
||||
</h1>
|
||||
|
||||
<h2>
|
||||
From <field name="event_date" class="oe_inline"/>
|
||||
to <field name="event_end_date" class="oe_inline"/>
|
||||
</h2>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="sent_by_uid" string="Invitation From"/>
|
||||
<field name="user_id" string="Invited User"/>
|
||||
<field name="partner_id" string="Contact"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="cutype" string="Invitation Type"/>
|
||||
<field name="role" string="Role"/>
|
||||
<field name="rsvp"/>
|
||||
<field name="ref" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<group string="Delegated From">
|
||||
<field name="parent_ids" readonly="1" nolabel="1"/>
|
||||
</group>
|
||||
<group string="Delegated To" >
|
||||
<field name="child_ids" readonly="1" nolabel="1"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Attendee tree view -->
|
||||
<record id="base_calendar_attendee_tree_view" model="ir.ui.view">
|
||||
<field name="name">calendar.attendee.tree</field>
|
||||
<field name="model">calendar.attendee</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Invitation details">
|
||||
<field name="sent_by_uid" string="Invitation From"/>
|
||||
<field name="role" string="My Role"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<field name="partner_id" invisible="1"/>
|
||||
<field name="cutype" string="Invitation Type"/>
|
||||
<field name="state"/>
|
||||
<field name="rsvp" string="Required to Join"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Attendee search view -->
|
||||
<record id="base_calendar_attendee_search_view" model="ir.ui.view">
|
||||
<field name="name">calendar.attendee.search</field>
|
||||
<field name="model">calendar.attendee</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Invitations">
|
||||
<field name="email" string="Email"/>
|
||||
<field name="event_date"/>
|
||||
<filter icon="terp-gtk-jump-to-ltr" name="toreview" string="To Review" domain="[('state','=', 'needs-action')]" help="Invitations To Review"/>
|
||||
<filter icon="terp-check" string="Accepted" domain="[('state','=', 'accepted')]" help="Accepted Invitations"/>
|
||||
<filter icon="terp-dialog-close" string="Declined" domain="[('state','=', 'declined')]" help="Declined Invitations"/>
|
||||
<filter icon="gtk-sort-descending" string="Delegated" domain="[('state','=', 'delegated')]" help="Delegated Invitations"/>
|
||||
<field name="user_id" string="Responsible"/>
|
||||
<field name="cutype" string="Invitation type"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
|
||||
<filter string="Contact" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Type" icon="terp-stock_symbol-selection" help="Invitation Type" domain="[]" context="{'group_by':'cutype'}"/>
|
||||
<filter string="Role" icon="terp-gtk-select-all" domain="[]" context="{'group_by':'role'}"/>
|
||||
<filter string="Required Reply" icon="terp-mail-replied" domain="[]" context="{'group_by':'rsvp'}"/>
|
||||
<filter string="Status" icon="terp-stock_effects-object-colorize" help="Invitation Type"
|
||||
domain="[]" context="{'group_by':'state'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_view_attendee_form" model="ir.actions.act_window">
|
||||
<field name="name">Event Invitations</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">calendar.attendee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="base_calendar.base_calendar_attendee_tree_view"/>
|
||||
<field name="context">{'default_sent_by_uid': uid}</field>
|
||||
</record>
|
||||
|
||||
<!-- Calendar's menu -->
|
||||
<menuitem id="base.menu_calendar_configuration" name="Calendar"
|
||||
parent="base.menu_base_config" sequence="50" groups="base.group_no_one"/>
|
||||
|
||||
<!-- Invitation menu -->
|
||||
<menuitem id="menu_attendee_invitations"
|
||||
parent="base.menu_calendar_configuration"
|
||||
sequence="10" action="action_view_attendee_form"/>
|
||||
|
||||
<!-- Alarm form view -->
|
||||
<record id="res_alarm_form_view" model="ir.ui.view">
|
||||
<field name="name">res.alarm.form</field>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_meeting"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_crm_meeting_read" model="ir.values">
|
||||
<field name="name">action_crm_meeting_read</field>
|
||||
@@ -28,7 +28,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_meeting"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_crm_meeting_unread" model="ir.values">
|
||||
<field name="name">action_crm_meeting_unread</field>
|
||||
|
||||
@@ -140,18 +140,20 @@ class users(osv.osv):
|
||||
# Add handlers for 'input_pw' field.
|
||||
|
||||
def set_pw(self, cr, uid, id, name, value, args, context):
|
||||
if not value:
|
||||
raise osv.except_osv(_('Error!'), _("You have to specify a password."))
|
||||
if value:
|
||||
obj = pooler.get_pool(cr.dbname).get('res.users')
|
||||
if not hasattr(obj, "_salt_cache"):
|
||||
obj._salt_cache = {}
|
||||
|
||||
obj = pooler.get_pool(cr.dbname).get('res.users')
|
||||
if not hasattr(obj, "_salt_cache"):
|
||||
obj._salt_cache = {}
|
||||
salt = obj._salt_cache[id] = gen_salt()
|
||||
encrypted = encrypt_md5(value, salt)
|
||||
|
||||
salt = obj._salt_cache[id] = gen_salt()
|
||||
encrypted = encrypt_md5(value, salt)
|
||||
else:
|
||||
#setting a password to '' is allowed. It can be used to inactivate the classic log-in of the user
|
||||
#while the access can still be granted by another login method (openid...)
|
||||
encrypted = ''
|
||||
cr.execute('update res_users set password=%s where id=%s',
|
||||
(encrypted.encode('utf-8'), int(id)))
|
||||
cr.commit()
|
||||
del value
|
||||
|
||||
def get_pw( self, cr, uid, ids, name, args, context ):
|
||||
|
||||
@@ -38,7 +38,7 @@ openerp.base_import = function (instance) {
|
||||
// if true, the 'Import', 'Export', etc... buttons will be shown
|
||||
instance.web.ListView.prototype.defaults.import_enabled = true;
|
||||
instance.web.ListView.include({
|
||||
on_loaded: function () {
|
||||
load_list: function () {
|
||||
var self = this;
|
||||
var add_button = false;
|
||||
if (!this.$buttons) {
|
||||
|
||||
@@ -302,50 +302,13 @@ class base_stage(object):
|
||||
rule_ids = rule_obj.search(cr, uid, [('model_id','=',model_ids[0])], context=context)
|
||||
return rule_obj._action(cr, uid, rule_ids, cases, scrit=scrit, context=context)
|
||||
|
||||
def remind_partner(self, cr, uid, ids, context=None, attach=False):
|
||||
return self.remind_user(cr, uid, ids, context, attach,
|
||||
destination=False)
|
||||
|
||||
def remind_user(self, cr, uid, ids, context=None, attach=False, destination=True):
|
||||
if hasattr(self, 'message_post'):
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
if destination:
|
||||
recipient_id = case.user_id.partner_id.id
|
||||
else:
|
||||
if not case.email_from:
|
||||
return False
|
||||
recipient_id = self.pool.get('res.partner').find_or_create(cr, uid, case.email_from, context=context)
|
||||
|
||||
body = case.description or ""
|
||||
for message in case.message_ids:
|
||||
if message.type == 'email' and message.body:
|
||||
body = message.body
|
||||
break
|
||||
body = self.format_body(body)
|
||||
attach_to_send = {}
|
||||
if attach:
|
||||
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', self._name), ('res_id', '=', case.id)])
|
||||
attach_to_send = self.pool.get('ir.attachment').read(cr, uid, attach_ids, ['datas_fname', 'datas'])
|
||||
attach_to_send = dict(map(lambda x: (x['datas_fname'], x['datas'].decode('base64')), attach_to_send))
|
||||
|
||||
subject = "Reminder: [%s] %s" % (case.id, case.name)
|
||||
self.message_post(cr, uid, case.id, body=body,
|
||||
subject=subject, attachments=attach_to_send,
|
||||
partner_ids=[recipient_id], context=context)
|
||||
return True
|
||||
|
||||
|
||||
def _check(self, cr, uid, ids=False, context=None):
|
||||
""" Function called by the scheduler to process cases for date actions.
|
||||
Must be overriden by inheriting classes.
|
||||
"""
|
||||
return True
|
||||
|
||||
def format_body(self, body):
|
||||
return self.pool.get('base.action.rule').format_body(body)
|
||||
|
||||
def format_mail(self, obj, body):
|
||||
return self.pool.get('base.action.rule').format_mail(obj, body)
|
||||
|
||||
# ******************************
|
||||
# Notifications
|
||||
# ******************************
|
||||
|
||||
@@ -85,7 +85,6 @@ Dashboard for CRM will include:
|
||||
'crm_lead_view.xml',
|
||||
'crm_lead_menu.xml',
|
||||
|
||||
'crm_meeting_view.xml',
|
||||
'crm_meeting_menu.xml',
|
||||
'crm_meeting_shortcut_data.xml',
|
||||
|
||||
@@ -107,6 +106,7 @@ Dashboard for CRM will include:
|
||||
'crm_demo.xml',
|
||||
'crm_lead_demo.xml',
|
||||
'crm_phonecall_demo.xml',
|
||||
'crm_action_rule_demo.xml',
|
||||
],
|
||||
'test': [
|
||||
'test/process/communication_with_customer.yml',
|
||||
|
||||
@@ -41,24 +41,15 @@ class base_action_rule(osv.osv):
|
||||
'regex_history' : fields.char('Regular Expression on Case History', size=128),
|
||||
'act_section_id': fields.many2one('crm.case.section', 'Set Team to'),
|
||||
'act_categ_id': fields.many2one('crm.case.categ', 'Set Category to'),
|
||||
'act_mail_to_partner': fields.boolean('Mail to Partner',
|
||||
help="Check this if you want the rule to send an email to the partner."),
|
||||
}
|
||||
|
||||
def email_send(self, cr, uid, obj, emails, body, emailfrom=tools.config.get('email_from', False), context=None):
|
||||
mail_id = super(base_action_rule, self).email_send(cr, uid, obj, emails, body, emailfrom=emailfrom, context=context)
|
||||
if mail_id and hasattr(obj, 'section_id') and obj.section_id and obj.section_id.alias_id:
|
||||
reply_to = obj.section_id.alias_id.name_get()[0][1]
|
||||
self.pool.get('mail.mail').write(cr, uid, [mail_id], {'reply_to': reply_to}, context=context)
|
||||
return mail_id
|
||||
|
||||
def do_check(self, cr, uid, action, obj, context=None):
|
||||
ok = super(base_action_rule, self).do_check(cr, uid, action, obj, context=context)
|
||||
|
||||
if hasattr(obj, 'section_id'):
|
||||
ok = ok and (not action.trg_section_id or action.trg_section_id.id == obj.section_id.id)
|
||||
if hasattr(obj, 'categ_id'):
|
||||
ok = ok and (not action.trg_categ_id or action.trg_categ_id.id == obj.categ_id.id)
|
||||
if hasattr(obj, 'categ_ids'):
|
||||
ok = ok and (not action.trg_categ_id or action.trg_categ_id.id in [x.id for x in obj.categ_ids])
|
||||
|
||||
#Cheking for history
|
||||
regex = action.regex_history
|
||||
@@ -80,36 +71,18 @@ class base_action_rule(osv.osv):
|
||||
ok = ok and res_count
|
||||
return ok
|
||||
|
||||
def do_action(self, cr, uid, action, model_obj, obj, context=None):
|
||||
def do_action(self, cr, uid, action, obj, context=None):
|
||||
res = super(base_action_rule, self).do_action(cr, uid, action, obj, context=context)
|
||||
model_obj = self.pool.get(action.model_id.model)
|
||||
write = {}
|
||||
if hasattr(action, 'act_section_id') and action.act_section_id:
|
||||
obj.section_id = action.act_section_id
|
||||
write['section_id'] = action.act_section_id.id
|
||||
|
||||
if hasattr(obj, 'email_cc') and action.act_email_cc:
|
||||
if '@' in (obj.email_cc or ''):
|
||||
emails = obj.email_cc.split(",")
|
||||
if obj.act_email_cc not in emails:# and '<'+str(action.act_email_cc)+">" not in emails:
|
||||
write['email_cc'] = obj.email_cc + ',' + obj.act_email_cc
|
||||
else:
|
||||
write['email_cc'] = obj.act_email_cc
|
||||
|
||||
# Put state change by rule in communication history
|
||||
if hasattr(obj, 'state') and hasattr(obj, 'message_post') and action.act_state:
|
||||
model_obj.message_post(cr, uid, [obj], _(action.act_state), context=context)
|
||||
if hasattr(action, 'act_categ_id') and action.act_categ_id:
|
||||
write['categ_ids'] = [4, action.act_categ_id.id]
|
||||
|
||||
model_obj.write(cr, uid, [obj.id], write, context)
|
||||
super(base_action_rule, self).do_action(cr, uid, action, model_obj, obj, context=context)
|
||||
emails = []
|
||||
|
||||
if hasattr(obj, 'email_from') and action.act_mail_to_partner:
|
||||
emails.append(obj.email_from)
|
||||
emails = filter(None, emails)
|
||||
if len(emails) and action.act_mail_body:
|
||||
emails = list(set(emails))
|
||||
self.email_send(cr, uid, obj, emails, action.act_mail_body)
|
||||
return True
|
||||
|
||||
return res
|
||||
|
||||
def state_get(self, cr, uid, context=None):
|
||||
"""Gets available states for crm"""
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<!-- email server actions -->
|
||||
<record id="action_email_reminder_lead" model="ir.actions.server">
|
||||
<field name="name">Reminder to User</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="state">email</field>
|
||||
<field name="email">object.user_id.email</field>
|
||||
<field name="subject">Reminder on Lead: [[object.id ]] [[object.partner_id and 'of ' +object.partner_id.name or '']]</field>
|
||||
<field name="message">Hello [[object.user_id.name]],
|
||||
can you check following lead, it's not open since 5 days ?
|
||||
|
||||
Lead: [[object.id ]]
|
||||
Description:
|
||||
|
||||
[[object.description]]
|
||||
|
||||
Thanks,
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_email_reminder_customer_lead" model="ir.actions.server">
|
||||
<field name="name">Reminder to Customer</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="state">email</field>
|
||||
<field name="email">object.email_from</field>
|
||||
<field name="subject">Reminder on Lead: [[object.id ]]</field>
|
||||
<field name="message">Hello [[object.partner_id and object.partner_id.name or '']],
|
||||
your following lead is not open since 5 days.
|
||||
|
||||
Lead: [[object.id ]]
|
||||
Description:
|
||||
|
||||
[[object.description]]
|
||||
|
||||
Thanks,
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="filter_draft_lead" model="ir.filters">
|
||||
<field name="name">Filter on leads which are draft.</field>
|
||||
<field name="model_id">crm.lead</field>
|
||||
<field name="domain">[('state','=','draft')]</field>
|
||||
</record>
|
||||
|
||||
<!-- automated actions -->
|
||||
<record id="rule_set_reminder_lead" model="base.action.rule">
|
||||
<field name="name">Set Auto Reminder on leads which are not open since 5 days.</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
<field name="sequence">1</field>
|
||||
<field name="filter_id" ref="filter_draft_lead"/>
|
||||
<field name="trg_date_type">create</field>
|
||||
<field name="trg_date_range">5</field>
|
||||
<field name="trg_date_range_type">day</field>
|
||||
<field name="server_action_ids" eval="[(6,0,[ref('action_email_reminder_customer_lead'), ref('action_email_reminder_lead')])]"/>
|
||||
</record>
|
||||
|
||||
<record id="filter_usa_lead" model="ir.filters">
|
||||
<field name="name">Filter on leads which come from USA.</field>
|
||||
<field name="model_id">crm.lead</field>
|
||||
<field name="domain">[('country_id','=','United States')]</field>
|
||||
</record>
|
||||
|
||||
<record id="rule_set_followers_lead" model="base.action.rule">
|
||||
<field name="name">Set Auto Followers on leads which are urgent and come from USA.</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
<field name="sequence">2</field>
|
||||
<field name="regex_name">urgent.*</field>
|
||||
<field name="filter_id" ref="filter_usa_lead"/>
|
||||
<field name="act_followers" eval="[(6,0,[ref('base.res_partner_4'), ref('base.res_partner_5'), ref('base.res_partner_6')])]"/>
|
||||
<field name="act_user_id" ref="base.user_root"/>
|
||||
<field name="act_section_id" ref="section_sales_department"/>
|
||||
<field name="trg_date_type">create</field>
|
||||
<field name="trg_date_range">0</field>
|
||||
<field name="trg_date_range_type">minutes</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -7,53 +7,21 @@
|
||||
<field name="model">base.action.rule</field>
|
||||
<field name="inherit_id" ref="base_action_rule.view_base_action_rule_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="partner" position="after">
|
||||
<group col="2" colspan="2">
|
||||
<separator colspan="4" string="Condition on Communication History"/>
|
||||
<xpath expr="//group[@name='partner']" position="after">
|
||||
<group name="case" string="Conditions on Case Fields">
|
||||
<field name="trg_section_id" widget="selection"/>
|
||||
<field name="trg_categ_id"/>
|
||||
</group>
|
||||
<group name="communication" string="Conditions on Communication History">
|
||||
<field name="regex_history"/>
|
||||
<field name="trg_max_history"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_base_action_rule_line_form2" model="ir.ui.view">
|
||||
<field name="name">base.action.rule.form2.inherit</field>
|
||||
<field name="model">base.action.rule</field>
|
||||
<field name="inherit_id" ref="base_action_rule.view_base_action_rule_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="partner" position="after">
|
||||
<group col="2" colspan="2">
|
||||
<separator colspan="4" string="Condition Case Fields"/>
|
||||
<field name="trg_section_id" widget="selection"/>
|
||||
<field name="trg_categ_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_base_action_rule_line_form3" model="ir.ui.view">
|
||||
<field name="name">base.action.rule.form3.inherit</field>
|
||||
<field name="model">base.action.rule</field>
|
||||
<field name="inherit_id" ref="base_action_rule.view_base_action_rule_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="act_user_id" position="after">
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='act_user_id']" position="after">
|
||||
<field name="act_section_id"/>
|
||||
<field name="act_categ_id"/>
|
||||
</field>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_base_action_rule_line_form4" model="ir.ui.view">
|
||||
<field name="name">base.action.rule.form4.inherit</field>
|
||||
<field name="model">base.action.rule</field>
|
||||
<field name="inherit_id" ref="base_action_rule.view_base_action_rule_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="act_mail_to_user" position="after">
|
||||
<field name="act_mail_to_partner"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_crm_lead_unread" model="ir.values">
|
||||
<field name="name">action_crm_lead_unread</field>
|
||||
@@ -27,7 +27,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_crm_lead_read" model="ir.values">
|
||||
<field name="name">action_crm_lead_read</field>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Calendar Attendee Form View -->
|
||||
<record id="attendee_form_view_inherit" model="ir.ui.view">
|
||||
<field name="name">calendar.attendee.form.inherit</field>
|
||||
<field name="model">calendar.attendee</field>
|
||||
<field name="inherit_id" ref="base_calendar.base_calendar_attendee_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="ref" position="after">
|
||||
<field name="categ_id" string="Event Type"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -123,7 +123,7 @@
|
||||
OpenERP allows you to easily define all the calls to be done
|
||||
by your sales team and follow up based on their summary.
|
||||
</p><p>
|
||||
You can use the import feature to massicely import a new list of
|
||||
You can use the import feature to massively import a new list of
|
||||
prospects to qualify.
|
||||
</p>
|
||||
</field>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_phonecall"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_crm_phonecall_unread" model="ir.values">
|
||||
<field name="name">action_crm_phonecall_unread</field>
|
||||
@@ -27,7 +27,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_phonecall"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_crm_phonecall_read" model="ir.values">
|
||||
<field name="name">action_crm_phonecall_read</field>
|
||||
@@ -70,19 +70,19 @@
|
||||
<field name="date"/>
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="partner_phone"/>
|
||||
<field name="user_id"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="create_date" invisible="1"/>
|
||||
<field name="opportunity_id" invisible="1"/>
|
||||
<button string="Meeting"
|
||||
states="open,pending" icon="gtk-redo"
|
||||
name="action_make_meeting" type="object"/>
|
||||
<button string="Convert to Opportunity"
|
||||
name="%(phonecall2opportunity_act)d"
|
||||
states="open,pending"
|
||||
icon="gtk-index"
|
||||
type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}"/>
|
||||
<button string="Meeting"
|
||||
states="open,pending" icon="gtk-redo"
|
||||
name="action_make_meeting" type="object"/>
|
||||
<field name="partner_phone"/>
|
||||
<field name="user_id"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="create_date" invisible="1"/>
|
||||
<field name="opportunity_id" invisible="1"/>
|
||||
<field name="state"/>
|
||||
<button name="case_open" string="Confirm" type="object"
|
||||
states="draft,pending" icon="gtk-go-forward"/>
|
||||
|
||||
@@ -87,7 +87,7 @@ class crm_phonecall2phonecall(osv.osv_memory):
|
||||
if 'user_id' in fields:
|
||||
res.update({'user_id': phonecall.user_id and phonecall.user_id.id or False})
|
||||
if 'date' in fields:
|
||||
res.update({'date': phonecall.date})
|
||||
res.update({'date': False})
|
||||
if 'section_id' in fields:
|
||||
res.update({'section_id': phonecall.section_id and phonecall.section_id.id or False})
|
||||
if 'categ_id' in fields:
|
||||
|
||||
@@ -124,7 +124,8 @@ class crm_claim(base_stage, osv.osv):
|
||||
'date': fields.datetime.now,
|
||||
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c),
|
||||
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
|
||||
'active': lambda *a: 1
|
||||
'active': lambda *a: 1,
|
||||
'stage_id':lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c)
|
||||
}
|
||||
|
||||
def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
|
||||
|
||||
@@ -102,22 +102,20 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Claim" version="7.0">
|
||||
<header>
|
||||
<span groups="base.group_user">
|
||||
<button name="case_open" string="Open" type="object" class="oe_highlight"
|
||||
states="draft,pending" />
|
||||
<button name="case_close" string="Done" type="object" class="oe_highlight"
|
||||
states="open,pending"/>
|
||||
<button name="case_refuse" string="Refuse" type="object" class="oe_highlight"
|
||||
states="draft,open,pending"/>
|
||||
<button name="stage_previous" string="Previous Stage" type="object"
|
||||
states="open,pending" icon="gtk-go-back" attrs="{'invisible': [('stage_id','=', False)]}"/>
|
||||
<button name="stage_next" string="Next Stage" type="object"
|
||||
states="open,pending" icon="gtk-go-forward" attrs="{'invisible': [('stage_id','=', False)]}"/>
|
||||
<button name="case_reset" string="Reset to Draft" type="object"
|
||||
states="cancel,done"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending"/>
|
||||
</span>
|
||||
<button name="case_open" string="Open" type="object" class="oe_highlight"
|
||||
states="draft,pending" groups="base.group_user"/>
|
||||
<button name="case_close" string="Done" type="object" class="oe_highlight"
|
||||
states="open,pending" groups="base.group_user"/>
|
||||
<button name="case_refuse" string="Refuse" type="object" class="oe_highlight"
|
||||
states="draft,open,pending" groups="base.group_user"/>
|
||||
<button name="stage_previous" string="Previous Stage" type="object" groups="base.group_user"
|
||||
states="open,pending" icon="gtk-go-back" attrs="{'invisible': [('stage_id','=', False)]}"/>
|
||||
<button name="stage_next" string="Next Stage" type="object" groups="base.group_user"
|
||||
states="open,pending" icon="gtk-go-forward" attrs="{'invisible': [('stage_id','=', False)]}"/>
|
||||
<button name="case_reset" string="Reset to Draft" type="object" groups="base.group_user"
|
||||
states="cancel,done"/>
|
||||
<button name="case_cancel" string="Cancel" type="object" groups="base.group_user"
|
||||
states="draft,open,pending"/>
|
||||
<field name="stage_id" widget="statusbar"
|
||||
on_change="onchange_stage_id(stage_id)"/>
|
||||
</header>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_event_event"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_event_event_unread" model="ir.values">
|
||||
<field name="name">action_event_event_unread</field>
|
||||
@@ -82,7 +82,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_event_event"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_event_event_read" model="ir.values">
|
||||
<field name="name">action_event_event_read</field>
|
||||
@@ -100,12 +100,10 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Events" version="7.0">
|
||||
<header>
|
||||
<span groups="base.group_user">
|
||||
<button string="Confirm Event" name="button_confirm" states="draft" type="object" class="oe_highlight"/>
|
||||
<button string="Event Ended" name="button_done" states="confirm" type="object" class="oe_highlight"/>
|
||||
<button string="Set To Draft" name="button_draft" states="cancel,done" type="object" />
|
||||
<button string="Cancel Event" name="button_cancel" states="draft,confirm" type="object"/>
|
||||
</span>
|
||||
<button string="Confirm Event" name="button_confirm" states="draft" type="object" class="oe_highlight" groups="base.group_user"/>
|
||||
<button string="Event Ended" name="button_done" states="confirm" type="object" class="oe_highlight" groups="base.group_user"/>
|
||||
<button string="Set To Draft" name="button_draft" states="cancel,done" type="object" groups="base.group_user"/>
|
||||
<button string="Cancel Event" name="button_cancel" states="draft,confirm" type="object" groups="base.group_user"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,done"/>
|
||||
</header>
|
||||
<sheet>
|
||||
@@ -398,7 +396,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_event_registration"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_event_registration_unread" model="ir.values">
|
||||
<field name="name">action_event_registration_unread</field>
|
||||
@@ -416,7 +414,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_event_registration"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_event_registration_read" model="ir.values">
|
||||
<field name="name">action_event_registration_read</field>
|
||||
|
||||
@@ -40,7 +40,7 @@ class sale_order_line(osv.osv):
|
||||
'event_id': fields.many2one('event.event', 'Event', help="Choose an event and it will automatically create a registration for this event."),
|
||||
#those 2 fields are used for dynamic domains and filled by onchange
|
||||
'event_type_id': fields.related('event_type_id', type='many2one', relation="event.type", string="Event Type"),
|
||||
'event_ok': fields.related('event_ok', string='event_ok', type='boolean'),
|
||||
'event_ok': fields.related('product_id', 'event_ok', string='event_ok', type='boolean'),
|
||||
}
|
||||
|
||||
def product_id_change(self, cr, uid, ids,
|
||||
|
||||
+1
-1
@@ -231,7 +231,7 @@ class hr_employee(osv.osv):
|
||||
def onchange_address_id(self, cr, uid, ids, address, context=None):
|
||||
if address:
|
||||
address = self.pool.get('res.partner').browse(cr, uid, address, context=context)
|
||||
return {'value': {'work_email': address.email, 'work_phone': address.phone, 'mobile_phone': address.mobile}}
|
||||
return {'value': {'work_phone': address.phone, 'mobile_phone': address.mobile}}
|
||||
return {'value': {}}
|
||||
|
||||
def onchange_company(self, cr, uid, ids, company, context=None):
|
||||
|
||||
+16
-13
@@ -7,14 +7,14 @@ msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 6.0dev\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2012-02-08 01:37+0100\n"
|
||||
"PO-Revision-Date: 2012-10-21 21:20+0000\n"
|
||||
"Last-Translator: mchip <mifchip@gmail.com>\n"
|
||||
"PO-Revision-Date: 2012-10-22 07:48+0000\n"
|
||||
"Last-Translator: nanothole <Unknown>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-22 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16165)\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-23 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16179)\n"
|
||||
|
||||
#. module: hr
|
||||
#: model:process.node,name:hr.process_node_openerpuser0
|
||||
@@ -56,7 +56,7 @@ msgstr ""
|
||||
#. module: hr
|
||||
#: model:ir.actions.act_window,name:hr.view_department_form_installer
|
||||
msgid "Create Your Departments"
|
||||
msgstr ""
|
||||
msgstr "Sukurkite padalinius"
|
||||
|
||||
#. module: hr
|
||||
#: model:ir.actions.act_window,help:hr.action_hr_job
|
||||
@@ -77,12 +77,12 @@ msgstr "Padalinys"
|
||||
#. module: hr
|
||||
#: view:hr.job:0
|
||||
msgid "Mark as Old"
|
||||
msgstr ""
|
||||
msgstr "Pažymeti kaip sena"
|
||||
|
||||
#. module: hr
|
||||
#: view:hr.job:0
|
||||
msgid "Jobs"
|
||||
msgstr ""
|
||||
msgstr "Darbai"
|
||||
|
||||
#. module: hr
|
||||
#: view:hr.job:0
|
||||
@@ -185,12 +185,12 @@ msgstr ""
|
||||
#. module: hr
|
||||
#: model:ir.ui.menu,name:hr.menu_open_view_attendance_reason_new_config
|
||||
msgid "Attendance"
|
||||
msgstr ""
|
||||
msgstr "Lankomumas"
|
||||
|
||||
#. module: hr
|
||||
#: view:hr.employee:0
|
||||
msgid "Social IDs"
|
||||
msgstr ""
|
||||
msgstr "SODRA Nr."
|
||||
|
||||
#. module: hr
|
||||
#: field:hr.employee,work_phone:0
|
||||
@@ -227,7 +227,7 @@ msgstr "Darbuotojas"
|
||||
#. module: hr
|
||||
#: model:process.node,note:hr.process_node_employeecontact0
|
||||
msgid "Other information"
|
||||
msgstr ""
|
||||
msgstr "Kita informacija"
|
||||
|
||||
#. module: hr
|
||||
#: field:hr.employee,work_email:0
|
||||
@@ -237,7 +237,7 @@ msgstr "Darbo el. paštas"
|
||||
#. module: hr
|
||||
#: field:hr.employee,birthday:0
|
||||
msgid "Date of Birth"
|
||||
msgstr ""
|
||||
msgstr "Gimimo data"
|
||||
|
||||
#. module: hr
|
||||
#: model:ir.ui.menu,name:hr.menu_hr_reporting
|
||||
@@ -253,7 +253,7 @@ msgstr ""
|
||||
#. module: hr
|
||||
#: view:hr.employee:0 field:hr.employee,job_id:0 view:hr.job:0
|
||||
msgid "Job"
|
||||
msgstr ""
|
||||
msgstr "Darbas"
|
||||
|
||||
#. module: hr
|
||||
#: field:hr.department,member_ids:0
|
||||
@@ -268,7 +268,7 @@ msgstr "Nustatymai"
|
||||
#. module: hr
|
||||
#: view:hr.employee:0 field:hr.employee,category_ids:0
|
||||
msgid "Categories"
|
||||
msgstr ""
|
||||
msgstr "Kategorijos"
|
||||
|
||||
#. module: hr
|
||||
#: field:hr.job,expected_employees:0
|
||||
@@ -799,3 +799,6 @@ msgstr ""
|
||||
#~ msgstr ""
|
||||
#~ "Objekto pavadinimas turi prasidėti su x_ ir jame negali būti specialiųjų "
|
||||
#~ "ženklų!"
|
||||
|
||||
#~ msgid "Work E-mail"
|
||||
#~ msgstr "Darbinis el. paštas"
|
||||
|
||||
@@ -283,7 +283,7 @@
|
||||
<form string="Interview Appraisal" version="7.0">
|
||||
<header>
|
||||
<button string="Cancel" name="survey_req_cancel" type="object"
|
||||
states="draft,waiting_answer"/>
|
||||
states="draft,waiting_answer" class="oe_left"/>
|
||||
<button string="Print Survey" name="action_print_survey" type="object"
|
||||
states="draft" context="{'survey_id': survey_id, 'response_id': [response], 'response_no':0}"
|
||||
attrs="{'readonly':[('survey_id','=',False)]}" class="oe_highlight"/>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<record id="product_expense_installer_tree_view" model="ir.ui.view">
|
||||
<field name="name">product.product.tree</field>
|
||||
<field name="model">product.product</field>
|
||||
<field eval="7" name="priority"/>
|
||||
<field eval="37" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom" string="Products">
|
||||
<field name="name"/>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_hr_holidays"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_holidays_unread" model="ir.values">
|
||||
<field name="name">action_holidays_unread</field>
|
||||
@@ -26,7 +26,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_hr_holidays"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_holidays_read" model="ir.values">
|
||||
<field name="name">action_holidays_read</field>
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<field name="name">applicants.status.tree</field>
|
||||
<field name="model">hr.applicant</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree colors="blue:state == 'draft';black:state in ('open','pending','done','cancel');" string="Applicants Status">
|
||||
<tree string="Applicants Status">
|
||||
<field name="create_date"/>
|
||||
<field name="job_id"/>
|
||||
<field name="partner_name"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<field name="user_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -32,7 +32,7 @@
|
||||
<field name="inherit_id" ref="hr.board_hr_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="/form/board/column[1]" position="inside">
|
||||
<action name="%(action_applicants_status)d" string="Applicants To be Processed"/>
|
||||
<action name="%(action_applicants_status)d" string="Applications to be Processed"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
priority: '3'
|
||||
user_id: base.user_demo
|
||||
partner_name: 'Marie Justine'
|
||||
state: 'open'
|
||||
partner_mobile: '9988774455'
|
||||
job_id: hr.job_developer
|
||||
stage_id: stage_job4
|
||||
@@ -41,7 +40,6 @@
|
||||
type_id: degree_bac5
|
||||
user_id: base.user_root
|
||||
partner_name: 'Sandra Elvis'
|
||||
state: 'cancel'
|
||||
stage_id: stage_job6
|
||||
name: 'More than 5 yrs Experience in PHP'
|
||||
-
|
||||
@@ -50,7 +48,6 @@
|
||||
type_id: degree_licenced
|
||||
user_id: base.user_demo
|
||||
partner_name: 'John Bruno'
|
||||
state: 'done'
|
||||
job_id: hr.job_developer
|
||||
color: 5
|
||||
stage_id: stage_job5
|
||||
@@ -61,8 +58,6 @@
|
||||
type_id: degree_licenced
|
||||
priority: '4'
|
||||
partner_name: 'David Armstrong'
|
||||
state: 'pending'
|
||||
state: open
|
||||
partner_mobile: '9966332214'
|
||||
job_id: hr.job_developer
|
||||
stage_id: stage_job2
|
||||
@@ -73,7 +68,6 @@
|
||||
date: !eval time.strftime('%Y-%m-12 17:49:19')
|
||||
type_id: degree_bac5
|
||||
partner_name: 'Tina Augustie'
|
||||
state: 'open'
|
||||
partner_mobile: '9898745745'
|
||||
job_id: hr.job_developer
|
||||
stage_id: stage_job4
|
||||
@@ -85,7 +79,6 @@
|
||||
date: !eval time.strftime('%Y-%m-12 17:49:19')
|
||||
type_id: degree_bac5
|
||||
partner_name: 'Shane Williams'
|
||||
state: 'open'
|
||||
partner_mobile: '9812398524'
|
||||
stage_id: stage_job4
|
||||
name: 'Programmer'
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_hr_applicant"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_applicant_unread" model="ir.values">
|
||||
<field name="name">action_project_unread</field>
|
||||
@@ -60,7 +60,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_hr_applicant"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_applicant_read" model="ir.values">
|
||||
<field name="name">action_project_read</field>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
import time
|
||||
uid = ref('base.user_demo')
|
||||
new_id = self.create(cr, uid, {'emp_id': ref('hr.employee_qdp'), 'name': 'Quentin Paolino',
|
||||
'server_date': time.strftime('%Y-%m-%d %H:%M:%S'), 'state': 'present'})
|
||||
'server_date': time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
self.sign_in_result(cr, uid, [new_id], context)
|
||||
-
|
||||
I change my project "Thymbra" and I click on the "Change Work" button of this wizard
|
||||
|
||||
@@ -129,17 +129,18 @@ class account_analytic_line(osv.osv):
|
||||
def _default_journal(self, cr, uid, context=None):
|
||||
proxy = self.pool.get('hr.employee')
|
||||
record_ids = proxy.search(cr, uid, [('user_id', '=', uid)], context=context)
|
||||
employee = proxy.browse(cr, uid, record_ids[0], context=context)
|
||||
return employee.journal_id and employee.journal_id.id or False
|
||||
if record_ids:
|
||||
employee = proxy.browse(cr, uid, record_ids[0], context=context)
|
||||
return employee.journal_id and employee.journal_id.id or False
|
||||
return False
|
||||
|
||||
def _default_general_account(self, cr, uid, context=None):
|
||||
proxy = self.pool.get('hr.employee')
|
||||
record_ids = proxy.search(cr, uid, [('user_id', '=', uid)], context=context)
|
||||
if not record_ids:
|
||||
raise osv.except_osv(_('Error!'), _('Please create an employee associated to this user.'))
|
||||
employee = proxy.browse(cr, uid, record_ids[0], context=context)
|
||||
if employee.product_id and employee.product_id.property_account_income:
|
||||
return employee.product_id.property_account_income.id
|
||||
if record_ids:
|
||||
employee = proxy.browse(cr, uid, record_ids[0], context=context)
|
||||
if employee.product_id and employee.product_id.property_account_income:
|
||||
return employee.product_id.property_account_income.id
|
||||
return False
|
||||
|
||||
_defaults = {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,28 +1,41 @@
|
||||
# Spanish translation for openobject-addons
|
||||
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
|
||||
# Spanish (Mexico) 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 <EMAIL@ADDRESS>, 2011.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2011-01-07 06:07+0000\n"
|
||||
"PO-Revision-Date: 2011-02-15 15:37+0000\n"
|
||||
"POT-Creation-Date: 2011-12-23 09:56+0000\n"
|
||||
"PO-Revision-Date: 2012-10-22 22:58+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"Language-Team: Spanish (Mexico) <es_MX@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-09-05 05:58+0000\n"
|
||||
"X-Generator: Launchpad (build 13830)\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-23 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16179)\n"
|
||||
|
||||
#. module: l10n_mx
|
||||
#: model:ir.module.module,description:l10n_mx.module_meta_information
|
||||
msgid ""
|
||||
"This is the module to manage the accounting chart for Mexico in Open ERP."
|
||||
msgstr ""
|
||||
"Este es el módulo para gestionar el plan contable para Méjico en Open ERP."
|
||||
#: model:account.account.type,name:l10n_mx.account_type_receivable
|
||||
msgid "Receivable"
|
||||
msgstr "Por cobrar"
|
||||
|
||||
#. module: l10n_mx
|
||||
#: model:account.account.type,name:l10n_mx.account_type_equity
|
||||
msgid "Equity"
|
||||
msgstr "Capital"
|
||||
|
||||
#. module: l10n_mx
|
||||
#: model:account.account.type,name:l10n_mx.account_type_tax
|
||||
msgid "Tax"
|
||||
msgstr "Impuesto"
|
||||
|
||||
#. module: l10n_mx
|
||||
#: model:account.account.type,name:l10n_mx.account_type_cash
|
||||
msgid "Cash"
|
||||
msgstr "Efectivo"
|
||||
|
||||
#. module: l10n_mx
|
||||
#: model:ir.actions.todo,note:l10n_mx.config_call_account_template_mx_chart
|
||||
@@ -35,16 +48,28 @@ msgid ""
|
||||
"Management/Configuration/Financial Accounting/Financial Accounts/Generate "
|
||||
"Chart of Accounts from a Chart Template."
|
||||
msgstr ""
|
||||
"Generar Plan Contable a partir de una plantilla de Plan. Se le preguntará "
|
||||
"por el nombre de la compañía, la plantilla de plan contable a seguir, el no. "
|
||||
"de dígitos para generar el código de sus cuentas y la cuenta bancaria, la "
|
||||
"divisa para crear Diarios. Por lo tanto, la copia exacta de la plantilla de "
|
||||
"plan contable será generada.\n"
|
||||
"Este es el mismo asistente que se ejecuta desde Gestión "
|
||||
"Financiera/Configuración/Contabilidad Financiera/Contabilidad "
|
||||
"Financiera/Generar Plan Contable a partir de una Plantilla de Plan."
|
||||
|
||||
#. module: l10n_mx
|
||||
#: model:ir.module.module,shortdesc:l10n_mx.module_meta_information
|
||||
msgid "Mexico - Chart of Account"
|
||||
msgstr "Méjico - Plan Contable"
|
||||
#: model:account.account.type,name:l10n_mx.account_type_payable
|
||||
msgid "Payable"
|
||||
msgstr "A pagar"
|
||||
|
||||
#. module: l10n_mx
|
||||
#: model:account.account.type,name:l10n_mx.account_type_asset
|
||||
msgid "Asset"
|
||||
msgstr "Activo"
|
||||
|
||||
#. module: l10n_mx
|
||||
#: model:account.account.type,name:l10n_mx.account_type_income
|
||||
msgid "Income"
|
||||
msgstr "Ingreso"
|
||||
|
||||
#. module: l10n_mx
|
||||
#: model:account.account.type,name:l10n_mx.account_type_expense
|
||||
msgid "Expense"
|
||||
msgstr "Gasto"
|
||||
|
||||
#. module: l10n_mx
|
||||
#: model:account.account.type,name:l10n_mx.account_type_view
|
||||
msgid "View"
|
||||
msgstr "Vista"
|
||||
|
||||
@@ -85,6 +85,7 @@ class mail_notification(osv.Model):
|
||||
|
||||
def set_message_read(self, cr, uid, msg_ids, read=None, context=None):
|
||||
""" TDE note: add a comment, verify method calls, because js seems obfuscated. """
|
||||
# TDE note: child_of to set unread ?
|
||||
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
notif_ids = self.search(cr, uid, [('partner_id', '=', user_pid), ('message_id', 'in', msg_ids)], context=context)
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class ir_ui_menu(osv.osv):
|
||||
""" Override to take off menu entries (mail.group) the user is not
|
||||
following. Access are done using SUPERUSER_ID to avoid access
|
||||
rights issues for an internal back-end algorithm. """
|
||||
ids = super(ir_ui_menu, self).search(cr, uid, args, offset=0, limit=None, order=order, context=context, count=False)
|
||||
ids = super(ir_ui_menu, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=False)
|
||||
partner_id = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
follower_obj = self.pool.get('mail.followers')
|
||||
for menu in self.browse(cr, uid, ids, context=context):
|
||||
@@ -52,4 +52,6 @@ class ir_ui_menu(osv.osv):
|
||||
], context=context)
|
||||
if not sub_ids:
|
||||
ids.remove(menu.id)
|
||||
if count:
|
||||
return len(ids)
|
||||
return ids
|
||||
|
||||
+121
-79
@@ -197,19 +197,29 @@ class mail_message(osv.Model):
|
||||
|
||||
:param dict message: read result of a mail.message
|
||||
"""
|
||||
is_author = False
|
||||
if message['author_id']:
|
||||
is_author = message['author_id'][0] == self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=None)['partner_id'][0]
|
||||
|
||||
has_voted = False
|
||||
if uid in message['vote_user_ids']:
|
||||
if uid in message.get('vote_user_ids'):
|
||||
has_voted = True
|
||||
|
||||
is_favorite = False
|
||||
if uid in message['favorite_user_ids']:
|
||||
if uid in message.get('favorite_user_ids'):
|
||||
is_favorite = True
|
||||
|
||||
is_private = False
|
||||
if message.get('model') and message.get('res_id'):
|
||||
is_private = True
|
||||
|
||||
try:
|
||||
attachment_ids = [{'id': attach[0], 'name': attach[1]} for attach in self.pool.get('ir.attachment').name_get(cr, uid, message['attachment_ids'], context=context)]
|
||||
except (orm.except_orm, osv.except_osv):
|
||||
attachment_ids = []
|
||||
|
||||
# TDE note: should we send partner_ids ?
|
||||
# TDE note: shouldn't we separated followers and other partners ? costly to compute maybe ,
|
||||
try:
|
||||
partner_ids = self.pool.get('res.partner').name_get(cr, uid, message['partner_ids'], context=context)
|
||||
except (orm.except_orm, osv.except_osv):
|
||||
@@ -226,91 +236,105 @@ class mail_message(osv.Model):
|
||||
'subject': message['subject'],
|
||||
'date': message['date'],
|
||||
'author_id': message['author_id'],
|
||||
'is_author': message['author_id'] and message['author_id'][0] == uid,
|
||||
'is_author': is_author,
|
||||
# TDE note: is this useful ? to check
|
||||
'partner_ids': partner_ids,
|
||||
'parent_id': message['parent_id'] and message['parent_id'][0] or False,
|
||||
'ancestor_id': False,
|
||||
'vote_nb': len(message['vote_user_ids']),
|
||||
'has_voted': has_voted,
|
||||
'is_private': message['model'] and message['res_id'],
|
||||
'is_private': is_private,
|
||||
'is_favorite': is_favorite,
|
||||
'to_read': message['to_read'],
|
||||
}
|
||||
|
||||
def _message_read_expandable(self, cr, uid, message_list, read_messages,
|
||||
message_loaded_ids=[], domain=[], context=None, parent_id=False, limit=None):
|
||||
""" Create the expandable message for all parent message read
|
||||
this function is used by message_read
|
||||
def _message_read_add_expandables(self, cr, uid, message_list, read_messages,
|
||||
thread_level=0, message_loaded_ids=[], domain=[], parent_id=False, context=None, limit=None):
|
||||
""" Create expandables for message_read, to load new messages.
|
||||
1. get the expandable for new threads
|
||||
if display is flat (thread_level == 0):
|
||||
fetch message_ids < min(already displayed ids), because we
|
||||
want a flat display, ordered by id
|
||||
else:
|
||||
fetch message_ids that are not childs of already displayed
|
||||
messages
|
||||
2. get the expandables for new messages inside threads if display
|
||||
is not flat
|
||||
for each thread header, search for its childs
|
||||
for each hole in the child list based on message displayed,
|
||||
create an expandable
|
||||
|
||||
:param list message_list: list of messages given by message_read to
|
||||
which we have to add expandables
|
||||
:param list message_list:list of message structure for the Chatter
|
||||
widget to which expandables are added
|
||||
:param dict read_messages: dict [id]: read result of the messages to
|
||||
easily have access to their values, given their ID
|
||||
:return bool: True
|
||||
"""
|
||||
# sort for group items / TDE: move to message_read
|
||||
# result = sorted(result, key=lambda k: k['id'])
|
||||
tree_not = []
|
||||
# expandable for not show message
|
||||
def _get_expandable(domain, message_nb, ancestor_id, id, model):
|
||||
return {
|
||||
'domain': domain,
|
||||
'nb_messages': message_nb,
|
||||
'type': 'expandable',
|
||||
'ancestor_id': ancestor_id,
|
||||
'id': id,
|
||||
# TDE note: why do we need model sometimes, and sometimes not ???
|
||||
'model': model,
|
||||
}
|
||||
|
||||
# all_not_loaded_ids = []
|
||||
id_list = sorted(read_messages.keys())
|
||||
|
||||
# 1. get the expandable for new threads
|
||||
if thread_level == 0:
|
||||
exp_domain = domain + [('id', '<', min(message_loaded_ids + id_list))]
|
||||
else:
|
||||
exp_domain = domain + ['!', ('id', 'child_of', message_loaded_ids + id_list)]
|
||||
ids = self.search(cr, uid, exp_domain, context=context, limit=1)
|
||||
if ids:
|
||||
message_list.append(_get_expandable(exp_domain, -1, parent_id, -1, None))
|
||||
|
||||
# 2. get the expandables for new messages inside threads if display is not flat
|
||||
if thread_level == 0:
|
||||
return True
|
||||
for message_id in id_list:
|
||||
message = read_messages[message_id]
|
||||
|
||||
# message is not a thread header (has a parent_id)
|
||||
# TDE note: parent_id is false is there is a parent we can not see -> ok
|
||||
if message.get('parent_id'):
|
||||
continue
|
||||
|
||||
# TDE note: check search is correctly implemented in mail.message
|
||||
not_loaded_ids = self.search(cr, uid, [
|
||||
('parent_id', '=', message['id']),
|
||||
('id', 'child_of', message['id']),
|
||||
('id', 'not in', message_loaded_ids),
|
||||
], context=context, limit=self._message_read_more_limit)
|
||||
# group childs not read
|
||||
id_min = None
|
||||
id_max = None
|
||||
nb = 0
|
||||
if not not_loaded_ids:
|
||||
continue
|
||||
# print 'not_loaded_ids', not_loaded_ids
|
||||
|
||||
# all_not_loaded_ids += not_loaded_ids
|
||||
# group childs not read
|
||||
id_min, id_max, nb = max(not_loaded_ids), 0, 0
|
||||
for not_loaded_id in not_loaded_ids:
|
||||
if not read_messages.get(not_loaded_id):
|
||||
nb += 1
|
||||
if id_min == None or id_min > not_loaded_id:
|
||||
if id_min > not_loaded_id:
|
||||
id_min = not_loaded_id
|
||||
if id_max == None or id_max < not_loaded_id:
|
||||
if id_max < not_loaded_id:
|
||||
id_max = not_loaded_id
|
||||
tree_not.append(not_loaded_id)
|
||||
elif nb > 0:
|
||||
exp_domain = [('id', '>=', id_min), ('id', '<=', id_max), ('id', 'child_of', message_id)]
|
||||
message_list.append(_get_expandable(exp_domain, nb, message_id, id_min, message.get('model')))
|
||||
id_min, id_max, nb = max(not_loaded_ids), 0, 0
|
||||
else:
|
||||
if nb > 0:
|
||||
message_list.append({
|
||||
'domain': [('id', '>=', id_min), ('id', '<=', id_max), ('parent_id', '=', message_id)],
|
||||
'nb_messages': nb,
|
||||
'type': 'expandable',
|
||||
'parent_id': message_id,
|
||||
'id': id_min,
|
||||
'model': message['model']
|
||||
})
|
||||
id_min = None
|
||||
id_max = None
|
||||
nb = 0
|
||||
id_min, id_max, nb = max(not_loaded_ids), 0, 0
|
||||
if nb > 0:
|
||||
message_list.append({
|
||||
'domain': [('id', '>=', id_min), ('id', '<=', id_max), ('parent_id', '=', message_id)],
|
||||
'nb_messages': nb,
|
||||
'type': 'expandable',
|
||||
'parent_id': message_id,
|
||||
'id': id_min,
|
||||
'model': message['model'],
|
||||
})
|
||||
exp_domain = [('id', '>=', id_min), ('id', '<=', id_max), ('id', 'child_of', message_id)]
|
||||
message_list.append(_get_expandable(exp_domain, nb, message_id, id_min, message.get('model')))
|
||||
|
||||
for msg_id in read_messages.keys() + tree_not:
|
||||
message_loaded_ids.append(msg_id)
|
||||
# message_loaded_ids = list(set(message_loaded_ids + read_messages.keys() + all_not_loaded_ids))
|
||||
|
||||
# expandable for limit max
|
||||
ids = self.search(cr, uid, domain + [('id', 'not in', message_loaded_ids)], context=context, limit=1)
|
||||
if len(ids) > 0:
|
||||
message_list.append({
|
||||
'domain': domain,
|
||||
'nb_messages': 0,
|
||||
'type': 'expandable',
|
||||
'parent_id': parent_id,
|
||||
'id': -1,
|
||||
})
|
||||
|
||||
return message_list
|
||||
return True
|
||||
|
||||
def _get_parent(self, cr, uid, message, context=None):
|
||||
""" Tools method that tries to get the parent of a mail.message. If
|
||||
@@ -327,23 +351,35 @@ class mail_message(osv.Model):
|
||||
except (orm.except_orm, osv.except_osv):
|
||||
return False
|
||||
|
||||
def message_read(self, cr, uid, ids=False, domain=[], message_loaded_ids=[], context=None, parent_id=False, limit=None):
|
||||
""" Read messages from mail.message, and get back a structured tree
|
||||
of messages to be displayed as discussion threads. If IDs is set,
|
||||
def message_read(self, cr, uid, ids=False, domain=None, message_unload_ids=None, thread_level=0, context=None, parent_id=False, limit=None):
|
||||
""" Read messages from mail.message, and get back a list of structured
|
||||
messages to be displayed as discussion threads. If IDs is set,
|
||||
fetch these records. Otherwise use the domain to fetch messages.
|
||||
After having fetch messages, their parents & child will be added to obtain
|
||||
well formed threads.
|
||||
After having fetch messages, their ancestors will be added to obtain
|
||||
well formed threads, if uid has access to them.
|
||||
|
||||
TDE note: update this comment after final method implementation
|
||||
After reading the messages, expandable messages are added in the
|
||||
message list (see ``_message_read_add_expandables``). It consists
|
||||
in messages holding the 'read more' data: number of messages to
|
||||
read, domain to apply.
|
||||
|
||||
:param domain: optional domain for searching ids
|
||||
:param limit: number of messages to fetch
|
||||
:param parent_id: if parent_id reached, stop searching for
|
||||
further parents
|
||||
:return list: list of trees of messages
|
||||
:param list ids: optional IDs to fetch
|
||||
:param list domain: optional domain for searching ids if ids not set
|
||||
:param list message_unload_ids: optional ids we do not want to fetch,
|
||||
because i.e. they are already displayed somewhere
|
||||
:param int parent_id: context of parent_id
|
||||
- if parent_id reached when adding ancestors, stop going further
|
||||
in the ancestor search
|
||||
- if set in flat mode, ancestor_id is set to parent_id
|
||||
:param int limit: number of messages to fetch, before adding the
|
||||
ancestors and expandables
|
||||
:return list: list of message structure for the Chatter widget
|
||||
"""
|
||||
if message_loaded_ids:
|
||||
domain += [('id', 'not in', message_loaded_ids)]
|
||||
assert thread_level in [0, 1], 'message_read() thread_level should be 0 (flat) or 1 (1 level of thread); given %s.' % thread_level
|
||||
domain = domain if domain is not None else []
|
||||
message_unload_ids = message_unload_ids if message_unload_ids is not None else []
|
||||
if message_unload_ids:
|
||||
domain += [('id', 'not in', message_unload_ids)]
|
||||
limit = limit or self._message_read_limit
|
||||
read_messages = {}
|
||||
message_list = []
|
||||
@@ -359,23 +395,29 @@ class mail_message(osv.Model):
|
||||
# fetch messages according to the domain, add their parents if uid has access to
|
||||
ids = self.search(cr, uid, domain, context=context, limit=limit)
|
||||
for message in self.read(cr, uid, ids, self._message_read_fields, context=context):
|
||||
# if not in tree and not in message_loded list
|
||||
if not read_messages.get(message.get('id')) and message.get('id') not in message_loaded_ids:
|
||||
# if not in tree and not in message_loaded list
|
||||
if not read_messages.get(message.get('id')) and message.get('id') not in message_unload_ids:
|
||||
read_messages[message.get('id')] = message
|
||||
message_list.append(self._message_get_dict(cr, uid, message, context=context))
|
||||
|
||||
# get all parented message if the user have the access
|
||||
# get the older ancestor the user can read, update its ancestor field
|
||||
if not thread_level:
|
||||
message_list[-1]['ancestor_id'] = parent_id
|
||||
continue
|
||||
parent = self._get_parent(cr, uid, message, context=context)
|
||||
while parent and parent.get('id') != parent_id:
|
||||
if not read_messages.get(parent.get('id')) and parent.get('id') not in message_loaded_ids:
|
||||
read_messages[parent.get('id')] = parent
|
||||
message_list.append(self._message_get_dict(cr, uid, parent, context=context))
|
||||
parent = self._get_parent(cr, uid, parent, context=context)
|
||||
message_list[-1]['ancestor_id'] = parent.get('id')
|
||||
message = parent
|
||||
parent = self._get_parent(cr, uid, message, context=context)
|
||||
# if in thread: add its ancestor to the list of messages
|
||||
if not read_messages.get(message.get('id')) and message.get('id') not in message_unload_ids:
|
||||
read_messages[message.get('id')] = message
|
||||
message_list.append(self._message_get_dict(cr, uid, message, context=context))
|
||||
|
||||
# get the child expandable messages for the tree
|
||||
message_list = sorted(message_list, key=lambda k: k['id'])
|
||||
message_list = self._message_read_expandable(cr, uid, message_list, read_messages,
|
||||
message_loaded_ids=message_loaded_ids, domain=domain, context=context, parent_id=parent_id, limit=limit)
|
||||
self._message_read_add_expandables(cr, uid, message_list, read_messages, thread_level=thread_level,
|
||||
message_loaded_ids=message_unload_ids, domain=domain, parent_id=parent_id, context=context, limit=limit)
|
||||
|
||||
return message_list
|
||||
|
||||
|
||||
@@ -343,7 +343,7 @@ openerp.mail = function(session) {
|
||||
'default_model': this.context.default_model,
|
||||
'default_res_id': this.context.default_res_id,
|
||||
'default_content_subtype': 'html',
|
||||
'default_parent_id': this.id,
|
||||
'default_ancestor_id': this.id,
|
||||
'default_body': mail.ChatterUtils.get_text2html(this.$render_expandable ? (this.$render_expandable.find('textarea').val() || '') : ''),
|
||||
'default_attachment_ids': attachments,
|
||||
'default_partner_ids': partner_ids
|
||||
@@ -392,13 +392,12 @@ openerp.mail = function(session) {
|
||||
false,
|
||||
'comment',
|
||||
'mail.mt_comment',
|
||||
this.context.default_parent_id,
|
||||
this.context.default_ancestor_id,
|
||||
attachments,
|
||||
this.parent_thread.context
|
||||
]).then(function(records){
|
||||
self.parent_thread.switch_new_message(records);
|
||||
self.on_cancel();
|
||||
self.do_show_compact();
|
||||
//session.web.unblockUI();
|
||||
});
|
||||
return true;
|
||||
@@ -485,12 +484,12 @@ openerp.mail = function(session) {
|
||||
this.context = _.extend({
|
||||
default_model: 'mail.thread',
|
||||
default_res_id: 0,
|
||||
default_parent_id: false }, options.context || {});
|
||||
default_ancestor_id: false }, options.context || {});
|
||||
|
||||
// data of this expandable message
|
||||
this.id = datasets.id || -1,
|
||||
this.model = datasets.model || false,
|
||||
this.parent_id = datasets.parent_id || false,
|
||||
this.ancestor_id = datasets.ancestor_id || false,
|
||||
this.nb_messages = datasets.nb_messages || 0,
|
||||
this.thread_level = datasets.thread_level || 0,
|
||||
this.type = 'expandable',
|
||||
@@ -569,10 +568,10 @@ openerp.mail = function(session) {
|
||||
* - record.attachment_ids[].url: url of each attachmentThe
|
||||
* thread view :
|
||||
* - root thread
|
||||
* - - sub message (parent_id = root message)
|
||||
* - - sub message (ancestor_id = root message)
|
||||
* - - - sub thread
|
||||
* - - - - sub sub message (parent id = sub thread)
|
||||
* - - sub message (parent_id = root message)
|
||||
* - - sub message (ancestor_id = root message)
|
||||
* - - - sub thread
|
||||
*/
|
||||
mail.ThreadMessage = session.web.Widget.extend({
|
||||
@@ -600,7 +599,7 @@ openerp.mail = function(session) {
|
||||
// data of this message
|
||||
this.id = datasets.id || -1,
|
||||
this.model = datasets.model || false,
|
||||
this.parent_id = datasets.parent_id || false,
|
||||
this.ancestor_id = datasets.ancestor_id || false,
|
||||
this.res_id = datasets.res_id || false,
|
||||
this.type = datasets.type || false,
|
||||
this.is_author = datasets.is_author || false,
|
||||
@@ -623,7 +622,7 @@ openerp.mail = function(session) {
|
||||
this.context = _.extend({
|
||||
default_model: 'mail.thread',
|
||||
default_res_id: 0,
|
||||
default_parent_id: false }, options.context || {});
|
||||
default_ancestor_id: false }, options.context || {});
|
||||
|
||||
// record options
|
||||
this.options = options.options;
|
||||
@@ -730,7 +729,7 @@ openerp.mail = function(session) {
|
||||
'context':{
|
||||
'default_model': this.model,
|
||||
'default_res_id': this.res_id,
|
||||
'default_parent_id': this.id
|
||||
'default_ancestor_id': this.id
|
||||
},
|
||||
'options': this.options
|
||||
}
|
||||
@@ -900,10 +899,10 @@ openerp.mail = function(session) {
|
||||
* This widget handles the display of a thread of messages. The
|
||||
* thread view:
|
||||
* - root thread
|
||||
* - - sub message (parent_id = root message)
|
||||
* - - sub message (ancestor_id = root message)
|
||||
* - - - sub thread
|
||||
* - - - - sub sub message (parent id = sub thread)
|
||||
* - - sub message (parent_id = root message)
|
||||
* - - sub message (ancestor_id = root message)
|
||||
* - - - sub thread
|
||||
*/
|
||||
mail.Thread = session.web.Widget.extend({
|
||||
@@ -932,7 +931,7 @@ openerp.mail = function(session) {
|
||||
this.context = _.extend({
|
||||
default_model: 'mail.thread',
|
||||
default_res_id: 0,
|
||||
default_parent_id: false }, options.context || {});
|
||||
default_ancestor_id: false }, options.context || {});
|
||||
|
||||
this.options = options.options;
|
||||
this.options._parents = (options.options._parents != undefined ? options.options._parents : []).concat( [this] );
|
||||
@@ -943,7 +942,7 @@ openerp.mail = function(session) {
|
||||
// data of this thread
|
||||
this.id = datasets.id || false,
|
||||
this.model = datasets.model || false,
|
||||
this.parent_id = datasets.parent_id || false,
|
||||
this.ancestor_id = datasets.ancestor_id || false,
|
||||
this.is_private = datasets.is_private || false,
|
||||
this.author_id = datasets.author_id || false,
|
||||
this.thread_level = (datasets.thread_level+1) || 0,
|
||||
@@ -1050,8 +1049,8 @@ openerp.mail = function(session) {
|
||||
if(arguments[1]) res.push(this);
|
||||
if(isNaN(nb_thread_level) || nb_thread_level>0){
|
||||
_(this.messages).each(function (val, key) {
|
||||
if(val.thread){
|
||||
res = res.concat( val.thread.get_childs((isNaN(nb_thread_level) ? null : nb_thread_level-1), true) )
|
||||
if(val.thread) {
|
||||
res = res.concat( val.thread.get_childs((isNaN(nb_thread_level) ? undefined : nb_thread_level-1), true) );
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1151,7 +1150,7 @@ openerp.mail = function(session) {
|
||||
// CHM note : option for sending in flat mode by server
|
||||
var nb_indented_thread = this.options.display_indented_thread > this.thread_level ? this.options.display_indented_thread - this.thread_level : 0;
|
||||
|
||||
return this.ds_message.call('message_read', [ids, fetch_domain, message_loaded_ids, /*nb_indented_thread,*/ fetch_context, this.context.default_parent_id || undefined]
|
||||
return this.ds_message.call('message_read', [ids, fetch_domain, message_loaded_ids, nb_indented_thread, fetch_context, this.context.default_ancestor_id || undefined]
|
||||
).then(this.proxy('switch_new_message'));
|
||||
},
|
||||
|
||||
@@ -1170,16 +1169,16 @@ openerp.mail = function(session) {
|
||||
'context': {
|
||||
'default_model': data.model || self.context.default_model,
|
||||
'default_res_id': data.res_id || self.context.default_res_id,
|
||||
'default_parent_id': self.id },
|
||||
'default_ancestor_id': self.id },
|
||||
});
|
||||
} else {
|
||||
var message = new mail.ThreadMessage(self, _.extend(data, {'thread_level': self.thread_level}), {
|
||||
var message = new mail.ThreadMessage(self, _.extend(data, {'thread_level': data.thread_level ? data.thread_level : self.thread_level}), {
|
||||
'domain': data.domain,
|
||||
'context': {
|
||||
'default_model': data.model,
|
||||
'default_res_id': data.res_id,
|
||||
'default_parent_id': data.id },
|
||||
'options': self.options
|
||||
'default_ancestor_id': data.id },
|
||||
'options': _.extend(self.options, data.options)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1207,34 +1206,25 @@ openerp.mail = function(session) {
|
||||
insert_message: function (message) {
|
||||
var self=this;
|
||||
|
||||
if(this.show_compose_message &&
|
||||
this.options.display_indented_thread >= self.thread_level){
|
||||
if(this.show_compose_message /*&&
|
||||
this.options.display_indented_thread >= self.thread_level*/){
|
||||
this.ComposeMessage.do_show_compact();
|
||||
}
|
||||
|
||||
this.$('.oe_wall_no_message').remove();
|
||||
|
||||
// insert on hierarchy display => insert in self child
|
||||
var thread_messages = self.messages;
|
||||
var thread = self;
|
||||
if( self.options.display_indented_thread < self.thread_level ) {
|
||||
var thread = self.options._parents[self.options.display_indented_thread] || self.options._parents[0];
|
||||
var thread_messages = [];
|
||||
_(thread.get_childs()).each(function (val, key) { thread_messages.push(val.parent_message); });
|
||||
}
|
||||
|
||||
// check older and newer message for insertion
|
||||
var parent_newer = false;
|
||||
var parent_older = false;
|
||||
if(message.id > 0){
|
||||
for(var i in thread_messages){
|
||||
if(thread_messages[i].id > message.id){
|
||||
if(!parent_newer || parent_newer.id > thread_messages[i].id) {
|
||||
parent_newer = thread_messages[i];
|
||||
for(var i in self.messages){
|
||||
if(self.messages[i].id > message.id){
|
||||
if(!parent_newer || parent_newer.id > self.messages[i].id) {
|
||||
parent_newer = self.messages[i];
|
||||
}
|
||||
} else if(thread_messages[i].id > 0 && thread_messages[i].id < message.id) {
|
||||
if(!parent_older || parent_older.id < thread_messages[i].id) {
|
||||
parent_older = thread_messages[i];
|
||||
} else if(self.messages[i].id > 0 && self.messages[i].id < message.id) {
|
||||
if(!parent_older || parent_older.id < self.messages[i].id) {
|
||||
parent_older = self.messages[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1255,11 +1245,11 @@ openerp.mail = function(session) {
|
||||
|
||||
} else if(message.id < 0) {
|
||||
|
||||
message.appendTo(thread.$el);
|
||||
message.appendTo(self.$el);
|
||||
|
||||
} else {
|
||||
|
||||
message.prependTo(thread.$el);
|
||||
message.prependTo(self.$el);
|
||||
}
|
||||
} else {
|
||||
if (parent_older) {
|
||||
@@ -1273,11 +1263,11 @@ openerp.mail = function(session) {
|
||||
|
||||
} else if(message.id < 0) {
|
||||
|
||||
message.prependTo(thread.$el);
|
||||
message.prependTo(self.$el);
|
||||
|
||||
} else {
|
||||
|
||||
message.appendTo(thread.$el);
|
||||
message.appendTo(self.$el);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1287,16 +1277,18 @@ openerp.mail = function(session) {
|
||||
|
||||
/**
|
||||
*get the parent thread of the messages.
|
||||
* Each message is send to his parent object for creating the object message.
|
||||
* Each message is send to his parent object (or parent thread flat mode) for creating the object message.
|
||||
* @param : {Array} datas from calling RPC to "message_read"
|
||||
*/
|
||||
switch_new_message: function(records) {
|
||||
var self=this;
|
||||
console.log(records);
|
||||
_(records).each(function(record){
|
||||
self.browse_thread({
|
||||
'id': record.parent_id,
|
||||
var thread = self.browse_thread({
|
||||
'id': record.ancestor_id,
|
||||
'default_return_top_thread':true
|
||||
}).create_message_object( record );
|
||||
});
|
||||
thread.create_message_object( record );
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1326,7 +1318,7 @@ openerp.mail = function(session) {
|
||||
var msg_up = messages[it-1];
|
||||
var msg_down = messages[it+1];
|
||||
|
||||
var message_dom = [ '&', ["id","in",[message.id]], ['parent_id', '=', message.parent_id] ];
|
||||
var message_dom = [ ["id", "=", message.id] ];
|
||||
|
||||
if ( msg_up && msg_up.type == "expandable" && msg_down && msg_down.type == "expandable") {
|
||||
// concat two expandable message and add this message to this dom
|
||||
@@ -1370,15 +1362,16 @@ openerp.mail = function(session) {
|
||||
var expandable = new mail.ThreadExpandable(this, {
|
||||
'id': message.id,
|
||||
'model': message.model,
|
||||
'parent_id': message.parent_id,
|
||||
'ancestor_id': message.ancestor_id,
|
||||
'nb_messages': 1,
|
||||
'thread_level': message.thread_level,
|
||||
'ancestor_id': message.ancestor_id
|
||||
}, {
|
||||
'domain': message_dom,
|
||||
'context': {
|
||||
'default_model': message.model || this.context.default_model,
|
||||
'default_res_id': message.res_id || this.context.default_res_id,
|
||||
'default_parent_id': this.id },
|
||||
'default_ancestor_id': this.id },
|
||||
});
|
||||
|
||||
// add object on array and DOM
|
||||
|
||||
+197
-15
@@ -123,6 +123,7 @@ class test_mail(TestMailMockups):
|
||||
|
||||
def setUp(self):
|
||||
super(test_mail, self).setUp()
|
||||
cr, uid = self.cr, self.uid
|
||||
self.ir_model = self.registry('ir.model')
|
||||
self.mail_alias = self.registry('mail.alias')
|
||||
self.mail_thread = self.registry('mail.thread')
|
||||
@@ -135,22 +136,25 @@ class test_mail(TestMailMockups):
|
||||
self.res_users = self.registry('res.users')
|
||||
self.res_partner = self.registry('res.partner')
|
||||
|
||||
# Find Employee group
|
||||
group_employee_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'base', 'group_user')
|
||||
group_employee_id = group_employee_ref and group_employee_ref[1] or False
|
||||
# Test users
|
||||
self.user_demo_id = self.registry('ir.model.data').get_object_reference(self.cr, self.uid, 'base', 'user_demo')[1]
|
||||
self.user_admin = self.res_users.browse(self.cr, self.uid, self.uid)
|
||||
self.user_raoul_id = self.res_users.create(cr, uid, {'name': 'Raoul Grosbedon', 'login': 'raoul', 'groups_id': [(6, 0, [group_employee_id])]})
|
||||
self.user_admin = self.res_users.browse(cr, uid, uid)
|
||||
|
||||
# Mock send_get_mail_body to test its functionality without other addons override
|
||||
self._send_get_mail_body = self.registry('mail.mail').send_get_mail_body
|
||||
self.registry('mail.mail').send_get_mail_body = self._mock_send_get_mail_body
|
||||
|
||||
# groups@.. will cause the creation of new mail groups
|
||||
self.mail_group_model_id = self.ir_model.search(self.cr, self.uid, [('model', '=', 'mail.group')])[0]
|
||||
self.mail_alias.create(self.cr, self.uid, {'alias_name': 'groups',
|
||||
self.mail_group_model_id = self.ir_model.search(cr, uid, [('model', '=', 'mail.group')])[0]
|
||||
self.mail_alias.create(cr, uid, {'alias_name': 'groups',
|
||||
'alias_model_id': self.mail_group_model_id})
|
||||
# create a 'pigs' group that will be used through the various tests
|
||||
self.group_pigs_id = self.mail_group.create(self.cr, self.uid,
|
||||
self.group_pigs_id = self.mail_group.create(cr, uid,
|
||||
{'name': 'Pigs', 'description': 'Fans of Pigs, unite !'})
|
||||
self.group_pigs = self.mail_group.browse(self.cr, self.uid, self.group_pigs_id)
|
||||
self.group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id)
|
||||
|
||||
def tearDown(self):
|
||||
# Remove mocks
|
||||
@@ -260,7 +264,7 @@ class test_mail(TestMailMockups):
|
||||
""" Tests designed for the subscriber API as well as message subtypes """
|
||||
cr, uid, user_admin, group_pigs = self.cr, self.uid, self.user_admin, self.group_pigs
|
||||
# Data: user Raoul
|
||||
user_raoul_id = self.res_users.create(cr, uid, {'name': 'Raoul Grosbedon', 'login': 'raoul'})
|
||||
user_raoul_id = self.user_raoul_id
|
||||
user_raoul = self.res_users.browse(cr, uid, user_raoul_id)
|
||||
# Data: message subtypes
|
||||
self.mail_message_subtype.create(cr, uid, {'name': 'mt_mg_def', 'default': True, 'res_model': 'mail.group'})
|
||||
@@ -522,15 +526,190 @@ class test_mail(TestMailMockups):
|
||||
|
||||
def test_30_message_read(self):
|
||||
""" Tests for message_read and expandables. """
|
||||
self.assertTrue(1 == 1, 'Test not implemented, do not replace by return True')
|
||||
|
||||
def _print_debug(message, debug=True, prefix=''):
|
||||
if debug:
|
||||
print prefix, message
|
||||
|
||||
def _print_msg(message, debug=True, prefix=''):
|
||||
if not debug:
|
||||
return
|
||||
if message.get('type') == 'expandable':
|
||||
print prefix, 'expandable', message
|
||||
else:
|
||||
print prefix, 'message', message.get('body'), message.get('id'), message.get('ancestor_id')
|
||||
|
||||
_debug = False
|
||||
cr, uid, user_admin, group_pigs = self.cr, self.uid, self.user_admin, self.group_pigs
|
||||
pigs_domain = [('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)]
|
||||
|
||||
# Data: create a discussion in Pigs (2 messages, one with 2 and one with 3 answers)
|
||||
msg_id0 = self.group_pigs.message_post(body='0', subtype='mt_comment')
|
||||
msg_id1 = self.group_pigs.message_post(body='1', subtype='mt_comment')
|
||||
msg_id2 = self.group_pigs.message_post(body='2', subtype='mt_comment')
|
||||
msg_id3 = self.group_pigs.message_post(body='1-1', subtype='mt_comment', parent_id=msg_id1)
|
||||
msg_id4 = self.group_pigs.message_post(body='2-1', subtype='mt_comment', parent_id=msg_id2)
|
||||
msg_id5 = self.group_pigs.message_post(body='1-2', subtype='mt_comment', parent_id=msg_id1)
|
||||
msg_id6 = self.group_pigs.message_post(body='2-2', subtype='mt_comment', parent_id=msg_id2)
|
||||
msg_id7 = self.group_pigs.message_post(body='1-1-1', subtype='mt_comment', parent_id=msg_id3)
|
||||
msg_id8 = self.group_pigs.message_post(body='2-1-1', subtype='mt_comment', parent_id=msg_id4)
|
||||
msg_id9 = self.group_pigs.message_post(body='1-1-1', subtype='mt_comment', parent_id=msg_id3)
|
||||
msg_id10 = self.group_pigs.message_post(body='2-1-1', subtype='mt_comment', parent_id=msg_id4)
|
||||
msg_ids = [msg_id0, msg_id1, msg_id2, msg_id3, msg_id4, msg_id5, msg_id6, msg_id7, msg_id8, msg_id9, msg_id10]
|
||||
|
||||
# Test: read some specific ids
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, ids=msg_ids[2:4], domain=[('body', 'like', 'dummy')])
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list]
|
||||
self.assertEqual(msg_ids[2:4], read_msg_ids, 'message_read with direct ids should read only the requested ids')
|
||||
|
||||
# Test: read messages of Pigs through a domain, being thread or not threaded
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=pigs_domain, limit=200)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list]
|
||||
self.assertEqual(msg_ids, read_msg_ids, 'message_read flat with domain on Pigs should equal all messages of Pigs')
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=pigs_domain, limit=200, thread_level=1)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list]
|
||||
self.assertEqual(msg_ids, read_msg_ids, 'message_read threaded with domain on Pigs should equal all messages of Pigs')
|
||||
|
||||
# ----------------------------------------
|
||||
# CASE1: message_read with domain, threaded
|
||||
# We simulate an entire flow, using the expandables to test them
|
||||
# ----------------------------------------
|
||||
_print_debug('\nCASE1: message_read with domain, threaded\n', _debug)
|
||||
|
||||
# Do: read last message, threaded
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=pigs_domain, limit=1, thread_level=1)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# Test: structure content, ancestor is added to the read messages, ordered by id, ancestor is set, 2 expandables
|
||||
self.assertEqual(len(read_msg_list), 4, 'message_read on last Pigs message should return 2 messages and 2 expandables')
|
||||
self.assertEqual(set([msg_id2, msg_id10]), set(read_msg_ids), 'message_read on the last Pigs message should also get its parent')
|
||||
self.assertEqual(read_msg_list[1].get('ancestor_id'), read_msg_list[0].get('id'), 'message_read should set the ancestor to the thread header')
|
||||
# Data: get expandables
|
||||
new_threads_exp, new_msg_exp = None, None
|
||||
for msg in read_msg_list:
|
||||
_print_msg(msg, _debug)
|
||||
if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('id') == -1:
|
||||
new_threads_exp = msg
|
||||
elif msg.get('type') == 'expandable':
|
||||
new_msg_exp = msg
|
||||
|
||||
# Do: fetch new messages in first thread, domain from expandable
|
||||
self.assertIsNotNone(new_msg_exp, 'message_read on last Pigs message should have returned a new messages expandable')
|
||||
domain = new_msg_exp.get('domain', [])
|
||||
# Test: expandable, conditions in domain
|
||||
_print_debug('Executing %s' % domain, _debug)
|
||||
self.assertIn(('id', 'child_of', msg_id2), domain, 'new messages expandable domain should contain a child_of condition')
|
||||
self.assertIn(('id', '>=', msg_id4), domain, 'new messages expandable domain should contain an id greater than condition')
|
||||
self.assertIn(('id', '<=', msg_id8), domain, 'new messages expandable domain should contain an id less than condition')
|
||||
self.assertEqual(new_msg_exp.get('ancestor_id'), msg_id2, 'new messages expandable should have ancestor_id set to the thread header')
|
||||
# Do: message_read with domain, thread_level=0, parent_id=msg_id2 (should be imposed by JS)
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=200, thread_level=0, parent_id=msg_id2)
|
||||
for msg in read_msg_list:
|
||||
_print_msg(msg, _debug)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# Test: other message in thread have been fetch
|
||||
self.assertEqual(set([msg_id4, msg_id6, msg_id8]), set(read_msg_ids), 'message_read in Pigs thread should return all the previous messages')
|
||||
|
||||
# Do: fetch a new thread, domain from expandable
|
||||
self.assertIsNotNone(new_threads_exp, 'message_read on last Pigs message should have returned a new threads expandable')
|
||||
domain = new_threads_exp.get('domain', [])
|
||||
# Test: expandable, conditions in domain
|
||||
_print_debug('Executing %s' % domain, _debug)
|
||||
for condition in pigs_domain:
|
||||
self.assertIn(condition, domain, 'new threads expandable domain should contain the message_read domain parameter')
|
||||
self.assertFalse(new_threads_exp.get('ancestor_id'), 'new threads expandable should not have an ancestor_id')
|
||||
# Do: message_read with domain, thread_level=1 (should be imposed by JS)
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=1, thread_level=1)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# Test: structure content, ancestor is added to the read messages, ordered by id, ancestor is set, 2 expandables
|
||||
self.assertEqual(len(read_msg_list), 4, 'message_read on Pigs should return 2 messages and 2 expandables')
|
||||
self.assertEqual(set([msg_id1, msg_id9]), set(read_msg_ids), 'message_read on a Pigs message should also get its parent')
|
||||
self.assertEqual(read_msg_list[1].get('ancestor_id'), read_msg_list[0].get('id'), 'message_read should set the ancestor to the thread header')
|
||||
# Data: get expandables
|
||||
new_threads_exp, new_msg_exp = None, None
|
||||
for msg in read_msg_list:
|
||||
_print_msg(msg, _debug)
|
||||
if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('id') == -1:
|
||||
new_threads_exp = msg
|
||||
elif msg.get('type') == 'expandable':
|
||||
new_msg_exp = msg
|
||||
|
||||
# Do: fetch new messages in second thread, domain from expandable
|
||||
self.assertIsNotNone(new_msg_exp, 'message_read on Pigs message should have returned a new messages expandable')
|
||||
domain = new_msg_exp.get('domain', [])
|
||||
# Test: expandable, conditions in domain
|
||||
_print_debug('Executing %s' % domain, _debug)
|
||||
self.assertIn(('id', 'child_of', msg_id1), domain, 'new messages expandable domain should contain a child_of condition')
|
||||
self.assertIn(('id', '>=', msg_id3), domain, 'new messages expandable domain should contain an id greater than condition')
|
||||
self.assertIn(('id', '<=', msg_id7), domain, 'new messages expandable domain should contain an id less than condition')
|
||||
self.assertEqual(new_msg_exp.get('ancestor_id'), msg_id1, 'new messages expandable should have ancestor_id set to the thread header')
|
||||
# Do: message_read with domain, thread_level=0, parent_id=msg_id1 (should be imposed by JS)
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=200, thread_level=0, parent_id=msg_id1)
|
||||
for msg in read_msg_list:
|
||||
_print_msg(msg, _debug)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# Test: other message in thread have been fetch
|
||||
self.assertEqual(set([msg_id3, msg_id5, msg_id7]), set(read_msg_ids), 'message_read on the last Pigs message should also get its parent')
|
||||
|
||||
# Test: fetch a new thread, domain from expandable
|
||||
self.assertIsNotNone(new_threads_exp, 'message_read should have returned a new threads expandable')
|
||||
domain = new_threads_exp.get('domain', [])
|
||||
# Test: expandable, conditions in domain
|
||||
_print_debug('Executing %s' % domain, _debug)
|
||||
for condition in pigs_domain:
|
||||
self.assertIn(condition, domain, 'general expandable domain should contain the message_read domain parameter')
|
||||
# Do: message_read with domain, thread_level=1 (should be imposed by JS)
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=1, thread_level=1)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# Test: structure content, ancestor is added to the read messages, ordered by id, ancestor is set, 2 expandables
|
||||
self.assertEqual(len(read_msg_list), 1, 'message_read on Pigs should return 1 message because everything else has been fetched')
|
||||
self.assertEqual([msg_id0], read_msg_ids, 'message_read after 2 More should return only 1 last message')
|
||||
for msg in read_msg_list:
|
||||
_print_msg(msg, _debug)
|
||||
|
||||
# ----------------------------------------
|
||||
# CASE2: message_read with domain, flat
|
||||
# ----------------------------------------
|
||||
_print_debug('\nCASE2: message_read with domain, flat\n', _debug)
|
||||
|
||||
# Do: read 2 lasts message, flat
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=pigs_domain, limit=2, thread_level=0)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# Test: structure content, ancestor is added to the read messages, ordered by id, ancestor is not set, 1 expandable
|
||||
self.assertEqual(len(read_msg_list), 3, 'message_read on last Pigs message should return 2 messages and 1 expandable')
|
||||
self.assertEqual(set([msg_id9, msg_id10]), set(read_msg_ids), 'message_read flat on Pigs last messages should only return those messages')
|
||||
self.assertFalse(read_msg_list[0].get('ancestor_id'), 'message_read flat should set the ancestor as False')
|
||||
self.assertFalse(read_msg_list[1].get('ancestor_id'), 'message_read flat should set the ancestor as False')
|
||||
# Data: get expandables
|
||||
new_threads_exp, new_msg_exp = None, None
|
||||
for msg in read_msg_list:
|
||||
_print_msg(msg, _debug)
|
||||
if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('id') == -1:
|
||||
new_threads_exp = msg
|
||||
|
||||
# Do: fetch new messages, domain from expandable
|
||||
self.assertIsNotNone(new_threads_exp, 'message_read flat on the 2 last Pigs messages should have returns a new threads expandable')
|
||||
domain = new_threads_exp.get('domain', [])
|
||||
# Test: expandable, conditions in domain
|
||||
_print_debug('Executing %s' % domain, _debug)
|
||||
for condition in pigs_domain:
|
||||
self.assertIn(condition, domain, 'new threads expandable domain should contain the message_read domain parameter')
|
||||
# Do: message_read with domain, thread_level=0 (should be imposed by JS)
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=20, thread_level=0)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# Test: structure content, ancestor is added to the read messages, ordered by id, ancestor is set, 2 expandables
|
||||
self.assertEqual(len(read_msg_list), 9, 'message_read on Pigs should return 9 messages and 0 expandable')
|
||||
self.assertEqual([msg_id0, msg_id1, msg_id2, msg_id3, msg_id4, msg_id5, msg_id6, msg_id7, msg_id8], read_msg_ids,
|
||||
'message_read, More on flat, should return all remaning messages')
|
||||
for msg in read_msg_list:
|
||||
_print_msg(msg, _debug)
|
||||
|
||||
def test_40_needaction(self):
|
||||
""" Tests for mail.message needaction. """
|
||||
cr, uid, user_admin, group_pigs = self.cr, self.uid, self.user_admin, self.group_pigs
|
||||
user_demo = self.res_users.browse(cr, uid, self.user_demo_id)
|
||||
group_pigs_demo = self.mail_group.browse(cr, self.user_demo_id, self.group_pigs_id)
|
||||
user_raoul = self.res_users.browse(cr, uid, self.user_raoul_id)
|
||||
group_pigs_demo = self.mail_group.browse(cr, self.user_raoul_id, self.group_pigs_id)
|
||||
na_admin_base = self.mail_message._needaction_count(cr, uid, domain=[])
|
||||
na_demo_base = self.mail_message._needaction_count(cr, user_demo.id, domain=[])
|
||||
na_demo_base = self.mail_message._needaction_count(cr, user_raoul.id, domain=[])
|
||||
|
||||
# Test: number of unread notification = needaction on mail.message
|
||||
notif_ids = self.mail_notification.search(cr, uid, [
|
||||
@@ -558,12 +737,12 @@ class test_mail(TestMailMockups):
|
||||
self.assertEqual(na_admin_group, 3, 'Admin should have 3 needaction related to Pigs')
|
||||
# Test: demo has 0 new notifications (not a follower, not receiving its own messages), and 0 new needaction
|
||||
notif_ids = self.mail_notification.search(cr, uid, [
|
||||
('partner_id', '=', user_demo.partner_id.id),
|
||||
('partner_id', '=', user_raoul.partner_id.id),
|
||||
('read', '=', False)
|
||||
])
|
||||
self.assertEqual(len(notif_ids), na_demo_base + 0, 'Demo should have 0 new unread notifications')
|
||||
na_demo = self.mail_message._needaction_count(cr, user_demo.id, domain=[])
|
||||
na_demo_group = self.mail_message._needaction_count(cr, user_demo.id, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)])
|
||||
na_demo = self.mail_message._needaction_count(cr, user_raoul.id, domain=[])
|
||||
na_demo_group = self.mail_message._needaction_count(cr, user_raoul.id, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)])
|
||||
self.assertEqual(na_demo, na_demo_base + 0, 'Demo should have 0 new needaction')
|
||||
self.assertEqual(na_demo_group, 0, 'Demo should have 0 needaction related to Pigs')
|
||||
|
||||
@@ -584,7 +763,10 @@ class test_mail(TestMailMockups):
|
||||
# TDE note: temp various asserts because of the random bug about msg1.child_ids
|
||||
msg_ids = self.mail_message.search(cr, uid, [('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], limit=1)
|
||||
new_msg = self.mail_message.browse(cr, uid, msg_ids[0])
|
||||
self.assertEqual(new_msg.parent_id, msg1, 'Newly processed mail_message (%d) should have msg1 as parent' % (new_msg.id))
|
||||
# if new_msg.parent_id.id != msg1.id:
|
||||
# import pdb
|
||||
# pdb.set_trace()
|
||||
self.assertEqual(new_msg.parent_id, msg1, 'Newly processed mail_message (%d) should have msg1 as parent (msg2 is %d)' % (new_msg.id, msg2.id))
|
||||
|
||||
# 2. References header
|
||||
reply_msg2 = MAIL_TEMPLATE.format(to='Pretty Pigs <group+pigs@example.com>, other@gmail.com', subject='Re: Re: 1',
|
||||
|
||||
@@ -22,7 +22,7 @@ check the logs to see if a message we just received was already logged.
|
||||
"""
|
||||
_PREVIOUS_LOG_CHECK = datetime.timedelta(days=365)
|
||||
|
||||
def get_sys_logs(cr, uid):
|
||||
def get_sys_logs(self, cr, uid):
|
||||
"""
|
||||
Utility method to send a publisher warranty get logs messages.
|
||||
"""
|
||||
@@ -42,7 +42,7 @@ def get_sys_logs(cr, uid):
|
||||
nbr_active_share_users = pool.get("res.users").search(cr, uid, [("share", "=", True), ("date", ">=", limit_date_str)], count=True)
|
||||
user = pool.get("res.users").browse(cr, uid, uid)
|
||||
|
||||
web_base_url = safe_eval(self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', 'False'))
|
||||
web_base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', 'False')
|
||||
msg = {
|
||||
"dbuuid": dbuuid,
|
||||
"nbr_users": nbr_users,
|
||||
@@ -62,6 +62,7 @@ def get_sys_logs(cr, uid):
|
||||
arguments_raw = urllib.urlencode(arguments)
|
||||
|
||||
url = config.get("publisher_warranty_url")
|
||||
|
||||
uo = urllib2.urlopen(url, arguments_raw, **add_arg)
|
||||
result = {}
|
||||
try:
|
||||
@@ -84,8 +85,8 @@ class publisher_warranty_contract(osv.osv):
|
||||
"""
|
||||
try:
|
||||
try:
|
||||
result = get_sys_logs(cr, uid)
|
||||
except Exception:
|
||||
result = get_sys_logs(self, cr, uid)
|
||||
except Exception, ex:
|
||||
if cron_mode: # we don't want to see any stack trace in cron
|
||||
return False
|
||||
_logger.debug("Exception while sending a get logs messages", exc_info=1)
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
<para style="terp_tblheader_General_Right">Total:</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_default_Right_9">[[ formatLang(pos_payment_user_total(data['form'], currency_obj = company.currency_id)) or removeParentNode('blockTable')]]</para>
|
||||
<para style="terp_default_Right_9">[[ formatLang(pos_payment_user_total(data['form']), currency_obj = company.currency_id) or removeParentNode('blockTable')]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
|
||||
@@ -938,10 +938,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||
this.renderElement();
|
||||
},
|
||||
addPaymentLine: function(newPaymentLine) {
|
||||
var self = this;
|
||||
var x = new module.PaymentlineWidget(null, {
|
||||
payment_line: newPaymentLine
|
||||
});
|
||||
x.on_delete.add(_.bind(this.deleteLine, this, x));
|
||||
x.on('delete_payment_line', self, self.deleteLine);
|
||||
x.appendTo(this.$('#paymentlines'));
|
||||
},
|
||||
renderElement: function() {
|
||||
|
||||
@@ -142,7 +142,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
},
|
||||
click_handler: function() {
|
||||
this.order.selectLine(this.model);
|
||||
this.on_selected();
|
||||
this.trigger('order_line_selected');
|
||||
},
|
||||
renderElement: function() {
|
||||
this._super();
|
||||
@@ -153,10 +153,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
},
|
||||
refresh: function(){
|
||||
this.renderElement();
|
||||
this.on_refresh();
|
||||
this.trigger('order_line_refreshed');
|
||||
},
|
||||
on_selected: function() {},
|
||||
on_refresh: function(){},
|
||||
});
|
||||
|
||||
module.OrderWidget = module.PosBaseWidget.extend({
|
||||
@@ -230,8 +228,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
model: orderLine,
|
||||
order: this.pos.get('selectedOrder'),
|
||||
});
|
||||
line.on_selected.add(_.bind(this.update_numpad, this));
|
||||
line.on_refresh.add(_.bind(this.update_summary, this));
|
||||
line.on('order_line_selected', self, self.update_numpad);
|
||||
line.on('order_line_refreshed', self, self.update_summary);
|
||||
line.appendTo($content);
|
||||
}, this));
|
||||
this.update_numpad();
|
||||
@@ -303,7 +301,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
this.payment_line = options.payment_line;
|
||||
this.payment_line.bind('change', this.changedAmount, this);
|
||||
},
|
||||
on_delete: function() {},
|
||||
changeAmount: function(event) {
|
||||
var newAmount;
|
||||
newAmount = event.currentTarget.value;
|
||||
@@ -317,10 +314,13 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
this.renderElement();
|
||||
},
|
||||
renderElement: function() {
|
||||
var self = this;
|
||||
this.name = this.payment_line.get_cashregister().get('journal_id')[1];
|
||||
this._super();
|
||||
this.$('input').keyup(_.bind(this.changeAmount, this));
|
||||
this.$('.delete-payment-line').click(this.on_delete);
|
||||
this.$('.delete-payment-line').click(function() {
|
||||
self.trigger('delete_payment_line');
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1055,8 +1055,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
this.pos.barcode_reader.disconnect();
|
||||
return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_client_pos_menu']], ['res_id']).pipe(
|
||||
_.bind(function(res) {
|
||||
return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(result) {
|
||||
var action = result.result;
|
||||
return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(action) {
|
||||
action.context = _.extend(action.context || {}, {'cancel_action': {type: 'ir.actions.client', tag: 'reload'}});
|
||||
//self.destroy();
|
||||
this.do_action(action);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Claims</field>
|
||||
<field ref="crm_claim.model_crm_claim" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in', [user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<record id="portal_task_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Task</field>
|
||||
<field ref="project.model_project_task" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in', [user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<record id="portal_issue_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Issues</field>
|
||||
<field ref="project_issue.model_project_issue" name="model_id"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in', [user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<field name="view_mode">tree,form,calendar,graph</field>
|
||||
<field name="context">{"search_default_draft":1}</field>
|
||||
<field name="search_view_id" ref="sale.view_sales_order_filter"/>
|
||||
<field name="help">You dont have any quotation.</field>
|
||||
<field name="help">You don't have any quotation.</field>
|
||||
</record>
|
||||
|
||||
<record id="action_order_form" model="ir.actions.act_window">
|
||||
@@ -23,7 +23,7 @@
|
||||
<field name="view_mode">tree,form,calendar,graph</field>
|
||||
<field name="search_view_id" ref="sale.view_sales_order_filter"/>
|
||||
<field name="context">{"search_default_sales":1}</field>
|
||||
<field name="help">You dont have any sale order.</field>
|
||||
<field name="help">You don't have any sale order.</field>
|
||||
</record>
|
||||
|
||||
<record id="action_picking_tree" model="ir.actions.act_window">
|
||||
@@ -34,7 +34,7 @@
|
||||
<field name="domain">[('type','=','out')]</field>
|
||||
<field name="context">{'default_type': 'out', 'contact_display': 'partner_address'}</field>
|
||||
<field name="search_view_id" ref="stock.view_picking_out_search"/>
|
||||
<field name="help">You dont have any delivery order.</field>
|
||||
<field name="help">You don't have any delivery order.</field>
|
||||
</record>
|
||||
|
||||
<record id="product_normal_action" model="ir.actions.act_window">
|
||||
@@ -55,7 +55,7 @@
|
||||
<field name="domain">[('type','=','out_invoice')]</field>
|
||||
<field name="context">{'default_type':'out_invoice', 'type':'out_invoice', 'journal_type': 'sale'}</field>
|
||||
<field name="search_view_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="help">You dont have any invoice.</field>
|
||||
<field name="help">You don't have any invoice.</field>
|
||||
</record>
|
||||
|
||||
<record id="action_vendor_receipt" model="ir.actions.act_window">
|
||||
@@ -65,7 +65,7 @@
|
||||
<field name="context">{'type':'receipt'}</field>
|
||||
<field name="search_view_id" ref="account_voucher.view_voucher_filter_customer_pay"/>
|
||||
<field name="target">current</field>
|
||||
<field name="help">You dont have any payment.</field>
|
||||
<field name="help">You don't have any payment.</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Quotations" id="portal_quotations" parent="portal.portal_orders"
|
||||
|
||||
@@ -6,42 +6,42 @@
|
||||
<record id="portal_sale_order_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Quotations/Sales Orders</field>
|
||||
<field name="model_id" ref="sale.model_sale_order"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Delivery Orders</field>
|
||||
<field name="model_id" ref="stock.model_stock_picking"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Delivery Orders Out</field>
|
||||
<field name="model_id" ref="stock.model_stock_picking_out"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_account_invoice_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Account Invoices</field>
|
||||
<field name="model_id" ref="account.model_account_invoice"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_personal_payment" model="ir.rule">
|
||||
<field name="name">Portal Personal Payments</field>
|
||||
<field name="model_id" ref="account_voucher.model_account_voucher"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_personal_contact" model="ir.rule">
|
||||
<field name="name">Portal Personal Contacts</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -176,6 +176,11 @@ instance.web.ViewManager.include({
|
||||
var notes = new_notes.substring(0,60) +'..';
|
||||
}
|
||||
r.text(nodes.x+60, nodes.y+30, (notes || new_notes)).attr({"title":nodes.notes,"cursor": "default"});
|
||||
r['image']('/web/static/src/img/icons/gtk-info.png', nodes.x, nodes.y+75, 16, 16)
|
||||
.attr({"cursor": "pointer", "title": "Help"})
|
||||
.click(function() {
|
||||
window.open(nodes.url || "http://doc.openerp.com/v6.1/index.php?model=" + nodes.model);
|
||||
});
|
||||
if(nodes.menu) {
|
||||
r['image']('/web/static/src/img/icons/gtk-jump-to.png', nodes.x+100, nodes.y+75, 16, 16)
|
||||
.attr({"cursor": "pointer", "title": nodes.menu.name})
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<div class="oe_view_manager_header" style="padding: 8px;">
|
||||
<div class="oe_header_row">
|
||||
<h2 class="oe_view_title">
|
||||
<span class="oe_view_title_text oe_breadcrumb_title"><t t-esc="action.name"/> (<t t-esc="action.res_model"/>)</span>
|
||||
<span class="oe_view_title_text oe_breadcrumb_title"><t t-esc="action.name"/> (<a t-attf-href="http://doc.openerp.com/v6.1/index.php?model=#{action.res_model}"><t t-esc="action.res_model"/></a>)</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
@@ -25,7 +25,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-left:10px;">
|
||||
<p><t t-esc="process_help"/></p>
|
||||
<p><t t-raw="process_help"/></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -410,7 +410,7 @@ class product_pricelist_item(osv.osv):
|
||||
'min_quantity': fields.integer('Min. Quantity', required=True, help="The rule only applies if the partner buys/sells equal to or more than this quantity."),
|
||||
'sequence': fields.integer('Sequence', required=True, help="Gives the order in which the pricelist items will be checked. The evaluation gives highest priority to lowest sequence and stops as soon as a matching item is found."),
|
||||
'base': fields.selection(_price_field_get, 'Based on', required=True, size=-1, help="The mode for computing the price for this rule."),
|
||||
'base_pricelist_id': fields.many2one('product.pricelist', 'If Other Pricelist'),
|
||||
'base_pricelist_id': fields.many2one('product.pricelist', 'Other Pricelist'),
|
||||
|
||||
'price_surcharge': fields.float('Price Surcharge',
|
||||
digits_compute= dp.get_precision('Product Price'), help='Specify the fixed amount to add or substract(if negative) to the amount calculated with the discount.'),
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
</group>
|
||||
<group col="4" string="Price Computation">
|
||||
<field name="base"/>
|
||||
<field name="base_pricelist_id" attrs="{'required': [('base','=', -1)], 'readonly': [('base','!=', -1)]}"/>
|
||||
<field name="base_pricelist_id" attrs="{'invisible':[('base', '!=', -1)],'required': [('base','=', -1)], 'readonly': [('base','!=', -1)]}"/>
|
||||
</group>
|
||||
<group col="6" colspan="5">
|
||||
<label string="New Price ="/>
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
Click to define a new product.
|
||||
</p><p>
|
||||
You must define a product for everything you buy or sell,
|
||||
wether it's a physical product, a consumable or service.
|
||||
whether it's a physical product, a consumable or service.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
@@ -236,7 +236,7 @@
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to define a new product.
|
||||
</p><p>
|
||||
You must define a product for everything you sell, wether it's
|
||||
You must define a product for everything you sell, whether it's
|
||||
a physical product, a consumable or a service you offer to
|
||||
customers.
|
||||
</p><p>
|
||||
@@ -284,7 +284,7 @@
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to define a new product.
|
||||
</p><p>
|
||||
You must define a product for everything you purchase, wheter
|
||||
You must define a product for everything you purchase, whether
|
||||
it's a physical product, a consumable or services you buy to
|
||||
subcontractants.
|
||||
</p><p>
|
||||
|
||||
@@ -777,7 +777,6 @@ class task(base_stage, osv.osv):
|
||||
_defaults = {
|
||||
'stage_id': _get_default_stage_id,
|
||||
'project_id': _get_default_project_id,
|
||||
'state': 'draft',
|
||||
'kanban_state': 'normal',
|
||||
'priority': '2',
|
||||
'progress': 0,
|
||||
@@ -1030,7 +1029,6 @@ class task(base_stage, osv.osv):
|
||||
'user_id': delegate_data['user_id'] and delegate_data['user_id'][0] or False,
|
||||
'planned_hours': delegate_data['planned_hours'] or 0.0,
|
||||
'parent_ids': [(6, 0, [task.id])],
|
||||
'state': 'draft',
|
||||
'description': delegate_data['new_task_description'] or '',
|
||||
'child_ids': [],
|
||||
'work_ids': []
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_project"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_project_unread" model="ir.values">
|
||||
<field name="name">action_project_unread</field>
|
||||
@@ -44,7 +44,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_project"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_project_read" model="ir.values">
|
||||
<field name="name">action_project_read</field>
|
||||
@@ -135,6 +135,7 @@
|
||||
<field name="resource_calendar_id"/>
|
||||
</group>
|
||||
<group string="Miscellaneous" name="misc">
|
||||
<field name="date_start"/>
|
||||
<field name="date" string="End Date"/>
|
||||
<field name="priority" groups="base.group_no_one"/>
|
||||
<field name="active" attrs="{'invisible':[('state','in',['open', 'pending', 'template'])]}"/>
|
||||
@@ -144,7 +145,7 @@
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Tasks Stages">
|
||||
<page string="Tasks Stages" attrs="{'invisible': [('use_tasks', '=', False)]}">
|
||||
<field name="type_ids"/>
|
||||
</page>
|
||||
</notebook>
|
||||
@@ -340,7 +341,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_task"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_project_task_unread" model="ir.values">
|
||||
<field name="name">action_project_task_unread</field>
|
||||
@@ -358,7 +359,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_task"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_project_task_read" model="ir.values">
|
||||
<field name="name">action_project_task_read</field>
|
||||
@@ -377,20 +378,18 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Project" version="7.0">
|
||||
<header>
|
||||
<span groups="base.group_user">
|
||||
<!--
|
||||
<button name="do_open" string="Start Task" type="object"
|
||||
states="draft,pending" class="oe_highlight"/>
|
||||
<button name="do_draft" string="Draft" type="object"
|
||||
states="cancel,done"/>
|
||||
-->
|
||||
<button name="%(action_project_task_reevaluate)d" string="Reactivate" type="action"
|
||||
states="cancelled,done" context="{'button_reactivate':True}"/>
|
||||
<button name="action_close" string="Done" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<button name="do_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending"/>
|
||||
</span>
|
||||
<!--
|
||||
<button name="do_open" string="Start Task" type="object"
|
||||
states="draft,pending" class="oe_highlight"/>
|
||||
<button name="do_draft" string="Draft" type="object"
|
||||
states="cancel,done"/>
|
||||
-->
|
||||
<button name="%(action_project_task_reevaluate)d" string="Reactivate" type="action"
|
||||
states="cancelled,done" context="{'button_reactivate':True}" groups="base.group_user"/>
|
||||
<button name="action_close" string="Done" type="object"
|
||||
states="draft,open,pending" groups="base.group_user"/>
|
||||
<button name="do_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending" groups="base.group_user"/>
|
||||
<field name="stage_id" widget="statusbar" clickable="True"/>
|
||||
</header>
|
||||
<sheet string="Task">
|
||||
@@ -416,10 +415,10 @@
|
||||
<field name="description" attrs="{'readonly':[('state','=','done')]}" placeholder="Add a Description..."/>
|
||||
<field name="work_ids" groups="project.group_tasks_work_on_tasks">
|
||||
<tree string="Task Work" editable="top">
|
||||
<field name="date"/>
|
||||
<field name="name"/>
|
||||
<field name="user_id"/>
|
||||
<field name="hours" widget="float_time" sum="Spent Hours"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
<group>
|
||||
@@ -787,7 +786,6 @@
|
||||
<menuitem action="open_task_type_form" name="Task Stages" id="menu_task_types_view" parent="base.menu_project_config_project" sequence="2"/>
|
||||
<menuitem action="open_view_project_all" id="menu_projects" name="Projects" parent="menu_project_management" sequence="1"/>
|
||||
|
||||
<act_window context="{'search_default_user_id': active_id, 'default_user_id': active_id}" id="act_res_users_2_project_project" name="User's projects" res_model="project.project" src_model="res.users" view_mode="tree,form" view_type="form"/>
|
||||
|
||||
<record id="task_company" model="ir.ui.view">
|
||||
<field name="name">res.company.task.config</field>
|
||||
|
||||
@@ -275,7 +275,6 @@ class project_issue(base_stage, osv.osv):
|
||||
'active': 1,
|
||||
'partner_id': lambda s, cr, uid, c: s._get_default_partner(cr, uid, c),
|
||||
'email_from': lambda s, cr, uid, c: s._get_default_email(cr, uid, c),
|
||||
'state': 'draft',
|
||||
'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c),
|
||||
'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c),
|
||||
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c),
|
||||
@@ -332,7 +331,7 @@ class project_issue(base_stage, osv.osv):
|
||||
})
|
||||
vals = {
|
||||
'task_id': new_task_id,
|
||||
'state':'pending'
|
||||
'stage_id': self.stage_find(cr, uid, [bug], bug.project_id.id, [('state', '=', 'pending')], context=context),
|
||||
}
|
||||
self.convert_to_task_send_note(cr, uid, [bug.id], context=context)
|
||||
case_obj.write(cr, uid, [bug.id], vals, context=context)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_issue"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_project_issue_unread" model="ir.values">
|
||||
<field name="name">action_project_issue_unread</field>
|
||||
@@ -29,7 +29,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_issue"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_project_issue_read" model="ir.values">
|
||||
<field name="name">action_project_issue_read</field>
|
||||
@@ -95,14 +95,12 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Issue" version="7.0">
|
||||
<header>
|
||||
<span groups="base.group_user">
|
||||
<button name="case_close" string="Done" type="object"
|
||||
states="open"/>
|
||||
<button name="case_close" string="Done" type="object"
|
||||
states="draft,pending"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending"/>
|
||||
</span>
|
||||
<button name="case_close" string="Done" type="object"
|
||||
states="open" groups="base.group_user"/>
|
||||
<button name="case_close" string="Done" type="object"
|
||||
states="draft,pending" groups="base.group_user"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending" groups="base.group_user"/>
|
||||
<field name="stage_id" widget="statusbar" clickable="True"/>
|
||||
</header>
|
||||
<sheet string="Issue">
|
||||
|
||||
@@ -46,12 +46,15 @@ class project_project(osv.osv):
|
||||
|
||||
def open_timesheets(self, cr, uid, ids, context=None):
|
||||
""" open Timesheets view """
|
||||
mod_obj = self.pool.get('ir.model.data')
|
||||
act_obj = self.pool.get('ir.actions.act_window')
|
||||
|
||||
project = self.browse(cr, uid, ids[0], context)
|
||||
view_context = {
|
||||
'search_default_account_id': [project.analytic_account_id.id],
|
||||
'default_account_id': project.analytic_account_id.id,
|
||||
}
|
||||
help = _("""<p class="oe_view_nocontent_create">Record your timesheets for the project '%s'.</p>""")
|
||||
help = _("""<p class="oe_view_nocontent_create">Record your timesheets for the project '%s'.</p>""") % (project.name,)
|
||||
try:
|
||||
if project.to_invoice and project.partner_id:
|
||||
help+= _("""<p>Timesheets on this project may be invoiced to %s, according to the terms defined in the contract.</p>""" ) % (project.partner_id.name,)
|
||||
@@ -59,16 +62,13 @@ class project_project(osv.osv):
|
||||
# if the user do not have access rights on the partner
|
||||
pass
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _('Timesheets'),
|
||||
'res_model': 'hr.analytic.timesheet',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'context': view_context,
|
||||
'nodestroy': True,
|
||||
'help': help
|
||||
}
|
||||
res = mod_obj.get_object_reference(cr, uid, 'hr_timesheet', 'act_hr_timesheet_line_evry1_all_form')
|
||||
id = res and res[1] or False
|
||||
result = act_obj.read(cr, uid, [id], context=context)[0]
|
||||
result['name'] = _('Timesheets')
|
||||
result['context'] = view_context
|
||||
result['help'] = help
|
||||
return result
|
||||
|
||||
project_project()
|
||||
|
||||
@@ -272,6 +272,16 @@ res_partner()
|
||||
class account_analytic_line(osv.osv):
|
||||
_inherit = "account.analytic.line"
|
||||
|
||||
def get_product(self, cr, uid, context=None):
|
||||
emp_obj = self.pool.get('hr.employee')
|
||||
emp_ids = emp_obj.search(cr, uid, [('user_id', '=', uid)], context=context)
|
||||
if emp_ids:
|
||||
employee = emp_obj.browse(cr, uid, emp_ids, context=context)[0]
|
||||
if employee.product_id:return employee.product_id.id
|
||||
return False
|
||||
|
||||
_defaults = {'product_id': get_product,}
|
||||
|
||||
def on_change_account_id(self, cr, uid, ids, account_id):
|
||||
res = {}
|
||||
if not account_id:
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
<field name="inherit_id" ref="account.view_account_analytic_line_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="account_id" position="replace">
|
||||
<field name="account_id" string="Analytic account/project"/>
|
||||
<field name="account_id" string="Analytic account/project" on_change="on_change_account_id(account_id)"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_purchase_order"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_purchase_order_unread" model="ir.values">
|
||||
<field name="name">action_purchase_order_unread</field>
|
||||
@@ -157,7 +157,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_purchase_order"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_purchase_order_read" model="ir.values">
|
||||
<field name="name">action_purchase_order_read</field>
|
||||
@@ -206,8 +206,8 @@
|
||||
<button name="picking_ok" states="except_picking" string="Manually Corrected"/>
|
||||
<button name="invoice_ok" states="except_invoice" string="Manually Corrected"/>
|
||||
<button name="purchase_approve" states="confirmed" string="Approve Order" class="oe_highlight" groups="purchase.group_purchase_manager"/>
|
||||
<button name="view_invoice" string="Receive Invoice" type="object" attrs="{'invisible': ['|', ('invoice_method','=','picking'), '|', ('state','!=', 'approved'), ('invoiced','=',True) ]}" class="oe_highlight"/>
|
||||
<button name="view_picking" string="Receive Products" type="object" attrs="{'invisible': ['|', ('shipped','=',True), ('state','!=', 'approved')]}" class="oe_highlight"/>
|
||||
<button name="view_invoice" string="Receive Invoice" type="object" attrs="{'invisible': ['|', ('invoice_method','=','picking'), '|', ('state','!=', 'approved'), ('invoiced','=',True) ]}" class="oe_highlight"/>
|
||||
<button name="action_cancel_draft" states="cancel,sent,confirmed" string="Set to Draft" type="object" />
|
||||
<button name="purchase_cancel" states="draft,confirmed,sent" string="Cancel"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,sent,approved,done" statusbar_colors='{"except_picking":"red","except_invoice":"red","confirmed":"blue"}' readonly="1"/>
|
||||
|
||||
+15
-15
@@ -7,14 +7,14 @@ msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 6.0dev_rc3\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2012-09-20 07:29+0000\n"
|
||||
"PO-Revision-Date: 2010-12-14 21:49+0000\n"
|
||||
"Last-Translator: qdp (OpenERP) <qdp-launchpad@tinyerp.com>\n"
|
||||
"PO-Revision-Date: 2012-10-22 17:52+0000\n"
|
||||
"Last-Translator: ignas <ignassladkevicius@yahoo.com>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-19 05:12+0000\n"
|
||||
"X-Generator: Launchpad (build 16165)\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-23 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16179)\n"
|
||||
|
||||
#. module: sale
|
||||
#: code:addons/sale/wizard/sale_make_invoice_advance.py:215
|
||||
@@ -160,14 +160,14 @@ msgstr ""
|
||||
#. module: sale
|
||||
#: field:sale.order,date_confirm:0
|
||||
msgid "Confirmation Date"
|
||||
msgstr ""
|
||||
msgstr "Patvirtinimo data"
|
||||
|
||||
#. module: sale
|
||||
#: view:sale.order:0
|
||||
#: view:sale.order.line:0
|
||||
#: view:sale.report:0
|
||||
msgid "Group By..."
|
||||
msgstr ""
|
||||
msgstr "Grupuoti pagal..."
|
||||
|
||||
#. module: sale
|
||||
#: view:sale.order.line:0
|
||||
@@ -322,7 +322,7 @@ msgstr ""
|
||||
#. module: sale
|
||||
#: help:sale.order,amount_total:0
|
||||
msgid "The total amount."
|
||||
msgstr ""
|
||||
msgstr "Bendra suma."
|
||||
|
||||
#. module: sale
|
||||
#: view:sale.report:0
|
||||
@@ -652,7 +652,7 @@ msgstr ""
|
||||
#: view:board.board:0
|
||||
#: model:ir.actions.act_window,name:sale.action_turnover_by_month
|
||||
msgid "Monthly Turnover"
|
||||
msgstr ""
|
||||
msgstr "Mėnesinė apyvarta"
|
||||
|
||||
#. module: sale
|
||||
#: view:sale.report:0
|
||||
@@ -716,7 +716,7 @@ msgstr "Bendra kaina"
|
||||
#. module: sale
|
||||
#: model:ir.actions.act_window,name:sale.action_order_tree
|
||||
msgid "Old Quotations"
|
||||
msgstr ""
|
||||
msgstr "Seni pasiūlymai"
|
||||
|
||||
#. module: sale
|
||||
#: help:sale.config.settings,module_sale_journal:0
|
||||
@@ -816,7 +816,7 @@ msgstr "Iš viso :"
|
||||
#. module: sale
|
||||
#: view:sale.report:0
|
||||
msgid "My Sales"
|
||||
msgstr ""
|
||||
msgstr "Mano pardavimai"
|
||||
|
||||
#. module: sale
|
||||
#: code:addons/sale/sale.py:253
|
||||
@@ -1233,7 +1233,7 @@ msgstr "Grupuoti sąskaitas faktūras"
|
||||
#. module: sale
|
||||
#: help:sale.order,amount_tax:0
|
||||
msgid "The tax amount."
|
||||
msgstr ""
|
||||
msgstr "Mokesčiai"
|
||||
|
||||
#. module: sale
|
||||
#: view:sale.order:0
|
||||
@@ -1252,7 +1252,7 @@ msgstr ""
|
||||
#. module: sale
|
||||
#: selection:sale.report,month:0
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
msgstr "Rugpjūtis"
|
||||
|
||||
#. module: sale
|
||||
#: view:sale.order:0
|
||||
@@ -1282,7 +1282,7 @@ msgstr ""
|
||||
#. module: sale
|
||||
#: selection:sale.report,month:0
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
msgstr "Birželis"
|
||||
|
||||
#. module: sale
|
||||
#: model:ir.actions.act_window,name:sale.action_email_templates
|
||||
@@ -1559,7 +1559,7 @@ msgstr ""
|
||||
#: view:sale.report:0
|
||||
#: field:sale.report,day:0
|
||||
msgid "Day"
|
||||
msgstr ""
|
||||
msgstr "Diena"
|
||||
|
||||
#. module: sale
|
||||
#: view:sale.order:0
|
||||
@@ -1830,7 +1830,7 @@ msgstr ""
|
||||
#. module: sale
|
||||
#: view:sale.order:0
|
||||
msgid "Other Information"
|
||||
msgstr ""
|
||||
msgstr "Kita informacija"
|
||||
|
||||
#. module: sale
|
||||
#: view:res.partner:0
|
||||
|
||||
@@ -76,7 +76,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
|
||||
@@ -716,6 +716,8 @@ class sale_order_line(osv.osv):
|
||||
'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
|
||||
'invoiced': fields.boolean('Invoiced', readonly=True),
|
||||
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]},
|
||||
help="If 'on order', it triggers a procurement when the sale order is confirmed to create a task, purchase order or manufacturing order linked to this sale order line."),
|
||||
'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')),
|
||||
'tax_id': fields.many2many('account.tax', 'sale_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'address_allotment_id': fields.many2one('res.partner', 'Allotment Partner'),
|
||||
@@ -744,6 +746,7 @@ class sale_order_line(osv.osv):
|
||||
'sequence': 10,
|
||||
'invoiced': 0,
|
||||
'state': 'draft',
|
||||
'type': 'make_to_stock',
|
||||
'price_unit': 0.0,
|
||||
}
|
||||
|
||||
|
||||
+23
-27
@@ -73,7 +73,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_sale_order"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_unread(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_sale_order_unread" model="ir.values">
|
||||
<field name="name">action_sale_order_unread</field>
|
||||
@@ -91,7 +91,7 @@
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_sale_order"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">self.message_check_and_set_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
<field name="code">self.message_mark_as_read(cr, uid, context.get('active_ids'), context=context)</field>
|
||||
</record>
|
||||
<record id="action_sale_order_read" model="ir.values">
|
||||
<field name="name">action_sale_order_read</field>
|
||||
@@ -147,23 +147,21 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Sales Order" version="7.0">
|
||||
<header>
|
||||
<span groups="base.group_user">
|
||||
<button name="invoice_recreate" states="invoice_except" string="Recreate Invoice"/>
|
||||
<button name="invoice_corrected" states="invoice_except" string="Ignore Exception"/>
|
||||
<button name="action_quotation_send" string="Send by Mail" type="object" states="draft" class="oe_highlight"/>
|
||||
<button name="action_quotation_send" string="Send by Mail" type="object" states="sent"/>
|
||||
<button name="print_quotation" string="Print" type="object" states="draft" class="oe_highlight"/>
|
||||
<button name="print_quotation" string="Print" type="object" states="sent"/>
|
||||
<button name="action_button_confirm" states="draft" string="Confirm" type="object"/>
|
||||
<button name="action_button_confirm" states="sent" string="Confirm" class="oe_highlight" type="object"/>
|
||||
<button name="action_view_invoice" string="View Invoice" type="object" class="oe_highlight"
|
||||
attrs="{'invisible': [('invoice_exists', '=', False)]}"/>
|
||||
<button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice"
|
||||
type="action" states="manual" class="oe_highlight"/>
|
||||
<button name="cancel" states="draft,sent" string="Cancel"/>
|
||||
<button name="action_cancel" states="manual,progress" string="Cancel" type="object"/>
|
||||
<button name="invoice_cancel" states="invoice_except" string="Cancel"/>
|
||||
</span>
|
||||
<button name="invoice_recreate" states="invoice_except" string="Recreate Invoice" groups="base.group_user"/>
|
||||
<button name="invoice_corrected" states="invoice_except" string="Ignore Exception" groups="base.group_user"/>
|
||||
<button name="action_quotation_send" string="Send by Mail" type="object" states="draft" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="action_quotation_send" string="Send by Mail" type="object" states="sent" groups="base.group_user"/>
|
||||
<button name="print_quotation" string="Print" type="object" states="draft" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="print_quotation" string="Print" type="object" states="sent" groups="base.group_user"/>
|
||||
<button name="action_button_confirm" states="draft" string="Confirm" type="object" groups="base.group_user"/>
|
||||
<button name="action_button_confirm" states="sent" string="Confirm" class="oe_highlight" type="object" groups="base.group_user"/>
|
||||
<button name="action_view_invoice" string="View Invoice" type="object" class="oe_highlight"
|
||||
attrs="{'invisible': [('invoice_exists', '=', False)]}" groups="base.group_user"/>
|
||||
<button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice"
|
||||
type="action" states="manual" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="cancel" states="draft,sent" string="Cancel" groups="base.group_user"/>
|
||||
<button name="action_cancel" states="manual,progress" string="Cancel" type="object" groups="base.group_user"/>
|
||||
<button name="invoice_cancel" states="invoice_except" string="Cancel" groups="base.group_user"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,sent,invoiced,done" statusbar_colors='{"invoice_except":"red","waiting_date":"blue"}'/>
|
||||
</header>
|
||||
<sheet>
|
||||
@@ -225,8 +223,8 @@
|
||||
</group>
|
||||
<group>
|
||||
<field name="tax_id" widget="many2many_tags" domain="[('parent_id','=',False),('type_tax_use','<>','purchase')]"/>
|
||||
<field name="type"/>
|
||||
<field name="th_weight"/>
|
||||
|
||||
<!-- we should put a config wizard for these two fields -->
|
||||
<field name="address_allotment_id"/>
|
||||
</group>
|
||||
@@ -464,21 +462,19 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Sales Order Lines" version="7.0">
|
||||
<header>
|
||||
<span groups="base.group_user">
|
||||
<button name="button_cancel" string="Cancel" type="object" states="confirmed,exception"/>
|
||||
<button name="%(action_view_sale_order_line_make_invoice)d" string="Create Invoice" type="action" attrs="{'invisible': ['|',('invoiced', '=', 1), ('state', 'not in', ('confirmed', 'draft'))]}" class="oe_highlight"/>
|
||||
<button name="button_done" string="Done" type="object" attrs="{'invisible': ['|',('invoiced', '=', 0), ('state', 'not in', ('confirmed', 'exception'))]}" class="oe_highlight"/>
|
||||
</span>
|
||||
<button name="button_cancel" string="Cancel" type="object" states="confirmed,exception" groups="base.group_user"/>
|
||||
<button name="%(action_view_sale_order_line_make_invoice)d" string="Create Invoice" type="action" attrs="{'invisible': ['|',('invoiced', '=', 1), ('state', 'not in', ('confirmed', 'draft'))]}" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="button_done" string="Done" type="object" attrs="{'invisible': ['|',('invoiced', '=', 0), ('state', 'not in', ('confirmed', 'exception'))]}" class="oe_highlight" groups="base.group_user"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,confirmed,done" statusbar_colors='{"exception":"red","cancel":"red"}'/>
|
||||
</header>
|
||||
<sheet>
|
||||
<label for="order_id" class="oe_edit_only"/>
|
||||
<h1><field name="order_id"/></h1>
|
||||
<h1><field name="order_id" domain="[('state','!=','done')]"/></h1>
|
||||
<label for="order_partner_id" class="oe_edit_only"/>
|
||||
<h2><field name="order_partner_id"/></h2>
|
||||
<group>
|
||||
<group>
|
||||
<field name="product_id" readonly="1"/>
|
||||
<field name="product_id"/>
|
||||
<label for="product_uom_qty"/>
|
||||
<div>
|
||||
<field name="product_uom_qty" readonly="1" class="oe_inline"/>
|
||||
|
||||
@@ -490,8 +490,6 @@ class sale_order_line(osv.osv):
|
||||
_columns = {
|
||||
'delay': fields.float('Delivery Lead Time', required=True, help="Number of days between the order confirmation the shipping of the products to the customer", readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'procurement_id': fields.many2one('procurement.order', 'Procurement'),
|
||||
'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]},
|
||||
help="If 'on order', it triggers a procurement when the sale order is confirmed to create a task, purchase order or manufacturing order linked to this sale order line."),
|
||||
'property_ids': fields.many2many('mrp.property', 'sale_order_line_property_rel', 'order_id', 'property_id', 'Properties', readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'product_packaging': fields.many2one('product.packaging', 'Packaging'),
|
||||
'move_ids': fields.one2many('stock.move', 'sale_line_id', 'Inventory Moves', readonly=True),
|
||||
@@ -499,7 +497,6 @@ class sale_order_line(osv.osv):
|
||||
}
|
||||
_defaults = {
|
||||
'delay': 0.0,
|
||||
'type': 'make_to_stock',
|
||||
'product_packaging': False,
|
||||
}
|
||||
|
||||
|
||||
@@ -80,19 +80,18 @@
|
||||
</tree>
|
||||
</field>
|
||||
</field>
|
||||
<xpath expr="//page[@string='Order Lines']/field[@name='order_line']/form[@string='Sales Order Lines']/group/group/field[@name='th_weight']" position="before">
|
||||
<xpath expr="//page[@string='Order Lines']/field[@name='order_line']/form[@string='Sales Order Lines']/group/group/field[@name='type']" position="before">
|
||||
<label for="delay"/>
|
||||
<div>
|
||||
<field name="delay" class="oe_inline"/> days
|
||||
</div>
|
||||
<field name="type"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[@string='Order Lines']/field[@name='order_line']/form[@string='Sales Order Lines']/group/group/field[@name='address_allotment_id']" position="after">
|
||||
<field name="property_ids" widget="many2many_tags"
|
||||
groups="sale.group_mrp_properties"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[@string='Order Lines']/field[@name='order_line']/form[@string='Sales Order Lines']/group/group/field[@name='tax_id']" position="before">
|
||||
<field name="product_packaging" context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}" on_change="product_packaging_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, parent.partner_id, product_packaging, True, context)" domain="[('product_id','=',product_id)]" groups="product.group_stock_packaging" colspan="3"/>
|
||||
<field name="product_packaging" context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}" on_change="product_packaging_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, parent.partner_id, product_packaging, True, context)" domain="[('product_id','=',product_id)]" groups="product.group_stock_packaging" />
|
||||
</xpath>
|
||||
<xpath expr="//page[@string='Order Lines']/field[@name='order_line']/form[@string='Sales Order Lines']/div/field[@name='invoice_lines']" position="after">
|
||||
<label for="move_ids"/>
|
||||
|
||||
+11
-15
@@ -746,16 +746,14 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Internal Picking List" version="7.0">
|
||||
<header>
|
||||
<span groups="base.group_user">
|
||||
<button name="draft_force_assign" states="draft" string="Confirm" type="object" class="oe_highlight"/>
|
||||
<button name="draft_validate" states="draft" string="Confirm & Transfer" type="object" class="oe_highlight"/>
|
||||
<!-- <button name="action_assign" states="confirmed" string="Check Availability" type="object"/> -->
|
||||
<button name="force_assign" states="confirmed" string="Force Availability" type="object" class="oe_highlight"/>
|
||||
<button name="action_process" states="assigned" string="Confirm & Transfer" groups="stock.group_stock_user" type="object" class="oe_highlight"/>
|
||||
<button name="%(action_stock_invoice_onshipping)d" string="Create Invoice/Refund" attrs="{'invisible': ['|','|',('state','<>','done'),('invoice_state','=','invoiced'),('invoice_state','=','none')]}" type="action" class="oe_highlight"/>
|
||||
<button name="%(act_stock_return_picking)d" string="Reverse Transfer" states="done" type="action"/>
|
||||
<button name="button_cancel" states="assigned,confirmed,draft" string="_Cancel"/>
|
||||
</span>
|
||||
<button name="draft_force_assign" states="draft" string="Confirm" type="object" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="draft_validate" states="draft" string="Confirm & Transfer" type="object" class="oe_highlight" groups="base.group_user"/>
|
||||
<!-- <button name="action_assign" states="confirmed" string="Check Availability" type="object"/> -->
|
||||
<button name="force_assign" states="confirmed" string="Force Availability" type="object" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="action_process" states="assigned" string="Confirm & Transfer" groups="stock.group_stock_user" type="object" class="oe_highlight"/>
|
||||
<button name="%(action_stock_invoice_onshipping)d" string="Create Invoice/Refund" attrs="{'invisible': ['|','|',('state','<>','done'),('invoice_state','=','invoiced'),('invoice_state','=','none')]}" type="action" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="%(act_stock_return_picking)d" string="Reverse Transfer" states="done" type="action" groups="base.group_user"/>
|
||||
<button name="button_cancel" states="assigned,confirmed,draft" string="_Cancel" groups="base.group_user"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,assigned,done" statusbar_colors='{"shipping_except":"red","invoice_except":"red","waiting_date":"blue"}'/>
|
||||
</header>
|
||||
<sheet>
|
||||
@@ -1282,11 +1280,9 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Stock Moves" version="7.0">
|
||||
<header>
|
||||
<span groups="base.group_user">
|
||||
<button name="force_assign" states="confirmed" string="Force Availability" type="object"/>
|
||||
<button name="action_confirm" states="draft" string="Confirm" type="object"/>
|
||||
<button name="cancel_assign" states="assigned" string="Cancel Availability" type="object"/>
|
||||
</span>
|
||||
<button name="force_assign" states="confirmed" string="Force Availability" type="object" groups="base.group_user"/>
|
||||
<button name="action_confirm" states="draft" string="Confirm" type="object" groups="base.group_user"/>
|
||||
<button name="cancel_assign" states="assigned" string="Cancel Availability" type="object" groups="base.group_user"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,assigned,done"/>
|
||||
</header>
|
||||
<group>
|
||||
|
||||
Reference in New Issue
Block a user