[MERGE] Merge parents

bzr revid: rim@openerp.com-20131125080844-kwasxlsc3jfof08l
This commit is contained in:
Richard Mathot (OpenERP)
2013-11-25 09:08:44 +01:00
155 changed files with 5942 additions and 4727 deletions
@@ -41,6 +41,21 @@ def _reopen(self, res_id, model):
class mail_compose_message(osv.TransientModel):
_inherit = 'mail.compose.message'
def default_get(self, cr, uid, fields, context=None):
"""
"""
if context is None:
context = {}
res = super(mail_compose_message, self).default_get(cr, uid, fields, context=context)
if context.get('default_template_id'):
res.update(
self.onchange_template_id(
cr, uid, [], context['default_template_id'], res.get('composition_mode'),
res.get('model'), res.get('res_id'), context=context
)['value']
)
return res
_columns = {
'template_id': fields.many2one('email.template', 'Use template', select=True),
'partner_to': fields.char('To (Partner IDs)',
+1 -1
View File
@@ -39,7 +39,7 @@ Key Features
* Use emails to automatically confirm and send acknowledgements for any event registration
""",
'author': 'OpenERP SA',
'depends': ['base_setup', 'board', 'email_template'],
'depends': ['base_setup', 'board', 'email_template', 'marketing'],
'data': [
'security/event_security.xml',
'security/ir.model.access.csv',
+4 -4
View File
@@ -41,7 +41,6 @@ class event_type(osv.osv):
'default_registration_max': 0,
}
class event_event(osv.osv):
"""Event"""
_name = 'event.event'
@@ -179,7 +178,7 @@ class event_event(osv.osv):
_visibility_selection = lambda self, *args, **kwargs: self._get_visibility_selection(*args, **kwargs)
_columns = {
'name': fields.char('Name', size=64, required=True, translate=True, readonly=False, states={'done': [('readonly', True)]}),
'name': fields.char('Event Name', size=64, required=True, translate=True, readonly=False, states={'done': [('readonly', True)]}),
'user_id': fields.many2one('res.users', 'Responsible User', readonly=False, states={'done': [('readonly', True)]}),
'type': fields.many2one('event.type', 'Type of Event', readonly=False, states={'done': [('readonly', True)]}),
'register_max': fields.integer('Maximum Registrations', help="You can for each event define a maximum registration level. If you have too much registrations you are not able to confirm your event. (put 0 to ignore this rule )", readonly=True, states={'draft': [('readonly', False)]}),
@@ -202,14 +201,12 @@ class event_event(osv.osv):
'email_registration_id' : fields.many2one('email.template','Registration Confirmation Email', help='This field contains the template of the mail that will be automatically sent each time a registration for this event is confirmed.'),
'email_confirmation_id' : fields.many2one('email.template','Event Confirmation Email', help="If you set an email template, each participant will receive this email announcing the confirmation of the event."),
'reply_to': fields.char('Reply-To Email', size=64, readonly=False, states={'done': [('readonly', True)]}, help="The email address of the organizer is likely to be put here, with the effect to be in the 'Reply-To' of the mails sent automatically at event or registrations confirmation. You can also put the email address of your mail gateway if you use one."),
'main_speaker_id': fields.many2one('res.partner','Main Speaker', readonly=False, states={'done': [('readonly', True)]}, help="Speaker who will be giving speech at the event."),
'address_id': fields.many2one('res.partner','Location', readonly=False, states={'done': [('readonly', True)]}),
'street': fields.related('address_id','street',type='char',string='Street'),
'street2': fields.related('address_id','street2',type='char',string='Street2'),
'state_id': fields.related('address_id','state_id',type='many2one', relation="res.country.state", string='State'),
'zip': fields.related('address_id','zip',type='char',string='zip'),
'city': fields.related('address_id','city',type='char',string='city'),
'speaker_confirmed': fields.boolean('Speaker Confirmed', readonly=False, states={'done': [('readonly', True)]}),
'country_id': fields.related('address_id', 'country_id',
type='many2one', relation='res.country', string='Country', readonly=False, states={'done': [('readonly', True)]}, store=True),
'description': fields.html(
@@ -220,6 +217,9 @@ class event_event(osv.osv):
'is_subscribed' : fields.function(_subscribe_fnc, type="boolean", string='Subscribed'),
'visibility': fields.selection(_visibility_selection, 'Privacy / Visibility',
select=True, required=True),
'organizer_id': fields.many2one('res.partner', "Organizer"),
'phone': fields.related('organizer_id', 'phone', type='char', string='Phone'),
'email': fields.related('organizer_id', 'email', type='char', string='Email'),
}
_defaults = {
'state': 'draft',
+11 -20
View File
@@ -9,13 +9,7 @@
<field name="view_mode">tree,form,calendar,graph</field>
<field name="context">{'search_default_event_id': active_id, 'default_event_id': active_id}</field>
</record>
<!-- Top menu item -->
<menuitem name="Events"
id="event_main_menu"
groups="base.group_user"
sequence="115"/>
<menuitem name="Events Organization" id="base.menu_event_main" parent="event_main_menu"/>
<menuitem name="Events" parent="base.marketing_menu" id="event_main_menu"/>
<!-- EVENTS -->
@@ -52,8 +46,9 @@
<field name="res_model">event.type</field>
<field name="view_type">form</field>
</record>
<menuitem name="Configuration" id="base.menu_marketing_config_root" parent="event_main_menu" sequence="30"/>
<menuitem name="Types of Events" id="menu_event_type" action="action_event_type" parent="base.menu_marketing_config_root" groups="base.group_no_one"/>
<menuitem name="Configuration" id="base.menu_marketing_config_root" parent="base.marketing_menu" sequence="30"/>
<menuitem name="Events" id="event_configuration" parent="base.menu_marketing_config_root"/>
<menuitem name="Types of Events" id="menu_event_type" action="action_event_type" parent="event.event_configuration" groups="base.group_no_one"/>
<!-- Events Organisation/CONFIGURATION/EVENTS -->
@@ -63,11 +58,11 @@
<field name="arch" type="xml">
<form string="Events" version="7.0">
<header>
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,done"/>
<button string="Confirm Event" name="button_confirm" states="draft" type="object" class="oe_highlight" groups="base.group_user"/>
<button string="Finish Event" name="button_done" states="confirm" type="object" class="oe_highlight" groups="base.group_user"/>
<button string="Set To Draft" name="button_draft" states="cancel,done" type="object" groups="base.group_user"/>
<button string="Cancel Event" name="button_cancel" states="draft,confirm" type="object" groups="base.group_user"/>
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,done"/>
</header>
<sheet>
<div class="oe_right oe_button_box" groups="base.group_user">
@@ -76,18 +71,19 @@
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
<field name="visibility"/>
</div>
<group>
<group name="main_field_group">
<group>
<field name="address_id" on_change="on_change_address_id(address_id)" context="{'show_address': 1}" options='{"always_reload": True}'/>
<field name="organizer_id"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
<group>
<field name="user_id"/>
<field name="type" on_change="onchange_event_type(type,context)" />
<field name="date_begin" on_change="onchange_start_date(date_begin,date_end)"/>
<field name="date_end"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="visibility"/>
</group>
</group>
<notebook>
@@ -102,10 +98,6 @@
</div>
<field name="register_attended"/>
</group>
<group>
<field name="main_speaker_id" domain="[('speaker','=',True)]" context="{'default_speaker':1}"/>
<field name="speaker_confirmed"/>
</group>
</group>
<field name="registration_ids" colspan="4" nolabel="1" groups="event.group_event_manager,event.group_event_user">
<tree string="Registration" editable="top">
@@ -175,7 +167,6 @@
<field name="register_current"/>
<field name="register_min"/>
<field name="register_max" invisible="1"/>
<field name="main_speaker_id" groups="base.group_no_one"/>
<field name="user_id"/>
<field name="state"/>
<field name="message_unread" invisible="1"/>
@@ -323,7 +314,7 @@
context="{'search_default_partner_id': [active_id], 'default_partner_id': active_id}"
view_type="form"/>
<menuitem name="Events" id="menu_event_event" action="action_event_view" parent="base.menu_event_main" />
<menuitem name="Events" id="menu_event_event" action="action_event_view" parent="event.event_main_menu" />
<!-- EVENTS/REGISTRATIONS/EVENTS -->
@@ -460,7 +451,7 @@
</record>
<menuitem name="Registrations"
id="menu_action_registration" parent="base.menu_event_main"
id="menu_action_registration" parent="event.event_main_menu"
action="action_registration" groups="event.group_event_manager,event.group_event_user"/>
<menuitem name="Reporting" id="base.menu_report_association" parent="event_main_menu" sequence="20"/>
@@ -44,7 +44,6 @@ class report_event_registration(osv.osv):
'user_id': fields.many2one('res.users', 'Event Responsible', readonly=True),
'user_id_registration': fields.many2one('res.users', 'Register', readonly=True),
'name_registration': fields.char('Participant / Contact Name',size=45, readonly=True),
'speaker_id': fields.many2one('res.partner', 'Speaker', readonly=True),
'company_id': fields.many2one('res.company', 'Company', readonly=True),
}
_order = 'event_date desc'
@@ -64,7 +63,6 @@ class report_event_registration(osv.osv):
r.user_id AS user_id_registration,
r.name AS name_registration,
e.company_id AS company_id,
e.main_speaker_id AS speaker_id,
to_char(e.date_begin, 'YYYY-MM-DD') AS event_date,
to_char(e.date_begin, 'YYYY') AS year,
to_char(e.date_begin, 'MM') AS month,
@@ -91,7 +89,6 @@ class report_event_registration(osv.osv):
e.user_id,
event_state,
e.company_id,
e.main_speaker_id,
year,
month,
e.register_max,
-77
View File
@@ -1,77 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Event Moodle',
'version': '0.1',
'category': 'Tools',
'description': """
Configure your moodle server.
=============================
With this module you are able to connect your OpenERP with a moodle platform.
This module will create courses and students automatically in your moodle platform
to avoid wasting time.
Now you have a simple way to create training or courses with OpenERP and moodle.
STEPS TO CONFIGURE:
-------------------
1. Activate web service in moodle.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>site administration >plugins >web services >manage protocols activate the xmlrpc web service
>site administration >plugins >web services >manage tokens create a token
>site administration >plugins >web services >overview activate webservice
2. Create confirmation email with login and password.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We strongly suggest you to add those following lines at the bottom of your event
confirmation email to communicate the login/password of moodle to your subscribers.
........your configuration text.......
**URL:** your moodle link for exemple: http://openerp.moodle.com
**LOGIN:** ${object.moodle_username}
**PASSWORD:** ${object.moodle_user_password}
""",
'author': 'OpenERP SA',
'depends': ['event'],
'data': [
'wizard_moodle.xml',
'event_view.xml',
'security/ir.model.access.csv'
],
'demo': [],
'test': [],
'installable': True,
'auto_install': False,
'images': ['images/token.png','images/enable_webservice.png','images/active_xmlrpc.png'],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-286
View File
@@ -1,286 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2012 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import fields, osv
import xmlrpclib
import string
import time
import random
from random import sample
from openerp.tools.translate import _
class event_moodle(osv.osv):
_name = 'event.moodle.config.wiz'
_columns = {
'moodle_username' : fields.char('Moodle Username', 128, help="You can also connect with your username that you define when you create a token"),
'moodle_password' : fields.char('Moodle Password', 128),
'moodle_token' : fields.char('Moodle Token', 128, help="Put your token that you created in your moodle server"),
'server_moodle': fields.char('Moodle Server', 128, required=True,help="URL where you have your moodle server. For exemple: 'http://127.0.0.1' or 'http://localhost'"),
'url': fields.char('URL to Moodle Server', size=256, help="The url that will be used for the connection with moodle in xml-rpc"),
}
_order = 'create_date desc'
_defaults = {
'server_moodle': 'http://127.0.0.1',
}
def configure_moodle(self, cr, uid, ids, context=None):
url = self.make_url(cr, uid, ids, context=context)
self.write(cr, uid, ids, {'url': url})
return {'type': 'ir.actions.act_window_close'}
def find(self, cr, uid, context=None):
"""
Find the config wizard containing the configuration and raise and error if none is available.
"""
moodle_config_wiz_ids = self.search(cr, uid, [], context=context)
if not moodle_config_wiz_ids:
raise osv.except_osv(_('Error!'),_("First configure your moodle connection."))
return moodle_config_wiz_ids[0]
def make_url(self, cr, uid, ids, context=None):
"""
create the good url with the information of the configuration
@return url for moodle connexion
"""
def _encode_password(password):
for i in range(len(password)):
x = password[i]
if x not in string.ascii_letters + string.digits:
unicode_car = (hex(ord(x)))
hex_car = '%'+str(unicode_car[2:])
password = password.replace(x,hex_car)
return password
url=""
config_moodle = self.browse(cr, uid, ids[0], context=context)
if config_moodle.moodle_username and config_moodle.moodle_password:
#connexion with password and username
password = _encode_password(config_moodle.moodle_password)
url = config_moodle.server_moodle + '/moodle/webservice/xmlrpc/simpleserver.php?wsusername=' + config_moodle.moodle_username + '&wspassword=' + password
if config_moodle.moodle_token:
#connexion with token
url = config_moodle.server_moodle + '/moodle/webservice/xmlrpc/server.php?wstoken=' + config_moodle.moodle_token
return url
def create_moodle_user(self, cr, uid, id, dic_user, context=None):
"""
create a moodle user
@param dic_user : is a list of dictonnaries with the moodle information
@return a liste of dictonaries with the create user id
"""
#connect to moodle
url = self.browse(cr, uid, id, context=context).url
sock = xmlrpclib.ServerProxy(url)
#add user in moodle and return list of id and username
return sock.core_user_create_users(dic_user)
def create_moodle_courses(self, cr, uid, id, courses, context=None):
"""
create a mmodle course
@param courses : is a list of dictionaries with the moodle course information
@return a list of dictionaries with the create course id
"""
#connect to moodle
url = self.browse(cr, uid, id, context=context).url
if not url:
raise osv.except_osv(_('Error!'),_("You must configure your moodle connection."))
sock = xmlrpclib.ServerProxy(url)
return sock.core_course_create_courses(courses)
def moodle_enrolled(self, cr, uid, id, enrolled, context=None):
"""
this method is used to match a course with users
@param enrolled : list of dictonaries with the course id and the user id
"""
#connect to moodle
url = self.browse(cr, uid, id, context=context).url
sock = xmlrpclib.ServerProxy(url)
#add enrolled in moodle
sock.enrol_manual_enrol_users(enrolled)
def create_password(self):
"""
create a random password
"""
rand = string.ascii_letters + string.digits
length = 8
passwd = ''.join(sample(rand, length))
passwd = passwd + '+'
return passwd
def check_email(self, email):
"""
check if email is correct
"""
if email:
if (email.count('@') != 1 and email.count('.') < 1):
raise osv.except_osv(_('Error!'),_("Your email '%s' is wrong.") % (email))
def make_username(self, username, response_courses):
"""
create a moodle username with a random number for the uniqueness
@return the moodle username
"""
if username:
#remove space in the name
username = username.replace(" ","_")
#give an user name
name_user = username + "%d" % (response_courses,) + "%d" % (random.randint(1,999999),)
else:
name_user = "moodle_" + "%d" % (response_courses,) + "%d" % (random.randint(1,999999),)
return name_user
class event_event(osv.osv):
_inherit = "event.event"
_columns={
'moodle_id': fields.integer('Moodle ID', help='The identifier of this event in Moodle'),
}
def check_registration_limits(self, cr, uid, ids, context=None):
"""
create moodle courses ,users and match them when an event is confirmed
if the event_registration is not confirmed then it doesn t nothing
"""
res = super(event_event, self).check_registration_limits(cr, uid, ids, context=context)
moodle_pool = self.pool.get('event.moodle.config.wiz')
moodle_config_wiz_id = moodle_pool.find(cr, uid, context=context)
list_users=[]
userid = []
for event in self.browse(cr, uid, ids, context=context):
#moodle use time() to store the date
date = time.strptime(event.date_begin, '%Y-%m-%d %H:%M:%S')
date = int (time.mktime(date))
#create the dict of values to create the course in Moodle
dic_courses= [{
'fullname': event.name,
'shortname': '',
'startdate': date,
'summary': event.note,
'categoryid':1, #the category hardcoded is 'Miscellaneous'
}]
#create a course in moodle and keep the id
response_courses = moodle_pool.create_moodle_courses(cr, uid, moodle_config_wiz_id, dic_courses, context=context)
self.write(cr, uid, event.id, {'moodle_id': response_courses[0]['id']})
moodle_uids = []
for registration in event.registration_ids:
if registration.state == 'open':
#enroll the registration in Moodle as it is confirmed
if not registration.moodle_uid:
#create a dictionary for an user
name_user = moodle_pool.make_username(registration.name, response_courses[0]['id'])
moodle_pool.check_email(registration.email)
passwd = moodle_pool.create_password()
dic_users={
'username' : name_user,
'password' : passwd,
'city' : registration.city,
'firstname' : registration.name ,
'lastname': '',
'email': registration.email
}
#create the user in moodle
response_user = moodle_pool.create_moodle_user(cr, uid, moodle_config_wiz_id, [dic_users], context=context)
for user in response_user:
self.pool.get('event.registration').write(cr,uid,[registration.id],{'moodle_uid': user['id'], 'moodle_user_password': passwd, 'moodle_username': name_user})
moodle_uids.append(user['id'])
else:
moodle_uids.append(registration.moodle_uid)
#link the course with users
enrolled = []
for moodle_user in moodle_uids:
enrolled.append({
'roleid' :'5', #mark as 'Student'
'userid' : moodle_user,
'courseid' :response_courses[0]['id']
})
moodle_pool.moodle_enrolled(cr, uid, moodle_config_wiz_id, enrolled, context=context)
return res
class event_registration(osv.osv):
_inherit = "event.registration"
_columns={
'moodle_user_password': fields.char('Password for Moodle User', 128),
'moodle_username': fields.char('Moodle Username', 128),
'moodle_uid': fields.integer('Moodle User ID'),
}
def confirm_registration(self, cr, uid, ids, context=None):
"""
create a user and match to a course if the event is already confirmed
"""
res = super(event_registration, self).confirm_registration(cr, uid, ids, context=context)
moodle_pool = self.pool.get('event.moodle.config.wiz')
moodle_config_wiz_id = moodle_pool.find(cr, uid, context=context)
for register in self.browse(cr, uid, ids, context=context):
if register.event_id.state == 'confirm' and register.event_id.moodle_id:
if not register.moodle_uid:
#create the user in moodle
name_user = moodle_pool.make_username(register.name, register.event_id.moodle_id)
moodle_pool.check_email(register.email)
passwd = moodle_pool.create_password()
dic_users = [{
'username': name_user,
'password': passwd,
'city': register.city,
'firstname': register.name,
'lastname': '', #we could make a split of the register.name on ' ' but it would be inaccurate, so it seems better to let it empty as it's not really useful
'email': register.email,
}]
response_user = moodle_pool.create_moodle_user(cr, uid, moodle_config_wiz_id, dic_users, context=context)
#write in database the password and the username
moodle_user_id = response_user[0]['id']
self.pool.get('event.registration').write(cr, uid, ids, {'moodle_uid': moodle_user_id, 'moodle_user_password': passwd, 'moodle_username': name_user})
else:
moodle_user_id = register.moodle_uid
enrolled=[{
'roleid': '5', #mark as student
'userid': moodle_user_id,
'courseid': register.event_id.moodle_id
}]
moodle_pool.moodle_enrolled(cr, uid, moodle_config_wiz_id, enrolled, context=context)
return res
def onchange_moodle_name(self, cr, uid, ids, moodle_username, context=None):
"""
This onchange receive as parameter a username moddle and will fill the moodle_uid and password fields if existing records with this username are found
@param moodle_username: the existing moodle username
"""
res = {}
reg_ids = self.search(cr, uid, [('moodle_username', '=', moodle_username)], order='create_date desc', context=context)
if reg_ids:
reg = self.browse(cr, uid, reg_ids[0], context=context)
res = {'value' :{
'moodle_uid': reg.moodle_uid,
'name': reg.name,
'email':reg.email,
'phone':reg.phone,
'city': reg.city,
'street': reg.street}}
return res
-38
View File
@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="moodle_information">
<field name="name">event.moodle.registration</field>
<field name="model">event.registration</field>
<field name="inherit_id" ref="event.view_event_registration_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='user_id']" position="after">
<field name="moodle_user_password" readonly='1'/>
<field name="moodle_uid" readonly="1"/>
</xpath>
<field name="email" position="replace">
<!-- set the email as required -->
<field name="email" nolabel="1" required="1" />
</field>
<field name="name" position="replace">
<field name="moodle_username" colspan="2" on_change="onchange_moodle_name(moodle_user_password)"/>
<field name="name" required="1" />
</field>
</field>
</record>
<record model="ir.ui.view" id="moodle_information_event">
<field name="name">event.moodle.event</field>
<field name="model">event.event</field>
<field name="inherit_id" ref="event.view_event_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='registration_ids']/tree/field[@name='name']" position="replace">
<field name="moodle_username" on_change="onchange_moodle_name(moodle_user_password)"/>
<field name="name" required="1" />
</xpath>
<field name="email" position="replace">
<field name="email" required="1" />
</field>
</field>
</record>
</data>
</openerp>
-185
View File
@@ -1,185 +0,0 @@
# Czech translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-03-31 16:48+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Czech <cs@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:37+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr ""
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr ""
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr ""
-198
View File
@@ -1,198 +0,0 @@
# German translation for openobject-addons
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-12-10 08:39+0000\n"
"Last-Translator: Thorsten Vocks (OpenBig.org) <thorsten.vocks@big-"
"consulting.net>\n"
"Language-Team: German <de@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:37+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Anbindung mit Benutzer und Passwort"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
"URL Ihres Moodle Servers. Zum Beispiel: 'http://127.0.0.1' oder "
"'http://localhost'"
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Passwort für Moodle Benutzer"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Moodle Passwort"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Ihre EMail #%s' ist falsch."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr "Verbindungstoken"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
"Der einfachste Weg für eine OpenERP Verbindung zu einem Moodle Server ist "
"der Erstellung eines 'Tokens' in Moodle. Dieser wird dann eingesetzt, um "
"OpenERP als vertrauenswürdige Anwendung zu authentifizieren."
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "URL des Moodle Servers"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr ""
"Die url die benutzt wird, um eine Verbindung zu moodle via xml-rpc "
"herzustellen"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Veranstaltung Anmeldung"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
"Ein anderer Ansatz ist die Erstellung eines Benutzers für OpenERP in Moodle "
"zu erstellen. Wenn Sie dieses bevorzugen, sollte natürlich sicher gestellt "
"werden, dass ausreichende Zugriffsrechte erteilt werden."
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "Moodle Benutzer ID"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Moodle Server"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "Moodle ID"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Server"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Fehler !"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr "Sie müssen zuerst Ihre Moodle Verbindung konfigurieren."
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Moodle Benutzername"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Konfigurieren Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Moodle Token"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
"Sie können sich ebenso mit Ihrem Benutzernamen, den Sie bei der Token "
"Erstellung erzeugt haben, anmelden."
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr "Die Identifizierung Ihrer Veranstaltung in Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr "Tragen Sie den in Moodle erstellten Token ein"
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Moodle Konfiguration"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "oder"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Konfigurieren Sie zuerst Ihre Moodle Verbindung"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Anwenden"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Abbrechen"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Veranstaltung"
-194
View File
@@ -1,194 +0,0 @@
# Spanish translation for openobject-addons
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-12-12 20:43+0000\n"
"Last-Translator: lambdasoftware <development@lambdasoftware.net>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:38+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Conexión con nombre de usuario y contraseña"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
"Dirección (URL) de su servidor moodle. Por ejemplo: 'http://127.0.0.1' o "
"'http://localhost'"
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Contraseña del usuario Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Contraseña de Moodle"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Su email '%s' es erróneo."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr "Conexión con testigo (token)"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
"La manera más sencilla para conectar OpenERP con el servidor moodle es crear "
"un 'token' en Moodle. Esto permitirá autenticar a OpenERP como una "
"aplicación de confianza."
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "Dirección (URL) al servidor de Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr "Dirección que se usará para conectar con moodle a través de xml-rpc"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Registro de eventos"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
"Otro enfoque es crear un usuario para OpenERP en Moodle. Si lo hace, "
"asegúrese de que el usuario tiene los permisos adecuados."
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "ID del usario Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Servidor Moodle"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "ID de Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Servidor"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "¡Error!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr "Debe configurar la conexión con moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Nombre de usuario Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Configurar Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Testigo (Token) de Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
"También puede conectarse con el nombre de usuario que definió cuando creó el "
"token"
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr "Identificador de este evento en Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr "Ponga el token que ha creado en su servidor moodle"
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Configuración de Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "o"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Configure primero su conexion moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Aplicar"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Cancelar"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Evento"
-175
View File
@@ -1,175 +0,0 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * event_moodle
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0alpha\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-12-21 17:05+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid "URL where you have your moodle server. For exemple: 'http://127.0.0.1' or 'http://localhost'"
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "The easiest way to connect OpenERP with a moodle server is to create a 'token' in Moodle. It will be used to authenticate OpenERP as a trustable application."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Another approach is to create a user for OpenERP in Moodle. If you do so, make sure that this user has appropriate access rights."
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr ""
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid "You can also connect with your username that you define when you create a token"
msgstr ""
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr ""
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr ""
-194
View File
@@ -1,194 +0,0 @@
# French translation for openobject-addons
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-12-21 13:44+0000\n"
"Last-Translator: Julius <contact@imaugis.com>\n"
"Language-Team: French <fr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:37+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Connexion avec identifiant et mot de passe"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
"L'Url de votre serveur Moodle. Par exemple : 'http://127.0.0.1' ou "
"http://localhost'"
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Mot de passe de l'utilisateur Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Mot de passe Moodle"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Votre email '%s' est incorrect"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr "Connexion avec une session d'authentification (Token)"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
"La manière la plus simple de se connecter à OpenERP avec un serveur moodle "
"est de créer une session d'authentification (token). Ceci permet "
"d'authentifier OpenERP comme une application de confiance"
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "URL du serveur Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr "L'url qui sera utilisé pour la connexion de Moodle en xml-rpc"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Inscription à l'événement"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
"Une autre approche est de créer un utilisateur pour OpenERP sur Moodle. Si "
"vous faîtes cela, vérifier que l'utilisateur a des droits d'accés appropriés"
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "Identifiant de l'utilisateur Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Serveur Moodle"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "Identifiant Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Serveur"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Erreur !"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr "Vous devez configurer votre connexion moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Nom de l'utilisateur Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Configurer Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Session d'authentification (Token)"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
"Vous pouvez aussi vous connecter avec votre identifiant que vous avez défini "
"lors de la création d'un Token"
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr ""
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Configuration Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "ou"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Première configuration de votre connexion Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Annuler"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Évènement"
-185
View File
@@ -1,185 +0,0 @@
# Croatian translation for openobject-addons
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-12-09 20:12+0000\n"
"Last-Translator: Goran Kliska <gkliska@gmail.com>\n"
"Language-Team: Croatian <hr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:38+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Lozinka za Moodle korisnika"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Moodle lozinka"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Vaša email adresa '%s' nije ispravna."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "URL Moodle poslužitelja"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Moodle poslužitelj"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "Moodle ID"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Poslužitelj"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Greška!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Moodle korisničko ime"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Moodle postavke"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Moodle token"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr ""
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "ili"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Primjeni"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Odustani"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Event"
-197
View File
@@ -1,197 +0,0 @@
# Hungarian translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-02-28 08:28+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Hungarian <hu@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:37+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Csatlakozás felhasználónévvel és jelszóval"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
"A moodle tanulási környezet szerver helyének URL elérési útja. Pédául: "
"'http://127.0.0.1' or 'http://localhost'"
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Jelszó a Moodle tanulási környezet felhasználónak"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Moodle tanulási környezeti jelszó"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Az '%s' e-mailje hibás."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr "Szimbólum tokennel való belépés"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
"A legkönnyebb kapcsolódási lehetőség Moodle szerverrel az OpenERP "
"rendszerhez úgy, hogy egy szimbólum 'tokent' hoz A Moodle-n. Ezt az OpenERP "
"hitelesítésére lesz használva mint hitelesített alkalmazás."
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "URL a Moodle szerverhez"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr ""
"Ezt az url elérési útat az xml-rpc fogja használni a Moodle tanulási "
"környezet csatlakozására"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Rendezvény regisztráció"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
"Másik lehetőség, hogy az OpenERP felhasználót a moodle tanulási környezetből "
"állítja be. Ha így tesz, akkor győződjön meg, hogy ennek a felhasználónak "
"megfelelő elérési jogosultságai vannak."
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "Moodle tanulási környezet felhasználó ID azonosítója"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Moodle szerver"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "Moodle ID azonosító"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Szerver"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Hiba!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr "Be kell állítani a Moodle tanulási környezet csatlakozást."
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Moodle tanulási környezet felhasználó"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Moodle tanulási környezet beállítása"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Moodle tanulási környezet Token"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
"A token létrehozásakor létrehozott felhasználó nevével is kapcsolódhat"
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr "Ennek az eseménynek az azonosítójaa moodle tanulási környezetben"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr ""
"Tegye ide a tokent amit a Moodle tanulási környezet szerveren létrehozott"
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Moodle tanulási környezet beállítás"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "vagy"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Előszőr állítsa be a Moodle tanulási környezet csatlakozást"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Alkalmaz"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Mégsem"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Esemény"
-194
View File
@@ -1,194 +0,0 @@
# Macedonian translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-03-08 14:43+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Macedonian <mk@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:37+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Конекција со корисничко име и лозинка"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
"URl адресата на вашиот moodle сервер. На пример, 'http://127.0.0.1' или "
"'http://localhost'"
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Лозинка за Moodle корисник"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Moodle лозинка"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Вашата е-пошта '%s' е погрешна."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr "Конекција со токен"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
"Најлесен начин да се поврзете на OpenERP со moodle сервер е да креирате "
"'токен' во Moodle. Тој ќе се користи за да се идентификува OpenERP како "
"доверлива апликација."
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "URL на Moodle Сервер"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr "URL која ќе се користи за конекција со moodle во xml-rpc"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Регистрација на настан"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
"Другиот начин е да се креира корисник за OpenERP во Moodle. Доколку го "
"направите тоа, погрижете се овој корисник да ги има сите права за пристап."
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "ID на Moodle корисник"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Moodle Сервер"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "Moodle ID"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Сервер"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Грешка!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr "Мора да ја конфигурирате вашата moodle конекција."
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Moodle корисничко име"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Конфигурирај Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Moodle Токен"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
"Можете да се конектирате со вашето корисничко име што го дефинирате кога "
"креирате токен"
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr "Идентификувач на овој настан во Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr "Ставете го токенот кој го креиравте во вашиот Moodle сервер"
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Moodle Конфигурација"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "или"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Најпрво конфигурирајте ја вашата moodle конекција."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Примени"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Откажи"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Настан"
-185
View File
@@ -1,185 +0,0 @@
# Mongolian translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-02-06 09:39+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Mongolian <mn@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:38+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Хэрэглэгчийн нэр ба нууц үгтэй холболт"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Moodle хэрэглэгчийн нууц үг"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Moodle нууц үг"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Таны емайл '%s' буруу байна."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "Moodle серверийн URL"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Үйл явдлын бүртгэл"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "Moodle хэрэглэгч ID"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Moodle Сервер"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "Moodle ID"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Сервер"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Алдаа гарлаа!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Moodle хэрэглэгчийн нэр"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Moodle тохиргоо"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Moodle тасалбар"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr ""
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Moodle тохиргоо"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "эсвэл"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Эхлээд moodleхолболтыг тохируул"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Ашиглах"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Цуцлах"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Үйл ажиллагаа"
-185
View File
@@ -1,185 +0,0 @@
# Dutch translation for openobject-addons
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-11-30 20:02+0000\n"
"Last-Translator: Erwin van der Ploeg (BAS Solutions) <Unknown>\n"
"Language-Team: Dutch <nl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:37+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Connectie met gebruikersnaam en wachtwoord."
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Wachtwoord voor Moodle gebruiker"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Moodle wachtwoord"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Uwr email '%s' is fout."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr "Connectie met een token"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "URL van Moodle Server"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Evenementregistratie"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "Moodle User ID"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Moodle Server"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "Moodle ID"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Server"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Fout!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Moodle gebruikersnaam"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Moodle instellen"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Moodle Token"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr ""
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Moodle instellingen"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "of"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Stel eerst uw Moodle connectie in."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Toepassen"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Annuleren"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Evenement"
-187
View File
@@ -1,187 +0,0 @@
# Portuguese translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-01-04 17:35+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Portuguese <pt@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:38+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Ligação com nome de utilizador e senha"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
"Endereço onde tem o seu servidor moodle. Por exemplo: 'http://127.0.0.1' ou "
"'http://localhost'"
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Senha para o utilizador Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Senha Moodle"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "O seu email '%s' está errado."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "Endereço para o servidor Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr "O endereço que será usado para a ligação com o moodle em xml-rpc"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Servidor Moodle"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Servidor"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Erro!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr "Tem que configurar a sua ligação ao moodle."
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Configurar Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr ""
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Configuração Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Primeiro configure a sua ligação ao moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Aplicar"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Cancelar"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Evento"
-195
View File
@@ -1,195 +0,0 @@
# 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 <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-12-24 18:29+0000\n"
"Last-Translator: Fábio Martinelli - http://zupy.com.br "
"<webmaster@guaru.net>\n"
"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:38+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Conectar com usuário e senha"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
"URL aonde está configurado o servidor moodle. Por exemplo 'http://127.0.0.1' "
"ou 'http://localhost'"
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Senha para o Usuário Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Senha Moodle"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Seu email '%s' está errado."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr "Conectar com um Token"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
"A maneira mais fácil de conectar o OpenERP com um servidor moodle é criar um "
"token no Moodle. Ele será usado para autenticar o OpenERP como uma aplicação "
"confiável."
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "URL para o Servidor Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr "A url que será usada para a conexão do moodle em xml-rpc"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Inscrição no Evento"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
"Outra maneira é criar um usuário para o OpenERP no Moodle. Se você fizer "
"dessa forma, tenha certeza de que este usuário possui os direitos de acesso "
"apropriados."
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "ID do Usuário no Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Servidor Moodle"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "ID Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Servidor"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Erro!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr "Você precisa configurar sua conexão ao moodle."
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Usuário Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Configurar Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Token Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
"Você também pode conectar com o usuário que você definiu ao criar um token"
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr "O identificador deste evento no Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr "Coloque o token que você criou no seu servidor moodle"
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Configuracão do Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "ou"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Primeiro configure sua conexão do Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Aplicar"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Cancelar"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Evento"
-195
View File
@@ -1,195 +0,0 @@
# Romanian translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-01-23 21:24+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Romanian <ro@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:38+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Conectare cu numele de utilizator si parola"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "wiz.config.eveniment.moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
"URL-ul unde aveti serverul moodle. De exemplu: 'http://127.0.0.1' or "
"'http://localhost'"
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Parola pentru Utilizatorul Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Parola Moodle"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Email-ul dumneavoastra '%s' este gresit."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr "Conectare cu un Simbol"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
"Cel mai usor mod de conectare a lui OpenERP cu un server moodle este sa "
"creati un 'simbol' in Moodle. Va fi folosit pentru a autentifica OpenERP "
"drept o aplicatie de incredere."
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "URL catre Serverul Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr "Url-ul care va fi folosit pentru conectarea cu moodle in xml-rpc"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Inregistrarea Evenimentelor"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
"O alta abordare este sa creati un utilizator pentru OpenERP in Moodle. Daca "
"faceti acest lucru, asigurati-va ca acest utilizator are drepturi de acces "
"adecvate."
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "ID Utilizator Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Server Moodle"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "ID Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Server"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Eroare!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr "Trebuie sa configurati conexiunea moodle."
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Nume de utilizator Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Configureaza Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Simbol Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
"De asemenea, puteti sa va conectati cu numele de utilizator pe care il "
"definiti atunci cand creati un simbol"
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr "Identificatorul acestui eveniment in Moodle"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr "Puneti simbolul pe care l-ati creat in serverul moodle"
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Configurare Moodle"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "sau"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Mai intai configurati-va conexiunea moodle."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Aplica"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Anuleaza"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Eveniment"
-185
View File
@@ -1,185 +0,0 @@
# Russian translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-11-13 05:19+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Russian <ru@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-11-14 05:23+0000\n"
"X-Generator: Launchpad (build 16820)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr ""
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr ""
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr ""
-185
View File
@@ -1,185 +0,0 @@
# Slovenian translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-01-26 12:20+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Slovenian <sl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:38+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr ""
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr ""
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Registracija dogodka"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr ""
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Strežnik"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Napaka!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr ""
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr ""
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr ""
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "ali"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr ""
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Uporabi"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "Prekliči"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Dogodek"
-193
View File
@@ -1,193 +0,0 @@
# Turkish translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-02-04 14:05+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Turkish <tr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:38+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "Kullanıcı adı ve parola ile bağlanma"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "etkinlik.moodle.yapılanma.sih"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
"Moodle sunucunuzun bulunduğu URL. Örneğin: 'http://127.0.0.1' or "
"'http://localhost'"
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Moodle kullanıcı parolası"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Moodle Parolası"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "Epostanız '%s' yanlıştır."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr "Andaç ile bağlanma"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
"OpenERP ye bir moodle sunucusu ile en kolay bağlanma yolu Moodle da bir "
"'andaç' oluşturmaktır. OpenERP nin güvenilir bir uygulama olduğunu "
"doğrulamak için kullanılacaktır."
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "Moodle Sunucusu için URL"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr "xml-rpc de moodle ile bağlanmak için kullanılacak url."
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "Etkinlik Kaydı"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr ""
"Diğer bir yaklaşım Moodle da OpenERP için bir kullanıcı oluşturmaktır. Böyle "
"yaparsanız, bu kullanıcının uygun izinlerinin olduğundan emin olun."
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "Moodle Kullanıcı ID"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Moodle Sunucusu"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "Moodle ID"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "Sunucu"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "Hata!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr "Moodle bağlantınızı yapılandırmalısınız."
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Moodle Kullanıcı Adı"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "Moodle Yapılandır"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Moodle Andaçı"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr ""
"Bir andaç oluştururken tanımladığınız kullanıcı adınızla da bağlanabilirsiniz"
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr "Moodle da bu etkinliğin kimliği"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr "Moodle sunucusunda oluşturduğunuz andaçı koyun"
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Modle Yapılandırması"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "ya da"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "Önce moodle bağlantınızı yapılandırın."
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "Uygula"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "İptal"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "Etkinlik"
-188
View File
@@ -1,188 +0,0 @@
# Chinese (Simplified) translation for openobject-addons
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-12-30 00:29+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:38+0000\n"
"X-Generator: Launchpad (build 16761)\n"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with username and password"
msgstr "用户名和密码的链接"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_moodle_config_wiz
msgid "event.moodle.config.wiz"
msgstr "event.moodle.config.wiz"
#. module: event_moodle
#: help:event.moodle.config.wiz,server_moodle:0
msgid ""
"URL where you have your moodle server. For exemple: 'http://127.0.0.1' or "
"'http://localhost'"
msgstr ""
"你的 moodle 服务器的URL。\r\n"
"例如:“http://127.0.0.1”或“http://localhost”"
#. module: event_moodle
#: field:event.registration,moodle_user_password:0
msgid "Password for Moodle User"
msgstr "Moodle用户密码"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_password:0
msgid "Moodle Password"
msgstr "Moodle 密码"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Your email '%s' is wrong."
msgstr "你的邮件 '%s' 是错误的"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Connection with a Token"
msgstr "用 令牌 链接"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"The easiest way to connect OpenERP with a moodle server is to create a "
"'token' in Moodle. It will be used to authenticate OpenERP as a trustable "
"application."
msgstr ""
"用Moodle服务器连接OpenERP的最简单的方法是创建一个“标记”在Moodle。将使用它作为可信赖的应用程序中进行身份验证OpenERP的。"
#. module: event_moodle
#: field:event.moodle.config.wiz,url:0
msgid "URL to Moodle Server"
msgstr "Moodle 服务器的URL"
#. module: event_moodle
#: help:event.moodle.config.wiz,url:0
msgid "The url that will be used for the connection with moodle in xml-rpc"
msgstr "XML-RPC中的URL将被用于连接与Moodle"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_registration
msgid "Event Registration"
msgstr "事件记录"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid ""
"Another approach is to create a user for OpenERP in Moodle. If you do so, "
"make sure that this user has appropriate access rights."
msgstr "在moodle中创建一个Openerp用户的其它方法。如果你这样做了,确实这用户有适当的访问权限。"
#. module: event_moodle
#: field:event.registration,moodle_uid:0
msgid "Moodle User ID"
msgstr "Moodle 用户ID"
#. module: event_moodle
#: field:event.moodle.config.wiz,server_moodle:0
msgid "Moodle Server"
msgstr "Moodle 服务器"
#. module: event_moodle
#: field:event.event,moodle_id:0
msgid "Moodle ID"
msgstr "Moodle ID"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Server"
msgstr "服务器"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#: code:addons/event_moodle/event_moodle.py:105
#: code:addons/event_moodle/event_moodle.py:137
#, python-format
msgid "Error!"
msgstr "错误!"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:105
#, python-format
msgid "You must configure your moodle connection."
msgstr "你必须配置你的 Moodle 链接"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_username:0
#: field:event.registration,moodle_username:0
msgid "Moodle Username"
msgstr "Moodle 用户名"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
#: model:ir.actions.act_window,name:event_moodle.configure_moodle
msgid "Configure Moodle"
msgstr "配置 Moodle"
#. module: event_moodle
#: field:event.moodle.config.wiz,moodle_token:0
msgid "Moodle Token"
msgstr "Moodle 令牌"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_username:0
msgid ""
"You can also connect with your username that you define when you create a "
"token"
msgstr "当你创建了一个令牌,你也能用你定义的用户名链接。"
#. module: event_moodle
#: help:event.event,moodle_id:0
msgid "The identifier of this event in Moodle"
msgstr "该事件在 Moodle 中的标识"
#. module: event_moodle
#: help:event.moodle.config.wiz,moodle_token:0
msgid "Put your token that you created in your moodle server"
msgstr "把你的令牌 放在你的服务器中"
#. module: event_moodle
#: model:ir.ui.menu,name:event_moodle.wizard_moodle
msgid "Moodle Configuration"
msgstr "Moodle 配置"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "or"
msgstr "或"
#. module: event_moodle
#: code:addons/event_moodle/event_moodle.py:57
#, python-format
msgid "First configure your moodle connection."
msgstr "第一次配置的你moodle连接"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Apply"
msgstr "应用"
#. module: event_moodle
#: view:event.moodle.config.wiz:0
msgid "Cancel"
msgstr "取消"
#. module: event_moodle
#: model:ir.model,name:event_moodle.model_event_event
msgid "Event"
msgstr "事件"
@@ -1,3 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_event_moodle,event.moodle.admin,model_event_moodle_config_wiz,event.group_event_manager,1,1,1,1
access_event_moodle_user,event.moodle.usr,model_event_moodle_config_wiz,event.group_event_user,0,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_event_moodle event.moodle.admin model_event_moodle_config_wiz event.group_event_manager 1 1 1 1
3 access_event_moodle_user event.moodle.usr model_event_moodle_config_wiz event.group_event_user 0 0 0 0
-50
View File
@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="create_moodle_config_view">
<field name="name">moodle.config.wizard.form</field>
<field name="model">event.moodle.config.wiz</field>
<field name="arch" type="xml">
<form string="Configure Moodle" version="7.0">
<group>
<separator string="Server" colspan="4"/>
<field name="server_moodle"/>
<newline/>
<separator string="Connection with a Token" colspan="4"/>
<label string="The easiest way to connect OpenERP with a moodle server is to create a 'token' in Moodle. It will be used to authenticate OpenERP as a trustable application." colspan="4"/>
<field name="moodle_token"/>
<newline/>
<separator string="Connection with username and password" colspan="4"/>
<label string="Another approach is to create a user for OpenERP in Moodle. If you do so, make sure that this user has appropriate access rights." colspan="4"/>
<field name="moodle_username"/>
<field name="moodle_password" password="True"/>
</group>
<footer>
<button type="object" name="configure_moodle"
string="Apply" class="oe_highlight" />
or
<button string="Cancel" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="configure_moodle">
<field name="name">Configure Moodle</field>
<field name="res_model">event.moodle.config.wiz</field>
<field name="view_id" ref="create_moodle_config_view"/>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<!-- register configuration wizard -->
<record id="base.open_menu" model="ir.actions.todo">
<field name="action_id" ref="configure_moodle"/>
<field name="state">open</field>
</record>
<menuitem name="Moodle Configuration" parent="base.menu_marketing_config_root" id="wizard_moodle" action="configure_moodle"/>
</data>
</openerp>
-3
View File
@@ -118,9 +118,6 @@ class event_event(osv.osv):
_columns = {
'event_ticket_ids': fields.one2many('event.event.ticket', "event_id", "Event Ticket"),
'organizer_id': fields.many2one('res.partner', "Organizer"),
'phone': fields.related('organizer_id', 'phone', type='char', string='Phone'),
'email': fields.related('organizer_id', 'email', type='char', string='Email'),
'register_max': fields.function(_get_register_max,
string='Maximum Registrations',
help="The maximum registration level is equal to the sum of the maximum registration of event ticket." +
-3
View File
@@ -57,9 +57,6 @@
</field>
</page>
</xpath>
<field name="address_id" position="after">
<field name="organizer_id"/>
</field>
</data>
</field>
</record>
@@ -2,7 +2,7 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -19,7 +19,4 @@
#
##############################################################################
import event_moodle
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
import models
+16
View File
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
{
'name': 'Payment Acquirer',
'category': 'Hidden',
'summary': 'Payment Acquirer Base Module',
'version': '1.0',
'description': """Payment Acquirer Base Module""",
'author': 'OpenERP SA',
'depends': ['mail'],
'data': [
'views/payment_acquirer.xml',
'security/ir.model.access.csv',
],
'installable': True,
}
@@ -0,0 +1,9 @@
.. _changelog:
Changelog
=========
`trunk (saas-3)`
----------------
- Module creation
+14
View File
@@ -0,0 +1,14 @@
Payment module documentation
============================
Payment documentation topics
''''''''''''''''''''''''''''
Changelog
'''''''''
.. toctree::
:maxdepth: 1
changelog.rst
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import payment_acquirer
@@ -0,0 +1,292 @@
# -*- coding: utf-'8' "-*-"
from openerp.osv import osv, fields
import logging
_logger = logging.getLogger(__name__)
class ValidationError(ValueError):
""" Used for value error when validating transaction data coming from acquirers. """
pass
class PaymentAcquirer(osv.Model):
""" Acquirer Model. Each specific acquirer can extend the model by adding
its own fields. Using the required_if_provider='<name>' attribute on fields
it is possible to have required fields that depend on a specific acquirer.
Each acquirer has a link to an ir.ui.view record that is a template of
a button used to display the payment form. See examples in ``payment_acquirer_ogone``
and ``payment_acquirer_paypal`` modules.
Methods that should be added in an acquirer-specific implementation:
- ``<name>_form_generate_values(self, cr, uid, id, reference, amount, currency,
partner_id=False, partner_values=None, tx_custom_values=None, context=None)``:
method that generates the values used to render the form button template.
- ``<name>_get_form_action_url(self, cr, uid, id, context=None):``: method
that returns the url of the button form. It is used for example in
ecommerce application, if you want to repost some data to the acquirer.
Each acquirer should also define controllers to handle communication between
OpenERP and the acquirer. It generally consists in return urls given to the
button form and that the acquirer uses to send the customer back after the
transaction, with transaction details given as a POST request.
"""
_name = 'payment.acquirer'
_description = 'Payment Acquirer'
_columns = {
'name': fields.char('Name', required=True),
'message': fields.html('Message', help='Message displayed to help payment and validation'),
'view_template_id': fields.many2one('ir.ui.view', 'Form Button Template', required=True),
'env': fields.selection(
[('test', 'Test'), ('prod', 'Production')],
string='Environment'),
'portal_published': fields.boolean('Visible in Portal',
help="Make this payment acquirer available (Customer invoices, etc.)"),
}
_defaults = {
'portal_published': True,
'env': 'test',
}
def _check_required_if_provider(self, cr, uid, ids, context=None):
""" If the field has 'required_if_provider="<name>"' attribute, then it
required if record.name is <name>. """
for acquirer in self.browse(cr, uid, ids, context=context):
if any(c for c, f in self._all_columns.items() if getattr(f.column, 'required_if_provider', None) == acquirer.name and not acquirer[c]):
return False
return True
_constraints = [
(_check_required_if_provider, 'Required fields not filled', ['required for this provider']),
]
def render(self, cr, uid, id, reference, amount, currency, tx_id=None, partner_id=False, partner_values=None, tx_custom_values=None, context=None):
""" Renders the form template of the given acquirer as a qWeb template.
All templates should handle:
- acquirer: the payment.acquirer browse record
- user: the current user browse record
- currency: currency browse record
- amount: amount of the transaction
- reference: reference of the transaction
- partner: the current partner browse record, if any (not necessarily set)
- partner_values: a dictionary of partner-related values
- tx_custom_values: a dictionary of transaction related values that depends
on the acquirer. Some specific keys should be managed
in each provider, depending on the features it offers:
- 'feedback_url': feedback URL, controler that manage answer of the acquirer
(without base url)
- 'return_url': URL for coming back after payment validation (wihout
base url)
- 'cancel_url': URL if the client cancels the payment
- 'error_url': URL if there is an issue with the payment
- context: OpenERP context dictionary
:param string reference: the transaction reference
:param float amount: the amount the buyer has to pay
:param res.currency browse record currency: currency
:param int tx_id: id of a transaction; if set, bypasses all other given
values and only render the already-stored transaction
:param res.partner browse record partner_id: the buyer
:param dict partner_values: a dictionary of values for the buyer (see above)
:param dict tx_custom_values: a dictionary of values for the transction
that is given to the acquirer-specific method
generating the form values
:param dict context: OpenERP context
"""
if context is None:
context = {}
partner = None
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
acquirer = self.browse(cr, uid, id, context=context)
method_name = '%s_form_generate_values' % (acquirer.name)
if tx_id and hasattr(self.pool['payment.transaction'], method_name):
method = getattr(self.pool['payment.transaction'], method_name)
tx_values = method(cr, uid, tx_id, tx_custom_values, context=context)
elif hasattr(self, method_name):
method = getattr(self, method_name)
tx_values = method(cr, uid, id, reference, amount, currency, partner_id, partner_values, tx_custom_values, context=context)
else:
tx_values = tx_custom_values
qweb_context = {
'acquirer': acquirer,
'user': self.pool.get("res.users").browse(cr, uid, uid, context=context),
'reference': reference,
'amount': amount,
'currency': currency,
'partner': partner,
'partner_values': partner_values,
'tx_values': tx_values,
'context': context,
}
# because render accepts view ids but not qweb -> need to find the xml_id
return self.pool['ir.ui.view'].render(cr, uid, acquirer.view_template_id.xml_id, qweb_context, engine='ir.qweb', context=context)
def get_form_action_url(self, cr, uid, id, context=None):
acquirer = self.browse(cr, uid, id, context=context)
if hasattr(self, '%s_get_form_action_url' % acquirer.name):
return getattr(self, '%s_get_form_action_url' % acquirer.name)(cr, uid, id, context=context)
return False
class PaymentTransaction(osv.Model):
""" Transaction Model. Each specific acquirer can extend the model by adding
its own fields.
Methods that should be added in an acquirer-specific implementation:
- ``<name>_form_generate_values(self, cr, uid, id, tx_custom_values=None,
context=None)``: method that generates the values used to render the
form button template.
Methods that can be added in an acquirer-specific implementation:
- ``<name>_create``: method receiving values used when creating a new
transaction and that returns a dictionary that will update those values.
This method can be used to tweak some transaction values.
Methods defined for convention, depending on your controllers:
- ``<name>_form_feedback(self, cr, uid, data, context=None)``: method that
handles the data coming from the acquirer after the transaction. It will
generally receives data posted by the acquirer after the transaction.
"""
_name = 'payment.transaction'
_description = 'Payment Transaction'
_inherit = ['mail.thread']
_order = 'id desc'
_rec_name = 'reference'
_columns = {
'date_create': fields.datetime('Creation Date', readonly=True, required=True),
'date_validate': fields.datetime('Validation Date'),
'acquirer_id': fields.many2one(
'payment.acquirer', 'Acquirer',
required=True,
),
'type': fields.selection(
[('server2server', 'Server To Server'), ('form', 'Form')],
string='Type', required=True),
'state': fields.selection(
[('draft', 'Draft'), ('pending', 'Pending'),
('done', 'Done'), ('error', 'Error'),
('cancel', 'Canceled')
], 'Status', required=True,
track_visiblity='onchange'),
'state_message': fields.text('Message',
help='Field used to store error and/or validation messages for information'),
# payment
'amount': fields.float('Amount', required=True,
help='Amount in cents',
track_visibility='always'),
'currency_id': fields.many2one('res.currency', 'Currency', required=True),
'reference': fields.char('Order Reference', required=True),
# duplicate partner / transaction data to store the values at transaction time
'partner_id': fields.many2one('res.partner', 'Partner'),
'partner_name': fields.char('Partner Name'),
'partner_lang': fields.char('Lang'),
'partner_email': fields.char('Email'),
'partner_zip': fields.char('Zip'),
'partner_address': fields.char('Address'),
'partner_city': fields.char('City'),
'partner_country_id': fields.many2one('res.country', 'Country'),
'partner_phone': fields.char('Phone'),
'partner_reference': fields.char('Buyer Reference'),
}
_sql_constraints = [
('reference_uniq', 'UNIQUE(reference)', 'The payment transaction reference must be unique!'),
]
_defaults = {
'date_create': fields.datetime.now,
'type': 'form',
'state': 'draft',
'partner_lang': 'en_US',
}
def create(self, cr, uid, values, context=None):
if values.get('partner_id'): # @TDENOTE: not sure
values.update(self.on_change_partner_id(cr, uid, None, values.get('partner_id'), context=context)['values'])
# call custom create method if defined (i.e. ogone_create for ogone)
if values.get('acquirer_id'):
acquirer = self.pool['payment.acquirer'].browse(cr, uid, values.get('acquirer_id'), context=context)
custom_method_name = '%s_create' % acquirer.name
if hasattr(self, custom_method_name):
values.update(getattr(self, custom_method_name)(cr, uid, values, context=context))
return super(PaymentTransaction, self).create(cr, uid, values, context=context)
def on_change_partner_id(self, cr, uid, ids, partner_id, context=None):
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
values = {
'partner_name': partner.name,
'partner_lang': partner.lang,
'partner_email': partner.email,
'partner_zip': partner.zip,
'partner_address': ' '.join((partner.street or '', partner.street2 or '')).strip(),
'partner_city': partner.city,
'partner_country_id': partner.country_id.id,
'partner_phone': partner.phone,
}
else:
values = {
'partner_name': False,
'partner_lang': 'en_US',
'partner_email': False,
'partner_zip': False,
'partner_address': False,
'partner_city': False,
'partner_country_id': False,
'partner_phone': False,
}
return {'values': values}
# --------------------------------------------------
# FORM RELATED METHODS
# --------------------------------------------------
def form_feedback(self, cr, uid, data, acquirer_name, context=None):
invalid_parameters, tx = None, None
tx_find_method_name = '_%s_form_get_tx_from_data' % acquirer_name
if hasattr(self, tx_find_method_name):
tx = getattr(self, tx_find_method_name)(cr, uid, data, context=context)
invalid_param_method_name = '_%s_form_get_invalid_parameters' % acquirer_name
if hasattr(self, invalid_param_method_name):
invalid_parameters = getattr(self, invalid_param_method_name)(cr, uid, tx, data, context=context)
if invalid_parameters:
_error_message = '%s: incorrect tx data:\n' % (acquirer_name)
for item in invalid_parameters:
_error_message += '\t%s: received %s instead of %s\n' % (item[0], item[1], item[2])
_logger.error(_error_message)
return False
feedback_method_name = '_%s_form_validate' % acquirer_name
if hasattr(self, feedback_method_name):
return getattr(self, feedback_method_name)(cr, uid, tx, data, context=context)
return True
# --------------------------------------------------
# SERVER2SERVER RELATED METHODS
# --------------------------------------------------
def create_s2s(self, cr, uid, tx_values, cc_values, context=None):
tx_id = self.create(cr, uid, tx_values, context=context)
return tx_id
@@ -0,0 +1,7 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
payment_acquirer_all,payment.acquirer.all,model_payment_acquirer,,1,0,0,0
payment_acquirer_user,payment.acquirer.user,model_payment_acquirer,base.group_user,1,1,1,0
payment_acquirer_system,payment.acquirer.system,model_payment_acquirer,base.group_system,1,1,1,1
payment_transaction_all,payment.transaction.all,model_payment_transaction,,1,1,1,0
payment_transaction_user,payment.transaction.user,model_payment_transaction,base.group_user,1,1,1,0
payment_transaction_system,payment.transaction.system,model_payment_transaction,base.group_system,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 payment_acquirer_all payment.acquirer.all model_payment_acquirer 1 0 0 0
3 payment_acquirer_user payment.acquirer.user model_payment_acquirer base.group_user 1 1 1 0
4 payment_acquirer_system payment.acquirer.system model_payment_acquirer base.group_system 1 1 1 1
5 payment_transaction_all payment.transaction.all model_payment_transaction 1 1 1 0
6 payment_transaction_user payment.transaction.user model_payment_transaction base.group_user 1 1 1 0
7 payment_transaction_system payment.transaction.system model_payment_transaction base.group_system 1 1 1 1
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import common
+47
View File
@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
from openerp.tests import common
class PaymentAcquirerCommon(common.TransactionCase):
def setUp(self):
super(PaymentAcquirerCommon, self).setUp()
self.payment_acquirer = self.registry('payment.acquirer')
self.payment_transaction = self.registry('payment.transaction')
self.currency_euro_id = self.registry('res.currency').search(
self.cr, self.uid, [('name', '=', 'EUR')], limit=1)[0]
self.currency_euro = self.registry('res.currency').browse(
self.cr, self.uid, self.currency_euro_id)
country_belgium_id = self.registry('res.country').search(
self.cr, self.uid, [('code', 'like', 'BE')], limit=1)[0]
# dict partner values
self.buyer_values = {
'name': 'Norbert Buyer',
'lang': 'en_US',
'email': 'norbert.buyer@example.com',
'street': 'Huge Street',
'street2': '2/543',
'phone': '0032 12 34 56 78',
'city': 'Sin City',
'zip': '1000',
'country_id': country_belgium_id,
'country_name': 'Belgium',
}
# test partner
self.buyer_id = self.registry('res.partner').create(
self.cr, self.uid, {
'name': 'Norbert Buyer',
'lang': 'en_US',
'email': 'norbert.buyer@example.com',
'street': 'Huge Street',
'street2': '2/543',
'phone': '0032 12 34 56 78',
'city': 'Sin City',
'zip': '1000',
'country_id': country_belgium_id,
}
)
@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<menuitem
name='Payments'
id='root_payment_menu'
parent='base.menu_administration'/>
<record id="acquirer_form" model="ir.ui.view">
<field name="name">acquirer.form</field>
<field name="model">payment.acquirer</field>
<field name="arch" type="xml">
<form string="Payment Acquirer" version="7.0">
<group name="acquirer_base">
<field name="name"/>
<field name="portal_published"/>
<field name="env"/>
<field name="message"/>
<label for="view_template_id"/>
<div>
<field name="view_template_id" nolabel="1"/>
<div>
This is an HTML form template to submit a payment through this acquirer.
The template will be rendered with qWeb, so it may use qWeb expressions.
The qWeb evaluation context provides:
<ul>
<li>acquirer: payment.acquirer browse record</li>
<li>user: current user browse record</li>
<li>reference: the transaction reference number</li>
<li>currency: the transaction currency browse record</li>
<li>amount: the transaction amount, a float</li>
<li>partner: the buyer partner browse record, not necessarily set</li>
<li>partner_values: specific values about the buyer, for example coming from a shipping form</li>
<li>tx_values: specific transaction values</li>
<li>context: the current context dictionary</li>
</ul>
</div>
</div>
</group>
</form>
</field>
</record>
<record id="acquirer_list" model="ir.ui.view">
<field name="model">payment.acquirer</field>
<field name="arch" type="xml">
<tree string="Payment Acquirers">
<field name="name"/>
<field name="portal_published"/>
<field name="env"/>
</tree>
</field>
</record>
<record id="acquirer_search" model="ir.ui.view">
<field name="model">payment.acquirer</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
</search>
</field>
</record>
<record id="action_payment_acquirer" model="ir.actions.act_window">
<field name="name">Payment Acquirers</field>
<field name="res_model">payment.acquirer</field>
<field name='view_type'>form</field>
<field name='view_mode'>tree,form</field>
</record>
<menuitem
action='action_payment_acquirer'
id='payment_acquirer_menu'
parent='root_payment_menu'
sequence='10' />
<record id="transaction_form" model="ir.ui.view">
<field name="model">payment.transaction</field>
<field name="arch" type="xml">
<form string="Payment Transactions" version="7.0">
<sheet>
<group>
<group>
<field name="reference"/>
<field name="amount"/>
<field name="currency_id"/>
<field name="partner_id"/>
<field name="partner_name"/>
<field name="partner_email"/>
</group>
<group>
<field name="date_create"/>
<field name="date_validate"/>
<field name="acquirer_id"/>
<field name="state"/>
<field name="state_message"/>
</group>
</group>
<notebook>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
<field name="message_ids" widget="mail_thread" options='{"thread_level": 1}' placeholder="Send a message to the group"/>
</div>
</form>
</field>
</record>
<record id="transaction_list" model="ir.ui.view">
<field name="model">payment.transaction</field>
<field name="arch" type="xml">
<tree string="Payment Transactions">
<field name="reference"/>
<field name="acquirer_id"/>
<field name="partner_id"/>
<field name="partner_name"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="transaction" model="ir.ui.view">
<field name="model">payment.transaction</field>
<field name="arch" type="xml">
<search>
<field name="reference"/>
<field name="acquirer_id"/>
<field name="partner_id"/>
<field name="partner_name"/>
</search>
</field>
</record>
<record id="action_payment_transaction" model="ir.actions.act_window">
<field name="name">Payment Transactions</field>
<field name="res_model">payment.transaction</field>
<field name='view_type'>form</field>
<field name='view_mode'>tree,form</field>
</record>
<menuitem
action='action_payment_transaction'
id='payment_transaction_menu'
parent='root_payment_menu'
sequence='20' />
</data>
</openerp>
+23
View File
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import models
import controllers
@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
{
'name': 'Ogone Payment Acquirer',
'category': 'Hidden',
'summary': 'Payment Acquirer: Ogone Implementation',
'version': '1.0',
'description': """Ogone Payment Acquirer""",
'author': 'OpenERP SA',
'depends': ['payment_acquirer'],
'data': [
'views/ogone.xml',
'views/payment_acquirer.xml',
'data/ogone.xml',
],
'installable': True,
}
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import main
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
import logging
import pprint
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
_logger = logging.getLogger(__name__)
class OgoneController(http.Controller):
_accept_url = '/payment/ogone/test/accept'
_decline_url = '/payment/ogone/test/decline'
_exception_url = '/payment/ogone/test/exception'
_cancel_url = '/payment/ogone/test/cancel'
@website.route([
'/payment/ogone/accept', '/payment/ogone/test/accept',
'/payment/ogone/decline', '/payment/ogone/test/decline',
'/payment/ogone/exception', '/payment/ogone/test/exception',
'/payment/ogone/cancel', '/payment/ogone/test/cancel',
], type='http', auth='admin')
def ogone_form_feedback(self, **post):
_logger.info('Ogone: entering form_feedback with post data %s', pprint.pformat(post)) # debug
cr, uid, context = request.cr, request.uid, request.context
request.registry['payment.transaction'].ogone_form_feedback(cr, uid, post, context)
return request.redirect(post.pop('return_url', '/'))
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import ogone
+497
View File
@@ -0,0 +1,497 @@
# -*- coding: utf-8 -*-
OGONE_ERROR_MAP = {
'0020001001': "Authorization failed, please retry",
'0020001002': "Authorization failed, please retry",
'0020001003': "Authorization failed, please retry",
'0020001004': "Authorization failed, please retry",
'0020001005': "Authorization failed, please retry",
'0020001006': "Authorization failed, please retry",
'0020001007': "Authorization failed, please retry",
'0020001008': "Authorization failed, please retry",
'0020001009': "Authorization failed, please retry",
'0020001010': "Authorization failed, please retry",
'0030001999': "Our payment system is currently under maintenance, please try later",
'0050001005': "Expiry date error",
'0050001007': "Requested Operation code not allowed",
'0050001008': "Invalid delay value",
'0050001010': "Input date in invalid format",
'0050001013': "Unable to parse socket input stream",
'0050001014': "Error in parsing stream content",
'0050001015': "Currency error",
'0050001016': "Transaction still posted at end of wait",
'0050001017': "Sync value not compatible with delay value",
'0050001019': "Transaction duplicate of a pre-existing transaction",
'0050001020': "Acceptation code empty while required for the transaction",
'0050001024': "Maintenance acquirer differs from original transaction acquirer",
'0050001025': "Maintenance merchant differs from original transaction merchant",
'0050001028': "Maintenance operation not accurate for the original transaction",
'0050001031': "Host application unknown for the transaction",
'0050001032': "Unable to perform requested operation with requested currency",
'0050001033': "Maintenance card number differs from original transaction card number",
'0050001034': "Operation code not allowed",
'0050001035': "Exception occurred in socket input stream treatment",
'0050001036': "Card length does not correspond to an acceptable value for the brand",
'0050001036': "Card length does not correspond to an acceptable value for the brand",
'0050001068': "A technical problem occurred, please contact helpdesk",
'0050001069': "Invalid check for CardID and Brand",
'0050001070': "A technical problem occurred, please contact helpdesk",
'0050001116': "Unknown origin IP",
'0050001117': "No origin IP detected",
'0050001118': "Merchant configuration problem, please contact support",
'10001001': "Communication failure",
'10001002': "Communication failure",
'10001003': "Communication failure",
'10001004': "Communication failure",
'10001005': "Communication failure",
'20001001': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001002': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001003': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001004': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001005': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001006': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001007': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001008': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001009': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001010': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001101': "A technical problem occurred, please contact helpdesk",
'20001105': "We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction within one working day. Please check the status later.",
'20001111': "A technical problem occurred, please contact helpdesk",
'20002001': "Origin for the response of the bank can not be checked",
'20002002': "Beneficiary account number has been modified during processing",
'20002003': "Amount has been modified during processing",
'20002004': "Currency has been modified during processing",
'20002005': "No feedback from the bank server has been detected",
'30001001': "Payment refused by the acquirer",
'30001002': "Duplicate request",
'30001010': "A technical problem occurred, please contact helpdesk",
'30001011': "A technical problem occurred, please contact helpdesk",
'30001012': "Card black listed - Contact acquirer",
'30001015': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
'30001051': "A technical problem occurred, please contact helpdesk",
'30001054': "A technical problem occurred, please contact helpdesk",
'30001057': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
'30001058': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
'30001060': "Aquirer indicates that a failure occured during payment processing",
'30001070': "RATEPAY Invalid Response Type (Failure)",
'30001071': "RATEPAY Missing Mandatory status code field (failure)",
'30001072': "RATEPAY Missing Mandatory Result code field (failure)",
'30001073': "RATEPAY Response parsing Failed",
'30001090': "CVC check required by front end and returned invalid by acquirer",
'30001091': "ZIP check required by front end and returned invalid by acquirer",
'30001092': "Address check required by front end and returned as invalid by acquirer.",
'30001100': "Unauthorized buyer's country",
'30001101': "IP country <> card country",
'30001102': "Number of different countries too high",
'30001103': "unauthorized card country",
'30001104': "unauthorized ip address country",
'30001105': "Anonymous proxy",
'30001110': "If the problem persists, please contact Support, or go to paysafecard's card balance page (https://customer.cc.at.paysafecard.com/psccustomer/GetWelcomePanelServlet?language=en) to see when the amount reserved on your card will be available again.",
'30001120': "IP address in merchant's black list",
'30001130': "BIN in merchant's black list",
'30001131': "Wrong BIN for 3xCB",
'30001140': "Card in merchant's card blacklist",
'30001141': "Email in blacklist",
'30001142': "Passenger name in blacklist",
'30001143': "Card holder name in blacklist",
'30001144': "Passenger name different from owner name",
'30001145': "Time to departure too short",
'30001149': "Card Configured in Card Supplier Limit for another relation (CSL)",
'30001150': "Card not configured in the system for this customer (CSL)",
'30001151': "REF1 not allowed for this relationship (Contract number",
'30001152': "Card/Supplier Amount limit reached (CSL)",
'30001153': "Card not allowed for this supplier (Date out of contract bounds)",
'30001154': "You have reached the usage limit allowed",
'30001155': "You have reached the usage limit allowed",
'30001156': "You have reached the usage limit allowed",
'30001157': "Unauthorized IP country for itinerary",
'30001158': "email usage limit reached",
'30001159': "Unauthorized card country/IP country combination",
'30001160': "Postcode in highrisk group",
'30001161': "generic blacklist match",
'30001162': "Billing Address is a PO Box",
'30001180': "maximum scoring reached",
'30001997': "Authorization canceled by simulation",
'30001998': "A technical problem occurred, please try again.",
'30001999': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
'30002001': "Payment refused by the financial institution",
'30002001': "Payment refused by the financial institution",
'30021001': "Call acquirer support call number.",
'30022001': "Payment must be approved by the acquirer before execution.",
'30031001': "Invalid merchant number.",
'30041001': "Retain card.",
'30051001': "Authorization declined",
'30071001': "Retain card - special conditions.",
'30121001': "Invalid transaction",
'30131001': "Invalid amount",
'30131002': "You have reached the total amount allowed",
'30141001': "Invalid card number",
'30151001': "Unknown acquiring institution.",
'30171001': "Payment method cancelled by the buyer",
'30171002': "The maximum time allowed is elapsed.",
'30191001': "Try again later.",
'30201001': "A technical problem occurred, please contact helpdesk",
'30301001': "Invalid format",
'30311001': "Unknown acquirer ID.",
'30331001': "Card expired.",
'30341001': "Suspicion of fraud.",
'30341002': "Suspicion of fraud (3rdMan)",
'30341003': "Suspicion of fraud (Perseuss)",
'30341004': "Suspicion of fraud (ETHOCA)",
'30381001': "A technical problem occurred, please contact helpdesk",
'30401001': "Invalid function.",
'30411001': "Lost card.",
'30431001': "Stolen card, pick up",
'30511001': "Insufficient funds.",
'30521001': "No Authorization. Contact the issuer of your card.",
'30541001': "Card expired.",
'30551001': "Invalid PIN.",
'30561001': "Card not in authorizer's database.",
'30571001': "Transaction not permitted on card.",
'30581001': "Transaction not allowed on this terminal",
'30591001': "Suspicion of fraud.",
'30601001': "The merchant must contact the acquirer.",
'30611001': "Amount exceeds card ceiling.",
'30621001': "Restricted card.",
'30631001': "Security policy not respected.",
'30641001': "Amount changed from ref. trn.",
'30681001': "Tardy response.",
'30751001': "PIN entered incorrectly too often",
'30761001': "Card holder already contesting.",
'30771001': "PIN entry required.",
'30811001': "Message flow error.",
'30821001': "Authorization center unavailable",
'30831001': "Authorization center unavailable",
'30901001': "Temporary system shutdown.",
'30911001': "Acquirer unavailable.",
'30921001': "Invalid card type for acquirer.",
'30941001': "Duplicate transaction",
'30961001': "Processing temporarily not possible",
'30971001': "A technical problem occurred, please contact helpdesk",
'30981001': "A technical problem occurred, please contact helpdesk",
'31011001': "Unknown acceptance code",
'31021001': "Invalid currency",
'31031001': "Acceptance code missing",
'31041001': "Inactive card",
'31051001': "Merchant not active",
'31061001': "Invalid expiration date",
'31071001': "Interrupted host communication",
'31081001': "Card refused",
'31091001': "Invalid password",
'31101001': "Plafond transaction (majoré du bonus) dépassé",
'31111001': "Plafond mensuel (majoré du bonus) dépassé",
'31121001': "Plafond centre de facturation dépassé",
'31131001': "Plafond entreprise dépassé",
'31141001': "Code MCC du fournisseur non autorisé pour la carte",
'31151001': "Numéro SIRET du fournisseur non autorisé pour la carte",
'31161001': "This is not a valid online banking account",
'32001004': "A technical problem occurred, please try again.",
'34011001': "Bezahlung mit RatePAY nicht möglich.",
'39991001': "A technical problem occurred, please contact the helpdesk of your acquirer",
'40001001': "A technical problem occurred, please try again.",
'40001002': "A technical problem occurred, please try again.",
'40001003': "A technical problem occurred, please try again.",
'40001004': "A technical problem occurred, please try again.",
'40001005': "A technical problem occurred, please try again.",
'40001006': "A technical problem occurred, please try again.",
'40001007': "A technical problem occurred, please try again.",
'40001008': "A technical problem occurred, please try again.",
'40001009': "A technical problem occurred, please try again.",
'40001010': "A technical problem occurred, please try again.",
'40001011': "A technical problem occurred, please contact helpdesk",
'40001012': "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.",
'40001013': "A technical problem occurred, please contact helpdesk",
'40001016': "A technical problem occurred, please contact helpdesk",
'40001018': "A technical problem occurred, please try again.",
'40001019': "Sorry, an error occurred during processing. Please retry the operation (use back button of the browser). If problem persists, contact your merchant's helpdesk.",
'40001020': "Sorry, an error occurred during processing. Please retry the operation (use back button of the browser). If problem persists, contact your merchant's helpdesk.",
'40001050': "A technical problem occurred, please contact helpdesk",
'40001133': "Authentication failed, the signature of your bank access control server is incorrect",
'40001134': "Authentication failed, please retry or cancel.",
'40001135': "Authentication temporary unavailable, please retry or cancel.",
'40001136': "Technical problem with your browser, please retry or cancel",
'40001137': "Your bank access control server is temporary unavailable, please retry or cancel",
'40001998': "Temporary technical problem. Please retry a little bit later.",
'50001001': "Unknown card type",
'50001002': "Card number format check failed for given card number.",
'50001003': "Merchant data error",
'50001004': "Merchant identification missing",
'50001005': "Expiry date error",
'50001006': "Amount is not a number",
'50001007': "A technical problem occurred, please contact helpdesk",
'50001008': "A technical problem occurred, please contact helpdesk",
'50001009': "A technical problem occurred, please contact helpdesk",
'50001010': "A technical problem occurred, please contact helpdesk",
'50001011': "Brand not supported for that merchant",
'50001012': "A technical problem occurred, please contact helpdesk",
'50001013': "A technical problem occurred, please contact helpdesk",
'50001014': "A technical problem occurred, please contact helpdesk",
'50001015': "Invalid currency code",
'50001016': "A technical problem occurred, please contact helpdesk",
'50001017': "A technical problem occurred, please contact helpdesk",
'50001018': "A technical problem occurred, please contact helpdesk",
'50001019': "A technical problem occurred, please contact helpdesk",
'50001020': "A technical problem occurred, please contact helpdesk",
'50001021': "A technical problem occurred, please contact helpdesk",
'50001022': "A technical problem occurred, please contact helpdesk",
'50001023': "A technical problem occurred, please contact helpdesk",
'50001024': "A technical problem occurred, please contact helpdesk",
'50001025': "A technical problem occurred, please contact helpdesk",
'50001026': "A technical problem occurred, please contact helpdesk",
'50001027': "A technical problem occurred, please contact helpdesk",
'50001028': "A technical problem occurred, please contact helpdesk",
'50001029': "A technical problem occurred, please contact helpdesk",
'50001030': "A technical problem occurred, please contact helpdesk",
'50001031': "A technical problem occurred, please contact helpdesk",
'50001032': "A technical problem occurred, please contact helpdesk",
'50001033': "A technical problem occurred, please contact helpdesk",
'50001034': "A technical problem occurred, please contact helpdesk",
'50001035': "A technical problem occurred, please contact helpdesk",
'50001036': "Card length does not correspond to an acceptable value for the brand",
'50001037': "Purchasing card number for a regular merchant",
'50001038': "Non Purchasing card for a Purchasing card merchant",
'50001039': "Details sent for a non-Purchasing card merchant, please contact helpdesk",
'50001040': "Details not sent for a Purchasing card transaction, please contact helpdesk",
'50001041': "Payment detail validation failed",
'50001042': "Given transactions amounts (tax,discount,shipping,net,etc…) do not compute correctly together",
'50001043': "A technical problem occurred, please contact helpdesk",
'50001044': "No acquirer configured for this operation",
'50001045': "No UID configured for this operation",
'50001046': "Operation not allowed for the merchant",
'50001047': "A technical problem occurred, please contact helpdesk",
'50001048': "A technical problem occurred, please contact helpdesk",
'50001049': "A technical problem occurred, please contact helpdesk",
'50001050': "A technical problem occurred, please contact helpdesk",
'50001051': "A technical problem occurred, please contact helpdesk",
'50001052': "A technical problem occurred, please contact helpdesk",
'50001053': "A technical problem occurred, please contact helpdesk",
'50001054': "Card number incorrect or incompatible",
'50001055': "A technical problem occurred, please contact helpdesk",
'50001056': "A technical problem occurred, please contact helpdesk",
'50001057': "A technical problem occurred, please contact helpdesk",
'50001058': "A technical problem occurred, please contact helpdesk",
'50001059': "A technical problem occurred, please contact helpdesk",
'50001060': "A technical problem occurred, please contact helpdesk",
'50001061': "A technical problem occurred, please contact helpdesk",
'50001062': "A technical problem occurred, please contact helpdesk",
'50001063': "Card Issue Number does not correspond to range or not present",
'50001064': "Start Date not valid or not present",
'50001066': "Format of CVC code invalid",
'50001067': "The merchant is not enrolled for 3D-Secure",
'50001068': "The card number or account number (PAN) is invalid",
'50001069': "Invalid check for CardID and Brand",
'50001070': "The ECI value given is either not supported, or in conflict with other data in the transaction",
'50001071': "Incomplete TRN demat",
'50001072': "Incomplete PAY demat",
'50001073': "No demat APP",
'50001074': "Authorisation too old",
'50001075': "VERRes was an error message",
'50001076': "DCP amount greater than authorisation amount",
'50001077': "Details negative amount",
'50001078': "Details negative quantity",
'50001079': "Could not decode/decompress received PARes (3D-Secure)",
'50001080': "Received PARes was an erereor message from ACS (3D-Secure)",
'50001081': "Received PARes format was invalid according to the 3DS specifications (3D-Secure)",
'50001082': "PAReq/PARes reconciliation failure (3D-Secure)",
'50001084': "Maximum amount reached",
'50001087': "The transaction type requires authentication, please check with your bank.",
'50001090': "CVC missing at input, but CVC check asked",
'50001091': "ZIP missing at input, but ZIP check asked",
'50001092': "Address missing at input, but Address check asked",
'50001095': "Invalid date of birth",
'50001096': "Invalid commodity code",
'50001097': "The requested currency and brand are incompatible.",
'50001111': "Data validation error",
'50001113': "This order has already been processed",
'50001114': "Error pre-payment check page access",
'50001115': "Request not received in secure mode",
'50001116': "Unknown IP address origin",
'50001117': "NO IP address origin",
'50001118': "Pspid not found or not correct",
'50001119': "Password incorrect or disabled due to numbers of errors",
'50001120': "Invalid currency",
'50001121': "Invalid number of decimals for the currency",
'50001122': "Currency not accepted by the merchant",
'50001123': "Card type not active",
'50001124': "Number of lines don't match with number of payments",
'50001125': "Format validation error",
'50001126': "Overflow in data capture requests for the original order",
'50001127': "The original order is not in a correct status",
'50001128': "missing authorization code for unauthorized order",
'50001129': "Overflow in refunds requests",
'50001130': "Error access to original order",
'50001131': "Error access to original history item",
'50001132': "The Selected Catalog is empty",
'50001133': "Duplicate request",
'50001134': "Authentication failed, please retry or cancel.",
'50001135': "Authentication temporary unavailable, please retry or cancel.",
'50001136': "Technical problem with your browser, please retry or cancel",
'50001137': "Your bank access control server is temporary unavailable, please retry or cancel",
'50001150': "Fraud Detection, Technical error (IP not valid)",
'50001151': "Fraud detection : technical error (IPCTY unknown or error)",
'50001152': "Fraud detection : technical error (CCCTY unknown or error)",
'50001153': "Overflow in redo-authorisation requests",
'50001170': "Dynamic BIN check failed",
'50001171': "Dynamic country check failed",
'50001172': "Error in Amadeus signature",
'50001174': "Card Holder Name is too long",
'50001175': "Name contains invalid characters",
'50001176': "Card number is too long",
'50001177': "Card number contains non-numeric info",
'50001178': "Card Number Empty",
'50001179': "CVC too long",
'50001180': "CVC contains non-numeric info",
'50001181': "Expiration date contains non-numeric info",
'50001182': "Invalid expiration month",
'50001183': "Expiration date must be in the future",
'50001184': "SHA Mismatch",
'50001205': "Missing mandatory fields for billing address.",
'50001206': "Missing mandatory field date of birth.",
'50001207': "Missing required shopping basket details.",
'50001208': "Missing social security number",
'50001209': "Invalid country code",
'50001210': "Missing yearly salary",
'50001211': "Missing gender",
'50001212': "Missing email",
'50001213': "Missing IP address",
'50001214': "Missing part payment campaign ID",
'50001215': "Missing invoice number",
'50001216': "The alias must be different than the card number",
'60000001': "account number unknown",
'60000003': "not credited dd-mm-yy",
'60000005': "name/number do not correspond",
'60000007': "account number blocked",
'60000008': "specific direct debit block",
'60000009': "account number WKA",
'60000010': "administrative reason",
'60000011': "account number expired",
'60000012': "no direct debit authorisation given",
'60000013': "debit not approved",
'60000014': "double payment",
'60000018': "name/address/city not entered",
'60001001': "no original direct debit for revocation",
'60001002': "payer’s account number format error",
'60001004': "payer’s account at different bank",
'60001005': "payee’s account at different bank",
'60001006': "payee’s account number format error",
'60001007': "payer’s account number blocked",
'60001008': "payer’s account number expired",
'60001009': "payee’s account number expired",
'60001010': "direct debit not possible",
'60001011': "creditor payment not possible",
'60001012': "payer’s account number unknown WKA-number",
'60001013': "payee’s account number unknown WKA-number",
'60001014': "impermissible WKA transaction",
'60001015': "period for revocation expired",
'60001017': "reason for revocation not correct",
'60001018': "original run number not numeric",
'60001019': "payment ID incorrect",
'60001020': "amount not numeric",
'60001021': "amount zero not permitted",
'60001022': "negative amount not permitted",
'60001023': "payer and payee giro account number",
'60001025': "processing code (verwerkingscode) incorrect",
'60001028': "revocation not permitted",
'60001029': "guaranteed direct debit on giro account number",
'60001030': "NBC transaction type incorrect",
'60001031': "description too large",
'60001032': "book account number not issued",
'60001034': "book account number incorrect",
'60001035': "payer’s account number not numeric",
'60001036': "payer’s account number not eleven-proof",
'60001037': "payer’s account number not issued",
'60001039': "payer’s account number of DNB/BGC/BLA",
'60001040': "payee’s account number not numeric",
'60001041': "payee’s account number not eleven-proof",
'60001042': "payee’s account number not issued",
'60001044': "payee’s account number unknown",
'60001050': "payee’s name missing",
'60001051': "indicate payee’s bank account number instead of 3102",
'60001052': "no direct debit contract",
'60001053': "amount beyond bounds",
'60001054': "selective direct debit block",
'60001055': "original run number unknown",
'60001057': "payer’s name missing",
'60001058': "payee’s account number missing",
'60001059': "restore not permitted",
'60001060': "bank’s reference (navraaggegeven) missing",
'60001061': "BEC/GBK number incorrect",
'60001062': "BEC/GBK code incorrect",
'60001087': "book account number not numeric",
'60001090': "cancelled on request",
'60001091': "cancellation order executed",
'60001092': "cancelled instead of bended",
'60001093': "book account number is a shortened account number",
'60001094': "instructing party account number not identical with payer",
'60001095': "payee unknown GBK acceptor",
'60001097': "instructing party account number not identical with payee",
'60001099': "clearing not permitted",
'60001101': "payer’s account number not spaces",
'60001102': "PAN length not numeric",
'60001103': "PAN length outside limits",
'60001104': "track number not numeric",
'60001105': "track number not valid",
'60001106': "PAN sequence number not numeric",
'60001107': "domestic PAN not numeric",
'60001108': "domestic PAN not eleven-proof",
'60001109': "domestic PAN not issued",
'60001110': "foreign PAN not numeric",
'60001111': "card valid date not numeric",
'60001112': "book period number (boekperiodenr) not numeric",
'60001113': "transaction number not numeric",
'60001114': "transaction time not numeric",
'60001115': "transaction no valid time",
'60001116': "transaction date not numeric",
'60001117': "transaction no valid date",
'60001118': "STAN not numeric",
'60001119': "instructing party’s name missing",
'60001120': "foreign amount (bedrag-vv) not numeric",
'60001122': "rate (verrekenkoers) not numeric",
'60001125': "number of decimals (aantaldecimalen) incorrect",
'60001126': "tariff (tarifering) not B/O/S",
'60001127': "domestic costs (kostenbinnenland) not numeric",
'60001128': "domestic costs (kostenbinnenland) not higher than zero",
'60001129': "foreign costs (kostenbuitenland) not numeric",
'60001130': "foreign costs (kostenbuitenland) not higher than zero",
'60001131': "domestic costs (kostenbinnenland) not zero",
'60001132': "foreign costs (kostenbuitenland) not zero",
'60001134': "Euro record not fully filled in",
'60001135': "Client currency incorrect",
'60001136': "Amount NLG not numeric",
'60001137': "Amount NLG not higher than zero",
'60001138': "Amount NLG not equal to Amount",
'60001139': "Amount NLG incorrectly converted",
'60001140': "Amount EUR not numeric",
'60001141': "Amount EUR not greater than zero",
'60001142': "Amount EUR not equal to Amount",
'60001143': "Amount EUR incorrectly converted",
'60001144': "Client currency not NLG",
'60001145': "rate euro-vv (Koerseuro-vv) not numeric",
'60001146': "comma rate euro-vv (Kommakoerseuro-vv) incorrect",
'60001147': "acceptgiro distributor not valid",
'60001148': "Original run number and/or BRN are missing",
'60001149': "Amount/Account number/ BRN different",
'60001150': "Direct debit already revoked/restored",
'60001151': "Direct debit already reversed/revoked/restored",
'60001153': "Payer’s account number not known",
}
DATA_VALIDATION_ERROR = '50001111'
def retryable(error):
return error in [
'0020001001', '0020001002', '0020001003', '0020001004', '0020001005',
'0020001006', '0020001007', '0020001008', '0020001009', '0020001010',
'30001010', '30001011', '30001015',
'30001057', '30001058',
'30001998', '30001999',
#'30611001', # amount exceeds card limit
'30961001',
'40001001', '40001002', '40001003', '40001004', '40001005',
'40001006', '40001007', '40001008', '40001009', '40001010',
'40001012',
'40001018', '40001019', '40001020',
'40001134', '40001135', '40001136', '40001137',
#'50001174', # cardholder name too long
]
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<record id="payment_acquirer_ogone" model="payment.acquirer">
<field name="name">ogone</field>
<field name="view_template_id" ref="ogone_acquirer_button"/>
<field name="env">test</field>
<field name='ogone_pspid'>dummy</field>
<field name='ogone_userid'>dummy</field>
<field name='ogone_password'>dummy</field>
<field name="ogone_shakey_in">tINY4Yv14789gUix1130</field>
<field name="ogone_shakey_out">tINYj885Tfvd4P471464</field>
</record>
</data>
</openerp>
@@ -0,0 +1,9 @@
.. _changelog:
Changelog
=========
`trunk (saas-3)`
----------------
- Module creation
@@ -0,0 +1,14 @@
Payment module documentation
============================
Payment documentation topics
''''''''''''''''''''''''''''
Changelog
'''''''''
.. toctree::
:maxdepth: 1
changelog.rst
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import ogone
@@ -0,0 +1,408 @@
# -*- coding: utf-'8' "-*-"
from hashlib import sha1
import logging
from lxml import etree, objectify
from pprint import pformat
import time
from urllib import urlencode
import urllib2
import urlparse
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
from openerp.addons.payment_acquirer_ogone.controllers.main import OgoneController
from openerp.addons.payment_acquirer_ogone.data import ogone
from openerp.osv import osv, fields
from openerp.tools import float_round
_logger = logging.getLogger(__name__)
class PaymentAcquirerOgone(osv.Model):
_inherit = 'payment.acquirer'
def _get_ogone_urls(self, cr, uid, ids, name, args, context=None):
""" Ogone URLS:
- standard order: POST address for form-based
@TDETODO: complete me
"""
res = {}
for acquirer in self.browse(cr, uid, ids, context=context):
qualif = acquirer.env
res[acquirer.id] = {
'ogone_standard_order_url': 'https://secure.ogone.com/ncol/%s/orderstandard.asp' % qualif,
'ogone_direct_order_url': 'https://secure.ogone.com/ncol/%s/orderdirect.asp' % qualif,
'ogone_direct_query_url': 'https://secure.ogone.com/ncol/%s/querydirect.asp' % qualif,
'ogone_afu_agree_url': 'https://secure.ogone.com/ncol/%s/AFU_agree.asp' % qualif,
}
return res
_columns = {
'ogone_pspid': fields.char(
'PSPID', required_if_provider='ogone'),
'ogone_userid': fields.char(
'API User id', required_if_provider='ogone'),
'ogone_password': fields.char(
'Password', required_if_provider='ogone'),
'ogone_shakey_in': fields.char(
'SHA Key IN', size=32, required_if_provider='ogone'),
'ogone_shakey_out': fields.char(
'SHA Key OUT', size=32, required_if_provider='ogone'),
# store ogone contact URLs -> not necessary IMHO
'ogone_standard_order_url': fields.function(
_get_ogone_urls, type='char', multi='_get_ogone_urls',
string='Stanrd Order URL (form)'),
'ogone_direct_order_url': fields.function(
_get_ogone_urls, type='char', multi='_get_ogone_urls',
string='Direct Order URL (2)'),
'ogone_direct_query_url': fields.function(
_get_ogone_urls, type='char', multi='_get_ogone_urls',
string='Direct Query URL'),
'ogone_afu_agree_url': fields.function(
_get_ogone_urls, type='char', multi='_get_ogone_urls',
string='AFU Agree URL'),
}
def _ogone_generate_shasign(self, acquirer, inout, values):
""" Generate the shasign for incoming or outgoing communications.
:param browse acquirer: the payment.acquirer browse record. It should
have a shakey in shaky out
:param string inout: 'in' (openerp contacting ogone) or 'out' (ogone
contacting openerp). In this last case only some
fields should be contained (see e-Commerce basic)
:param dict values: transaction values
:return string: shasign
"""
assert inout in ('in', 'out')
assert acquirer.name == 'ogone'
key = getattr(acquirer, 'ogone_shakey_' + inout)
def filter_key(key):
if inout == 'in':
return True
else:
keys = "ORDERID CURRENCY AMOUNT PM ACCEPTANCE STATUS CARDNO ALIAS ED CN TRXDATE PAYID NCERROR BRAND ECI IP COMPLUS".split()
return key.upper() in keys
items = sorted((k.upper(), v) for k, v in values.items())
sign = ''.join('%s=%s%s' % (k, v, key) for k, v in items if v and filter_key(k))
shasign = sha1(sign).hexdigest()
return shasign
def ogone_form_generate_values(self, cr, uid, id, reference, amount, currency, partner_id=False, partner_values=None, tx_custom_values=None, context=None):
if partner_values is None:
partner_values = {}
base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
acquirer = self.browse(cr, uid, id, context=context)
partner = None
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
tx_values = {
'PSPID': acquirer.ogone_pspid,
'ORDERID': reference,
'AMOUNT': '%d' % int(float_round(amount, 2) * 100),
'CURRENCY': currency and currency.name or 'EUR',
'LANGUAGE': partner and partner.lang or partner_values.get('lang', ''),
'CN': partner and partner.name or partner_values.get('name', ''),
'EMAIL': partner and partner.email or partner_values.get('email', ''),
'OWNERZIP': partner and partner.zip or partner_values.get('zip', ''),
'OWNERADDRESS': partner and ' '.join((partner.street or '', partner.street2 or '')).strip() or ' '.join((partner_values.get('street', ''), partner_values.get('street2', ''))).strip(),
'OWNERTOWN': partner and partner.city or partner_values.get('city', ''),
'OWNERCTY': partner and partner.country_id and partner.country_id.name or partner_values.get('country_name', ''),
'OWNERTELNO': partner and partner.phone or partner_values.get('phone', ''),
'ACCEPTURL': '%s' % urlparse.urljoin(base_url, OgoneController._accept_url),
'DECLINEURL': '%s' % urlparse.urljoin(base_url, OgoneController._decline_url),
'EXCEPTIONURL': '%s' % urlparse.urljoin(base_url, OgoneController._exception_url),
'CANCELURL': '%s' % urlparse.urljoin(base_url, OgoneController._cancel_url),
}
if tx_custom_values and tx_custom_values.get('return_url'):
tx_values['PARAMPLUS'] = 'return_url=%s' % tx_custom_values.pop('return_url')
if tx_custom_values:
tx_values.update(tx_custom_values)
shasign = self._ogone_generate_shasign(acquirer, 'in', tx_values)
tx_values['SHASIGN'] = shasign
return tx_values
def ogone_get_form_action_url(self, cr, uid, id, context=None):
acquirer = self.browse(cr, uid, id, context=context)
return acquirer.ogone_standard_order_url
class PaymentTxOgone(osv.Model):
_inherit = 'payment.transaction'
# ogone status
_ogone_valid_tx_status = [5, 9]
_ogone_wait_tx_status = [41, 50, 51, 52, 55, 56, 91, 92, 99]
_ogone_pending_tx_status = [46] # 3DS HTML response
_ogone_cancel_tx_status = [1]
_columns = {
'ogone_3ds': fields.dummy('3ds Activated'),
'ogone_3ds_html': fields.html('3DS HTML'),
'ogone_feedback_model': fields.char(),
'ogone_feedback_eval': fields.char(),
'ogone_complus': fields.char('Complus'),
'ogone_payid': fields.char('PayID', help='Payment ID, generated by Ogone')
}
# --------------------------------------------------
# FORM RELATED METHODS
# --------------------------------------------------
def ogone_form_generate_values(self, cr, uid, id, tx_custom_values=None, context=None):
""" Ogone-specific value generation for rendering a transaction-based
form button. """
tx = self.browse(cr, uid, id, context=context)
tx_data = {
'LANGUAGE': tx.partner_lang,
'CN': tx.partner_name,
'EMAIL': tx.partner_email,
'OWNERZIP': tx.partner_zip,
'OWNERADDRESS': tx.partner_address,
'OWNERTOWN': tx.partner_city,
'OWNERCTY': tx.partner_country_id and tx.partner_country_id.name or '',
'OWNERTELNO': tx.partner_phone,
}
if tx_custom_values:
tx_data.update(tx_custom_values)
return self.pool['payment.acquirer'].ogone_form_generate_values(
cr, uid, tx.acquirer_id.id,
tx.reference, tx.amount, tx.currency_id,
tx_custom_values=tx_data,
context=context
)
def _ogone_form_get_tx_from_data(self, cr, uid, data, context=None):
""" Given a data dict coming from ogone, verify it and find the related
transaction record. """
reference, pay_id, shasign = data.get('orderID'), data.get('PAYID'), data.get('SHASIGN')
if not reference or not pay_id or not shasign:
error_msg = 'Ogone: received data with missing reference (%s) or pay_id (%s) or shashign (%s)' % (reference, pay_id, shasign)
_logger.error(error_msg)
raise ValidationError(error_msg)
# find tx -> @TDENOTE use paytid ?
tx_ids = self.search(cr, uid, [('reference', '=', reference)], context=context)
if not tx_ids or len(tx_ids) > 1:
error_msg = 'Ogone: received data for reference %s' % (reference)
if not tx_ids:
error_msg += '; no order found'
else:
error_msg += '; multiple order found'
_logger.error(error_msg)
raise ValidationError(error_msg)
tx = self.pool['payment.transaction'].browse(cr, uid, tx_ids[0], context=context)
# verify shasign
shasign_check = self.pool['payment.acquirer']._ogone_generate_shasign(tx.acquirer_id, 'out', data)
if shasign_check.upper() != shasign.upper():
error_msg = 'Ogone: invalid shasign, received %s, computed %s, for data %s' % (shasign, shasign_check, data)
_logger.error(error_msg)
raise ValidationError(error_msg)
return tx
def ogone_form_feedback(self, cr, uid, data, context=None):
tx = self._ogone_form_get_tx_from_data(cr, uid, data, context)
if not tx:
raise ValidationError('Ogone: feedback: tx not found')
if tx.state == 'done':
_logger.warning('Ogone: trying to validate an already validated tx (ref %s' % tx.reference)
return False
status = int(data.get('STATUS', '0'))
if status in self._ogone_valid_tx_status:
tx.write({
'state': 'done',
'date_validate': data['TRXDATE'],
'ogone_payid': data['PAYID'],
})
return True
elif status in self._ogone_cancel_tx_status:
tx.write({
'state': 'cancel',
})
elif status in self._ogone_pending_tx_status:
tx.write({
'state': 'pending',
})
else:
error = 'Ogone: feedback error: %(error_str)s\n\n%(error_code)s: %(error_msg)s' % {
'error_str': data.get('NCERROR'),
'error_code': data.get('NCERRORPLUS'),
'error_msg': ogone.OGONE_ERROR_MAP.get(data.get('NCERRORPLUS')),
}
_logger.info(error)
tx.write({'state': 'error', 'state_message': error})
return False
# --------------------------------------------------
# S2S RELATED METHODS
# --------------------------------------------------
def ogone_s2s_create_alias(self, cr, uid, id, values, context=None):
""" Purpose: create an alias via batch """
tx = self.browse(cr, uid, id, context=context)
assert tx.type == 'server2server', 'Calling s2s dedicated method for a %s acquirer' % tx.type
alias = 'OPENERP-%d-%d' % (tx.partner_id.id, tx.id)
expiry_date = '%s%s' % (values['expiry_date_mm'], values['expiry_date_yy'][2:])
line = 'ADDALIAS;%(alias)s;%(holder_name)s;%(number)s;%(expiry_date)s;%(brand)s;%(pspid)s'
line = line % dict(values, alias=alias, expiry_date=expiry_date, pspid=tx.acquirer_id.ogone_pspid)
tx_data = {
'FILE_REFERENCE': 'OPENERP-NEW-ALIAS-%s' % time.time(), # something unique,
'TRANSACTION_CODE': 'ATR',
'OPERATION': 'SAL',
'NB_PAYMENTS': 1, # even if we do not actually have any payment, ogone want it to not be 0
'FILE': line,
'REPLY_TYPE': 'XML',
'PSPID': tx.acquirer_id.ogone_pspid,
'USERID': tx.acquirer_id.ogone_userid,
'PSWD': tx.acquirer_id.ogone_password,
'PROCESS_MODE': 'CHECKANDPROCESS',
}
request = urllib2.Request(tx.acquirer_id.ogone_afu_agree_url, urlencode(tx_data))
result = urllib2.urlopen(request).read()
try:
tree = objectify.fromstring(result)
except etree.XMLSyntaxError:
_logger.exception('Invalid xml response from ogone')
return None
error_code = error_str = None
if hasattr(tree, 'PARAMS_ERROR'):
error_code = tree.NCERROR.text
error_str = 'PARAMS ERROR: %s' % (tree.PARAMS_ERROR.text or '',)
else:
node = tree.FORMAT_CHECK
error_node = getattr(node, 'FORMAT_CHECK_ERROR', None)
if error_node is not None:
error_code = error_node.NCERROR.text
error_str = 'CHECK ERROR: %s' % (error_node.ERROR.text or '',)
if error_code:
error_msg = ogone.OGONE_ERROR_MAP.get(error_code)
error = '%s\n\n%s: %s' % (error_str, error_code, error_msg)
_logger.error(error)
raise Exception(error) # TODO specific exception
tx.write({'partner_reference': alias})
return True
def ogone_s2s_generate_values(self, cr, uid, id, custom_values, context=None):
tx = self.browse(cr, uid, id, context=context)
tx_data = {
'PSPID': tx.acquirer_id.ogone_pspid,
'USERID': tx.acquirer_id.ogone_userid,
'PSWD': tx.acquirer_id.ogone_password,
'OrderID': tx.reference,
'amount': '%d' % int(float_round(tx.amount, 2) * 100), # tde check amount or str * 100 ?
'CURRENCY': tx.currency_id.name,
'LANGUAGE': tx.partner_lang,
'OPERATION': 'SAL',
'ECI': 2, # Recurring (from MOTO)
'ALIAS': tx.partner_reference,
'RTIMEOUT': 30,
}
if custom_values.get('ogone_cvc'):
tx_data['CVC'] = custom_values.get('ogone_cvc')
if custom_values.pop('ogone_3ds', None):
tx_data.update({
'FLAG3D': 'Y', # YEAH!!
})
if custom_values.get('ogone_complus'):
tx_data['COMPLUS'] = custom_values.get('ogone_complus')
if custom_values.get('ogone_accept_url'):
pass
shasign = self.pool['payment.acquirer']._ogone_generate_shasign(tx.acquirer_id, 'in', tx_data)
tx_data['SHASIGN'] = shasign
return tx_data
def ogone_s2s_feedback(self, cr, uid, data, context=None):
pass
def ogone_s2s_execute(self, cr, uid, id, values, context=None):
tx = self.browse(cr, uid, id, context=context)
tx_data = self.ogone_s2s_generate_values(cr, uid, id, values, context=context)
_logger.info('Generated Ogone s2s data %s', pformat(tx_data)) # debug
request = urllib2.Request(tx.acquirer_id.ogone_direct_order_url, urlencode(tx_data))
result = urllib2.urlopen(request).read()
_logger.info('Contacted Ogone direct order; result %s', result) # debug
tree = objectify.fromstring(result)
payid = tree.get('PAYID')
query_direct_data = dict(
PSPID=tx.acquirer_id.ogone_pspid,
USERID=tx.acquirer_id.ogone_userid,
PSWD=tx.acquirer_id.ogone_password,
ID=payid,
)
query_direct_url = 'https://secure.ogone.com/ncol/%s/querydirect.asp' % (tx.acquirer_id.env,)
tries = 2
tx_done = False
tx_status = False
while not tx_done or tries > 0:
try:
tree = objectify.fromstring(result)
except etree.XMLSyntaxError:
# invalid response from ogone
_logger.exception('Invalid xml response from ogone')
raise
# see https://secure.ogone.com/ncol/paymentinfos1.asp
VALID_TX = [5, 9]
WAIT_TX = [41, 50, 51, 52, 55, 56, 91, 92, 99]
PENDING_TX = [46] # 3DS HTML response
# other status are errors...
status = tree.get('STATUS')
if status == '':
status = None
else:
status = int(status)
if status in VALID_TX:
tx_status = True
tx_done = True
elif status in PENDING_TX:
html = str(tree.HTML_ANSWER)
tx_data.update(ogone_3ds_html=html.decode('base64'))
tx_status = False
tx_done = True
elif status in WAIT_TX:
time.sleep(1500)
request = urllib2.Request(query_direct_url, urlencode(query_direct_data))
result = urllib2.urlopen(request).read()
_logger.debug('Contacted Ogone query direct; result %s', result)
else:
error_code = tree.get('NCERROR')
if not ogone.retryable(error_code):
error_str = tree.get('NCERRORPLUS')
error_msg = ogone.OGONE_ERROR_MAP.get(error_code)
error = 'ERROR: %s\n\n%s: %s' % (error_str, error_code, error_msg)
_logger.info(error)
raise Exception(error)
tries = tries - 1
if not tx_done and tries == 0:
raise Exception('Cannot get transaction status...')
return tx_status
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from . import test_ogone
checks = [
test_ogone,
]
@@ -0,0 +1,233 @@
# -*- coding: utf-8 -*-
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
from openerp.addons.payment_acquirer.tests.common import PaymentAcquirerCommon
from openerp.addons.payment_acquirer_ogone.controllers.main import OgoneController
from openerp.tools import mute_logger
from lxml import objectify
# import requests
import time
import urlparse
class OgonePayment(PaymentAcquirerCommon):
def setUp(self):
super(OgonePayment, self).setUp()
cr, uid = self.cr, self.uid
self.base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url')
model, self.ogone_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_ogone', 'ogone_acquirer_button')
# create a new ogone account
self.ogone_id = self.payment_acquirer.create(
cr, uid, {
'name': 'ogone',
'env': 'test',
'view_template_id': self.ogone_view_id,
'ogone_pspid': 'dummy',
'ogone_userid': 'dummy',
'ogone_password': 'dummy',
'ogone_shakey_in': 'tINY4Yv14789gUix1130',
'ogone_shakey_out': 'tINYj885Tfvd4P471464',
})
self.ogone_url = self.payment_acquirer._get_ogone_urls(cr, uid, [self.ogone_id], None, None)[self.ogone_id]['ogone_standard_order_url']
def test_00_ogone_acquirer(self):
ogone = self.payment_acquirer.browse(self.cr, self.uid, self.ogone_id, None)
self.assertEqual(ogone.env, 'test', 'test without test env')
def test_10_ogone_form_render(self):
cr, uid, context = self.cr, self.uid, {}
# ----------------------------------------
# Test: button direct rendering + shasign
# ----------------------------------------
form_values = {
'PSPID': 'dummy',
'ORDERID': 'test_ref0',
'AMOUNT': '1',
'CURRENCY': 'EUR',
'LANGUAGE': 'en_US',
'CN': 'Norbert Buyer',
'EMAIL': 'norbert.buyer@example.com',
'OWNERZIP': '1000',
'OWNERADDRESS': 'Huge Street 2/543',
'OWNERCTY': 'Belgium',
'OWNERTOWN': 'Sin City',
'OWNERTELNO': '0032 12 34 56 78',
'SHASIGN': '815f67b8ff70d234ffcf437c13a9fa7f807044cc',
'ACCEPTURL': '%s' % urlparse.urljoin(self.base_url, OgoneController._accept_url),
'DECLINEURL': '%s' % urlparse.urljoin(self.base_url, OgoneController._decline_url),
'EXCEPTIONURL': '%s' % urlparse.urljoin(self.base_url, OgoneController._exception_url),
'CANCELURL': '%s' % urlparse.urljoin(self.base_url, OgoneController._cancel_url),
}
# render the button
res = self.payment_acquirer.render(
cr, uid, self.ogone_id,
'test_ref0', 0.01, self.currency_euro,
partner_id=None,
partner_values=self.buyer_values,
context=context)
# check form result
tree = objectify.fromstring(res)
self.assertEqual(tree.get('action'), 'https://secure.ogone.com/ncol/test/orderstandard.asp', 'ogone: wrong form POST url')
for form_input in tree.input:
if form_input.get('name') in ['submit']:
continue
self.assertEqual(
form_input.get('value'),
form_values[form_input.get('name')],
'ogone: wrong value for form: received %s instead of %s' % (form_input.get('value'), form_values[form_input.get('name')])
)
# ----------------------------------------
# Test2: button using tx + validation
# ----------------------------------------
# create a new draft tx
tx_id = self.payment_transaction.create(
cr, uid, {
'amount': 0.01,
'acquirer_id': self.ogone_id,
'currency_id': self.currency_euro_id,
'reference': 'test_ref0',
'partner_id': self.buyer_id,
}, context=context
)
# render the button
res = self.payment_acquirer.render(
cr, uid, self.ogone_id,
'should_be_erased', 0.01, self.currency_euro,
tx_id=tx_id,
partner_id=None,
partner_values=self.buyer_values,
context=context)
# check form result
tree = objectify.fromstring(res)
self.assertEqual(tree.get('action'), 'https://secure.ogone.com/ncol/test/orderstandard.asp', 'ogone: wrong form POST url')
for form_input in tree.input:
if form_input.get('name') in ['submit']:
continue
self.assertEqual(
form_input.get('value'),
form_values[form_input.get('name')],
'ogone: wrong value for form input %s: received %s instead of %s' % (form_input.get('name'), form_input.get('value'), form_values[form_input.get('name')])
)
@mute_logger('openerp.addons.payment_acquirer_ogone.models.ogone', 'ValidationError')
def test_20_ogone_form_management(self):
cr, uid, context = self.cr, self.uid, {}
# typical data posted by ogone after client has successfully paid
ogone_post_data = {
'orderID': u'test_ref_2',
'STATUS': u'9',
'CARDNO': u'XXXXXXXXXXXX0002',
'PAYID': u'25381582',
'CN': u'Norbert Buyer',
'NCERROR': u'0',
'TRXDATE': u'11/15/13',
'IP': u'85.201.233.72',
'BRAND': u'VISA',
'ACCEPTANCE': u'test123',
'currency': u'EUR',
'amount': u'1.95',
'SHASIGN': u'7B7B0ED9CBC4A85543A9073374589033A62A05A5',
'ED': u'0315',
'PM': u'CreditCard'
}
# should raise error about unknown tx
with self.assertRaises(ValidationError):
self.payment_transaction.ogone_form_feedback(cr, uid, ogone_post_data, context=context)
# create tx
tx_id = self.payment_transaction.create(
cr, uid, {
'amount': 1.95,
'acquirer_id': self.ogone_id,
'currency_id': self.currency_euro_id,
'reference': 'test_ref_2',
'partner_name': 'Norbert Buyer',
}, context=context
)
# validate it
self.payment_transaction.ogone_form_feedback(cr, uid, ogone_post_data, context=context)
# check state
tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
self.assertEqual(tx.state, 'done', 'ogone: validation did not put tx into done state')
self.assertEqual(tx.ogone_payid, ogone_post_data.get('PAYID'), 'ogone: validation did not update tx payid')
# reset tx
tx.write({'state': 'draft', 'date_validate': False, 'ogone_payid': False})
# now ogone post is ok: try to modify the SHASIGN
ogone_post_data['SHASIGN'] = 'a4c16bae286317b82edb49188d3399249a784691'
with self.assertRaises(ValidationError):
self.payment_transaction.ogone_form_feedback(cr, uid, ogone_post_data, context=context)
# simulate an error
ogone_post_data['STATUS'] = 2
ogone_post_data['SHASIGN'] = 'a4c16bae286317b82edb49188d3399249a784691'
self.payment_transaction.ogone_form_feedback(cr, uid, ogone_post_data, context=context)
# check state
tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
self.assertEqual(tx.state, 'error', 'ogone: erroneous validation did not put tx into error state')
def test_30_ogone_s2s(self):
test_ref = 'test_ref_%.15f' % time.time()
cr, uid, context = self.cr, self.uid, {}
# create a new draft tx
tx_id = self.payment_transaction.create(
cr, uid, {
'amount': 0.01,
'acquirer_id': self.ogone_id,
'currency_id': self.currency_euro_id,
'reference': test_ref,
'partner_id': self.buyer_id,
'type': 'server2server',
}, context=context
)
# create an alias
res = self.payment_transaction.ogone_s2s_create_alias(
cr, uid, tx_id, {
'expiry_date_mm': '01',
'expiry_date_yy': '2015',
'holder_name': 'Norbert Poilu',
'number': '4000000000000002',
'brand': 'VISA',
}, context=context)
# check an alias is set, containing at least OPENERP
tx = self.payment_transaction.browse(cr, uid, tx_id, context=context)
self.assertIn('OPENERP', tx.partner_reference, 'ogone: wrong partner reference after creating an alias')
res = self.payment_transaction.ogone_s2s_execute(cr, uid, tx_id, {}, context=context)
# print res
# {
# 'orderID': u'reference',
# 'STATUS': u'9',
# 'CARDNO': u'XXXXXXXXXXXX0002',
# 'PAYID': u'24998692',
# 'CN': u'Norbert Poilu',
# 'NCERROR': u'0',
# 'TRXDATE': u'11/05/13',
# 'IP': u'85.201.233.72',
# 'BRAND': u'VISA',
# 'ACCEPTANCE': u'test123',
# 'currency': u'EUR',
# 'amount': u'1.95',
# 'SHASIGN': u'EFDC56879EF7DE72CCF4B397076B5C9A844CB0FA',
# 'ED': u'0314',
# 'PM': u'CreditCard'
# }
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<template id="ogone_acquirer_button">
<form t-if="acquirer" t-att-action="acquirer.ogone_standard_order_url" method="post" target="_self">
<!-- seller -->
<input type='hidden' name='PSPID' t-att-value='tx_values["PSPID"]'/>
<input type='hidden' name='ORDERID' t-att-value='tx_values["ORDERID"]'/>
<!-- cart -->
<input type='hidden' name='AMOUNT' t-att-value='tx_values["AMOUNT"]'/>
<input type='hidden' name='CURRENCY' t-att-value='tx_values["CURRENCY"]'/>
<!-- buyer -->
<input type='hidden' name='LANGUAGE' t-att-value='tx_values["LANGUAGE"]'/>
<input type='hidden' name='CN' t-att-value='tx_values["CN"]'/>
<input type='hidden' name='EMAIL' t-att-value='tx_values["EMAIL"]'/>
<input type='hidden' name='OWNERZIP' t-att-value='tx_values["OWNERZIP"]'/>
<input type='hidden' name='OWNERADDRESS' t-att-value='tx_values["OWNERADDRESS"]'/>
<input type='hidden' name='OWNERCTY' t-att-value='tx_values["OWNERCTY"]'/>
<input type='hidden' name='OWNERTOWN' t-att-value='tx_values["OWNERTOWN"]'/>
<input type='hidden' name='OWNERTELNO' t-att-value='tx_values["OWNERTELNO"]'/>
<!-- before payment verification -->
<input type='hidden' name='SHASIGN' t-att-value='tx_values["SHASIGN"]'/>
<!-- look and print -->
<!-- <input type='hidden' name='TITLE' t-att-value='tx_dict["currency_name"]'/>
<input type='hidden' name='BGCOLOR' t-att-value='tx_dict["currency_name"]'/>
<input type='hidden' name='TXTCOLOR' t-att-value='tx_dict["currency_name"]'/>
<input type='hidden' name='TBLBGCOLOR' t-att-value='tx_dict["currency_name"]'/>
<input type='hidden' name='TBLTXTCOLOR' t-att-value='tx_dict["currency_name"]'/>
<input type='hidden' name='BUTTONBGCOLOR' t-att-value='tx_dict["currency_name"]'/>
<input type='hidden' name='BUTTONTXTCOLOR' t-att-value='tx_dict["currency_name"]'/>
<input type='hidden' name='LOGO' t-att-value='tx_dict["currency_name"]'/>
<input type='hidden' name='FONTTYPE' t-att-value='tx_dict["currency_name"]'/> -->
<!-- after payment parameters -->
<t t-if='tx_values.get("PARAMPLUS")'>
<input type='hidden' name="PARAMPLUS" t-att-value='tx_values["PARAMPLUS"]'/>
</t>
<!-- redirection -->
<input type='hidden' name='ACCEPTURL' t-att-value='tx_values["ACCEPTURL"]'/>
<input type='hidden' name='DECLINEURL' t-att-value='tx_values["DECLINEURL"]'/>
<input type='hidden' name='EXCEPTIONURL' t-att-value='tx_values["EXCEPTIONURL"]'/>
<input type='hidden' name='CANCELURL' t-att-value='tx_values["CANCELURL"]'/>
<input type="image" name="submit" id="payment_submit"
src="/payment_acquirer_ogone/static/src/img/ogone_logo_plain.gif"/>
</form>
</template>
</data>
</openerp>
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="acquirer_form_ogone" model="ir.ui.view">
<field name="name">acquirer.form.ogone</field>
<field name="model">payment.acquirer</field>
<field name="inherit_id" ref="payment_acquirer.acquirer_form"/>
<field name="arch" type="xml">
<xpath expr='//group[@name="acquirer_base"]' position='after'>
<group string="Ogone Details"
attrs="{'invisible': [('name', '!=', 'ogone')]}">
<field name="ogone_pspid"/>
<field name="ogone_userid"/>
<field name="ogone_password"/>
<field name="ogone_shakey_in"/>
<field name="ogone_shakey_out"/>
</group>
</xpath>
</field>
</record>
<record id="transaction_form_ogone" model="ir.ui.view">
<field name="name">acquirer.transaction.form.ogone</field>
<field name="model">payment.transaction</field>
<field name="inherit_id" ref="payment_acquirer.transaction_form"/>
<field name="arch" type="xml">
<xpath expr='//notebook' position='inside'>
<page string="Ogone TX Details">
<group>
<field name="ogone_payid"/>
<!-- <field name="ogone_3ds"/>
<field name="ogone_3ds_html"/> -->
</group>
</page>
</xpath>
</field>
</record>
</data>
</openerp>
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import models
import controllers
@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
{
'name': 'Paypal Payment Acquirer',
'category': 'Hidden',
'summary': 'Payment Acquirer: Paypal Implementation',
'version': '1.0',
'description': """Paypal Payment Acquirer""",
'author': 'OpenERP SA',
'depends': ['payment_acquirer'],
'data': [
'views/paypal.xml',
'views/payment_acquirer.xml',
'data/paypal.xml',
],
'installable': True,
}
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import main
@@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.addons.web import http
from openerp.addons.web.http import request
# from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
from openerp.addons.website.models import website
import logging
import requests
from urllib import urlencode
_logger = logging.getLogger(__name__)
class PaypalController(http.Controller):
_notify_url = '/payment/paypal/ipn/'
_return_url = '/payment/paypal/dpn/'
_cancel_url = '/payment/paypal/cancel/'
@website.route([
'/payment/paypal/ipn/',
], type='http', auth='public')
def paypal_ipn(self, **post):
print 'Entering paypal_ipn with post', post
# step 1: return an empty HTTP 200 response -> will be done at the end by returning ''
# step 2: POST the complete, unaltered message back to Paypal (preceded by cmd=_notify-validate), with same encoding
paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr"
post_url = '%s?cmd=_notify-validate&%s' % (paypal_url, urlencode(post))
resp = requests.post(post_url)
print '\tReceived response', resp, resp.text
# step 3: paypal send either VERIFIED or INVALID (single word)
if resp.text == 'VERIFIED':
_logger.info('Paypal: received verified IPN')
cr, uid, context = request.cr, request.uid, request.context
payment_transaction = request.registry['payment.transaction']
res = payment_transaction.paypal_form_feedback(cr, uid, post, context=context)
print '\tValidation result', res
elif resp.text == 'INVALID':
_logger.warning('Paypal: received invalid IPN with post %s' % post)
else:
_logger.warning('Paypal: received unrecognized IPN with post %s' % post)
return ''
@website.route([
'/payment/paypal/dpn',
], type='http', auth="public")
def paypal_dpn(self, **post):
""" TODO
"""
cr, uid, context = request.cr, request.uid, request.context
print 'Entering paypal_dpn with post', post
# step 1: return an empty HTTP 200 response -> will be done at the end by returning ''
# step 2: POST the complete, unaltered message back to Paypal (preceded by cmd=_notify-validate), with same encoding
paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr"
post_url = '%s?cmd=_notify-validate&%s' % (paypal_url, urlencode(post))
resp = requests.post(post_url)
print '\tReceived response', resp, resp.text
# step 3: paypal send either VERIFIED or INVALID (single word)
if resp.text == 'VERIFIED':
_logger.info('Paypal: received verified IPN')
cr, uid, context = request.cr, request.uid, request.context
payment_transaction = request.registry['payment.transaction']
res = payment_transaction.paypal_form_feedback(cr, uid, post, context=context)
print '\tValidation result', res
elif resp.text == 'INVALID':
_logger.warning('Paypal: received invalid IPN with post %s' % post)
else:
_logger.warning('Paypal: received unrecognized IPN with post %s' % post)
return_url = post.pop('return_url', '/')
print 'return_url', return_url
return request.redirect(return_url)
@website.route([
'/payment/paypal/cancel',
], type='http', auth="public")
def paypal_cancel(self, **post):
""" TODO
"""
cr, uid, context = request.cr, request.uid, request.context
print 'Entering paypal_cancel with post', post
return_url = post.pop('return_url', '/')
print 'return_url', return_url
return request.redirect(return_url)
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<record id="payment_acquirer_paypal" model="payment.acquirer">
<field name="name">paypal</field>
<field name="view_template_id" ref="paypal_acquirer_button"/>
<field name="env">test</field>
<field name="paypal_tx_url">https://www.sandbox.paypal.com/cgi-bin/webscr</field>
<field name="paypal_email_id">dummy</field>
<field name="paypal_username">dummy</field>
</record>
</data>
</openerp>
@@ -0,0 +1,9 @@
.. _changelog:
Changelog
=========
`trunk (saas-3)`
----------------
- Module creation
@@ -0,0 +1,14 @@
Payment module documentation
============================
Payment documentation topics
''''''''''''''''''''''''''''
Changelog
'''''''''
.. toctree::
:maxdepth: 1
changelog.rst
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import paypal
@@ -0,0 +1,191 @@
# -*- coding: utf-'8' "-*-"
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
from openerp.addons.payment_acquirer_paypal.controllers.main import PaypalController
from openerp.osv import osv, fields
from openerp.tools.float_utils import float_compare
import logging
import urlparse
_logger = logging.getLogger(__name__)
class AcquirerPaypal(osv.Model):
_inherit = 'payment.acquirer'
_columns = {
'paypal_email_id': fields.char('Email ID', required_if_provider='paypal'),
'paypal_username': fields.char('Username', required_if_provider='paypal'),
'paypal_password': fields.char('Password'),
'paypal_signature': fields.char('Signature'),
'paypal_tx_url': fields.char('Transaction URL', required_if_provider='paypal'),
'paypal_use_dpn': fields.boolean('Use DPN'),
'paypal_use_ipn': fields.boolean('Use IPN'),
}
_defaults = {
'paypal_use_dpn': True,
'paypal_use_ipn': True,
'paypal_tx_url': 'https://www.sandbox.paypal.com/cgi-bin/webscr',
}
def paypal_form_generate_values(self, cr, uid, id, reference, amount, currency, partner_id=False, partner_values=None, tx_custom_values=None, context=None):
if partner_values is None:
partner_values = {}
base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
acquirer = self.browse(cr, uid, id, context=context)
partner = None
if partner_id:
partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
tx_values = {
'cmd': '_xclick',
'business': acquirer.paypal_email_id,
'item_name': reference,
'item_number': reference,
'amount': amount,
'currency_code': currency and currency.name or 'EUR',
'address1': partner and ' '.join((partner.street or '', partner.street2 or '')).strip() or ' '.join((partner_values.get('street', ''), partner_values.get('street2', ''))).strip(),
'city': partner and partner.city or partner_values.get('city', ''),
'country': partner and partner.country_id and partner.country_id.name or partner_values.get('country_name', ''),
'email': partner and partner.email or partner_values.get('email', ''),
'zip': partner and partner.zip or partner_values.get('zip', ''),
'first_name': partner and partner.name or partner_values.get('name', '').split()[-1:],
'last_name': partner and partner.name or partner_values.get('name', '').split()[:-1],
'return': '%s' % urlparse.urljoin(base_url, PaypalController._return_url),
'notify_url': '%s' % urlparse.urljoin(base_url, PaypalController._notify_url),
'cancel_return': '%s' % urlparse.urljoin(base_url, PaypalController._cancel_url),
}
if tx_custom_values and tx_custom_values.get('return_url'):
tx_values['custom'] = 'return_url=%s' % tx_custom_values.pop('return_url')
if tx_custom_values:
tx_values.update(tx_custom_values)
return tx_values
def paypal_get_form_action_url(self, cr, uid, id, context=None):
acquirer = self.browse(cr, uid, id, context=context)
return acquirer.paypal_tx_url
class TxPaypal(osv.Model):
_inherit = 'payment.transaction'
_columns = {
'paypal_txn_id': fields.char('Transaction ID'),
'paypal_txn_type': fields.char('Transaction type'),
}
# --------------------------------------------------
# FORM RELATED METHODS
# --------------------------------------------------
def paypal_form_generate_values(self, cr, uid, id, tx_custom_values=None, context=None):
tx = self.browse(cr, uid, id, context=context)
tx_data = {
'item_name': tx.name,
'first_name': tx.partner_name and tx.partner_name.split()[-1:],
'last_name': tx.partner_name and tx.partner_name.split()[:-1],
'email': tx.partner_email,
'zip': tx.partner_zip,
'address1': tx.partner_address,
'city': tx.partner_city,
'country': tx.partner_country_id and tx.partner_country_id.name or '',
}
if tx_custom_values:
tx_data.update(tx_custom_values)
return self.pool['payment.acquirer'].paypal_form_generate_values(
cr, uid, tx.acquirer_id.id,
tx.reference, tx.amount, tx.currency_id,
tx_custom_values=tx_data,
context=context
)
def _paypal_get_tx_from_data(self, cr, uid, data, context=None):
reference, txn_id = data.get('item_number'), data.get('txn_id')
if not reference or not txn_id:
error_msg = 'Paypal: received data with missing reference (%s) or txn_id (%s)' % (reference, txn_id)
_logger.error(error_msg)
raise ValidationError(error_msg)
# find tx -> @TDENOTE use txn_id ?
tx_ids = self.pool['payment.transaction'].search(cr, uid, [('reference', '=', reference)], context=context)
if not tx_ids or len(tx_ids) > 1:
error_msg = 'Paypal: received data for reference %s' % (reference)
if not tx_ids:
error_msg += '; no order found'
else:
error_msg += '; multiple order found'
_logger.error(error_msg)
raise ValidationError(error_msg)
tx = self.pool['payment.transaction'].browse(cr, uid, tx_ids[0], context=context)
return tx
def paypal_form_feedback(self, cr, uid, data, context=None):
invalid_parameters = []
# get tx
tx = self._paypal_get_tx_from_data(cr, uid, data, context=context)
if data.get('notify_version')[0] != '2.6':
_logger.warning(
'Received a notification from Paypal with version %s instead of 2.6. This could lead to issues when managing it.' %
data.get('notify_version')
)
if data.get('test_ipn'):
_logger.warning(
'Received a notification from Paypal using sandbox'
),
# check what is buyed
if float_compare(float(data.get('mc_gross', '0.0')), tx.amount, 2) != 0:
invalid_parameters.append(('mc_gross', tx.amount))
if data.get('mc_currency') != tx.currency_id.name:
invalid_parameters.append(('mc_currency', tx.currency_id.name))
# if parameters.get('payment_fee') != tx.payment_fee:
# invalid_parameters.append(('payment_fee', tx.payment_fee))
# if parameters.get('quantity') != tx.quantity:
# invalid_parameters.append(('mc_currency', tx.quantity))
# if parameters.get('shipping') != tx.shipping:
# invalid_parameters.append(('shipping', tx.shipping))
# check buyer
# if parameters.get('payer_id') != tx.payer_id:
# invalid_parameters.append(('mc_gross', tx.payer_id))
# if parameters.get('payer_email') != tx.payer_email:
# invalid_parameters.append(('payer_email', tx.payer_email))
# check seller
# if parameters.get('receiver_email') != tx.receiver_email:
# invalid_parameters.append(('receiver_email', tx.receiver_email))
# if parameters.get('receiver_id') != tx.receiver_id:
# invalid_parameters.append(('receiver_id', tx.receiver_id))
if invalid_parameters:
_warn_message = 'The following transaction parameters are incorrect:\n'
for item in invalid_parameters:
_warn_message += '\t%s: received %s instead of %s\n' % (item, data.get(item[0]), item[1])
_logger.warning(_warn_message)
return False
status = data.get('payment_status', 'Pending')
if status in ['Completed', 'Processed']:
tx.write({
'state': 'done',
'txn_id': data['txn_id'],
'date_validate': data.get('payment_date', fields.datetime.now()),
'paypal_txn_type': data.get('express_checkout')
})
return True
elif status in ['Pending', 'Expired']:
tx.write({
'state': 'pending',
'txn_id': data['txn_id'],
})
return True
else:
error = 'Paypal: feedback error'
_logger.info(error)
tx.write({
'state': 'error',
'state_message': error
})
return False
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from . import test_paypal
checks = [
test_paypal,
]
@@ -0,0 +1,155 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.addons.payment_acquirer.tests.common import PaymentAcquirerCommon
from openerp.osv.orm import except_orm
from lxml import objectify
# import requests
# import urlparse
class BasicPayment(PaymentAcquirerCommon):
def test_10_paypal_basic(self):
pass
def test_11_paypal_form(self):
cr, uid = self.cr, self.uid
context = {}
base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url')
# ogone_url = self.payment_acquirer._get_ogone_urls(cr, uid, [ogone_id], None, None)[ogone_id]['ogone_standard_order_url']
model, paypal_view_id = self.registry('ir.model.data').get_object_reference(cr, uid, 'payment_acquirer_paypal', 'paypal_acquirer_button')
# forgot some mandatory fields: should crash
with self.assertRaises(except_orm):
paypal_id = self.payment_acquirer.create(
cr, uid, {
'name': 'paypal',
'env': 'test',
'view_template_id': paypal_view_id,
'paypal_email_id': 'tde+paypal-facilitator@openerp.com',
}, context=context
)
# tde+buyer@openerp.com
# create a new paypal account
paypal_id = self.payment_acquirer.create(
cr, uid, {
'name': 'paypal',
'env': 'test',
'view_template_id': paypal_view_id,
'paypal_email_id': 'dummy',
'paypal_username': 'dummy',
}, context=context
)
# verify acquirer data
paypal = self.payment_acquirer.browse(cr, uid, paypal_id, context)
self.assertEqual(paypal.env, 'test', 'test without test env')
# render the button
res = self.payment_acquirer.render(
cr, uid, paypal_id,
'test_ref0', 0.01, self.currency_euro,
partner_id=None,
partner_values=self.buyer_values,
context=context)
# print res
# # check some basic paypal methods
# res = self.payment_transaction.validate_paypal_notification(
# cr, uid,
# 'http://localhost/payment?mc_gross=19.95&protection_eligibility=Eligible&address_status=confirmed&payer_id=LPLWNMTBWMFAY&tax=0.00&address_street=1+Main+St&payment_date=20%3A12%3A59+Jan+13%2C+2009+PST&payment_status=Completed&charset=windows-1252&address_zip=95131&first_name=Test&mc_fee=0.88&address_country_code=US&address_name=Test+User&notify_version=2.6&custom=&payer_status=verified&address_country=United+States&address_city=San+Jose&quantity=1&verify_sign=AtkOfCXbDm2hu0ZELryHFjY-Vb7PAUvS6nMXgysbElEn9v-1XcmSoGtf&payer_email=gpmac_1231902590_per%40paypal.com&txn_id=61E67681CH3238416&payment_type=instant&last_name=User&address_state=CA&receiver_email=gpmac_1231902686_biz%40paypal.com&payment_fee=0.88&receiver_id=S8XGHLYDW9T3S&txn_type=express_checkout&item_name=&mc_currency=USD&item_number=&residence_country=US&test_ipn=1&handling_amount=0.00&transaction_subject=&payment_gross=19.95&shipping=0.00')
# self.assertEqual(res, False, 'payment: paypal validation on a txn_id that does not exists should return False')
# txn_id = self.payment_transaction.create(
# cr, uid, {
# 'amount': 0.01,
# 'acquirer_id': paypal_id,
# 'currency_id': currency_id,
# 'reference': 'test_reference',
# 'paypal_txn_id': '61E67681CH3238416',
# }, context=context
# )
# res = self.payment_transaction.validate_paypal_notification(
# cr, uid,
# 'http://localhost/payment?mc_gross=19.95&protection_eligibility=Eligible&address_status=confirmed&payer_id=LPLWNMTBWMFAY&tax=0.00&address_street=1+Main+St&payment_date=20%3A12%3A59+Jan+13%2C+2009+PST&payment_status=Completed&charset=windows-1252&address_zip=95131&first_name=Test&mc_fee=0.88&address_country_code=US&address_name=Test+User&notify_version=2.6&custom=&payer_status=verified&address_country=United+States&address_city=San+Jose&quantity=1&verify_sign=AtkOfCXbDm2hu0ZELryHFjY-Vb7PAUvS6nMXgysbElEn9v-1XcmSoGtf&payer_email=gpmac_1231902590_per%40paypal.com&txn_id=61E67681CH3238416&payment_type=instant&last_name=User&address_state=CA&receiver_email=gpmac_1231902686_biz%40paypal.com&payment_fee=0.88&receiver_id=S8XGHLYDW9T3S&txn_type=express_checkout&item_name=&mc_currency=USD&item_number=&residence_country=US&test_ipn=1&handling_amount=0.00&transaction_subject=&payment_gross=19.95&shipping=0.00')
# print res
# # user pays using Paypal
# resp = self.payment_transaction.create_paypal_command(
# cr, uid, cmd='_xclick', parameters={
# 'business': 'tdelavallee-facilitator@gmail.com',
# 'amount': 50,
# 'item_name': 'test_item',
# 'quantity': 1,
# 'currency_code': 'USD',
# 'return': 'http://www.example.com',
# })
# print resp
# print resp.url
# print resp.text
# self.payment_transaction.validate(cr, uid, [tx_id], context=context)
# {
# 'protection_eligibility': u'Ineligible',
# 'last_name': u'Poilu',
# 'txn_id': u'08D73520KX778924N',
# 'receiver_email': u'tde+paypal-facilitator@openerp.com',
# 'payment_status': u'Pending',
# 'payment_gross': u'',
# 'tax': u'0.00',
# 'residence_country': u'FR',
# 'address_state': u'Alsace',
# 'payer_status': u'verified',
# 'txn_type': u'web_accept',
# 'address_street': u'Av. de la Pelouse, 87648672 Mayet',
# 'handling_amount': u'0.00',
# 'payment_date': u'03:21:19 Nov 18, 2013 PST',
# 'first_name': u'Norbert',
# 'item_name': u'test_ref_0',
# 'address_country': u'France',
# 'charset': u'windows-1252',
# 'custom': u'',
# 'notify_version': u'3.7',
# 'address_name': u'Norbert Poilu',
# 'pending_reason': u'multi_currency',
# 'item_number': u'test_ref_0',
# 'receiver_id': u'DEG7Z7MYGT6QA',
# 'transaction_subject': u'',
# 'business': u'tde+paypal-facilitator@openerp.com',
# 'test_ipn': u'1',
# 'payer_id': u'VTDKRZQSAHYPS',
# 'verify_sign': u'An5ns1Kso7MWUdW4ErQKJJJ4qi4-AVoiUf-3478q3vrSmqh08IouiYpM',
# 'address_zip': u'75002',
# 'address_country_code': u'FR',
# 'address_city': u'Paris',
# 'address_status': u'unconfirmed',
# 'mc_currency': u'EUR',
# 'shipping': u'0.00',
# 'payer_email': u'tde+buyer@openerp.com',
# 'payment_type': u'instant',
# 'mc_gross': u'1.95',
# 'ipn_track_id': u'866df2ccd444b',
# 'quantity': u'1'
# }
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="acquirer_form_paypal" model="ir.ui.view">
<field name="name">acquirer.form.paypal</field>
<field name="model">payment.acquirer</field>
<field name="inherit_id" ref="payment_acquirer.acquirer_form"/>
<field name="arch" type="xml">
<xpath expr='//group[@name="acquirer_base"]' position='after'>
<group string="Paypal Details"
attrs="{'invisible': [('name', '!=', 'paypal')]}">
<field name="paypal_email_id"/>
<field name="paypal_username"/>
<field name="paypal_password"/>
<field name="paypal_signature"/>
<field name="paypal_use_ipn"/>
</group>
</xpath>
</field>
</record>
<record id="transaction_form_paypal" model="ir.ui.view">
<field name="name">acquirer.transaction.form.paypal</field>
<field name="model">payment.transaction</field>
<field name="inherit_id" ref="payment_acquirer.transaction_form"/>
<field name="arch" type="xml">
<xpath expr='//notebook' position='inside'>
<page string="Paypal TX Details">
<group>
<field name="paypal_txn_id"/>
<field name="paypal_txn_type"/>
</group>
</page>
</xpath>
</field>
</record>
</data>
</openerp>
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<template id="paypal_acquirer_button">
<form t-if="acquirer.paypal_email_id" t-att-action="acquirer.paypal_tx_url" method="post" target="_self">
<input type="hidden" name="cmd" t-att-value="tx_values['cmd']"/>
<input type="hidden" name="business" t-att-value="tx_values['business']"/>
<input type="hidden" name="item_name" t-att-value="tx_values['item_name']"/>
<input type="hidden" name="item_number" t-att-value="tx_values['item_number']"/>
<input type="hidden" name="amount" t-att-value="tx_values['amount']"/>
<input type="hidden" name="currency_code" t-att-value="tx_values['currency_code']"/>
<!-- partner / address data -->
<input type="hidden" name="address1" t-att-value="tx_values['address1']"/>
<input type="hidden" name="city" t-att-value="tx_values['city']"/>
<input type="hidden" name="country" t-att-value="tx_values['country']"/>
<input type="hidden" name="email" t-att-value="tx_values['email']"/>
<input type="hidden" name="first_name" t-att-value="tx_values['first_name']"/>
<input type="hidden" name="last_name" t-att-value="tx_values['last_name']"/>
<input type="hidden" name="zip" t-att-value="tx_values['zip']"/>
<!-- after payment parameters -->
<t t-if='tx_values.get("custom")'>
<input type='hidden' name="custom" t-att-value='tx_values["custom"]'/>
</t>
<!-- URLs -->
<input t-if="acquirer.paypal_use_dpn" type='hidden' name='return'
t-att-value="tx_values['return']"/>
<input t-if="acquirer.paypal_use_ipn" type='hidden' name='notify_url'
t-att-value="tx_values['notify_url']"/>
<input t-if="tx_values['cancel_return']" type="hidden" name="cancel_return"
t-att-value="tx_values['cancel_return']"/>
<!-- button -->
<input type="image" name="submit" id="payment_submit"
width="100px"
src="/payment_acquirer_paypal/static/src/img/paypal_logo.png"/>
</form>
</template>
</data>
</openerp>
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import models
import controllers
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
{
'name': 'Transfer Payment Acquirer',
'category': 'Hidden',
'summary': 'Payment Acquirer: Transfer Implementation',
'version': '1.0',
'description': """Transfer Payment Acquirer""",
'author': 'OpenERP SA',
'depends': ['payment_acquirer'],
'data': [
'views/transfer.xml',
'data/transfer.xml',
],
'installable': True,
}
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import main
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
import logging
import pprint
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
_logger = logging.getLogger(__name__)
class OgoneController(http.Controller):
_accept_url = '/payment/transfer/feedback'
@website.route([
'/payment/transfer/feedback',
], type='http', auth='admin')
def transfer_form_feedback(self, **post):
cr, uid, context = request.cr, request.uid, request.context
_logger.info('Beginning form_feedback with post data %s', pprint.pformat(post)) # debug
request.registry['payment.transaction'].form_feedback(cr, uid, post, 'transfer', context)
return request.redirect(post.pop('return_url', '/'))
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="payment_acquirer_transfer" model="payment.acquirer">
<field name="name">transfer</field>
<field name="view_template_id" ref="transfer_acquirer_button"/>
<field name="env">test</field>
<field name="portal_published" eval="True"/>
<field name="message"><![CDATA[
<p>Please use the account 001-002-003 to make the payment.</p>]]>
</field>
</record>
</data>
</openerp>
@@ -0,0 +1,9 @@
.. _changelog:
Changelog
=========
`trunk (saas-3)`
----------------
- Module creation
@@ -0,0 +1,14 @@
Payment module documentation
============================
Payment documentation topics
''''''''''''''''''''''''''''
Changelog
'''''''''
.. toctree::
:maxdepth: 1
changelog.rst
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import payment_acquirer
@@ -0,0 +1,53 @@
# -*- coding: utf-'8' "-*-"
from openerp.addons.payment_acquirer.models.payment_acquirer import ValidationError
from openerp.osv import osv
from openerp.tools.float_utils import float_compare
import logging
import pprint
_logger = logging.getLogger(__name__)
class TransferPaymentAcquirer(osv.Model):
_inherit = 'payment.acquirer'
def transfer_get_form_action_url(self, cr, uid, id, context=None):
return '/payment/transfer/feedback'
class TransferPaymentTransaction(osv.Model):
_inherit = 'payment.transaction'
def _transfer_form_get_tx_from_data(self, cr, uid, data, context=None):
reference, amount, currency_name = data.get('reference'), data.get('amount'), data.get('currency_name')
tx_ids = self.search(
cr, uid, [
('reference', '=', reference),
], context=context)
if not tx_ids or len(tx_ids) > 1:
error_msg = 'received data for reference %s' % (pprint.pformat(reference))
if not tx_ids:
error_msg += '; no order found'
else:
error_msg += '; multiple order found'
_logger.error(error_msg)
raise ValidationError(error_msg)
return self.browse(cr, uid, tx_ids[0], context=context)
def _transfer_form_get_invalid_parameters(self, cr, uid, tx, data, context=None):
invalid_parameters = []
if float_compare(float(data.get('amount', '0.0')), tx.amount, 2) != 0:
invalid_parameters.append(('amount', data.get('amount'), '%.2f' % tx.amount))
if data.get('currency') != tx.currency_id.name:
invalid_parameters.append(('currency', data.get('currency'), tx.currency_id.name))
return invalid_parameters
def _transfer_form_validate(self, cr, uid, tx, data, context=None):
_logger.info('Validated transfer payment for tx %s: set as pending' % (tx.reference))
return tx.write({'state': 'pending'})
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<template id="transfer_acquirer_button">
<div t-field="acquirer.message"/>
<form t-if="acquirer" action="/payment/transfer/feedback" method="post" target="_self">
<t t-if="tx_values.get('return_url')">
<input type='hidden' name='return_url' t-att-value='tx_values["return_url"]'/>
</t>
<input type='hidden' name='reference' t-att-value='reference'/>
<input type='hidden' name='amount' t-att-value='amount'/>
<input type='hidden' name='currency' t-att-value='currency.name'/>
<input type="submit" name="submit" id="payment_submit"
class="btn btn-primary" value="Confirmer"/>
</form>
</template>
</data>
</openerp>
+2 -3
View File
@@ -642,6 +642,7 @@ class product_product(osv.osv):
_table = "product_product"
_inherits = {'product.template': 'product_tmpl_id'}
_inherit = ['mail.thread']
_inherit = ['mail.thread']
_order = 'default_code,name_template'
_columns = {
'qty_available': fields.function(_product_qty_available, type='float', string='Quantity On Hand'),
@@ -839,9 +840,7 @@ class product_product(osv.osv):
context=context)
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
if context is None:
context = {}
if context and context.get('search_default_categ_id', False):
if context and context.get('search_default_categ_id'):
args.append((('categ_id', 'child_of', context['search_default_categ_id'])))
return super(product_product, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count)
-2
View File
@@ -306,8 +306,6 @@ class project_issue(osv.Model):
}
def set_priority(self, cr, uid, ids, priority, *args):
"""Set lead priority
"""
return self.write(cr, uid, ids, {'priority' : priority})
def set_high_priority(self, cr, uid, ids, *args):
+4 -32
View File
@@ -48,42 +48,14 @@ class Website(openerp.addons.web.controllers.main.Home):
@website.route('/pagenew/<path:path>', type='http', auth="user")
def pagenew(self, path, noredirect=NOPE):
module = 'website'
# completely arbitrary max_length
idname = slugify(path, max_length=50)
request.cr.execute('SAVEPOINT pagenew')
imd = request.registry['ir.model.data']
view = request.registry['ir.ui.view']
view_model, view_id = imd.get_object_reference(
request.cr, request.uid, 'website', 'default_page')
newview_id = view.copy(
request.cr, request.uid, view_id, context=request.context)
newview = view.browse(
request.cr, request.uid, newview_id, context=request.context)
newview.write({
'arch': newview.arch.replace("website.default_page",
"%s.%s" % (module, idname)),
'name': path,
'page': True,
})
# Fuck it, we're doing it live
web = request.registry['website']
try:
imd.create(request.cr, request.uid, {
'name': idname,
'module': module,
'model': 'ir.ui.view',
'res_id': newview_id,
'noupdate': True
}, context=request.context)
path = web.new_page(request.cr, request.uid, path, request.context)
except psycopg2.IntegrityError:
logger.exception('Unable to create ir_model_data for page %s', path)
request.cr.execute('ROLLBACK TO SAVEPOINT pagenew')
return werkzeug.exceptions.InternalServerError()
else:
request.cr.execute('RELEASE SAVEPOINT pagenew')
url = "/page/%s" % idname
url = "/page/" + path
if noredirect is not NOPE:
return werkzeug.wrappers.Response(url, mimetype='text/plain')
return werkzeug.utils.redirect(url)
@@ -112,7 +84,7 @@ class Website(openerp.addons.web.controllers.main.Home):
@website.route(['/website/snippets'], type='json', auth="public")
def snippets(self):
return request.website.render('website.snippets')
return request.website._render('website.snippets')
@website.route('/page/<page:page>', type='http', auth="public", multilang=True)
def page(self, page, **opt):
+7 -7
View File
@@ -10,7 +10,6 @@ import cStringIO
import datetime
import itertools
import logging
import re
import urllib2
import urlparse
@@ -216,18 +215,19 @@ class Image(orm.AbstractModel):
source_element, t_att, g_att, qweb_context, context=context)
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
cls = ''
if 'class' in options:
cls = ' class="%s"' % werkzeug.utils.escape(options['class'])
if options is None: options = {}
classes = ['img', 'img-responsive'] + options.get('class', '').split()
return '<img%s src="/website/image?model=%s&field=%s&id=%s"/>' % (
cls, record._model._name, field_name, record.id)
return '<img class="%s" src="/website/image?model=%s&field=%s&id=%s"/>' % (
' '.join(itertools.imap(werkzeug.utils.escape, classes)),
record._model._name,
field_name, record.id)
def from_html(self, cr, uid, model, column, element, context=None):
url = element.find('img').get('src')
url_object = urlparse.urlsplit(url)
query = urlparse.parse_qs(url_object.query)
query = dict(urlparse.parse_qsl(url_object.query))
if url_object.path == '/website/image' and query['model'] == 'ir.attachment':
attachment = self.pool['ir.attachment'].browse(
cr, uid, int(query['id']), context=context)
+33 -2
View File
@@ -3,6 +3,7 @@ import fnmatch
import functools
import inspect
import logging
import psycopg2
import math
import itertools
import traceback
@@ -21,6 +22,7 @@ from openerp.tools.safe_eval import safe_eval
from openerp.addons.web import http
from openerp.addons.web.http import request, LazyResponse
from ..utils import slugify
logger = logging.getLogger(__name__)
@@ -117,6 +119,34 @@ class website(osv.osv):
}
public_user = None
def new_page(self, cr, uid, name, template='website.default_page', ispage=True, context=None):
context=context or {}
# completely arbitrary max_length
idname = slugify(name, max_length=50)
cr.execute('SAVEPOINT pagenew')
imd = self.pool.get('ir.model.data')
view = self.pool.get('ir.ui.view')
module, tmp_page = template.split('.')
view_model, view_id = imd.get_object_reference(cr, uid, module, tmp_page)
newview_id = view.copy(cr, uid, view_id, context=context)
newview = view.browse(cr, uid, newview_id, context=context)
newview.write({
'arch': newview.arch.replace(template, "%s.%s" % (module, idname)),
'name': name,
'page': ispage,
})
imd.create(cr, uid, {
'name': idname,
'module': module,
'model': 'ir.ui.view',
'res_id': newview_id,
'noupdate': True
}, context=context)
cr.execute('RELEASE SAVEPOINT pagenew')
return "%s.%s" % (module, idname)
def get_public_user(self, cr, uid, context=None):
if not self.public_user:
@@ -473,7 +503,7 @@ class website(osv.osv):
'range': range,
'template': template,
}
return request.website.render("website.kanban_contain", values)
return request.website._render("website.kanban_contain", values)
def kanban_col(self, cr, uid, ids, model, domain, page, template, step, orderby, context=None):
html = ""
@@ -508,6 +538,7 @@ class website_menu(osv.osv):
_defaults = {
'url': '',
'sequence': 0,
'new_window': False,
}
_parent_store = True
_parent_order = 'sequence, name'
@@ -515,7 +546,7 @@ class website_menu(osv.osv):
def get_menu(self, cr, uid, website_id, context=None):
root_domain = [('parent_id', '=', False)] # ('website_id', '=', website_id),
menu_ids = self.search(cr, uid, root_domain, context=context)
menu_ids = self.search(cr, uid, root_domain, order='id', context=context)
menu = self.browse(cr, uid, menu_ids, context=context)
return menu[0]
+2 -5
View File
@@ -1,3 +1,4 @@
@charset "utf-8";
/* THIS CSS FILE IS FOR WEBSITE THEMING CUSTOMIZATION ONLY
*
* css for editor buttons, openerp widget included in the website and other
@@ -434,7 +435,6 @@ ul.nav-stacked > li > a {
.oe_dark {
background: #eff8f8;
background: rgba(100, 200, 200, 0.14);
background-image: none !important;
-webkit-box-shadow: 0px 5px 9px -7px rgba(0, 0, 255, 0.5) inset, 0px -3px 9px -7px rgba(0, 0, 255, 0.5) inset;
-moz-box-shadow: 0px 5px 9px -7px rgba(0, 0, 255, 0.5) inset, 0px -3px 9px -7px rgba(0, 0, 255, 0.5) inset;
box-shadow: 0px 5px 9px -7px rgba(0, 0, 255, 0.5) inset, 0px -3px 9px -7px rgba(0, 0, 255, 0.5) inset;
@@ -442,20 +442,17 @@ ul.nav-stacked > li > a {
.oe_black {
background-color: rgba(0, 0, 0, 0.9);
background-image: none !important;
}
.oe_green {
background-color: rgba(0, 128, 0, 0.8);
background-image: none !important;
}
.oe_red {
background-color: rgba(255, 0, 0, 0.8);
background-image: none !important;
}
.oe_custom_bg {
.oe_img_bg {
height: 100%;
background-size: 100%;
}
+2 -6
View File
@@ -328,17 +328,13 @@ ul.nav-stacked > li > a
.oe_dark
background: #eff8f8
background: rgba(100, 200, 200, 0.14)
background-image: none !important
+box-shadow(0px 5px 9px -7px rgba(0, 0, 255, 0.5) inset, 0px -3px 9px -7px rgba(0, 0, 255, 0.5) inset)
.oe_black
background-color: rgba(0, 0, 0, 0.9)
background-image: none !important
.oe_green
background-color: rgba(0, 128, 0, 0.8)
background-image: none !important
.oe_red
background-color: rgba(255, 0, 0, 0.8)
background-image: none !important
.oe_custom_bg
.oe_img_bg
height: 100%
background-size: 100%
background-size: 100%
Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

+202 -185
View File
@@ -30,8 +30,8 @@
function link_dialog(editor) {
return new website.editor.RTELinkDialog(editor).appendTo(document.body);
}
function image_dialog(editor) {
return new website.editor.RTEImageDialog(editor).appendTo(document.body);
function image_dialog(editor, image) {
return new website.editor.RTEImageDialog(editor, image).appendTo(document.body);
}
// only enable editors manually
@@ -53,7 +53,7 @@
&& !element.data('cke-realelement')
&& !element.isReadOnly()
&& (element.data('oe-model') !== 'ir.ui.view')) {
image_dialog(editor);
image_dialog(editor, element);
return;
}
@@ -69,13 +69,9 @@
}, null, null, 500);
var previousSelection;
editor.on('selectionChange', function (evt) {
var selected = evt.data.path.lastElement;
if (previousSelection) {
// cleanup previous selection
$(previousSelection).next().remove();
previousSelection = null;
}
$(editor.element.$).on('mouseenter', 'img', function () {
if (previousSelection) { return; }
var selected = new CKEDITOR.dom.element(this);
if (!selected.is('img')
|| selected.data('cke-realelement')
|| selected.isReadOnly()
@@ -84,26 +80,46 @@
}
// display button
var $el = $(previousSelection = selected.$);
var $el = $((previousSelection = selected).$);
var $btn = $('<button type="button" class="btn btn-primary image-edit-button" contenteditable="false">Edit</button>')
.insertAfter($el)
.click(function (e) {
e.preventDefault();
e.stopPropagation();
image_dialog(editor);
image_dialog(editor, selected);
});
var position = $el.position();
// http://bugs.jquery.com/ticket/5445#comment:6
// if the image has margin: x auto for centering, FF & IE
// will report top/left as the "correct" value and
// marginTop/marginLeft at "0px", webkit browsers will
// report top/left as 0-ish and set marginTop and
// marginLeft
var image_top = position.top + parseInt($el.css('marginTop'), 10);
var image_left = position.left + parseInt($el.css('marginLeft'), 10);
$btn.css({
position: 'absolute',
top: $el.height() / 2 + position.top - $btn.outerHeight() / 2,
left: $el.width() / 2 + position.left - $btn.outerWidth() / 2,
top: $el.height() / 2 + image_top - $btn.outerHeight() / 2,
left: $el.width() / 2 + image_left - $btn.outerWidth() / 2,
});
$el.css('opacity', 0.75);
}).on('mouseleave', 'img', function (e) {
var $previous = $(previousSelection.$);
var $button = $previous.next('button');
$button.css('visibility', 'hidden');
var el = document.elementFromPoint(e.clientX, e.clientY);
$button.css('visibility', '');
if (el === this) { return; }
$button.remove();
$previous.css('opacity', '');
previousSelection = null;
});
editor.on('destroy', function (evt) {
if (previousSelection) {
$('.image-edit-button').remove();
}
if (!previousSelection) { return; }
$('.image-edit-button')
.prev().css('opacity', '').end()
.remove();
});
//noinspection JSValidateTypes
@@ -202,6 +218,154 @@
}
});
CKEDITOR.plugins.add('linkstyle', {
requires: 'panelbutton,floatpanel',
init: function (editor) {
var label = "Link Style";
editor.ui.add('LinkStyle', CKEDITOR.UI_PANELBUTTON, {
label: label,
title: label,
icon: '/website/static/src/img/bglink.png',
modes: { wysiwyg: true },
editorFocus: true,
panel: {
css: '/website/static/lib/bootstrap/css/bootstrap.css',
attributes: { 'role': 'listbox', 'aria-label': label },
},
types: {
'btn-default': _t("Basic"),
'btn-primary': _t("Primary"),
'btn-success': _t("Success"),
'btn-info': _t("Info"),
'btn-warning': _t("Warning"),
'btn-danger': _t("Danger"),
},
sizes: {
'btn-xs': _t("Extra Small"),
'btn-sm': _t("Small"),
'': _t("Default"),
'btn-lg': _t("Large")
},
onRender: function () {
var self = this;
editor.on('selectionChange', function (e) {
var path = e.data.path, el;
if (!(e = path.contains('a')) || e.isReadOnly()) {
self.disable();
return;
}
self.enable();
});
// no hook where button is available, so wait
// "some time" after render.
setTimeout(function () {
self.disable();
}, 0)
},
enable: function () {
this.setState(CKEDITOR.TRISTATE_OFF);
},
disable: function () {
this.setState(CKEDITOR.TRISTATE_DISABLED);
},
onOpen: function () {
var link = get_selected_link(editor);
var id = this._.id;
var block = this._.panel._.panel._.blocks[id];
var $root = $(block.element.$);
$root.find('button').removeClass('active').removeProp('disabled');
// enable buttons matching link state
for (var type in this.types) {
if (!this.types.hasOwnProperty(type)) { continue; }
if (!link.hasClass(type)) { continue; }
$root.find('button[data-type=types].' + type)
.addClass('active');
}
var found;
for (var size in this.sizes) {
if (!this.sizes.hasOwnProperty(size)) { continue; }
if (!size || !link.hasClass(size)) { continue; }
found = true;
$root.find('button[data-type=sizes].' + size)
.addClass('active');
}
if (!found && link.hasClass('btn')) {
$root.find('button[data-type="sizes"][data-set-class=""]')
.addClass('active');
}
},
onBlock: function (panel, block) {
var self = this;
block.autoSize = true;
var html = ['<div style="padding: 5px">'];
html.push('<div style="white-space: nowrap">');
_(this.types).each(function (label, key) {
html.push(_.str.sprintf(
'<button type="button" class="btn %s" ' +
'data-type="types" data-set-class="%s">%s</button>',
key, key, label));
});
html.push('</div>');
html.push('<div style="white-space: nowrap; margin: 5px 0; text-align: center">');
_(this.sizes).each(function (label, key) {
html.push(_.str.sprintf(
'<button type="button" class="btn btn-default %s" ' +
'data-type="sizes" data-set-class="%s">%s</button>',
key, key, label));
});
html.push('</div>');
html.push('<button type="button" class="btn btn-link btn-block" ' +
'data-type="reset">Reset</button>');
html.push('</div>');
block.element.setHtml(html.join(' '));
var $panel = $(block.element.$);
$panel.on('click', 'button', function () {
self.clicked(this);
});
},
clicked: function (button) {
editor.focus();
editor.fire('saveSnapshot');
var $button = $(button),
$link = $(get_selected_link(editor).$);
if (!$link.hasClass('btn')) {
$link.addClass('btn btn-default');
}
switch($button.data('type')) {
case 'reset':
$link.removeClass('btn')
.removeClass(_.keys(this.types).join(' '))
.removeClass(_.keys(this.sizes).join(' '));
break;
case 'types':
$link.removeClass(_.keys(this.types).join(' '))
.addClass($button.data('set-class'));
break;
case 'sizes':
$link.removeClass(_.keys(this.sizes).join(' '))
.addClass($button.data('set-class'));
}
this._.panel.hide();
editor.fire('saveSnapshot');
},
});
}
});
CKEDITOR.plugins.add('oeref', {
requires: 'widget',
@@ -224,157 +388,6 @@
}
});
CKEDITOR.plugins.add('bootstrapcombo', {
requires: 'richcombo',
init: function (editor) {
var config = editor.config;
editor.ui.addRichCombo('BootstrapLinkCombo', {
// default title
label: "Links",
// hover
title: "Link styling",
toolbar: 'styles,10',
allowedContent: ['a'],
panel: {
css: [
'/website/static/lib/bootstrap/css/bootstrap.css',
CKEDITOR.skin.getPath( 'editor' )
].concat( config.contentsCss ),
multiSelect: true,
},
types: {
'basic': 'btn-default',
'primary': 'btn-primary',
'success': 'btn-success',
'info': 'btn-info',
'warning': 'btn-warning',
'danger': 'btn-danger',
},
sizes: {
'large': 'btn-lg',
'default': '',
'small': 'btn-sm',
'extra small': 'btn-xs',
},
init: function () {
this.add('', 'Reset');
this.startGroup("Types");
for(var type in this.types) {
if (!this.types.hasOwnProperty(type)) { continue; }
var cls = this.types[type];
var el = _.str.sprintf(
'<span class="btn %s">%s</span>',
cls, type);
this.add(type, el);
}
this.startGroup("Sizes");
for (var size in this.sizes) {
if (!this.sizes.hasOwnProperty(size)) { continue; }
cls = this.sizes[size];
el = _.str.sprintf(
'<span class="btn btn-default %s">%s</span>',
cls, size);
this.add(size, el);
}
this.commit();
},
onRender: function () {
var self = this;
editor.on('selectionChange', function (e) {
var path = e.data.path, el;
if (!(el = path.contains('a'))) {
self.element = null;
self.disable();
return;
}
self.enable();
// This is crap, but getting the currently selected
// element from within onOpen absolutely does not
// work, so store the "current" element in the
// widget instead
self.element = el;
});
setTimeout(function () {
// Because I can't find any normal hook where the
// bloody button's bloody element is available
self.disable();
}, 0);
},
onOpen: function () {
this.showAll();
this.unmarkAll();
for(var val in this.types) {
if (!this.types.hasOwnProperty(val)) { continue; }
var cls = this.types[val];
if (!this.element.hasClass(cls)) { continue; }
this.mark(val);
break;
}
var found;
for(val in this.sizes) {
if (!this.sizes.hasOwnProperty(val)) { continue; }
cls = this.sizes[val];
if (!cls || !this.element.hasClass(cls)) { continue; }
found = true;
this.mark(val);
break;
}
if (!found && this.element.hasClass('btn')) {
this.mark('default');
}
},
onClick: function (value) {
editor.focus();
editor.fire('saveShapshot');
// basic btn setup
var el = this.element;
if (!el.hasClass('btn')) {
el.addClass('btn');
el.addClass('btn-default');
}
if (!value) {
this.setClass(this.types);
this.setClass(this.sizes);
el.removeClass('btn');
} else if (value in this.types) {
this.setClass(this.types, value);
} else if (value in this.sizes) {
this.setClass(this.sizes, value);
}
editor.fire('saveShapshot');
},
setClass: function (classMap, value) {
var element = this.element;
_(classMap).each(function (cls) {
if (!cls) { return; }
element.removeClass(cls);
}.bind(this));
var cls = classMap[value];
if (cls) {
element.addClass(cls);
}
}
});
},
});
var editor = new website.EditorBar();
var $body = $(document.body);
editor.prependTo($body).then(function () {
@@ -788,7 +801,7 @@
fillEmptyBlocks: false,
filebrowserImageUploadUrl: "/website/attach",
// Support for sharedSpaces in 4.x
extraPlugins: 'sharedspace,customdialogs,tablebutton,oeref,bootstrapcombo',
extraPlugins: 'sharedspace,customdialogs,tablebutton,oeref,linkstyle',
// Place toolbar in controlled location
sharedSpaces: { top: 'oe_rte_toolbar' },
toolbar: [{
@@ -800,7 +813,7 @@
"Superscript", "TextColor", "BGColor", "RemoveFormat"
]},{
name: 'span', items: [
"Link", "Blockquote", "BulletedList",
"Link", "LinkStyle", "Blockquote", "BulletedList",
"NumberedList", "Indent", "Outdent"
]},{
name: 'justify', items: [
@@ -810,7 +823,7 @@
"Image", "TableButton"
]},{
name: 'styles', items: [
"Styles", "BootstrapLinkCombo"
"Styles"
]}
],
// styles dropdown in toolbar
@@ -1182,26 +1195,30 @@
},
});
website.editor.RTEImageDialog = website.editor.ImageDialog.extend({
init: function () {
this._super.apply(this, arguments);
init: function (editor, image) {
this._super(editor);
this.element = image;
this.on('start', this, this.proxy('started'));
this.on('save', this, this.proxy('saved'));
},
started: function (holder) {
var selection = this.editor.getSelection();
var el = selection && selection.getSelectedElement();
this.element = null;
if (el && el.is('img')) {
this.element = el;
_(this.image_styles).each(function (style) {
if (el.hasClass(style)) {
holder.style = style;
}
});
holder.url = el.getAttribute('src');
if (!this.element) {
var selection = this.editor.getSelection();
this.element = selection && selection.getSelectedElement();
}
var el = this.element;
if (!el || !el.is('img')) {
return;
}
_(this.image_styles).each(function (style) {
if (el.hasClass(style)) {
holder.style = style;
}
});
holder.url = el.getAttribute('src');
},
saved: function (data) {
var element, editor = this.editor;
@@ -5,15 +5,12 @@
website.menu = {};
website.add_template_file('/website/static/src/xml/website.menu.xml');
var globalEditor;
website.EditorBar.include({
events: _.extend({}, website.EditorBar.prototype.events, {
'click a[data-action="edit-structure"]': 'editStructure',
}),
editStructure: function () {
var self = this;
globalEditor = self;
var context = website.get_context();
openerp.jsonRpc('/web/dataset/call_kw', 'call', {
model: 'website.menu',
@@ -24,7 +21,6 @@
},
}).then(function (menu) {
var result = new website.menu.EditMenuDialog(menu).appendTo(document.body);
self.trigger('tour:menu_editor_dialog_ready');
return result;
});
},
@@ -171,7 +167,6 @@
$link_text.focus();
});
});
globalEditor.trigger('tour:new_menu_entry_dialog_ready');
return result;
},
save: function () {
@@ -192,7 +187,6 @@
}
},
destroy: function () {
globalEditor.trigger('tour:new_menu_entry_dialog_closed');
this._super.apply(this, arguments);
},
});
@@ -82,7 +82,7 @@
var self = this;
var speed = parseFloat(self.$target.attr("data-scroll-background-ratio") || 0);
if (speed == 1) {
if (speed === 1 || this.$target.css("background-image") === "none") {
this.$target.css("background-attachment", "fixed").css("background-position", "0px 0px");
return;
} else {
@@ -101,7 +101,7 @@
} else {
offset = - self.$target.offset().top * speed;
}
self.$target.attr("data-scroll-background-offset", offset);
self.$target.attr("data-scroll-background-offset", offset > 0 ? 0 : offset);
$(window).scroll();
};
img.src = this.$target.css("background-image").replace(/url\(['"]*|['"]*\)/g, "");
@@ -77,6 +77,7 @@
hack_to_add_snippet_id();
});
website.snippet.styles = {};
website.snippet.selector = [];
website.snippet.BuildingBlock = openerp.Widget.extend({
template: 'website.snippets',
@@ -138,22 +139,19 @@
},
fetch_snippet_templates: function () {
var self = this;
this.style_templates = {};
openerp.jsonRpc("/website/snippets", 'call', {})
.then(function (html) {
var $html = $(html);
var $styles = $html.find("#snippet_styles");
$styles.find("> [data-snippet-id]").each(function () {
var $styles = $html.find("[data-snippet-style-id]");
$styles.each(function () {
var $style = $(this);
var snipped_id = $style.data('snippet-id');
self.style_templates[snipped_id] = {
'snipped-id' : snipped_id,
var style_id = $style.data('snippet-style-id');
website.snippet.styles[style_id] = {
'snippet-style-id' : style_id,
'selector': $style.data('selector'),
'class': $style.data("class"),
'label': $style.find(".oe_snippet_label").text(),
'group': $style.find(".oe_snippet_group").text()
'$el': $style,
};
});
$styles.addClass("hidden");
@@ -529,13 +527,212 @@
});
website.snippet.styleRegistry = {};
website.snippet.StyleEditor = openerp.Class.extend({
// initialisation (don't overwrite)
init: function (parent, $target, snippet_id) {
this.parent = parent;
this.$target = $target;
var styles = this.$target.data("snippet-style-ids") || {};
styles[snippet_id] = this;
this.$target.data("snippet-style-ids", styles);
this.$overlay = this.$target.data('overlay');
this['snippet-style-id'] = snippet_id;
this.$el = website.snippet.styles[snippet_id].$el.find(">li").clone();
this.required = this.$el.data("required");
this.set_active();
this.$el.find('li[data-class] a').on('mouseover mouseout click', _.bind(this._mouse, this));
this.$target.on('snippet-style-reset', _.bind(this.set_active, this));
this.start();
},
_mouse: function (event) {
var self = this;
if (event.type === 'mouseout') {
if (!this.over) return;
this.over = false;
} else if (event.type === 'click') {
this.over = false;
}else {
this.over = true;
}
var $prev, $next;
if (event.type === 'mouseout') {
$prev = $(event.currentTarget).parent();
$next = this.$el.find("li[data-class].active");
} else {
$prev = this.$el.find("li[data-class].active");
$next = $(event.currentTarget).parent();
}
if (!$prev.length) {
$prev = false;
}
if ($prev && $prev[0] === $next[0]) {
$next = false;
if (this.required) {
return;
}
}
var np = {'$next': $next, '$prev': $prev};
if (event.type === 'click') {
setTimeout(function () {
self.set_active();
self.$target.trigger("snippet-style-change", [self, np]);
},0);
this.select(event, {'$next': $next, '$prev': $prev});
} else {
setTimeout(function () {
self.$target.trigger("snippet-style-preview", [self, np]);
},0);
this.preview(event, np);
}
},
// start is call just after the init
start: function () {
},
/* select
* called when a user select an item
* variables: np = {$next, $prev}
* $next is false if they are no next item selected
* $prev is false if they are no previous item selected
*/
select: function (event, np) {
var self = this;
// add or remove html class
if (np.$prev) {
this.$target.removeClass(np.$prev.data('class' || ""));
}
if (np.$next) {
this.$target.addClass(np.$next.data('class') || "");
}
},
/* preview
* called when a user is on mouse over or mouse out of an item
* variables: np = {$next, $prev}
* $next is false if they are no next item selected
* $prev is false if they are no previous item selected
*/
preview: function (event, np) {
var self = this;
// add or remove html class
if (np.$prev) {
this.$target.removeClass(np.$prev.data('class') || "");
}
if (np.$next) {
this.$target.addClass(np.$next.data('class') || "");
}
},
/* set_active
* select and set item active or not (add highlight item and his parents)
* called before start
*/
set_active: function () {
var self = this;
this.$el.find('li').removeClass("active");
var $active = this.$el.find('li[data-class]')
.filter(function () {
var $li = $(this);
return ($li.data('class') && self.$target.hasClass($li.data('class')));
})
.first()
.addClass("active");
this.$el.find('li:has(li[data-class].active)').addClass("active");
}
});
website.snippet.styleRegistry['size'] = website.snippet.StyleEditor.extend({
select: function(event, np) {
this._super(event, np);
this.parent.parent.cover_target(this.$overlay, this.$target);
},
preview: function (event, np) {
this._super(event, np);
this.parent.parent.cover_target(this.$overlay, this.$target);
}
});
website.snippet.styleRegistry.background = website.snippet.StyleEditor.extend({
_get_bg: function () {
return this.$target.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, "");
},
_set_bg: function (src) {
this.$target.css("background-image", src && src !== "" ? 'url(' + src + ')' : "");
},
start: function () {
this._super();
var src = this._get_bg();
this.$el.find("li[data-class].active.oe_custom_bg").data("src", src);
},
select: function(event, np) {
var self = this;
this._super(event, np);
if (np.$next) {
if (np.$next.hasClass("oe_custom_bg")) {
var editor = new website.editor.ImageDialog();
editor.on('start', self, function (o) {o.url = np.$prev && np.$prev.data("src") || "";});
editor.on('save', self, function (o) {
self._set_bg(o.url);
np.$next.data("src", o.url);
self.$target.trigger("snippet-style-change", [self, np]);
});
editor.on('cancel', self, function () {
if (!np.$prev || np.$prev.data("src") === "") {
np.$next.removeClass('active');
self.$target.removeClass(np.$next.data("class"));
self.$target.trigger("snippet-style-change", [self, np]);
}
});
editor.appendTo($('body'));
} else {
this._set_bg(np.$next.data("src"));
}
} else {
this._set_bg(false);
}
},
preview: function (event, np) {
this._super(event, np);
if (np.$next) {
this._set_bg(np.$next.data("src"));
}
},
set_active: function () {
var self = this;
var bg = self.$target.css("background-image");
this.$el.find('li').removeClass("active");
var $active = this.$el.find('li[data-class]')
.filter(function () {
var $li = $(this);
return ($li.data('src') && bg.indexOf($li.data('src')) >= 0) ||
(!$li.data('src') && self.$target.hasClass($li.data('class')));
})
.first();
if (!$active.length) {
$active = this.$target.css("background-image") !== 'none' ?
this.$el.find('li[data-class].oe_custom_bg') :
this.$el.find('li[data-class=""]');
}
$active.addClass("active");
this.$el.find('li:has(li[data-class].active)').addClass("active");
}
});
website.snippet.editorRegistry = {};
website.snippet.Editor = openerp.Class.extend({
init: function (parent, dom, force_snippet_id) {
init: function (parent, dom) {
this.parent = parent;
this.$target = $(dom);
this.$overlay = this.$target.data('overlay');
this.snippet_id = force_snippet_id || this.$target.data("snippet-id");
this.snippet_id = this.$target.data("snippet-id");
this._readXMLData();
this.load_style_options();
this.get_parent_block();
@@ -652,90 +849,21 @@
},
load_style_options: function () {
if (this.$target.data('snippetStyles')) {
return;
}
var self = this;
var $styles = this.$overlay.find('.oe_options');
var $ul = $styles.find('ul:first');
_.each(this.parent.style_templates, function (val) {
_.each(website.snippet.styles, function (val) {
if (!self.parent.dom_filter(val.selector).is(self.$target)) {
return;
}
var $li = $("<li class='oe_style'/>").data(val);
$li.append($('<a/>').text(val.label));
if (self.$target.hasClass( val.class )) {
$li.addClass("active");
}
if (val.group.length) {
var $group = $ul.find("li.dropdown-submenu").filter(function () {
return $("a:first", this).text() === val.group;
});
if (!$group.length) {
$group = $('<li class="dropdown-submenu"><a href="#" tabindex="-1"/><ul class="dropdown-menu"/></li>');
$group.find("a").text(val.group);
$ul.append($group);
}
$group.find("ul").append($li);
} else {
$ul.append($li);
}
var Editor = website.snippet.styleRegistry[val['snippet-style-id']] || website.snippet.StyleEditor;
var editor = new Editor(self, self.$target, val['snippet-style-id']);
$ul.prepend(editor.$el);
});
if ($ul.find("li").length) {
$styles.removeClass("hidden");
// il they are only one group, display in flat mode
var $groups = $ul.find("li.dropdown-submenu");
if ($groups.length === 1) {
$ul.append($groups.find("ul li"));
$groups.remove();
}
}
this.$target.data('snippetStyles', $styles);
this.change_style();
},
change_style: function () {
var self = this;
this.$overlay.find('.oe_options li.oe_style a')
.on('click', function (event) {
var $li = $(event.currentTarget).parent();
var active = $li.hasClass("active");
if ($li.hasClass("active")) {
self.$target.removeClass($li.data('class'));
} else {
var $prev = $li.parent("ul").find("li.active").removeClass("active");
if ($prev.length) {
self.$target.removeClass($prev.data('class'));
// active snippet after remove class
if (website.snippet.editorRegistry[$prev.data("snipped-id")]) {
new website.snippet.editorRegistry[$prev.data("snipped-id")](self.parent, self.$target, $prev.data("snipped-id"))
.drop_and_build_snippet(self.$target);
}
}
self.$target.addClass($li.data('class'));
}
// active snippet after add or remove class
if (website.snippet.editorRegistry[$li.data("snipped-id")]) {
new website.snippet.editorRegistry[$li.data("snipped-id")](self.parent, self.$target, $li.data("snipped-id"))
.drop_and_build_snippet(self.$target);
}
$li.toggleClass("active");
})
.on('mouseover', function (event) {
self.$target.removeClass(self.$overlay.find('.oe_options li.oe_style.active').data('class') || "");
self.$target.addClass($(event.currentTarget).parent().data('class') || "");
})
.on('mouseout', function (event) {
self.$target.removeClass($(event.currentTarget).parent().data('class') || "");
self.$target.addClass(self.$overlay.find('.oe_options li.oe_style.active').data('class') || "");
});
},
get_parent_block: function () {
@@ -801,59 +929,6 @@
clean_for_save: function () {
},
change_background: function (bg, ul_options, callback) {
var self = this;
this.set_options_background(bg, ul_options);
var $ul = this.$editor.find(ul_options);
var bg_value = (typeof bg === 'string' ? this.$target.find(bg) : $(bg)).css("background-image").replace(/url\(['"]*|['"]*\)/g, "");
// bind event on options
var $li = $ul.find("li");
$li.on('click', function (event) {
if ($(this).data("value")) {
$li.removeClass("active");
$(this).addClass("active");
self.$editor.find('input').val("");
} else {
var editor = new website.editor.ImageDialog();
editor.on('start', self, function (o) {o.url = bg_value;});
editor.on('save', self, function (o) {
var $bg = typeof bg === 'string' ? self.$target.find(bg) : $(bg);
$bg.css("background-image", "url(" + o.url + ")");
});
editor.appendTo($('body'));
}
if (callback) {
callback();
}
})
.on('mouseover', function (event) {
if ($(this).data("value")) {
var src = $(this).data("value");
var $bg = typeof bg === 'string' ? self.$target.find(bg) : $(bg);
$bg.css("background-image", "url(" + src + ")");
}
})
.on('mouseout', function (event) {
var src = $ul.find('li.active').data("value");
var $bg = typeof bg === 'string' ? self.$target.find(bg) : $(bg);
$bg.css("background-image", "url(" + src + ")");
});
},
set_options_background: function (bg, ul_options) {
var $ul = this.$editor.find(ul_options);
var bg_value = (typeof bg === 'string' ? this.$target.find(bg) : $(bg)).css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, "");
// select in ul options
$ul.find("li").removeClass("active");
var selected = $ul.find('[data-value="' + bg_value + '"], [data-value="' + bg_value.replace(/.*:\/\/[^\/]+/, '') + '"]');
selected.addClass('active');
if (!selected.length) {
$ul.find('.oe_custom_bg b').html(bg_value);
}
},
});
@@ -1070,11 +1145,15 @@
if(!this.$target.find(".item.active").length) {
this.$target.find(".item:first").addClass("active");
}
this.$target.css("background-image", "");
console.log(this._class);
this.$target.removeClass(this._class);
this.$target.removeAttr('contentEditable')
.find('.content, .carousel-image img')
.removeAttr('contentEditable');
},
start : function () {
var self = this;
this._super();
this.id = this.$target.attr("id");
@@ -1085,20 +1164,38 @@
this.$editor.find(".js_add").on('click', _.bind(this.on_add, this));
this.$editor.find(".js_remove").on('click', _.bind(this.on_remove, this));
this.change_background(".item.active", 'ul[name="carousel-background"]');
this.change_style();
this.change_size();
this.set_options_style();
this.$target.carousel();
this.rebind_event();
// set background and prepare to clean for save
var add_class = function (c){
if (c) self._class = (self._class || "").replace(new RegExp("[ ]+" + c.replace(" ", "|[ ]+")), '') + ' ' + c;
return self._class || "";
};
this.$target.on('snippet-style-change snippet-style-preview', function (event, style, np) {
var $active = self.$target.find(".item.active");
if (style['snippet-style-id'] === "size") return;
if (style['snippet-style-id'] === "background") {
$active.css("background-image", self.$target.css("background-image"));
}
if (np.$prev) {
$active.removeClass(np.$prev.data("class"));
}
if (np.$next) {
$active.addClass(np.$next.data("class"));
add_class(np.$next.data("class"));
}
});
this.$target.on('slid', function () { // slide.bs.carousel
var $active = self.$target.find(".item.active");
self.$target
.css("background-image", $active.css("background-image"))
.removeClass(add_class($active.attr("class")))
.addClass($active.attr("class"))
.trigger("snippet-style-reset");
var self = this;
this.$target.on('slide.bs.carousel', function () {
self.set_options_style();
self.set_options_background(".item.active", 'ul[name="carousel-background"]');
self.$target.carousel();
});
this.rebind_event();
this.$target.trigger('slid');
},
// rebind event to active carousel on edit mode
rebind_event: function () {
@@ -1121,9 +1218,15 @@
this.$indicators.append('<li data-target="#' + this.id + '" data-slide-to="' + cycle + '"></li>');
var $clone = this.$el.find(".item.active").clone();
var avtive_bg = $active.css("background-image").replace(/.*:\/\/[^\/]+|\)$/g, '');
var bg = this.$editor.find('ul[name="carousel-background"] li:not([data-value="'+ avtive_bg +'"]):first').data("value");
$clone.css("background-image", "url('"+ bg +"')");
// choose an other background
var $styles = this.$target.data("snippet-style-ids").background.$el.find("li[data-class]:not(.oe_custom_bg)");
var styles_index = $styles.index($styles.filter(".active")[0]);
var $select = $($styles[styles_index >= $styles.length-1 ? 0 : styles_index+1]);
$clone.css("background-image", $select.data("src") ? "url('"+ $select.data("src") +"')" : "");
$clone.addClass($select.data("class") || "");
// insert
$clone.removeClass('active').insertAfter($active);
this.$target.carousel().carousel(++index);
this.rebind_event();
@@ -1158,78 +1261,16 @@
this.$target.find('.carousel-control, .carousel-indicators').addClass("hidden");
}
},
set_options_style: function () {
var style = false;
var $el = this.$inner.find('.item.active');
var $ul = this.$editor.find('ul[name="carousel-style"]');
if ($el.hasClass('text_only'))
style = 'text_only';
if ($el.hasClass('image_text'))
style = 'image_text';
if ($el.hasClass('text_image'))
style = 'text_image';
$ul.find('[data-value="' + style + '"]').addClass('active');
},
change_style: function () {
var self = this;
var $ul = this.$editor.find('ul[name="carousel-style"]');
var $li = $ul.find("li");
$li.on('click', function (event) {
$li.removeClass("active");
$(this).addClass("active");
})
.on('mouseover', function (event) {
var $el = self.$inner.find('.item.active');
$el.removeClass('image_text text_image text_only');
$el.addClass($(event.currentTarget).data("value"));
})
.on('mouseout', function (event) {
var $el = self.$inner.find('.item.active');
$el.removeClass('image_text text_image text_only');
$el.addClass($ul.find('li.active').data("value"));
});
},
change_size: function () {
var $el = this.$target;
var size = 'oe_big';
if (this.$target.hasClass('oe_small'))
size = 'oe_small';
else if (this.$target.hasClass('oe_medium'))
size = 'oe_medium';
var $ul = this.$editor.find('ul[name="carousel-size"]');
var $li = $ul.find("li");
$ul.find('[data-value="' + size + '"]').addClass('active');
$li.on('click', function (event) {
$li.removeClass("active");
$(this).addClass("active");
})
.on('mouseover', function (event) {
$el.removeClass('oe_big oe_small oe_medium');
$el.addClass($(event.currentTarget).data("value"));
})
.on('mouseout', function (event) {
$el.removeClass('oe_big oe_small oe_medium');
$el.addClass($ul.find('li.active').data("value"));
});
}
});
website.snippet.editorRegistry.parallax = website.snippet.editorRegistry.resize.extend({
start : function () {
var self = this;
this._super();
this.change_background(this.$target, 'ul[name="parallax-background"]', function () {
this.scroll();
this.$target.on('snippet-style-change snippet-style-preview', function () {
self.$target.data("snippet-view").set_values();
});
this.scroll();
this.change_size();
},
scroll: function () {
var self = this;
@@ -1252,60 +1293,6 @@
this.$target.find(".parallax")
.css("background-position", '')
.removeAttr("data-scroll-background-offset");
},
change_size: function () {
var self = this;
var size = 'oe_big';
if (this.$target.hasClass('oe_small'))
size = 'oe_small';
else if (this.$target.hasClass('oe_medium'))
size = 'oe_medium';
var $ul = this.$editor.find('ul[name="parallax-size"]');
var $li = $ul.find("li");
$ul.find('[data-value="' + size + '"]').addClass('active');
$li.on('click', function (event) {
$li.removeClass("active");
$(this).addClass("active");
self.$target.data("snippet-view").set_values();
return false;
})
.on('mouseover', function (event) {
self.$target.removeClass('oe_big oe_small oe_medium');
self.$target.addClass($(event.currentTarget).data("value"));
})
.on('mouseout', function (event) {
self.$target.removeClass('oe_big oe_small oe_medium');
self.$target.addClass($ul.find('li.active').data("value"));
});
}
});
website.snippet.editorRegistry.custom_background = website.snippet.Editor.extend({
drop_and_build_snippet: function() {
var self = this;
var active = this.$target.hasClass(this.$el.data("class"));
if (active) {
var bg_value = this.$target.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, "");
var editor = new website.editor.ImageDialog();
editor.on('start', self, function (o) {o.url = bg_value;});
editor.on('save', self, function (o) {
self.$target.css("background-image", "url(" + o.url + ")");
});
editor.on('cancel', self, function () {
if (bg_value === "") {
self.$target.data("snippetStyles").find(".oe_style").filter(function () {
return $(this).data('snipped-id') === 'custom_background';
}).removeClass('active');
self.$target.removeClass(self.$el.data("class"));
}
});
editor.appendTo($('body'));
} else {
this.$target.css("background-image", "");
}
}
});
@@ -3,8 +3,6 @@
var website = openerp.website;
var render = website.tour.render;
website.EditorBar.include({
start: function () {
this.registerTour(new website.AppTour(this));
@@ -24,7 +22,7 @@
backdrop: true,
title: "Install an App",
content: "You can intall some apps to manage your website content.",
template: render('website.tour_popover', { next: "Start Tutorial", end: "Skip It" }),
template: self.popover({ next: "Start Tutorial", end: "Skip It" }),
},
{
stepId: 'customize',
@@ -32,8 +30,7 @@
placement: 'left',
title: "Install an app",
content: "Add new apps by customizing your website.",
template: render('website.tour_popover'),
onShow: function () {
triggers: function () {
editor.on('rte:customize_menu_ready', editor, function () {
self.movetoStep('install-app');
});
@@ -46,7 +43,6 @@
orphan: true,
title: "Install an app",
content: "Click 'Install Apps' to select and install the application you would like to manage from your website.",
template: render('website.tour_popover'),
},
];
return this._super();
@@ -3,8 +3,6 @@
var website = openerp.website;
var render = website.tour.render;
website.EditorBar.include({
start: function () {
this.registerTour(new website.BannerTour(this));
@@ -25,7 +23,7 @@
backdrop: true,
title: "Welcome to your website!",
content: "This tutorial will guide you to build your home page. We will start by adding a banner.",
template: render('website.tour_popover', { next: "Start Tutorial", end: "Skip It" }),
template: self.popover({ next: "Start Tutorial", end: "Skip It" }),
},
{
stepId: 'edit-page',
@@ -33,8 +31,7 @@
placement: 'bottom',
title: "Edit this page",
content: "Every page of your website can be modified through the <i>Edit</i> button.",
template: render('website.tour_popover'),
onShow: function () {
triggers: function () {
editor.on('tour:editor_bar_loaded', editor, function () {
self.movetoStep('add-block');
});
@@ -46,8 +43,7 @@
placement: 'bottom',
title: "Insert building blocks",
content: "To add content in a page, you can insert building blocks.",
template: render('website.tour_popover'),
onShow: function () {
triggers: function () {
$('button[data-action=snippet]').click(function () {
self.movetoStep('drag-banner');
});
@@ -59,20 +55,8 @@
placement: 'bottom',
title: "Drag & Drop a Banner",
content: "Drag the Banner block and drop it in your page.",
template: render('website.tour_popover'),
onShow: function () {
var $body = $(document.body);
function beginDrag () {
$('.popover.tour').remove();
function goToNextStep () {
$('#snippets').toggle();
self.movetoStep('edit-title');
$body.off('mouseup', goToNextStep);
}
$body.off('mousedown', beginDrag);
$body.on('mouseup', goToNextStep);
}
$body.on('mousedown', beginDrag);
triggers: function () {
self.onSnippetDraggedMoveTo('edit-title');
},
},
{
@@ -81,8 +65,8 @@
placement: 'top',
title: "Customize banner's text",
content: "Click in the text and start editing it. Click continue once it's done.",
template: render('website.tour_popover', { next: "Continue" }),
onHide: function () {
template: self.popover({ next: "Continue" }),
triggers: function () {
var $banner = $("#wrap [data-snippet-id=carousel]:first");
if ($banner.length) {
$banner.click();
@@ -95,8 +79,8 @@
placement: 'left',
title: "Customize the banner",
content: "You can customize characteristic of any blocks through the Customize menu. For instance, change the background of the banner.",
template: render('website.tour_popover', { next: "Continue" }),
onShow: function () {
template: self.popover({ next: "Continue" }),
triggers: function () {
$('.dropdown-menu [name=carousel-background]').click(function () {
self.movetoStep('save-changes');
});
@@ -109,17 +93,13 @@
reflex: true,
title: "Save your modifications",
content: "Once you click on save, your website page is updated.",
template: render('website.tour_popover'),
onHide: function () {
self.saveStep('part-2');
},
},
{
stepId: 'part-2',
orphan: true,
title: "Congratulation!",
content: "Your homepage have been updated. Now, we suggest you insert another snippet to overview possible customization.",
template: render('website.tour_popover', { next: "Continue" }),
template: self.popover({ next: "Continue" }),
},
{
stepId: 'show-tutorials',
@@ -128,12 +108,12 @@
reflex: true,
title: "Help is always available",
content: "You can always click here if you want more helps or continue to build and get more tips about your website contents like page menu, ...",
template: render('website.tour_popover', { end: "Close" }),
template: self.popover({ end: "Close" }),
}
];
return this._super();
},
continueTour: function () {
resume: function () {
return (this.isCurrentStep('part-2') || this.isCurrentStep('show-tutorials')) && !this.tour.ended();
},
});
+30 -16
View File
@@ -4,12 +4,6 @@
var website = openerp.website;
website.add_template_file('/website/static/src/xml/website.tour.xml');
website.tour = {
render: function render (template, dict) {
return openerp.qweb.render(template, dict);
}
};
website.Tour = openerp.Class.extend({
tour: undefined,
steps: [],
@@ -19,9 +13,11 @@
name: this.id,
storage: this.tourStorage,
keyboard: false,
template: this.popover(),
});
this.tour.addSteps(_.map(this.steps, function (step) {
step.title = website.tour.render('website.tour_popover_title', { title: step.title });
step.title = openerp.qweb.render('website.tour_popover_title', { title: step.title });
step.onShow = step.triggers;
return step;
}));
},
@@ -32,7 +28,7 @@
$('.popover.tour').remove();
},
start: function () {
if (this.continueTour() || ((this.currentStepIndex() === 0) && !this.tour.ended())) {
if (this.resume() || ((this.currentStepIndex() === 0) && !this.tour.ended())) {
this.tour.start();
}
},
@@ -59,25 +55,21 @@
this.tour.goto(index);
}
},
saveStep: function (stepId) {
var index = this.indexOfStep(stepId);
this.tourStorage.setItem(this.id+'_current_step', index);
},
stop: function () {
this.tour.end();
},
redirect: function (url) {
url = url || new website.UrlParser(window.location.href);
if (this.startPath && url.pathname !== this.startPath) {
var newUrl = this.startPath + (url.search ? (url.search + "&") : "?") + this.id + "=true"
var newUrl = this.startPath + (url.search ? (url.search + "&") : "?") + this.id + "=true";
window.location.replace(newUrl);
}
},
continueTour: function () {
resume: function () {
// Override if necessary
return this.currentStepIndex() === 0;
},
isTriggerUrl: function (url) {
trigger: function (url) {
// Override if necessary
url = url || new website.UrlParser(window.location.href);
var urlTrigger = this.id + "=true";
@@ -87,6 +79,28 @@
var url = new website.UrlParser(window.location.href);
return pattern.test(url.pathname+url.search);
},
popover: function (options) {
return openerp.qweb.render('website.tour_popover', options);
},
onSnippetDraggedMoveTo: function (stepId) {
var self = this;
var $body = $(document.body);
function beginDrag () {
$('.popover.tour').remove();
function goToNextStep () {
$('#snippets').toggle();
if (stepId) {
self.movetoStep(stepId);
} else {
self.stop();
}
$body.off('mouseup', goToNextStep);
}
$body.off('mousedown', beginDrag);
$body.on('mouseup', goToNextStep);
}
$body.on('mousedown', beginDrag);
}
});
website.UrlParser = openerp.Class.extend({
@@ -122,7 +136,7 @@
tour.start();
});
menu.append($menuItem);
if (tour.isTriggerUrl()) {
if (tour.trigger()) {
tour.start();
}
});
@@ -3,8 +3,6 @@
var website = openerp.website;
var render = website.tour.render;
website.EditorBar.include({
start: function () {
this.registerTour(new website.PageTour(this));
@@ -14,7 +12,7 @@
website.PageTour = website.Tour.extend({
id: 'page-tutorial',
name: "Add a new page",
name: "Add a page",
init: function (editor) {
var self = this;
self.steps = [
@@ -24,7 +22,7 @@
backdrop: true,
title: "Menu editor",
content: "We will show how to edit your website's menu.",
template: render('website.tour_popover', { next: "Start Tutorial", end: "Skip It" }),
template: self.popover({ next: "Start Tutorial", end: "Skip It" }),
},
{
stepId: 'content-menu',
@@ -33,7 +31,6 @@
reflex: true,
title: "Edit the content",
content: "Click here to edit the menu.",
template: render('website.tour_popover'),
},
{
stepId: 'edit-entry',
@@ -41,9 +38,8 @@
placement: 'left',
title: "Edit menu",
content: "Click here to create a new menu entry and manage options.",
template: render('website.tour_popover'),
onShow: function () {
editor.on('tour:menu_editor_dialog_ready', editor, function () {
triggers: function () {
$(document).one('shown.bs.modal', function () {
self.movetoStep('add-menu-entry');
});
},
@@ -54,9 +50,8 @@
placement: 'left',
title: "Add menu entry",
content: "Click here to create a new menu entry.",
template: render('website.tour_popover'),
onShow: function () {
editor.on('tour:new_menu_entry_dialog_ready', editor, function () {
triggers: function () {
$(document).one('shown.bs.modal', function () {
self.movetoStep('enter-entry-name');
});
},
@@ -67,7 +62,7 @@
placement: 'left',
title: "Choose a label",
content: "This label will appear in the top menu and will be visible by all your audience.\nGive a meaningful name to help your visitors. For instance, 'Photos Gallery'.",
template: render('website.tour_popover', { next: "Continue" }),
template: self.popover({ next: "Continue" }),
},
{
stepId: 'enter-page-name',
@@ -75,7 +70,7 @@
placement: 'left',
title: "Link your menu to a 'gallery' page",
content: "This page does not exist. Create it by filling the name here. For instance, 'gallery'.",
template: render('website.tour_popover', { next: "Continue" }),
template: self.popover({ next: "Continue" }),
},
{
stepId: 'save-page',
@@ -83,9 +78,8 @@
placement: 'right',
title: "Save the page",
content: "Save your new page.",
template: render('website.tour_popover'),
onShow: function () {
editor.on('tour:new_menu_entry_dialog_closed', editor, function () {
triggers: function () {
$(document).one('hidden.bs.modal', function () {
self.movetoStep('save-menu');
});
},
@@ -97,7 +91,6 @@
reflex: true,
title: "Save the menu",
content: "Save the menu to edit the Gallery content directly from the interface.",
template: render('website.tour_popover'),
},
];
return this._super();

Some files were not shown because too many files have changed in this diff Show More