[MERGE] forward port of branch 8.0 up to aabbdc7

This commit is contained in:
Denis Ledoux
2015-09-21 16:01:58 +02:00
40 changed files with 468 additions and 319 deletions
+6 -4
View File
@@ -85,8 +85,7 @@ class sale_order(osv.Model):
if order.company_id.currency_id.id != order.pricelist_id.currency_id.id:
price_unit = currency_obj.compute(cr, uid, order.company_id.currency_id.id, order.pricelist_id.currency_id.id,
price_unit, context=dict(context or {}, date=order.date_order))
#create the sale order line
line_id = line_obj.create(cr, uid, {
values = {
'order_id': order.id,
'name': grid.carrier_id.name,
'product_uom_qty': 1,
@@ -94,7 +93,10 @@ class sale_order(osv.Model):
'product_id': grid.carrier_id.product_id.id,
'price_unit': price_unit,
'tax_id': [(6, 0, taxes_ids)],
'is_delivery': True
}, context=context)
'is_delivery': True,
}
if order.order_line:
values['sequence'] = order.order_line[-1].sequence + 1
line_id = line_obj.create(cr, uid, values, context=context)
line_ids.append(line_id)
return line_ids
+3
View File
@@ -7,6 +7,7 @@
<field name="model_id" ref="event.model_event_registration"/>
<field name="email_from">${(object.event_id.organizer_id.email or object.event_id.user_id.email or '')|safe}</field>
<field name="email_to" >${object.email|safe}</field>
<field name="lang">${object.partner_id.lang}</field>
<field name="reply_to">${object.event_id.reply_to|safe}</field>
<field name="subject">Your subscription at ${object.event_id.name}</field>
<field name="body_html"><![CDATA[<p>Hello ${object.name},</p>
@@ -21,6 +22,7 @@ You will automatically receive an email providing you more practical information
<field name="model_id" ref="event.model_event_registration"/>
<field name="email_from">${(object.event_id.organizer_id.email or object.event_id.user_id.email or '')|safe}</field>
<field name="email_to" >${object.partner_id.email or object.email|safe}</field>
<field name="lang">${object.partner_id.lang}</field>
<field name="reply_to">${object.event_id.reply_to|safe}</field>
<field name="subject">Reminder of event ${object.event_id.name}</field>
<field name="body_html"><![CDATA[<p>Hello ${object.name},</p>
@@ -35,6 +37,7 @@ For any further information please contact our event department.</p>
<field name="model_id" ref="event.model_event_registration"/>
<field name="email_from">${(object.event_id.organizer_id.email or object.event_id.user_id.email or '')|safe}</field>
<field name="email_to" >${object.partner_id.email or object.email|safe}</field>
<field name="lang">${object.partner_id.lang}</field>
<field name="reply_to">${object.event_id.reply_to|safe}</field>
<field name="subject">Thanks for attending ${object.event_id.name}</field>
<field name="body_html"><![CDATA[<p>Hello ${object.name},</p>
+8
View File
@@ -76,6 +76,14 @@ class EscposDriver(Thread):
printers = usb.core.find(find_all=True, custom_match=FindUsbClass(7))
# Currently we ask customers to put the STAR TSP650II into
# 'USB Mode' Vendor class instead of Printer class. When set
# to Printer class it doesn't show up under Linux at
# all. Vendor class does work, but that means that it's not
# going to have an interfaceClass 7.
if not printers:
printers = usb.core.find(find_all=True, idVendor=0x0519)
for printer in printers:
connected.append({
'vendor': printer.idVendor,
+4 -4
View File
@@ -86,7 +86,7 @@ class NoStatusError(Error):
self.resultcode = 70
def __str__(self):
return "Impossible to get status from the printer"
return "Impossible to get status from the printer: " + str(self.msg)
class TicketNotPrinted(Error):
def __init__(self, msg=""):
@@ -95,7 +95,7 @@ class TicketNotPrinted(Error):
self.resultcode = 80
def __str__(self):
return "A part of the ticket was not been printed"
return "A part of the ticket was not been printed: " + str(self.msg)
class NoDeviceError(Error):
def __init__(self, msg=""):
@@ -104,7 +104,7 @@ class NoDeviceError(Error):
self.resultcode = 90
def __str__(self):
return "Impossible to find the printer Device"
return str(self.msg)
class HandleDeviceError(Error):
def __init__(self, msg=""):
@@ -113,4 +113,4 @@ class HandleDeviceError(Error):
self.resultcode = 100
def __str__(self):
return "Impossible to handle device"
return str(self.msg)
+1 -1
View File
@@ -58,7 +58,7 @@ class Usb(Escpos):
return True
except usb.core.USBError as e:
i += 1
if i > 100:
if i > 10:
return False
sleep(0.1)
+1 -18
View File
@@ -108,24 +108,7 @@ class Proxy(http.Controller):
if count == 0:
resp += "<div class='device'>No USB Device Found</div>"
resp += "</div>\n"
resp += """
<h2>Add New Printer</h2>
<p>
Copy and paste your printer's device description in the form below. You can find
your printer's description in the device list above. If you find that your printer works
well, please send your printer's description to <a href='mailto:support@odoo.com'>
support@openerp.com</a> so that we can add it to the default list of supported devices.
</p>
<form action='/hw_proxy/escpos/add_supported_device' method='GET'>
<input type='text' style='width:400px' name='device_string' placeholder='123a:b456 Sample Device description' />
<input type='submit' value='submit' />
</form>
<h2>Reset To Defaults</h2>
<p>If the added devices cause problems, you can <a href='/hw_proxy/escpos/reset_supported_devices'>Reset the
device list to factory default.</a> This operation cannot be undone.</p>
"""
resp += "</body>\n</html>\n\n"
resp += "</div>\n</body>\n</html>\n\n"
return request.make_response(resp,{
'Cache-Control': 'no-cache',
-1
View File
@@ -3,7 +3,6 @@
{
'name': 'Saudi Arabia - Accounting',
'version': '1.1',
'sequence': 1,
'author': 'DVIT.ME',
'category': 'Localization/Account Charts',
'description': """
+1 -1
View File
@@ -13,7 +13,7 @@ access_mail_notification_system,mail.notification.system,model_mail_notification
access_mail_group_all,mail.group.all,model_mail_group,,1,0,0,0
access_mail_group_user,mail.group.user,model_mail_group,base.group_user,1,1,1,1
access_mail_alias_all,mail.alias.all,model_mail_alias,,1,0,0,0
access_mail_alias_user,mail.alias.user,model_mail_alias,base.group_user,1,1,1,0
access_mail_alias_user,mail.alias.user,model_mail_alias,base.group_user,1,1,1,1
access_mail_alias_system,mail.alias.system,model_mail_alias,base.group_system,1,1,1,1
access_mail_message_subtype_all,mail.message.subtype.all,model_mail_message_subtype,,1,0,0,0
access_mail_message_subtype_system,mail.message.subtype.system,model_mail_message_subtype,base.group_system,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
13 access_mail_group_all mail.group.all model_mail_group 1 0 0 0
14 access_mail_group_user mail.group.user model_mail_group base.group_user 1 1 1 1
15 access_mail_alias_all mail.alias.all model_mail_alias 1 0 0 0
16 access_mail_alias_user mail.alias.user model_mail_alias base.group_user 1 1 1 0 1
17 access_mail_alias_system mail.alias.system model_mail_alias base.group_system 1 1 1 1
18 access_mail_message_subtype_all mail.message.subtype.all model_mail_message_subtype 1 0 0 0
19 access_mail_message_subtype_system mail.message.subtype.system model_mail_message_subtype base.group_system 1 1 1 1
+1 -1
View File
@@ -232,7 +232,7 @@ class Partner(osv.osv):
s = 4
if partner_data.member_lines:
for mline in partner_data.member_lines:
if mline.date_to >= today:
if mline.date_to >= today and mline.date_from < today:
if mline.account_invoice_line and mline.account_invoice_line.invoice_id:
mstate = mline.account_invoice_line.invoice_id.state
if mstate == 'paid':
+26
View File
@@ -458,6 +458,32 @@ class PaymentTransaction(osv.Model):
return super(PaymentTransaction, self).create(cr, uid, values, context=context)
def write(self, cr, uid, ids, values, context=None):
Acquirer = self.pool['payment.acquirer']
if ('acquirer_id' in values or 'amount' in values) and 'fees' not in values:
# The acquirer or the amount has changed, and the fees are not explicitely forced. Fees must be recomputed.
if isinstance(ids, (int, long)):
ids = [ids]
for txn_id in ids:
vals = dict(values)
vals['fees'] = 0.0
transaction = self.browse(cr, uid, txn_id, context=context)
if 'acquirer_id' in values:
acquirer = Acquirer.browse(cr, uid, values['acquirer_id'], context=context) if values['acquirer_id'] else None
else:
acquirer = transaction.acquirer_id
if acquirer:
custom_method_name = '%s_compute_fees' % acquirer.provider
if hasattr(Acquirer, custom_method_name):
amount = (values['amount'] if 'amount' in values else transaction.amount) or 0.0
currency_id = values.get('currency_id') or transaction.currency_id.id
country_id = values.get('partner_country_id') or transaction.partner_country_id.id
fees = getattr(Acquirer, custom_method_name)(cr, uid, acquirer.id, amount, currency_id, country_id, context=None)
vals['fees'] = float_round(fees, 2)
res = super(PaymentTransaction, self).write(cr, uid, txn_id, vals, context=context)
return res
return super(PaymentTransaction, self).write(cr, uid, ids, values, context=context)
def on_change_partner_id(self, cr, uid, ids, partner_id, context=None):
partner = None
if partner_id:
+1 -1
View File
@@ -302,7 +302,7 @@ class PaymentTxOgone(osv.Model):
'state': 'cancel',
'acquirer_reference': data.get('PAYID'),
})
elif status in self._ogone_pending_tx_status:
elif status in self._ogone_pending_tx_status or status in self._ogone_wait_tx_status:
tx.write({
'state': 'pending',
'acquirer_reference': data.get('PAYID'),
@@ -1,4 +1,5 @@
from datetime import datetime
from openerp import tools
from openerp.osv import fields, osv
from openerp.tools.translate import _
@@ -45,7 +46,7 @@ class stock_history(osv.osv):
res = super(stock_history, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby, lazy=lazy)
if context is None:
context = {}
date = context.get('history_date')
date = context.get('history_date', datetime.now())
if 'inventory_value' in fields:
group_lines = {}
for line in res:
+2 -2
View File
@@ -452,8 +452,8 @@ def content_disposition(filename):
version = int((request.httprequest.user_agent.version or '0').split('.')[0])
if browser == 'msie' and version < 9:
return "attachment; filename=%s" % escaped
elif browser == 'safari':
return u"attachment; filename=%s" % filename
elif browser == 'safari' and version < 537:
return u"attachment; filename=%s" % filename.encode('ascii', 'replace')
else:
return "attachment; filename*=UTF-8''%s" % escaped
+43 -11
View File
@@ -9,11 +9,33 @@
<script src="/web/static/lib/qunit/qunit.js" type="text/javascript"></script>
<script src="/web/static/lib/underscore/underscore.js" type="text/javascript"></script>
<script src="/web/static/lib/underscore/underscore.string.js" type="text/javascript"></script>
<script src="/web/static/lib/underscore.string/lib/underscore.string.js" type="text/javascript"></script>
<!-- jquery -->
<script src="/web/static/lib/jquery/jquery-1.7.2.js"></script>
<script src="/web/static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js"></script>
<script src="/web/static/lib/jquery/jquery.js"></script>
<link rel="stylesheet" href="/web/static/lib/bootstrap/css/bootstrap.css"/>
<script type="text/javascript" src="/web/static/lib/bootstrap/js/bootstrap.js"></script>
<script type="text/javascript" charset="utf-8">
$.fn.bstooltip = $.fn.tooltip;
$.fn.bsbutton = $.fn.button;
</script>
<script type="text/javascript" src="/web/static/lib/jquery.ui/js/jquery-ui-1.9.1.custom.js"></script>
<script type="text/javascript" charset="utf-8">
$.fn.tooltip = $.fn.bstooltip;
$.fn.button = $.fn.bsbutton;
</script>
<link rel="stylesheet" href="/web/static/lib/jquery.ui.timepicker/css/jquery-ui-timepicker-addon.css"/>
<script type="text/javascript" src="/web/static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js"></script>
<link rel="stylesheet" href="/web/static/lib/jquery.ui.notify/css/ui.notify.css"/>
<script type="text/javascript" src="/web/static/lib/jquery.ui.notify/js/jquery.notify.js"></script>
<script src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script>
<script src="/web/static/lib/datejs/globalization/en-US.js"></script>
@@ -23,15 +45,25 @@
<script src="/web/static/lib/datejs/extras.js"></script>
<script src="/web/static/lib/qweb/qweb2.js"></script>
<script type="text/javascript" src="/web/static/src/js/openerpframework.js"></script>
<script type="text/javascript" src="/web/static/lib/backbone/backbone.js"></script>
<script src="/web/static/lib/py.js/lib/py.js"></script>
<script src="/web/static/src/js/boot.js"></script>
<script src="/web/static/src/js/core.js"></script>
<script src="/web/static/src/js/dates.js"></script>
<script src="/web/static/src/js/formats.js"></script>
<script src="/web/static/src/js/chrome.js"></script>
<script src="/web/static/src/js/data.js"></script>
<script type="text/javascript" src="/web/static/lib/py.js/lib/py.js"></script>
<script type="text/javascript" src="/web/static/src/js/boot.js"></script>
<script type="text/javascript" src="/web/static/src/js/testing.js"></script>
<script type="text/javascript" src="/web/static/src/js/pyeval.js"></script>
<script type="text/javascript" src="/web/static/src/js/core.js"></script>
<script type="text/javascript" src="/web/static/src/js/formats.js"></script>
<script type="text/javascript" src="/web/static/src/js/chrome.js"></script>
<script type="text/javascript" src="/web/static/src/js/views.js"></script>
<script type="text/javascript" src="/web/static/src/js/data.js"></script>
<script type="text/javascript" src="/web/static/src/js/data_export.js"></script>
<script type="text/javascript" src="/web/static/src/js/search.js"></script>
<script type="text/javascript" src="/web/static/src/js/view_list.js"></script>
<script type="text/javascript" src="/web/static/src/js/view_form.js"></script>
<script type="text/javascript" src="/web/static/src/js/view_list_editable.js"></script>
<script type="text/javascript" src="/web/static/src/js/view_tree.js"></script>
<script type="text/javascript" src="/base/static/src/js/apps.js"></script>
<script src="/web/static/src/js/test_support.js"></script>
</head>
+1 -1
View File
@@ -441,7 +441,7 @@ class Website(openerp.addons.web.controllers.main.Home):
'/website/image/<xmlid>/<field>/<int:max_width>x<int:max_height>',
'/website/image/<model>/<id>/<field>',
'/website/image/<model>/<id>/<field>/<int:max_width>x<int:max_height>'
], auth="public", website=True)
], auth="public", website=True, multilang=False)
def website_image(self, model=None, id=None, field=None, xmlid=None, max_width=None, max_height=None):
""" Fetches the requested field and ensures it does not go above
(max_width, max_height), resizing it if necessary.
@@ -1122,7 +1122,7 @@ define(['summernote/summernote'], function () {
// escape text nodes for xml saving
var escaped_el = $el.clone();
var to_escape = escaped_el.find('*').addBack();
to_escape = to_escape.not(to_escape.filter('script,style,[data-oe-model][data-oe-model!="ir.ui.view"]').find('*').addBack());
to_escape = to_escape.not(to_escape.filter('object,iframe,script,style,[data-oe-model][data-oe-model!="ir.ui.view"]').find('*').addBack());
to_escape.contents().each(function(){
if(this.nodeType == 3) {
this.nodeValue = $('<div />').text(this.nodeValue).html();
+1 -1
View File
@@ -9,7 +9,7 @@
<h3 class="modal-title">Mobile preview</h3>
</div>
<div class="modal-body">
<iframe id="mobile-viewport" class="oe_mobile_viewport" src="?mobile-preview=true" style="width: 326px"></iframe>
<iframe id="mobile-viewport" class="oe_mobile_viewport" style="width: 326px"></iframe>
</div>
</div>
</div>
@@ -3,8 +3,10 @@ from openerp import SUPERUSER_ID
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models.website import unslug
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from openerp.tools.translate import _
import time
import werkzeug.urls
@@ -40,7 +42,11 @@ class WebsiteMembership(http.Controller):
base_line_domain = [("partner.website_published", "=", True), ('state', 'in', ['free', 'paid'])]
if membership_id and membership_id != 'free':
membership_id = int(membership_id)
base_line_domain.append(('membership_id', '=', membership_id))
today = time.strftime(DEFAULT_SERVER_DATE_FORMAT)
base_line_domain += [
('membership_id', '=', membership_id), ('date_to', '>=', today),
('date_from', '<', today), ('state', '=', 'paid')
]
membership = product_obj.browse(cr, uid, membership_id, context=context)
else:
membership = None
+28 -7
View File
@@ -467,16 +467,31 @@ class website_sale(http.Controller):
mandatory_shipping_fields = ["name", "phone", "street", "city", "country_id"]
optional_shipping_fields = ["state_id", "zip"]
def _get_mandatory_billing_fields(self):
return self.mandatory_billing_fields
def _get_optional_billing_fields(self):
return self.optional_billing_fields
def _get_mandatory_shipping_fields(self):
return self.mandatory_shipping_fields
def _get_optional_shipping_fields(self):
return self.optional_shipping_fields
def _post_prepare_query(self, query, data, address_type):
return query
def checkout_parse(self, address_type, data, remove_prefix=False):
""" data is a dict OR a partner browse record
"""
# set mandatory and optional fields
assert address_type in ('billing', 'shipping')
if address_type == 'billing':
all_fields = self.mandatory_billing_fields + self.optional_billing_fields
all_fields = self._get_mandatory_billing_fields() + self._get_optional_billing_fields()
prefix = ''
else:
all_fields = self.mandatory_shipping_fields + self.optional_shipping_fields
all_fields = self._get_mandatory_shipping_fields() + self._get_optional_shipping_fields()
prefix = 'shipping_'
# set data
@@ -497,6 +512,8 @@ class website_sale(http.Controller):
if query.get(prefix + 'vat'):
query[prefix + 'vat_subjected'] = True
query = self._post_prepare_query(query, data, address_type)
if not remove_prefix:
return query
@@ -509,7 +526,7 @@ class website_sale(http.Controller):
error_message = []
# Validation
for field_name in self.mandatory_billing_fields:
for field_name in self._get_mandatory_billing_fields():
if not data.get(field_name):
error[field_name] = 'missing'
@@ -531,7 +548,7 @@ class website_sale(http.Controller):
error["vat"] = 'error'
if data.get("shipping_id") == -1:
for field_name in self.mandatory_shipping_fields:
for field_name in self._get_mandatory_shipping_fields():
field_name = 'shipping_' + field_name
if not data.get(field_name):
error[field_name] = 'missing'
@@ -542,6 +559,12 @@ class website_sale(http.Controller):
return error, error_message
def _get_shipping_info(self, checkout):
shipping_info = {}
shipping_info.update(self.checkout_parse('shipping', checkout, True))
shipping_info['type'] = 'delivery'
return shipping_info
def checkout_form_save(self, checkout):
cr, uid, context, registry = request.cr, request.uid, request.context, request.registry
@@ -578,11 +601,9 @@ class website_sale(http.Controller):
# create a new shipping partner
if checkout.get('shipping_id') == -1:
shipping_info = {}
shipping_info = self._get_shipping_info(checkout)
if partner_lang:
shipping_info['lang'] = partner_lang
shipping_info.update(self.checkout_parse('shipping', checkout, True))
shipping_info['type'] = 'delivery'
shipping_info['parent_id'] = partner_id
checkout['shipping_id'] = orm_partner.create(cr, SUPERUSER_ID, shipping_info, context)
+4 -2
View File
@@ -2,13 +2,15 @@
from . import pygments_override
from . import switcher
from . import translator
import sphinx.environment
import sphinx.builders.html
from docutils import nodes
def setup(app):
app.set_translator('html', translator.BootstrapTranslator)
if getattr(app.config, 'html_translator_class', None):
app.warn("Overriding the explicitly set html_translator_class setting",
location="odoo extension")
app.config.html_translator_class = 'odoo.translator.BootstrapTranslator'
switcher.setup(app)
app.add_config_value('odoo_cover_default', None, 'env')
+109 -33
View File
@@ -9098,7 +9098,8 @@ hr.divider {
width: 900%;
margin-left: -13px;
}
main .alert {
main .alert,
main .deprecated {
padding: 15px;
border-radius: 0;
border-width: 0 0 0 3px;
@@ -9110,25 +9111,35 @@ main .alert {
color: #173038;
}
@media (min-width: 480px) {
main .alert {
main .alert,
main .deprecated {
padding-left: 5.5em;
}
}
main .alert > p,
main .alert > ul {
main .deprecated > p,
main .alert > ul,
main .deprecated > ul {
margin: .5em 0;
}
main .alert > .alert-title,
main .alert > h3 {
main .deprecated > .alert-title,
main .alert > h3,
main .deprecated > h3 {
color: #4b9eb6;
}
main .alert > .alert-title:before,
main .alert > h3:before {
main .deprecated > .alert-title:before,
main .alert > h3:before,
main .deprecated > h3:before {
content: "\e639";
}
main .alert > h3,
main .alert > .alert-title {
font-size: 1.642857143em;
main .deprecated > h3,
main .alert > .alert-title,
main .deprecated > .alert-title,
main .alert > p > .versionmodified,
main .deprecated > p > .versionmodified {
line-height: 1em;
margin: 0 0 10px 0;
font-size: 14px;
@@ -9136,12 +9147,15 @@ main .alert > .alert-title {
font-family: Lato, sans-serif;
}
main .alert > h3:before,
main .alert > .alert-title:before {
main .deprecated > h3:before,
main .alert > .alert-title:before,
main .deprecated > .alert-title:before,
main .alert > p > .versionmodified:before,
main .deprecated > p > .versionmodified:before {
font-family: 'Material-Design-Icons';
content: "\e639";
display: inline-block;
text-rendering: geometricPrecision;
font-size: 1.6em;
transform: translate(0, -0.15em);
position: absolute;
top: 50%;
@@ -9152,83 +9166,144 @@ main .alert > .alert-title:before {
}
@media (max-width: 480px) {
main .alert > h3:before,
main .alert > .alert-title:before {
main .deprecated > h3:before,
main .alert > .alert-title:before,
main .deprecated > .alert-title:before,
main .alert > p > .versionmodified:before,
main .deprecated > p > .versionmodified:before {
display: none;
}
}
main .alert.alert-success {
main .alert.alert-success,
main .deprecated.alert-success {
border-color: #b9dfb9;
background-color: #eef7ee;
color: #183518;
}
main .alert.alert-success > .alert-title,
main .alert.alert-success > h3 {
main .deprecated.alert-success > .alert-title,
main .alert.alert-success > h3,
main .deprecated.alert-success > h3 {
color: #50af51;
}
main .alert.alert-success > .alert-title:before,
main .alert.alert-success > h3:before {
main .deprecated.alert-success > .alert-title:before,
main .alert.alert-success > h3:before,
main .deprecated.alert-success > h3:before {
content: "\e625";
}
main .alert.alert-info,
main .alert.tip {
main .deprecated.alert-info,
main .alert.tip,
main .deprecated.tip {
border-color: #b8d9e2;
background-color: #eef6f8;
color: #173038;
}
main .alert.alert-info > .alert-title,
main .deprecated.alert-info > .alert-title,
main .alert.tip > .alert-title,
main .deprecated.tip > .alert-title,
main .alert.alert-info > h3,
main .alert.tip > h3 {
main .deprecated.alert-info > h3,
main .alert.tip > h3,
main .deprecated.tip > h3 {
color: #4b9eb6;
}
main .alert.alert-info > .alert-title:before,
main .deprecated.alert-info > .alert-title:before,
main .alert.tip > .alert-title:before,
main .deprecated.tip > .alert-title:before,
main .alert.alert-info > h3:before,
main .alert.tip > h3:before {
main .deprecated.alert-info > h3:before,
main .alert.tip > h3:before,
main .deprecated.tip > h3:before {
content: "\e639";
}
main .alert.alert-warning,
main .alert.warning {
main .deprecated.alert-warning,
main .alert.warning,
main .deprecated.warning,
main .alert.deprecated,
main .deprecated.deprecated {
border-color: #fceedb;
background-color: #fef9f3;
color: #81500b;
}
main .alert.alert-warning > .alert-title,
main .deprecated.alert-warning > .alert-title,
main .alert.warning > .alert-title,
main .deprecated.warning > .alert-title,
main .alert.deprecated > .alert-title,
main .deprecated.deprecated > .alert-title,
main .alert.alert-warning > h3,
main .alert.warning > h3 {
main .deprecated.alert-warning > h3,
main .alert.warning > h3,
main .deprecated.warning > h3,
main .alert.deprecated > h3,
main .deprecated.deprecated > h3,
main .alert.alert-warning > p > .versionmodified,
main .deprecated.alert-warning > p > .versionmodified,
main .alert.warning > p > .versionmodified,
main .deprecated.warning > p > .versionmodified,
main .alert.deprecated > p > .versionmodified,
main .deprecated.deprecated > p > .versionmodified {
color: #f0ad4e;
}
main .alert.alert-warning > .alert-title:before,
main .deprecated.alert-warning > .alert-title:before,
main .alert.warning > .alert-title:before,
main .deprecated.warning > .alert-title:before,
main .alert.deprecated > .alert-title:before,
main .deprecated.deprecated > .alert-title:before,
main .alert.alert-warning > h3:before,
main .alert.warning > h3:before {
main .deprecated.alert-warning > h3:before,
main .alert.warning > h3:before,
main .deprecated.warning > h3:before,
main .alert.deprecated > h3:before,
main .deprecated.deprecated > h3:before,
main .alert.alert-warning > p > .versionmodified:before,
main .deprecated.alert-warning > p > .versionmodified:before,
main .alert.warning > p > .versionmodified:before,
main .deprecated.warning > p > .versionmodified:before,
main .alert.deprecated > p > .versionmodified:before,
main .deprecated.deprecated > p > .versionmodified:before {
content: "\e6a4";
}
main .alert.alert-danger {
main .alert.alert-danger,
main .deprecated.alert-danger {
border-color: #f4cecd;
background-color: #fdf7f7;
color: #611715;
}
main .alert.alert-danger > .alert-title,
main .alert.alert-danger > h3 {
main .deprecated.alert-danger > .alert-title,
main .alert.alert-danger > h3,
main .deprecated.alert-danger > h3 {
color: #d9534f;
}
main .alert.alert-danger > .alert-title:before,
main .alert.alert-danger > h3:before {
main .deprecated.alert-danger > .alert-title:before,
main .alert.alert-danger > h3:before,
main .deprecated.alert-danger > h3:before {
content: "\e6a4";
}
main .alert.alert-exercise {
main .alert.alert-exercise,
main .deprecated.alert-exercise {
border-color: #deddde;
background-color: #f7f7f7;
color: #393639;
}
main .alert.alert-exercise > .alert-title,
main .alert.alert-exercise > h3 {
main .deprecated.alert-exercise > .alert-title,
main .alert.alert-exercise > h3,
main .deprecated.alert-exercise > h3 {
color: #938e94;
}
main .alert.alert-exercise > .alert-title:before,
main .alert.alert-exercise > h3:before {
main .deprecated.alert-exercise > .alert-title:before,
main .alert.alert-exercise > h3:before,
main .deprecated.alert-exercise > h3:before {
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
-o-transform: translate(0, 0);
@@ -9237,10 +9312,14 @@ main .alert.alert-exercise > h3:before {
content: "\e709";
}
@media (min-width: 1170px) {
main .alert.doc-content {
main .alert.doc-content,
main .deprecated.doc-content {
max-width: 55%;
}
}
main .deprecated .versionmodified {
display: block;
}
.pq-patch {
background: #c2c2c2;
}
@@ -9508,7 +9587,7 @@ aside {
#navClone ul li {
padding: 0;
position: relative;
border-radius: none;
border-radius: 0;
border-bottom: 1px solid rgba(35, 43, 65, 0.1);
}
.navbar-aside ul li > a,
@@ -9520,7 +9599,7 @@ aside {
color: #393f4f;
font-weight: bold;
display: block;
border-radius: none;
border-radius: 0;
line-height: 1.2;
background: #dbdbdb;
border-bottom: none;
@@ -9531,9 +9610,8 @@ aside {
#navClone ul li > a:active,
.navbar-aside ul li > a:focus,
#navClone ul li > a:focus {
background-color: transparent;
text-decoration: none;
border-radius: none;
border-radius: 0;
background: #cecece;
border-left: 5px solid rgba(33, 183, 153, 0.5);
}
@@ -9617,7 +9695,6 @@ aside {
height: 56px;
display: inline-block;
z-index: 0;
background-color: transparent;
border-radius: 50%;
padding: 16px;
box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.05);
@@ -9636,7 +9713,7 @@ aside {
position: absolute;
z-index: 1;
overflow: hidden;
right: 0%;
right: 0;
width: 380px;
bottom: 0;
padding: 0;
@@ -9650,7 +9727,6 @@ aside {
box-shadow: 0 0 0 transparent;
}
#floating_action_menu .content {
margin-bottom: 0;
margin: 0;
opacity: 0;
filter: alpha(opacity=0);
+28 -30
View File
@@ -353,7 +353,7 @@ hr.divider {
margin-left: -13px;
}
main .alert {
main .alert, main .deprecated {
padding: 15px;
border-radius: 0;
border-width: 0 0 0 3px;
@@ -368,8 +368,7 @@ main .alert {
}
.alert-info; // 'INFO' is the default style
> h3, > .alert-title {
font-size: 1.642857143em;
> h3, > .alert-title, > p > .versionmodified {
line-height: 1em;
margin: 0 0 10px 0;
font-size: 14px;
@@ -381,7 +380,6 @@ main .alert {
content: "\e639";
display: inline-block;
text-rendering: geometricPrecision;
font-size: 1.6em;
transform: translate(0, -0.15em);
position: absolute;
top: 50%;
@@ -412,22 +410,22 @@ main .alert {
color: darken(@doc_info, 35%);
> .alert-title, > h3 {
color: @doc_info
}
> .alert-title:before, > h3:before {
content: "\e639";
color: @doc_info;
&:before {
content: "\e639";
}
}
}
&.alert-warning, &.warning {
&.alert-warning, &.warning, &.deprecated {
border-color: lighten(@doc_warning, 30%);
background-color: lighten(@doc_warning, 35%);
color: darken(@doc_warning, 35%);
> .alert-title, > h3 {
color: @doc_warning
}
> .alert-title:before, > h3:before {
content: "\e6a4";
> .alert-title, > h3, > p > .versionmodified {
color: @doc_warning;
&:before {
content: "\e6a4";
}
}
}
&.alert-danger {
@@ -436,10 +434,10 @@ main .alert {
color: darken(@doc_danger, 35%);
> .alert-title, > h3 {
color: @doc_danger
}
> .alert-title:before, > h3:before {
content: "\e6a4";
color: @doc_danger;
&:before {
content: "\e6a4";
}
}
}
&.alert-exercise {
@@ -449,11 +447,11 @@ main .alert {
> .alert-title, > h3 {
color: @doc_exercise;
}
> .alert-title:before, > h3:before {
.translate(0;0);
top: 28px;
content: "\e709";
&:before {
.translate(0;0);
top: 28px;
content: "\e709";
}
}
}
@@ -463,6 +461,9 @@ main .alert {
}
}
}
main .deprecated .versionmodified {
display: block;
}
.pq-patch{
background: rgb(194, 194, 194);
@@ -688,7 +689,7 @@ aside{
li {
padding: 0;
position:relative;
border-radius: none;
border-radius: 0;
border-bottom: 1px solid fadeout(@doc_text, 90%);
> a {
font-size: 0.7em;
@@ -698,15 +699,14 @@ aside{
color: @doc_heading;
font-weight: bold;
display: block;
border-radius: none;
border-radius: 0;
line-height: 1.2;
background: darken(@doc_paper_dark, 10%);
border-bottom: none;
&:hover, &:active, &:focus {
background-color: transparent;
text-decoration: none;
border-radius: none;
border-radius: 0;
background: darken(@doc_paper_dark, 15%);
border-left: 5px solid fadeout(@doc_accent, 50%);
}
@@ -788,7 +788,6 @@ aside{
height: 56px;
display: inline-block;
z-index: 0;
background-color: transparent;
border-radius: 50%;
padding: 16px;
box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.05);
@@ -806,7 +805,7 @@ aside{
position: absolute;
z-index: 1;
overflow: hidden;
right: 0%;
right: 0;
width: 380px;
bottom: 0;
padding: 0;
@@ -817,7 +816,6 @@ aside{
.box-shadow(0 0 0 transparent);
.content {
margin-bottom: 0;
margin:0;
li {
border: none;
+2 -9
View File
@@ -787,13 +787,6 @@ method should simply set the value of the field to compute on every record in
for record in self:
record.name = str(random.randint(1, 1e6))
Our compute method is very simple: it loops over ``self`` and performs the same
operation on every record. We can make it slightly simpler by using the
decorator :func:`~openerp.api.one` to automatically loop on the collection::
@api.one
def _compute_name(self):
self.name = str(random.randint(1, 1e6))
Dependencies
------------
@@ -812,10 +805,10 @@ field whenever some of its dependencies have been modified::
name = fields.Char(compute='_compute_name')
value = fields.Integer()
@api.one
@api.depends('value')
def _compute_name(self):
self.name = "Record with value %s" % self.value
for record in self:
self.name = "Record with value %s" % self.value
.. exercise:: Computed fields
+29 -30
View File
@@ -1,10 +1,10 @@
# HG changeset patch
# Parent 85a8d7317b9e13480f39ad739955442d15144451
# Parent 16fcdc4c6462a7872636f3c19550c16879af5281
Index: addons/openacademy/models.py
===================================================================
--- addons.orig/openacademy/models.py 2014-08-28 13:45:01.987048512 +0200
+++ addons/openacademy/models.py 2014-08-28 13:59:30.387035620 +0200
diff --git a/openacademy/models.py b/openacademy/models.py
--- a/openacademy/models.py
+++ b/openacademy/models.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
@@ -12,50 +12,49 @@ Index: addons/openacademy/models.py
from openerp import models, fields, api, exceptions
class Course(models.Model):
@@ -55,6 +56,8 @@
@@ -55,6 +56,8 @@ class Session(models.Model):
attendee_ids = fields.Many2many('res.partner', string="Attendees")
taken_seats = fields.Float(string="Taken seats", compute='_taken_seats')
+ end_date = fields.Date(string="End Date", store=True,
+ compute='_get_end_date', inverse='_set_end_date')
@api.one
@api.depends('seats', 'attendee_ids')
@@ -82,6 +85,30 @@
def _taken_seats(self):
@@ -81,6 +84,30 @@ class Session(models.Model):
},
}
@api.one
+ @api.depends('start_date', 'duration')
+ def _get_end_date(self):
+ if not (self.start_date and self.duration):
+ self.end_date = self.start_date
+ return
+ for r in self:
+ if not (r.start_date and r.duration):
+ r.end_date = r.start_date
+ continue
+
+ # Add duration to start_date, but: Monday + 5 days = Saturday, so
+ # subtract one second to get on Friday instead
+ start = fields.Datetime.from_string(self.start_date)
+ duration = timedelta(days=self.duration, seconds=-1)
+ self.end_date = start + duration
+ # Add duration to start_date, but: Monday + 5 days = Saturday, so
+ # subtract one second to get on Friday instead
+ start = fields.Datetime.from_string(r.start_date)
+ duration = timedelta(days=r.duration, seconds=-1)
+ r.end_date = start + duration
+
+ @api.one
+ def _set_end_date(self):
+ if not (self.start_date and self.end_date):
+ return
+ for r in self:
+ if not (r.start_date and r.end_date):
+ continue
+
+ # Compute the difference between dates, but: Friday - Monday = 4 days,
+ # so add one day to get 5 days instead
+ start_date = fields.Datetime.from_string(self.start_date)
+ end_date = fields.Datetime.from_string(self.end_date)
+ self.duration = (end_date - start_date).days + 1
+ # Compute the difference between dates, but: Friday - Monday = 4 days,
+ # so add one day to get 5 days instead
+ start_date = fields.Datetime.from_string(r.start_date)
+ end_date = fields.Datetime.from_string(r.end_date)
+ r.duration = (end_date - start_date).days + 1
+
+ @api.one
@api.constrains('instructor_id', 'attendee_ids')
def _check_instructor_not_in_attendees(self):
if self.instructor_id and self.instructor_id in self.attendee_ids:
Index: addons/openacademy/views/openacademy.xml
===================================================================
--- addons.orig/openacademy/views/openacademy.xml 2014-08-28 13:45:01.987048512 +0200
+++ addons/openacademy/views/openacademy.xml 2014-08-28 13:54:02.000000000 +0200
for r in self:
diff --git a/openacademy/views/openacademy.xml b/openacademy/views/openacademy.xml
--- a/openacademy/views/openacademy.xml
+++ b/openacademy/views/openacademy.xml
@@ -125,11 +125,24 @@
</field>
</record>
+13 -14
View File
@@ -1,28 +1,27 @@
# HG changeset patch
# Parent a358be0a577b0569831958a8ec1302825c645dee
# Parent 59107edbe5f81bab5e7db172bf2bffa504ce399a
Index: addons/openacademy/models.py
===================================================================
--- addons.orig/openacademy/models.py 2014-08-26 17:26:03.795783315 +0200
+++ addons/openacademy/models.py 2014-08-26 17:26:03.791783315 +0200
@@ -28,3 +28,13 @@
diff --git a/openacademy/models.py b/openacademy/models.py
--- a/openacademy/models.py
+++ b/openacademy/models.py
@@ -28,3 +28,13 @@ class Session(models.Model):
course_id = fields.Many2one('openacademy.course',
ondelete='cascade', string="Course", required=True)
attendee_ids = fields.Many2many('res.partner', string="Attendees")
+
+ taken_seats = fields.Float(string="Taken seats", compute='_taken_seats')
+
+ @api.one
+ @api.depends('seats', 'attendee_ids')
+ def _taken_seats(self):
+ if not self.seats:
+ self.taken_seats = 0.0
+ else:
+ self.taken_seats = 100.0 * len(self.attendee_ids) / self.seats
Index: addons/openacademy/views/openacademy.xml
===================================================================
--- addons.orig/openacademy/views/openacademy.xml 2014-08-26 17:26:03.795783315 +0200
+++ addons/openacademy/views/openacademy.xml 2014-08-26 17:26:03.791783315 +0200
+ for r in self:
+ if not r.seats:
+ r.taken_seats = 0.0
+ else:
+ r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats
diff --git a/openacademy/views/openacademy.xml b/openacademy/views/openacademy.xml
--- a/openacademy/views/openacademy.xml
+++ b/openacademy/views/openacademy.xml
@@ -100,6 +100,7 @@
<field name="start_date"/>
<field name="duration"/>
@@ -1,10 +1,10 @@
# HG changeset patch
# Parent 7a7d003fe38426a405ce0657a627a139133ec4dd
# Parent 52f54b46487c8224a5aade4b921be77360ed3eae
Index: addons/openacademy/models.py
===================================================================
--- addons.orig/openacademy/models.py 2014-08-26 17:26:06.591783274 +0200
+++ addons/openacademy/models.py 2014-08-26 17:26:06.587783274 +0200
diff --git a/openacademy/models.py b/openacademy/models.py
--- a/openacademy/models.py
+++ b/openacademy/models.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
@@ -13,13 +13,13 @@ Index: addons/openacademy/models.py
class Course(models.Model):
_name = 'openacademy.course'
@@ -56,3 +56,9 @@
@@ -56,3 +56,9 @@ class Session(models.Model):
'message': "Increase seats or remove excess attendees",
},
}
+
+ @api.one
+ @api.constrains('instructor_id', 'attendee_ids')
+ def _check_instructor_not_in_attendees(self):
+ if self.instructor_id and self.instructor_id in self.attendee_ids:
+ raise exceptions.ValidationError("A session's instructor can't be an attendee")
+ for r in self:
+ if r.instructor_id and r.instructor_id in r.attendee_ids:
+ raise exceptions.ValidationError("A session's instructor can't be an attendee")
+6 -6
View File
@@ -1,15 +1,15 @@
# HG changeset patch
# Parent 7d14b75cdfd4c7a272a13572947de5d47f3e851f
# Parent f400352a70963801f0b4732d33a0183e4f6800ff
Index: addons/openacademy/models.py
===================================================================
--- addons.orig/openacademy/models.py 2014-08-28 11:00:44.343194847 +0200
+++ addons/openacademy/models.py 2014-08-28 13:44:32.143048955 +0200
@@ -13,6 +13,20 @@
diff --git a/openacademy/models.py b/openacademy/models.py
--- a/openacademy/models.py
+++ b/openacademy/models.py
@@ -13,6 +13,20 @@ class Course(models.Model):
session_ids = fields.One2many(
'openacademy.session', 'course_id', string="Sessions")
+ @api.one
+ @api.multi
+ def copy(self, default=None):
+ default = dict(default or {})
+
+17 -18
View File
@@ -1,40 +1,39 @@
# HG changeset patch
# Parent dba00a105dd2a82490394b8dec5fea5f1d8847e1
# Parent f4374b6e2e661e0782e396b24c57c1eb97d13288
Index: addons/openacademy/models.py
===================================================================
--- addons.orig/openacademy/models.py 2014-08-28 14:21:46.543015785 +0200
+++ addons/openacademy/models.py 2014-08-28 14:21:46.539015785 +0200
@@ -59,6 +59,9 @@
diff --git a/openacademy/models.py b/openacademy/models.py
--- a/openacademy/models.py
+++ b/openacademy/models.py
@@ -59,6 +59,9 @@ class Session(models.Model):
end_date = fields.Date(string="End Date", store=True,
compute='_get_end_date', inverse='_set_end_date')
+ hours = fields.Float(string="Duration in hours",
+ compute='_get_hours', inverse='_set_hours')
+
@api.one
@api.depends('seats', 'attendee_ids')
def _taken_seats(self):
@@ -109,6 +112,15 @@
self.duration = (end_date - start_date).days + 1
for r in self:
@@ -108,6 +111,15 @@ class Session(models.Model):
end_date = fields.Datetime.from_string(r.end_date)
r.duration = (end_date - start_date).days + 1
@api.one
+ @api.depends('duration')
+ def _get_hours(self):
+ self.hours = self.duration * 24
+ for r in self:
+ r.hours = r.duration * 24
+
+ @api.one
+ def _set_hours(self):
+ self.duration = self.hours / 24
+ for r in self:
+ r.duration = r.hours / 24
+
+ @api.one
@api.constrains('instructor_id', 'attendee_ids')
def _check_instructor_not_in_attendees(self):
if self.instructor_id and self.instructor_id in self.attendee_ids:
Index: addons/openacademy/views/openacademy.xml
===================================================================
--- addons.orig/openacademy/views/openacademy.xml 2014-08-28 14:21:46.543015785 +0200
+++ addons/openacademy/views/openacademy.xml 2014-08-28 14:21:46.539015785 +0200
for r in self:
diff --git a/openacademy/views/openacademy.xml b/openacademy/views/openacademy.xml
--- a/openacademy/views/openacademy.xml
+++ b/openacademy/views/openacademy.xml
@@ -145,11 +145,23 @@
</field>
</record>
+16 -17
View File
@@ -1,37 +1,36 @@
# HG changeset patch
# Parent a6fe4d3923db1f8f5dff2c39a711a814b0a0f549
# Parent 0687e07f570f363bf5005c6337e0c565a63a6bac
Index: addons/openacademy/models.py
===================================================================
--- addons.orig/openacademy/models.py 2014-08-28 14:21:55.039015659 +0200
+++ addons/openacademy/models.py 2014-08-28 14:21:55.031015659 +0200
@@ -62,6 +62,9 @@
diff --git a/openacademy/models.py b/openacademy/models.py
--- a/openacademy/models.py
+++ b/openacademy/models.py
@@ -62,6 +62,9 @@ class Session(models.Model):
hours = fields.Float(string="Duration in hours",
compute='_get_hours', inverse='_set_hours')
+ attendees_count = fields.Integer(
+ string="Attendees count", compute='_get_attendees_count', store=True)
+
@api.one
@api.depends('seats', 'attendee_ids')
def _taken_seats(self):
@@ -121,6 +124,11 @@
self.duration = self.hours / 24
for r in self:
@@ -120,6 +123,11 @@ class Session(models.Model):
for r in self:
r.duration = r.hours / 24
@api.one
+ @api.depends('attendee_ids')
+ def _get_attendees_count(self):
+ self.attendees_count = len(self.attendee_ids)
+ for r in self:
+ r.attendees_count = len(r.attendee_ids)
+
+ @api.one
@api.constrains('instructor_id', 'attendee_ids')
def _check_instructor_not_in_attendees(self):
if self.instructor_id and self.instructor_id in self.attendee_ids:
Index: addons/openacademy/views/openacademy.xml
===================================================================
--- addons.orig/openacademy/views/openacademy.xml 2014-08-28 14:21:55.039015659 +0200
+++ addons/openacademy/views/openacademy.xml 2014-08-28 14:21:55.031015659 +0200
@@ -158,11 +158,22 @@
for r in self:
diff --git a/openacademy/views/openacademy.xml b/openacademy/views/openacademy.xml
--- a/openacademy/views/openacademy.xml
+++ b/openacademy/views/openacademy.xml
@@ -157,11 +157,22 @@
</field>
</record>
+8 -8
View File
@@ -1,14 +1,14 @@
# HG changeset patch
# Parent 8d5573b704b2867788dd6895503f1871c2976a29
# Parent 9eb163e5da677a0d09e01a354ba56697b576a4bc
Index: addons/openacademy/models.py
===================================================================
--- addons.orig/openacademy/models.py 2014-08-26 17:26:05.687783287 +0200
+++ addons/openacademy/models.py 2014-08-26 17:26:05.679783287 +0200
@@ -39,3 +39,20 @@
self.taken_seats = 0.0
else:
self.taken_seats = 100.0 * len(self.attendee_ids) / self.seats
diff --git a/openacademy/models.py b/openacademy/models.py
--- a/openacademy/models.py
+++ b/openacademy/models.py
@@ -39,3 +39,20 @@ class Session(models.Model):
r.taken_seats = 0.0
else:
r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats
+
+ @api.onchange('seats', 'attendee_ids')
+ def _verify_valid_seats(self):
+15 -16
View File
@@ -1,39 +1,38 @@
# HG changeset patch
# Parent 8c721171aa16a41e94059f53d6780c67b5ef2dfc
# Parent 8d2ca42b5be2031ea9624896df53f09f7ca131be
Index: addons/openacademy/models.py
===================================================================
--- addons.orig/openacademy/models.py 2014-08-28 14:22:01.371015565 +0200
+++ addons/openacademy/models.py 2014-08-28 14:22:01.367015565 +0200
@@ -66,6 +66,24 @@
diff --git a/openacademy/models.py b/openacademy/models.py
--- a/openacademy/models.py
+++ b/openacademy/models.py
@@ -66,6 +66,24 @@ class Session(models.Model):
attendees_count = fields.Integer(
string="Attendees count", compute='_get_attendees_count', store=True)
+ state = fields.Selection([
+ ('draft', "Draft"),
+ ('confirmed', "Confirmed"),
+ ('done', "Done"),
+ ('draft', "Draft"),
+ ('confirmed', "Confirmed"),
+ ('done', "Done"),
+ ], default='draft')
+
+ @api.one
+ @api.multi
+ def action_draft(self):
+ self.state = 'draft'
+
+ @api.one
+ @api.multi
+ def action_confirm(self):
+ self.state = 'confirmed'
+
+ @api.one
+ @api.multi
+ def action_done(self):
+ self.state = 'done'
+
@api.one
@api.depends('seats', 'attendee_ids')
def _taken_seats(self):
Index: addons/openacademy/views/openacademy.xml
===================================================================
--- addons.orig/openacademy/views/openacademy.xml 2014-08-28 14:22:01.371015565 +0200
+++ addons/openacademy/views/openacademy.xml 2014-08-28 14:22:01.367015565 +0200
for r in self:
diff --git a/openacademy/views/openacademy.xml b/openacademy/views/openacademy.xml
--- a/openacademy/views/openacademy.xml
+++ b/openacademy/views/openacademy.xml
@@ -96,6 +96,19 @@
<field name="model">openacademy.session</field>
<field name="arch" type="xml">
+19 -21
View File
@@ -1,10 +1,10 @@
# HG changeset patch
# Parent c72382bf0c5794135fa318f6ba59899b2277d8c5
# Parent 82f902dbb7aab4d3ddd9caaa9170536afa9d274d
Index: addons/openacademy/__openerp__.py
===================================================================
--- addons.orig/openacademy/__openerp__.py 2014-08-28 14:22:04.135015524 +0200
+++ addons/openacademy/__openerp__.py 2014-08-28 14:22:04.131015524 +0200
diff --git a/openacademy/__openerp__.py b/openacademy/__openerp__.py
--- a/openacademy/__openerp__.py
+++ b/openacademy/__openerp__.py
@@ -29,6 +29,7 @@
'templates.xml',
'views/openacademy.xml',
@@ -13,23 +13,21 @@ Index: addons/openacademy/__openerp__.py
],
# only loaded in demonstration mode
'demo': [
Index: addons/openacademy/models.py
===================================================================
--- addons.orig/openacademy/models.py 2014-08-28 14:22:04.135015524 +0200
+++ addons/openacademy/models.py 2014-08-28 14:22:04.131015524 +0200
@@ -70,7 +70,7 @@
('draft', "Draft"),
('confirmed', "Confirmed"),
('done', "Done"),
diff --git a/openacademy/models.py b/openacademy/models.py
--- a/openacademy/models.py
+++ b/openacademy/models.py
@@ -70,7 +70,7 @@ class Session(models.Model):
('draft', "Draft"),
('confirmed', "Confirmed"),
('done', "Done"),
- ], default='draft')
+ ])
@api.one
@api.multi
def action_draft(self):
Index: addons/openacademy/views/openacademy.xml
===================================================================
--- addons.orig/openacademy/views/openacademy.xml 2014-08-28 14:22:04.135015524 +0200
+++ addons/openacademy/views/openacademy.xml 2014-08-28 14:22:04.131015524 +0200
diff --git a/openacademy/views/openacademy.xml b/openacademy/views/openacademy.xml
--- a/openacademy/views/openacademy.xml
+++ b/openacademy/views/openacademy.xml
@@ -97,13 +97,13 @@
<field name="arch" type="xml">
<form string="Session Form">
@@ -47,10 +45,10 @@ Index: addons/openacademy/views/openacademy.xml
string="Mark as done" states="confirmed"
class="oe_highlight"/>
<field name="state" widget="statusbar"/>
Index: addons/openacademy/views/session_workflow.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ addons/openacademy/views/session_workflow.xml 2014-08-28 14:22:04.131015524 +0200
diff --git a/openacademy/views/session_workflow.xml b/openacademy/views/session_workflow.xml
new file mode 100644
--- /dev/null
+++ b/openacademy/views/session_workflow.xml
@@ -0,0 +1,50 @@
+<openerp>
+ <data>
+13 -11
View File
@@ -1,7 +1,9 @@
Index: addons/openacademy/models.py
===================================================================
--- addons.orig/openacademy/models.py 2014-08-28 14:02:42.203032773 +0200
+++ addons/openacademy/models.py 2014-08-28 14:06:54.871029022 +0200
# HG changeset patch
# Parent 7c95aad3b60e4c2006c5f706bd157e8e05318bfa
diff --git a/openacademy/models.py b/openacademy/models.py
--- a/openacademy/models.py
+++ b/openacademy/models.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
@@ -11,7 +13,7 @@ Index: addons/openacademy/models.py
class Course(models.Model):
_name = 'openacademy.course'
@@ -19,11 +19,11 @@
@@ -19,11 +19,11 @@ class Course(models.Model):
default = dict(default or {})
copied_count = self.search_count(
@@ -26,7 +28,7 @@ Index: addons/openacademy/models.py
default['name'] = new_name
return super(Course, self).copy(default)
@@ -97,15 +97,15 @@
@@ -97,15 +97,15 @@ class Session(models.Model):
if self.seats < 0:
return {
'warning': {
@@ -46,9 +48,9 @@ Index: addons/openacademy/models.py
},
}
@@ -151,4 +151,4 @@
@api.constrains('instructor_id', 'attendee_ids')
@@ -151,4 +151,4 @@ class Session(models.Model):
def _check_instructor_not_in_attendees(self):
if self.instructor_id and self.instructor_id in self.attendee_ids:
- raise exceptions.ValidationError("A session's instructor can't be an attendee")
+ raise exceptions.ValidationError(_("A session's instructor can't be an attendee"))
for r in self:
if r.instructor_id and r.instructor_id in r.attendee_ids:
- raise exceptions.ValidationError("A session's instructor can't be an attendee")
+ raise exceptions.ValidationError(_("A session's instructor can't be an attendee"))
+2 -2
View File
@@ -766,8 +766,8 @@ Method decorators
=================
.. automodule:: openerp.api
:members: one, multi, model, depends, constrains, onchange, returns,
v7, v8
:members: multi, model, depends, constrains, onchange, returns,
one, v7, v8
.. _reference/orm/fields:
+19 -15
View File
@@ -10,11 +10,14 @@
Upgrade API
===========
Introduction
~~~~~~~~~~~~
This document describes the API used to upgrade an Odoo database to a
higher version.
It allows a database to be upgraded without ressorting to the html form at
https://upgrade.odoo.com/database/upload
https://upgrade.odoo.com
Although the database will follow the same process described on that form.
@@ -26,6 +29,9 @@ The required steps are:
* obtaining the status of the database request
* downloading the upgraded database dump
The methods
~~~~~~~~~~~
.. _upgrade-api-create-method:
Creating a database upgrade request
@@ -40,8 +46,8 @@ This action creates a database request with the following information:
* the database dump name (required but purely informative)
* optionally the server timezone (for Odoo source version < 6.1)
create method
-------------
The ``create`` method
---------------------
.. py:function:: https://upgrade.odoo.com/database/v1/create
@@ -56,11 +62,10 @@ create method
:return: request result
:rtype: json dictionary
The *create* method returns a json dictionary containing the following keys:
failures
''''''''
``failures``
''''''''''''
The list of errors.
@@ -107,8 +112,8 @@ See a sample output aside.
}
request
'''''''
``request``
'''''''''''
If the *create* method is successful, the value associated to the *request* key
will be a dictionary containing various information about the created request:
@@ -198,8 +203,8 @@ Uploading your database dump
This action upload your database dump.
upload method
-------------
The ``upload`` method
---------------------
.. py:function:: https://upgrade.odoo.com/database/v1/upload
@@ -269,8 +274,8 @@ Asking to process your request
This action ask the Upgrade Platform to process your database dump.
process method
--------------
The ``process`` method
----------------------
.. py:function:: https://upgrade.odoo.com/database/v1/process
@@ -335,8 +340,8 @@ Obtaining your request status
This action ask the status of your database upgrade request.
status method
-------------
The ``status`` method
---------------------
.. py:function:: https://upgrade.odoo.com/database/v1/status
@@ -392,7 +397,6 @@ database upgrade request.
URL_PARAMS="key=${KEY}&request=${REQUEST_ID}"
curl -sS "${PROCESS_URL}?${URL_PARAMS}"
Sample output
-------------
+9
View File
@@ -383,6 +383,15 @@ def one(method):
names = recs.method(args)
names = model.method(cr, uid, ids, args, context=context)
.. deprecated:: 9.0
:func:`~.one` often makes the code less clear and behaves in ways
developers and readers may not expect.
It is strongly recommended to use :func:`~.multi` and either
iterate on the ``self`` recordset or ensure that the recordset
is a single record with :meth:`~openerp.models.Model.ensure_one`.
"""
split = get_context_split(method)
downgrade = get_downgrade(method)
+7 -6
View File
@@ -3934,8 +3934,8 @@ class BaseModel(object):
# for recomputing new-style fields
recs.modified(upd_todo)
unknown_fields = updend[:]
for table in self._inherits:
unknown_fields = set(updend)
for table, inherit_field in self._inherits.iteritems():
col = self._inherits[table]
nids = []
for sub_ids in cr.split_for_in_conditions(ids):
@@ -3944,10 +3944,11 @@ class BaseModel(object):
nids.extend([x[0] for x in cr.fetchall()])
v = {}
for val in updend:
if self._inherit_fields[val][0] == table:
v[val] = vals[val]
unknown_fields.remove(val)
for fname in updend:
field = self._fields[fname]
if field.inherited and field.related[0] == inherit_field:
v[fname] = vals[fname]
unknown_fields.discard(fname)
if v:
self.pool[table].write(cr, user, nids, v, context)
+2 -13
View File
@@ -56,19 +56,8 @@ from openerp import SUPERUSER_ID, registry
@contextmanager
def _get_cursor():
# yield a valid cursor from any environment or create a new one if none found
from openerp.api import Environment
from openerp.http import request
try:
request.env # force request's env to be computed
except RuntimeError:
pass # ignore if not in a request
for env in Environment.envs:
if not env.cr.closed:
yield env.cr
break
else:
with registry().cursor() as cr:
yield cr
with registry().cursor() as cr:
yield cr
EMPTY_DICT = frozendict()
+3 -2
View File
@@ -1031,7 +1031,8 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True,
if isinstance(res_id, (int, long)) or \
(isinstance(res_id, basestring) and res_id.isdigit()):
dic['res_id'] = int(res_id)
dic['module'] = module_name
if module_name:
dic['module'] = module_name
else:
# res_id is an xml id
dic['res_id'] = None
@@ -1039,7 +1040,7 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True,
if '.' in res_id:
dic['module'], dic['imd_name'] = res_id.split('.', 1)
else:
dic['module'], dic['imd_name'] = False, res_id
dic['module'], dic['imd_name'] = module_name, res_id
irt_cursor.push(dic)
+2 -2
View File
@@ -11,8 +11,8 @@ decorator==3.4.0
docutils==0.12
feedparser==5.1.3
gdata==2.0.18
gevent==1.0.1
greenlet==0.4.5
gevent==1.0.2
greenlet==0.4.7
jcconv==0.2.3
lxml==3.4.1
mock==1.0.1