-
-
-
+
+
+
diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py
index b111cf2b771..f9388706e97 100644
--- a/addons/account/account_move_line.py
+++ b/addons/account/account_move_line.py
@@ -514,8 +514,7 @@ class account_move_line(osv.osv):
'analytic_lines': fields.one2many('account.analytic.line', 'move_id', 'Analytic lines'),
'centralisation': fields.selection([('normal','Normal'),('credit','Credit Centralisation'),('debit','Debit Centralisation'),('currency','Currency Adjustment')], 'Centralisation', size=8),
'balance': fields.function(_balance, fnct_search=_balance_search, string='Balance'),
- 'state': fields.selection([('draft','Unbalanced'), ('valid','Valid')], 'Status', readonly=True,
- help='When new move line is created the state will be \'Draft\'.\n* When all the payments are done it will be in \'Valid\' state.'),
+ 'state': fields.selection([('draft','Unbalanced'), ('valid','Balanced')], 'Status', readonly=True),
'tax_code_id': fields.many2one('account.tax.code', 'Tax Account', help="The Account can either be a base tax code or a tax code account."),
'tax_amount': fields.float('Tax/Base Amount', digits_compute=dp.get_precision('Account'), select=True, help="If the Tax account is a tax code account, this field will contain the taxed amount.If the tax account is base tax code, "\
"this field will contain the basic amount(without tax)."),
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 1c40bebba52..1b614a1ee85 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -633,13 +633,10 @@
[[ line['blocked'] and 'X' or '' ]]
@@ -241,7 +236,7 @@
[[ formatLang((reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['credit'] or 0) or (y['account_id']['type'] == 'payable' and y['debit'] * -1 or 0)), getLines(o), 0))) ]]
-
+
+
-
+
-
+
-
+
diff --git a/addons/anonymization/i18n/lv.po b/addons/anonymization/i18n/lv.po
new file mode 100644
index 00000000000..34a9fe41f7b
--- /dev/null
+++ b/addons/anonymization/i18n/lv.po
@@ -0,0 +1,213 @@
+# Latvian translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2012-02-08 00:35+0000\n"
+"PO-Revision-Date: 2012-10-16 20:21+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Latvian \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-17 04:36+0000\n"
+"X-Generator: Launchpad (build 16152)\n"
+
+#. module: anonymization
+#: model:ir.model,name:anonymization.model_ir_model_fields_anonymize_wizard
+msgid "ir.model.fields.anonymize.wizard"
+msgstr "ir.model.fields.anonymize.wizard"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymization,field_name:0
+msgid "Field Name"
+msgstr "Lauka Nosaukums"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymization,field_id:0
+msgid "Field"
+msgstr "Lauks"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymization.history,state:0
+#: field:ir.model.fields.anonymize.wizard,state:0
+msgid "State"
+msgstr "Stāvoklis"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymize.wizard,file_import:0
+msgid "Import"
+msgstr "Importēt"
+
+#. module: anonymization
+#: model:ir.model,name:anonymization.model_ir_model_fields_anonymization
+msgid "ir.model.fields.anonymization"
+msgstr "ir.model.fields.anonymization"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymization.history,direction:0
+msgid "Direction"
+msgstr "Virziens"
+
+#. module: anonymization
+#: model:ir.actions.act_window,name:anonymization.action_ir_model_fields_anonymization_tree
+#: view:ir.model.fields.anonymization:0
+#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization_fields
+msgid "Anonymized Fields"
+msgstr "Anonimizēti Lauki"
+
+#. module: anonymization
+#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization
+msgid "Database anonymization"
+msgstr "Datubāzes anonimizācija"
+
+#. module: anonymization
+#: selection:ir.model.fields.anonymization.history,direction:0
+msgid "clear -> anonymized"
+msgstr "tīrs -> anonimizēts"
+
+#. module: anonymization
+#: selection:ir.model.fields.anonymization,state:0
+#: selection:ir.model.fields.anonymize.wizard,state:0
+msgid "Anonymized"
+msgstr "Anonimizēta"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymization,state:0
+msgid "unknown"
+msgstr "nezināms"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymization,model_id:0
+msgid "Object"
+msgstr "Objekts"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymization.history,filepath:0
+msgid "File path"
+msgstr "Ceļš uz failu"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymization.history,date:0
+msgid "Date"
+msgstr "Datums"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymize.wizard,file_export:0
+msgid "Export"
+msgstr "Eksportēt"
+
+#. module: anonymization
+#: view:ir.model.fields.anonymize.wizard:0
+msgid "Reverse the Database Anonymization"
+msgstr "Atgriezt Datubāzes Anonimizāciju"
+
+#. module: anonymization
+#: view:ir.model.fields.anonymize.wizard:0
+msgid "Database Anonymization"
+msgstr "Datubāzes Anonimizācija"
+
+#. module: anonymization
+#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization_wizard
+msgid "Anonymize database"
+msgstr "Anonimizēt datubāzi"
+
+#. module: anonymization
+#: view:ir.model.fields.anonymization.history:0
+#: field:ir.model.fields.anonymization.history,field_ids:0
+msgid "Fields"
+msgstr "Lauki"
+
+#. module: anonymization
+#: selection:ir.model.fields.anonymization,state:0
+#: selection:ir.model.fields.anonymize.wizard,state:0
+msgid "Clear"
+msgstr "Notīrīt"
+
+#. module: anonymization
+#: view:ir.model.fields.anonymize.wizard:0
+#: field:ir.model.fields.anonymize.wizard,summary:0
+msgid "Summary"
+msgstr "Kopsavilkums"
+
+#. module: anonymization
+#: view:ir.model.fields.anonymization:0
+msgid "Anonymized Field"
+msgstr "Anonimizēts lauks"
+
+#. module: anonymization
+#: selection:ir.model.fields.anonymize.wizard,state:0
+msgid "Unstable"
+msgstr "Nestabīls"
+
+#. module: anonymization
+#: selection:ir.model.fields.anonymization.history,state:0
+msgid "Exception occured"
+msgstr "Notikusī kļūda"
+
+#. module: anonymization
+#: selection:ir.model.fields.anonymization,state:0
+#: selection:ir.model.fields.anonymize.wizard,state:0
+msgid "Not Existing"
+msgstr "Neeksistē"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymization,model_name:0
+msgid "Object Name"
+msgstr "Objekta nosaukums"
+
+#. module: anonymization
+#: model:ir.actions.act_window,name:anonymization.action_ir_model_fields_anonymization_history_tree
+#: view:ir.model.fields.anonymization.history:0
+#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization_history
+msgid "Anonymization History"
+msgstr "Anonimizācijas Vēsture"
+
+#. module: anonymization
+#: model:ir.model,name:anonymization.model_ir_model_fields_anonymization_history
+msgid "ir.model.fields.anonymization.history"
+msgstr "ir.model.fields.anonymization.history"
+
+#. module: anonymization
+#: model:ir.actions.act_window,name:anonymization.action_ir_model_fields_anonymize_wizard
+#: view:ir.model.fields.anonymize.wizard:0
+msgid "Anonymize Database"
+msgstr "Anonimizēt Datubāzi"
+
+#. module: anonymization
+#: field:ir.model.fields.anonymize.wizard,name:0
+msgid "File Name"
+msgstr "Faila nosaukums"
+
+#. module: anonymization
+#: selection:ir.model.fields.anonymization.history,direction:0
+msgid "anonymized -> clear"
+msgstr "anonimizēts -> tīrs"
+
+#. module: anonymization
+#: selection:ir.model.fields.anonymization.history,state:0
+msgid "Started"
+msgstr "Iesākta"
+
+#. module: anonymization
+#: selection:ir.model.fields.anonymization.history,state:0
+msgid "Done"
+msgstr "Izdarīts"
+
+#. module: anonymization
+#: view:ir.model.fields.anonymization.history:0
+#: field:ir.model.fields.anonymization.history,msg:0
+#: field:ir.model.fields.anonymize.wizard,msg:0
+msgid "Message"
+msgstr "Ziņojums"
+
+#. module: anonymization
+#: code:addons/anonymization/anonymization.py:55
+#: sql_constraint:ir.model.fields.anonymization:0
+#, python-format
+msgid "You cannot have two fields with the same name on the same object!"
+msgstr "Nevar būt divi lauki ar vienādiem nosaukumiem vienam objektam!"
diff --git a/addons/audittrail/audittrail_view.xml b/addons/audittrail/audittrail_view.xml
index b041329f6bd..c26e1b5b570 100644
--- a/addons/audittrail/audittrail_view.xml
+++ b/addons/audittrail/audittrail_view.xml
@@ -145,7 +145,7 @@
audittrail.log.treeaudittrail.log
-
+
diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py
index ae01df5f6f7..26016f3f0a1 100644
--- a/addons/auth_oauth/controllers/main.py
+++ b/addons/auth_oauth/controllers/main.py
@@ -4,28 +4,25 @@ import simplejson
import werkzeug.urls
import werkzeug.utils
-import openerp.modules.registry
-import openerp.addons.web.controllers.main
-import openerp.addons.web.common.http as openerpweb
-from openerp import SUPERUSER_ID
+import openerp
_logger = logging.getLogger(__name__)
-class OAuthController(openerpweb.Controller):
+class OAuthController(openerp.addons.web.http.Controller):
_cp_path = '/auth_oauth'
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def list_providers(self, req, dbname):
try:
registry = openerp.modules.registry.RegistryManager.get(dbname)
with registry.cursor() as cr:
providers = registry.get('auth.oauth.provider')
- l = providers.read(cr, SUPERUSER_ID, providers.search(cr, SUPERUSER_ID, [('enabled','=',True)]))
+ l = providers.read(cr, openerp.SUPERUSER_ID, providers.search(cr, openerp.SUPERUSER_ID, [('enabled','=',True)]))
except Exception:
l = []
return l
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def signin(self, req, **kw):
state = simplejson.loads(kw['state'])
dbname = state['d']
@@ -34,7 +31,7 @@ class OAuthController(openerpweb.Controller):
with registry.cursor() as cr:
try:
u = registry.get('res.users')
- credentials = u.auth_oauth(cr, SUPERUSER_ID, provider, kw)
+ credentials = u.auth_oauth(cr, openerp.SUPERUSER_ID, provider, kw)
cr.commit()
return openerp.addons.web.controllers.main.login_and_redirect(req, *credentials)
except AttributeError:
@@ -43,7 +40,7 @@ class OAuthController(openerpweb.Controller):
url = "/#action=login&oauth_error=1"
except Exception,e:
# signup error
- _logger.exception('oops')
+ _logger.exception("OAuth2: %s" % str(e))
url = "/#action=login&oauth_error=2"
return openerp.addons.web.controllers.main.set_cookie_and_redirect(req, url)
diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py
index fd26e89c2e3..115e3136f00 100644
--- a/addons/auth_oauth/res_users.py
+++ b/addons/auth_oauth/res_users.py
@@ -15,13 +15,17 @@ class res_users(osv.Model):
_inherit = 'res.users'
_columns = {
- 'oauth_provider_id': fields.many2one('auth.oauth.provider','OAuth Provider'),
+ 'oauth_provider_id': fields.many2one('auth.oauth.provider', 'OAuth Provider'),
'oauth_uid': fields.char('OAuth User ID', help="Oauth Provider user_id"),
- 'oauth_access_token': fields.char('OAuth Token', readonly=True),
+ 'oauth_access_token': fields.char('OAuth Access Token', readonly=True),
}
+ _sql_constraints = [
+ ('uniq_users_oauth_provider_oauth_uid', 'unique(oauth_provider_id, oauth_uid)', 'OAuth UID must be unique per provider'),
+ ]
+
def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None):
- params = urllib.urlencode({ 'access_token': access_token })
+ params = urllib.urlencode({'access_token': access_token})
if urlparse.urlparse(endpoint)[4]:
url = endpoint + '&' + params
else:
@@ -41,22 +45,26 @@ class res_users(osv.Model):
validation = self.auth_oauth_rpc(cr, uid, p.validation_endpoint, access_token)
if validation.get("error"):
- raise openerp.exceptions.AccessDenied
+ raise Exception(validation['error'])
if p.data_endpoint:
data = self.auth_oauth_rpc(cr, uid, p.data_endpoint, access_token)
validation.update(data)
# required
oauth_uid = validation['user_id']
if not oauth_uid:
- raise openerp.exceptions.AccessDenied
+ raise openerp.exceptions.AccessDenied()
email = validation.get('email', 'provider_%d_user_%d' % (p.id, oauth_uid))
# optional
name = validation.get('name', email)
- res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)])
+ res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid), ('oauth_provider_id', '=', provider)])
if res:
- self.write(cr, uid, res[0], { 'oauth_access_token': access_token })
+ assert len(res) == 1
+ self.write(cr, uid, res[0], {'oauth_access_token': access_token})
else:
- # New user
+ # New user if signup module available
+ if not hasattr(self, '_signup_create_user'):
+ raise openerp.exceptions.AccessDenied()
+
new_user = {
'name': name,
'login': email,
@@ -66,7 +74,9 @@ class res_users(osv.Model):
'oauth_access_token': access_token,
'active': True,
}
- self.auth_signup_create(cr, uid, new_user)
+ # TODO pass signup token to allow attach new user to right partner
+ self._signup_create_user(cr, uid, new_user)
+
credentials = (cr.dbname, email, access_token)
return credentials
@@ -74,7 +84,7 @@ class res_users(osv.Model):
try:
return super(res_users, self).check_credentials(cr, uid, password)
except openerp.exceptions.AccessDenied:
- res = self.search(cr, SUPERUSER_ID, [('id','=',uid),('oauth_access_token','=',password)])
+ res = self.search(cr, SUPERUSER_ID, [('id', '=', uid), ('oauth_access_token', '=', password)])
if not res:
raise
diff --git a/addons/auth_openid/controllers/main.py b/addons/auth_openid/controllers/main.py
index ebcaab4bf25..7ee562d4d29 100644
--- a/addons/auth_openid/controllers/main.py
+++ b/addons/auth_openid/controllers/main.py
@@ -23,24 +23,21 @@ import logging
import os
import tempfile
import urllib
-from openerp import SUPERUSER_ID
import werkzeug.urls
import werkzeug.exceptions
-from openerp.modules.registry import RegistryManager
-from openerp.addons.web.controllers.main import login_and_redirect, set_cookie_and_redirect
-try:
- import openerp.addons.web.common.http as openerpweb
-except ImportError:
- import web.common.http as openerpweb # noqa
-
from openid import oidutil
from openid.store import filestore
from openid.consumer import consumer
from openid.cryptutil import randomString
from openid.extensions import ax, sreg
+import openerp
+from openerp import SUPERUSER_ID
+from openerp.modules.registry import RegistryManager
+from openerp.addons.web.controllers.main import login_and_redirect, set_cookie_and_redirect
+
from .. import utils
_logger = logging.getLogger(__name__)
@@ -70,7 +67,7 @@ class GoogleAppsAwareConsumer(consumer.GenericConsumer):
return super(GoogleAppsAwareConsumer, self).complete(message, endpoint, return_to)
-class OpenIDController(openerpweb.Controller):
+class OpenIDController(openerp.addons.web.http.Controller):
_cp_path = '/auth_openid/login'
_store = filestore.FileOpenIDStore(_storedir)
@@ -118,7 +115,7 @@ class OpenIDController(openerpweb.Controller):
def _get_realm(self, req):
return req.httprequest.host_url
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def verify_direct(self, req, db, url):
result = self._verify(req, db, url)
if 'error' in result:
@@ -127,7 +124,7 @@ class OpenIDController(openerpweb.Controller):
return werkzeug.utils.redirect(result['value'])
return result['value']
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def verify(self, req, db, url):
return self._verify(req, db, url)
@@ -157,7 +154,7 @@ class OpenIDController(openerpweb.Controller):
form_html = request.htmlMarkup(realm, redirect_to)
return {'action': 'post', 'value': form_html, 'session_id': req.session_id}
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def process(self, req, **kw):
session = getattr(req.session, 'openid_session', None)
if not session:
@@ -225,7 +222,7 @@ class OpenIDController(openerpweb.Controller):
return set_cookie_and_redirect(req, '/#action=login&loginerror=1')
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def status(self, req):
session = getattr(req.session, 'openid_session', {})
return {'status': session.get('status'), 'message': session.get('message')}
diff --git a/addons/auth_openid/static/src/js/auth_openid.js b/addons/auth_openid/static/src/js/auth_openid.js
index 70739e056ed..56ec5b57d3f 100644
--- a/addons/auth_openid/static/src/js/auth_openid.js
+++ b/addons/auth_openid/static/src/js/auth_openid.js
@@ -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', {}, function(result) {
+ this.rpc('/auth_openid/login/status', {}).then(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}, function(result) {
+ this.rpc('/auth_openid/login/verify', {'db': db, 'url': openid_url}).then(function(result) {
if (result.error) {
self.do_warn(result.title, result.error);
return;
diff --git a/addons/auth_reset_password/controllers/main.py b/addons/auth_reset_password/controllers/main.py
index 5185a65c3ce..639945cfc09 100644
--- a/addons/auth_reset_password/controllers/main.py
+++ b/addons/auth_reset_password/controllers/main.py
@@ -18,20 +18,20 @@
# along with this program. If not, see
#
##############################################################################
-
-from openerp import SUPERUSER_ID
-from openerp.modules.registry import RegistryManager
-import openerp.addons.web.common.http as openerpweb
+import logging
import werkzeug
-import logging
+import openerp
+from openerp import SUPERUSER_ID
+from openerp.modules.registry import RegistryManager
+
_logger = logging.getLogger(__name__)
-class Controller(openerpweb.Controller):
+class Controller(openerp.addons.web.http.Controller):
_cp_path = '/auth_reset_password'
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def reset_password(self, req, dbname, login):
""" retrieve user, and perform reset password """
url = '/'
diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py
index 56e5e910212..54dcc5b4362 100644
--- a/addons/auth_signup/controllers/main.py
+++ b/addons/auth_signup/controllers/main.py
@@ -18,32 +18,31 @@
# along with this program. If not, see
#
##############################################################################
-
-from openerp import SUPERUSER_ID
-from openerp.modules.registry import RegistryManager
-from openerp.addons.web.controllers.main import login_and_redirect
-import openerp.addons.web.common.http as openerpweb
+import logging
import werkzeug
-import logging
+import openerp
+from openerp.modules.registry import RegistryManager
+from openerp.addons.web.controllers.main import login_and_redirect
+
_logger = logging.getLogger(__name__)
-class Controller(openerpweb.Controller):
+class Controller(openerp.addons.web.http.Controller):
_cp_path = '/auth_signup'
- @openerpweb.jsonrequest
+ @openerp.addons.web.http.jsonrequest
def retrieve(self, req, dbname, token):
""" retrieve the user info (name, login or email) corresponding to a signup token """
registry = RegistryManager.get(dbname)
user_info = None
with registry.cursor() as cr:
res_partner = registry.get('res.partner')
- user_info = res_partner.signup_retrieve_info(cr, SUPERUSER_ID, token)
+ user_info = res_partner.signup_retrieve_info(cr, openerp.SUPERUSER_ID, token)
return user_info
- @openerpweb.httprequest
- def signup(self, req, dbname, token, name, login, password):
+ @openerp.addons.web.http.httprequest
+ def signup(self, req, dbname, token, name, login, password, state=''):
""" sign up a user (new or existing), and log it in """
url = '/'
registry = RegistryManager.get(dbname)
@@ -51,9 +50,9 @@ class Controller(openerpweb.Controller):
try:
res_users = registry.get('res.users')
values = {'name': name, 'login': login, 'password': password}
- credentials = res_users.signup(cr, SUPERUSER_ID, values, token)
+ credentials = res_users.signup(cr, openerp.SUPERUSER_ID, values, token)
cr.commit()
- return login_and_redirect(req, *credentials)
+ return login_and_redirect(req, *credentials, redirect_url='/#%s'%state)
except Exception as e:
# signup error
_logger.exception('error when signup')
diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py
index 7b663bd0e33..59196c4da87 100644
--- a/addons/auth_signup/res_users.py
+++ b/addons/auth_signup/res_users.py
@@ -18,6 +18,10 @@
# along with this program. If not, see
#
##############################################################################
+import random
+import time
+import urllib
+import urlparse
import openerp
from openerp.osv import osv, fields
@@ -25,11 +29,6 @@ from openerp import SUPERUSER_ID
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.safe_eval import safe_eval
-import time
-import random
-import urllib
-import urlparse
-
def random_token():
# the token has an entropy of about 120 bits (6 bits/char * 20 chars)
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
@@ -38,7 +37,6 @@ def random_token():
def now():
return time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
-
class res_partner(osv.Model):
_inherit = 'res.partner'
@@ -132,8 +130,6 @@ class res_partner(osv.Model):
res['email'] = partner.email or ''
return res
-
-
class res_users(osv.Model):
_inherit = 'res.users'
diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js
index 509fafa35cc..0974b73292d 100644
--- a/addons/auth_signup/static/src/js/auth_signup.js
+++ b/addons/auth_signup/static/src/js/auth_signup.js
@@ -90,6 +90,7 @@ openerp.auth_signup = function(instance) {
name: name,
login: login,
password: password,
+ state: $.param(this.params)
};
var url = "/auth_signup/signup?" + $.param(params);
window.location = url;
diff --git a/addons/base_crypt/i18n/lv.po b/addons/base_crypt/i18n/lv.po
new file mode 100644
index 00000000000..71e5a3f0e6d
--- /dev/null
+++ b/addons/base_crypt/i18n/lv.po
@@ -0,0 +1,45 @@
+# Latvian translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2012-02-08 00:36+0000\n"
+"PO-Revision-Date: 2012-10-16 16:11+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Latvian \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-17 04:36+0000\n"
+"X-Generator: Launchpad (build 16152)\n"
+
+#. module: base_crypt
+#: model:ir.model,name:base_crypt.model_res_users
+msgid "res.users"
+msgstr "res.users"
+
+#. module: base_crypt
+#: sql_constraint:res.users:0
+msgid "You can not have two users with the same login !"
+msgstr "Nevar būt divi lietotāji ar vienādu pieteikuma vārdu!"
+
+#. module: base_crypt
+#: constraint:res.users:0
+msgid "The chosen company is not in the allowed companies for this user"
+msgstr "Izvēlētais uzņēmums nav šim lietotājam atļauto uzņēmumu sarakstā"
+
+#. module: base_crypt
+#: code:addons/base_crypt/crypt.py:140
+#, python-format
+msgid "Please specify the password !"
+msgstr "Lūdzu norādiet paroli!"
+
+#. module: base_crypt
+#: code:addons/base_crypt/crypt.py:140
+#, python-format
+msgid "Error"
+msgstr "Kļūda"
diff --git a/addons/base_import/__openerp__.py b/addons/base_import/__openerp__.py
index eff20bc90ab..f5a707650d8 100644
--- a/addons/base_import/__openerp__.py
+++ b/addons/base_import/__openerp__.py
@@ -26,13 +26,14 @@ Re-implement openerp's file import system:
'author': 'OpenERP SA',
'depends': ['base'],
'installable': True,
- 'auto_install': False, # set to true and allow uninstall?
+ 'auto_install': True,
'css': [
'static/lib/select2/select2.css',
'static/src/css/import.css',
],
'js': [
'static/lib/select2/select2.js',
+ 'static/lib/javascript-state-machine/state-machine.js',
'static/src/js/import.js',
],
'qweb': ['static/src/xml/import.xml'],
diff --git a/addons/base_import/controllers.py b/addons/base_import/controllers.py
index 85ff993e92e..c831ffd229d 100644
--- a/addons/base_import/controllers.py
+++ b/addons/base_import/controllers.py
@@ -1,15 +1,12 @@
# -*- coding: utf-8 -*-
import simplejson
-try:
- import openerp.addons.web.common.http as openerpweb
-except ImportError:
- import web.common.http as openerpweb
+import openerp
-class ImportController(openerpweb.Controller):
+class ImportController(openerp.addons.web.http.Controller):
_cp_path = '/base_import'
- @openerpweb.httprequest
+ @openerp.addons.web.http.httprequest
def set_file(self, req, file, import_id, jsonp='callback'):
import_id = int(import_id)
diff --git a/addons/base_import/models.py b/addons/base_import/models.py
index 1e5ad002b84..996dbf7964d 100644
--- a/addons/base_import/models.py
+++ b/addons/base_import/models.py
@@ -83,6 +83,10 @@ class ir_import(orm.TransientModel):
}]
fields_got = self.pool[model].fields_get(cr, uid, context=context)
for name, field in fields_got.iteritems():
+ # an empty string means the field is deprecated, @deprecated must
+ # be absent or False to mean not-deprecated
+ if field.get('deprecated', False) is not False:
+ continue
if field.get('readonly'):
states = field.get('states')
if not states:
@@ -97,7 +101,7 @@ class ir_import(orm.TransientModel):
'id': name,
'name': name,
'string': field['string'],
- # Y U NO ALWAYS HAVE REQUIRED
+ # Y U NO ALWAYS HAS REQUIRED
'required': bool(field.get('required')),
'fields': [],
}
@@ -124,8 +128,8 @@ class ir_import(orm.TransientModel):
"""
csv_iterator = csv.reader(
StringIO(record.file),
- quotechar=options['quoting'],
- delimiter=options['separator'])
+ quotechar=str(options['quoting']),
+ delimiter=str(options['separator']))
csv_nonempty = itertools.ifilter(None, csv_iterator)
# TODO: guess encoding with chardet? Or https://github.com/aadsm/jschardet
encoding = options.get('encoding', 'utf-8')
@@ -307,22 +311,14 @@ class ir_import(orm.TransientModel):
except ValueError, e:
return [{
'type': 'error',
- 'message': str(e),
+ 'message': unicode(e),
'record': False,
}]
- try:
- _logger.info('importing %d rows...', len(data))
- (code, record, message, _wat) = self.pool[record.res_model].import_data(
- cr, uid, import_fields, data, context=context)
- _logger.info('done')
-
- except Exception, e:
- _logger.exception("Import failed")
- # TODO: remove when exceptions stop being an "expected"
- # behavior of import_data on some (most) invalid
- # input.
- code, record, message = -1, None, str(e)
+ _logger.info('importing %d rows...', len(data))
+ import_result = self.pool[record.res_model].load(
+ cr, uid, import_fields, data, context=context)
+ _logger.info('done')
# If transaction aborted, RELEASE SAVEPOINT is going to raise
# an InternalError (ROLLBACK should work, maybe). Ignore that.
@@ -339,14 +335,4 @@ class ir_import(orm.TransientModel):
except psycopg2.InternalError:
pass
- if code != -1:
- return []
-
- # TODO: add key for error location?
- # TODO: error not within normal preview, how to display? Re-preview
- # with higher ``count``?
- return [{
- 'type': 'error',
- 'message': message,
- 'record': record or False
- }]
+ return import_result['messages']
diff --git a/addons/base_import/static/lib/javascript-state-machine/LICENSE b/addons/base_import/static/lib/javascript-state-machine/LICENSE
new file mode 100644
index 00000000000..8ad703ca4ef
--- /dev/null
+++ b/addons/base_import/static/lib/javascript-state-machine/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2012 Jake Gordon and contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/addons/base_import/static/lib/javascript-state-machine/README.md b/addons/base_import/static/lib/javascript-state-machine/README.md
new file mode 100644
index 00000000000..64c045e69d7
--- /dev/null
+++ b/addons/base_import/static/lib/javascript-state-machine/README.md
@@ -0,0 +1,327 @@
+Javascript Finite State Machine (v2.1.0)
+========================================
+
+This standalone javascript micro-framework provides a finite state machine for your pleasure.
+
+ * You can find the [code here](https://github.com/jakesgordon/javascript-state-machine)
+ * You can find a [description here](http://codeincomplete.com/posts/2011/8/19/javascript_state_machine_v2/)
+ * You can find a [working demo here](http://codeincomplete.com/posts/2011/8/19/javascript_state_machine_v2/example/)
+
+Download
+========
+
+You can download [state-machine.js](https://github.com/jakesgordon/javascript-state-machine/raw/master/state-machine.js),
+or the [minified version](https://github.com/jakesgordon/javascript-state-machine/raw/master/state-machine.min.js)
+
+Alternatively:
+
+ git clone git@github.com:jakesgordon/javascript-state-machine
+
+
+ * All code is in state-machine.js
+ * Minified version provided in state-machine.min.js
+ * No 3rd party library is required
+ * Demo can be found in /index.html
+ * QUnit tests can be found in /test/index.html
+
+Usage
+=====
+
+Include `state-machine.min.js` in your application.
+
+In its simplest form, create a standalone state machine using:
+
+ var fsm = StateMachine.create({
+ initial: 'green',
+ events: [
+ { name: 'warn', from: 'green', to: 'yellow' },
+ { name: 'panic', from: 'yellow', to: 'red' },
+ { name: 'calm', from: 'red', to: 'yellow' },
+ { name: 'clear', from: 'yellow', to: 'green' }
+ ]});
+
+... will create an object with a method for each event:
+
+ * fsm.warn() - transition from 'green' to 'yellow'
+ * fsm.panic() - transition from 'yellow' to 'red'
+ * fsm.calm() - transition from 'red' to 'yellow'
+ * fsm.clear() - transition from 'yellow' to 'green'
+
+along with the following members:
+
+ * fsm.current - contains the current state
+ * fsm.is(s) - return true if state `s` is the current state
+ * fsm.can(e) - return true if event `e` can be fired in the current state
+ * fsm.cannot(e) - return true if event `e` cannot be fired in the current state
+
+Multiple 'from' and 'to' states for a single event
+==================================================
+
+If an event is allowed **from** multiple states, and always transitions to the same
+state, then simply provide an array of states in the `from` attribute of an event. However,
+if an event is allowed from multiple states, but should transition **to** a different
+state depending on the current state, then provide multiple event entries with
+the same name:
+
+ var fsm = StateMachine.create({
+ initial: 'hungry',
+ events: [
+ { name: 'eat', from: 'hungry', to: 'satisfied' },
+ { name: 'eat', from: 'satisfied', to: 'full' },
+ { name: 'eat', from: 'full', to: 'sick' },
+ { name: 'rest', from: ['hungry', 'satisfied', 'full', 'sick'], to: 'hungry' },
+ ]});
+
+This example will create an object with 2 event methods:
+
+ * fsm.eat()
+ * fsm.rest()
+
+The `rest` event will always transition to the `hungry` state, while the `eat` event
+will transition to a state that is dependent on the current state.
+
+>> NOTE: The `rest` event could use a wildcard '*' for the 'from' state if it should be
+allowed from any current state.
+
+>> NOTE: The `rest` event in the above example can also be specified as multiple events with
+the same name if you prefer the verbose approach.
+
+Callbacks
+=========
+
+4 callbacks are available if your state machine has methods using the following naming conventions:
+
+ * onbefore**event** - fired before the event
+ * onleave**state** - fired when leaving the old state
+ * onenter**state** - fired when entering the new state
+ * onafter**event** - fired after the event
+
+You can affect the event in 3 ways:
+
+ * return `false` from an `onbeforeevent` handler to cancel the event.
+ * return `false` from an `onleavestate` handler to cancel the event.
+ * return `ASYNC` from an `onleavestate` handler to perform an asynchronous state transition (see next section)
+
+For convenience, the 2 most useful callbacks can be shortened:
+
+ * on**event** - convenience shorthand for onafter**event**
+ * on**state** - convenience shorthand for onenter**state**
+
+In addition, a generic `onchangestate()` callback can be used to call a single function for _all_ state changes:
+
+All callbacks will be passed the same arguments:
+
+ * **event** name
+ * **from** state
+ * **to** state
+ * _(followed by any arguments you passed into the original event method)_
+
+Callbacks can be specified when the state machine is first created:
+
+ var fsm = StateMachine.create({
+ initial: 'green',
+ events: [
+ { name: 'warn', from: 'green', to: 'yellow' },
+ { name: 'panic', from: 'yellow', to: 'red' },
+ { name: 'calm', from: 'red', to: 'yellow' },
+ { name: 'clear', from: 'yellow', to: 'green' }
+ ],
+ callbacks: {
+ onpanic: function(event, from, to, msg) { alert('panic! ' + msg); },
+ onclear: function(event, from, to, msg) { alert('thanks to ' + msg); },
+ ongreen: function(event, from, to) { document.body.className = 'green'; },
+ onyellow: function(event, from, to) { document.body.className = 'yellow'; },
+ onred: function(event, from, to) { document.body.className = 'red'; },
+ }
+ });
+
+ fsm.panic('killer bees');
+ fsm.clear('sedatives in the honey pots');
+ ...
+
+Additionally, they can be added and removed from the state machine at any time:
+
+ fsm.ongreen = null;
+ fsm.onyellow = null;
+ fsm.onred = null;
+ fsm.onchangestate = function(event, from, to) { document.body.className = to; };
+
+Asynchronous State Transitions
+==============================
+
+Sometimes, you need to execute some asynchronous code during a state transition and ensure the
+new state is not entered until your code has completed.
+
+A good example of this is when you transition out of a `menu` state, perhaps you want to gradually
+fade the menu away, or slide it off the screen and don't want to transition to your `game` state
+until after that animation has been performed.
+
+You can now return `StateMachine.ASYNC` from your `onleavestate` handler and the state machine
+will be _'put on hold'_ until you are ready to trigger the transition using the new `transition()`
+method.
+
+For example, using jQuery effects:
+
+ var fsm = StateMachine.create({
+
+ initial: 'menu',
+
+ events: [
+ { name: 'play', from: 'menu', to: 'game' },
+ { name: 'quit', from: 'game', to: 'menu' }
+ ],
+
+ callbacks: {
+
+ onentermenu: function() { $('#menu').show(); },
+ onentergame: function() { $('#game').show(); },
+
+ onleavemenu: function() {
+ $('#menu').fadeOut('fast', function() {
+ fsm.transition();
+ });
+ return StateMachine.ASYNC; // tell StateMachine to defer next state until we call transition (in fadeOut callback above)
+ },
+
+ onleavegame: function() {
+ $('#game').slideDown('slow', function() {
+ fsm.transition();
+ };
+ return StateMachine.ASYNC; // tell StateMachine to defer next state until we call transition (in slideDown callback above)
+ }
+
+ }
+ });
+
+
+State Machine Classes
+=====================
+
+You can also turn all instances of a _class_ into an FSM by applying
+the state machine functionality to the prototype, including your callbacks
+in your prototype, and providing a `startup` event for use when constructing
+instances:
+
+ MyFSM = function() { // my constructor function
+ this.startup();
+ };
+
+ MyFSM.prototype = {
+
+ onpanic: function(event, from, to) { alert('panic'); },
+ onclear: function(event, from, to) { alert('all is clear'); },
+
+ // my other prototype methods
+
+ };
+
+ StateMachine.create({
+ target: MyFSM.prototype,
+ events: [
+ { name: 'startup', from: 'none', to: 'green' },
+ { name: 'warn', from: 'green', to: 'yellow' },
+ { name: 'panic', from: 'yellow', to: 'red' },
+ { name: 'calm', from: 'red', to: 'yellow' },
+ { name: 'clear', from: 'yellow', to: 'green' }
+ ]});
+
+
+This should be easy to adjust to fit your appropriate mechanism for object construction.
+
+Initialization Options
+======================
+
+How the state machine should initialize can depend on your application requirements, so
+the library provides a number of simple options.
+
+By default, if you dont specify any initial state, the state machine will be in the `'none'`
+state and you would need to provide an event to take it out of this state:
+
+ var fsm = StateMachine.create({
+ events: [
+ { name: 'startup', from: 'none', to: 'green' },
+ { name: 'panic', from: 'green', to: 'red' },
+ { name: 'calm', from: 'red', to: 'green' },
+ ]});
+ alert(fsm.current); // "none"
+ fsm.startup();
+ alert(fsm.current); // "green"
+
+If you specify the name of your initial event (as in all the earlier examples), then an
+implicit `startup` event will be created for you and fired when the state machine is constructed.
+
+ var fsm = StateMachine.create({
+ initial: 'green',
+ events: [
+ { name: 'panic', from: 'green', to: 'red' },
+ { name: 'calm', from: 'red', to: 'green' },
+ ]});
+ alert(fsm.current); // "green"
+
+If your object already has a `startup` method you can use a different name for the initial event
+
+ var fsm = StateMachine.create({
+ initial: { state: 'green', event: 'init' },
+ events: [
+ { name: 'panic', from: 'green', to: 'red' },
+ { name: 'calm', from: 'red', to: 'green' },
+ ]});
+ alert(fsm.current); // "green"
+
+Finally, if you want to wait to call the initial state transition event until a later date you
+can `defer` it:
+
+ var fsm = StateMachine.create({
+ initial: { state: 'green', event: 'init', defer: true },
+ events: [
+ { name: 'panic', from: 'green', to: 'red' },
+ { name: 'calm', from: 'red', to: 'green' },
+ ]});
+ alert(fsm.current); // "none"
+ fsm.init();
+ alert(fsm.current); // "green"
+
+Of course, we have now come full circle, this last example is pretty much functionally the
+same as the first example in this section where you simply define your own startup event.
+
+So you have a number of choices available to you when initializing your state machine.
+
+Handling Failures
+======================
+
+By default, if you try to call an event method that is not allowed in the current state, the
+state machine will throw an exception. If you prefer to handle the problem yourself, you can
+define a custom `error` handler:
+
+ var fsm = StateMachine.create({
+ initial: 'green',
+ error: function(eventName, from, to, args, errorCode, errorMessage) {
+ return 'event ' + eventName + ' was naughty :- ' + errorMessage;
+ },
+ events: [
+ { name: 'panic', from: 'green', to: 'red' },
+ { name: 'calm', from: 'red', to: 'green' },
+ ]});
+ alert(fsm.calm()); // "event calm was naughty :- event not allowed in current state green"
+
+Release Notes
+=============
+
+See [RELEASE NOTES](https://github.com/jakesgordon/javascript-state-machine/blob/master/RELEASE_NOTES.md) file.
+
+License
+=======
+
+See [LICENSE](https://github.com/jakesgordon/javascript-state-machine/blob/master/LICENSE) file.
+
+Contact
+=======
+
+If you have any ideas, feedback, requests or bug reports, you can reach me at
+[jake@codeincomplete.com](mailto:jake@codeincomplete.com), or via
+my website: [Code inComplete](http://codeincomplete.com/posts/2011/8/19/javascript_state_machine_v2/)
+
+
+
+
+
diff --git a/addons/base_import/static/lib/javascript-state-machine/RELEASE_NOTES.md b/addons/base_import/static/lib/javascript-state-machine/RELEASE_NOTES.md
new file mode 100644
index 00000000000..06abf402d38
--- /dev/null
+++ b/addons/base_import/static/lib/javascript-state-machine/RELEASE_NOTES.md
@@ -0,0 +1,32 @@
+Version 2.1.0 (January 7th 2012)
+--------------------------------
+
+ * Wrapped in self executing function to be more easily used with loaders like `require.js` or `curl.js` (issue #15)
+ * Allow event to be cancelled by returning `false` from `onleavestate` handler (issue #13) - WARNING: this breaks backward compatibility for async transitions (you now need to return `StateMachine.ASYNC` instead of `false`)
+ * Added explicit return values for event methods (issue #12)
+ * Added support for wildcard events that can be fired 'from' any state (issue #11)
+ * Added support for no-op events that transition 'to' the same state (issue #5)
+ * extended custom error callback to handle any exceptions caused by caller provided callbacks
+ * added custom error callback to override exception when an illegal state transition is attempted (thanks to cboone)
+ * fixed typos (thanks to cboone)
+ * fixed issue #4 - ensure before/after event hooks are called even if the event doesn't result in a state change
+
+Version 2.0.0 (August 19th 2011)
+--------------------------------
+
+ * adding support for asynchronous state transitions (see README) - with lots of qunit tests (see test/async.js).
+ * consistent arguments for ALL callbacks, first 3 args are ALWAYS event name, from state and to state, followed by whatever arguments the user passed to the original event method.
+ * added a generic `onchangestate(event,from,to)` callback to detect all state changes with a single function.
+ * allow callbacks to be declared at creation time (instead of having to attach them afterwards)
+ * renamed 'hooks' => 'callbacks'
+ * [read more...](http://codeincomplete.com/posts/2011/8/19/javascript_state_machine_v2/)
+
+Version 1.2.0 (June 21st 2011)
+------------------------------
+ * allows the same event to transition to different states, depending on the current state (see 'Multiple...' section in README.md)
+ * [read more...](http://codeincomplete.com/posts/2011/6/21/javascript_state_machine_v1_2_0/)
+
+Version 1.0.0 (June 1st 2011)
+-----------------------------
+ * initial version
+ * [read more...](http://codeincomplete.com/posts/2011/6/1/javascript_state_machine/)
diff --git a/addons/base_import/static/lib/javascript-state-machine/Rakefile b/addons/base_import/static/lib/javascript-state-machine/Rakefile
new file mode 100644
index 00000000000..beb8702a7f0
--- /dev/null
+++ b/addons/base_import/static/lib/javascript-state-machine/Rakefile
@@ -0,0 +1,8 @@
+
+desc "create minified version of state-machine.js"
+task :minify do
+ require File.expand_path(File.join(File.dirname(__FILE__), 'minifier/minifier'))
+ Minifier.enabled = true
+ Minifier.minify('state-machine.js')
+end
+
diff --git a/addons/base_import/static/lib/javascript-state-machine/index.html b/addons/base_import/static/lib/javascript-state-machine/index.html
new file mode 100644
index 00000000000..2d6cb62617b
--- /dev/null
+++ b/addons/base_import/static/lib/javascript-state-machine/index.html
@@ -0,0 +1,39 @@
+
+
+
+ Javascript Finite State Machine
+
+
+
+
+
+
+
+
+
Finite State Machine
+
+
+
+
+
+
+
+
+
+
+
+
+ dashed lines are asynchronous state transitions (3 seconds)
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/base_import/static/lib/javascript-state-machine/state-machine.js b/addons/base_import/static/lib/javascript-state-machine/state-machine.js
new file mode 100644
index 00000000000..0d503ee7bdb
--- /dev/null
+++ b/addons/base_import/static/lib/javascript-state-machine/state-machine.js
@@ -0,0 +1,155 @@
+(function (window) {
+
+ StateMachine = {
+
+ //---------------------------------------------------------------------------
+
+ VERSION: "2.1.0",
+
+ //---------------------------------------------------------------------------
+
+ Result: {
+ SUCCEEDED: 1, // the event transitioned successfully from one state to another
+ NOTRANSITION: 2, // the event was successfull but no state transition was necessary
+ CANCELLED: 3, // the event was cancelled by the caller in a beforeEvent callback
+ ASYNC: 4, // the event is asynchronous and the caller is in control of when the transition occurs
+ },
+
+ Error: {
+ INVALID_TRANSITION: 100, // caller tried to fire an event that was innapropriate in the current state
+ PENDING_TRANSITION: 200, // caller tried to fire an event while an async transition was still pending
+ INVALID_CALLBACK: 300, // caller provided callback function threw an exception
+ },
+
+ WILDCARD: '*',
+ ASYNC: 'async',
+
+ //---------------------------------------------------------------------------
+
+ create: function(cfg, target) {
+
+ var initial = (typeof cfg.initial == 'string') ? { state: cfg.initial } : cfg.initial; // allow for a simple string, or an object with { state: 'foo', event: 'setup', defer: true|false }
+ var fsm = target || cfg.target || {};
+ var events = cfg.events || [];
+ var callbacks = cfg.callbacks || {};
+ var map = {};
+
+ var add = function(e) {
+ var from = (e.from instanceof Array) ? e.from : (e.from ? [e.from] : [StateMachine.WILDCARD]); // allow 'wildcard' transition if 'from' is not specified
+ map[e.name] = map[e.name] || {};
+ for (var n = 0 ; n < from.length ; n++)
+ map[e.name][from[n]] = e.to || from[n]; // allow no-op transition if 'to' is not specified
+ };
+
+ if (initial) {
+ initial.event = initial.event || 'startup';
+ add({ name: initial.event, from: 'none', to: initial.state });
+ }
+
+ for(var n = 0 ; n < events.length ; n++)
+ add(events[n]);
+
+ for(var name in map) {
+ if (map.hasOwnProperty(name))
+ fsm[name] = StateMachine.buildEvent(name, map[name]);
+ }
+
+ for(var name in callbacks) {
+ if (callbacks.hasOwnProperty(name))
+ fsm[name] = callbacks[name]
+ }
+
+ fsm.current = 'none';
+ fsm.is = function(state) { return this.current == state; };
+ fsm.can = function(event) { return !this.transition && (map[event].hasOwnProperty(this.current) || map[event].hasOwnProperty(StateMachine.WILDCARD)); }
+ fsm.cannot = function(event) { return !this.can(event); };
+ fsm.error = cfg.error || function(name, from, to, args, error, msg) { throw msg; }; // default behavior when something unexpected happens is to throw an exception, but caller can override this behavior if desired (see github issue #3)
+
+ if (initial && !initial.defer)
+ fsm[initial.event]();
+
+ return fsm;
+
+ },
+
+ //===========================================================================
+
+ doCallback: function(fsm, func, name, from, to, args) {
+ if (func) {
+ try {
+ return func.apply(fsm, [name, from, to].concat(args));
+ }
+ catch(e) {
+ return fsm.error(name, from, to, args, StateMachine.Error.INVALID_CALLBACK, "an exception occurred in a caller-provided callback function");
+ }
+ }
+ },
+
+ beforeEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onbefore' + name], name, from, to, args); },
+ afterEvent: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onafter' + name] || fsm['on' + name], name, from, to, args); },
+ leaveState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onleave' + from], name, from, to, args); },
+ enterState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onenter' + to] || fsm['on' + to], name, from, to, args); },
+ changeState: function(fsm, name, from, to, args) { return StateMachine.doCallback(fsm, fsm['onchangestate'], name, from, to, args); },
+
+
+ buildEvent: function(name, map) {
+ return function() {
+
+ var from = this.current;
+ var to = map[from] || map[StateMachine.WILDCARD] || from;
+ var args = Array.prototype.slice.call(arguments); // turn arguments into pure array
+
+ if (this.transition)
+ return this.error(name, from, to, args, StateMachine.Error.PENDING_TRANSITION, "event " + name + " inappropriate because previous transition did not complete");
+
+ if (this.cannot(name))
+ return this.error(name, from, to, args, StateMachine.Error.INVALID_TRANSITION, "event " + name + " inappropriate in current state " + this.current);
+
+ if (false === StateMachine.beforeEvent(this, name, from, to, args))
+ return StateMachine.CANCELLED;
+
+ if (from === to) {
+ StateMachine.afterEvent(this, name, from, to, args);
+ return StateMachine.NOTRANSITION;
+ }
+
+ // prepare a transition method for use EITHER lower down, or by caller if they want an async transition (indicated by an ASYNC return value from leaveState)
+ var fsm = this;
+ this.transition = function() {
+ fsm.transition = null; // this method should only ever be called once
+ fsm.current = to;
+ StateMachine.enterState( fsm, name, from, to, args);
+ StateMachine.changeState(fsm, name, from, to, args);
+ StateMachine.afterEvent( fsm, name, from, to, args);
+ };
+
+ var leave = StateMachine.leaveState(this, name, from, to, args);
+ if (false === leave) {
+ this.transition = null;
+ return StateMachine.CANCELLED;
+ }
+ else if ("async" === leave) {
+ return StateMachine.ASYNC;
+ }
+ else {
+ if (this.transition)
+ this.transition(); // in case user manually called transition() but forgot to return ASYNC
+ return StateMachine.SUCCEEDED;
+ }
+
+ };
+ }
+
+ }; // StateMachine
+
+ //===========================================================================
+
+ if ("function" === typeof define) {
+ define("statemachine", [], function() { return StateMachine; });
+ }
+ else {
+ window.StateMachine = StateMachine;
+ }
+
+}(this));
+
diff --git a/addons/base_import/static/src/css/import.css b/addons/base_import/static/src/css/import.css
index f6258f5aa50..21e598ff707 100644
--- a/addons/base_import/static/src/css/import.css
+++ b/addons/base_import/static/src/css/import.css
@@ -10,7 +10,8 @@
.oe_import .oe_import_grid,
.oe_import .oe_import_error_report,
.oe_import .oe_import_with_file,
-.oe_import .oe_import_noheaders {
+.oe_import .oe_import_noheaders,
+.oe_import .oe_import_report_more {
display: none;
}
@@ -19,7 +20,8 @@
}
.oe_import.oe_import_error .oe_import_error_report,
.oe_import.oe_import_with_file .oe_import_with_file,
-.oe_import.oe_import_noheaders .oe_import_noheaders {
+.oe_import.oe_import_noheaders .oe_import_noheaders,
+.oe_import .oe_import_report_showmore .oe_import_report_more {
display: block;
}
@@ -29,6 +31,9 @@
.oe_import .oe_import_error_report ul .oe_import_report_warning {
background-color: #FEFFD9;
}
+.oe_import .oe_import_error_report ul .oe_import_report_info {
+ background-color: #d3ffd3;
+}
.oe_import .oe_import_noheaders {
color: #888;
@@ -47,7 +52,7 @@
}
.oe_import .oe_import_options label {
display: inline-block;
- width: 10em;
+ width: 8em;
text-align: right;
}
diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js
index c2deb660ff2..33c86e88b2c 100644
--- a/addons/base_import/static/src/js/import.js
+++ b/addons/base_import/static/src/js/import.js
@@ -47,31 +47,35 @@ openerp.base_import = function (instance) {
this._super.apply(this, arguments);
if(add_button) {
this.$buttons.on('click', '.oe_list_button_import', function() {
- new instance.web.DataImport(self, self.dataset).open();
+ self.do_action({
+ type: 'ir.actions.client',
+ tag: 'import',
+ params: {
+ model: self.dataset.model
+ }
+ }, void 0, void 0, function () {
+ self.reload();
+ });
return false;
});
}
}
});
- instance.web.DataImport = instance.web.Dialog.extend({
+ instance.web.client_actions.add(
+ 'import', 'instance.web.DataImport');
+ instance.web.DataImport = instance.web.Widget.extend({
template: 'ImportView',
- dialog_title: _lt("Import Data"),
opts: [
{name: 'encoding', label: _lt("Encoding:"), value: 'utf-8'},
{name: 'separator', label: _lt("Separator:"), value: ','},
{name: 'quoting', label: _lt("Quoting:"), value: '"'}
],
events: {
- 'change .oe_import_grid input': 'import_dryrun',
- 'change input.oe_import_file': 'file_update',
- 'change input.oe_import_has_header, .oe_import_options input': 'settings_updated',
- 'click a.oe_import_csv': function (e) {
- e.preventDefault();
- },
- 'click a.oe_import_export': function (e) {
- e.preventDefault();
- },
+ // 'change .oe_import_grid input': 'import_dryrun',
+ 'change .oe_import_file': 'loaded_file',
+ 'click .oe_import_file_reload': 'loaded_file',
+ 'change input.oe_import_has_header, .oe_import_options input': 'settings_changed',
'click a.oe_import_toggle': function (e) {
e.preventDefault();
var $el = $(e.target);
@@ -79,30 +83,84 @@ openerp.base_import = function (instance) {
? $el.next()
: $el.parent().next())
.toggle();
+ },
+ 'click .oe_import_report a.oe_import_report_count': function (e) {
+ e.preventDefault();
+ $(e.target).parent().toggleClass('oe_import_report_showmore');
+ },
+ 'click .oe_import_moreinfo_action a': function (e) {
+ e.preventDefault();
+ // #data will parse the attribute on its own, we don't like
+ // that sort of things
+ var action = JSON.parse($(e.target).attr('data-action'));
+ // FIXME: when JS-side clean_action
+ action.views = _(action.views).map(function (view) {
+ var id = view[0], type = view[1];
+ return [
+ id,
+ type !== 'tree' ? type
+ : action.view_type === 'form' ? 'list'
+ : 'tree'
+ ];
+ });
+ this.do_action(_.extend(action, {
+ target: 'new',
+ flags: {
+ search_view: true,
+ display_title: true,
+ pager: true,
+ list: {selectable: false}
+ }
+ }));
+ },
+ // buttons
+ 'click .oe_import_validate': 'validate',
+ 'click .oe_import_import': 'import',
+ 'click .oe_import_cancel': function (e) {
+ e.preventDefault();
+ this.exit();
}
},
- init: function (parent, dataset) {
+ init: function (parent, params) {
var self = this;
- this._super(parent, {
- buttons: [
- {text: _t("Import File"), click: function () {
- self.do_import();
- }, 'class': 'oe_import_dialog_button'}
- ]
- });
- this.res_model = parent.model;
+ this._super.apply(this, arguments);
+ this.res_model = params.model;
// import object id
this.id = null;
this.Import = new instance.web.Model('base_import.import');
},
start: function () {
var self = this;
- return this.Import.call('create', [{
- 'res_model': this.res_model
- }]).then(function (id) {
- self.id = id;
- self.$('input[name=import_id]').val(id);
- });
+ this.setup_encoding_picker();
+
+ return $.when(
+ this._super(),
+ this.Import.call('create', [{
+ 'res_model': this.res_model
+ }]).then(function (id) {
+ self.id = id;
+ self.$('input[name=import_id]').val(id);
+ })
+ )
+ },
+ setup_encoding_picker: function () {
+ this.$('input.oe_import_encoding').select2({
+ width: '160px',
+ query: function (q) {
+ var make = function (term) { return {id: term, text: term}; };
+ var suggestions = _.map(
+ ('utf-8 utf-16 windows-1252 latin1 latin2 big5 ' +
+ 'gb18030 shift_jis windows-1251 koir8_r').split(/\s+/),
+ make);
+ if (q.term) {
+ suggestions.unshift(make(q.term));
+ }
+ q.callback({results: suggestions});
+ },
+ initSelection: function (e, c) {
+ return c({id: 'utf-8', text: 'utf-8'});
+ }
+ }).select2('val', 'utf-8');
},
import_options: function () {
@@ -118,34 +176,52 @@ openerp.base_import = function (instance) {
},
//- File & settings change section
- file_update: function (e) {
+ onfile_loaded: function () {
+ this.$('.oe_import_button').prop('disabled', true);
if (!this.$('input.oe_import_file').val()) { return; }
this.$el.removeClass('oe_import_preview oe_import_error');
jsonp(this.$el, {
url: '/base_import/set_file'
- }, this.proxy('settings_updated'));
+ }, this.proxy('settings_changed'));
},
- settings_updated: function () {
+ onpreviewing: function () {
+ var self = this;
+ this.$('.oe_import_button').prop('disabled', true);
this.$el.addClass('oe_import_with_file');
// TODO: test that write // succeeded?
- this.Import.call(
- 'parse_preview', [this.id, this.import_options()])
- .then(this.proxy('preview'));
- },
- preview: function (result) {
+ this.$el.removeClass('oe_import_preview_error oe_import_error');
this.$el.toggleClass(
'oe_import_noheaders',
!this.$('input.oe_import_has_header').prop('checked'));
- if (result.error) {
- this.$el.addClass('oe_import_error');
- this.$('.oe_import_error_report').html(
+ this.Import.call(
+ 'parse_preview', [this.id, this.import_options()])
+ .then(function (result) {
+ var signal = result.error ? 'preview_failed' : 'preview_succeeded';
+ self[signal](result);
+ });
+ },
+ onpreview_error: function (event, from, to, result) {
+ this.$('.oe_import_options').show();
+ this.$el.addClass('oe_import_preview_error oe_import_error');
+ this.$('.oe_import_error_report').html(
QWeb.render('ImportView.preview.error', result));
- return;
- }
+ },
+ onpreview_success: function (event, from, to, result) {
+ this.$('.oe_import_import').removeClass('oe_highlight');
+ this.$('.oe_import_validate').addClass('oe_highlight');
+ this.$('.oe_import_button').prop('disabled', false);
this.$el.addClass('oe_import_preview');
this.$('table').html(QWeb.render('ImportView.preview', result));
+ if (result.headers.length === 1) {
+ this.$('.oe_import_options').show();
+ this.onresults(null, null, null, [{
+ type: 'warning',
+ message: _t("A single column was found in the file, this often means the file separator is incorrect")
+ }]);
+ }
+
var $fields = this.$('.oe_import_fields input');
this.render_fields_matches(result, $fields);
var data = this.generate_fields_completion(result);
@@ -180,7 +256,6 @@ openerp.base_import = function (instance) {
width: 'resolve',
dropdownCssClass: 'oe_import_selector'
});
- this.import_dryrun();
},
generate_fields_completion: function (root) {
var basic = [];
@@ -252,40 +327,116 @@ openerp.base_import = function (instance) {
//- import itself
call_import: function (options) {
- var self = this;
var fields = this.$('.oe_import_fields input.oe_import_match_field').map(function (index, el) {
return $(el).select2('val') || false;
}).get();
return this.Import.call(
'do', [this.id, fields, this.import_options()], options);
},
- import_dryrun: function () {
-// this.call_import({ dryrun: true })
-// .then(this.proxy('render_import_errors'));
+ onvalidate: function () {
+ return this.call_import({ dryrun: true })
+ .then(this.proxy('validated'));
},
- do_import: function () {
+ onimport: function () {
var self = this;
- this.call_import({ dryrun: false }).then(function (errors) {
- if (_.isEmpty(errors)) {
- if (self.getParent().reload_content) {
- self.getParent().reload_content();
- }
- self.close();
+ return this.call_import({ dryrun: false }).then(function (message) {
+ if (!_.any(message, function (message) {
+ return message.type === 'error' })) {
+ self['import_succeeded']();
return;
}
- self.render_import_errors(errors);
+ self['import_failed'](message);
});
},
- render_import_errors: function (errors) {
- if (_.isEmpty(errors)) {
- this.$el.removeClass('oe_import_error');
- return;
+ onimported: function () {
+ this.exit();
+ },
+ exit: function () {
+ this.do_action({
+ type: 'ir.actions.client',
+ tag: 'history_back'
+ });
+ },
+ onresults: function (event, from, to, message) {
+ var no_messages = _.isEmpty(message);
+ this.$('.oe_import_import').toggleClass('oe_highlight', no_messages);
+ this.$('.oe_import_validate').toggleClass('oe_highlight', !no_messages);
+ if (no_messages) {
+ message.push({
+ type: 'info',
+ message: _t("Everything seems valid.")
+ });
}
- // import failed (or maybe just warnings, if we ever get
- // warnings?)
+ // row indexes come back 0-indexed, spreadsheets
+ // display 1-indexed.
+ var offset = 1;
+ // offset more if header
+ if (this.import_options().headers) { offset += 1; }
+
this.$el.addClass('oe_import_error');
this.$('.oe_import_error_report').html(
- QWeb.render('ImportView.error', {errors: errors}));
+ QWeb.render('ImportView.error', {
+ errors: _(message).groupBy('message'),
+ at: function (rows) {
+ var from = rows.from + offset;
+ var to = rows.to + offset;
+ if (from === to) {
+ return _.str.sprintf(_t("at row %d"), from);
+ }
+ return _.str.sprintf(_t("between rows %d and %d"),
+ from, to);
+ },
+ more: function (n) {
+ return _.str.sprintf(_t("(%d more)"), n);
+ },
+ info: function (msg) {
+ if (typeof msg === 'string') {
+ return _.str.sprintf(
+ '
- [[o.employee_id.address_home_id and o.employee_id.address_home_id.name or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.street or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.street2 or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.zip or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.city or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.state_id and o.employee_id.address_home_id.state_id.name or '' ]] [[o.employee_id.address_home_id and o.employee_id.address_home_id.country_id and o.employee_id.address_home_id.country_id.name or '' ]]
+ [[o.employee_id.address_home_id and o.employee_id.address_home_id.name or '' ]]
+ [[o.employee_id.address_home_id and display_address(o.employee_id.address_home_id)]]
@@ -293,7 +294,7 @@
[[ formatLang(p.amount) ]]
- [[ formatLang(p.total) ]] [[o.company_id and o.company_id.currency_id.symbol or '']]
+ [[ formatLang(p.total, currency_obj = o.company_id and o.company_id.currency_id)]]
- [[o.employee_id.address_home_id and o.employee_id.address_home_id.name or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.street or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.street2 or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.zip or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.city or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.state_id and o.employee_id.address_home_id.state_id.name or '' ]] [[o.employee_id.address_home_id and o.employee_id.address_home_id.country_id and o.employee_id.address_home_id.country_id.name or '' ]]
+ [[o.employee_id.address_home_id and o.employee_id.address_home_id.name or '' ]]
+ [[o.employee_id.address_home_id and display_address(o.employee_id.address_home_id)]]
@@ -334,7 +335,7 @@
[[ '..'*h['level'] ]][[ h['rule_category'] ]][[ h['level']!=0 and ( setTag('para','para',{'style':'terp_default_8'})) or removeParentNode('font') ]]
- [[ formatLang(h['total']) ]] [[o.company_id and o.company_id.currency_id.symbol or '']] [[ h['level']==0 and ( setTag('para','para',{'style':'terp_default_10'})) or removeParentNode('font') ]]
+ [[ formatLang(h['total'], currency_obj = o.company_id and o.company_id.currency_id)]] [[ h['level']==0 and ( setTag('para','para',{'style':'terp_default_10'})) or removeParentNode('font') ]]
@@ -391,7 +392,7 @@
[[ formatLang(r['amount']) ]]
- [[ formatLang(r['total']) ]] [[ o.company_id and o.company_id.currency_id.symbol or '']][[ r.get('register_name', False) and ( setTag('para','para',{'style':'terp_default_10'})) or removeParentNode('font')]]
+ [[ formatLang(r['total'], currency_obj = o.company_id and o.company_id.currency_id)]][[ r.get('register_name', False) and ( setTag('para','para',{'style':'terp_default_10'})) or removeParentNode('font')]]
diff --git a/addons/hr_payroll_account/hr_payroll_account.py b/addons/hr_payroll_account/hr_payroll_account.py
index 184f9a06867..94df47f6e44 100644
--- a/addons/hr_payroll_account/hr_payroll_account.py
+++ b/addons/hr_payroll_account/hr_payroll_account.py
@@ -36,7 +36,7 @@ class hr_payslip(osv.osv):
_columns = {
'period_id': fields.many2one('account.period', 'Force Period',states={'draft': [('readonly', False)]}, readonly=True, domain=[('state','<>','done')], help="Keep empty to use the period of the validation(Payslip) date."),
- 'journal_id': fields.many2one('account.journal', 'Expense Journal',states={'draft': [('readonly', False)]}, readonly=True, required=True),
+ 'journal_id': fields.many2one('account.journal', 'Salary Journal',states={'draft': [('readonly', False)]}, readonly=True, required=True),
'move_id': fields.many2one('account.move', 'Accounting Entry', readonly=True),
}
@@ -215,7 +215,7 @@ class hr_payslip_run(osv.osv):
_inherit = 'hr.payslip.run'
_description = 'Payslip Run'
_columns = {
- 'journal_id': fields.many2one('account.journal', 'Expense Journal', states={'draft': [('readonly', False)]}, readonly=True, required=True),
+ 'journal_id': fields.many2one('account.journal', 'Salary Journal', states={'draft': [('readonly', False)]}, readonly=True, required=True),
}
def _get_default_journal(self, cr, uid, context=None):
diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py
index ccfcae0d26e..56c517620e0 100644
--- a/addons/hr_recruitment/hr_recruitment.py
+++ b/addons/hr_recruitment/hr_recruitment.py
@@ -297,7 +297,6 @@ class hr_applicant(base_stage, osv.Model):
res['context'] = {
'default_partner_ids': applicant.partner_id and [applicant.partner_id.id] or False,
'default_user_id': uid,
- 'default_state': 'open',
'default_name': applicant.name,
'default_categ_ids': category and [category.id] or False,
}
diff --git a/addons/hr_recruitment/hr_recruitment_view.xml b/addons/hr_recruitment/hr_recruitment_view.xml
index d48086f5663..d6d04c1b969 100644
--- a/addons/hr_recruitment/hr_recruitment_view.xml
+++ b/addons/hr_recruitment/hr_recruitment_view.xml
@@ -289,7 +289,8 @@
diff --git a/addons/l10n_be_hr_payroll/i18n/pt_BR.po b/addons/l10n_be_hr_payroll/i18n/pt_BR.po
new file mode 100644
index 00000000000..2c4f688842a
--- /dev/null
+++ b/addons/l10n_be_hr_payroll/i18n/pt_BR.po
@@ -0,0 +1,162 @@
+# Brazilian Portuguese translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2012-02-08 00:36+0000\n"
+"PO-Revision-Date: 2012-10-16 23:34+0000\n"
+"Last-Translator: Syllas F. de O. Neto \n"
+"Language-Team: Brazilian Portuguese \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-10-17 04:36+0000\n"
+"X-Generator: Launchpad (build 16152)\n"
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,disabled_spouse_bool:0
+msgid "if recipient spouse is declared disabled by law"
+msgstr "Caso o cônjuge beneficiário seja considerado incapaz perante a lei"
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,disabled_children_bool:0
+msgid "if recipient children is/are declared disabled by law"
+msgstr ""
+"Caso o(s) filho(s) beneficiário(s) seja(m) considerado(s) incapaz(es) "
+"perante a lei"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,misc_onss_deduction:0
+msgid "Miscellaneous exempt ONSS "
+msgstr "Outros isentos de INSS "
+
+#. module: l10n_be_hr_payroll
+#: model:ir.model,name:l10n_be_hr_payroll.model_hr_employee
+msgid "Employee"
+msgstr "Empregado"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_spouse_bool:0
+msgid "Disabled Spouse"
+msgstr "Cõnjuge incapaz"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,retained_net_amount:0
+msgid "Net retained "
+msgstr "Líquido retido "
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,resident_bool:0
+msgid "Nonresident"
+msgstr "Não residente no país local"
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,resident_bool:0
+msgid "if recipient lives in a foreign country"
+msgstr "Caso o beneficiário resida em outro país"
+
+#. module: l10n_be_hr_payroll
+#: view:hr.employee:0
+msgid "if spouse has professionnel income or not"
+msgstr "Caso o cônjuge possua renda"
+
+#. module: l10n_be_hr_payroll
+#: view:hr.contract:0
+msgid "Miscellaneous"
+msgstr "Outros"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,insurance_employee_deduction:0
+msgid "Insurance Group - by worker "
+msgstr "Categoria do Seguro - por empregado "
+
+#. module: l10n_be_hr_payroll
+#: selection:hr.employee,spouse_fiscal_status:0
+msgid "With Income"
+msgstr "Com renda"
+
+#. module: l10n_be_hr_payroll
+#: selection:hr.employee,spouse_fiscal_status:0
+msgid "Without Income"
+msgstr "Sem renda"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_children_number:0
+msgid "Number of disabled children"
+msgstr "Quantidade de filho(s) incapaz(es)"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,additional_net_amount:0
+msgid "Net supplements"
+msgstr "Renda suplementar"
+
+#. module: l10n_be_hr_payroll
+#: constraint:hr.employee:0
+msgid "Error ! You cannot create recursive Hierarchy of Employees."
+msgstr "Erro! Você não pode criar uma Hierarquia de Empregados recursiva."
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,car_company_amount:0
+msgid "Company car employer"
+msgstr "Carro da empresa"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,misc_advantage_amount:0
+msgid "Benefits of various nature "
+msgstr "Benefícios de outras naturezas "
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,car_employee_deduction:0
+msgid "Company Car Deduction for Worker"
+msgstr "Dedução referente ao carro da empresa"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_children_bool:0
+msgid "Disabled Children"
+msgstr "Filho(s) incapaz(es)"
+
+#. module: l10n_be_hr_payroll
+#: model:ir.model,name:l10n_be_hr_payroll.model_hr_contract
+msgid "Contract"
+msgstr "Contrato"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,meal_voucher_amount:0
+msgid "Check Value Meal "
+msgstr "Vale refeição "
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,travel_reimbursement_amount:0
+msgid "Reimbursement of travel expenses"
+msgstr "Reembolso de despeza de viagem"
+
+#. module: l10n_be_hr_payroll
+#: constraint:hr.contract:0
+msgid "Error! contract start-date must be lower then contract end-date."
+msgstr ""
+"Erro! A data de início do contrato deve ser menor que a data de término do "
+"contrato."
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,spouse_fiscal_status:0
+msgid "Tax status for spouse"
+msgstr "Situação fiscal do cônjuge"
+
+#. module: l10n_be_hr_payroll
+#: view:hr.contract:0
+msgid "by Worker"
+msgstr "por Empregado"
+
+#. module: l10n_be_hr_payroll
+#: view:hr.employee:0
+msgid "number of dependent children declared as disabled"
+msgstr "Quantidade de filhos declarados como incapazes"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,meal_voucher_employee_deduction:0
+msgid "Check Value Meal - by worker "
+msgstr "Vale refeição - por empregado "
diff --git a/addons/l10n_ch/sterchi_chart/account.xml b/addons/l10n_ch/sterchi_chart/account.xml
index b04031d42ce..bd848642a97 100644
--- a/addons/l10n_ch/sterchi_chart/account.xml
+++ b/addons/l10n_ch/sterchi_chart/account.xml
@@ -11807,7 +11807,6 @@
-
diff --git a/addons/l10n_cn/account_chart.xml b/addons/l10n_cn/account_chart.xml
index e51a9d70654..afcb3e04b0c 100644
--- a/addons/l10n_cn/account_chart.xml
+++ b/addons/l10n_cn/account_chart.xml
@@ -957,7 +957,6 @@
-
diff --git a/addons/l10n_cn/i18n/pt_BR.po b/addons/l10n_cn/i18n/pt_BR.po
index 68670229801..64e1f8cc066 100644
--- a/addons/l10n_cn/i18n/pt_BR.po
+++ b/addons/l10n_cn/i18n/pt_BR.po
@@ -8,29 +8,29 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME \n"
"POT-Creation-Date: 2011-12-23 09:56+0000\n"
-"PO-Revision-Date: 2011-03-09 22:08+0000\n"
-"Last-Translator: Emerson \n"
+"PO-Revision-Date: 2012-10-16 23:56+0000\n"
+"Last-Translator: Syllas F. de O. Neto \n"
"Language-Team: Brazilian Portuguese \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-08-28 06:42+0000\n"
-"X-Generator: Launchpad (build 15864)\n"
+"X-Launchpad-Export-Date: 2012-10-17 04:36+0000\n"
+"X-Generator: Launchpad (build 16152)\n"
#. module: l10n_cn
#: model:account.account.type,name:l10n_cn.user_type_profit_and_loss
msgid "损益类"
-msgstr ""
+msgstr "Categoria Lucro ou Prejuízo"
#. module: l10n_cn
#: model:account.account.type,name:l10n_cn.user_type_all
msgid "所有科目"
-msgstr ""
+msgstr "Todos os assuntos"
#. module: l10n_cn
#: model:account.account.type,name:l10n_cn.user_type_equity
msgid "所有者权益类"
-msgstr ""
+msgstr "Capital Próprio"
#. module: l10n_cn
#: model:ir.actions.todo,note:l10n_cn.config_call_account_template_cn_chart
@@ -43,28 +43,28 @@ msgid ""
"Management/Configuration/Financial Accounting/Financial Accounts/Generate "
"Chart of Accounts from a Chart Template."
msgstr ""
-"Generate Chart of Accounts from a Chart Template. You will be asked to pass "
-"the name of the company, the chart template to follow, the no. of digits to "
-"generate the code for your accounts and Bank account, currency to create "
-"Journals. Thus,the pure copy of chart Template is generated.\n"
-"\tThis is the same wizard that runs from Financial "
-"Management/Configuration/Financial Accounting/Financial Accounts/Generate "
-"Chart of Accounts from a Chart Template."
+"Gerar Gráfico de Contas apartir de um modelo. Você deverá informar o nome da "
+"empresa, o gráfico modelo, o número de dígitos para gerar o código para suas "
+"contas, a conta bancária e a moeda para gerar a sequência. Em seguida uma "
+"cópia do gráfico modelo é gerada.\n"
+"Este é o mesmo assistente que é executado a partir de Gerenciamento "
+"Financeiro/Configuração/Contabilidade Financeira/Contas Financeiras/Gerar "
+"Gráfico de Contas a partir de um Gráfico Modelo."
#. module: l10n_cn
#: model:account.account.type,name:l10n_cn.user_type_debt
msgid "负债类"
-msgstr ""
+msgstr "Classe Passivos"
#. module: l10n_cn
#: model:account.account.type,name:l10n_cn.user_type_cost
msgid "成本类"
-msgstr ""
+msgstr "Custo da Classe"
#. module: l10n_cn
#: model:account.account.type,name:l10n_cn.user_type_capital
msgid "资产类"
-msgstr ""
+msgstr "Classe Ativos"
#~ msgid "中国会计科目表"
#~ msgstr "中国会计科目表"
diff --git a/addons/l10n_fr/fr_pcg_taxes.xml b/addons/l10n_fr/fr_pcg_taxes.xml
index b44d04439f0..78b34f2d696 100644
--- a/addons/l10n_fr/fr_pcg_taxes.xml
+++ b/addons/l10n_fr/fr_pcg_taxes.xml
@@ -441,7 +441,6 @@
-
diff --git a/addons/l10n_fr_hr_payroll/report/fiche_paye.rml b/addons/l10n_fr_hr_payroll/report/fiche_paye.rml
index 5221b00c462..76c6eb9dedf 100644
--- a/addons/l10n_fr_hr_payroll/report/fiche_paye.rml
+++ b/addons/l10n_fr_hr_payroll/report/fiche_paye.rml
@@ -290,9 +290,7 @@
[[o.employee_id.name or '_']]
- [[o.employee_id.address_home_id.street or '_' ]]
- [[o.employee_id.address_home_id.street2 or '' ]]
- [[o.employee_id.address_home_id.zip or '_' ]] [[o.employee_id.address_home_id.city or '' ]]
+ [[display_address(o.employee_id.address_home_id) or '_' ]]
- [[o.employee_id.address_home_id and o.employee_id.address_home_id.name or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.street or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.street2 or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.zip or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.city or '' ]],[[o.employee_id.address_home_id and o.employee_id.address_home_id.state_id and o.employee_id.address_home_id.state_id.name or '' ]] [[o.employee_id.address_home_id and o.employee_id.address_home_id.country_id and o.employee_id.address_home_id.country_id.name or '' ]]
+ [[o.employee_id.address_home_id and o.employee_id.address_home_id.name or '' ]],[[o.employee_id.address_home_id and display_address(o.employee_id.address_home_id)]]
@@ -334,7 +334,7 @@
[[ '..'*h['level'] ]][[ h['rule_category'] ]][[ h['level']!=0 and ( setTag('para','para',{'style':'terp_default_8'})) or removeParentNode('font') ]]
- [[ formatLang(h['total']) ]] [[o.company_id and o.company_id.currency_id.symbol or '']] [[ h['level']==0 and ( setTag('para','para',{'style':'terp_default_10'})) or removeParentNode('font') ]]
+ [[ formatLang(h['total'], currency_obj = o.company_id and o.company_id.currency_id)]] [[ h['level']==0 and ( setTag('para','para',{'style':'terp_default_10'})) or removeParentNode('font') ]]
When you sell this product, OpenERP will trigger a manufacturing
order using the bill of materials assigned to this product.
The delivery order will be ready once the production is done.
-
+
@@ -1037,6 +1038,7 @@
{'default_product_id': active_id, 'search_default_product_id': active_id}Bill of Materials
+ [('bom_id','=',False)]mrp.bom
@@ -1050,7 +1052,5 @@
-
-
diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py
index 795ac5453fb..19f8a48b6fe 100644
--- a/addons/mrp/procurement.py
+++ b/addons/mrp/procurement.py
@@ -31,6 +31,7 @@ class procurement_order(osv.osv):
_columns = {
'bom_id': fields.many2one('mrp.bom', 'BoM', ondelete='cascade', select=True),
'property_ids': fields.many2many('mrp.property', 'procurement_property_rel', 'procurement_id','property_id', 'Properties'),
+ 'production_id': fields.many2one('mrp.production', 'Manufacturing Order'),
}
def check_produce_product(self, cr, uid, procurement, context=None):
@@ -95,16 +96,22 @@ class procurement_order(osv.osv):
'move_prod_id': res_id,
'company_id': procurement.company_id.id,
})
+
res[procurement.id] = produce_id
- self.write(cr, uid, [procurement.id], {'state': 'running'})
- self.running_send_note(cr, uid, ids, context=context)
+ self.write(cr, uid, [procurement.id], {'state': 'running', 'production_id': produce_id})
bom_result = production_obj.action_compute(cr, uid,
[produce_id], properties=[x.id for x in procurement.property_ids])
wf_service.trg_validate(uid, 'mrp.production', produce_id, 'button_confirm', cr)
if res_id:
move_obj.write(cr, uid, [res_id],
{'location_id': procurement.location_id.id})
+ self.production_order_create_note(cr, uid, ids, context=context)
return res
+
+ def production_order_create_note(self, cr, uid, ids, context=None):
+ for procurement in self.browse(cr, uid, ids, context=context):
+ body = _("Manufacturing Order created.")
+ self.message_post(cr, uid, [procurement.id], body=body, context=context)
procurement_order()
diff --git a/addons/mrp_operations/report/mrp_workorder_analysis_view.xml b/addons/mrp_operations/report/mrp_workorder_analysis_view.xml
index cca9a7e3b24..de486face78 100644
--- a/addons/mrp_operations/report/mrp_workorder_analysis_view.xml
+++ b/addons/mrp_operations/report/mrp_workorder_analysis_view.xml
@@ -9,7 +9,7 @@
mrp.workorder.treemrp.workorder
-
+
diff --git a/addons/mrp_repair/i18n/pt_BR.po b/addons/mrp_repair/i18n/pt_BR.po
index cf9c24dd2bd..d194c9c48aa 100644
--- a/addons/mrp_repair/i18n/pt_BR.po
+++ b/addons/mrp_repair/i18n/pt_BR.po
@@ -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:36+0000\n"
-"PO-Revision-Date: 2012-05-10 18:03+0000\n"
-"Last-Translator: Adriano Prado \n"
+"PO-Revision-Date: 2012-10-17 00:28+0000\n"
+"Last-Translator: Syllas F. de O. Neto \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-08-28 06:29+0000\n"
-"X-Generator: Launchpad (build 15864)\n"
+"X-Launchpad-Export-Date: 2012-10-17 04:36+0000\n"
+"X-Generator: Launchpad (build 16152)\n"
#. module: mrp_repair
#: view:mrp.repair:0
@@ -35,6 +35,15 @@ msgid ""
"* The 'Done' state is set when repairing is completed. \n"
"* The 'Cancelled' state is used when user cancel repair order."
msgstr ""
+" * 'Provisória' é usada quando um usuário está preparando uma nova ordem de "
+"reparo não confirmada.\n"
+"* 'Confirmada' é usado quando o usuário confirma a ordem de reparo.\n"
+"* 'Pronto para Reparo\" é usado para iniciar o reparo, o usuário pode "
+"começar a reparar somente após a confirmação da ordem de reparo.\n"
+"* 'Faturar' é usado para gerar a fatura antes ou após o reparo feito.\n"
+"* 'Concluído' é definido quando o reparo finalizar.\n"
+"* O 'Cancelado' estado é usado quando o usuário cancelar a ordem de "
+"reparação."
#. module: mrp_repair
#: field:mrp.repair.line,move_id:0
@@ -179,7 +188,7 @@ msgstr "Atenção !"
#. module: mrp_repair
#: report:repair.order:0
msgid "Tax"
-msgstr ""
+msgstr "Imposto"
#. module: mrp_repair
#: view:mrp.repair:0
@@ -312,6 +321,12 @@ msgid ""
" \n"
"* The 'Cancelled' state is set automatically when user cancel repair order."
msgstr ""
+" * 'Provisório' é definido automaticamente, quando a ordem de reparo está em "
+"situação provisória.\n"
+"* 'Confirmado' é definido automaticamente quando a ordem for confirmada.\n"
+"* 'Concluído' é definido automaticamente quando o reparo estiver concluído.\n"
+"* 'Cancelado' é definido automaticamente quando o usuário cancelar a ordem "
+"de reparos."
#. module: mrp_repair
#: report:repair.order:0
diff --git a/addons/mrp_repair/report/order.rml b/addons/mrp_repair/report/order.rml
index be5737d4b85..202ed6e4684 100644
--- a/addons/mrp_repair/report/order.rml
+++ b/addons/mrp_repair/report/order.rml
@@ -312,7 +312,7 @@
[[ formatLang(line.price_unit) ]]
- [[ formatLang(pos_payment_user_total(data['form'])) or removeParentNode('blockTable')]] [[company.currency_id.symbol]]
+ [[ formatLang(pos_payment_user_total(data['form'], currency_obj = company.currency_id)) or removeParentNode('blockTable')]]
diff --git a/addons/point_of_sale/report/pos_receipt.rml b/addons/point_of_sale/report/pos_receipt.rml
index 55873887210..d7b8b08ad29 100644
--- a/addons/point_of_sale/report/pos_receipt.rml
+++ b/addons/point_of_sale/report/pos_receipt.rml
@@ -72,8 +72,7 @@
[[ repeatIn(objects,'o') ]][[o.user_id.company_id.name]]
- [[ address and address.street ]], [[ address and address.zip ]] [[ address and address.city ]]
- [[ address and address.country_id.name ]]
+ [[ address and display_address(address)]]Tel : [[ address and address.phone ]]User : [[ o.user_id.name ]]Shop : [[ o.shop_id.name ]]
@@ -109,7 +108,7 @@
[[o.state=='cancel' and o.statement_ids and '-' or '']][['%.f' % line.qty ]]
- [[o.state=='cancel' and o.statement_ids and '-' or '']][[ '%.2f' % net(line.id) ]] [[company.currency_id.symbol]] [[ line and line.discount == 0.0 and removeParentNode('font') ]] ([[ '%.2f' % line.discount ]]%) [[company.currency_id.symbol]]
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][[ formatLang(net(line.id), currency_obj=company.currency_id) ]] [[ line and line.discount == 0.0 and removeParentNode('font') ]] ([[ formatLang(line.discount, currency_obj=company.currency_id) ]])
@@ -119,7 +118,7 @@
Taxes :
- [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.2f' % o.amount_tax]] [[company.currency_id.symbol]]
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][[formatLang(o.amount_tax, currency_obj=company.currency_id)]]
@@ -129,7 +128,7 @@
Total :
- [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.2f' % o.amount_total]] [[company.currency_id.symbol]]
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][[formatLang(o.amount_total, currency_obj=company.currency_id)]]
@@ -158,7 +157,7 @@
- [[ '%.2f' %(d['amt'] or 0) ]] [[company.currency_id.symbol]]
+ [[ formatLang(d['amt'] or 0, currency_obj=company.currency_id) ]]
diff --git a/addons/process/static/src/js/process.js b/addons/process/static/src/js/process.js
index c593c1569fc..c214dbb0fdf 100644
--- a/addons/process/static/src/js/process.js
+++ b/addons/process/static/src/js/process.js
@@ -216,13 +216,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],
- function(res) {
+ ['action', 'tree_but_open',[['ir.ui.menu', id]], dataset.context]).then(function(res) {
var action = res[0][res[0].length - 1];
self.rpc("/web/action/load", {
action_id: action.id,
context: dataset.context
- }, function(result) {
+ }).then(function(result) {
action_manager.replace(self.$el);
action_manager.do_action(result.result);
})
@@ -239,7 +238,7 @@ instance.web.ViewManager.include({
title: _t('Process')
});
var form_controller = pop.view_form;
- pop.on('on_write_complete', self, self.initialize_process_view);
+ pop.on('write_completed', self, self.initialize_process_view);
}
});
};
diff --git a/addons/procurement/__openerp__.py b/addons/procurement/__openerp__.py
index a1aed1dfba8..48569fa76c4 100644
--- a/addons/procurement/__openerp__.py
+++ b/addons/procurement/__openerp__.py
@@ -57,7 +57,7 @@ depending on the product's configuration.
'company_view.xml',
'board_mrp_procurement_view.xml',
],
- 'demo': ['stock_orderpoint.xml'],
+ 'demo': ['stock_orderpoint.xml','procurement_demo.xml'],
'test': ['test/procurement.yml'],
'installable': True,
'auto_install': True,
diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py
index 5d81bcbb9ba..b21cef30773 100644
--- a/addons/procurement/procurement.py
+++ b/addons/procurement/procurement.py
@@ -102,7 +102,6 @@ class procurement_order(osv.osv):
'procure_method': fields.selection([('make_to_stock','Make to Stock'),('make_to_order','Make to Order')], 'Procurement Method', states={'draft':[('readonly',False)], 'confirmed':[('readonly',False)]},
readonly=True, required=True, help="If you encode manually a Procurement, you probably want to use" \
" a make to order method."),
-
'note': fields.text('Note'),
'message': fields.char('Latest error', size=124, help="Exception occurred while computing procurement orders."),
'state': fields.selection([
@@ -362,11 +361,10 @@ class procurement_order(osv.osv):
""" Changes procurement state to Running and writes message.
@return: True
"""
- message = _('From stock: products assigned.')
+ message = _('Products reserved from stock.')
self.write(cr, uid, ids, {'state': 'running',
'message': message}, context=context)
self.message_post(cr, uid, ids, body=message, context=context)
- self.running_send_note(cr, uid, ids, context=context)
return True
def _check_make_to_stock_service(self, cr, uid, procurement, context=None):
@@ -390,8 +388,6 @@ class procurement_order(osv.osv):
order_point_id = self.pool.get('stock.warehouse.orderpoint').search(cr, uid, [('product_id', '=', procurement.product_id.id)], context=context)
if not order_point_id and not ok:
message = _("Not enough stock and no minimum orderpoint rule defined.")
- elif not order_point_id:
- message = _("No minimum orderpoint rule defined.")
elif not ok:
message = _("Not enough stock.")
@@ -407,7 +403,6 @@ class procurement_order(osv.osv):
"""
for procurement in self.browse(cr, uid, ids, context=context):
self.write(cr, uid, [procurement.id], {'state': 'running'})
- self.running_send_note(cr, uid, ids, context=None)
return True
def action_produce_assign_product(self, cr, uid, ids, context=None):
@@ -469,7 +464,6 @@ class procurement_order(osv.osv):
@return: True
"""
res = self.write(cr, uid, ids, {'state': 'ready'})
- self.ready_send_note(cr, uid, ids, context=None)
return res
def action_done(self, cr, uid, ids):
@@ -503,12 +497,6 @@ class procurement_order(osv.osv):
def confirm_send_note(self, cr, uid, ids, context=None):
self.message_post(cr, uid, ids, body=_("Procurement confirmed."), context=context)
- def running_send_note(self, cr, uid, ids, context=None):
- self.message_post(cr, uid, ids, body=_("Procurement set to running."), context=context)
-
- def ready_send_note(self, cr, uid, ids, context=None):
- self.message_post(cr, uid, ids, body=_("Procurement set to ready."), context=context)
-
def cancel_send_note(self, cr, uid, ids, context=None):
self.message_post(cr, uid, ids, body=_("Procurement cancelled."), context=context)
@@ -641,7 +629,18 @@ class stock_warehouse_orderpoint(osv.osv):
})
return super(stock_warehouse_orderpoint, self).copy(cr, uid, id, default, context=context)
-stock_warehouse_orderpoint()
+class product_template(osv.osv):
+ _inherit="product.template"
+
+ _columns = {
+ 'type': fields.selection([('product','Stockable Product'),('consu', 'Consumable'),('service','Service')], 'Product Type', required=True, help="Will change the way procurements are processed. Consumable are product where you don't manage stock, a service is a non-material product provided by a company or an individual."),
+ 'procure_method': fields.selection([('make_to_stock','Make to Stock'),('make_to_order','Make to Order')], 'Procurement Method', required=True, help="'Make to Stock': When needed, take from the stock or wait until re-supplying. 'Make to Order': When needed, purchase or produce for the procurement request."),
+ 'supply_method': fields.selection([('produce','Manufacture'),('buy','Buy')], 'Supply Method', required=True, help="Produce will generate production order or tasks, according to the product type. Buy will trigger purchase orders when requested."),
+ }
+ _defaults = {
+ 'procure_method': 'make_to_stock',
+ 'supply_method': 'buy',
+ }
class product_product(osv.osv):
_inherit="product.product"
@@ -649,6 +648,6 @@ class product_product(osv.osv):
'orderpoint_ids': fields.one2many('stock.warehouse.orderpoint', 'product_id', 'Minimum Stock Rules'),
}
-product_product()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/procurement/procurement_demo.xml b/addons/procurement/procurement_demo.xml
new file mode 100644
index 00000000000..608eb56f3ba
--- /dev/null
+++ b/addons/procurement/procurement_demo.xml
@@ -0,0 +1,204 @@
+
+
+
+
+
+ make_to_order
+ produce
+
+
+
+ make_to_order
+ produce
+
+
+
+ product
+ make_to_order
+ produce
+
+
+
+ product
+ make_to_order
+ produce
+
+
+
+ product
+ make_to_order
+ produce
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+ make_to_order
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+ make_to_order
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+ make_to_order
+ produce
+
+
+
+ product
+
+
+
+ product
+ make_to_order
+ produce
+
+
+
+ product
+ make_to_order
+ produce
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+ make_to_order
+ produce
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+ make_to_order
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+ make_to_order
+
+
+
+ product
+
+
+
+ product
+
+
+
+ make_to_order
+ produce
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+ product
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/procurement/procurement_view.xml b/addons/procurement/procurement_view.xml
index bf73b383216..973a09477fc 100644
--- a/addons/procurement/procurement_view.xml
+++ b/addons/procurement/procurement_view.xml
@@ -294,6 +294,29 @@
stock.warehouse.orderpoint
+
+ product.template.procurement
+ product.template
+
+
+
+
+
+
+
+
+
+
+ product.search.procurment.form
+ product.product
+
+
+
+
+
+
+
+
product.product.procurementproduct.product
@@ -303,6 +326,33 @@
+
+
+
+
+
+
+
+ When you sell this service, nothing special will be triggered
+ to deliver the customer, as you set the procurement method as
+ 'Make to Stock'.
+
+
+ When you sell this product, OpenERP will use the available
+ inventory for the delivery order.
+
+ If there are not enough quantities available, the delivery order
+ will wait for new products. To fulfill the inventory, you should
+ create others rules like orderpoints.
+
+
+ When you sell this product, a delivery order will be created.
+ OpenERP will consider that the required quantities are always
+ available as it's a consumable (as a result of this, the quantity
+ on hand may become negative).
+
+
+
diff --git a/addons/product/product.py b/addons/product/product.py
index d5acee0333b..6c6c5f2650c 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -109,8 +109,8 @@ class product_uom(osv.osv):
_order = "name"
_columns = {
- 'name': fields.char('Name', size=64, required=True, translate=True),
- 'category_id': fields.many2one('product.uom.categ', 'Unit of Measure Category', required=True, ondelete='cascade',
+ 'name': fields.char('Unit of Measure', size=64, required=True, translate=True),
+ 'category_id': fields.many2one('product.uom.categ', 'Category', required=True, ondelete='cascade',
help="Quantity conversions may happen automatically between Units of Measure in the same category, according to their respective ratios."),
'factor': fields.float('Ratio', required=True,digits=(12, 12),
help='How many times this Unit of Measure is smaller than the reference Unit of Measure in this category:\n'\
@@ -126,7 +126,7 @@ class product_uom(osv.osv):
'active': fields.boolean('Active', help="By unchecking the active field you can disable a unit of measure without deleting it."),
'uom_type': fields.selection([('bigger','Bigger than the reference Unit of Measure'),
('reference','Reference Unit of Measure for this category'),
- ('smaller','Smaller than the reference Unit of Measure')],'Unit of Measure Type', required=1),
+ ('smaller','Smaller than the reference Unit of Measure')],'Type', required=1),
}
_defaults = {
@@ -280,11 +280,8 @@ class product_template(osv.osv):
'description': fields.text('Description',translate=True),
'description_purchase': fields.text('Purchase Description',translate=True),
'description_sale': fields.text('Sale Description',translate=True),
- 'type': fields.selection([('product','Stockable Product'),('consu', 'Consumable'),('service','Service')], 'Product Type', required=True, help="Will change the way procurements are processed. Consumable are product where you don't manage stock."),
- 'supply_method': fields.selection([('produce','Manufacture'),('buy','Buy')], 'Supply Method', required=True, help="Produce will generate production order or tasks, according to the product type. Buy will trigger purchase orders when requested."),
- 'sale_delay': fields.float('Customer Lead Time', help="This is the average delay in days between the confirmation of the customer order and the delivery of the finished products. It's the time you promise to your customers."),
+ 'type': fields.selection([('consu', 'Consumable'),('service','Service')], 'Product Type', required=True, help="Consumable are product where you don't manage stock, a service is a non-material product provided by a company or an individual."),
'produce_delay': fields.float('Manufacturing Lead Time', help="Average delay in days to produce this product. This is only for the production order and, if it is a multi-level bill of material, it's only for the level of this product. Different lead times will be summed for all levels and purchase orders."),
- 'procure_method': fields.selection([('make_to_stock','Make to Stock'),('make_to_order','Make to Order')], 'Procurement Method', required=True, help="'Make to Stock': When needed, take from the stock or wait until re-supplying. 'Make to Order': When needed, purchase or produce for the procurement request."),
'rental': fields.boolean('Can be Rent'),
'categ_id': fields.many2one('product.category','Category', required=True, change_default=True, domain="[('type','=','normal')]" ,help="Select category for the current product"),
'list_price': fields.float('Sale Price', digits_compute=dp.get_precision('Product Price'), help="Base price for computing the customer price. Sometimes called the catalog price."),
@@ -296,7 +293,6 @@ class product_template(osv.osv):
help="Standard Price: the cost price is fixed and recomputed periodically (usually at the end of the year), Average Price: the cost price is recomputed at each reception of products."),
'warranty': fields.float('Warranty'),
'sale_ok': fields.boolean('Can be Sold', help="Determines if the product can be visible in the list of product within a selection from a sale order line."),
- 'purchase_ok': fields.boolean('Can be Purchased', help="Determine if the product is visible in the list of products within a selection from a purchase order line."),
'state': fields.selection([('',''),
('draft', 'In Development'),
('sellable','Normal'),
@@ -309,11 +305,8 @@ class product_template(osv.osv):
'uos_coeff': fields.float('Unit of Measure -> UOS Coeff', digits_compute= dp.get_precision('Product UoS'),
help='Coefficient to convert Unit of Measure to UOS\n'
' uos = uom * coeff'),
- 'mes_type': fields.selection((('fixed', 'Fixed'), ('variable', 'Variable')), 'Measure Type', required=True),
+ 'mes_type': fields.selection((('fixed', 'Fixed'), ('variable', 'Variable')), 'Measure Type'),
'seller_ids': fields.one2many('product.supplierinfo', 'product_id', 'Partners'),
- 'loc_rack': fields.char('Rack', size=16),
- 'loc_row': fields.char('Row', size=16),
- 'loc_case': fields.char('Case', size=16),
'company_id': fields.many2one('res.company', 'Company', select=1),
}
@@ -351,21 +344,17 @@ class product_template(osv.osv):
_defaults = {
'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'product.template', context=c),
- 'list_price': lambda *a: 1,
- 'cost_method': lambda *a: 'standard',
- 'supply_method': lambda *a: 'buy',
- 'standard_price': lambda *a: 0.0,
- 'sale_ok': lambda *a: 1,
- 'sale_delay': lambda *a: 7,
- 'produce_delay': lambda *a: 1,
- 'purchase_ok': lambda *a: 1,
- 'procure_method': lambda *a: 'make_to_stock',
+ 'list_price': 1,
+ 'cost_method': 'standard',
+ 'standard_price': 0.0,
+ 'sale_ok': 1,
+ 'produce_delay': 1,
'uom_id': _get_uom_id,
'uom_po_id': _get_uom_id,
- 'uos_coeff' : lambda *a: 1.0,
- 'mes_type' : lambda *a: 'fixed',
+ 'uos_coeff' : 1.0,
+ 'mes_type' : 'fixed',
'categ_id' : _default_category,
- 'type' : lambda *a: 'consu',
+ 'type' : 'consu',
}
def _check_uom(self, cursor, user, ids, context=None):
diff --git a/addons/product/product_data.xml b/addons/product/product_data.xml
index 1974acc6df2..8e5280d036a 100644
--- a/addons/product/product_data.xml
+++ b/addons/product/product_data.xml
@@ -197,7 +197,6 @@ parameter) will see those record just disappear.
Serviceservice
-
diff --git a/addons/product/product_demo.xml b/addons/product/product_demo.xml
index 66b86fc7b63..14477d2401a 100644
--- a/addons/product/product_demo.xml
+++ b/addons/product/product_demo.xml
@@ -70,8 +70,6 @@
20.530.75service
- make_to_order
- produceThis type of service include basic monitoring of products.
@@ -84,8 +82,6 @@
25.538.25service
- make_to_order
- produceThis type of service include assistance for security questions, system configuration requirements, implementation or special needs.
@@ -97,9 +93,7 @@
450.0300.0
- product
- make_to_order
- produce
+ consu4.0
@@ -115,9 +109,8 @@ HDD SH-1500.0750.0
- product
- make_to_order
- produce
+ consu
+
4.0
@@ -133,9 +126,7 @@ HDD SH-1600.0900.0
- product
- make_to_order
- produce
+ consu7.0
@@ -148,7 +139,7 @@ HDD SH-1800.01200.0
- product
+ consu
@@ -158,7 +149,7 @@ HDD SH-1
880.01350.0
- product
+ consu
@@ -168,7 +159,7 @@ HDD SH-1
10.013.0
- product
+ consu
@@ -178,8 +169,7 @@ HDD SH-1
10.013.0
- product
- make_to_order
+ consu
@@ -189,7 +179,7 @@ HDD SH-1
12.5014
- product
+ consu
@@ -199,7 +189,7 @@ HDD SH-1
1416.50
- product
+ consu
@@ -209,8 +199,7 @@ HDD SH-1
1812.50
- product
- make_to_order
+ consu
@@ -220,7 +209,7 @@ HDD SH-1
78.085.0
- product
+ consu
@@ -230,7 +219,7 @@ HDD SH-1
87.095.0
- product
+ consu
@@ -240,7 +229,7 @@ HDD SH-1
80.085.0
- product
+ consu
@@ -250,9 +239,7 @@ HDD SH-1
20.025.0
- product
- make_to_order
- produce
+ consu
@@ -262,7 +249,7 @@ HDD SH-1
860.0975.0
- product
+ consu
@@ -272,9 +259,7 @@ HDD SH-1
1020.01150.0
- product
- make_to_order
- produce
+ consu
@@ -284,9 +269,7 @@ HDD SH-1
1100.01250.0
- product
- make_to_order
- produce
+ consuOn demand hard-disk having capacity based on requirement.
@@ -297,7 +280,7 @@ HDD SH-1
1700.01950.0
- product
+ consu
@@ -307,7 +290,7 @@ HDD SH-1
1790.02000.0
- product
+ consu
@@ -317,7 +300,7 @@ HDD SH-1
2010.02100.0
- product
+ consu
@@ -327,7 +310,7 @@ HDD SH-1
1910.01980.0
- product
+ consu
@@ -337,7 +320,7 @@ HDD SH-1
876.0885.0
- product
+ consu
@@ -347,7 +330,7 @@ HDD SH-1
2870.02950.0
- product
+ consu17" Monitor
@@ -361,7 +344,7 @@ QWERTY keyboard3000.03245.0
- product
+ consu17" Monitor
@@ -375,9 +358,7 @@ QWERTY keyboard3300.03645.0
- product
- make_to_order
- produce
+ consuCustom Laptop based on customer's requirement.
@@ -388,7 +369,7 @@ QWERTY keyboard
390.0405.0
- product
+ consu
@@ -399,7 +380,7 @@ QWERTY keyboard
90.0100.0
- product
+ consu
@@ -410,7 +391,7 @@ QWERTY keyboard
126.0145.0
- product
+ consu
@@ -420,7 +401,7 @@ QWERTY keyboard
134.0150.0
- product
+ consu.
@@ -431,7 +412,7 @@ QWERTY keyboard
57.062.0
- product
+ consuHands free headset for laptop PC with in-line microphone and headphone plug.
@@ -442,8 +423,7 @@ QWERTY keyboard
60.065.0
- product
- make_to_order
+ consuHeadset for laptop PC with USB connector.
@@ -455,7 +435,7 @@ QWERTY keyboard
38.045.0
- product
+ consu
@@ -466,7 +446,7 @@ QWERTY keyboard
18.4020.0
- product
+ consu
@@ -477,7 +457,7 @@ QWERTY keyboard
21.6024.0
- product
+ consu
@@ -488,8 +468,7 @@ QWERTY keyboard
4258.04410.0
- product
- make_to_order
+ consuAll in one hi-speed printer with fax and scanner.
@@ -501,7 +480,7 @@ QWERTY keyboard
60.065.0
- product
+ consu
@@ -512,7 +491,7 @@ QWERTY keyboard
66.070.0
- product
+ consu
@@ -569,8 +548,6 @@ QWERTY keyboard
155.0173.0consu
- make_to_order
- produceFull featured image editing software.
@@ -582,7 +559,7 @@ QWERTY keyboard
55.060.0
- product
+ consu
@@ -593,7 +570,7 @@ QWERTY keyboard
35.040.0
- product
+ consu
@@ -604,7 +581,7 @@ QWERTY keyboard
55.070.0
- product
+ consu
@@ -615,7 +592,7 @@ QWERTY keyboard
13.018.0
- product
+ consu
diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml
index 8c19aee026f..b7fbcd560f7 100644
--- a/addons/product/product_view.xml
+++ b/addons/product/product_view.xml
@@ -10,12 +10,10 @@
-
+
-
-
-
+
@@ -60,7 +58,7 @@