[MERGE] Sync with trunk

bzr revid: odo@openerp.com-20121109133623-pvgt4b9koun74ib3
This commit is contained in:
Olivier Dony 2012-11-09 14:36:23 +01:00
commit d47d5f202d
87 changed files with 18774 additions and 267 deletions

View File

@ -541,10 +541,18 @@ class account_account(osv.osv):
return False
return True
def _check_company_account(self, cr, uid, ids, context=None):
for account in self.browse(cr, uid, ids, context=context):
if account.parent_id:
if account.company_id != account.parent_id.company_id:
return False
return True
_constraints = [
(_check_recursion, 'Error!\nYou cannot create recursive accounts.', ['parent_id']),
(_check_type, 'Configuration Error!\nYou cannot define children to an account with internal type different of "View".', ['type']),
(_check_account_type, 'Configuration Error!\nYou cannot select an account type with a deferral method different of "Unreconciled" for accounts with internal type "Payable/Receivable".', ['user_type','type']),
(_check_company_account, 'Error!\nYou cannot create an account which has parent account of different company.', ['parent_id']),
]
_sql_constraints = [
('code_company_uniq', 'unique (code,company_id)', 'The code of the account must be unique per company !')

View File

@ -975,7 +975,7 @@ class account_move_line(osv.osv):
if context is None:
context = {}
result = super(account_move_line, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu)
if view_type != 'tree':
if (view_type != 'tree') or view_id:
#Remove the toolbar from the form view
if view_type == 'form':
if result.get('toolbar', False):

View File

@ -1791,7 +1791,7 @@
<field name="name"/>
<field name="active"/>
</group>
<field name="note" placeholder="Note fo the invoice..."/>
<field name="note" placeholder="Note for the invoice..."/>
<separator string="Computation"/>
<field name="line_ids"/>
</form>

View File

@ -48,7 +48,7 @@ openerp.account = function (instance) {
this.last_group_by = group_by;
this.old_search = _.bind(this._super, this);
var mod = new instance.web.Model("account.move.line", context, domain);
return mod.call("list_partners_to_reconcile", []).pipe(function(result) {
return mod.call("list_partners_to_reconcile", []).then(function(result) {
var current = self.current_partner !== null ? self.partners[self.current_partner][0] : null;
self.partners = result;
var index = _.find(_.range(self.partners.length), function(el) {
@ -74,7 +74,7 @@ openerp.account = function (instance) {
return fct();
} else {
return new instance.web.Model("res.partner").call("read",
[self.partners[self.current_partner][0], ["last_reconciliation_date"]]).pipe(function(res) {
[self.partners[self.current_partner][0], ["last_reconciliation_date"]]).then(function(res) {
self.last_reconciliation_date =
instance.web.format_value(res.last_reconciliation_date, {"type": "datetime"}, _t("Never"));
return fct();
@ -92,7 +92,7 @@ openerp.account = function (instance) {
return false;
}
new instance.web.Model("ir.model.data").call("get_object_reference", ["account", "action_view_account_move_line_reconcile"]).pipe(function(result) {
new instance.web.Model("ir.model.data").call("get_object_reference", ["account", "action_view_account_move_line_reconcile"]).then(function(result) {
var additional_context = _.extend({
active_id: ids[0],
active_ids: ids,
@ -101,7 +101,7 @@ openerp.account = function (instance) {
return self.rpc("/web/action/load", {
action_id: result[1],
context: additional_context
}).then(function (result) {
}).done(function (result) {
result.context = _.extend(result.context || {}, additional_context);
result.flags = result.flags || {};
result.flags.new_window = true;
@ -116,7 +116,7 @@ openerp.account = function (instance) {
mark_as_reconciled: function() {
var self = this;
var id = self.partners[self.current_partner][0];
new instance.web.Model("res.partner").call("mark_as_reconciled", [[id]]).pipe(function() {
new instance.web.Model("res.partner").call("mark_as_reconciled", [[id]]).then(function() {
self.do_search(self.last_domain, self.last_context, self.last_group_by);
});
},

View File

@ -7,14 +7,15 @@ 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-05-10 17:31+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"PO-Revision-Date: 2012-11-07 13:27+0000\n"
"Last-Translator: Frederic Clementi - Camptocamp.com "
"<frederic.clementi@camptocamp.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-30 05:19+0000\n"
"X-Generator: Launchpad (build 16206)\n"
"X-Launchpad-Export-Date: 2012-11-08 04:47+0000\n"
"X-Generator: Launchpad (build 16232)\n"
#. module: account_voucher
#: view:sale.receipt.report:0
@ -469,7 +470,7 @@ msgstr "Délai moyen de règlement"
#. module: account_voucher
#: field:res.company,income_currency_exchange_account_id:0
msgid "Income Currency Rate"
msgstr "Taux de change d'achat"
msgstr "Compte de gain de change"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1063
@ -625,9 +626,9 @@ msgid ""
"Unable to create accounting entry for currency rate difference. You have to "
"configure the field 'Income Currency Rate' on the company! "
msgstr ""
"Impossible de créer une entrée de la comptabilité à cause de la différence "
"de taux de change. Vous devez configurer le champ 'Taux de change de vente' "
"sur la société! "
"Impossible de créer une écriture comptable à cause de la différence de taux "
"de change. Vous devez configurer le champ 'Compte de gain de change' au "
"niveau du formulaire de la société! "
#. module: account_voucher
#: view:account.voucher:0 view:sale.receipt.report:0
@ -802,7 +803,7 @@ msgstr "Factures et transactions exceptionnelles"
#. module: account_voucher
#: field:res.company,expense_currency_exchange_account_id:0
msgid "Expense Currency Rate"
msgstr "Taux de change de la dépense"
msgstr "Compte de perte de change"
#. module: account_voucher
#: sql_constraint:account.invoice:0
@ -1089,9 +1090,9 @@ msgid ""
"Unable to create accounting entry for currency rate difference. You have to "
"configure the field 'Expense Currency Rate' on the company! "
msgstr ""
"Impossible de créer une entrée en comptabilité pour la différence de taux de "
"change. Vous devez configurer le champ \"Taux de change d'achat\" de la "
"société ! "
"Impossible de créer une écriture comptable à cause de la différence de taux "
"de change. Vous devez configurer le champ 'Compte de perte de change' au "
"niveau du formulaire de la société! "
#. module: account_voucher
#: field:account.voucher,type:0
@ -1156,7 +1157,7 @@ msgstr "Année"
#. module: account_voucher
#: field:account.voucher.line,amount_unreconciled:0
msgid "Open Balance"
msgstr "Solde initial"
msgstr "Restant dû"
#. module: account_voucher
#: view:account.voucher:0 field:account.voucher,amount:0

View File

@ -40,7 +40,7 @@
Once the end date of the contract is
passed or the maximum number of service
units (e.g. support contract) is
reached, the account manager is warned
reached, the account manager is notified
by email to renew the contract with the
customer.
</p>

View File

@ -3,7 +3,7 @@ openerp.auth_anonymous = function(instance) {
instance.web.Login.include({
start: function() {
var self = this;
return $.when(this._super()).pipe(function() {
return $.when(this._super()).then(function() {
var dblist = self._db_list || [];
if (!self.session.session_is_valid() && dblist.length === 1) {
self.remember_credentials = false;

View File

@ -12,7 +12,7 @@ openerp.auth_oauth = function(instance) {
} else if(this.params.oauth_error === 2) {
this.do_warn("Authentication error","");
}
return d.then(this.do_oauth_load).fail(function() {
return d.done(this.do_oauth_load).fail(function() {
self.do_oauth_load([]);
});
},
@ -23,7 +23,7 @@ openerp.auth_oauth = function(instance) {
do_oauth_load: function() {
var db = this.$("form [name=db]").val();
if (db) {
this.rpc("/auth_oauth/list_providers", { dbname: db }).then(this.on_oauth_loaded);
this.rpc("/auth_oauth/list_providers", { dbname: db }).done(this.on_oauth_loaded);
}
},
on_oauth_loaded: function(result) {

View File

@ -69,7 +69,7 @@ instance.web.Login = instance.web.Login.extend({
_check_error: function() {
var self = this;
if (this.params.loginerror !== undefined) {
this.rpc('/auth_openid/login/status', {}).then(function(result) {
this.rpc('/auth_openid/login/status', {}).done(function(result) {
if (_.contains(['success', 'failure'], result.status) && result.message) {
self.do_warn('Invalid OpenID Login', result.message);
}
@ -106,7 +106,7 @@ instance.web.Login = instance.web.Login.extend({
do_openid_login: function(db, openid_url) {
var self = this;
this.rpc('/auth_openid/login/verify', {'db': db, 'url': openid_url}).then(function(result) {
this.rpc('/auth_openid/login/verify', {'db': db, 'url': openid_url}).done(function(result) {
if (result.error) {
self.do_warn(result.title, result.error);
return;

View File

@ -16,10 +16,10 @@
<group col="4">
<field name="name"/>
<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"/>
<field name="model" invisible="1"/>
</group>
<notebook>
<page string="Conditions">

View File

@ -139,7 +139,7 @@ openerp.base_import = function (instance) {
this._super(),
this.Import.call('create', [{
'res_model': this.res_model
}]).then(function (id) {
}]).done(function (id) {
self.id = id;
self.$('input[name=import_id]').val(id);
})
@ -200,7 +200,7 @@ openerp.base_import = function (instance) {
!this.$('input.oe_import_has_header').prop('checked'));
this.Import.call(
'parse_preview', [this.id, this.import_options()])
.then(function (result) {
.done(function (result) {
var signal = result.error ? 'preview_failed' : 'preview_succeeded';
self[signal](result);
});
@ -341,11 +341,11 @@ openerp.base_import = function (instance) {
},
onvalidate: function () {
return this.call_import({ dryrun: true })
.then(this.proxy('validated'));
.done(this.proxy('validated'));
},
onimport: function () {
var self = this;
return this.call_import({ dryrun: false }).then(function (message) {
return this.call_import({ dryrun: false }).done(function (message) {
if (!_.any(message, function (message) {
return message.type === 'error' })) {
self['import_succeeded']();

View File

@ -60,14 +60,14 @@ class sale_config_settings(osv.osv_memory):
'module_web_linkedin': fields.boolean('Get contacts automatically from linkedIn',
help="""When you create a new contact (person or company), you will be able to load all the data from LinkedIn (photos, address, etc)."""),
'module_crm': fields.boolean('CRM'),
'module_plugin_thunderbird': fields.boolean('Enable Thunderbird plugin',
'module_plugin_thunderbird': fields.boolean('Enable Thunderbird plug-in',
help="""The plugin allows you archive email and its attachments to the selected
OpenERP objects. You can select a partner, or a lead and
attach the selected mail as a .eml file in
the attachment of a selected record. You can create documents for CRM Lead,
Partner from the selected emails.
This installs the module plugin_thunderbird."""),
'module_plugin_outlook': fields.boolean('Enable Outlook plugin',
'module_plugin_outlook': fields.boolean('Enable Outlook plug-in',
help="""The Outlook plugin allows you to select an object that you would like to add
to your email and its attachments from MS Outlook. You can select a partner,
or a lead object and archive a selected

View File

@ -46,7 +46,7 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
delete(action.attrs.colspan);
var action_id = _.str.toNumber(action.attrs.name);
if (!_.isNaN(action_id)) {
self.rpc('/web/action/load', {action_id: action_id}).then(function(result) {
self.rpc('/web/action/load', {action_id: action_id}).done(function(result) {
self.on_load_action(result, column_index + '_' + action_index, action.attrs);
});
}
@ -81,7 +81,7 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
this.rpc('/web/view/undo_custom', {
view_id: this.view.fields_view.view_id,
reset: true
}).then(this.do_reload);
}).done(this.do_reload);
},
on_change_layout: function() {
var self = this;
@ -242,7 +242,7 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
};
var list = am.inner_widget.views.list;
if (list) {
list.deferred.then(function() {
list.deferred.done(function() {
$(list.controller.groups).off('row_link').on('row_link', function(e, id) {
new_form_action(id);
});
@ -250,7 +250,7 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
}
var kanban = am.inner_widget.views.kanban;
if (kanban) {
kanban.deferred.then(function() {
kanban.deferred.done(function() {
kanban.controller.open_record = function(id, editable) {
new_form_action(id, editable);
};
@ -335,7 +335,7 @@ instance.board.AddToDashboard = instance.web.search.Input.extend({
e.preventDefault();
self.add_dashboard();
});
return this.load_data().then(this.proxy("render_data"));
return this.load_data().done(this.proxy("render_data"));
},
load_data:function(){
var board = new instance.web.Model('board.board');
@ -347,7 +347,7 @@ instance.board.AddToDashboard = instance.web.search.Input.extend({
return new instance.web.Model('ir.model.data')
.query(['res_id'])
.filter([['name','=','menu_reporting_dashboard']])
.first().pipe(function (result) {
.first().then(function (result) {
var menu = _(dashboard_menu).chain()
.pluck('children')
.flatten(true)
@ -382,7 +382,7 @@ instance.board.AddToDashboard = instance.web.search.Input.extend({
domain: domain,
view_mode: view_parent.active_view,
name: this.$el.find("input").val()
}).then(function(r) {
}).done(function(r) {
if (r === false) {
self.do_warn("Could not add filter to dashboard");
} else {

View File

@ -610,9 +610,9 @@ class crm_lead(base_stage, format_address, osv.osv):
}
def convert_opportunity(self, cr, uid, ids, partner_id, user_ids=False, section_id=False, context=None):
partner = self.pool.get('res.partner')
customer = False
if partner_id:
partner = self.pool.get('res.partner')
customer = partner.browse(cr, uid, partner_id, context=context)
for lead in self.browse(cr, uid, ids, context=context):
if lead.state in ('done', 'cancel'):
@ -676,19 +676,17 @@ class crm_lead(base_stage, format_address, osv.osv):
def convert_partner(self, cr, uid, ids, action='create', partner_id=False, context=None):
"""
This function convert partner based on action.
Convert partner based on action.
if action is 'create', create new partner with contact and assign lead to new partner_id.
otherwise assign lead to specified partner_id
"""
if context is None:
context = {}
partner_ids = {}
force_partner_id = partner_id
for lead in self.browse(cr, uid, ids, context=context):
if action == 'create':
if not partner_id:
partner_id = self._create_lead_partner(cr, uid, lead, context)
partner_id = force_partner_id or self._create_lead_partner(cr, uid, lead, context=context)
self._lead_set_partner(cr, uid, lead, partner_id, context=context)
partner_ids[lead.id] = partner_id
return partner_ids

View File

@ -56,6 +56,7 @@ added to partners that match the segmentation criterions after computation.'),
@param uid: the current users ID for security checks,
@param ids: List of Process continues IDs"""
partner_obj = self.pool.get('res.partner')
categs = self.read(cr, uid, ids, ['categ_id', 'exclusif', 'partner_id',\
'sales_purchase_active', 'profiling_active'])
for categ in categs:
@ -80,9 +81,11 @@ added to partners that match the segmentation criterions after computation.'),
for pid in to_remove_list:
partners.remove(pid)
for partner_id in partners:
cr.execute('insert into res_partner_res_partner_category_rel (category_id,partner_id) \
values (%s,%s)', (categ['categ_id'][0], partner_id))
for partner in partner_obj.browse(cr, uid, partners):
category_ids = [categ_id.id for categ_id in partner.category_id]
if categ['categ_id'][0] not in category_ids:
cr.execute('insert into res_partner_res_partner_category_rel (category_id,partner_id) \
values (%s,%s)', (categ['categ_id'][0], partner.id))
self.write(cr, uid, [id], {'state':'not running', 'partner_id':0})
return True

View File

@ -175,12 +175,19 @@ class crm_lead2opportunity_mass_convert(osv.osv_memory):
return res
def _convert_opportunity(self, cr, uid, ids, vals, context=None):
"""
When "massively" (more than one at a time) converting leads to
opportunities, check the salesteam_id and salesmen_ids and update
the values before calling super.
"""
if context is None:
context = {}
data = self.browse(cr, uid, ids, context=context)[0]
salesteam_id = data.section_id and data.section_id.id or False
salesman = []
salesmen_ids = []
if data.user_ids:
salesman = [x.id for x in data.user_ids]
vals.update({'user_ids': salesman, 'section_id': salesteam_id})
salesmen_ids = [x.id for x in data.user_ids]
vals.update({'user_ids': salesmen_ids, 'section_id': salesteam_id})
return super(crm_lead2opportunity_mass_convert, self)._convert_opportunity(cr, uid, ids, vals, context=context)
def mass_convert(self, cr, uid, ids, context=None):

View File

@ -35,7 +35,7 @@ class crm_lead2partner(osv.osv_memory):
}
def view_init(self, cr, uid, fields, context=None):
"""
This function checks for precondition before wizard executes
Check for precondition before wizard executes.
"""
if context is None:
context = {}
@ -69,22 +69,19 @@ class crm_lead2partner(osv.osv_memory):
return partner_id
def default_get(self, cr, uid, fields, context=None):
"""
This function gets default values
"""
res = super(crm_lead2partner, self).default_get(cr, uid, fields, context=context)
res = super(crm_lead2partner, self).default_get(cr, uid, fields, context=context)
partner_id = self._select_partner(cr, uid, context=context)
if 'partner_id' in fields:
res.update({'partner_id': partner_id})
if 'action' in fields:
res.update({'action': partner_id and 'exist' or 'create'})
return res
def open_create_partner(self, cr, uid, ids, context=None):
"""
This function Opens form of create partner.
Open form of create partner.
"""
view_obj = self.pool.get('ir.ui.view')
view_id = view_obj.search(cr, uid, [('model', '=', self._name), \
@ -101,21 +98,21 @@ class crm_lead2partner(osv.osv_memory):
def _create_partner(self, cr, uid, ids, context=None):
"""
This function Creates partner based on action.
Create partner based on action.
"""
if context is None:
context = {}
lead = self.pool.get('crm.lead')
lead_ids = context and context.get('active_ids') or []
lead_ids = context.get('active_ids', [])
data = self.browse(cr, uid, ids, context=context)[0]
partner_id = data.partner_id and data.partner_id.id or False
return lead.convert_partner(cr, uid, lead_ids, data.action, partner_id, context=context)
def make_partner(self, cr, uid, ids, context=None):
"""
This function Makes partner based on action.
Make a partner based on action.
Only called from form view, so only meant to convert one lead at a time.
"""
# Only called from Form view, so only meant to convert one Lead.
lead_id = context and context.get('active_id') or False
partner_ids_map = self._create_partner(cr, uid, ids, context=context)
return self.pool.get('res.partner').redirect_partner_form(cr, uid, partner_ids_map.get(lead_id, False), context=context)

View File

@ -244,6 +244,7 @@ class crm_segmentation(osv.osv):
@param uid: the current users ID for security checks,
@param ids: List of crm segmentations IDs """
partner_obj = self.pool.get('res.partner')
categs = self.read(cr,uid,ids,['categ_id','exclusif','partner_id', \
'sales_purchase_active', 'profiling_active'])
for categ in categs:
@ -280,8 +281,10 @@ class crm_segmentation(osv.osv):
for pid in to_remove_list:
partners.remove(pid)
for partner_id in partners:
cr.execute('insert into res_partner_res_partner_category_rel (category_id,partner_id) values (%s,%s)', (categ['categ_id'][0],partner_id))
for partner in partner_obj.browse(cr, uid, partners):
category_ids = [categ_id.id for categ_id in partner.category_id]
if categ['categ_id'][0] not in category_ids:
cr.execute('insert into res_partner_res_partner_category_rel (category_id,partner_id) values (%s,%s)', (categ['categ_id'][0],partner.id))
self.write(cr, uid, [id], {'state':'not running', 'partner_id':0})
return True

View File

@ -39,11 +39,11 @@ instance.edi.EdiImport = instance.web.Widget.extend({
},
do_import: function() {
this.rpc('/edi/import_edi_url', {url: this.url}).then(this.on_imported, this.on_imported_error);
this.rpc('/edi/import_edi_url', {url: this.url}).done(this.on_imported).fail(this.on_imported_error);
},
on_imported: function(response) {
if ('action' in response) {
this.rpc("/web/session/save_session_action", {the_action: response.action}).then(function(key) {
this.rpc("/web/session/save_session_action", {the_action: response.action}).done(function(key) {
window.location = "/#sa="+encodeURIComponent(key);
});
}
@ -78,7 +78,7 @@ instance.edi.EdiImport = instance.web.Widget.extend({
});
instance.edi.edi_import = function (url) {
instance.session.session_bind().then(function () {
instance.session.session_bind().done(function () {
new instance.edi.EdiImport(null,url).appendTo($("body").addClass('openerp'));
});
}

View File

@ -510,7 +510,7 @@
<field name="model">event.registration</field>
<field name="arch" type="xml">
<search string="Event Registration">
<field name="name" string="Participant" filter_domain="['|','|','|',('name','ilike',self),('partner_id','ilike',self),('email','ilike',self),('origin','ilike',self)]"/>
<field name="name" string="Participant" filter_domain="['|','|',('name','ilike',self),('email','ilike',self),('origin','ilike',self)]"/>
<filter icon="terp-mail-message-new" string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]"/>
<separator/>
<filter icon="terp-check" string="New" name="draft" domain="[('state','=','draft')]" help="Registrations in unconfirmed state"/>
@ -519,6 +519,7 @@
<filter icon="terp-personal" string="My Registrations" help="My Registrations" domain="[('user_id','=',uid)]"/>
<field name="event_id"/>
<field name="user_id"/>
<field name="partner_id"/>
<group expand="0" string="Group By...">
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>

21
addons/fleet/__init__.py Normal file
View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import fleet

View File

@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name' : 'Fleet Management',
'version' : '0.1',
'author' : 'OpenERP S.A.',
'category': 'Managing vehicles and contracts',
'website' : 'http://www.openerp.com',
'summary' : 'Vehicle, leasing, insurances, costs',
'description' : """
Vehicle, leasing, insurances, cost
==================================
With this module, OpenERP helps you managing all your vehicles, the
contracts associated to those vehicle as well as services, fuel log
entries, costs and many other features necessary to the management
of your fleet of vehicle(s)
Main Features
-------------
* Add vehicles to your fleet
* Manage contracts for vehicles
* Reminder when a contract reach its expiration date
* Add services, fuel log entry, odometer values for all vehicles
* Show all costs associated to a vehicle or to a type of service
* Analysis graph for costs
""",
'depends' : [
'base',
'mail',
'board'
],
'data' : [
'fleet_view.xml',
'fleet_data.xml',
'fleet_board_view.xml',
],
'update_xml' : ['security/ir.model.access.csv'],
'demo': ['fleet_cars.xml','fleet_demo.xml'],
'installable' : True,
'application' : True,
}

818
addons/fleet/fleet.py Normal file
View File

@ -0,0 +1,818 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import osv, fields
import time
import datetime
import tools
from osv.orm import except_orm
from tools.translate import _
from dateutil.relativedelta import relativedelta
def str_to_datetime(strdate):
return datetime.datetime.strptime(strdate, tools.DEFAULT_SERVER_DATE_FORMAT)
class fleet_vehicle_cost(osv.Model):
_name = 'fleet.vehicle.cost'
_description = 'Cost related to a vehicle'
_order = 'date desc, vehicle_id asc'
def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
res = dict.fromkeys(ids, False)
for record in self.browse(cr,uid,ids,context=context):
if record.odometer_id:
res[record.id] = record.odometer_id.value
return res
def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
if not value:
raise except_orm(_('Operation not allowed!'), _('Emptying the odometer value of a vehicle is not allowed.'))
date = self.browse(cr, uid, id, context=context).date
if not(date):
date = fields.date.context_today(self, cr, uid, context=context)
vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id
data = {'value': value, 'date': date, 'vehicle_id': vehicle_id.id}
odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
return self.write(cr, uid, id, {'odometer_id': odometer_id}, context=context)
def _year_get_fnc(self, cr, uid, ids, name, unknow_none, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
res[record.id] = str(time.strptime(record.date, tools.DEFAULT_SERVER_DATE_FORMAT).tm_year)
return res
def _cost_name_get_fnc(self, cr, uid, ids, name, unknow_none, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
name = record.vehicle_id.name
if record.cost_subtype.name:
name += ' / '+ record.cost_subtype.name
if record.date:
name += ' / '+ record.date
res[record.id] = name
return res
_columns = {
'name': fields.function(_cost_name_get_fnc, type="char", string='Name', store=True),
'vehicle_id': fields.many2one('fleet.vehicle', 'Vehicle', required=True, help='Vehicle concerned by this log'),
'cost_subtype': fields.many2one('fleet.service.type', 'Type', help='Cost type purchased with this cost'),
'amount': fields.float('Total Price'),
'cost_type': fields.selection([('contract', 'Contract'), ('services','Services'), ('fuel','Fuel'), ('other','Other')], 'Category of the cost', help='For internal purpose only', required=True),
'parent_id': fields.many2one('fleet.vehicle.cost', 'Parent', help='Parent cost to this current cost'),
'cost_ids': fields.one2many('fleet.vehicle.cost', 'parent_id', 'Included Services'),
'odometer_id': fields.many2one('fleet.vehicle.odometer', 'Odometer', help='Odometer measure of the vehicle at the moment of this log'),
'odometer': fields.function(_get_odometer, fnct_inv=_set_odometer, type='float', string='Odometer Value', help='Odometer measure of the vehicle at the moment of this log'),
'odometer_unit': fields.related('vehicle_id', 'odometer_unit', type="char", string="Unit", readonly=True),
'date' :fields.date('Date',help='Date when the cost has been executed'),
'contract_id': fields.many2one('fleet.vehicle.log.contract', 'Contract', help='Contract attached to this cost'),
'auto_generated': fields.boolean('Automatically Generated', readonly=True, required=True),
'year': fields.function(_year_get_fnc, type="char", string='Year', store=True),
}
_defaults ={
'cost_type': 'other',
}
def create(self, cr, uid, data, context=None):
#make sure that the data are consistent with values of parent and contract records given
if 'parent_id' in data and data['parent_id']:
parent = self.browse(cr, uid, data['parent_id'], context=context)
data['vehicle_id'] = parent.vehicle_id.id
data['date'] = parent.date
data['cost_type'] = parent.cost_type
if 'contract_id' in data and data['contract_id']:
contract = self.pool.get('fleet.vehicle.log.contract').browse(cr, uid, data['contract_id'], context=context)
data['vehicle_id'] = contract.vehicle_id.id
data['cost_subtype'] = contract.cost_subtype.id
data['cost_type'] = contract.cost_type
if 'odometer' in data and not data['odometer']:
#if received value for odometer is 0, then remove it from the data as it would result to the creation of a
#odometer log with 0, which is to be avoided
del(data['odometer'])
return super(fleet_vehicle_cost, self).create(cr, uid, data, context=context)
class fleet_vehicle_tag(osv.Model):
_name = 'fleet.vehicle.tag'
_columns = {
'name': fields.char('Name', required=True, translate=True),
}
class fleet_vehicle_state(osv.Model):
_name = 'fleet.vehicle.state'
_order = 'sequence asc'
_columns = {
'name': fields.char('Name', required=True),
'sequence': fields.integer('Order', help="Used to order the note stages")
}
_sql_constraints = [('fleet_state_name_unique','unique(name)', 'State name already exists')]
class fleet_vehicle_model(osv.Model):
def _model_name_get_fnc(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
name = record.modelname
if record.brand.name:
name = record.brand.name + ' / ' + name
res[record.id] = name
return res
def on_change_brand(self, cr, uid, ids, model_id, context=None):
if not model_id:
return {'value': {'image_medium': False}}
brand = self.pool.get('fleet.vehicle.model.brand').browse(cr, uid, model_id, context=context)
return {
'value': {
'image_medium': brand.image,
}
}
_name = 'fleet.vehicle.model'
_description = 'Model of a vehicle'
_order = 'name asc'
_columns = {
'name': fields.function(_model_name_get_fnc, type="char", string='Name', store=True),
'modelname': fields.char('Model name', size=32, required=True),
'brand': fields.many2one('fleet.vehicle.model.brand', 'Model Brand', required=True, help='Brand of the vehicle'),
'vendors': fields.many2many('res.partner', 'fleet_vehicle_model_vendors', 'model_id', 'partner_id', string='Vendors'),
'image': fields.related('brand', 'image', type="binary", string="Logo"),
'image_medium': fields.related('brand', 'image_medium', type="binary", string="Logo"),
'image_small': fields.related('brand', 'image_small', type="binary", string="Logo"),
}
class fleet_vehicle_model_brand(osv.Model):
_name = 'fleet.vehicle.model.brand'
_description = 'Brand model of the vehicle'
_order = 'name asc'
def _get_image(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False)
for obj in self.browse(cr, uid, ids, context=context):
result[obj.id] = tools.image_get_resized_images(obj.image)
return result
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
_columns = {
'name': fields.char('Brand Name', size=64, required=True),
'image': fields.binary("Logo",
help="This field holds the image used as logo for the brand, limited to 1024x1024px."),
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
string="Medium-sized photo", type="binary", multi="_get_image",
store = {
'fleet.vehicle.model.brand': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Medium-sized logo of the brand. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views."),
'image_small': fields.function(_get_image, fnct_inv=_set_image,
string="Smal-sized photo", type="binary", multi="_get_image",
store = {
'fleet.vehicle.model.brand': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Small-sized photo of the brand. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
}
class fleet_vehicle(osv.Model):
_inherit = 'mail.thread'
def _vehicle_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
res[record.id] = record.model_id.brand.name + '/' + record.model_id.modelname + ' / ' + record.license_plate
return res
def return_action_to_open(self, cr, uid, ids, context=None):
""" This opens the xml view specified in xml_id for the current vehicle """
if context is None:
context = {}
if context.get('xml_id'):
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet', context['xml_id'], context=context)
res['context'] = context
res['context'].update({'default_vehicle_id': ids[0]})
res['domain'] = [('vehicle_id','=', ids[0])]
return res
return False
def act_show_log_cost(self, cr, uid, ids, context=None):
""" This opens log view to view and add new log for this vehicle, groupby default to only show effective costs
@return: the costs log view
"""
if context is None:
context = {}
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','fleet_vehicle_costs_act', context=context)
res['context'] = context
res['context'].update({
'default_vehicle_id': ids[0],
'search_default_parent_false': True
})
res['domain'] = [('vehicle_id','=', ids[0])]
return res
def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
res = dict.fromkeys(ids, 0)
for record in self.browse(cr,uid,ids,context=context):
ids = self.pool.get('fleet.vehicle.odometer').search(cr, uid, [('vehicle_id', '=', record.id)], limit=1, order='value desc')
if len(ids) > 0:
res[record.id] = self.pool.get('fleet.vehicle.odometer').browse(cr, uid, ids[0], context=context).value
return res
def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
if value:
date = fields.date.context_today(self, cr, uid, context=context)
data = {'value': value, 'date': date, 'vehicle_id': id}
return self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
def _search_get_overdue_contract_reminder(self, cr, uid, obj, name, args, context):
res = []
today = fields.date.today(self, cr, uid, context=context)
for field, operator, value in args:
assert operator in ('=', '!=', '<>') and value in (True, False), 'Operation not supported'
if (operator == '=' and value == True) or (operator in ('<>', '!=') and value == False):
search_operator = 'in'
else:
search_operator = 'not in'
today = fields.date.context_today(self, cr, uid, context=context)
cr.execute('select cost.vehicle_id, count(contract.id) as contract_number FROM fleet_vehicle_cost cost left join fleet_vehicle_log_contract contract on contract.cost_id = cost.id WHERE contract.expiration_date is not null AND contract.expiration_date < %s AND contract.state IN (\'open\', \'toclose\') GROUP BY cost.vehicle_id', (today,))
res_ids = [x[0] for x in cr.fetchall()]
res.append(('id', search_operator, res_ids))
return res
def _search_contract_renewal_due_soon(self, cr, uid, obj, name, args, context):
res = []
for field, operator, value in args:
assert operator in ('=', '!=', '<>') and value in (True, False), 'Operation not supported'
if (operator == '=' and value == True) or (operator in ('<>', '!=') and value == False):
search_operator = 'in'
else:
search_operator = 'not in'
today = fields.date.context_today(self, cr, uid, context=context)
datetime_today = datetime.datetime.strptime(today, tools.DEFAULT_SERVER_DATE_FORMAT)
limit_date = str((datetime_today + relativedelta(days=+15)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT))
cr.execute('select cost.vehicle_id, count(contract.id) as contract_number FROM fleet_vehicle_cost cost left join fleet_vehicle_log_contract contract on contract.cost_id = cost.id WHERE contract.expiration_date is not null AND contract.expiration_date > %s AND contract.expiration_date < %s AND contract.state IN (\'open\', \'toclose\') GROUP BY cost.vehicle_id', (today, limit_date))
res_ids = [x[0] for x in cr.fetchall()]
res.append(('id', search_operator, res_ids))
return res
def _get_contract_reminder_fnc(self, cr, uid, ids, field_names, unknow_none, context=None):
res= {}
for record in self.browse(cr, uid, ids, context=context):
overdue = False
due_soon = False
total = 0
name = ''
for element in record.log_contracts:
if element.state in ('open', 'toclose') and element.expiration_date:
current_date_str = fields.date.context_today(self, cr, uid, context=context)
due_time_str = element.expiration_date
current_date = str_to_datetime(current_date_str)
due_time = str_to_datetime(due_time_str)
diff_time = (due_time-current_date).days
if diff_time < 0:
overdue = True
total += 1
if diff_time < 15 and diff_time >= 0:
due_soon = True;
total += 1
if overdue or due_soon:
ids = self.pool.get('fleet.vehicle.log.contract').search(cr,uid,[('vehicle_id', '=', record.id), ('state', 'in', ('open', 'toclose'))], limit=1, order='expiration_date asc')
if len(ids) > 0:
#we display only the name of the oldest overdue/due soon contract
name=(self.pool.get('fleet.vehicle.log.contract').browse(cr, uid, ids[0], context=context).cost_subtype.name)
res[record.id] = {
'contract_renewal_overdue': overdue,
'contract_renewal_due_soon': due_soon,
'contract_renewal_total': (total - 1), #we remove 1 from the real total for display purposes
'contract_renewal_name': name,
}
return res
def _get_default_state(self, cr, uid, context):
try:
model, model_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'vehicle_state_active')
except ValueError:
model_id = False
return model_id
_name = 'fleet.vehicle'
_description = 'Information on a vehicle'
_order= 'license_plate asc'
_columns = {
'name': fields.function(_vehicle_name_get_fnc, type="char", string='Name', store=True),
'company_id': fields.many2one('res.company', 'Company'),
'license_plate': fields.char('License Plate', size=32, required=True, help='License plate number of the vehicle (ie: plate number for a car)'),
'vin_sn': fields.char('Chassis Number', size=32, help='Unique number written on the vehicle motor (VIN/SN number)'),
'driver': fields.many2one('res.partner', 'Driver', help='Driver of the vehicle'),
'model_id': fields.many2one('fleet.vehicle.model', 'Model', required=True, help='Model of the vehicle'),
'log_fuel': fields.one2many('fleet.vehicle.log.fuel', 'vehicle_id', 'Fuel Logs'),
'log_services': fields.one2many('fleet.vehicle.log.services', 'vehicle_id', 'Services Logs'),
'log_contracts': fields.one2many('fleet.vehicle.log.contract', 'vehicle_id', 'Contracts'),
'acquisition_date': fields.date('Acquisition Date', required=False, help='Date when the vehicle has been bought'),
'color': fields.char('Color', size=32, help='Color of the vehicle'),
'state': fields.many2one('fleet.vehicle.state', 'State', help='Current state of the vehicle', ondelete="set null"),
'location': fields.char('Location', size=128, help='Location of the vehicle (garage, ...)'),
'seats': fields.integer('Seats Number', help='Number of seats of the vehicle'),
'doors': fields.integer('Doors Number', help='Number of doors of the vehicle'),
'tag_ids' :fields.many2many('fleet.vehicle.tag', 'fleet_vehicle_vehicle_tag_rel', 'vehicle_tag_id','tag_id', 'Tags'),
'odometer': fields.function(_get_odometer, fnct_inv=_set_odometer, type='float', string='Odometer Value', help='Odometer measure of the vehicle at the moment of this log'),
'odometer_unit': fields.selection([('kilometers', 'Kilometers'),('miles','Miles')], 'Odometer Unit', help='Unit of the odometer ',required=True),
'transmission': fields.selection([('manual', 'Manual'), ('automatic', 'Automatic')], 'Transmission', help='Transmission Used by the vehicle'),
'fuel_type': fields.selection([('gasoline', 'Gasoline'), ('diesel', 'Diesel'), ('electric', 'Electric'), ('hybrid', 'Hybrid')], 'Fuel Type', help='Fuel Used by the vehicle'),
'horsepower': fields.integer('Horsepower'),
'horsepower_tax': fields.float('Horsepower Taxation'),
'power': fields.integer('Power (kW)', help='Power in kW of the vehicle'),
'co2': fields.float('CO2 Emissions', help='CO2 emissions of the vehicle'),
'image': fields.related('model_id', 'image', type="binary", string="Logo"),
'image_medium': fields.related('model_id', 'image_medium', type="binary", string="Logo"),
'image_small': fields.related('model_id', 'image_small', type="binary", string="Logo"),
'contract_renewal_due_soon': fields.function(_get_contract_reminder_fnc, fnct_search=_search_contract_renewal_due_soon, type="boolean", string='Has Contracts to renew', multi='contract_info'),
'contract_renewal_overdue': fields.function(_get_contract_reminder_fnc, fnct_search=_search_get_overdue_contract_reminder, type="boolean", string='Has Contracts Overdued', multi='contract_info'),
'contract_renewal_name': fields.function(_get_contract_reminder_fnc, type="text", string='Name of contract to renew soon', multi='contract_info'),
'contract_renewal_total': fields.function(_get_contract_reminder_fnc, type="integer", string='Total of contracts due or overdue minus one', multi='contract_info'),
'car_value': fields.float('Car Value', help='Value of the bought vehicle'),
}
_defaults = {
'doors': 5,
'odometer_unit': 'kilometers',
'state': _get_default_state,
}
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
default.update({
'log_fuel':[],
'log_contracts':[],
'log_services':[],
'tag_ids':[],
'vin_sn':'',
})
return super(fleet_vehicle, self).copy(cr, uid, id, default, context=context)
def on_change_model(self, cr, uid, ids, model_id, context=None):
if not model_id:
return {}
model = self.pool.get('fleet.vehicle.model').browse(cr, uid, model_id, context=context)
return {
'value': {
'image_medium': model.image,
}
}
def create(self, cr, uid, data, context=None):
vehicle_id = super(fleet_vehicle, self).create(cr, uid, data, context=context)
vehicle = self.browse(cr, uid, vehicle_id, context=context)
self.message_post(cr, uid, [vehicle_id], body=_('Vehicle %s has been added to the fleet!') % (vehicle.license_plate), context=context)
return vehicle_id
def write(self, cr, uid, ids, vals, context=None):
"""
This function write an entry in the openchatter whenever we change important information
on the vehicle like the model, the drive, the state of the vehicle or its license plate
"""
for vehicle in self.browse(cr, uid, ids, context):
changes = []
if 'model_id' in vals and vehicle.model_id.id != vals['model_id']:
value = self.pool.get('fleet.vehicle.model').browse(cr,uid,vals['model_id'],context=context).name
oldmodel = vehicle.model_id.name or _('None')
changes.append(_("Model: from '%s' to '%s'") %(oldmodel, value))
if 'driver' in vals and vehicle.driver.id != vals['driver']:
value = self.pool.get('res.partner').browse(cr,uid,vals['driver'],context=context).name
olddriver = (vehicle.driver.name) or _('None')
changes.append(_("Driver: from '%s' to '%s'") %(olddriver, value))
if 'state' in vals and vehicle.state.id != vals['state']:
value = self.pool.get('fleet.vehicle.state').browse(cr,uid,vals['state'],context=context).name
oldstate = vehicle.state.name or _('None')
changes.append(_("State: from '%s' to '%s'") %(oldstate, value))
if 'license_plate' in vals and vehicle.license_plate != vals['license_plate']:
old_license_plate = vehicle.license_plate or _('None')
changes.append(_("License Plate: from '%s' to '%s'") %(old_license_plate, vals['license_plate']))
if len(changes) > 0:
self.message_post(cr, uid, [vehicle.id], body=", ".join(changes), context=context)
vehicle_id = super(fleet_vehicle,self).write(cr, uid, ids, vals, context)
return True
class fleet_vehicle_odometer(osv.Model):
_name='fleet.vehicle.odometer'
_description='Odometer log for a vehicle'
_order='date desc'
def _vehicle_log_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
name = record.vehicle_id.name
if record.date:
name = name+ ' / '+ str(record.date)
res[record.id] = name
return res
def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
if not vehicle_id:
return {}
odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
return {
'value': {
'unit': odometer_unit,
}
}
_columns = {
'name': fields.function(_vehicle_log_name_get_fnc, type="char", string='Name', store=True),
'date': fields.date('Date'),
'value': fields.float('Odometer Value', group_operator="max"),
'vehicle_id': fields.many2one('fleet.vehicle', 'Vehicle', required=True),
'unit': fields.related('vehicle_id', 'odometer_unit', type="char", string="Unit", readonly=True),
}
_defaults = {
'date': fields.date.context_today,
}
class fleet_vehicle_log_fuel(osv.Model):
def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
if not vehicle_id:
return {}
odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
return {
'value': {
'odometer_unit': odometer_unit,
}
}
def on_change_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
#need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not
#make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per
#liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead
#of 3.0/2=1.5)
liter = float(liter)
price_per_liter = float(price_per_liter)
amount = float(amount)
if liter > 0 and price_per_liter > 0:
return {'value' : {'amount' : liter * price_per_liter,}}
elif liter > 0 and amount > 0:
return {'value' : {'price_per_liter' : amount / liter,}}
elif price_per_liter > 0 and amount > 0:
return {'value' : {'liter' : amount / price_per_liter,}}
else :
return {}
def on_change_price_per_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
#need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not
#make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per
#liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead
#of 3.0/2=1.5)
liter = float(liter)
price_per_liter = float(price_per_liter)
amount = float(amount)
if price_per_liter > 0 and liter > 0:
return {'value' : {'amount' : liter * price_per_liter,}}
elif price_per_liter > 0 and amount > 0:
return {'value' : {'liter' : amount / price_per_liter,}}
elif liter > 0 and amount > 0:
return {'value' : {'price_per_liter' : amount / liter,}}
else :
return {}
def on_change_amount(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
#need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not
#make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per
#liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead
#of 3.0/2=1.5)
liter = float(liter)
price_per_liter = float(price_per_liter)
amount = float(amount)
if amount > 0 and liter > 0:
return {'value': {'price_per_liter': amount / liter,}}
elif amount > 0 and price_per_liter > 0:
return {'value': {'liter': amount / price_per_liter,}}
elif liter > 0 and price_per_liter > 0:
return {'value': {'amount': liter * price_per_liter,}}
return {}
def _get_default_service_type(self, cr, uid, context):
try:
model, model_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'type_service_refueling')
except ValueError:
model_id = False
return model_id
_name = 'fleet.vehicle.log.fuel'
_description = 'Fuel log for vehicles'
_inherits = {'fleet.vehicle.cost': 'cost_id'}
_columns = {
'liter': fields.float('Liter'),
'price_per_liter': fields.float('Price Per Liter'),
'purchaser_id': fields.many2one('res.partner', 'Purchaser', domain="['|',('customer','=',True),('employee','=',True)]"),
'inv_ref': fields.char('Invoice Reference', size=64),
'vendor_id': fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
'notes': fields.text('Notes'),
'cost_amount': fields.related('cost_id', 'amount', string='Amount', type='float', store=True), #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database
}
_defaults = {
'purchaser_id': lambda self, cr, uid, ctx: uid,
'date': fields.date.context_today,
'cost_subtype': _get_default_service_type,
'cost_type': 'fuel',
}
class fleet_vehicle_log_services(osv.Model):
def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
if not vehicle_id:
return {}
odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
return {
'value': {
'odometer_unit': odometer_unit,
}
}
def _get_default_service_type(self, cr, uid, context):
try:
model, model_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'type_service_service_8')
except ValueError:
model_id = False
return model_id
_inherits = {'fleet.vehicle.cost': 'cost_id'}
_name = 'fleet.vehicle.log.services'
_description = 'Services for vehicles'
_columns = {
'purchaser_id': fields.many2one('res.partner', 'Purchaser', domain="['|',('customer','=',True),('employee','=',True)]"),
'inv_ref': fields.char('Invoice Reference', size=64),
'vendor_id': fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
'cost_amount': fields.related('cost_id', 'amount', string='Amount', type='float', store=True), #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database
'notes': fields.text('Notes'),
}
_defaults = {
'purchaser_id': lambda self, cr, uid, ctx: uid,
'date': fields.date.context_today,
'cost_subtype': _get_default_service_type,
'cost_type': 'services'
}
class fleet_service_type(osv.Model):
_name = 'fleet.service.type'
_description = 'Type of services available on a vehicle'
_columns = {
'name': fields.char('Name', required=True, translate=True),
'category': fields.selection([('contract', 'Contract'), ('service', 'Service'), ('both', 'Both')], 'Category', required=True, help='Choose wheter the service refer to contracts, vehicle services or both'),
}
class fleet_vehicle_log_contract(osv.Model):
def scheduler_manage_auto_costs(self, cr, uid, context=None):
#This method is called by a cron task
#It creates costs for contracts having the "recurring cost" field setted, depending on their frequency
#For example, if a contract has a reccuring cost of 200 with a weekly frequency, this method creates a cost of 200 on the first day of each week, from the date of the last recurring costs in the database to today
#If the contract has not yet any recurring costs in the database, the method generates the recurring costs from the start_date to today
#The created costs are associated to a contract thanks to the many2one field contract_id
#If the contract has no start_date, no cost will be created, even if the contract has recurring costs
vehicle_cost_obj = self.pool.get('fleet.vehicle.cost')
d = datetime.datetime.strptime(fields.date.context_today(self, cr, uid, context=context), tools.DEFAULT_SERVER_DATE_FORMAT).date()
contract_ids = self.pool.get('fleet.vehicle.log.contract').search(cr, uid, [('state','!=','closed')], offset=0, limit=None, order=None,context=None, count=False)
deltas = {'yearly': relativedelta(years=+1), 'monthly': relativedelta(months=+1), 'weekly': relativedelta(weeks=+1), 'daily': relativedelta(days=+1)}
for contract in self.pool.get('fleet.vehicle.log.contract').browse(cr, uid, contract_ids, context=context):
if not contract.start_date or contract.cost_frequency == 'no':
continue
found = False
last_cost_date = contract.start_date
if contract.generated_cost_ids:
last_autogenerated_cost_id = vehicle_cost_obj.search(cr, uid, ['&', ('contract_id','=',contract.id), ('auto_generated','=',True)], offset=0, limit=1, order='date desc',context=context, count=False)
if last_autogenerated_cost_id:
found = True
last_cost_date = vehicle_cost_obj.browse(cr, uid, last_autogenerated_cost_id[0], context=context).date
startdate = datetime.datetime.strptime(last_cost_date, tools.DEFAULT_SERVER_DATE_FORMAT).date()
if found:
startdate += deltas.get(contract.cost_frequency)
while (startdate < d) & (startdate < datetime.datetime.strptime(contract.expiration_date, tools.DEFAULT_SERVER_DATE_FORMAT).date()):
data = {
'amount': contract.cost_generated,
'date': startdate.strftime(tools.DEFAULT_SERVER_DATE_FORMAT),
'vehicle_id': contract.vehicle_id.id,
'cost_subtype': contract.cost_subtype.id,
'contract_id': contract.id,
'auto_generated': True
}
cost_id = self.pool.get('fleet.vehicle.cost').create(cr, uid, data, context=context)
startdate += deltas.get(contract.cost_frequency)
return True
def scheduler_manage_contract_expiration(self, cr, uid, context=None):
#This method is called by a cron task
#It manages the state of a contract, possibly by posting a message on the vehicle concerned and updating its status
datetime_today = datetime.datetime.strptime(fields.date.context_today(self, cr, uid, context=context), tools.DEFAULT_SERVER_DATE_FORMAT)
limit_date = (datetime_today + relativedelta(days=+15)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
ids = self.search(cr, uid, ['&', ('state', '=', 'open'), ('expiration_date', '<', limit_date)], offset=0, limit=None, order=None, context=context, count=False)
res = {}
for contract in self.browse(cr, uid, ids, context=context):
if contract.vehicle_id.id in res:
res[contract.vehicle_id.id] += 1
else:
res[contract.vehicle_id.id] = 1
for vehicle, value in res.items():
self.pool.get('fleet.vehicle').message_post(cr, uid, vehicle, body=_('%s contract(s) need(s) to be renewed and/or closed!') % (str(value)), context=context)
return self.write(cr, uid, ids, {'state': 'toclose'}, context=context)
def run_scheduler(self, cr, uid, context=None):
self.scheduler_manage_auto_costs(cr, uid, context=context)
self.scheduler_manage_contract_expiration(cr, uid, context=context)
return True
def _vehicle_contract_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
name = record.vehicle_id.name
if record.cost_subtype.name:
name += ' / '+ record.cost_subtype.name
if record.date:
name += ' / '+ record.date
res[record.id] = name
return res
def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
if not vehicle_id:
return {}
odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
return {
'value': {
'odometer_unit': odometer_unit,
}
}
def compute_next_year_date(self, strdate):
oneyear = datetime.timedelta(days=365)
curdate = str_to_datetime(strdate)
return datetime.datetime.strftime(curdate + oneyear, tools.DEFAULT_SERVER_DATE_FORMAT)
def on_change_start_date(self, cr, uid, ids, strdate, enddate, context=None):
if (strdate):
return {'value': {'expiration_date': self.compute_next_year_date(strdate),}}
return {}
def get_days_left(self, cr, uid, ids, prop, unknow_none, context=None):
"""return a dict with as value for each contract an integer
if contract is in an open state and is overdue, return 0
if contract is in a closed state, return -1
otherwise return the number of days before the contract expires
"""
res = {}
for record in self.browse(cr, uid, ids, context=context):
if (record.expiration_date and (record.state == 'open' or record.state == 'toclose')):
today = str_to_datetime(time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT))
renew_date = str_to_datetime(record.expiration_date)
diff_time = (renew_date-today).days
res[record.id] = diff_time > 0 and diff_time or 0
else:
res[record.id] = -1
return res
def act_renew_contract(self, cr, uid, ids, context=None):
assert len(ids) == 1, "This operation should only be done for 1 single contract at a time, as it it suppose to open a window as result"
for element in self.browse(cr, uid, ids, context=context):
#compute end date
startdate = str_to_datetime(element.start_date)
enddate = str_to_datetime(element.expiration_date)
diffdate = (enddate - startdate)
default = {
'date': fields.date.context_today(self, cr, uid, context=context),
'start_date': datetime.datetime.strftime(str_to_datetime(element.expiration_date) + datetime.timedelta(days=1), tools.DEFAULT_SERVER_DATE_FORMAT),
'expiration_date': datetime.datetime.strftime(enddate + diffdate, tools.DEFAULT_SERVER_DATE_FORMAT),
}
newid = super(fleet_vehicle_log_contract, self).copy(cr, uid, [element.id], default, context=context)
mod, modid = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'fleet_vehicle_log_contract_form')
return {
'name':_("Renew Contract"),
'view_mode': 'form',
'view_id': modid,
'view_type': 'tree,form',
'res_model': 'fleet.vehicle.log.contract',
'type': 'ir.actions.act_window',
'nodestroy': True,
'domain': '[]',
'res_id': newid,
'context': {'active_id':newid},
}
def _get_default_contract_type(self, cr, uid, context=None):
try:
model, model_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'type_contract_leasing')
except ValueError:
model_id = False
return model_id
def on_change_indic_cost(self, cr, uid, ids, cost_ids, context=None):
totalsum = 0.0
for element in cost_ids:
if element and len(element) == 3 and element[2] is not False:
totalsum += element[2].get('amount', 0.0)
return {
'value': {
'sum_cost': totalsum,
}
}
def _get_sum_cost(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for contract in self.browse(cr, uid, ids, context=context):
totalsum = 0
for cost in contract.cost_ids:
totalsum += cost.amount
res[contract.id] = totalsum
return res
_inherits = {'fleet.vehicle.cost': 'cost_id'}
_name = 'fleet.vehicle.log.contract'
_description = 'Contract information on a vehicle'
_order='state desc,expiration_date'
_columns = {
'name': fields.function(_vehicle_contract_name_get_fnc, type="text", string='Name', store=True),
'start_date': fields.date('Contract Start Date', help='Date when the coverage of the contract begins'),
'expiration_date': fields.date('Contract Expiration Date', help='Date when the coverage of the contract expirates (by default, one year after begin date)'),
'days_left': fields.function(get_days_left, type='integer', string='Warning Date'),
'insurer_id' :fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
'purchaser_id': fields.many2one('res.partner', 'Contractor', domain="['|', ('customer','=',True), ('employee','=',True)]",help='Person to which the contract is signed for'),
'ins_ref': fields.char('Contract Reference', size=64),
'state': fields.selection([('open', 'In Progress'), ('toclose','To Close'), ('closed', 'Terminated')], 'Status', readonly=True, help='Choose wheter the contract is still valid or not'),
'notes': fields.text('Terms and Conditions', help='Write here all supplementary informations relative to this contract'),
'cost_generated': fields.float('Recurring Cost Amount', help="Costs paid at regular intervals, depending on the cost frequency. If the cost frequency is set to unique, the cost will be logged at the start date"),
'cost_frequency': fields.selection([('no','No'), ('daily', 'Daily'), ('weekly','Weekly'), ('monthly','Monthly'), ('yearly','Yearly')], 'Recurring Cost Frequency', help='Frequency of the recuring cost', required=True),
'generated_cost_ids': fields.one2many('fleet.vehicle.cost', 'contract_id', 'Generated Costs', ondelete='cascade'),
'sum_cost': fields.function(_get_sum_cost, type='float', string='Indicative Costs Total'),
'cost_amount': fields.related('cost_id', 'amount', string='Amount', type='float', store=True), #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database
}
_defaults = {
'purchaser_id': lambda self, cr, uid, ctx: uid,
'date': fields.date.context_today,
'start_date': fields.date.context_today,
'state':'open',
'expiration_date': lambda self, cr, uid, ctx: self.compute_next_year_date(fields.date.context_today(self, cr, uid, context=ctx)),
'cost_frequency': 'no',
'cost_subtype': _get_default_contract_type,
'cost_type': 'contract',
}
def copy(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
today = fields.date.context_today(self, cr, uid, context=context)
default['date'] = today
default['start_date'] = today
default['expiration_date'] = self.compute_next_year_date(today)
default['ins_ref'] = ''
default['state'] = 'open'
default['notes'] = ''
return super(fleet_vehicle_log_contract, self).copy(cr, uid, id, default, context=context)
def contract_close(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'state': 'closed'}, context=context)
def contract_open(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'state': 'open'}, context=context)
class fleet_contract_state(osv.Model):
_name = 'fleet.contract.state'
_description = 'Contains the different possible status of a leasing contract'
_columns = {
'name':fields.char('Contract Status', size=64, required=True),
}

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="ir.actions.act_window" id="action_fleet_vehicle_log_fuel_graph">
<field name="name">Fuel Costs by Month</field>
<field name="res_model">fleet.vehicle.cost</field>
<field name="view_id" ref="fleet_vehicle_costs_graph"></field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="domain">['&amp;',('parent_id','=',False),('cost_type','=','fuel')]</field>
</record>
<record model="ir.actions.act_window" id="action_fleet_vehicle_log_services_graph">
<field name="name">Services Costs by Month</field>
<field name="res_model">fleet.vehicle.cost</field>
<field name="view_id" ref="fleet_vehicle_costs_graph" />
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="domain">['&amp;',('parent_id','=',False),('cost_type','=','services')]</field>
</record>
<record model="ir.actions.act_window" id="action_fleet_vehicle_log_contract_graph">
<field name="name">Contracts Costs by Month</field>
<field name="res_model">fleet.vehicle.cost</field>
<field name="view_id" ref="fleet_vehicle_costs_graph"></field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="domain">['&amp;',('parent_id','=',False),('cost_type','=','contract')]</field>
</record>
<record model="ir.actions.act_window" id="action_fleet_vehicle_costs_graph">
<field name="name">Costs by Month</field>
<field name="res_model">fleet.vehicle.cost</field>
<field name="view_id" ref="fleet_vehicle_costs_graph"></field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="domain">[('parent_id','=',False)]</field>
</record>
<record model="ir.actions.act_window" id="action_fleet_vehicle_kanban">
<field name="name">Vehicles with alerts</field>
<field name="res_model">fleet.vehicle</field>
<field name="view_id" ref="fleet_vehicle_kanban"></field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="domain">['|',('contract_renewal_due_soon','>',0),('contract_renewal_overdue','>',0)]</field>
<field name="help" type="html">
<p>
Here are displayed vehicles for which one or more contracts need to be renewed. If you see this message, then there is no contracts to renew.
</p>
</field>
</record>
<record model="ir.actions.act_window" id="action_fleet_reporting_costs">
<field name="name">Costs Analysis</field>
<field name="res_model">fleet.vehicle.cost</field>
<field name="view_id" ref="fleet_vehicle_costs_tree"></field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="context">{"search_default_parent_false" : True,"search_default_groupby_year" : True,"search_default_groupby_cost_type" : True,"search_default_groupby_cost_subtype" : True, "search_default_groupby_vehicle_id" : True,}</field>
<field name="help" type="html">
<p>
OpenERP helps you managing the costs for your different vehicles
Costs are generally created from services and contract and appears here.
</p>
<p>
Thanks to the different filters, OpenERP can only print the effective
costs, sort them by type and by vehicle.
</p>
</field>
</record>
<record model="ir.actions.act_window" id="action_fleet_reporting_costs_non_effective">
<field name="name">Indicative Costs Analysis</field>
<field name="res_model">fleet.vehicle.cost</field>
<field name="view_id" ref="fleet_vehicle_costs_tree"></field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="context">{"search_default_parent_true" : True,"search_default_groupby_cost_subtype" : True,"search_default_groupby_cost_type" : True,"search_default_groupby_parent_id" : True,}</field>
<field name="help" type="html">
<p>
OpenERP helps you managing the costs for your different vehicles
Costs are generally created from services and contract and appears here.
</p>
<p>
Thanks to the different filters, OpenERP can only print the effective
costs, sort them by type and by vehicle.
</p>
</field>
</record>
<record id="board_fleet_form" model="ir.ui.view">
<field name="name">board.fleet.form</field>
<field name="model">board.board</field>
<field name="arch" type="xml">
<form string="Fleet Dashboard" version="7.0">
<board style="2-1">
<column>
<action string="Vehicles With Alerts" name="%(fleet.action_fleet_vehicle_kanban)d" view_mode="kanban"/>
<action string="Costs by Month" name="%(fleet.action_fleet_vehicle_costs_graph)d" view_mode="graph,tree"/>
</column>
<column>
<action string="Fuel Costs" name="%(fleet.action_fleet_vehicle_log_fuel_graph)d" view_mode="graph,tree"/>
<action string="Services Costs" name="%(fleet.action_fleet_vehicle_log_services_graph)d" view_mode="graph,tree"/>
<action string="Contracts Costs" name="%(fleet.action_fleet_vehicle_log_contract_graph)d" view_mode="graph,tree"/>
</column>
</board>
</form>
</field>
</record>
<record id="open_board_fleet" model="ir.actions.act_window">
<field name="name">Fleet</field>
<field name="res_model">board.board</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="usage">menu</field>
<field name="view_id" ref="board_fleet_form"/>
<field name="help" type="html">
<div class="oe_empty_custom_dashboard">
<p>
<b>Fleet dashboard is empty.</b>
</p><p>
To add your first report into this dashboard, go to any
menu, switch to list or graph view, and click <i>'Add to
Dashboard'</i> in the extended search options.
</p><p>
You can filter and group data before inserting into the
dashboard using the search options.
</p>
</div>
</field>
</record>
<menuitem id="menu_fleet_dashboard"
parent="base.menu_reporting_dashboard"
action="open_board_fleet"
sequence="50"/>
<menuitem name="Fleet" parent="base.menu_reporting" id="menu_fleet_reporting" sequence="50" />
<menuitem id="menu_fleet_reporting_costs"
parent="menu_fleet_reporting"
action="action_fleet_reporting_costs"
sequence="1"/>
<menuitem id="menu_fleet_reporting_indicative_costs"
parent="menu_fleet_reporting"
action="action_fleet_reporting_costs_non_effective"
sequence="2"/>
</data>
</openerp>

13736
addons/fleet/fleet_cars.xml Normal file

File diff suppressed because it is too large Load Diff

440
addons/fleet/fleet_data.xml Normal file
View File

@ -0,0 +1,440 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<!--
<record forcecreate="True" id="ir_cron_service_services_reminders" model="ir.cron">
<field name="name">Creation of Vehicle services and Services renewals reminders</field>
<field eval="True" name="active" />
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
<field eval="'fleet.vehicle'" name="model" />
<field eval="'run_scheduler'" name="function" />
<field eval="'()'" name="args" />
</record>
-->
<record forcecreate="True" id="ir_cron_contract_costs_generator" model="ir.cron">
<field name="name">Generation of contracts costs based on the costs frequency</field>
<field eval="True" name="active" />
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
<field eval="'fleet.vehicle.log.contract'" name="model" />
<field eval="'run_scheduler'" name="function" />
<field eval="'()'" name="args" />
</record>
<record id="type_service_service_1" model="fleet.service.type">
<field name="name">Calculation Benefit In Kind</field>
<field name="category">service</field>
</record>
<record id="type_service_service_2" model="fleet.service.type">
<field name="name">Depreciation and Interests</field>
<field name="category">service</field>
</record>
<record id="type_service_service_3" model="fleet.service.type">
<field name="name">Tax roll</field>
<field name="category">service</field>
</record>
<record id="type_service_service_5" model="fleet.service.type">
<field name="name">Summer tires</field>
<field name="category">service</field>
</record>
<record id="type_service_service_6" model="fleet.service.type">
<field name="name">Snow tires</field>
<field name="category">service</field>
</record>
<record id="type_service_service_7" model="fleet.service.type">
<field name="name">Summer tires</field>
<field name="category">service</field>
</record>
<record id="type_service_service_8" model="fleet.service.type">
<field name="name">Repair and maintenance</field>
<field name="category">service</field>
</record>
<record id="type_service_service_9" model="fleet.service.type">
<field name="name">Assistance</field>
<field name="category">service</field>
</record>
<record id="type_service_service_10" model="fleet.service.type">
<field name="name">Replacement Vehicle</field>
<field name="category">service</field>
</record>
<record id="type_service_service_11" model="fleet.service.type">
<field name="name">Management Fee</field>
<field name="category">service</field>
</record>
<record id="type_service_service_12" model="fleet.service.type">
<field name="name">Rent (Excluding VAT)</field>
<field name="category">service</field>
</record>
<record id="type_service_service_13" model="fleet.service.type">
<field name="name">Entry into service tax</field>
<field name="category">service</field>
</record>
<record id="type_service_service_14" model="fleet.service.type">
<field name="name">Total expenses (Excluding VAT)</field>
<field name="category">service</field>
</record>
<record id="type_service_service_15" model="fleet.service.type">
<field name="name">Residual value (Excluding VAT)</field>
<field name="category">service</field>
</record>
<record id="type_service_service_16" model="fleet.service.type">
<field name="name">Options</field>
<field name="category">service</field>
</record>
<record id="type_service_service_17" model="fleet.service.type">
<field name="name">Emissions</field>
<field name="category">service</field>
</record>
<record id="type_service_service_18" model="fleet.service.type">
<field name="name">Touring Assistance</field>
<field name="category">service</field>
</record>
<record id="type_service_service_19" model="fleet.service.type">
<field name="name">Residual value in %</field>
<field name="category">service</field>
</record>
<record id="type_service_1" model="fleet.service.type">
<field name="name">A/C Compressor Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_2" model="fleet.service.type">
<field name="name">A/C Condenser Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_3" model="fleet.service.type">
<field name="name">A/C Diagnosis</field>
<field name="category">service</field>
</record>
<record id="type_service_4" model="fleet.service.type">
<field name="name">A/C Evaporator Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_5" model="fleet.service.type">
<field name="name">A/C Recharge</field>
<field name="category">service</field>
</record>
<record id="type_service_6" model="fleet.service.type">
<field name="name">Air Filter Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_7" model="fleet.service.type">
<field name="name">Alternator Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_8" model="fleet.service.type">
<field name="name">Ball Joint Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_9" model="fleet.service.type">
<field name="name">Battery Inspection</field>
<field name="category">service</field>
</record>
<record id="type_service_10" model="fleet.service.type">
<field name="name">Battery Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_11" model="fleet.service.type">
<field name="name">Brake Caliper Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_12" model="fleet.service.type">
<field name="name">Brake Inspection</field>
<field name="category">service</field>
</record>
<record id="type_service_13" model="fleet.service.type">
<field name="name">Brake Pad(s) Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_14" model="fleet.service.type">
<field name="name">Car Wash</field>
<field name="category">service</field>
</record>
<record id="type_service_15" model="fleet.service.type">
<field name="name">Catalytic Converter Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_16" model="fleet.service.type">
<field name="name">Charging System Diagnosis</field>
<field name="category">service</field>
</record>
<record id="type_service_17" model="fleet.service.type">
<field name="name">Door Window Motor/Regulator Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_18" model="fleet.service.type">
<field name="name">Engine Belt Inspection</field>
<field name="category">service</field>
</record>
<record id="type_service_19" model="fleet.service.type">
<field name="name">Engine Coolant Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_20" model="fleet.service.type">
<field name="name">Engine/Drive Belt(s) Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_21" model="fleet.service.type">
<field name="name">Exhaust Manifold Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_22" model="fleet.service.type">
<field name="name">Fuel Injector Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_23" model="fleet.service.type">
<field name="name">Fuel Pump Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_24" model="fleet.service.type">
<field name="name">Head Gasket(s) Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_25" model="fleet.service.type">
<field name="name">Heater Blower Motor Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_26" model="fleet.service.type">
<field name="name">Heater Control Valve Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_27" model="fleet.service.type">
<field name="name">Heater Core Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_28" model="fleet.service.type">
<field name="name">Heater Hose Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_29" model="fleet.service.type">
<field name="name">Ignition Coil Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_30" model="fleet.service.type">
<field name="name">Intake Manifold Gasket Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_31" model="fleet.service.type">
<field name="name">Oil Change</field>
<field name="category">service</field>
</record>
<record id="type_service_32" model="fleet.service.type">
<field name="name">Oil Pump Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_33" model="fleet.service.type">
<field name="name">Other Maintenance</field>
<field name="category">service</field>
</record>
<record id="type_service_34" model="fleet.service.type">
<field name="name">Oxygen Sensor Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_35" model="fleet.service.type">
<field name="name">Power Steering Hose Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_36" model="fleet.service.type">
<field name="name">Power Steering Pump Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_37" model="fleet.service.type">
<field name="name">Radiator Repair</field>
<field name="category">service</field>
</record>
<record id="type_service_38" model="fleet.service.type">
<field name="name">Resurface Rotors</field>
<field name="category">service</field>
</record>
<record id="type_service_39" model="fleet.service.type">
<field name="name">Rotate Tires</field>
<field name="category">service</field>
</record>
<record id="type_service_40" model="fleet.service.type">
<field name="name">Rotor Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_41" model="fleet.service.type">
<field name="name">Spark Plug Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_42" model="fleet.service.type">
<field name="name">Starter Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_43" model="fleet.service.type">
<field name="name">Thermostat Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_44" model="fleet.service.type">
<field name="name">Tie Rod End Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_45" model="fleet.service.type">
<field name="name">Tire Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_46" model="fleet.service.type">
<field name="name">Tire Service</field>
<field name="category">service</field>
</record>
<record id="type_service_47" model="fleet.service.type">
<field name="name">Transmission Filter Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_48" model="fleet.service.type">
<field name="name">Transmission Fluid Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_49" model="fleet.service.type">
<field name="name">Transmission Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_50" model="fleet.service.type">
<field name="name">Water Pump Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_51" model="fleet.service.type">
<field name="name">Wheel Alignment</field>
<field name="category">service</field>
</record>
<record id="type_service_52" model="fleet.service.type">
<field name="name">Wheel Bearing Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_53" model="fleet.service.type">
<field name="name">Windshield Wiper(s) Replacement</field>
<field name="category">service</field>
</record>
<record id="type_contract_omnium" model="fleet.service.type">
<field name="name">Omnium</field>
<field name="category">contract</field>
</record>
<record id="type_contract_leasing" model="fleet.service.type">
<field name="name">Leasing</field>
<field name="category">contract</field>
</record>
<record id="type_contract_repairing" model="fleet.service.type">
<field name="name">Repairing</field>
<field name="category">both</field>
</record>
<record id="type_service_refueling" model="fleet.service.type">
<field name="name">Refueling</field>
<field name="category">service</field>
</record>
<record id="vehicle_tag_junior" model="fleet.vehicle.tag" >
<field name="name">Junior</field>
</record>
<record id="vehicle_tag_senior" model="fleet.vehicle.tag" >
<field name="name">Senior</field>
</record>
<record id="vehicle_tag_leasing" model="fleet.vehicle.tag" >
<field name="name">Employee Car</field>
</record>
<record id="vehicle_tag_purchased" model="fleet.vehicle.tag" >
<field name="name">Purchased</field>
</record>
<record id="vehicle_tag_compact" model="fleet.vehicle.tag" >
<field name="name">Compact</field>
</record>
<record id="vehicle_tag_sedan" model="fleet.vehicle.tag" >
<field name="name">Sedan</field>
</record>
<record id="vehicle_tag_convertible" model="fleet.vehicle.tag" >
<field name="name">Convertible</field>
</record>
<record id="vehicle_tag_break" model="fleet.vehicle.tag" >
<field name="name">Break</field>
</record>
</data>
</openerp>

1166
addons/fleet/fleet_demo.xml Normal file

File diff suppressed because it is too large Load Diff

907
addons/fleet/fleet_view.xml Normal file
View File

@ -0,0 +1,907 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record model='ir.ui.view' id='fleet_vehicle_model_form'>
<field name="name">fleet.vehicle.model.form</field>
<field name="model">fleet.vehicle.model</field>
<field name="arch" type="xml">
<form string="Model" version="7.0">
<sheet>
<field name="image_medium" widget='image' class="oe_left oe_avatar"/>
<group col="2">
<group>
<field name="brand" on_change="on_change_brand(brand)"/>
</group>
<group>
<field name="modelname" />
</group>
</group>
<notebook>
<page string="Vendors">
<field name="vendors" widget="many2many_kanban"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_model_tree'>
<field name="name">fleet.vehicle.model.tree</field>
<field name="model">fleet.vehicle.model</field>
<field name="arch" type="xml">
<tree string="Models" version="7.0">
<field name="brand" />
<field name="modelname" />
</tree>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_model_act'>
<field name="name">Vehicle Model</field>
<field name="res_model">fleet.vehicle.model</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new model.
</p><p>
You can define several models (e.g. A3, A4) for each brand (Audi).
</p>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_model_brand_tree'>
<field name="name">fleet.vehicle.model.brand.tree</field>
<field name="model">fleet.vehicle.model.brand</field>
<field name="arch" type="xml">
<tree string="Model Brand" version="7.0">
<field name="name" />
</tree>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_model_brand_form'>
<field name="name">fleet.vehicle.model.brand.form</field>
<field name="model">fleet.vehicle.model.brand</field>
<field name="arch" type="xml">
<form string="Model Brand" version="7.0">
<sheet>
<group>
<div>
<field name="image_medium" widget="image" class="oe_left oe_avatar"/>
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name" class="oe_inline" />
</h1>
</div>
</group>
</sheet>
</form>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_model_brand_kanban'>
<field name="name">fleet.vehicle.model.brandkanban</field>
<field name="model">fleet.vehicle.model.brand</field>
<field name="arch" type="xml">
<kanban>
<field name="name" />
<field name="image" />
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_vignette oe_semantic_html_override">
<a type="open" href="#" class="oe_kanban_action oe_kanban_action_a">
<img t-att-src="kanban_image('fleet.vehicle.model.brand', 'image_small', record.id.value)" class="oe_employee_picture"/>
</a>
<div style="text-align:center;">
<h4 class="oe_partner_heading">
<a type="open">
<field name="name"/>
</a>
</h4>
</div>
</div>
<script>
$('.oe_picture').load(function() { if($(this).width() > $(this).height()) { $(this).addClass('oe_employee_picture_wide') } });
</script>
</t>
</templates>
</kanban>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_model_brand_act'>
<field name="name">Model brand of Vehicle</field>
<field name="res_model">fleet.vehicle.model.brand</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new brand.
</p>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_state_tree'>
<field name="name">fleet.vehicle.state.tree</field>
<field name="model">fleet.vehicle.state</field>
<field name="arch" type="xml">
<tree string="State" version="7.0" editable="bottom">
<field name="sequence" widget="handler" invisible="1"/>
<field name="name" />
</tree>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_state_act'>
<field name="name">States of Vehicle</field>
<field name="res_model">fleet.vehicle.state</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a vehicule status.
</p><p>
You can customize available status to track the evolution of
each vehicule. Example: Active, Being Repaired, Sold.
</p>
</field>
</record>
<menuitem name="Fleet" id="menu_root" sequence="70" />
<menuitem name="Configuration" parent="menu_root" id="fleet_configuration" sequence="3" />
<menuitem action="fleet_vehicle_model_act" parent="fleet_configuration" id="fleet_vehicle_model_menu" groups="base.group_no_one"/>
<menuitem action="fleet_vehicle_model_brand_act" parent="fleet_configuration" id="fleet_vehicle_model_brand_menu" groups="base.group_no_one"/>
<menuitem action="fleet_vehicle_state_act" parent="fleet_configuration" id="fleet_vehicle_state_menu" />
<record model='ir.ui.view' id='fleet_vehicle_form'>
<field name="name">fleet.vehicle.form</field>
<field name="model">fleet.vehicle</field>
<field name="arch" type="xml">
<form string="Vehicle" version="7.0">
<header>
<field name="state" widget="statusbar" clickable="True" />
</header>
<sheet>
<field name="image_medium" widget='image' class="oe_left oe_avatar"/>
<div class="oe_title">
<label for="model_id" class="oe_edit_only"/>
<h1>
<field name="model_id" class="oe_inline" on_change="on_change_model(model_id)"/>
</h1>
<label for="license_plate" class="oe_edit_only"/>
<h2>
<field name="license_plate" class="oe_inline"/>
</h2>
<label for="tag_ids" class="oe_edit_only"/>
<field name="tag_ids" widget="many2many_tags" />
</div>
<div class="oe_right oe_button_box">
<button name="return_action_to_open" type="object" context="{'xml_id':'fleet_vehicle_log_contract_act'}" string="Contracts" help="show the contract for this vehicle" />
<button name="act_show_log_cost" type="object" string="Costs" help="show all the costs for this vehicle" />
<button name="return_action_to_open" type="object" context="{'xml_id':'fleet_vehicle_log_services_act'}" string="Services" help="show the services logs for this vehicle" />
<button name="return_action_to_open" type="object" context="{'xml_id':'fleet_vehicle_log_fuel_act'}" string="Fuel Logs" help="show the fuel logs for this vehicle" />
<button name="return_action_to_open" type="object" context="{'xml_id':'fleet_vehicle_odometer_act'}" string="Odometer Logs" help="show the odometer logs for this vehicle" />
</div>
<group col="2" string="General Properties">
<group >
<field name="driver" />
<field name="location" />
<field name="vin_sn" />
<field name="company_id" groups="base.group_multi_company"/>
</group>
<group >
<label for="odometer" />
<div>
<field name="odometer" class="oe_inline"/>
<field name="odometer_unit" class="oe_inline"/>
</div>
<field name="acquisition_date" />
<field name="car_value" />
</group>
</group>
<group col="2">
<group string="Additional Properties">
<field name="seats" />
<field name="doors" />
<field name="color" />
</group>
<group string="Engine Options">
<field name="transmission" />
<field name="fuel_type" />
<field name="co2" />
<field name="horsepower" />
<field name="horsepower_tax" />
<field name="power" />
</group>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_ids" widget="mail_thread" options='{"thread_level": 1}'/>
<field name="message_follower_ids" widget="mail_followers"/>
</div>
</form>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_tree'>
<field name="name">fleet.vehicle.tree</field>
<field name="model">fleet.vehicle</field>
<field name="sequence">1</field>
<field name="arch" type="xml">
<tree string="Vehicle" version="7.0" colors="orange:contract_renewal_due_soon and not contract_renewal_overdue;red:contract_renewal_overdue">
<field name="license_plate" />
<field name="model_id" />
<field name="driver" />
<field name="vin_sn" />
<field name="acquisition_date" />
<field name="state"/>
<field name="odometer" />
<field name="odometer_unit" />
<field name="contract_renewal_due_soon" invisible="1"/>
<field name="contract_renewal_overdue" invisible="1" />
<field name="contract_renewal_total" invisible="1"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="fleet_vehicle_search">
<field name="name">fleet.vehicle.search</field>
<field name="model">fleet.vehicle</field>
<field name="arch" type="xml">
<search string="All vehicles">
<field name="name" filter_domain="['|', ('name','ilike',self), ('license_plate','ilike',self)]" string="Vehicle"/>
<field name="driver"/>
<field name="tag_ids"/>
<field name="location"/>
<field name="state" />
<field name="state" />
<filter name="alert_true" domain="['|',('contract_renewal_due_soon','>',0),('contract_renewal_overdue','>',0)]" string="Has Alert(s)"/>
</search>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_kanban'>
<field name="name">fleet.vehicle.kanban</field>
<field name="model">fleet.vehicle</field>
<field name="arch" type="xml">
<kanban>
<field name="license_plate" />
<field name="model_id" />
<field name="driver" />
<field name="location" />
<field name="state" />
<field name="image" />
<field name="tag_ids" />
<field name="contract_renewal_due_soon" />
<field name="contract_renewal_overdue" />
<field name="contract_renewal_name" />
<field name="contract_renewal_total" />
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_vignette oe_semantic_html_override">
<a type="open" href="#" class="oe_kanban_action oe_kanban_action_a">
<img t-att-src="kanban_image('fleet.vehicle', 'image_small', record.id.value)"/>
</a>
<div class="oe_kanban_details">
<h4 class="oe_partner_heading">
<a type="open">
<field name="license_plate"/><br/>
<field name="model_id" />
</a>
</h4>
<t t-if="record.contract_renewal_due_soon.raw_value and !record.contract_renewal_overdue.raw_value">
<a data-type="object" data-name="return_action_to_open" href="#" class="oe_kanban_action oe_kanban_action_a" data-context='{"xml_id":"fleet_vehicle_log_contract_act"}'>
<span class="oe_tag oe_kanban_color_3"><field name="contract_renewal_name" />
<t t-if="record.contract_renewal_total.raw_value > 0"> and <field name="contract_renewal_total" /> other(s) </t>
</span>
</a>
</t>
<t t-if="record.contract_renewal_overdue.raw_value">
<a data-type="object" data-name="return_action_to_open" href="#" class="oe_kanban_action oe_kanban_action_a" data-context='{"xml_id":"fleet_vehicle_log_contract_act"}'>
<span class="oe_tag oe_kanban_color_2"><field name="contract_renewal_name" />
<t t-if="record.contract_renewal_total.raw_value > 0"> and <field name="contract_renewal_total" /> other(s) </t>
</span>
</a>
</t>
<ul>
<li>
<t t-if="record.driver.raw_value"><field name="driver"/></t>
</li>
<li>
<t t-if="record.location.raw_value"><field name="location"/></t>
</li>
</ul>
<div class="oe_kanban_partner_categories">
<span class="oe_kanban_list_many2many">
<div modifiers="{}" name="tag_ids" class="oe_form_field oe_tags" model="fleet.vehicle.tag" t-att-data="record.tag_ids.raw_value" />
</span>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_act'>
<field name="name">Vehicles</field>
<field name="res_model">fleet.vehicle</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new vehicle.
</p><p>
You will be able to manage your fleet by keeping track of the
contracts, services, fixed and recurring costs, odometers and
fuel logs associated to each vehicle.
</p><p>
OpenERP will warn you when services or contract have to be
renewed.
</p>
</field>
</record>
<menuitem name="Vehicles" parent="menu_root" id="fleet_vehicles" sequence="2" />
<menuitem action="fleet_vehicle_act" parent="fleet_vehicles" id="fleet_vehicle_menu" />
<record model='ir.ui.view' id='fleet_vehicle_log_contract_form'>
<field name="name">fleet.vehicle.log_contract.form</field>
<field name="model">fleet.vehicle.log.contract</field>
<field name="arch" type="xml">
<form string="Contract logs" version="7.0">
<header>
<button modifiers="{'invisible': [['state', '=', 'closed']]}" name="contract_close" states="open" type="object" class="oe_highlight" string="Terminate Contract"/>
<button modifiers="{'invisible': [['state', '=', 'closed']]}" name="contract_close" states="toclose" type="object" class="oe_highlight" string="Terminate Contract"/>
<button modifiers="{'invisible': [['state', 'not in', ['closed']]]}" name="contract_open" states="closed" type="object" class="oe_highlight" string="Set Contract In Progress"/>
<button class="oe_highlight" name="act_renew_contract" type="object" string="Renew Contract" help="Create a new contract automatically with all the same informations except for the date that will start at the end of current contract" />
<field name="state" widget="statusbar" />
</header>
<sheet>
<group col="2">
<group string="Contract details">
<field name="vehicle_id" on_change="on_change_vehicle(vehicle_id)"/>
<field name="cost_subtype" required="1" domain="['|',('category','=','contract'),('category','=','both')]"/>
<field name="amount" string="Activation Cost"/>
<label for="cost_generated"/>
<div>
<field name="cost_generated" class="oe_inline" attrs="{'invisible': [('cost_frequency','=','no')]}" />
<field name="cost_frequency" class="oe_inline" />
</div>
</group>
<group string="Odometer details">
<label for="odometer"/>
<div>
<field name="odometer" class="oe_inline"/>
<field name="odometer_unit" class="oe_inline"/>
</div>
</group>
</group>
<group col="2">
<group>
<field name="date" string="Invoice Date"/>
<field name="start_date"/>
<field name="expiration_date" />
</group>
<group>
<field name="insurer_id" />
<field name="purchaser_id" />
<field name="ins_ref" />
</group>
</group>
<notebook>
<page string="Included Services">
<group>
<field name="cost_ids" context="{'vehicle_id': vehicle_id}" nolabel="1" on_change="on_change_indic_cost(cost_ids)">
<tree version="7.0" editable="bottom">
<field name="cost_subtype" string="Service" domain="[('category','=','service')]"/>
<field name="amount" sum="Price" string="Indicative Cost" />
</tree>
</field>
</group>
<div class="oe_right"><group><field name="sum_cost" string="Indicative Costs Total"/></group></div>
</page>
<page string="Generated Costs">
<group>
<field name="generated_cost_ids" context="{'vehicle_id': vehicle_id}" nolabel="1" sum="amount">
<tree version="7.0" editable="bottom" >
<field name="date" />
<field name="amount" sum="amount"/>
</tree>
</field>
</group>
</page>
</notebook>
<group string="Terms and Conditions">
<field name="notes" nolabel="1" placeholder="Write here all other information relative to this contract" />
</group>
</sheet>
</form>
</field>
</record>
<act_window
id="act_renew_contract"
name="Renew Contract"
res_model="fleet.vehicle.log.contract"
src_model="fleet.vehicle.log.contract"
view_mode="form"
view_type="form"
/>
<record model='ir.ui.view' id='fleet_vehicle_log_contract_tree'>
<field name="name">fleet.vehicle.log.contract.tree</field>
<field name="model">fleet.vehicle.log.contract</field>
<field name="arch" type="xml">
<tree string="Contract logs" version="7.0" colors="orange:days_left>0 and days_left&lt;15;red:days_left==0;grey:state=='closed'">
<field name="start_date" />
<field name="expiration_date" />
<field name="days_left" invisible="1"/>
<field name="vehicle_id" />
<field name="cost_subtype"/>
<field name="insurer_id" />
<field name="amount" string="Activation Cost"/>
<field name="cost_generated"/>
<field name="cost_frequency"/>
<field name="state" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="fleet_vehicle_log_contract_graph">
<field name="name">fleet.vehicle.log.contract.graph</field>
<field name="model">fleet.vehicle.log.contract</field>
<!--<field name="type">graph</field>-->
<field name="arch" type="xml">
<graph string="Contract Costs Per Month">
<field name="date" />
<field name="cost_amount" operator="+"/>
<field name="vehicle_id" group="True"/>
</graph>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_log_contract_act'>
<field name="name">Vehicles Contracts</field>
<field name="res_model">fleet.vehicle.log.contract</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form,graph</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new contract.
</p><p>
Manage all your contracts (leasing, insurances, etc.) with
their related services, costs. OpenERP will automatically warn
you when some contracts have to be renewed.
</p><p>
Each contract (e.g.: leasing) may include several services
(reparation, insurances, periodic maintenance).
</p>
</field>
</record>
<menuitem action="fleet_vehicle_log_contract_act" parent="fleet_vehicles" id="fleet_vehicle_log_contract_menu" />
<record model='ir.ui.view' id='fleet_vehicle_odometer_form'>
<field name="name">fleet.vehicle.odometer.form</field>
<field name="model">fleet.vehicle.odometer</field>
<field name="arch" type="xml">
<form string="Odometer Logs" version="7.0">
<sheet>
<group>
<field name="vehicle_id" on_change="on_change_vehicle(vehicle_id)"/>
<div>
<field name="value" class="oe_inline"/>
<field name="unit" class="oe_inline"/>
</div>
<field name="date" />
</group>
</sheet>
</form>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_odometer_tree'>
<field name="name">fleet.vehicle.odometer.tree</field>
<field name="model">fleet.vehicle.odometer</field>
<field name="arch" type="xml">
<tree string="Odometer Logs" version="7.0" editable="bottom">
<field name="date" />
<field name="vehicle_id" on_change="on_change_vehicle(vehicle_id)"/>
<field name="value" />
<field name="unit" />
</tree>
</field>
</record>
<!--
<record model='ir.ui.view' id='fleet_vehicle_odometer_search'>
<field name="name">fleet.vehicle.odometer.search</field>
<field name="model">fleet.vehicle.odometer</field>
<field name="arch" type="xml">
<search string="Vehicles odometers" >
<field name="vehicle_id" />
<field name="value"/>
<field name="unit"/>
<field name="date"/>
<filter name="groupby_vehicle" context="{'group_by' : 'vehicle_id'}" string="Vehicle"/>
</search>
</field>
</record>
-->
<record model="ir.ui.view" id="fleet_vehicle_odometer_graph">
<field name="name">fleet.vehicle.odometer.graph</field>
<field name="model">fleet.vehicle.odometer</field>
<!--<field name="type">graph</field>-->
<field name="arch" type="xml">
<graph string="Odometer Values Per Month">
<field name="date" />
<field name="value" operator="+"/>
<field name="vehicle_id" group="True"/>
</graph>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_odometer_act'>
<field name="name">Vehicles Odometer</field>
<field name="res_model">fleet.vehicle.odometer</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form,graph</field>
<field name="context">{"search_default_groupby_vehicle" : True}</field>
<field name="help" type="html">
<p>
Here you can add various odometer entries for all vehicles.
You can also show odometer value for a particular vehicle using
the search field.
</p>
</field>
</record>
<menuitem action="fleet_vehicle_odometer_act" parent="fleet_vehicles" id="fleet_vehicle_odometer_menu" />
<record model='ir.ui.view' id='fleet_vehicle_log_fuel_form'>
<field name="name">fleet.vehicle.log.fuel.form</field>
<field name="model">fleet.vehicle.log.fuel</field>
<field name="arch" type="xml">
<form string="Fuel Logs" version="7.0">
<sheet>
<group col="2">
<group string="Vehicle Details">
<field name="vehicle_id" on_change="on_change_vehicle(vehicle_id)"/>
</group>
<group string="Refueling Details">
<field name="liter" on_change="on_change_liter(liter,price_per_liter,amount)"/>
<field name="price_per_liter" on_change="on_change_price_per_liter(liter,price_per_liter,amount)" />
<field name="amount" on_change="on_change_amount(liter,price_per_liter,amount)"/>
</group>
</group>
<group col="2">
<group string="Odometer Details">
<label for="odometer"/>
<div>
<field name="odometer" class="oe_inline"/>
<field name="odometer_unit" class="oe_inline"/>
</div>
</group>
<group string="Additional Details">
<field name="date" />
<field name="purchaser_id" />
<field name="inv_ref" />
<field name="vendor_id" />
</group>
</group>
<group string="Notes">
<field nolabel="1" name="notes" placeholder="Write here any other information"/>
</group>
</sheet>
</form>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_log_fuel_tree'>
<field name="name">fleet.vehicle.log.fuel.tree</field>
<field name="model">fleet.vehicle.log.fuel</field>
<field name="arch" type="xml">
<tree string="Fuel Logs">
<field name="date" />
<field name="vehicle_id" />
<field name="odometer" invisible="1"/>
<field name="odometer_unit" invisible="1"/>
<field name="purchaser_id" />
<field name="inv_ref" invisible="1"/>
<field name="vendor_id" invisible="1"/>
<field name="liter" />
<field name="price_per_liter" invisible="1"/>
<field name="amount" sum="Price"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="fleet_vehicle_log_fuel_graph">
<field name="name">fleet.vehicle.log.fuel.graph</field>
<field name="model">fleet.vehicle.log.fuel</field>
<!--<field name="type">graph</field>-->
<field name="arch" type="xml">
<graph string="Fuel Costs Per Month">
<field name="date" />
<field name="cost_amount" operator="+"/>
<field name="vehicle_id" group="True"/>
</graph>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_log_fuel_act'>
<field name="name">Vehicles Fuel Logs</field>
<field name="res_model">fleet.vehicle.log.fuel</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form,graph</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new fuel log.
</p><p>
Here you can add refuelling entries for all vehicles. You can
also filter logs of a particular vehicle using the search
field.
</p>
</field>
</record>
<menuitem action="fleet_vehicle_log_fuel_act" parent="fleet_vehicles" id="fleet_vehicle_log_fuel_menu" />
<record model='ir.ui.view' id='fleet_vehicle_log_services_form'>
<field name="name">fleet.vehicle.log.services.form</field>
<field name="model">fleet.vehicle.log.services</field>
<field name="arch" type="xml">
<form string="Services Logs" version="7.0">
<sheet>
<group col="2">
<group string="Services Details">
<field name="vehicle_id" on_change="on_change_vehicle(vehicle_id)"/>
<field name="cost_subtype" string="Service Type" domain="['|',('category','=','service'),('category','=','both')]" required="1"/>
<field name="amount" string="Price"/>
</group>
<group string="Odometer Details">
<label for="odometer"/>
<div>
<field name="odometer" class="oe_inline"/>
<field name="odometer_unit" class="oe_inline"/>
</div>
</group>
</group>
<group col="2">
<group string="Additional Details">
<field name="date" />
<field name="purchaser_id" />
<field name="vendor_id" />
<field name="inv_ref" />
</group>
</group>
<group string="Included Services">
<field name="cost_ids" nolabel="1">
<tree string="Included Services" version="7.0" editable="bottom">
<field name="cost_subtype" string="Service" domain="[('category','=','service')]"/>
<field name="amount" sum="Price" string="Cost"/>
</tree>
</field>
</group>
<group string="Notes">
<field nolabel="1" name="notes" placeholder="Write here any other information related to the service completed."/>
</group>
</sheet>
</form>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_log_services_tree'>
<field name="name">fleet.vehicle.log.services.tree</field>
<field name="model">fleet.vehicle.log.services</field>
<field name="arch" type="xml">
<tree string="Services Logs">
<field name="date" />
<field name="vehicle_id" />
<field name="cost_subtype"/>
<field name="purchaser_id"/>
<field name="vendor_id" />
<field name="inv_ref" />
<field name="notes" />
<field name="amount" sum="Total"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="fleet_vehicle_log_services_graph">
<field name="name">fleet.vehicle.log.services.graph</field>
<field name="model">fleet.vehicle.log.services</field>
<field name="arch" type="xml">
<graph string="Services Costs Per Month">
<field name="date" />
<field name="cost_amount" operator="+"/>
<field name="vehicle_id" group="True"/>
</graph>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_log_services_act'>
<field name="name">Vehicles Services Logs</field>
<field name="res_model">fleet.vehicle.log.services</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form,graph</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new service entry.
</p><p>
OpenERP helps you keeping track of all the services done
on your vehicle. Services can be of many type: occasional
repair, fixed maintenance, etc.
</p>
</field>
</record>
<menuitem action="fleet_vehicle_log_services_act" parent="fleet_vehicles" id="fleet_vehicle_log_services_menu" />
<record model='ir.ui.view' id='fleet_vehicle_service_types_tree'>
<field name="name">fleet.service.type.tree</field>
<field name="model">fleet.service.type</field>
<field name="arch" type="xml">
<tree string="Service types" editable="bottom">
<field name="name" />
<field name="category"/>
</tree>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_service_types_act'>
<field name="name">Service Types</field>
<field name="res_model">fleet.service.type</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new type of service.
</p><p>
Each service can used in contracts, as a standalone service or both.
</p>
</field>
</record>
<menuitem action="fleet_vehicle_service_types_act" parent="fleet_configuration" id="fleet_vehicle_service_types_menu" groups="base.group_no_one"/>
<record model='ir.ui.view' id='fleet_vehicle_costs_tree'>
<field name="name">fleet.vehicle.cost.tree</field>
<field name="model">fleet.vehicle.cost</field>
<field name="arch" type="xml">
<tree string="Vehicles costs" >
<field name="date"/>
<field name="vehicle_id" />
<field name="cost_type"/>
<field name="cost_subtype"/>
<field name="amount" sum="Total Cost"/>
<field name="parent_id" invisible="1" />
<field name="year" invisible="1"/>
</tree>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_costs_search'>
<field name="name">fleet.vehicle.cost.search</field>
<field name="model">fleet.vehicle.cost</field>
<field name="arch" type="xml">
<search string="Vehicles costs" >
<field name="vehicle_id" />
<field name="cost_subtype"/>
<field name="year"/>
<field name="date"/>
<field name="parent_id"/>
<filter name="parent_false" domain="[('parent_id','=',False)]" string="Effective Costs"/>
<filter name="parent_true" domain="[('parent_id','!=',False)]" string="Indicative Costs"/>
<group expand="1" string="Group By...">
<filter name="groupby_year" context="{'group_by' : 'year'}" string="Year"/>
<filter name="groupby_date" context="{'group_by' : 'date'}" string="Date"/>
<filter name="groupby_cost_type" context="{'group_by' : 'cost_type'}" string="Cost Type"/>
<filter name="groupby_cost_subtype" context="{'group_by' : 'cost_subtype'}" string="Cost Subtype"/>
<filter name="groupby_vehicle_id" context="{'group_by' : 'vehicle_id'}" string="Vehicle"/>
<filter name="groupby_parent_id" context="{'group_by' : 'parent_id'}" string="Parent"/>
</group>
</search>
</field>
</record>
<record model='ir.ui.view' id='fleet_vehicle_costs_form'>
<field name="name">fleet.vehicle.cost.form</field>
<field name="model">fleet.vehicle.cost</field>
<field name="arch" type="xml">
<form string="Vehicle costs" version="7.0">
<sheet>
<group col="2" string="Cost Details">
<group>
<field name="vehicle_id" />
<field name="cost_subtype"/>
<field name="amount"/>
</group>
<group>
<field name="date"/>
<field name="parent_id"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="fleet_vehicle_costs_graph">
<field name="name">fleet.vehicle.cost.graph</field>
<field name="model">fleet.vehicle.cost</field>
<field name="arch" type="xml">
<graph string="Costs Per Month">
<field name="date" />
<field name="amount"/>
<field name="vehicle_id" group="True"/>
</graph>
</field>
</record>
<record model='ir.actions.act_window' id='fleet_vehicle_costs_act'>
<field name="name">Vehicle Costs</field>
<field name="res_model">fleet.vehicle.cost</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form,graph</field>
<field name="context">{"search_default_parent_false" : True, "search_default_groupby_vehicle_id" : True,}</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new cost.
</p><p>
OpenERP helps you managing the costs for your different
vehicles. Costs are created automatically from services,
contracts (fixed or recurring) and fuel logs.
</p>
</field>
</record>
<menuitem action="fleet_vehicle_costs_act" parent="fleet_vehicles" id="fleet_vehicle_costs_menu" />
<!--
<record model='ir.ui.view' id='fleet_hr_employee_form'>
<field name="name">fleet.hr.employee.form</field>
<field name="model">hr.employee</field>
<field name="type">form</field>
<field name="inherit_id" ref="hr.view_employee_form" />
<field name="arch" type="xml">
<notebook position="inside">
<page string="Vehicle">
<group>
<field name="vehicle_id" widget="many2many_tags"/>
</group>
</page>
</notebook>
</field>
</record>
<record model="fleet.vehicle.model" id="citroen">
<field name="name">Citroen</field>
</record>
<record model="fleet.vehicle" id="stw_vehicle">
<field name="name">240BTN</field>
<field name="model_id" ref="citroen" />
</record>
-->
</data>
</openerp>

View File

@ -0,0 +1,11 @@
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
fleet_vehicle_model_access_right,fleet_vehicle_model_access_right,model_fleet_vehicle_model,,1,1,1,1
fleet_vehicle_tag_access_right,fleet_vehicle_tag_access_right,model_fleet_vehicle_tag,,1,1,1,1
fleet_vehicle_state_access_right,fleet_vehicle_state_access_right,model_fleet_vehicle_state,,1,1,1,1
fleet_vehicle_odometer_access_right,fleet_vehicle_odometer_access_right,model_fleet_vehicle_odometer,,1,1,1,1
fleet_vehicle_model_brand_access_right,fleet_vehicle_model_brand_access_right,model_fleet_vehicle_model_brand,,1,1,1,1
fleet_vehicle_access_right,fleet_vehicle_access_right,model_fleet_vehicle,,1,1,1,1
fleet_vehicle_log_fuel_access_right,fleet_vehicle_log_fuel_access_right,model_fleet_vehicle_log_fuel,,1,1,1,1
fleet_vehicle_log_services_access_right,fleet_vehicle_log_services_access_right,model_fleet_vehicle_log_services,,1,1,1,1
fleet_vehicle_log_contract_access_right,fleet_vehicle_log_contract_access_right,model_fleet_vehicle_log_contract,,1,1,1,1
fleet_service_type_access_right,fleet_service_type_access_right,model_fleet_service_type,,1,1,1,1
1 id name model_id/id group_id/id perm_read perm_write perm_create perm_unlink
2 fleet_vehicle_model_access_right fleet_vehicle_model_access_right model_fleet_vehicle_model 1 1 1 1
3 fleet_vehicle_tag_access_right fleet_vehicle_tag_access_right model_fleet_vehicle_tag 1 1 1 1
4 fleet_vehicle_state_access_right fleet_vehicle_state_access_right model_fleet_vehicle_state 1 1 1 1
5 fleet_vehicle_odometer_access_right fleet_vehicle_odometer_access_right model_fleet_vehicle_odometer 1 1 1 1
6 fleet_vehicle_model_brand_access_right fleet_vehicle_model_brand_access_right model_fleet_vehicle_model_brand 1 1 1 1
7 fleet_vehicle_access_right fleet_vehicle_access_right model_fleet_vehicle 1 1 1 1
8 fleet_vehicle_log_fuel_access_right fleet_vehicle_log_fuel_access_right model_fleet_vehicle_log_fuel 1 1 1 1
9 fleet_vehicle_log_services_access_right fleet_vehicle_log_services_access_right model_fleet_vehicle_log_services 1 1 1 1
10 fleet_vehicle_log_contract_access_right fleet_vehicle_log_contract_access_right model_fleet_vehicle_log_contract 1 1 1 1
11 fleet_service_type_access_right fleet_service_type_access_right model_fleet_service_type 1 1 1 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,124 @@
# Spanish 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>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
"PO-Revision-Date: 2012-11-07 12:33+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Spanish <es@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: 2012-11-08 04:47+0000\n"
"X-Generator: Launchpad (build 16232)\n"
#. module: google_base_account
#: field:res.users,gmail_user:0
msgid "Username"
msgstr "Nombre de usuario"
#. module: google_base_account
#: model:ir.actions.act_window,name:google_base_account.act_google_login_form
msgid "Google Login"
msgstr "Acceso de Google"
#. module: google_base_account
#: code:addons/google_base_account/wizard/google_login.py:29
#, python-format
msgid "Google Contacts Import Error!"
msgstr "¡Error en la importacion de los contactos de Google!"
#. module: google_base_account
#: view:res.users:0
msgid " Synchronization "
msgstr " Sincronización "
#. module: google_base_account
#: sql_constraint:res.users:0
msgid "You can not have two users with the same login !"
msgstr "¡No puede tener dos usuarios con el mismo identificador!"
#. module: google_base_account
#: code:addons/google_base_account/wizard/google_login.py:75
#, python-format
msgid "Error"
msgstr "Error"
#. module: google_base_account
#: view:google.login:0
msgid "Google login"
msgstr "Acceso Google"
#. module: google_base_account
#: model:ir.model,name:google_base_account.model_res_users
msgid "res.users"
msgstr "Usuarios"
#. module: google_base_account
#: field:google.login,password:0
msgid "Google Password"
msgstr "Contraseña de Google"
#. module: google_base_account
#: view:google.login:0
msgid "_Cancel"
msgstr "_Cancelar"
#. module: google_base_account
#: view:res.users:0
msgid "Google Account"
msgstr "Cuenta de Google"
#. module: google_base_account
#: field:google.login,user:0
msgid "Google Username"
msgstr "Usuario de Google"
#. module: google_base_account
#: code:addons/google_base_account/wizard/google_login.py:29
#, python-format
msgid ""
"Please install gdata-python-client from http://code.google.com/p/gdata-"
"python-client/downloads/list"
msgstr ""
"Por favor, instale gdata-python-client de http://code.google.com/p/gdata-"
"python-client/downloads/list o desde el administrador de paquetes de su "
"distribución"
#. module: google_base_account
#: model:ir.model,name:google_base_account.model_google_login
msgid "Google Contact"
msgstr "Contacto Google"
#. module: google_base_account
#: view:google.login:0
msgid "_Login"
msgstr "Iniciar _sesión"
#. module: google_base_account
#: constraint:res.users:0
msgid "The chosen company is not in the allowed companies for this user"
msgstr ""
"La compañía seleccionada no está entre las companías permitidas para este "
"usuario"
#. module: google_base_account
#: field:res.users,gmail_password:0
msgid "Password"
msgstr "Contraseña"
#. module: google_base_account
#: code:addons/google_base_account/wizard/google_login.py:75
#, python-format
msgid "Authentication fail check the user and password !"
msgstr "Fallo en la autenticación. ¡Compruebe el usuario y la contraseña!"
#. module: google_base_account
#: view:google.login:0
msgid "ex: user@gmail.com"
msgstr "ejemplo: usuario@gmail.com"

View File

@ -0,0 +1,119 @@
# Mongolian 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>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
"PO-Revision-Date: 2012-11-08 03:11+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Mongolian <mn@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: 2012-11-09 04:39+0000\n"
"X-Generator: Launchpad (build 16250)\n"
#. module: google_base_account
#: field:res.users,gmail_user:0
msgid "Username"
msgstr "Хэрэглэгчийн нэр"
#. module: google_base_account
#: model:ir.actions.act_window,name:google_base_account.act_google_login_form
msgid "Google Login"
msgstr ""
#. module: google_base_account
#: code:addons/google_base_account/wizard/google_login.py:29
#, python-format
msgid "Google Contacts Import Error!"
msgstr ""
#. module: google_base_account
#: view:res.users:0
msgid " Synchronization "
msgstr ""
#. module: google_base_account
#: sql_constraint:res.users:0
msgid "You can not have two users with the same login !"
msgstr "Ижил нэвтрэх нэртэй хоёр хэрэглэгч байж болохгүй!"
#. module: google_base_account
#: code:addons/google_base_account/wizard/google_login.py:75
#, python-format
msgid "Error"
msgstr "Алдаа"
#. module: google_base_account
#: view:google.login:0
msgid "Google login"
msgstr ""
#. module: google_base_account
#: model:ir.model,name:google_base_account.model_res_users
msgid "res.users"
msgstr "res.users"
#. module: google_base_account
#: field:google.login,password:0
msgid "Google Password"
msgstr ""
#. module: google_base_account
#: view:google.login:0
msgid "_Cancel"
msgstr "_Цуцлах"
#. module: google_base_account
#: view:res.users:0
msgid "Google Account"
msgstr ""
#. module: google_base_account
#: field:google.login,user:0
msgid "Google Username"
msgstr ""
#. module: google_base_account
#: code:addons/google_base_account/wizard/google_login.py:29
#, python-format
msgid ""
"Please install gdata-python-client from http://code.google.com/p/gdata-"
"python-client/downloads/list"
msgstr ""
#. module: google_base_account
#: model:ir.model,name:google_base_account.model_google_login
msgid "Google Contact"
msgstr ""
#. module: google_base_account
#: view:google.login:0
msgid "_Login"
msgstr ""
#. module: google_base_account
#: constraint:res.users:0
msgid "The chosen company is not in the allowed companies for this user"
msgstr ""
#. module: google_base_account
#: field:res.users,gmail_password:0
msgid "Password"
msgstr ""
#. module: google_base_account
#: code:addons/google_base_account/wizard/google_login.py:75
#, python-format
msgid "Authentication fail check the user and password !"
msgstr ""
#. module: google_base_account
#: view:google.login:0
msgid "ex: user@gmail.com"
msgstr ""

View File

@ -16,9 +16,9 @@ var _t = instance.web._t,
var view = self.getParent();
var ids = ( view.fields_view.type != "form" )? view.groups.get_selection().ids : [ view.datarecord.id ];
if( !_.isEmpty(ids) ){
view.sidebar_context().then(function (context) {
view.sidebar_context().done(function (context) {
var ds = new instance.web.DataSet(this, 'ir.attachment', context);
ds.call('google_doc_get', [view.dataset.model, ids, context]).then(function(r) {
ds.call('google_doc_get', [view.dataset.model, ids, context]).done(function(r) {
if (r == 'False') {
var params = {
error: response,

View File

@ -57,7 +57,7 @@ openerp.hr_attendance = function (instance) {
var employee = new instance.web.DataSetSearch(self, 'hr.employee', self.session.user_context, [
['user_id', '=', self.session.uid]
]);
return employee.read_slice(['id', 'name', 'state', 'last_sign', 'attendance_access']).pipe(function (res) {
return employee.read_slice(['id', 'name', 'state', 'last_sign', 'attendance_access']).then(function (res) {
if (_.isEmpty(res) )
return;
if (res[0].attendance_access == false){
@ -75,7 +75,7 @@ openerp.hr_attendance = function (instance) {
do_update: function () {
this._super();
var self = this;
this.update_promise = this.update_promise.then(function () {
this.update_promise = this.update_promise.done(function () {
if (self.attendanceslider)
return;
self.attendanceslider = new instance.hr_attendance.AttendanceSlider(self);

View File

@ -291,6 +291,7 @@ survey_request()
class hr_evaluation_interview(osv.osv):
_name = 'hr.evaluation.interview'
_inherits = {'survey.request': 'request_id'}
_inherit = 'mail.thread'
_rec_name = 'request_id'
_description = 'Appraisal Interview'
_columns = {

View File

@ -266,7 +266,7 @@
Each employee may be assigned an Appraisal Plan. Such a plan
defines the frequency and the way you manage your periodic
personnel evaluation. You will be able to define steps and
attach interviews to each step. OpenERP manages all kind of
attach interviews to each step. OpenERP manages all kinds of
evaluations: bottom-up, top-down, self-evaluation and final
evaluation by the manager.
</p>

View File

@ -113,6 +113,13 @@ class hr_holidays(osv.osv):
result[hol.id] = hol.number_of_days_temp
return result
def _check_date(self, cr, uid, ids):
for holiday in self.browse(cr, uid, ids):
holiday_ids = self.search(cr, uid, [('date_from', '<=', holiday.date_to), ('date_to', '>=', holiday.date_from), ('employee_id', '=', holiday.employee_id.id), ('id', '<>', holiday.id)])
if holiday_ids:
return False
return True
_columns = {
'name': fields.char('Description', size=64),
'state': fields.selection([('draft', 'To Submit'), ('cancel', 'Cancelled'),('confirm', 'To Approve'), ('refuse', 'Refused'), ('validate1', 'Second Approval'), ('validate', 'Approved')],
@ -146,6 +153,10 @@ class hr_holidays(osv.osv):
'user_id': lambda obj, cr, uid, context: uid,
'holiday_type': 'employee'
}
_constraints = [
(_check_date, 'You can not have 2 leaves that overlaps on same day!', ['date_from','date_to']),
]
_sql_constraints = [
('type_value', "CHECK( (holiday_type='employee' AND employee_id IS NOT NULL) or (holiday_type='category' AND category_id IS NOT NULL))", "The employee or employee category of this request is missing."),
('date_check2', "CHECK ( (type='add') OR (date_from <= date_to))", "The start date must be anterior to the end date."),
@ -252,6 +263,13 @@ class hr_holidays(osv.osv):
result['value']['number_of_days_temp'] = 0
return result
def write(self, cr, uid, ids, vals, context=None):
check_fnct = self.pool.get('hr.holidays.status').check_access_rights
for holiday in self.browse(cr, uid, ids, context=context):
if holiday.state in ('validate','validate1') and not check_fnct(cr, uid, 'write', raise_exception=False):
raise osv.except_osv(_('Warning!'),_('You cannot modify a leave request that has been approved. Contact a human resource manager.'))
return super(hr_holidays, self).write(cr, uid, ids, vals, context=context)
def set_to_draft(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {

View File

@ -34,8 +34,8 @@
<record model="hr.holidays" id="hr_holidays_employee1_vc">
<field name="name">Summer Vacation</field>
<field name="holiday_status_id" ref="holiday_status_unpaid"/>
<field eval="time.strftime('%Y-%m-20')" name="date_from"/>
<field eval="time.strftime('%Y-%m-22')" name="date_to"/>
<field eval="time.strftime('%Y-%m-23')" name="date_from"/>
<field eval="time.strftime('%Y-%m-25')" name="date_to"/>
<field name="type">add</field>
<field name="state">draft</field>
<field name="number_of_days_temp">7</field>
@ -45,8 +45,8 @@
<record model="hr.holidays" id="hr_holidays_employee1_int_tour">
<field name="name">International Tour</field>
<field name="holiday_status_id" ref="holiday_status_comp"/>
<field eval="time.strftime('%Y-%m-20')" name="date_from"/>
<field eval="time.strftime('%Y-%m-22')" name="date_to"/>
<field eval="time.strftime('%Y-%m-26')" name="date_from"/>
<field eval="time.strftime('%Y-%m-28')" name="date_to"/>
<field name="type">add</field>
<field name="number_of_days_temp">7</field>
<field name="employee_id" ref="hr.employee_fp"/>

View File

@ -16,7 +16,7 @@ openerp.hr_recruitment = function(openerp) {
// Find their matching names
var dataset = new openerp.web.DataSetSearch(self, 'hr.applicant_category', self.session.context, [['id', 'in', _.uniq(categ_ids)]]);
dataset.read_slice(['id', 'name']).then(function(result) {
dataset.read_slice(['id', 'name']).done(function(result) {
_.each(result, function(v, k) {
// Set the proper value in the DOM and display the element
self.$el.find('span[data-categ_id=' + v.id + ']').text(v.name);

View File

@ -7,7 +7,7 @@
<field name="factor">50.0</field>
</record>
<record id="timesheet_invoice_factor3" model="hr_timesheet_invoice.factor">
<field name="name">Gratis</field>
<field name="name">Free of charge</field>
<field name="customer_name">Offered developments</field>
<field name="factor">100.0</field>
</record>

View File

@ -46,7 +46,7 @@ openerp.hr_timesheet_sheet = function(instance) {
var commands = this.field_manager.get_field_value("timesheet_ids");
this.res_o2m_drop.add(new instance.web.Model(this.view.model).call("resolve_2many_commands", ["timesheet_ids", commands, [],
new instance.web.CompoundContext()]))
.then(function(result) {
.done(function(result) {
self.querying = true;
self.set({sheets: result});
self.querying = false;
@ -57,7 +57,7 @@ openerp.hr_timesheet_sheet = function(instance) {
if (self.querying)
return;
self.updating = true;
self.field_manager.set_values({timesheet_ids: self.get("sheets")}).then(function() {
self.field_manager.set_values({timesheet_ids: self.get("sheets")}).done(function() {
self.updating = false;
});
},
@ -85,7 +85,7 @@ openerp.hr_timesheet_sheet = function(instance) {
var default_get;
return this.render_drop.add(new instance.web.Model("hr.analytic.timesheet").call("default_get", [
['account_id','general_account_id', 'journal_id','date','name','user_id','product_id','product_uom_id','to_invoice','amount','unit_amount'],
new instance.web.CompoundContext({'user_id': self.get('user_id')})]).pipe(function(result) {
new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(result) {
default_get = result;
// calculating dates
dates = [];
@ -108,9 +108,9 @@ openerp.hr_timesheet_sheet = function(instance) {
var account_ids = _.map(_.keys(accounts), function(el) { return el === "false" ? false : Number(el) });
return new instance.web.Model("hr.analytic.timesheet").call("multi_on_change_account_id", [[], account_ids,
new instance.web.CompoundContext({'user_id': self.get('user_id')})]).pipe(function(accounts_defaults) {
new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(accounts_defaults) {
accounts = _(accounts).chain().map(function(lines, account_id) {
account_defaults = _.extend({}, default_get, accounts_defaults[account_id]);
account_defaults = _.extend({}, default_get, (accounts_defaults[account_id] || {}).value || {});
// group by days
account_id = account_id === "false" ? false : Number(account_id);
var index = _.groupBy(lines, "date");
@ -136,7 +136,7 @@ openerp.hr_timesheet_sheet = function(instance) {
// we need the name_get of the analytic accounts
return new instance.web.Model("account.analytic.account").call("name_get", [_.pluck(accounts, "account"),
new instance.web.CompoundContext()]).pipe(function(result) {
new instance.web.CompoundContext()]).then(function(result) {
account_names = {};
_.each(result, function(el) {
account_names[el[0]] = el[1];
@ -146,7 +146,7 @@ openerp.hr_timesheet_sheet = function(instance) {
});
});;
});
})).pipe(function(result) {
})).then(function(result) {
// we put all the gathered data in self, then we render
self.dates = dates;
self.accounts = accounts;
@ -222,7 +222,7 @@ openerp.hr_timesheet_sheet = function(instance) {
return;
}
var ops = self.generate_o2m_value();
new instance.web.Model("hr.analytic.timesheet").call("on_change_account_id", [[], id]).pipe(function(res) {
new instance.web.Model("hr.analytic.timesheet").call("on_change_account_id", [[], id]).then(function(res) {
var def = _.extend({}, self.default_get, res.value, {
name: self.description_line,
unit_amount: 0,

View File

@ -0,0 +1,136 @@
# Spanish 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>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
"PO-Revision-Date: 2012-11-08 16:01+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Spanish <es@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: 2012-11-09 04:39+0000\n"
"X-Generator: Launchpad (build 16250)\n"
#. module: l10n_fr_rib
#: constraint:res.partner.bank:0
msgid ""
"\n"
"Please define BIC/Swift code on bank for bank type IBAN Account to make "
"valid payments"
msgstr ""
"\n"
"Por favor defina el código BIC/Swift del banco para una cuenta de tipo IBAN "
"para realizar pagos válidos"
#. module: l10n_fr_rib
#: model:res.partner.bank.type,name:l10n_fr_rib.bank_rib
msgid "RIB and optional IBAN"
msgstr "CC e IBAN opcional"
#. module: l10n_fr_rib
#: field:res.partner.bank,rib_acc_number:0
msgid "RIB account number"
msgstr "Número de la cuenta"
#. module: l10n_fr_rib
#: field:res.partner.bank,bank_code:0
msgid "Bank Code"
msgstr "Código de banco"
#. module: l10n_fr_rib
#: code:addons/l10n_fr_rib/bank.py:54
#, python-format
msgid "The RIB key %s does not correspond to the other codes: %s %s %s."
msgstr "La clave de la CC %s no se corresponde con otros códigos: %s %s %s."
#. module: l10n_fr_rib
#: model:res.partner.bank.type.field,name:l10n_fr_rib.rib_office_field
msgid "office"
msgstr "oficina"
#. module: l10n_fr_rib
#: field:res.bank,rib_code:0
msgid "RIB Bank Code"
msgstr "Código CC"
#. module: l10n_fr_rib
#: code:addons/l10n_fr_rib/bank.py:58
#, python-format
msgid "The IBAN %s is not valid."
msgstr "El IBAN %s no es válido."
#. module: l10n_fr_rib
#: model:ir.model,name:l10n_fr_rib.model_res_partner_bank
msgid "Bank Accounts"
msgstr "Cuentas bancarias"
#. module: l10n_fr_rib
#: field:res.partner.bank,office:0
msgid "Office Code"
msgstr "Código de oficina"
#. module: l10n_fr_rib
#: model:res.partner.bank.type.field,name:l10n_fr_rib.rib_bic_field
msgid "bank_bic"
msgstr "Número BIC"
#. module: l10n_fr_rib
#: model:res.partner.bank.type.field,name:l10n_fr_rib.rib_bank_code_field
msgid "bank_code"
msgstr "código bancario"
#. module: l10n_fr_rib
#: model:res.partner.bank.type.field,name:l10n_fr_rib.rib_key_field
msgid "key"
msgstr "clave"
#. module: l10n_fr_rib
#: model:res.partner.bank.type.field,name:l10n_fr_rib.rib_rib_acc_number_field
msgid "rib_acc_number"
msgstr "Número CC"
#. module: l10n_fr_rib
#: help:res.partner.bank,key:0
msgid ""
"The key is a number allowing to check the correctness of the other codes."
msgstr ""
"La clave es un número que permite comprobar si el resto de códigos son "
"correctos."
#. module: l10n_fr_rib
#: field:res.partner.bank,key:0
msgid "Key"
msgstr "Clave"
#. module: l10n_fr_rib
#: code:addons/l10n_fr_rib/bank.py:53
#: code:addons/l10n_fr_rib/bank.py:58
#, python-format
msgid "Error"
msgstr "Error"
#. module: l10n_fr_rib
#: model:res.partner.bank.type,format_layout:l10n_fr_rib.bank_rib
msgid "%(bank_name)s: %(bank_code)s %(office)s %(rib_acc_number)s %(key)s"
msgstr "%(bank_name)s: %(bank_code)s %(office)s %(rib_acc_number)s %(key)s"
#. module: l10n_fr_rib
#: constraint:res.partner.bank:0
msgid "The RIB and/or IBAN is not valid"
msgstr "La CC y/o IBAN no es válida"
#. module: l10n_fr_rib
#: model:ir.model,name:l10n_fr_rib.model_res_bank
msgid "Bank"
msgstr "Banco"
#. module: l10n_fr_rib
#: model:res.partner.bank.type.field,name:l10n_fr_rib.rib_acc_number_field
msgid "acc_number"
msgstr "Número cuenta"

View File

@ -0,0 +1,177 @@
# Spanish 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>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 01:06+0000\n"
"PO-Revision-Date: 2012-11-08 14:29+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Spanish <es@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: 2012-11-09 04:39+0000\n"
"X-Generator: Launchpad (build 16250)\n"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_fiscal_position_template
msgid "Template for Fiscal Position"
msgstr "Plantilla para posición fiscal"
#. module: l10n_multilang
#: sql_constraint:account.account:0
msgid "The code of the account must be unique per company !"
msgstr "¡El código de la cuenta debe ser único por compañía!"
#. module: l10n_multilang
#: constraint:account.account.template:0
msgid ""
"Configuration Error!\n"
"You can not define children to an account with internal type different of "
"\"View\"! "
msgstr ""
"Error de configuración!\n"
"¡No puede definir hijos para una cuenta con el tipo interno distinto de "
"\"Vista\"! "
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_analytic_journal
msgid "Analytic Journal"
msgstr "Diario analítico"
#. module: l10n_multilang
#: constraint:account.account.template:0
msgid "Error ! You can not create recursive account templates."
msgstr "¡Error! No puede crear plantillas de cuentas recursivas."
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_journal
msgid "Journal"
msgstr "Diario"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_chart_template
msgid "Templates for Account Chart"
msgstr "Plantillas para el plan contable"
#. module: l10n_multilang
#: sql_constraint:account.tax:0
msgid "The description must be unique per company!"
msgstr "¡La descripción debe ser única por compañia!"
#. module: l10n_multilang
#: constraint:account.tax.code.template:0
msgid "Error ! You can not create recursive Tax Codes."
msgstr "¡Error! No puede crear códigos de impuestos recursivos."
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_tax_template
msgid "account.tax.template"
msgstr "Plantilla de impuestos"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_tax
msgid "account.tax"
msgstr "Impuesto"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_account
msgid "Account"
msgstr "Cuenta"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_wizard_multi_charts_accounts
msgid "wizard.multi.charts.accounts"
msgstr "Asistente de plan de cuentas"
#. module: l10n_multilang
#: constraint:account.journal:0
msgid ""
"Configuration error! The currency chosen should be shared by the default "
"accounts too."
msgstr ""
"¡Error de configuración! La moneda elegida debería ser también la misma en "
"las cuentas por defecto"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_account_template
msgid "Templates for Accounts"
msgstr "Plantillas para cuentas"
#. module: l10n_multilang
#: help:account.chart.template,spoken_languages:0
msgid ""
"State here the languages for which the translations of templates could be "
"loaded at the time of installation of this localization module and copied in "
"the final object when generating them from templates. You must provide the "
"language codes separated by ';'"
msgstr ""
"Indique aquí los idiomas para los que las traducciones de las plantillas "
"pueden ser cargadas en el momento de la instalación de este módulo de "
"localización y copiados en el objeto final cuando se generen desde las "
"plantillas. Debe proveer los códigos de idioma separados por ';'."
#. module: l10n_multilang
#: constraint:account.account:0
msgid "Error ! You can not create recursive accounts."
msgstr "¡Error! No se pueden crear cuentas recursivas."
#. module: l10n_multilang
#: constraint:account.account:0
msgid ""
"Configuration Error! \n"
"You can not select an account type with a deferral method different of "
"\"Unreconciled\" for accounts with internal type \"Payable/Receivable\"! "
msgstr ""
"¡Error de configuración! \n"
"¡No puede seleccionar un tipo de cuenta con un método de cierre diferente de "
"\"Reconciliado\" para las cuentas con tipo interno \"A pagar/A cobrar\"! "
#. module: l10n_multilang
#: sql_constraint:account.journal:0
msgid "The name of the journal must be unique per company !"
msgstr "¡El nombre del diaro debe ser único por compañía!"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_analytic_account
msgid "Analytic Account"
msgstr "Cuenta analítica"
#. module: l10n_multilang
#: sql_constraint:account.journal:0
msgid "The code of the journal must be unique per company !"
msgstr "¡El código del diario debe ser único por compañía!"
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_fiscal_position
msgid "Fiscal Position"
msgstr "Posición fiscal"
#. module: l10n_multilang
#: constraint:account.account:0
msgid ""
"Configuration Error! \n"
"You can not define children to an account with internal type different of "
"\"View\"! "
msgstr ""
"¡Error de configuración! \n"
"¡No puede definir hijos en una cuenta con tipo interno distinto a \"Vista\"! "
#. module: l10n_multilang
#: constraint:account.analytic.account:0
msgid "Error! You can not create recursive analytic accounts."
msgstr "¡Error! No puede crear cuentas analíticas recursivas."
#. module: l10n_multilang
#: model:ir.model,name:l10n_multilang.model_account_tax_code_template
msgid "Tax Code Template"
msgstr "Plantilla códigos de impuestos"
#. module: l10n_multilang
#: field:account.chart.template,spoken_languages:0
msgid "Spoken Languages"
msgstr "Idiomas hablados"

View File

@ -22,12 +22,12 @@
import mail_message_subtype
import mail_alias
import mail_followers
import mail_favorite
import mail_message
import mail_mail
import mail_thread
import mail_group
import mail_vote
import mail_favorite
import res_partner
import res_users
import report

View File

@ -357,7 +357,7 @@ openerp.mail = function (session) {
this.context.default_parent_id,
attachments,
this.parent_thread.context
]).then(function (record) {
]).done(function (record) {
var thread = self.parent_thread;
// create object and attach to the thread object
thread.message_fetch(false, false, [record], function (arg, data) {
@ -745,7 +745,7 @@ openerp.mail = function (session) {
}
// if this message is read, all childs message display is read
this.ds_notification.call('set_message_read', [ [this.id].concat( this.get_child_ids() ) , this.to_read, this.context]).pipe(function () {
this.ds_notification.call('set_message_read', [ [this.id].concat( this.get_child_ids() ) , this.to_read, this.context]).then(function () {
self.$el.removeClass(self.to_read ? 'oe_msg_unread':'oe_msg_read').addClass(self.to_read ? 'oe_msg_read':'oe_msg_unread');
self.to_read = !self.to_read;
});
@ -802,7 +802,7 @@ openerp.mail = function (session) {
on_vote: function (event) {
event.stopPropagation();
var self=this;
return this.ds_message.call('vote_toggle', [[self.id]]).pipe(function (vote) {
return this.ds_message.call('vote_toggle', [[self.id]]).then(function (vote) {
self.has_voted = vote;
self.vote_nb += self.has_voted ? 1 : -1;
self.display_vote();
@ -827,7 +827,7 @@ openerp.mail = function (session) {
event.stopPropagation();
var self=this;
var button = self.$('.oe_star:first');
return this.ds_message.call('favorite_toggle', [[self.id]]).pipe(function (star) {
return this.ds_message.call('favorite_toggle', [[self.id]]).then(function (star) {
self.is_favorite=star;
if (self.is_favorite) {
button.addClass('oe_starred');
@ -1112,7 +1112,7 @@ openerp.mail = function (session) {
var thread_level = 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, thread_level, fetch_context, this.context.default_parent_id || undefined])
.then(callback ? _.bind(callback, this, arguments) : this.proxy('switch_new_message'));
.done(callback ? _.bind(callback, this, arguments) : this.proxy('switch_new_message'));
},
/**
@ -1581,7 +1581,7 @@ openerp.mail = function (session) {
load_searchview: function (defaults, hidden) {
var self = this;
this.searchview = new session.web.SearchView(this, this.ds_msg, false, defaults || {}, hidden || false);
return this.searchview.appendTo(this.$('.oe_view_manager_view_search')).then(function () {
return this.searchview.appendTo(this.$('.oe_view_manager_view_search')).done(function () {
self.searchview.on('search_data', self, self.do_searchview_search);
});
},
@ -1599,7 +1599,7 @@ openerp.mail = function (session) {
domains: domains || [],
contexts: contexts || [],
group_by_seq: groupbys || []
}).then(function (results) {
}).done(function (results) {
self.search_results['context'] = results.context;
self.search_results['domain'] = results.domain;
self.root.destroy();

View File

@ -85,7 +85,7 @@ openerp_mail_followers = function(session, mail) {
read_value: function () {
var self = this;
return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).pipe(function (results) {
return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).then(function (results) {
self.set_value(results[0].message_follower_ids);
});
},
@ -98,9 +98,9 @@ openerp_mail_followers = function(session, mail) {
fetch_followers: function (value_) {
this.value = value_ || {};
return this.ds_follow.call('read', [this.value, ['name', 'user_ids']])
.pipe(this.proxy('display_followers'), this.proxy('fetch_generic'))
.pipe(this.proxy('display_buttons'))
.pipe(this.proxy('fetch_subtypes'));
.then(this.proxy('display_followers'), this.proxy('fetch_generic'))
.then(this.proxy('display_buttons'))
.then(this.proxy('fetch_subtypes'));
},
/** Read on res.partner failed: fall back on a generic case
@ -109,10 +109,10 @@ openerp_mail_followers = function(session, mail) {
fetch_generic: function (error, event) {
var self = this;
event.preventDefault();
return this.ds_users.call('read', [this.session.uid, ['partner_id']]).pipe(function (results) {
return this.ds_users.call('read', [this.session.uid, ['partner_id']]).then(function (results) {
var pid = results['partner_id'][0];
self.message_is_follower = (_.indexOf(self.get('value'), pid) != -1);
}).pipe(self.proxy('display_generic'));
}).then(self.proxy('display_generic'));
},
_format_followers: function(count){
// TDE note: why redefining _t ?
@ -179,7 +179,7 @@ openerp_mail_followers = function(session, mail) {
var subtype_list_ul = this.$('.oe_subtype_list').empty();
if (! this.message_is_follower) return;
var context = new session.web.CompoundContext(this.build_context(), {});
this.ds_model.call('message_get_subscription_data', [[this.view.datarecord.id], context]).pipe(this.proxy('display_subtypes'));
this.ds_model.call('message_get_subscription_data', [[this.view.datarecord.id], context]).then(this.proxy('display_subtypes'));
},
/** Display subtypes: {'name': default, followed} */
@ -206,7 +206,7 @@ openerp_mail_followers = function(session, mail) {
$(record).attr('checked',false);
});
var context = new session.web.CompoundContext(this.build_context(), {});
return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], [this.session.uid], context]).pipe(this.proxy('read_value'));
return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], [this.session.uid], context]).then(this.proxy('read_value'));
},
do_update_subscription: function (event) {
@ -221,7 +221,7 @@ openerp_mail_followers = function(session, mail) {
var context = new session.web.CompoundContext(this.build_context(), {});
return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], this.message_is_follower ? checklist:undefined, context])
.pipe(this.proxy('read_value'));
.then(this.proxy('read_value'));
},
});
};

View File

@ -46,7 +46,7 @@ instance.web.form.FieldMany2ManyTagsEmail = instance.web.form.FieldMany2ManyTags
["email", "=", false],
["notification_email_send", "in", ['all', 'comment']] ]],
{context: this.build_context()})
.pipe(function (record_ids) {
.then(function (record_ids) {
// valid partner
var valid_partner = _.difference(ids, record_ids);
self.values = self.values.concat(valid_partner);

View File

@ -197,8 +197,8 @@
<div class="oe_msg_center">
<div class='oe_msg_icons'>
<span class='oe_read' t-if="widget.show_read_unread_button"><a title="Read" class="oe_e">X</a></span>
<span class='oe_unread' t-if="widget.show_read_unread_button"><a title="Set back to unread" class="oe_e">v</a></span>
<span class='oe_read' t-if="widget.show_read_unread_button"><a title="Mark as read" class="oe_e">X</a></span>
<span class='oe_unread' t-if="widget.show_read_unread_button"><a title="Mark as unread" class="oe_e">v</a></span>
<span class='oe_reply' t-if="widget.show_reply_button"><a title="Reply" class="oe_e">(</a></span>
<span t-attf-class="oe_star #{widget.is_favorite?'oe_starred':''}"><a title="Add To Favorites" class="oe_e">7</a></span>
</div>

View File

@ -270,7 +270,7 @@
<field name="signal" groups="base.group_no_one"/>
<field name="start"/>
<field name="object_id" invisible="1"/>
<field name="campaign_id" invisible="1"/>
<field name="campaign_id" invisible="1" required="0"/>
</group>
<group>
<field name="variable_cost"/>

View File

@ -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 00:49+0000\n"
"PO-Revision-Date: 2012-11-01 19:12+0000\n"
"PO-Revision-Date: 2012-11-07 23:15+0000\n"
"Last-Translator: Dusan Laznik <laznik@mentis.si>\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-11-03 05:03+0000\n"
"X-Generator: Launchpad (build 16218)\n"
"X-Launchpad-Export-Date: 2012-11-09 04:39+0000\n"
"X-Generator: Launchpad (build 16250)\n"
#. module: mrp
#: view:mrp.routing.workcenter:0
@ -34,7 +34,7 @@ msgstr ""
#. module: mrp
#: help:mrp.production,location_src_id:0
msgid "Location where the system will look for components."
msgstr ""
msgstr "Lokacija za iskanje komponent"
#. module: mrp
#: field:mrp.production,workcenter_lines:0
@ -67,11 +67,13 @@ msgid ""
"The 'Minimum stock rule' allows the system to create procurement orders "
"automatically as soon as the minimum stock is reached."
msgstr ""
"Pravilo \"Minimalna zaloga\" omogoča avtomatsko kreiranje naročil "
"dobaviteljem."
#. module: mrp
#: field:mrp.production,picking_id:0
msgid "Picking list"
msgstr ""
msgstr "Dobavnica"
#. module: mrp
#: code:addons/mrp/report/price.py:130
@ -83,18 +85,18 @@ msgstr "Urna postavka"
#: code:addons/mrp/report/price.py:139
#, python-format
msgid "Cost Price per Uom"
msgstr ""
msgstr "Stroškovna cena na enoto"
#. module: mrp
#: view:mrp.production:0
msgid "Scrap Products"
msgstr ""
msgstr "Odpis izdelkov"
#. module: mrp
#: model:ir.actions.act_window,name:mrp.mrp_routing_action
#: model:ir.ui.menu,name:mrp.menu_mrp_routing_action
msgid "Routings"
msgstr ""
msgstr "Delovni tok"
#. module: mrp
#: field:mrp.workcenter,product_id:0
@ -139,7 +141,7 @@ msgstr "Dokončani proizvodi"
#. module: mrp
#: view:mrp.production:0
msgid "Manufacturing Orders which are currently in production."
msgstr ""
msgstr "Delovni nalogi trenutno v proizvodnji"
#. module: mrp
#: model:process.transition,name:mrp.process_transition_servicerfq0
@ -204,6 +206,7 @@ msgid ""
"Fill this product to track easily your production costs in the analytic "
"accounting."
msgstr ""
"Izpolnite ta izdelek , za spremljavo stroškov v analitičnem računovodstvu"
#. module: mrp
#: model:process.node,note:mrp.process_node_purchaseprocure0
@ -246,12 +249,12 @@ msgstr "Nabava storitev"
#. module: mrp
#: view:mrp.workcenter:0
msgid "Capacity Information"
msgstr ""
msgstr "Informacije o kapacitetah"
#. module: mrp
#: field:mrp.production,move_created_ids2:0
msgid "Produced Products"
msgstr ""
msgstr "Končani izdelki"
#. module: mrp
#: report:mrp.production.order:0
@ -294,7 +297,7 @@ msgstr ""
#. module: mrp
#: help:mrp.bom,position:0
msgid "Reference to a position in an external plan."
msgstr ""
msgstr "Referenca na pozicijo v drugem planu"
#. module: mrp
#: constraint:stock.move:0
@ -309,12 +312,12 @@ msgstr ""
#. module: mrp
#: model:ir.model,name:mrp.model_mrp_product_produce
msgid "Product Produce"
msgstr ""
msgstr "Končani izdelki"
#. module: mrp
#: constraint:mrp.bom:0
msgid "Error ! You cannot create recursive BoM."
msgstr ""
msgstr "Napaka ! (Rekurzivna kosovnica)"
#. module: mrp
#: model:ir.model,name:mrp.model_mrp_routing_workcenter
@ -324,7 +327,7 @@ msgstr ""
#. module: mrp
#: model:process.transition,name:mrp.process_transition_procurestockableproduct0
msgid "Procurement of stockable Product"
msgstr ""
msgstr "Nabava izdelka , ki se skladišči"
#. module: mrp
#: view:mrp.bom:0
@ -361,7 +364,7 @@ msgstr "Potrdi Proizvodnjo"
msgid ""
"The system creates an order (production or purchased) depending on the sold "
"quantity and the products parameters."
msgstr ""
msgstr "Sistem kreira nalog(delovni ali nabavni), odvisno od parametrov"
#. module: mrp
#: model:process.transition,note:mrp.process_transition_stockproduction0
@ -386,7 +389,7 @@ msgstr ""
msgid ""
"This is the Internal Picking List that brings the finished product to the "
"production plan"
msgstr ""
msgstr "To je interna dobavnica , ki prenese izdelke v plan proizvodnje"
#. module: mrp
#: model:ir.ui.menu,name:mrp.menu_view_resource_calendar_search_mrp
@ -396,7 +399,7 @@ msgstr "Delovni čas"
#. module: mrp
#: model:ir.actions.act_window,name:mrp.action_report_in_out_picking_tree
msgid "Weekly Stock Value Variation"
msgstr ""
msgstr "Tedensko nihanje vrednosti zalog"
#. module: mrp
#: view:mrp.production:0
@ -426,7 +429,7 @@ msgstr ""
#. module: mrp
#: view:board.board:0
msgid "Stock Value Variation"
msgstr ""
msgstr "Nihanje vrednosti zalog"
#. module: mrp
#: model:ir.actions.act_window,name:mrp.action2
@ -436,7 +439,7 @@ msgstr "Struktura kosovnice"
#. module: mrp
#: model:process.node,note:mrp.process_node_serviceproduct0
msgid "Product type is service"
msgstr ""
msgstr "Vrsta izdelka je usluga"
#. module: mrp
#: sql_constraint:res.company:0
@ -505,12 +508,12 @@ msgstr ""
#: view:mrp.routing:0
#: field:mrp.routing,location_id:0
msgid "Production Location"
msgstr ""
msgstr "Lokacija proizvodnje"
#. module: mrp
#: view:mrp.production:0
msgid "Change Qty"
msgstr ""
msgstr "Spremeni količino"
#. module: mrp
#: model:ir.actions.act_window,name:mrp.action_configure_workcenter
@ -520,7 +523,7 @@ msgstr ""
#. module: mrp
#: view:mrp.production:0
msgid "Force Reservation"
msgstr ""
msgstr "Vsili rezervacijo"
#. module: mrp
#: field:report.mrp.inout,value:0
@ -579,7 +582,7 @@ msgstr ""
#. module: mrp
#: field:mrp.workcenter,time_start:0
msgid "Time before prod."
msgstr ""
msgstr "Čas pred proizvodnjo"
#. module: mrp
#: help:mrp.routing,active:0
@ -591,14 +594,14 @@ msgstr ""
#. module: mrp
#: model:process.transition,name:mrp.process_transition_billofmaterialrouting0
msgid "Material Routing"
msgstr ""
msgstr "Tok materiala"
#. module: mrp
#: view:mrp.production:0
#: field:mrp.production,move_lines2:0
#: report:mrp.production.order:0
msgid "Consumed Products"
msgstr ""
msgstr "Porabljeni izdelki"
#. module: mrp
#: model:ir.actions.act_window,name:mrp.action_mrp_workcenter_load_wizard
@ -617,7 +620,7 @@ msgstr "Izdelek nima kosovnice"
#: model:ir.actions.act_window,name:mrp.mrp_bom_form_action2
#: model:ir.ui.menu,name:mrp.menu_mrp_bom_form_action2
msgid "Bill of Material Components"
msgstr ""
msgstr "Komponente sestavnice"
#. module: mrp
#: model:ir.model,name:mrp.model_stock_move
@ -651,7 +654,7 @@ msgstr ""
#. module: mrp
#: help:mrp.workcenter,time_cycle:0
msgid "Time in hours for doing one cycle."
msgstr ""
msgstr "Čas za končanje cikla"
#. module: mrp
#: constraint:mrp.bom:0
@ -666,7 +669,7 @@ msgstr "V proizvodnji"
#. module: mrp
#: model:ir.ui.menu,name:mrp.menu_mrp_property
msgid "Master Bill of Materials"
msgstr ""
msgstr "Glavna sastavnica"
#. module: mrp
#: help:mrp.bom,product_uos:0
@ -695,7 +698,7 @@ msgstr ""
#. module: mrp
#: selection:mrp.workcenter.load,time_unit:0
msgid "Per month"
msgstr ""
msgstr "Mesečno"
#. module: mrp
#: code:addons/mrp/wizard/change_production_qty.py:78
@ -707,13 +710,13 @@ msgstr ""
#. module: mrp
#: report:bom.structure:0
msgid "Product Name"
msgstr ""
msgstr "Ime Izdelka"
#. module: mrp
#: code:addons/mrp/mrp.py:503
#, python-format
msgid "Invalid action !"
msgstr ""
msgstr "Nepravilno dejanje!"
#. module: mrp
#: help:mrp.bom,product_efficiency:0
@ -725,7 +728,7 @@ msgstr ""
#: code:addons/mrp/mrp.py:762
#, python-format
msgid "Warning!"
msgstr ""
msgstr "Opozorilo!"
#. module: mrp
#: report:mrp.production.order:0
@ -741,17 +744,17 @@ msgstr ""
#. module: mrp
#: model:process.transition,name:mrp.process_transition_producttostockrules0
msgid "Procurement rule"
msgstr ""
msgstr "Pravilo nabave"
#. module: mrp
#: view:mrp.production:0
msgid "Partial"
msgstr ""
msgstr "Delno"
#. module: mrp
#: report:mrp.production.order:0
msgid "WorkCenter"
msgstr ""
msgstr "Proizvodni center"
#. module: mrp
#: model:process.transition,note:mrp.process_transition_procureserviceproduct0
@ -769,7 +772,7 @@ msgstr "Nujno"
#. module: mrp
#: view:mrp.production:0
msgid "Manufacturing Orders which are waiting for raw materials."
msgstr ""
msgstr "Delovni nalogi , ki čakajo na material"
#. module: mrp
#: model:ir.actions.act_window,help:mrp.mrp_workcenter_action
@ -780,16 +783,18 @@ msgid ""
"resource leave are not taken into account in the time computation of the "
"work center."
msgstr ""
"Delovno enoto sestavljajo delavci in/ali stroji , ki predstavljajo eno enoto "
"za planiranje kapacitet."
#. module: mrp
#: model:ir.model,name:mrp.model_mrp_production
msgid "Manufacturing Order"
msgstr ""
msgstr "Delovni nalog"
#. module: mrp
#: model:process.transition,name:mrp.process_transition_productionprocureproducts0
msgid "Procurement of raw material"
msgstr ""
msgstr "Nabava surovin"
#. module: mrp
#: view:mrp.production:0
@ -806,7 +811,7 @@ msgstr ""
#: view:mrp.bom:0
#: view:mrp.production:0
msgid "Date"
msgstr ""
msgstr "Datum"
#. module: mrp
#: field:mrp.bom,type:0
@ -823,7 +828,7 @@ msgstr ""
#. module: mrp
#: view:mrp.property:0
msgid "Search"
msgstr ""
msgstr "Iskanje"
#. module: mrp
#: code:addons/mrp/mrp.py:626
@ -884,7 +889,7 @@ msgstr "Možno dati v zalogo"
#: code:addons/mrp/report/price.py:130
#, python-format
msgid "Work Center name"
msgstr ""
msgstr "Ime delovne eote"
#. module: mrp
#: field:mrp.routing,code:0
@ -1034,7 +1039,7 @@ msgstr ""
#. module: mrp
#: help:mrp.workcenter,costs_hour:0
msgid "Specify Cost of Work Center per hour."
msgstr ""
msgstr "Cena delovne enote na uro"
#. module: mrp
#: help:mrp.workcenter,capacity_per_cycle:0
@ -1095,7 +1100,7 @@ msgstr "Analitični dnevnik"
#: model:ir.ui.menu,name:mrp.menu_view_resource_search_mrp
#: field:mrp.routing,workcenter_lines:0
msgid "Work Centers"
msgstr ""
msgstr "Delovne enote"
#. module: mrp
#: selection:mrp.workcenter.load,time_unit:0
@ -1110,6 +1115,8 @@ msgid ""
"They are attached to bills of materials that will define the required raw "
"materials."
msgstr ""
"Delovni tok opredeljuje zaporedje delovnih enot in operacij za izdelavo "
"določenega izdelka."
#. module: mrp
#: model:ir.actions.act_window,name:mrp.product_form_config_action
@ -1152,7 +1159,7 @@ msgstr ""
#. module: mrp
#: view:report.workcenter.load:0
msgid "Work Center load"
msgstr ""
msgstr "Zasedenost delovnega centra"
#. module: mrp
#: help:mrp.production,location_dest_id:0
@ -1853,7 +1860,7 @@ msgstr ""
#. module: mrp
#: field:mrp.routing.workcenter,routing_id:0
msgid "Parent Routing"
msgstr ""
msgstr "Nadrejeni delovni tok"
#. module: mrp
#: help:mrp.workcenter,time_start:0
@ -2013,7 +2020,7 @@ msgstr ""
#: view:mrp.routing:0
#: model:process.node,name:mrp.process_node_routing0
msgid "Routing"
msgstr "Usmerjanje"
msgstr "Delovni tok"
#. module: mrp
#: field:mrp.production,date_planned:0

View File

@ -28,10 +28,6 @@ class mrp_config_settings(osv.osv_memory):
_inherit = 'res.config.settings'
_columns = {
'module_stock_planning': fields.boolean('Manage master production shedule',
help ="""This allows to create a manual procurement plan apart of the normal MRP scheduling,
which works automatically based on minimum stock rules.
This installs the module stock_planning."""),
'module_mrp_repair': fields.boolean("Manage repairs of products ",
help="""Allows to manage all product repairs.
* Add/remove products in the reparation

View File

@ -56,10 +56,6 @@
<field name="module_mrp_operations" class="oe_inline"/>
<label for="module_mrp_operations" />
</div>
<div>
<field name="module_stock_planning" class="oe_inline"/>
<label for="module_stock_planning"/>
</div>
</div>
</group>
<separator string="Master Data"/>

339
addons/note/i18n/nl.po Normal file
View File

@ -0,0 +1,339 @@
# Dutch 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>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-11-02 12:54+0000\n"
"PO-Revision-Date: 2012-11-07 14:51+0000\n"
"Last-Translator: Erwin van der Ploeg (Endian Solutions) <Unknown>\n"
"Language-Team: Dutch <nl@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: 2012-11-08 04:47+0000\n"
"X-Generator: Launchpad (build 16232)\n"
#. module: note
#: sql_constraint:res.users:0
msgid "You can not have two users with the same login !"
msgstr "U kunt niet twee gebruikers hebben met dezelfde gebruikersnaam !"
#. module: note
#: field:note.note,memo:0
msgid "Note Content"
msgstr "Notitie inhoud"
#. module: note
#: view:note.stage:0
msgid "Stages of Notes"
msgstr "Notitie fases"
#. module: note
#: model:ir.model,name:note.model_base_config_settings
msgid "base.config.settings"
msgstr "base.config.settings"
#. module: note
#: model:ir.model,name:note.model_note_tag
msgid "Note Tag"
msgstr "Notitie label"
#. module: note
#: model:res.groups,name:note.group_note_fancy
msgid "Notes / Fancy mode"
msgstr "Notitie / Luxe modus"
#. module: note
#: model:ir.model,name:note.model_note_note
#: view:note.note:0
msgid "Note"
msgstr "Notitie"
#. module: note
#: view:note.note:0
msgid "Group By..."
msgstr "Groepeer op..."
#. module: note
#: field:note.note,message_summary:0
msgid "Summary"
msgstr "Samenvatting"
#. module: note
#: field:note.note,message_follower_ids:0
msgid "Followers"
msgstr "Volgers"
#. module: note
#: model:ir.actions.act_window,help:note.action_note_note
msgid ""
"<p class=\"oe_view_nocontent_create\">\n"
" Click to add a personal note.\n"
" </p><p>\n"
" Use notes to organize personal tasks or notes. All\n"
" notes are private; no one else will be able to see them. "
"However\n"
" you can share some notes with other people by inviting "
"followers\n"
" on the note. (Useful for meeting minutes, especially if\n"
" you activate the pad feature for collaborative writings).\n"
" </p><p>\n"
" You can customize how you process your notes/tasks by adding,\n"
" removing or modifying columns.\n"
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" Klik om een persoonlijke notitie toe te voegen.\n"
" </p><p>\n"
" Gebruik notities om uw persoonlijke taken en notities te "
"organiseren. Alle\n"
" notities zijn prive; niemand anders kan deze notities zien. "
"Echter is het wel \n"
" mogenlijk om sommige notities te delen met andere gebruikers, "
"door deze uit te nodigen\n"
" op een notitie. (Dit is handig voor bijvoorbeeld een "
"gespreksverslag, en zeker als je\n"
" de pad mogelijkheid activeert voor het samenwerken)\n"
" </p><p>\n"
" U kunt het proces van notities en taken aanpassen door het "
"toevoegen,\n"
" verwijderen of aanpassen van kolommen.\n"
" </p>\n"
" "
#. module: note
#: view:note.note:0
msgid "kanban note"
msgstr "kanban notitie"
#. module: note
#: model:note.stage,name:note.demo_note_stage_01
#: model:note.stage,name:note.note_stage_01
msgid "Today"
msgstr "Vandaag"
#. module: note
#: model:ir.model,name:note.model_res_users
msgid "Users"
msgstr "Gebruikers"
#. module: note
#: view:note.note:0
msgid "í"
msgstr "í"
#. module: note
#: view:note.stage:0
msgid "Stage of Notes"
msgstr "Notitie fases"
#. module: note
#: field:note.note,message_unread:0
msgid "Unread Messages"
msgstr "Ongelezen berichten"
#. module: note
#: field:note.note,current_partner_id:0
msgid "unknown"
msgstr "onbekend"
#. module: note
#: view:note.note:0
msgid "By sticky note Category"
msgstr "Notitie categorie"
#. module: note
#: help:note.note,message_unread:0
msgid "If checked new messages require your attention."
msgstr "Indien aangevinkt zullen nieuwe berichten uw aandacht vragen."
#. module: note
#: field:note.stage,name:0
msgid "Stage Name"
msgstr "Naam fase"
#. module: note
#: field:note.note,message_is_follower:0
msgid "Is a Follower"
msgstr "Is een volger"
#. module: note
#: view:note.note:0
msgid "title"
msgstr "titel"
#. module: note
#: model:note.stage,name:note.demo_note_stage_02
#: model:note.stage,name:note.note_stage_02
msgid "Tomorrow"
msgstr "Morgen"
#. module: note
#: view:note.note:0
#: field:note.note,open:0
msgid "Active"
msgstr "Actief"
#. module: note
#: help:note.stage,user_id:0
msgid "Owner of the note stage."
msgstr "Eigenaar van de berichten fase"
#. module: note
#: model:ir.ui.menu,name:note.menu_notes_stage
msgid "Categories"
msgstr "Categorieën"
#. module: note
#: field:note.note,message_comment_ids:0
#: help:note.note,message_comment_ids:0
msgid "Comments and emails"
msgstr "Opmerkingen en e-mails."
#. module: note
#: field:note.tag,name:0
msgid "Tag Name"
msgstr "Label naam"
#. module: note
#: field:note.note,message_ids:0
msgid "Messages"
msgstr "Berichten"
#. module: note
#: view:base.config.settings:0
#: model:ir.actions.act_window,name:note.action_note_note
#: model:ir.ui.menu,name:note.menu_note_notes
#: view:note.note:0
#: model:note.stage,name:note.note_stage_04
msgid "Notes"
msgstr "Notities"
#. module: note
#: model:note.stage,name:note.demo_note_stage_03
#: model:note.stage,name:note.note_stage_03
msgid "Later"
msgstr "Later"
#. module: note
#: model:ir.model,name:note.model_note_stage
msgid "Note Stage"
msgstr "Notitie fase"
#. module: note
#: view:note.note:0
msgid "dropdown menu"
msgstr "keuze menu"
#. module: note
#: model:note.stage,name:note.demo_note_stage_04
msgid "Morning"
msgstr "Ochtend"
#. module: note
#: help:note.stage,sequence:0
msgid "Used to order the note stages"
msgstr "Wordt gebruikt om de notitie fases te sorteren"
#. module: note
#: view:note.note:0
msgid "W"
msgstr "W"
#. module: note
#: field:note.note,stage_ids:0
msgid "Stages of Users"
msgstr "Gebrukers fases"
#. module: note
#: field:note.note,name:0
msgid "Note Summary"
msgstr "Notitie samenvatting"
#. module: note
#: model:ir.actions.act_window,name:note.action_note_stage
#: view:note.note:0
msgid "Stages"
msgstr "Fases"
#. module: note
#: help:note.note,message_ids:0
msgid "Messages and communication history"
msgstr "Berichten en communicatie historie"
#. module: note
#: view:note.note:0
msgid "Delete"
msgstr "Verwijderen"
#. module: note
#: field:note.note,color:0
msgid "Color Index"
msgstr "Kleur index"
#. module: note
#: field:note.note,sequence:0
#: field:note.stage,sequence:0
msgid "Sequence"
msgstr "Reeks"
#. module: note
#: field:note.note,tag_ids:0
msgid "Tags"
msgstr "Labels"
#. module: note
#: view:note.note:0
msgid "Archive"
msgstr "Archief"
#. module: note
#: field:base.config.settings,module_note_pad:0
msgid "Use collaborative pads (etherpad)"
msgstr "Gebruik collaboratieve pads (etherpad)"
#. module: note
#: help:note.note,message_summary:0
msgid ""
"Holds the Chatter summary (number of messages, ...). This summary is "
"directly in html format in order to be inserted in kanban views."
msgstr ""
"Bevat de samenvatting van de chatter (aantal berichten,...). Deze "
"samenvatting is direct in html formaat om zo in de kanban weergave te worden "
"ingevoegd."
#. module: note
#: field:base.config.settings,group_note_fancy:0
msgid "Use fancy layouts for notes"
msgstr "Gebruik luxe layouts voor notities"
#. module: note
#: field:note.stage,user_id:0
msgid "Owner"
msgstr "Eigenaar"
#. module: note
#: constraint:res.users:0
msgid "The chosen company is not in the allowed companies for this user"
msgstr "Het gekozen bedrijf is niet toegestaan voor deze gebruiker"
#. module: note
#: view:note.note:0
#: field:note.note,stage_id:0
msgid "Stage"
msgstr "Fase"
#. module: note
#: field:note.note,date_done:0
msgid "Date done"
msgstr "Datum verwerkt"
#. module: note
#: field:note.stage,fold:0
msgid "Folded by Default"
msgstr "Standaard ingevouwen"

View File

@ -19,7 +19,7 @@ class pad_common(osv.osv_memory):
pad = {
"server" : company.pad_server,
"key" : company.pad_key or "4DxmsNIbnQUVQMW9S9tx2oLOSjFdrx1l",
"key" : company.pad_key,
}
# make sure pad server in the form of http://hostname

View File

@ -1,9 +1,13 @@
<openerp>
<data noupdate="1">
<data>
<record id="base.main_company" model="res.company">
<field name="pad_server">pad.openerp.com</field>
</record>
<record id="base.main_company" model="res.company">
<field name="pad_key">4DxmsNIbnQUVQMW9S9tx2oLOSjFdrx1l</field>
</record>
</data>
</openerp>

View File

@ -12,8 +12,9 @@ openerp.pad = function(instance) {
model: self.view.model,
field_name: self.name,
object_id: self.view.datarecord.id
}}).then(function(data) {
}}).done(function(data) {
if(data&&data.url){
self.set({value: data.url});
_super(data.url);
self.renderElement();
}

View File

@ -0,0 +1,39 @@
# Spanish 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>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
"PO-Revision-Date: 2012-11-08 12:44+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Spanish <es@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: 2012-11-09 04:39+0000\n"
"X-Generator: Launchpad (build 16250)\n"
#. module: pad_project
#: constraint:project.task:0
msgid "Error ! Task end-date must be greater then task start-date"
msgstr ""
"¡Error! La fecha final de la tarea debe ser mayor que la fecha de inicio"
#. module: pad_project
#: model:ir.model,name:pad_project.model_project_task
msgid "Task"
msgstr "Tarea"
#. module: pad_project
#: view:project.task:0
msgid "Pad"
msgstr "Pad"
#. module: pad_project
#: constraint:project.task:0
msgid "Error ! You cannot create recursive tasks."
msgstr "¡Error! No se pueden crear tareas recursivas."

23
addons/plugin/i18n/es.po Normal file
View File

@ -0,0 +1,23 @@
# Spanish 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>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
"PO-Revision-Date: 2012-11-08 11:25+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Spanish <es@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: 2012-11-09 04:39+0000\n"
"X-Generator: Launchpad (build 16250)\n"
#. module: plugin
#: model:ir.model,name:plugin.model_plugin_handler
msgid "plugin.handler"
msgstr "Manejador del plug-in"

View File

@ -10,7 +10,11 @@
<form position="attributes">
<attribute name="string">Install Outlook Plug-In</attribute>
</form>
<xpath expr="//footer" position="replace"/>
<xpath expr="//footer" position="replace">
<footer>
<button string="Close" special="Cancel" class="oe_highlight"/>
</footer>
</xpath>
<xpath expr="//separator[@string='title']" position="after" version="7.0">
<group>
<field name="plugin32" widget="url"/>
@ -19,10 +23,10 @@
<separator string="Installation and Configuration Steps"/>
<p>Click on the link above to download the installer for either 32 or 64 bits, and execute it.</p>
<p>System requirements:</p>
<ul>
<li>1. MS Outlook 2005 or above.</li>
<li>2. MS .Net Framework 3.5 or above.</li>
</ul>
<ol>
<li> MS Outlook 2005 or above.</li>
<li> MS .Net Framework 3.5 or above.</li>
</ol>
</xpath>
<separator string="title" position="attributes">
<attribute name="string"></attribute>
@ -51,7 +55,7 @@
<div>
<field name="module_plugin_outlook" class="oe_inline"/>
<label for="module_plugin_outlook"/>
<button name="%(action_outlook_installer)d" type="action" string="Download and install the plugin" icon="gtk-execute"
<button name="%(action_outlook_installer)d" type="action" string="Download and install the plug-in" icon="gtk-execute"
attrs="{'invisible': [('module_plugin_outlook','=',False)]}" class="oe_link"/>
</div>
</div>

View File

@ -30,13 +30,11 @@ class plugin_thunderbird_installer(osv.osv_memory):
'thunderbird': fields.boolean('Thunderbird Plug-in', help="Allows you to select an object that you would like to add to your email and its attachments."),
'plugin_name': fields.char('File name', size=64),
'plugin_file': fields.char('Thunderbird Plug-in', size=256, readonly=True, help="Thunderbird plug-in file. Save this file and install it in Thunderbird."),
'pdf_file': fields.char('Installation Manual', size=256, help="The documentation file :- how to install Thunderbird Plug-in.", readonly=True),
}
_defaults = {
'thunderbird': True,
'plugin_name': 'openerp_plugin.xpi',
'pdf_file': 'http://doc.openerp.com/book/2/2_6_Comms/2_6_Comms_thunderbird.html',
}
def default_get(self, cr, uid, fields, context=None):
@ -45,4 +43,4 @@ class plugin_thunderbird_installer(osv.osv_memory):
res['plugin_file'] = base_url + '/plugin_thunderbird/static/openerp_plugin.xpi'
return res
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -10,25 +10,28 @@
<form position="attributes">
<attribute name="string">Install Thunderbird Plug-In</attribute>
</form>
<xpath expr="//footer" position="replace"/>
<xpath expr="//footer" position="replace">
<footer>
<button string="Close" special="Cancel" class="oe_highlight"/>
</footer>
</xpath>
<xpath expr="//separator[@string='title']" position="after">
<group>
<field name="thunderbird" invisible="1"/>
<field name="plugin_name" invisible="1"/>
<field name="plugin_file" filename="plugin_name" widget="url"/>
<field name="pdf_file" widget="url"/>
</group>
<separator string="Installation and Configuration Steps"/>
<p>Thunderbird plugin installation:</p>
<ul>
<li>1. Save the Thunderbird plug-in.</li>
<li>2. From the Thunderbird menubar: Tools ­> Add-ons -> Screwdriver/Wrench Icon -> Install add-on from file...</li>
<li>3. Select the plug-in (the file named openerp_plugin.xpi).</li>
<li>4. Click "Install Now".</li>
<li>5. Restart Thunderbird.</li>
<li>6. From the Thunderbird menubar: OpenERP -> Configuration.</li>
<li>7. Configure your openerp server.</li>
</ul>
<p>Thunderbird plug-in installation:</p>
<ol>
<li> Save the Thunderbird plug-in.</li>
<li> From the Thunderbird menubar: Tools ­> Add-ons -> Screwdriver/Wrench Icon -> Install add-on from file...</li>
<li> Select the plug-in (the file named openerp_plugin.xpi).</li>
<li> Click "Install Now".</li>
<li> Restart Thunderbird.</li>
<li> From the Thunderbird menubar: OpenERP -> Configuration.</li>
<li> Configure your openerp server.</li>
</ol>
</xpath>
<separator string="title" position="attributes">
<attribute name="string"></attribute>
@ -57,7 +60,7 @@
<div>
<field name="module_plugin_thunderbird" class="oe_inline"/>
<label for="module_plugin_thunderbird"/>
<button name="%(action_thunderbird_installer)d" type="action" string="Download and install the plugin" icon="gtk-execute"
<button name="%(action_thunderbird_installer)d" type="action" string="Download and install the plug-in" icon="gtk-execute"
attrs="{'invisible': [('module_plugin_thunderbird','=',False)]}" class="oe_link"/>
</div>
</div>

View File

@ -37,12 +37,11 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
callbacks[i](params);
}
this.connection.rpc('/pos/'+name, params || {}).then(function(result){
ret.resolve(result);
},
function(error){
ret.reject(error);
});
this.connection.rpc('/pos/' + name, params || {}).done(function(result) {
ret.resolve(result);
}).fail(function(error) {
ret.reject(error);
});
return ret;
},
@ -96,7 +95,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
return this.weight;
}else{
this.message('weighting_read_kg',{})
.then(function(weight){
.done(function(weight){
if(self.weighting && !self.bypass_proxy){
self.weight = weight;
}

View File

@ -59,10 +59,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
// Any change on this data made on the server is thus not reflected on the point of sale until it is relaunched.
// when all the data has loaded, we compute some stuff, and declare the Pos ready to be used.
$.when(this.load_server_data())
.then(function(){
.done(function(){
//self.log_loaded_data(); //Uncomment if you want to log the data to the console for easier debugging
self.ready.resolve();
},function(){
}).fail(function(){
//we failed to load some backend data, or the backend was badly configured.
//the error messages will be displayed in PosWidget
self.ready.reject();
@ -78,7 +78,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
var self = this;
var loaded = self.fetch('res.users',['name','company_id'],[['id','=',this.session.uid]])
.pipe(function(users){
.then(function(users){
self.set('user',users[0]);
return self.fetch('res.company',
@ -93,19 +93,19 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
'partner_id',
],
[['id','=',users[0].company_id[0]]]);
}).pipe(function(companies){
}).then(function(companies){
self.set('company',companies[0]);
return self.fetch('res.partner',['contact_address'],[['id','=',companies[0].partner_id[0]]]);
}).pipe(function(company_partners){
}).then(function(company_partners){
self.get('company').contact_address = company_partners[0].contact_address;
return self.fetch('res.currency',['symbol','position'],[['id','=',self.get('company').currency_id[0]]]);
}).pipe(function(currencies){
}).then(function(currencies){
self.set('currency',currencies[0]);
return self.fetch('product.uom', null, null);
}).pipe(function(units){
}).then(function(units){
self.set('units',units);
var units_by_id = {};
for(var i = 0, len = units.length; i < len; i++){
@ -114,15 +114,15 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
self.set('units_by_id',units_by_id);
return self.fetch('product.packaging', null, null);
}).pipe(function(packagings){
}).then(function(packagings){
self.set('product.packaging',packagings);
return self.fetch('res.users', ['name','ean13'], [['ean13', '!=', false]]);
}).pipe(function(users){
}).then(function(users){
self.set('user_list',users);
return self.fetch('account.tax', ['amount', 'price_include', 'type']);
}).pipe(function(taxes){
}).then(function(taxes){
self.set('taxes', taxes);
return self.fetch(
@ -130,7 +130,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
['id', 'journal_ids','name','user_id','config_id','start_at','stop_at'],
[['state', '=', 'opened'], ['user_id', '=', self.session.uid]]
);
}).pipe(function(sessions){
}).then(function(sessions){
self.set('pos_session', sessions[0]);
return self.fetch(
@ -141,7 +141,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
'iface_print_via_proxy','iface_cashdrawer','state','sequence_id','session_ids'],
[['id','=', self.get('pos_session').config_id[0]]]
);
}).pipe(function(configs){
}).then(function(configs){
var pos_config = configs[0];
self.set('pos_config', pos_config);
self.iface_electronic_scale = !!pos_config.iface_electronic_scale;
@ -151,15 +151,15 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
self.iface_cashdrawer = !!pos_config.iface_cashdrawer;
return self.fetch('sale.shop',[],[['id','=',pos_config.shop_id[0]]]);
}).pipe(function(shops){
}).then(function(shops){
self.set('shop',shops[0]);
return self.fetch('product.packaging',['ean','product_id']);
}).pipe(function(packagings){
}).then(function(packagings){
self.db.add_packagings(packagings);
return self.fetch('pos.category', ['id','name','parent_id','child_id','image'])
}).pipe(function(categories){
}).then(function(categories){
self.db.add_categories(categories);
return self.fetch(
@ -169,7 +169,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
[['pos_categ_id','!=', false],['sale_ok','=',true]],
{pricelist: self.get('shop').pricelist_id[0]} // context for price
);
}).pipe(function(products){
}).then(function(products){
self.db.add_products(products);
return self.fetch(
@ -177,14 +177,14 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
['account_id','currency','journal_id','state','name','user_id','pos_session_id'],
[['state','=','open'],['pos_session_id', '=', self.get('pos_session').id]]
);
}).pipe(function(bank_statements){
}).then(function(bank_statements){
var journals = new Array();
_.each(bank_statements,function(statement) {
journals.push(statement.journal_id[0])
});
self.set('bank_statements', bank_statements);
return self.fetch('account.journal', undefined, [['id','in', journals]]);
}).pipe(function(journals){
}).then(function(journals){
self.set('journals',journals);
// associate the bank statements with their journals.

View File

@ -557,7 +557,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
setTimeout(function(){
var def = job.fun();
if(def){
def.then(run);
def.done(run);
}else{
run();
}
@ -615,7 +615,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
var def = new $.Deferred();
console.log("START");
self.pos.proxy.payment_request(self.pos.get('selectedOrder').getDueLeft())
.then(function(ack){
.done(function(ack){
if(ack === 'ok'){
self.queue.schedule(self.update);
}else if(ack.indexOf('error') === 0){
@ -638,7 +638,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
return def.resolve();
}
self.pos.proxy.payment_status()
.then(function(status){
.done(function(status){
if(status.status === 'paid'){
var currentOrder = self.pos.get('selectedOrder');
@ -941,8 +941,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
var self = this;
var x = new module.PaymentlineWidget(null, {
payment_line: newPaymentLine
});
x.on('delete_payment_line', self, self.deleteLine);
});
x.on('delete_payment_line', self, function(r) {
self.deleteLine(r);
});
x.appendTo(this.$('#paymentlines'));
},
renderElement: function() {

View File

@ -315,7 +315,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this._super();
this.$('input').keyup(_.bind(this.changeAmount, this));
this.$('.delete-payment-line').click(function() {
self.trigger('delete_payment_line');
self.trigger('delete_payment_line', self);
});
},
});
@ -806,7 +806,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
start: function() {
var self = this;
return self.pos.ready.then(function() {
return self.pos.ready.done(function() {
self.build_currency_template();
self.renderElement();
@ -845,7 +845,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
self.$('.loader').animate({opacity:0},1500,'swing',function(){self.$('.loader').hide();});
self.$('.loader img').hide();
},function(){ // error when loading models data from the backend
}).fail(function(){ // error when loading models data from the backend
self.$('.loader img').hide();
return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_pos_session_opening']], ['res_id'])
.pipe( _.bind(function(res){

View File

@ -10,7 +10,14 @@
<field name="view_id" ref="crm_claim.crm_case_claims_tree_view"/>
<field name="context">{"search_default_user_id":'', "stage_type":'claim'}</field>
<field name="search_view_id" ref="crm_claim.view_crm_case_claims_filter"/>
<field name="help">Record and track your customers' claims. Claims may be linked to a sales order or a lot. You can send emails with attachments and keep the full history for a claim (emails sent, intervention type and so on). Claims may automatically be linked to an email address using the mail gateway module.</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to register a new claim.
</p><p>
You can track your claims from this menu and the action we
will take.
</p>
</field>
</record>
<menuitem name="Claims" id="portal_after_sales_claims" parent="portal.portal_after_sales"

View File

@ -13,7 +13,7 @@
<field name="view_mode">kanban,calendar,tree,form,graph</field>
<field name="context">{"search_default_upcoming":1}</field>
<field name="search_view_id" ref="event.view_event_search"/>
<field name="help">No public events.</field>
<field name="help">There are no public events.</field>
</record>
<menuitem name="Events" id="portal_company_events" parent="portal.portal_company"

View File

@ -100,7 +100,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 don't have any payment.</field>
<field name="help">You don't have any refunds or payments.</field>
</record>
<menuitem id="portal_quotations" parent="portal.portal_orders"

View File

@ -54,6 +54,7 @@ their documents through the portal.</field>
<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 eval="0" name="perm_read"/>
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
</record>

View File

@ -20,7 +20,7 @@ instance.web.ViewManager.include({
if(this.active_view == 'form') {
this.record_id = this.views[this.active_view].controller.datarecord.id;
}
this.process_get_object().pipe(function(process) {
this.process_get_object().then(function(process) {
if(process && process.length) {
if(process.length > 1) {
self.process_selection = process;
@ -30,7 +30,7 @@ instance.web.ViewManager.include({
}
}
return $.Deferred().resolve();
}).pipe(function() {
}).then(function() {
var def = $.Deferred();
if(self.process_id) {
$.when(self.process_graph_get()).done(function(res) {
@ -221,12 +221,12 @@ instance.web.ViewManager.include({
var dataset = new instance.web.DataSet(this, 'ir.values', this.session.user_context);
var action_manager = new instance.web.ActionManager(self);
dataset.call('get',
['action', 'tree_but_open',[['ir.ui.menu', id]], dataset.context]).then(function(res) {
['action', 'tree_but_open',[['ir.ui.menu', id]], dataset.context]).done(function(res) {
var action = res[0][res[0].length - 1];
self.rpc("/web/action/load", {
action_id: action.id,
context: dataset.context
}).then(function(result) {
}).done(function(result) {
action_manager.replace(self.$el);
action_manager.do_action(result.result);
})

View File

@ -1305,7 +1305,17 @@ class task(base_stage, osv.osv):
msg = _('Task has been <b>delegated</b> to <em>%s</em>.') % (task.user_id.name)
self.message_post(cr, uid, [task.id], body=msg, context=context)
return True
def project_task_reevaluate(self, cr, uid, ids, context=None):
if self.pool.get('res.users').has_group(cr, uid, 'project.group_time_work_estimation_tasks'):
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'project.task.reevaluate',
'type': 'ir.actions.act_window',
'target': 'new',
}
return self.do_reopen(cr, uid, ids, context=context)
class project_work(osv.osv):
_name = "project.task.work"

View File

@ -392,7 +392,7 @@
<button name="do_draft" string="Draft" type="object"
states="cancel,done"/>
-->
<button name="%(action_project_task_reevaluate)d" string="Reactivate" type="action"
<button name="project_task_reevaluate" string="Reactivate" type="object"
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"/>

View File

@ -16,7 +16,7 @@ openerp.project = function(openerp) {
// Find their matching names
var dataset = new openerp.web.DataSetSearch(self, 'res.users', self.session.context, [['id', 'in', _.uniq(members_ids)]]);
dataset.read_slice(['id', 'name']).then(function(result) {
dataset.read_slice(['id', 'name']).done(function(result) {
_.each(result, function(v, k) {
// Set the proper value in the DOM
self.$el.find('img[data-member_id=' + v.id + ']').attr('title', v.name).tipsy({
@ -41,7 +41,7 @@ openerp.project = function(openerp) {
// Find their matching names
var dataset = new openerp.web.DataSetSearch(self, 'project.category', self.session.context, [['id', 'in', _.uniq(categ_ids)]]);
dataset.read_slice(['id', 'name']).then(function(result) {
dataset.read_slice(['id', 'name']).done(function(result) {
_.each(result, function(v, k) {
// Set the proper value in the DOM and display the element
self.$el.find('span[data-categ_id=' + v.id + ']').text(v.name);

View File

@ -268,7 +268,7 @@
<page string="Incoming Shipments &amp; Invoices">
<group>
<group>
<field name="dest_address_id" string="Customer Address" on_change="onchange_dest_address_id(dest_address_id)"/>
<field name="dest_address_id" string="Customer Address" on_change="onchange_dest_address_id(dest_address_id)" groups="stock.group_locations"/>
<field name="minimum_planned_date"/>
<field name="location_id" groups="stock.group_locations"/>
<field name="shipped" groups="base.group_no_one"/>

View File

@ -43,14 +43,13 @@ class purchase_config_settings(osv.osv_memory):
'group_costing_method':fields.boolean("Compute product cost price based on average cost",
implied_group='product.group_costing_method',
help="""Allows you to compute product cost price based on average cost."""),
'group_purchase_delivery_address': fields.boolean("Allow a different address for incoming products and invoicings",
'group_purchase_delivery_address': fields.boolean("Allow a different address for incoming products and invoicing",
implied_group='purchase.group_delivery_invoice_address',
help="Allows you to specify different delivery and invoice addresses on a purchase order."),
'module_warning': fields.boolean("Alerts by products or supplier",
help="""Allow to configure warnings on products and trigger them when a user wants to purchase a given product or a given supplier.
Example: Product: this product is deprecated, do not purchase more than 5.
Supplier: don't forget to ask for an express delivery."""),
help="""Allow to configure notification on products and trigger them when a user wants to purchase a given product or a given supplier.
Example: Product: this product is deprecated, do not purchase more than 5.
Supplier: don't forget to ask for an express delivery."""),
'module_purchase_double_validation': fields.boolean("Force two levels of approvals",
help="""Provide a double validation mechanism for purchases exceeding minimum amount.
This installs the module purchase_double_validation."""),

View File

@ -44,7 +44,7 @@ class sale_configuration(osv.osv_memory):
'group_sale_pricelist':fields.boolean("Use pricelists to adapt your price per customers",
implied_group='product.group_sale_pricelist',
help="""Allows to manage different prices based on rules per category of customers.
Example: 10% for retailers, promotion of 5 EUR on this product, etc."""),
Example: 10% for retailers, promotion of 5 EUR on this product, etc."""),
'group_uom':fields.boolean("Allow using different units of measures",
implied_group='product.group_uom',
help="""Allows you to select and maintain different units of measure for products."""),
@ -52,9 +52,9 @@ class sale_configuration(osv.osv_memory):
implied_group='sale.group_discount_per_so_line',
help="Allows you to apply some discount per sale order line."),
'module_warning': fields.boolean("Allow configuring alerts by customer or products",
help="""Allow to configure warnings on products and trigger them when a user wants to sale a given product or a given customer.
Example: Product: this product is deprecated, do not purchase more than 5.
Supplier: don't forget to ask for an express delivery."""),
help="""Allow to configure notification on products and trigger them when a user wants to sale a given product or a given customer.
Example: Product: this product is deprecated, do not purchase more than 5.
Supplier: don't forget to ask for an express delivery."""),
'module_sale_margin': fields.boolean("Display margins on sales orders",
help="""This adds the 'Margin' on sales order.
This gives the profitability by calculating the difference between the Unit Price and Cost Price.

View File

@ -170,8 +170,8 @@
<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_button_confirm" states="draft" string="Confirm Sale" type="object" groups="base.group_user"/>
<button name="action_button_confirm" states="sent" string="Confirm Sale" 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"

View File

@ -123,6 +123,7 @@ class sale_advance_payment_inv(osv.osv_memory):
# create the invoice
inv_line_values = {
'name': res.get('name'),
'origin': sale.name,
'account_id': res['account_id'],
'price_unit': inv_amount,
'quantity': wizard.qtty or 1.0,

View File

@ -15,7 +15,7 @@ openerp.share = function(session) {
self.rpc('/web/session/eval_domain_and_context', {
domains: [domain],
contexts: [view.dataset.context]
}).then(function (result) {
}).done(function (result) {
Share.create({
name: action.name,
record_name: rec_name,
@ -24,8 +24,8 @@ openerp.share = function(session) {
user_type: user_type || 'embedded',
view_type: view.fields_view.type,
invite: invite || false,
}).then(function(share_id) {
var step1 = Share.call('go_step_1', [[share_id]]).then(function(result) {
}).done(function(share_id) {
var step1 = Share.call('go_step_1', [[share_id]]).done(function(result) {
var action = result;
self.do_action(action);
});
@ -37,7 +37,7 @@ openerp.share = function(session) {
if (!session.session.share_flag) {
session.session.share_flag = $.Deferred(function() {
var func = new session.web.Model("share.wizard").get_func("has_share");
func(session.session.uid).pipe(function(res) {
func(session.session.uid).then(function(res) {
if(res) {
session.session.share_flag.resolve();
} else {

View File

@ -41,7 +41,7 @@
<field name="sale_delay" attrs="{'readonly':[('sale_ok','=',False)]}"/>
</group>
<group name="delay" position="after">
<group name="store" string="Storage Localization">
<group name="store" string="Storage Location">
<field name="loc_rack"/>
<field name="loc_row"/>
<field name="loc_case"/>
@ -103,7 +103,7 @@
</group>
</group>
<group name="status" position="after" version="7.0">
<group name="store" string="Storage Localization">
<group name="store" string="Storage Location">
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
<field name="loc_rack" attrs="{'invisible':[('type','=','service')]}"/>
<field name="loc_row" attrs="{'invisible':[('type','=','service')]}"/>

View File

@ -126,7 +126,7 @@
</group>
</group>
<notebook>
<page string="General Informations">
<page string="General Information">
<field name="inventory_line_id">
<tree string="Products" editable="bottom">
<field domain="[('usage','=','internal')]" name="location_id" groups="stock.group_locations"/>

View File

View File

@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2010-2012 OpenERP s.a. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Google Analytics',
'version': '1.0',
'category': 'Tools',
'complexity': "easy",
'description': """
Google Analytics.
==============================
Collects web application usage with Google Analytics.
""",
'author': 'OpenERP SA',
'website': 'http://openerp.com',
'depends': ['web', 'auth_signup'],
'data': [],
'installable': True,
'active': False,
'js': ['static/src/js/web_analytics.js'],
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,134 @@
var _gaq = _gaq || []; // asynchronous stack used by google analytics
openerp.web_analytics = function(instance) {
/** The Google Analytics Module inserts the Google Analytics JS Snippet
* at the top of the page, and sends to google an url each time the
* openerp url is changed.
* The pushes of the urls is made by triggering the 'state_pushed' event in the
* web_client.do_push_state() method which is responsible of changing the openerp current url
*/
// Google Analytics Code snippet
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga,s);
})();
if (instance.webclient) {
// Set the account and domain to start tracking
_gaq.push(['_setAccount', 'UA-7333765-1']); // vta@openerp.com localhost
_gaq.push(['_setDomainName', 'none']); // Change for the real domain
// Track user types
if (instance.session.uid !== 1) {
if ((/\.demo.openerp.com/).test(instance.session.server)) {
_gaq.push(['_setCustomVar', 1, 'User Type', 'Demo User', 1]);
} else {
_gaq.push(['_setCustomVar', 1, 'User Type', 'Normal User', 1]);
}
} else {
_gaq.push(['_setCustomVar', 1, 'User Type', 'Admin User', 1]);
}
// Track object usage
_gaq.push(['_setCustomVar', 2, 'Object', 'no_model', 3]);
// Tack view usage
_gaq.push(['_setCustomVar', 3, 'View Type', 'default', 3]);
_gaq.push(['_trackPageview']);
var self = this;
instance.webclient.on('state_pushed', self, function(state) {
// Track only pages corresponding to a 'normal' view of OpenERP, views
// related to client actions are tracked by the action manager
if (state.model && state.view_type) {
// Track object usage
_gaq.push(['_setCustomVar', 2, 'Object', state.model, 3]);
// Tack view usage
_gaq.push(['_setCustomVar', 3, 'View Type', state.view_type, 3]);
// Track the page
var url = instance.web_analytics.parseUrl({'model': state.model, 'view_type': state.view_type});
_gaq.push(['_trackPageview', url]);
}
});
}
// Track the events related with the creation and the modification of records
instance.web.FormView = instance.web.FormView.extend({
init: function(parent, dataset, view_id, options) {
this._super.apply(this, arguments);
var self = this;
this.on('record_created', self, function(r) {
var url = instance.web_analytics.parseUrl({'model': this.model, 'view_type': 'form'});
_gaq.push(['_trackEvent', this.model, 'on_button_create_save', url]);
});
this.on('record_saved', self, function(r) {
var url = instance.web_analytics.parseUrl({'model': this.model, 'view_type': 'form'});
_gaq.push(['_trackEvent', this.model, 'on_button_edit_save', url]);
});
}
});
// Track client actions
instance.web.ActionManager.include({
ir_actions_client: function (action, options) {
var url = instance.web_analytics.parseUrl({'action': action.tag});
_gaq.push(['_trackPageview', url]);
return this._super.apply(this, arguments);
},
});
// Track button events
instance.web.View.include({
do_execute_action: function(action_data, dataset, record_id, on_closed) {
console.log(action_data);
var category = this.model || dataset.model || '';
var action;
if (action_data.name && _.isNaN(action_data.name-0)) {
action = action_data.name;
} else {
action = action_data.string || action_data.special || '';
}
var label = instance.web_analytics.parseUrl({'model': category, 'view_type': this.view_type});
_gaq.push(['_trackEvent', category, action, label]);
return this._super.apply(this, arguments);
},
});
// Track error events
instance.web.CrashManager = instance.web.CrashManager.extend({
show_error: function(error) {
var hash = window.location.hash;
var params = $.deparam(hash.substr(hash.indexOf('#')+1));
var options = {};
if (params.model && params.view_type) {
options = {'model': params.model, 'view_type': params.view_type};
} else {
options = {'action': params.action};
}
var label = instance.web_analytics.parseUrl(options);
if (error.code) {
_gaq.push(['_trackEvent', error.message, error.data.fault_code, label, ,true]);
} else {
_gaq.push(['_trackEvent', error.type, error.data.debug, label, ,true]);
}
this._super.apply(this, arguments);
},
});
instance.web_analytics.parseUrl = function(options) {
var url = '';
_.each(options, function(value, key) {
url += '/' + key + '=' + value;
});
return url;
};
};

View File

@ -14,7 +14,7 @@ openerp.web_linkedin = function(instance) {
},
test_linkedin: function() {
var self = this;
return this.test_api_key().pipe(function() {
return this.test_api_key().then(function() {
if (self.linkedin_added)
return self.linkedin_def.promise();
var tag = document.createElement('script');
@ -37,7 +37,7 @@ openerp.web_linkedin = function(instance) {
if (this.api_key) {
return $.when();
}
return new instance.web.Model("ir.config_parameter").call("get_param", ["web.linkedin.apikey"]).pipe(function(a) {
return new instance.web.Model("ir.config_parameter").call("get_param", ["web.linkedin.apikey"]).then(function(a) {
if (!!a) {
self.api_key = a;
return true;
@ -69,13 +69,13 @@ openerp.web_linkedin = function(instance) {
},
search_linkedin: function() {
var self = this;
this.display_dm.add(instance.web_linkedin.tester.test_linkedin()).then(function() {
this.display_dm.add(instance.web_linkedin.tester.test_linkedin()).done(function() {
var pop = new instance.web_linkedin.LinkedinPopup(self, self.get("value"));
pop.open();
pop.on("selected", this, function(entity) {
self.selected_entity(entity);
});
}, _.bind(this.linkedin_disabled, this));
}).fail(_.bind(this.linkedin_disabled, this));
},
linkedin_disabled: function() {
instance.web.dialog($(QWeb.render("LinkedIn.DisabledWarning")), {
@ -87,7 +87,7 @@ openerp.web_linkedin = function(instance) {
},
selected_entity: function(entity) {
var self = this;
this.create_on_change(entity).then(function(to_change) {
this.create_on_change(entity).done(function(to_change) {
self.view.set_values(to_change);
});
},
@ -101,7 +101,7 @@ openerp.web_linkedin = function(instance) {
to_change.image = false;
if (entity.logoUrl) {
defs.push(self.rpc('/web_linkedin/binary/url2binary',
{'url': entity.logoUrl}).pipe(function(data){
{'url': entity.logoUrl}).then(function(data){
to_change.image = data;
}));
}
@ -120,7 +120,7 @@ openerp.web_linkedin = function(instance) {
}).error(function() {
children_def.reject();
});
defs.push(children_def.pipe(function(result) {
defs.push(children_def.then(function(result) {
result = _.reject(result.people.values || [], function(el) {
return ! el.formattedName;
});
@ -128,7 +128,7 @@ openerp.web_linkedin = function(instance) {
el.__type = "people";
return self.create_on_change(el);
});
return $.when.apply($, defs).pipe(function() {
return $.when.apply($, defs).then(function() {
var p_to_change = _.toArray(arguments);
to_change.child_ids = p_to_change;
});
@ -144,7 +144,7 @@ openerp.web_linkedin = function(instance) {
to_change.image = false;
if (entity.pictureUrl) {
defs.push(self.rpc('/web_linkedin/binary/url2binary',
{'url': entity.pictureUrl}).pipe(function(data){
{'url': entity.pictureUrl}).then(function(data){
to_change.image = data;
}));
}
@ -163,7 +163,7 @@ openerp.web_linkedin = function(instance) {
to_change.linkedinUrl = entity.publicProfileUrl;
*/
}
return $.when.apply($, defs).pipe(function() {
return $.when.apply($, defs).then(function() {
return to_change;
});
},
@ -186,7 +186,7 @@ openerp.web_linkedin = function(instance) {
this._super();
var self = this;
this.on("authentified", this, this.authentified);
instance.web_linkedin.tester.test_authentication().then(function() {
instance.web_linkedin.tester.test_authentication().done(function() {
self.trigger("authentified");
});
},
@ -200,7 +200,7 @@ openerp.web_linkedin = function(instance) {
encodeURI(this.text), this.limit)).result(function (result) {
cdef.resolve(result);
});
var def = cdef.pipe(function(companies) {
var def = cdef.then(function(companies) {
var lst = companies.companies.values || [];
lst = _.first(lst, self.limit);
lst = _.map(lst, function(el) {
@ -214,7 +214,7 @@ openerp.web_linkedin = function(instance) {
params({"keywords": this.text, "count": this.limit}).result(function(result) {
pdef.resolve(result);
});
var def2 = pdef.pipe(function(people) {
var def2 = pdef.then(function(people) {
var plst = people.people.values || [];
plst = _.first(plst, self.limit);
plst = _.map(plst, function(el) {

View File

@ -46,7 +46,7 @@ instance.web_shortcuts.Shortcuts = instance.web.Widget.extend({
load: function() {
var self = this;
this.$el.find('.oe_systray_shortcuts_items').empty();
return this.rpc('/web/shortcuts/list', {}).then(function(shortcuts) {
return this.rpc('/web/shortcuts/list', {}).done(function(shortcuts) {
_.each(shortcuts, function(sc) {
self.trigger('display', sc);
});
@ -80,7 +80,7 @@ instance.web_shortcuts.Shortcuts = instance.web.Widget.extend({
id = $link.data('id');
self.session.active_id = id;
// TODO: Use do_action({menu_id: id, type: 'ir.actions.menu'})
self.rpc('/web/menu/action', {'menu_id': id}).then(function(ir_menu_data) {
self.rpc('/web/menu/action', {'menu_id': id}).done(function(ir_menu_data) {
if (ir_menu_data.action.length){
instance.webclient.on_menu_action({action_id: ir_menu_data.action[0][2].id});
}
@ -96,7 +96,7 @@ instance.web.UserMenu.include({
do_update: function() {
var self = this;
this._super.apply(this, arguments);
this.update_promise.then(function() {
this.update_promise.done(function() {
if (self.shortcuts) {
self.shortcuts.trigger('load');
} else {
@ -110,7 +110,7 @@ instance.web.UserMenu.include({
instance.web.ViewManagerAction.include({
switch_mode: function (view_type, no_store) {
var self = this;
this._super.apply(this, arguments).then(function() {
this._super.apply(this, arguments).done(function() {
self.shortcut_check(self.views[view_type]);
});
},