[MERGE] forward port branch 10.0 up to 3f6e573c67
This commit is contained in:
@@ -56,7 +56,7 @@ class account_journal(models.Model):
|
|||||||
last_bank_stmt = self.env['account.bank.statement'].search([('journal_id', 'in', self.ids),('date', '<=', last_month.strftime(DF))], order="date desc, id desc", limit=1)
|
last_bank_stmt = self.env['account.bank.statement'].search([('journal_id', 'in', self.ids),('date', '<=', last_month.strftime(DF))], order="date desc, id desc", limit=1)
|
||||||
start_balance = last_bank_stmt and last_bank_stmt[0].balance_end or 0
|
start_balance = last_bank_stmt and last_bank_stmt[0].balance_end or 0
|
||||||
|
|
||||||
locale = self._context.get('lang', 'en_US')
|
locale = self._context.get('lang') or 'en_US'
|
||||||
show_date = last_month
|
show_date = last_month
|
||||||
#get date in locale format
|
#get date in locale format
|
||||||
name = format_date(show_date, 'd LLLL Y', locale=locale)
|
name = format_date(show_date, 'd LLLL Y', locale=locale)
|
||||||
@@ -94,7 +94,7 @@ class account_journal(models.Model):
|
|||||||
data = []
|
data = []
|
||||||
today = datetime.strptime(fields.Date.context_today(self), DF)
|
today = datetime.strptime(fields.Date.context_today(self), DF)
|
||||||
data.append({'label': _('Past'), 'value':0.0, 'type': 'past'})
|
data.append({'label': _('Past'), 'value':0.0, 'type': 'past'})
|
||||||
day_of_week = int(format_datetime(today, 'e', locale=self._context.get('lang', 'en_US')))
|
day_of_week = int(format_datetime(today, 'e', locale=self._context.get('lang') or 'en_US'))
|
||||||
first_day_of_week = today + timedelta(days=-day_of_week+1)
|
first_day_of_week = today + timedelta(days=-day_of_week+1)
|
||||||
for i in range(-1,4):
|
for i in range(-1,4):
|
||||||
if i==0:
|
if i==0:
|
||||||
@@ -105,9 +105,9 @@ class account_journal(models.Model):
|
|||||||
start_week = first_day_of_week + timedelta(days=i*7)
|
start_week = first_day_of_week + timedelta(days=i*7)
|
||||||
end_week = start_week + timedelta(days=6)
|
end_week = start_week + timedelta(days=6)
|
||||||
if start_week.month == end_week.month:
|
if start_week.month == end_week.month:
|
||||||
label = str(start_week.day) + '-' +str(end_week.day)+ ' ' + format_date(end_week, 'MMM', locale=self._context.get('lang', 'en_US'))
|
label = str(start_week.day) + '-' +str(end_week.day)+ ' ' + format_date(end_week, 'MMM', locale=self._context.get('lang') or 'en_US')
|
||||||
else:
|
else:
|
||||||
label = format_date(start_week, 'd MMM', locale=self._context.get('lang', 'en_US'))+'-'+format_date(end_week, 'd MMM', locale=self._context.get('lang', 'en_US'))
|
label = format_date(start_week, 'd MMM', locale=self._context.get('lang') or 'en_US')+'-'+format_date(end_week, 'd MMM', locale=self._context.get('lang') or 'en_US')
|
||||||
data.append({'label':label,'value':0.0, 'type': 'past' if i<0 else 'future'})
|
data.append({'label':label,'value':0.0, 'type': 'past' if i<0 else 'future'})
|
||||||
|
|
||||||
# Build SQL query to find amount aggregated by week
|
# Build SQL query to find amount aggregated by week
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class ReportOverdue(models.AbstractModel):
|
|||||||
"FROM account_move_line l "
|
"FROM account_move_line l "
|
||||||
"JOIN account_account_type at ON (l.user_type_id = at.id) "
|
"JOIN account_account_type at ON (l.user_type_id = at.id) "
|
||||||
"JOIN account_move m ON (l.move_id = m.id) "
|
"JOIN account_move m ON (l.move_id = m.id) "
|
||||||
"WHERE l.partner_id IN %s AND at.type IN ('receivable', 'payable') GROUP BY l.date, l.name, l.ref, l.date_maturity, l.partner_id, at.type, l.blocked, l.amount_currency, l.currency_id, l.move_id, m.name", (((fields.date.today(), ) + (tuple(partner_ids),))))
|
"WHERE l.partner_id IN %s AND at.type IN ('receivable', 'payable') AND NOT l.reconciled GROUP BY l.date, l.name, l.ref, l.date_maturity, l.partner_id, at.type, l.blocked, l.amount_currency, l.currency_id, l.move_id, m.name", (((fields.date.today(), ) + (tuple(partner_ids),))))
|
||||||
for row in self.env.cr.dictfetchall():
|
for row in self.env.cr.dictfetchall():
|
||||||
res[row.pop('partner_id')].append(row)
|
res[row.pop('partner_id')].append(row)
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -453,6 +453,8 @@ var abstractReconciliationLine = Widget.extend({
|
|||||||
|
|
||||||
start: function() {
|
start: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
// fail silently if reconciliation widget is removed (eg. mode is changed)
|
||||||
|
var parent = this.getParent();
|
||||||
return self._super().then(function() {
|
return self._super().then(function() {
|
||||||
|
|
||||||
// no animation while loading
|
// no animation while loading
|
||||||
@@ -468,8 +470,8 @@ var abstractReconciliationLine = Widget.extend({
|
|||||||
return $.when(self.render()).then(function(){
|
return $.when(self.render()).then(function(){
|
||||||
self.is_consistent = true;
|
self.is_consistent = true;
|
||||||
// Make an entrance
|
// Make an entrance
|
||||||
self.animation_speed = self.getParent().animation_speed;
|
self.animation_speed = parent.animation_speed;
|
||||||
self.aestetic_animation_speed = self.getParent().aestetic_animation_speed;
|
self.aestetic_animation_speed = parent.aestetic_animation_speed;
|
||||||
if (self.context.animate_entrance) {
|
if (self.context.animate_entrance) {
|
||||||
return self.$el.stop(true, true).fadeIn({ duration: self.aestetic_animation_speed, queue: false }).css('display', 'none').slideDown(self.aestetic_animation_speed);
|
return self.$el.stop(true, true).fadeIn({ duration: self.aestetic_animation_speed, queue: false }).css('display', 'none').slideDown(self.aestetic_animation_speed);
|
||||||
}
|
}
|
||||||
@@ -2268,13 +2270,19 @@ var manualReconciliation = abstractReconciliation.extend({
|
|||||||
animate_entrance = defaultIfUndef(animate_entrance, true);
|
animate_entrance = defaultIfUndef(animate_entrance, true);
|
||||||
var self = this;
|
var self = this;
|
||||||
var displayed_collections = self.getDisplayedCollections();
|
var displayed_collections = self.getDisplayedCollections();
|
||||||
|
var plural = { 'customer': 'customers', 'supplier': 'suppliers', 'account': 'others' };
|
||||||
|
|
||||||
self.updateProgressbar();
|
self.updateProgressbar();
|
||||||
|
|
||||||
|
// number of reconciliation items already displayed
|
||||||
|
var num_child_displayed = self.getChildren().length;
|
||||||
|
|
||||||
// Remove children that should not be displayed
|
// Remove children that should not be displayed
|
||||||
if (self.mode !== 'all') {
|
if (self.mode !== 'all') {
|
||||||
_.each(self.getChildren(), function(child) {
|
_.each(self.getChildren(), function(child) {
|
||||||
if (child.data.reconciliation_type !== self.mode) {
|
var type = plural[child.data.reconciliation_type];
|
||||||
|
if (type !== self.mode) {
|
||||||
|
num_child_displayed--;
|
||||||
child.$el.slideUp(self.aestetic_animation_speed, function(){ child.destroy() });
|
child.$el.slideUp(self.aestetic_animation_speed, function(){ child.destroy() });
|
||||||
child.data.displayed = false;
|
child.data.displayed = false;
|
||||||
}
|
}
|
||||||
@@ -2287,7 +2295,7 @@ var manualReconciliation = abstractReconciliation.extend({
|
|||||||
var items_to_display = _.foldl(displayed_collections, function(prev, current){ return prev.concat(current.items) }, []);
|
var items_to_display = _.foldl(displayed_collections, function(prev, current){ return prev.concat(current.items) }, []);
|
||||||
// Filter out those which are already displayed
|
// Filter out those which are already displayed
|
||||||
items_to_display = _.filter(items_to_display, function(item) { return item.displayed === false; })
|
items_to_display = _.filter(items_to_display, function(item) { return item.displayed === false; })
|
||||||
.slice(0, self.num_reconciliations_fetched_in_batch - self.getChildren().length);
|
.slice(0, self.num_reconciliations_fetched_in_batch - num_child_displayed);
|
||||||
_.each(items_to_display, function(item){
|
_.each(items_to_display, function(item){
|
||||||
children_promises.push(self.displayReconciliation(item, animate_entrance));
|
children_promises.push(self.displayReconciliation(item, animate_entrance));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1211,11 +1211,11 @@ class Meeting(models.Model):
|
|||||||
|
|
||||||
elif interval == 'month':
|
elif interval == 'month':
|
||||||
# Localized month name and year
|
# Localized month name and year
|
||||||
result = babel.dates.format_date(date=date, format='MMMM y', locale=self._context.get('lang', 'en_US'))
|
result = babel.dates.format_date(date=date, format='MMMM y', locale=self._context.get('lang') or 'en_US')
|
||||||
|
|
||||||
elif interval == 'dayname':
|
elif interval == 'dayname':
|
||||||
# Localized day name
|
# Localized day name
|
||||||
result = babel.dates.format_date(date=date, format='EEEE', locale=self._context.get('lang', 'en_US'))
|
result = babel.dates.format_date(date=date, format='EEEE', locale=self._context.get('lang') or 'en_US')
|
||||||
|
|
||||||
elif interval == 'time':
|
elif interval == 'time':
|
||||||
# Localized time
|
# Localized time
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class Team(models.Model):
|
|||||||
@api.multi
|
@api.multi
|
||||||
def write(self, vals):
|
def write(self, vals):
|
||||||
result = super(Team, self).write(vals)
|
result = super(Team, self).write(vals)
|
||||||
if vals.get('use_leads') or vals.get('alias_defaults'):
|
if 'use_leads' in vals or 'alias_defaults' in vals:
|
||||||
for team in self:
|
for team in self:
|
||||||
team.alias_id.write(team.get_alias_values())
|
team.alias_id.write(team.get_alias_values())
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -489,13 +489,19 @@ class MergePartnerAutomatic(models.TransientModel):
|
|||||||
|
|
||||||
counter = 0
|
counter = 0
|
||||||
for min_id, aggr_ids in self._cr.fetchall():
|
for min_id, aggr_ids in self._cr.fetchall():
|
||||||
# exclude partner according to options
|
# To ensure that the used partners are accessible by the user
|
||||||
if model_mapping and self._partner_use_in(aggr_ids, model_mapping):
|
partners = self.env['res.partner'].search([('id', 'in', aggr_ids)])
|
||||||
|
if len(partners) < 2:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# exclude partner according to options
|
||||||
|
if model_mapping and self._partner_use_in(partners.ids, model_mapping):
|
||||||
|
continue
|
||||||
|
|
||||||
self.env['base.partner.merge.line'].create({
|
self.env['base.partner.merge.line'].create({
|
||||||
'wizard_id': self.id,
|
'wizard_id': self.id,
|
||||||
'min_id': min_id,
|
'min_id': min_id,
|
||||||
'aggr_ids': aggr_ids,
|
'aggr_ids': partners.ids,
|
||||||
})
|
})
|
||||||
counter += 1
|
counter += 1
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class EventEvent(models.Model):
|
|||||||
'interval_unit': 'days',
|
'interval_unit': 'days',
|
||||||
'interval_type': 'before_event',
|
'interval_type': 'before_event',
|
||||||
'template_id': self.env.ref('event.event_reminder')
|
'template_id': self.env.ref('event.event_reminder')
|
||||||
})] if self.user_has_groups('event.group_email_scheduling') else []
|
})]
|
||||||
|
|
||||||
# Seats and computation
|
# Seats and computation
|
||||||
seats_max = fields.Integer(
|
seats_max = fields.Integer(
|
||||||
|
|||||||
@@ -54,6 +54,20 @@
|
|||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- equiment : views -->
|
<!-- equiment : views -->
|
||||||
|
<record id="maintenance_equipment_view_search_inherit_hr" model='ir.ui.view'>
|
||||||
|
<field name="name">maintenance.equipment.view.search.inherit.hr</field>
|
||||||
|
<field name="model">maintenance.equipment</field>
|
||||||
|
<field name="inherit_id" ref="maintenance.hr_equipment_view_search"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<filter name="assigned" position="attributes">
|
||||||
|
<attribute name="domain">['|', ('employee_id', '!=', False), ('department_id', '!=', False)]</attribute>
|
||||||
|
</filter>
|
||||||
|
<filter name="available" position="attributes">
|
||||||
|
<attribute name="domain">[('employee_id', '=', False), ('department_id', '=', False)]</attribute>
|
||||||
|
</filter>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record id="maintenance_equipment_view_form_inherit_hr" model="ir.ui.view">
|
<record id="maintenance_equipment_view_form_inherit_hr" model="ir.ui.view">
|
||||||
<field name="name">maintenance.equipment.view.form.inherit.hr</field>
|
<field name="name">maintenance.equipment.view.form.inherit.hr</field>
|
||||||
<field name="model">maintenance.equipment</field>
|
<field name="model">maintenance.equipment</field>
|
||||||
@@ -99,4 +113,4 @@
|
|||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ class MarketingCampaignWorkitem(models.Model):
|
|||||||
campaign_id = fields.Many2one('marketing.campaign', related='activity_id.campaign_id', string='Campaign', readonly=True, store=True)
|
campaign_id = fields.Many2one('marketing.campaign', related='activity_id.campaign_id', string='Campaign', readonly=True, store=True)
|
||||||
object_id = fields.Many2one('ir.model', related='activity_id.campaign_id.object_id', string='Resource', index=1, readonly=True, store=True)
|
object_id = fields.Many2one('ir.model', related='activity_id.campaign_id.object_id', string='Resource', index=1, readonly=True, store=True)
|
||||||
res_id = fields.Integer('Resource ID', index=1, readonly=True)
|
res_id = fields.Integer('Resource ID', index=1, readonly=True)
|
||||||
res_name = fields.Char(compute='_compute_res_name', string='Resource Name', search='search_res_name')
|
res_name = fields.Char(compute='_compute_res_name', string='Resource Name', search='_search_res_name')
|
||||||
date = fields.Datetime('Execution Date', readonly=True, default=False,
|
date = fields.Datetime('Execution Date', readonly=True, default=False,
|
||||||
help='If date is not set, this workitem has to be run manually')
|
help='If date is not set, this workitem has to be run manually')
|
||||||
partner_id = fields.Many2one('res.partner', 'Partner', index=1, readonly=True)
|
partner_id = fields.Many2one('res.partner', 'Partner', index=1, readonly=True)
|
||||||
|
|||||||
@@ -386,3 +386,12 @@ class StockMove(models.Model):
|
|||||||
'split_from': self.id, # Needed in order to keep sale connection, but will be removed by unlink
|
'split_from': self.id, # Needed in order to keep sale connection, but will be removed by unlink
|
||||||
})
|
})
|
||||||
return self.env['stock.move']
|
return self.env['stock.move']
|
||||||
|
|
||||||
|
class PushedFlow(models.Model):
|
||||||
|
_inherit = "stock.location.path"
|
||||||
|
|
||||||
|
def _prepare_move_copy_values(self, move_to_copy, new_date):
|
||||||
|
new_move_vals = super(PushedFlow, self)._prepare_move_copy_values(move_to_copy, new_date)
|
||||||
|
new_move_vals['production_id'] = False
|
||||||
|
|
||||||
|
return new_move_vals
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class PaypalController(http.Controller):
|
|||||||
""" Extract the return URL from the data coming from paypal. """
|
""" Extract the return URL from the data coming from paypal. """
|
||||||
return_url = post.pop('return_url', '')
|
return_url = post.pop('return_url', '')
|
||||||
if not return_url:
|
if not return_url:
|
||||||
custom = json.loads(post.pop('custom', False) or post.pop('cm', False) or '{}')
|
custom = json.loads(urllib.unquote_plus(post.pop('custom', False) or post.pop('cm', False) or '{}'))
|
||||||
return_url = custom.get('return_url', '/')
|
return_url = custom.get('return_url', '/')
|
||||||
return return_url
|
return return_url
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class ProductAttributevalue(models.Model):
|
|||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _variant_name(self, variable_attributes):
|
def _variant_name(self, variable_attributes):
|
||||||
return ", ".join([v.name for v in self if v.attribute_id in variable_attributes])
|
return ", ".join([v.name for v in self.sorted(key=lambda r: r.name) if v.attribute_id in variable_attributes])
|
||||||
|
|
||||||
|
|
||||||
class ProductAttributePrice(models.Model):
|
class ProductAttributePrice(models.Model):
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class Pricelist(models.Model):
|
|||||||
if name and operator == '=' and not args:
|
if name and operator == '=' and not args:
|
||||||
# search on the name of the pricelist and its currency, opposite of name_get(),
|
# search on the name of the pricelist and its currency, opposite of name_get(),
|
||||||
# Used by the magic context filter in the product search view.
|
# Used by the magic context filter in the product search view.
|
||||||
query_args = {'name': name, 'limit': limit, 'lang': self._context.get('lang', 'en_US')}
|
query_args = {'name': name, 'limit': limit, 'lang': self._context.get('lang') or 'en_US'}
|
||||||
query = """SELECT p.id
|
query = """SELECT p.id
|
||||||
FROM ((
|
FROM ((
|
||||||
SELECT pr.id, pr.name
|
SELECT pr.id, pr.name
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ class SaleOrder(models.Model):
|
|||||||
vals = {}
|
vals = {}
|
||||||
if order.name not in invoices[group_key].origin.split(', '):
|
if order.name not in invoices[group_key].origin.split(', '):
|
||||||
vals['origin'] = invoices[group_key].origin + ', ' + order.name
|
vals['origin'] = invoices[group_key].origin + ', ' + order.name
|
||||||
if order.client_order_ref and order.client_order_ref not in invoices[group_key].name.split(', '):
|
if order.client_order_ref and order.client_order_ref not in invoices[group_key].name.split(', ') and order.client_order_ref != invoices[group_key].name:
|
||||||
vals['name'] = invoices[group_key].name + ', ' + order.client_order_ref
|
vals['name'] = invoices[group_key].name + ', ' + order.client_order_ref
|
||||||
invoices[group_key].write(vals)
|
invoices[group_key].write(vals)
|
||||||
if line.qty_to_invoice > 0:
|
if line.qty_to_invoice > 0:
|
||||||
@@ -818,7 +818,6 @@ class SaleOrderLine(models.Model):
|
|||||||
'uom_id': self.product_uom.id,
|
'uom_id': self.product_uom.id,
|
||||||
'product_id': self.product_id.id or False,
|
'product_id': self.product_id.id or False,
|
||||||
'layout_category_id': self.layout_category_id and self.layout_category_id.id or False,
|
'layout_category_id': self.layout_category_id and self.layout_category_id.id or False,
|
||||||
'product_id': self.product_id.id or False,
|
|
||||||
'invoice_line_tax_ids': [(6, 0, self.tax_id.ids)],
|
'invoice_line_tax_ids': [(6, 0, self.tax_id.ids)],
|
||||||
'account_analytic_id': self.order_id.project_id.id,
|
'account_analytic_id': self.order_id.project_id.id,
|
||||||
'analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)],
|
'analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)],
|
||||||
|
|||||||
@@ -213,9 +213,15 @@ class PushedFlow(models.Model):
|
|||||||
# TDE FIXME: should probably be done in the move model IMO
|
# TDE FIXME: should probably be done in the move model IMO
|
||||||
move._push_apply()
|
move._push_apply()
|
||||||
else:
|
else:
|
||||||
new_move = move.copy({
|
new_move_vals = self._prepare_move_copy_values(move, new_date)
|
||||||
'origin': move.origin or move.picking_id.name or "/",
|
new_move = move.copy(new_move_vals)
|
||||||
'location_id': move.location_dest_id.id,
|
move.write({'move_dest_id': new_move.id})
|
||||||
|
new_move.action_confirm()
|
||||||
|
|
||||||
|
def _prepare_move_copy_values(self, move_to_copy, new_date):
|
||||||
|
new_move_vals = {
|
||||||
|
'origin': move_to_copy.origin or move_to_copy.picking_id.name or "/",
|
||||||
|
'location_id': move_to_copy.location_dest_id.id,
|
||||||
'location_dest_id': self.location_dest_id.id,
|
'location_dest_id': self.location_dest_id.id,
|
||||||
'date': new_date,
|
'date': new_date,
|
||||||
'date_expected': new_date,
|
'date_expected': new_date,
|
||||||
@@ -226,6 +232,6 @@ class PushedFlow(models.Model):
|
|||||||
'push_rule_id': self.id,
|
'push_rule_id': self.id,
|
||||||
'warehouse_id': self.warehouse_id.id,
|
'warehouse_id': self.warehouse_id.id,
|
||||||
'procurement_id': False,
|
'procurement_id': False,
|
||||||
})
|
}
|
||||||
move.write({'move_dest_id': new_move.id})
|
|
||||||
new_move.action_confirm()
|
return new_move_vals
|
||||||
|
|||||||
@@ -520,7 +520,7 @@ class Quant(models.Model):
|
|||||||
if any(quant not in self for quant in package.get_content()):
|
if any(quant not in self for quant in package.get_content()):
|
||||||
all_in = False
|
all_in = False
|
||||||
if all_in:
|
if all_in:
|
||||||
destinations = [product_to_location[product] for product in package.get_content().mapped('product_id')]
|
destinations = set([product_to_location[product] for product in package.get_content().mapped('product_id')])
|
||||||
if len(destinations) > 1:
|
if len(destinations) > 1:
|
||||||
all_in = False
|
all_in = False
|
||||||
if all_in:
|
if all_in:
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ env.filters["json"] = json.dumps
|
|||||||
# 1 week cache for asset bundles as advised by Google Page Speed
|
# 1 week cache for asset bundles as advised by Google Page Speed
|
||||||
BUNDLE_MAXAGE = 60 * 60 * 24 * 7
|
BUNDLE_MAXAGE = 60 * 60 * 24 * 7
|
||||||
|
|
||||||
|
DBNAME_PATTERN = '^[a-zA-Z0-9][a-zA-Z0-9_.-]+$'
|
||||||
|
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
# Odoo Web helpers
|
# Odoo Web helpers
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
@@ -630,6 +632,7 @@ class Database(http.Controller):
|
|||||||
d['list_db'] = odoo.tools.config['list_db']
|
d['list_db'] = odoo.tools.config['list_db']
|
||||||
d['langs'] = odoo.service.db.exp_list_lang()
|
d['langs'] = odoo.service.db.exp_list_lang()
|
||||||
d['countries'] = odoo.service.db.exp_list_countries()
|
d['countries'] = odoo.service.db.exp_list_countries()
|
||||||
|
d['pattern'] = DBNAME_PATTERN
|
||||||
# databases list
|
# databases list
|
||||||
d['databases'] = []
|
d['databases'] = []
|
||||||
try:
|
try:
|
||||||
@@ -651,8 +654,8 @@ class Database(http.Controller):
|
|||||||
@http.route('/web/database/create', type='http', auth="none", methods=['POST'], csrf=False)
|
@http.route('/web/database/create', type='http', auth="none", methods=['POST'], csrf=False)
|
||||||
def create(self, master_pwd, name, lang, password, **post):
|
def create(self, master_pwd, name, lang, password, **post):
|
||||||
try:
|
try:
|
||||||
if not re.match('^[a-zA-Z][a-zA-Z0-9_]+$', name):
|
if not re.match(DBNAME_PATTERN, name):
|
||||||
raise Exception(_('Invalid database name. Only alphanumerical characters and underscore are allowed.'))
|
raise Exception(_('Invalid database name. Only alphanumerical characters, underscore, hyphen and dot are allowed.'))
|
||||||
# country code could be = "False" which is actually True in python
|
# country code could be = "False" which is actually True in python
|
||||||
country_code = post.get('country_code') or False
|
country_code = post.get('country_code') or False
|
||||||
dispatch_rpc('db', 'create_database', [master_pwd, name, bool(post.get('demo')), lang, password, post['login'], country_code])
|
dispatch_rpc('db', 'create_database', [master_pwd, name, bool(post.get('demo')), lang, password, post['login'], country_code])
|
||||||
@@ -665,8 +668,8 @@ class Database(http.Controller):
|
|||||||
@http.route('/web/database/duplicate', type='http', auth="none", methods=['POST'], csrf=False)
|
@http.route('/web/database/duplicate', type='http', auth="none", methods=['POST'], csrf=False)
|
||||||
def duplicate(self, master_pwd, name, new_name):
|
def duplicate(self, master_pwd, name, new_name):
|
||||||
try:
|
try:
|
||||||
if not re.match('^[a-zA-Z][a-zA-Z0-9_]+$', new_name):
|
if not re.match(DBNAME_PATTERN, new_name):
|
||||||
raise Exception(_('Invalid database name. Only alphanumerical characters and underscore are allowed.'))
|
raise Exception(_('Invalid database name. Only alphanumerical characters, underscore, hyphen and dot are allowed.'))
|
||||||
dispatch_rpc('db', 'duplicate_database', [master_pwd, name, new_name])
|
dispatch_rpc('db', 'duplicate_database', [master_pwd, name, new_name])
|
||||||
return http.local_redirect('/web/database/manager')
|
return http.local_redirect('/web/database/manager')
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
|||||||
@@ -129,12 +129,15 @@ var QWeb2 = {
|
|||||||
}
|
}
|
||||||
return r.join('');
|
return r.join('');
|
||||||
} else {
|
} else {
|
||||||
|
// avoid XMLSerializer with text node for IE
|
||||||
|
if (node.nodeType == 3) {
|
||||||
|
return node.data;
|
||||||
|
}
|
||||||
if (typeof XMLSerializer !== 'undefined') {
|
if (typeof XMLSerializer !== 'undefined') {
|
||||||
return (new XMLSerializer()).serializeToString(node);
|
return (new XMLSerializer()).serializeToString(node);
|
||||||
} else {
|
} else {
|
||||||
switch(node.nodeType) {
|
switch(node.nodeType) {
|
||||||
case 1: return node.outerHTML;
|
case 1: return node.outerHTML;
|
||||||
case 3: return node.data;
|
|
||||||
case 4: return '<![CDATA[' + node.data + ']]>';
|
case 4: return '<![CDATA[' + node.data + ']]>';
|
||||||
case 8: return '<!-- ' + node.data + '-->';
|
case 8: return '<!-- ' + node.data + '-->';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<label for="name" class="control-label">Database Name</label>
|
<label for="name" class="control-label">Database Name</label>
|
||||||
<input id="name" type="text" name="name" class="form-control" required="required" autocomplete="off" pattern="^[a-zA-Z][a-zA-Z0-9_]+$" title="Only alphanumerical characters and underscore are allowed"/>
|
<input id="name" type="text" name="name" class="form-control" required="required" autocomplete="off" pattern="{{ pattern }}" title="Only alphanumerical characters, underscore, hyphen and dot are allowed"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -207,7 +207,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="name" class="control-label">Database Name</label>
|
<label for="name" class="control-label">Database Name</label>
|
||||||
<input id="name" type="text" name="name" class="form-control" required="required" pattern="^[a-zA-Z][a-zA-Z0-9_]+$" title="Only alphanumerical characters and underscore are allowed"/>
|
<input id="name" type="text" name="name" class="form-control" required="required" pattern="{{ pattern }}" title="Only alphanumerical characters, underscore, hyphen and dot are allowed"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="copy">This database might have been moved or copied.</label>
|
<label for="copy">This database might have been moved or copied.</label>
|
||||||
@@ -280,7 +280,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="new_name" class="control-label">New Name</label>
|
<label for="new_name" class="control-label">New Name</label>
|
||||||
<input id="new_name" type="text" name="new_name" class="form-control" required="required" pattern="^[a-zA-Z][a-zA-Z0-9_]+$" title="Only alphanumerical characters and underscore are allowed"/>
|
<input id="new_name" type="text" name="new_name" class="form-control" required="required" pattern="{{ pattern }}" title="Only alphanumerical characters, underscore, hyphen and dot are allowed"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ class WebsiteBlog(http.Controller):
|
|||||||
|
|
||||||
:return redirect to the new blog created
|
:return redirect to the new blog created
|
||||||
"""
|
"""
|
||||||
new_blog_post = request.env['blog.post'].with_context(mail_create_nosubscribe=True).copy(int(blog_post_id), {})
|
new_blog_post = request.env['blog.post'].with_context(mail_create_nosubscribe=True).browse(int(blog_post_id)).copy()
|
||||||
return werkzeug.utils.redirect("/blog/%s/post/%s?enable_editor=1" % (slug(new_blog_post.blog_id), slug(new_blog_post)))
|
return werkzeug.utils.redirect("/blog/%s/post/%s?enable_editor=1" % (slug(new_blog_post.blog_id), slug(new_blog_post)))
|
||||||
|
|
||||||
@http.route('/blog/post_get_discussion/', type='json', auth="public", website=True)
|
@http.route('/blog/post_get_discussion/', type='json', auth="public", website=True)
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
Italy, 2017-04-18
|
||||||
|
|
||||||
|
Level Prime Srl agrees to the terms of the Odoo Corporate Contributor License
|
||||||
|
Agreement v1.0.
|
||||||
|
|
||||||
|
I declare that I am authorized and able to make this agreement and sign this
|
||||||
|
declaration.
|
||||||
|
|
||||||
|
Signed,
|
||||||
|
|
||||||
|
Roberto Fichera roberto.fichera@levelprime.com https://github.com/robyf70
|
||||||
|
|
||||||
|
|
||||||
|
List of contributors:
|
||||||
|
|
||||||
|
Roberto Fichera roberto.fichera@levelprime.com https://github.com/robyf70
|
||||||
|
Roberto Fichera robyf@tekno-soft.it https://github.com/robyf70
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="group_partner_manager" model="res.groups">
|
<record id="group_partner_manager" model="res.groups">
|
||||||
<field name="category_id" ref="module_category_extra"/>
|
<field name="category_id" ref="module_category_usability"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ class Start(Command):
|
|||||||
|
|
||||||
args, unknown = parser.parse_known_args(args=cmdargs)
|
args, unknown = parser.parse_known_args(args=cmdargs)
|
||||||
|
|
||||||
|
# When in a virtualenv, by default use it's path rather than the cwd
|
||||||
|
if args.path == '.' and os.environ.get('VIRTUAL_ENV'):
|
||||||
|
args.path = os.environ.get('VIRTUAL_ENV')
|
||||||
project_path = os.path.abspath(os.path.expanduser(os.path.expandvars(args.path)))
|
project_path = os.path.abspath(os.path.expanduser(os.path.expandvars(args.path)))
|
||||||
module_root = get_module_root(project_path)
|
module_root = get_module_root(project_path)
|
||||||
db_name = None
|
db_name = None
|
||||||
|
|||||||
+1
-1
@@ -1855,7 +1855,7 @@ class BaseModel(object):
|
|||||||
if ftype == 'many2one':
|
if ftype == 'many2one':
|
||||||
value = value[0]
|
value = value[0]
|
||||||
elif ftype in ('date', 'datetime'):
|
elif ftype in ('date', 'datetime'):
|
||||||
locale = self._context.get('lang', 'en_US')
|
locale = self._context.get('lang') or 'en_US'
|
||||||
fmt = DEFAULT_SERVER_DATETIME_FORMAT if ftype == 'datetime' else DEFAULT_SERVER_DATE_FORMAT
|
fmt = DEFAULT_SERVER_DATETIME_FORMAT if ftype == 'datetime' else DEFAULT_SERVER_DATE_FORMAT
|
||||||
tzinfo = None
|
tzinfo = None
|
||||||
range_start = value
|
range_start = value
|
||||||
|
|||||||
Reference in New Issue
Block a user