[MERGE] Forward-port of saas-5 up to 20cc18d
This commit is contained in:
commit
e11eddf753
|
@ -114,7 +114,7 @@ class account_invoice(models.Model):
|
||||||
def _compute_residual(self):
|
def _compute_residual(self):
|
||||||
nb_inv_in_partial_rec = max_invoice_id = 0
|
nb_inv_in_partial_rec = max_invoice_id = 0
|
||||||
self.residual = 0.0
|
self.residual = 0.0
|
||||||
for line in self.move_id.line_id:
|
for line in self.sudo().move_id.line_id:
|
||||||
if line.account_id.type in ('receivable', 'payable'):
|
if line.account_id.type in ('receivable', 'payable'):
|
||||||
if line.currency_id == self.currency_id:
|
if line.currency_id == self.currency_id:
|
||||||
self.residual += line.amount_residual_currency
|
self.residual += line.amount_residual_currency
|
||||||
|
@ -1397,8 +1397,7 @@ class account_invoice_line(models.Model):
|
||||||
res = []
|
res = []
|
||||||
for line in inv.invoice_line:
|
for line in inv.invoice_line:
|
||||||
mres = self.move_line_get_item(line)
|
mres = self.move_line_get_item(line)
|
||||||
if not mres:
|
mres['invl_id'] = line.id
|
||||||
continue
|
|
||||||
res.append(mres)
|
res.append(mres)
|
||||||
tax_code_found = False
|
tax_code_found = False
|
||||||
taxes = line.invoice_line_tax_id.compute_all(
|
taxes = line.invoice_line_tax_id.compute_all(
|
||||||
|
|
|
@ -124,7 +124,7 @@ class account_invoice_line(osv.osv):
|
||||||
account_prec = decimal_precision.precision_get(cr, uid, 'Account')
|
account_prec = decimal_precision.precision_get(cr, uid, 'Account')
|
||||||
# calculate and write down the possible price difference between invoice price and product price
|
# calculate and write down the possible price difference between invoice price and product price
|
||||||
for line in res:
|
for line in res:
|
||||||
if a == line['account_id'] and i_line.product_id.id == line['product_id']:
|
if line.get('invl_id', 0) == i_line.id and a == line['account_id']:
|
||||||
uom = i_line.product_id.uos_id or i_line.product_id.uom_id
|
uom = i_line.product_id.uos_id or i_line.product_id.uom_id
|
||||||
valuation_price_unit = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id)
|
valuation_price_unit = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id)
|
||||||
if inv.currency_id.id != company_currency:
|
if inv.currency_id.id != company_currency:
|
||||||
|
|
|
@ -54,7 +54,7 @@ class meeting_invitation(http.Controller):
|
||||||
# Function used, in RPC to check every 5 minutes, if notification to do for an event or not
|
# Function used, in RPC to check every 5 minutes, if notification to do for an event or not
|
||||||
@http.route('/calendar/notify', type='json', auth="none")
|
@http.route('/calendar/notify', type='json', auth="none")
|
||||||
def notify(self):
|
def notify(self):
|
||||||
registry = openerp.modules.registry.RegistryManager.get(request.session.db)
|
registry = request.registry
|
||||||
uid = request.session.uid
|
uid = request.session.uid
|
||||||
context = request.session.context
|
context = request.session.context
|
||||||
with registry.cursor() as cr:
|
with registry.cursor() as cr:
|
||||||
|
@ -63,7 +63,7 @@ class meeting_invitation(http.Controller):
|
||||||
|
|
||||||
@http.route('/calendar/notify_ack', type='json', auth="none")
|
@http.route('/calendar/notify_ack', type='json', auth="none")
|
||||||
def notify_ack(self, type=''):
|
def notify_ack(self, type=''):
|
||||||
registry = openerp.modules.registry.RegistryManager.get(request.session.db)
|
registry = request.registry
|
||||||
uid = request.session.uid
|
uid = request.session.uid
|
||||||
context = request.session.context
|
context = request.session.context
|
||||||
with registry.cursor() as cr:
|
with registry.cursor() as cr:
|
||||||
|
|
|
@ -237,8 +237,8 @@ class test_message_compose(TestMail):
|
||||||
email_template.send_mail(cr, uid, email_template_id, self.group_pigs_id, force_send=True, context=context)
|
email_template.send_mail(cr, uid, email_template_id, self.group_pigs_id, force_send=True, context=context)
|
||||||
sent_emails = self._build_email_kwargs_list
|
sent_emails = self._build_email_kwargs_list
|
||||||
email_to_lst = [
|
email_to_lst = [
|
||||||
['b@b.b', 'c@c.c'], ['"Administrator" <admin@yourcompany.example.com>'],
|
['b@b.b', 'c@c.c'], ['Administrator <admin@yourcompany.example.com>'],
|
||||||
['"Raoul Grosbedon" <raoul@raoul.fr>'], ['"Bert Tartignole" <bert@bert.fr>']]
|
['Raoul Grosbedon <raoul@raoul.fr>'], ['Bert Tartignole <bert@bert.fr>']]
|
||||||
self.assertEqual(len(sent_emails), 4, 'email_template: send_mail: 3 valid email recipients + email_to -> should send 4 emails')
|
self.assertEqual(len(sent_emails), 4, 'email_template: send_mail: 3 valid email recipients + email_to -> should send 4 emails')
|
||||||
for email in sent_emails:
|
for email in sent_emails:
|
||||||
self.assertIn(email['email_to'], email_to_lst, 'email_template: send_mail: wrong email_recipients')
|
self.assertIn(email['email_to'], email_to_lst, 'email_template: send_mail: wrong email_recipients')
|
||||||
|
|
|
@ -468,7 +468,7 @@
|
||||||
<field name="expiration_date" />
|
<field name="expiration_date" />
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="insurer_id" />
|
<field name="insurer_id" context="{'default_supplier': True}"/>
|
||||||
<field name="purchaser_id" />
|
<field name="purchaser_id" />
|
||||||
<field name="ins_ref" />
|
<field name="ins_ref" />
|
||||||
</group>
|
</group>
|
||||||
|
@ -676,7 +676,7 @@
|
||||||
<field name="date" />
|
<field name="date" />
|
||||||
<field name="purchaser_id" />
|
<field name="purchaser_id" />
|
||||||
<field name="inv_ref" />
|
<field name="inv_ref" />
|
||||||
<field name="vendor_id" />
|
<field name="vendor_id" context="{'default_supplier': True}"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<group string="Notes">
|
<group string="Notes">
|
||||||
|
@ -778,7 +778,7 @@
|
||||||
<group string="Additional Details">
|
<group string="Additional Details">
|
||||||
<field name="date" />
|
<field name="date" />
|
||||||
<field name="purchaser_id" />
|
<field name="purchaser_id" />
|
||||||
<field name="vendor_id" />
|
<field name="vendor_id" context="{'default_supplier': True}"/>
|
||||||
<field name="inv_ref" />
|
<field name="inv_ref" />
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
|
|
@ -194,7 +194,7 @@ class gamification_goal(osv.Model):
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'definition_id': fields.many2one('gamification.goal.definition', string='Goal Definition', required=True, ondelete="cascade"),
|
'definition_id': fields.many2one('gamification.goal.definition', string='Goal Definition', required=True, ondelete="cascade"),
|
||||||
'user_id': fields.many2one('res.users', string='User', required=True),
|
'user_id': fields.many2one('res.users', string='User', required=True, auto_join=True),
|
||||||
'line_id': fields.many2one('gamification.challenge.line', string='Challenge Line', ondelete="cascade"),
|
'line_id': fields.many2one('gamification.challenge.line', string='Challenge Line', ondelete="cascade"),
|
||||||
'challenge_id': fields.related('line_id', 'challenge_id',
|
'challenge_id': fields.related('line_id', 'challenge_id',
|
||||||
string="Challenge",
|
string="Challenge",
|
||||||
|
@ -239,7 +239,7 @@ class gamification_goal(osv.Model):
|
||||||
'state': 'draft',
|
'state': 'draft',
|
||||||
'start_date': fields.date.today,
|
'start_date': fields.date.today,
|
||||||
}
|
}
|
||||||
_order = 'create_date desc, end_date desc, definition_id, id'
|
_order = 'start_date desc, end_date desc, definition_id, id'
|
||||||
|
|
||||||
def _check_remind_delay(self, cr, uid, goal, context=None):
|
def _check_remind_delay(self, cr, uid, goal, context=None):
|
||||||
"""Verify if a goal has not been updated for some time and send a
|
"""Verify if a goal has not been updated for some time and send a
|
||||||
|
|
|
@ -40,7 +40,7 @@ class account_coda_import(osv.osv_memory):
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'coda_fname': lambda *a: '',
|
'coda_fname': 'coda.txt',
|
||||||
}
|
}
|
||||||
|
|
||||||
def coda_parsing(self, cr, uid, ids, context=None, batch=False, codafile=None, codafilename=None):
|
def coda_parsing(self, cr, uid, ids, context=None, batch=False, codafile=None, codafilename=None):
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import logging
|
import logging
|
||||||
|
from email.utils import formataddr
|
||||||
from urlparse import urljoin
|
from urlparse import urljoin
|
||||||
|
|
||||||
from openerp import api, tools
|
from openerp import api, tools
|
||||||
|
@ -184,11 +185,10 @@ class mail_mail(osv.Model):
|
||||||
|
|
||||||
def send_get_mail_to(self, cr, uid, mail, partner=None, context=None):
|
def send_get_mail_to(self, cr, uid, mail, partner=None, context=None):
|
||||||
"""Forge the email_to with the following heuristic:
|
"""Forge the email_to with the following heuristic:
|
||||||
- if 'partner' and mail is a notification on a document: followers (Followers of 'Doc' <email>)
|
- if 'partner', recipient specific (Partner Name <email>)
|
||||||
- elif 'partner', no notificatoin or no doc: recipient specific (Partner Name <email>)
|
|
||||||
- else fallback on mail.email_to splitting """
|
- else fallback on mail.email_to splitting """
|
||||||
if partner:
|
if partner:
|
||||||
email_to = ['"%s" <%s>' % (partner.name, partner.email)]
|
email_to = [formataddr((partner.name, partner.email))]
|
||||||
else:
|
else:
|
||||||
email_to = tools.email_split(mail.email_to)
|
email_to = tools.email_split(mail.email_to)
|
||||||
return email_to
|
return email_to
|
||||||
|
|
|
@ -24,6 +24,7 @@ import logging
|
||||||
from openerp import tools
|
from openerp import tools
|
||||||
|
|
||||||
from email.header import decode_header
|
from email.header import decode_header
|
||||||
|
from email.utils import formataddr
|
||||||
from openerp import SUPERUSER_ID, api
|
from openerp import SUPERUSER_ID, api
|
||||||
from openerp.osv import osv, orm, fields
|
from openerp.osv import osv, orm, fields
|
||||||
from openerp.tools import html_email_clean
|
from openerp.tools import html_email_clean
|
||||||
|
@ -170,9 +171,9 @@ class mail_message(osv.Model):
|
||||||
def _get_default_from(self, cr, uid, context=None):
|
def _get_default_from(self, cr, uid, context=None):
|
||||||
this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
||||||
if this.alias_name and this.alias_domain:
|
if this.alias_name and this.alias_domain:
|
||||||
return '%s <%s@%s>' % (this.name, this.alias_name, this.alias_domain)
|
return formataddr((this.name, '%s@%s' % (this.alias_name, this.alias_domain)))
|
||||||
elif this.email:
|
elif this.email:
|
||||||
return '%s <%s>' % (this.name, this.email)
|
return formataddr((this.name, this.email))
|
||||||
raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias."))
|
raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias."))
|
||||||
|
|
||||||
def _get_default_author(self, cr, uid, context=None):
|
def _get_default_author(self, cr, uid, context=None):
|
||||||
|
|
|
@ -37,6 +37,7 @@ import time
|
||||||
import xmlrpclib
|
import xmlrpclib
|
||||||
import re
|
import re
|
||||||
from email.message import Message
|
from email.message import Message
|
||||||
|
from email.utils import formataddr
|
||||||
from urllib import urlencode
|
from urllib import urlencode
|
||||||
|
|
||||||
from openerp import api, tools
|
from openerp import api, tools
|
||||||
|
@ -722,12 +723,10 @@ class mail_thread(osv.AbstractModel):
|
||||||
aliases.update(dict((res_id, '%s@%s' % (catchall_alias, alias_domain)) for res_id in left_ids))
|
aliases.update(dict((res_id, '%s@%s' % (catchall_alias, alias_domain)) for res_id in left_ids))
|
||||||
# compute name of reply-to
|
# compute name of reply-to
|
||||||
company_name = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).company_id.name
|
company_name = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).company_id.name
|
||||||
res.update(
|
for res_id in aliases.keys():
|
||||||
dict((res_id, '"%(company_name)s%(document_name)s" <%(email)s>' %
|
email_name = '%s%s' % (company_name, doc_names.get(res_id) and (' ' + doc_names[res_id]) or '')
|
||||||
{'company_name': company_name,
|
email_addr = aliases[res_id]
|
||||||
'document_name': doc_names.get(res_id) and ' ' + re.sub(r'[^\w+.]+', '-', doc_names[res_id]) or '',
|
res[res_id] = formataddr((email_name, email_addr))
|
||||||
'email': aliases[res_id]
|
|
||||||
} or False) for res_id in aliases.keys()))
|
|
||||||
left_ids = set(ids).difference(set(aliases.keys()))
|
left_ids = set(ids).difference(set(aliases.keys()))
|
||||||
if left_ids and default:
|
if left_ids and default:
|
||||||
res.update(dict((res_id, default) for res_id in left_ids))
|
res.update(dict((res_id, default) for res_id in left_ids))
|
||||||
|
|
|
@ -448,7 +448,7 @@ class test_mail(TestMail):
|
||||||
'message_post: mail.mail notifications should have been auto-deleted!')
|
'message_post: mail.mail notifications should have been auto-deleted!')
|
||||||
|
|
||||||
# Test: notifications emails: to a and b, c is email only, r is author
|
# Test: notifications emails: to a and b, c is email only, r is author
|
||||||
test_emailto = ['"Administrator" <a@a>', '"Bert Tartopoils" <b@b>']
|
test_emailto = ['Administrator <a@a>', 'Bert Tartopoils <b@b>']
|
||||||
# test_emailto = ['"Followers of -Pigs-" <a@a>', '"Followers of -Pigs-" <b@b>']
|
# test_emailto = ['"Followers of -Pigs-" <a@a>', '"Followers of -Pigs-" <b@b>']
|
||||||
self.assertEqual(len(sent_emails), 2,
|
self.assertEqual(len(sent_emails), 2,
|
||||||
'message_post: notification emails wrong number of send emails')
|
'message_post: notification emails wrong number of send emails')
|
||||||
|
@ -461,7 +461,7 @@ class test_mail(TestMail):
|
||||||
'message_post: notification email sent to more than one email address instead of a precise partner')
|
'message_post: notification email sent to more than one email address instead of a precise partner')
|
||||||
self.assertIn(sent_email['email_to'][0], test_emailto,
|
self.assertIn(sent_email['email_to'][0], test_emailto,
|
||||||
'message_post: notification email email_to incorrect')
|
'message_post: notification email email_to incorrect')
|
||||||
self.assertEqual(sent_email['reply_to'], '"YourCompany -Pigs-" <group+pigs@schlouby.fr>',
|
self.assertEqual(sent_email['reply_to'], u'"YourCompany \\"Pigs\\" !ù $%-" <group+pigs@schlouby.fr>',
|
||||||
'message_post: notification email reply_to incorrect')
|
'message_post: notification email reply_to incorrect')
|
||||||
self.assertEqual(_subject, sent_email['subject'],
|
self.assertEqual(_subject, sent_email['subject'],
|
||||||
'message_post: notification email subject incorrect')
|
'message_post: notification email subject incorrect')
|
||||||
|
@ -518,7 +518,7 @@ class test_mail(TestMail):
|
||||||
self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg2_id)]), 'mail.mail notifications should have been auto-deleted!')
|
self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg2_id)]), 'mail.mail notifications should have been auto-deleted!')
|
||||||
|
|
||||||
# Test: emails send by server (to a, b, c, d)
|
# Test: emails send by server (to a, b, c, d)
|
||||||
test_emailto = [u'"Administrator" <a@a>', u'"Bert Tartopoils" <b@b>', u'"Carine Poilvache" <c@c>', u'"D\xe9d\xe9 Grosbedon" <d@d>']
|
test_emailto = [u'Administrator <a@a>', u'Bert Tartopoils <b@b>', u'Carine Poilvache <c@c>', u'D\xe9d\xe9 Grosbedon <d@d>']
|
||||||
# test_emailto = [u'"Followers of Pigs" <a@a>', u'"Followers of Pigs" <b@b>', u'"Followers of Pigs" <c@c>', u'"Followers of Pigs" <d@d>']
|
# test_emailto = [u'"Followers of Pigs" <a@a>', u'"Followers of Pigs" <b@b>', u'"Followers of Pigs" <c@c>', u'"Followers of Pigs" <d@d>']
|
||||||
# self.assertEqual(len(sent_emails), 3, 'sent_email number of sent emails incorrect')
|
# self.assertEqual(len(sent_emails), 3, 'sent_email number of sent emails incorrect')
|
||||||
for sent_email in sent_emails:
|
for sent_email in sent_emails:
|
||||||
|
|
|
@ -81,7 +81,7 @@ class TestMailMessage(TestMail):
|
||||||
alias_domain = 'schlouby.fr'
|
alias_domain = 'schlouby.fr'
|
||||||
raoul_from = 'Raoul Grosbedon <raoul@raoul.fr>'
|
raoul_from = 'Raoul Grosbedon <raoul@raoul.fr>'
|
||||||
raoul_from_alias = 'Raoul Grosbedon <raoul@schlouby.fr>'
|
raoul_from_alias = 'Raoul Grosbedon <raoul@schlouby.fr>'
|
||||||
raoul_reply_alias = '"YourCompany Pigs" <group+pigs@schlouby.fr>'
|
raoul_reply_alias = 'YourCompany Pigs <group+pigs@schlouby.fr>'
|
||||||
|
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
# Case1: without alias_domain
|
# Case1: without alias_domain
|
||||||
|
@ -151,7 +151,7 @@ class TestMailMessage(TestMail):
|
||||||
msg_id = self.mail_message.create(cr, user_raoul_id, {})
|
msg_id = self.mail_message.create(cr, user_raoul_id, {})
|
||||||
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
|
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
|
||||||
# Test: generated reply_to
|
# Test: generated reply_to
|
||||||
self.assertEqual(msg.reply_to, '"YourCompany" <gateway@schlouby.fr>',
|
self.assertEqual(msg.reply_to, 'YourCompany <gateway@schlouby.fr>',
|
||||||
'mail_mail: reply_to should equal the catchall email alias')
|
'mail_mail: reply_to should equal the catchall email alias')
|
||||||
|
|
||||||
# Do: create a mail_mail
|
# Do: create a mail_mail
|
||||||
|
|
|
@ -42,8 +42,8 @@ class AcquirerPaypal(osv.Model):
|
||||||
_columns = {
|
_columns = {
|
||||||
'paypal_email_account': fields.char('Paypal Email ID', required_if_provider='paypal'),
|
'paypal_email_account': fields.char('Paypal Email ID', required_if_provider='paypal'),
|
||||||
'paypal_seller_account': fields.char(
|
'paypal_seller_account': fields.char(
|
||||||
'Paypal Seller ID',
|
'Paypal Merchant ID',
|
||||||
help='The Seller ID is used to ensure communications coming from Paypal are valid and secured.'),
|
help='The Merchant ID is used to ensure communications coming from Paypal are valid and secured.'),
|
||||||
'paypal_use_ipn': fields.boolean('Use IPN', help='Paypal Instant Payment Notification'),
|
'paypal_use_ipn': fields.boolean('Use IPN', help='Paypal Instant Payment Notification'),
|
||||||
# Server 2 server
|
# Server 2 server
|
||||||
'paypal_api_enabled': fields.boolean('Use Rest API'),
|
'paypal_api_enabled': fields.boolean('Use Rest API'),
|
||||||
|
|
|
@ -902,7 +902,7 @@
|
||||||
<br />
|
<br />
|
||||||
<t t-esc="widget.pos.company.name"/><br />
|
<t t-esc="widget.pos.company.name"/><br />
|
||||||
Phone: <t t-esc="widget.pos.company.phone || ''"/><br />
|
Phone: <t t-esc="widget.pos.company.phone || ''"/><br />
|
||||||
User: <t t-esc="widget.pos.cashier.name"/><br />
|
User: <t t-esc="widget.pos.cashier ? widget.pos.cashier.name : widget.pos.user.name"/><br />
|
||||||
Shop: <t t-esc="widget.pos.shop.name"/><br />
|
Shop: <t t-esc="widget.pos.shop.name"/><br />
|
||||||
<br />
|
<br />
|
||||||
<t t-if="widget.pos.config.receipt_header">
|
<t t-if="widget.pos.config.receipt_header">
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
from openerp import SUPERUSER_ID
|
from openerp import SUPERUSER_ID
|
||||||
from openerp.osv import osv, fields
|
from openerp.osv import osv, fields
|
||||||
|
from openerp import SUPERUSER_ID
|
||||||
|
|
||||||
|
|
||||||
class sale_order(osv.Model):
|
class sale_order(osv.Model):
|
||||||
|
@ -36,7 +37,7 @@ class sale_order(osv.Model):
|
||||||
def _portal_payment_block(self, cr, uid, ids, fieldname, arg, context=None):
|
def _portal_payment_block(self, cr, uid, ids, fieldname, arg, context=None):
|
||||||
result = dict.fromkeys(ids, False)
|
result = dict.fromkeys(ids, False)
|
||||||
payment_acquirer = self.pool['payment.acquirer']
|
payment_acquirer = self.pool['payment.acquirer']
|
||||||
for this in self.browse(cr, uid, ids, context=context):
|
for this in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||||
if this.state not in ('draft', 'cancel') and not this.invoiced:
|
if this.state not in ('draft', 'cancel') and not this.invoiced:
|
||||||
result[this.id] = payment_acquirer.render_payment_block(
|
result[this.id] = payment_acquirer.render_payment_block(
|
||||||
cr, uid, this.name, this.amount_total, this.pricelist_id.currency_id.id,
|
cr, uid, this.name, this.amount_total, this.pricelist_id.currency_id.id,
|
||||||
|
|
|
@ -5,16 +5,8 @@ access_account_invoice,account.invoice,account.model_account_invoice,base.group_
|
||||||
access_account_invoice_tax,account.invoice.tax,account.model_account_invoice_tax,base.group_portal,1,0,0,0
|
access_account_invoice_tax,account.invoice.tax,account.model_account_invoice_tax,base.group_portal,1,0,0,0
|
||||||
access_account_invoice_line,account.invoice.line,account.model_account_invoice_line,base.group_portal,1,0,0,0
|
access_account_invoice_line,account.invoice.line,account.model_account_invoice_line,base.group_portal,1,0,0,0
|
||||||
access_account_journal,account.journal,account.model_account_journal,base.group_portal,1,0,0,0
|
access_account_journal,account.journal,account.model_account_journal,base.group_portal,1,0,0,0
|
||||||
access_account_voucher,account.voucher,account_voucher.model_account_voucher,base.group_portal,1,0,0,0
|
access_sale_shop,sale.shop,sale.model_sale_shop,base.group_portal,1,0,0,0
|
||||||
access_account_voucher_line,account.voucher.line,account_voucher.model_account_voucher_line,base.group_portal,1,0,0,0
|
|
||||||
access_account_move,account.move,account.model_account_move,base.group_portal,1,0,0,0
|
|
||||||
access_account_move_line,account.move.line,account.model_account_move_line,base.group_portal,1,0,0,0
|
|
||||||
access_account_move_reconcile,account.move.reconcile,account.model_account_move_reconcile,base.group_portal,1,0,0,0
|
|
||||||
access_account_fiscalyear,account.sequence.fiscalyear,account.model_account_sequence_fiscalyear,base.group_portal,1,0,0,0
|
|
||||||
access_product_list,product.pricelist,product.model_product_pricelist,base.group_portal,1,0,0,0
|
access_product_list,product.pricelist,product.model_product_pricelist,base.group_portal,1,0,0,0
|
||||||
access_res_partner,res.partner,base.model_res_partner,base.group_portal,1,0,0,0
|
access_res_partner,res.partner,base.model_res_partner,base.group_portal,1,0,0,0
|
||||||
access_account_tax,account.tax,account.model_account_tax,base.group_portal,1,0,0,0
|
access_account_tax,account.tax,account.model_account_tax,base.group_portal,1,0,0,0
|
||||||
access_account_fiscalyear,account.fiscalyear,account.model_account_fiscalyear,base.group_portal,1,0,0,0
|
|
||||||
access_res_partner_category,res.partner.category,base.model_res_partner_category,base.group_portal,1,0,0,0
|
access_res_partner_category,res.partner.category,base.model_res_partner_category,base.group_portal,1,0,0,0
|
||||||
access_account_period,account.period,account.model_account_period,base.group_portal,1,0,0,0
|
|
||||||
access_account_account,account.account,account.model_account_account,base.group_portal,1,0,0,0
|
|
||||||
|
|
|
|
@ -18,7 +18,7 @@ their documents through the portal.</field>
|
||||||
<record id="portal_sale_order_user_rule" model="ir.rule">
|
<record id="portal_sale_order_user_rule" model="ir.rule">
|
||||||
<field name="name">Portal Personal Quotations/Sales Orders</field>
|
<field name="name">Portal Personal Quotations/Sales Orders</field>
|
||||||
<field name="model_id" ref="sale.model_sale_order"/>
|
<field name="model_id" ref="sale.model_sale_order"/>
|
||||||
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
|
<field name="domain_force">[('message_follower_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||||
<field eval="1" name="perm_unlink"/>
|
<field eval="1" name="perm_unlink"/>
|
||||||
<field eval="1" name="perm_write"/>
|
<field eval="1" name="perm_write"/>
|
||||||
|
@ -26,17 +26,32 @@ their documents through the portal.</field>
|
||||||
<field eval="0" name="perm_create"/>
|
<field eval="0" name="perm_create"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="portal_sale_order_line_rule" model="ir.rule">
|
||||||
|
<field name="name">Portal Sales Orders Line</field>
|
||||||
|
<field name="model_id" ref="sale.model_sale_order_line"/>
|
||||||
|
<field name="domain_force">[('order_id.message_follower_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||||
|
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<record id="portal_account_invoice_user_rule" model="ir.rule">
|
<record id="portal_account_invoice_user_rule" model="ir.rule">
|
||||||
<field name="name">Portal Personal Account Invoices</field>
|
<field name="name">Portal Personal Account Invoices</field>
|
||||||
<field name="model_id" ref="account.model_account_invoice"/>
|
<field name="model_id" ref="account.model_account_invoice"/>
|
||||||
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
|
<field name="domain_force">[('message_follower_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||||
|
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="portal_account_invoice_line_rule" model="ir.rule">
|
||||||
|
<field name="name">Portal Invoice Lines</field>
|
||||||
|
<field name="model_id" ref="account.model_account_invoice_line"/>
|
||||||
|
<field name="domain_force">[('invoice_id.message_follower_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="portal_personal_contact" model="ir.rule">
|
<record id="portal_personal_contact" model="ir.rule">
|
||||||
<field name="name">Portal Personal Contacts</field>
|
<field name="name">Portal Personal Contacts</field>
|
||||||
<field name="model_id" ref="base.model_res_partner"/>
|
<field name="model_id" ref="base.model_res_partner"/>
|
||||||
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
|
<field name="domain_force">[('message_follower_ids','in',[user.commercial_partner_id.id])]</field>
|
||||||
<field eval="0" name="perm_read"/>
|
<field eval="0" name="perm_read"/>
|
||||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
from psycopg2 import OperationalError
|
||||||
|
|
||||||
from openerp import SUPERUSER_ID
|
from openerp import SUPERUSER_ID
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields, osv
|
||||||
|
@ -193,31 +194,49 @@ class procurement_order(osv.osv):
|
||||||
def reset_to_confirmed(self, cr, uid, ids, context=None):
|
def reset_to_confirmed(self, cr, uid, ids, context=None):
|
||||||
return self.write(cr, uid, ids, {'state': 'confirmed'}, context=context)
|
return self.write(cr, uid, ids, {'state': 'confirmed'}, context=context)
|
||||||
|
|
||||||
def run(self, cr, uid, ids, context=None):
|
def run(self, cr, uid, ids, autocommit=False, context=None):
|
||||||
for procurement_id in ids:
|
for procurement_id in ids:
|
||||||
#we intentionnaly do the browse under the for loop to avoid caching all ids which would be resource greedy
|
#we intentionnaly do the browse under the for loop to avoid caching all ids which would be resource greedy
|
||||||
#and useless as we'll make a refresh later that will invalidate all the cache (and thus the next iteration
|
#and useless as we'll make a refresh later that will invalidate all the cache (and thus the next iteration
|
||||||
#will fetch all the ids again)
|
#will fetch all the ids again)
|
||||||
procurement = self.browse(cr, uid, procurement_id, context=context)
|
procurement = self.browse(cr, uid, procurement_id, context=context)
|
||||||
if procurement.state not in ("running", "done"):
|
if procurement.state not in ("running", "done"):
|
||||||
if self._assign(cr, uid, procurement, context=context):
|
try:
|
||||||
procurement.refresh()
|
if self._assign(cr, uid, procurement, context=context):
|
||||||
res = self._run(cr, uid, procurement, context=context or {})
|
procurement.refresh()
|
||||||
if res:
|
res = self._run(cr, uid, procurement, context=context or {})
|
||||||
self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context)
|
if res:
|
||||||
|
self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context)
|
||||||
|
else:
|
||||||
|
self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context)
|
||||||
else:
|
else:
|
||||||
|
self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context)
|
||||||
self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context)
|
self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context)
|
||||||
else:
|
if autocommit:
|
||||||
self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context)
|
cr.commit()
|
||||||
self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context)
|
except OperationalError:
|
||||||
|
if autocommit:
|
||||||
|
cr.rollback()
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raise
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def check(self, cr, uid, ids, context=None):
|
def check(self, cr, uid, ids, autocommit=False, context=None):
|
||||||
done_ids = []
|
done_ids = []
|
||||||
for procurement in self.browse(cr, uid, ids, context=context):
|
for procurement in self.browse(cr, uid, ids, context=context):
|
||||||
result = self._check(cr, uid, procurement, context=context)
|
try:
|
||||||
if result:
|
result = self._check(cr, uid, procurement, context=context)
|
||||||
done_ids.append(procurement.id)
|
if result:
|
||||||
|
done_ids.append(procurement.id)
|
||||||
|
if autocommit:
|
||||||
|
cr.commit()
|
||||||
|
except OperationalError:
|
||||||
|
if autocommit:
|
||||||
|
cr.rollback()
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raise
|
||||||
if done_ids:
|
if done_ids:
|
||||||
self.write(cr, uid, done_ids, {'state': 'done'}, context=context)
|
self.write(cr, uid, done_ids, {'state': 'done'}, context=context)
|
||||||
return done_ids
|
return done_ids
|
||||||
|
@ -291,11 +310,14 @@ class procurement_order(osv.osv):
|
||||||
dom = [('state', '=', 'confirmed')]
|
dom = [('state', '=', 'confirmed')]
|
||||||
if company_id:
|
if company_id:
|
||||||
dom += [('company_id', '=', company_id)]
|
dom += [('company_id', '=', company_id)]
|
||||||
|
prev_ids = []
|
||||||
while True:
|
while True:
|
||||||
ids = self.search(cr, SUPERUSER_ID, dom, context=context)
|
ids = self.search(cr, SUPERUSER_ID, dom, context=context)
|
||||||
if not ids:
|
if not ids or prev_ids == ids:
|
||||||
break
|
break
|
||||||
self.run(cr, SUPERUSER_ID, ids, context=context)
|
else:
|
||||||
|
prev_ids = ids
|
||||||
|
self.run(cr, SUPERUSER_ID, ids, autocommit=use_new_cursor, context=context)
|
||||||
if use_new_cursor:
|
if use_new_cursor:
|
||||||
cr.commit()
|
cr.commit()
|
||||||
|
|
||||||
|
@ -304,12 +326,14 @@ class procurement_order(osv.osv):
|
||||||
dom = [('state', '=', 'running')]
|
dom = [('state', '=', 'running')]
|
||||||
if company_id:
|
if company_id:
|
||||||
dom += [('company_id', '=', company_id)]
|
dom += [('company_id', '=', company_id)]
|
||||||
|
prev_ids = []
|
||||||
while True:
|
while True:
|
||||||
ids = self.search(cr, SUPERUSER_ID, dom, offset=offset, context=context)
|
ids = self.search(cr, SUPERUSER_ID, dom, offset=offset, context=context)
|
||||||
if not ids:
|
if not ids or prev_ids == ids:
|
||||||
break
|
break
|
||||||
done = self.check(cr, SUPERUSER_ID, ids, context=context)
|
else:
|
||||||
offset += len(ids) - len(done)
|
prev_ids = ids
|
||||||
|
self.check(cr, SUPERUSER_ID, ids, autocommit=use_new_cursor, context=context)
|
||||||
if use_new_cursor:
|
if use_new_cursor:
|
||||||
cr.commit()
|
cr.commit()
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FO
|
||||||
from openerp import SUPERUSER_ID
|
from openerp import SUPERUSER_ID
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from psycopg2 import OperationalError
|
||||||
import openerp
|
import openerp
|
||||||
|
|
||||||
class procurement_group(osv.osv):
|
class procurement_group(osv.osv):
|
||||||
|
@ -204,8 +205,8 @@ class procurement_order(osv.osv):
|
||||||
return True
|
return True
|
||||||
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
|
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
|
||||||
|
|
||||||
def run(self, cr, uid, ids, context=None):
|
def run(self, cr, uid, ids, autocommit=False, context=None):
|
||||||
res = super(procurement_order, self).run(cr, uid, ids, context=context)
|
res = super(procurement_order, self).run(cr, uid, ids, autocommit=autocommit, context=context)
|
||||||
#after all the procurements are run, check if some created a draft stock move that needs to be confirmed
|
#after all the procurements are run, check if some created a draft stock move that needs to be confirmed
|
||||||
#(we do that in batch because it fasts the picking assignation and the picking state computation)
|
#(we do that in batch because it fasts the picking assignation and the picking state computation)
|
||||||
move_to_confirm_ids = []
|
move_to_confirm_ids = []
|
||||||
|
@ -335,36 +336,51 @@ class procurement_order(osv.osv):
|
||||||
orderpoint_obj = self.pool.get('stock.warehouse.orderpoint')
|
orderpoint_obj = self.pool.get('stock.warehouse.orderpoint')
|
||||||
|
|
||||||
procurement_obj = self.pool.get('procurement.order')
|
procurement_obj = self.pool.get('procurement.order')
|
||||||
offset = 0
|
|
||||||
ids = [1]
|
|
||||||
dom = company_id and [('company_id', '=', company_id)] or []
|
dom = company_id and [('company_id', '=', company_id)] or []
|
||||||
while ids:
|
orderpoint_ids = orderpoint_obj.search(cr, uid, dom)
|
||||||
ids = orderpoint_obj.search(cr, uid, dom, offset=offset, limit=100)
|
prev_ids = []
|
||||||
|
while orderpoint_ids:
|
||||||
|
ids = orderpoint_ids[:100]
|
||||||
|
del orderpoint_ids[:100]
|
||||||
for op in orderpoint_obj.browse(cr, uid, ids, context=context):
|
for op in orderpoint_obj.browse(cr, uid, ids, context=context):
|
||||||
prods = self._product_virtual_get(cr, uid, op)
|
try:
|
||||||
if prods is None:
|
prods = self._product_virtual_get(cr, uid, op)
|
||||||
continue
|
if prods is None:
|
||||||
if prods < op.product_min_qty:
|
|
||||||
qty = max(op.product_min_qty, op.product_max_qty) - prods
|
|
||||||
|
|
||||||
reste = qty % op.qty_multiple
|
|
||||||
if reste > 0:
|
|
||||||
qty += op.qty_multiple - reste
|
|
||||||
|
|
||||||
if qty <= 0:
|
|
||||||
continue
|
continue
|
||||||
|
if prods < op.product_min_qty:
|
||||||
|
qty = max(op.product_min_qty, op.product_max_qty) - prods
|
||||||
|
|
||||||
qty -= orderpoint_obj.subtract_procurements(cr, uid, op, context=context)
|
reste = qty % op.qty_multiple
|
||||||
|
if reste > 0:
|
||||||
|
qty += op.qty_multiple - reste
|
||||||
|
|
||||||
if qty > 0:
|
if qty <= 0:
|
||||||
proc_id = procurement_obj.create(cr, uid,
|
continue
|
||||||
self._prepare_orderpoint_procurement(cr, uid, op, qty, context=context),
|
|
||||||
context=context)
|
qty -= orderpoint_obj.subtract_procurements(cr, uid, op, context=context)
|
||||||
self.check(cr, uid, [proc_id])
|
|
||||||
self.run(cr, uid, [proc_id])
|
if qty > 0:
|
||||||
offset += len(ids)
|
proc_id = procurement_obj.create(cr, uid,
|
||||||
|
self._prepare_orderpoint_procurement(cr, uid, op, qty, context=context),
|
||||||
|
context=context)
|
||||||
|
self.check(cr, uid, [proc_id])
|
||||||
|
self.run(cr, uid, [proc_id])
|
||||||
|
if use_new_cursor:
|
||||||
|
cr.commit()
|
||||||
|
except OperationalError:
|
||||||
|
if use_new_cursor:
|
||||||
|
orderpoint_ids.append(op.id)
|
||||||
|
cr.rollback()
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
raise
|
||||||
if use_new_cursor:
|
if use_new_cursor:
|
||||||
cr.commit()
|
cr.commit()
|
||||||
|
if prev_ids == ids:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
prev_ids = ids
|
||||||
|
|
||||||
if use_new_cursor:
|
if use_new_cursor:
|
||||||
cr.commit()
|
cr.commit()
|
||||||
cr.close()
|
cr.close()
|
||||||
|
|
|
@ -1418,16 +1418,18 @@ class ExportFormat(object):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def base(self, data, token):
|
def base(self, data, token):
|
||||||
|
params = simplejson.loads(data)
|
||||||
model, fields, ids, domain, import_compat = \
|
model, fields, ids, domain, import_compat = \
|
||||||
operator.itemgetter('model', 'fields', 'ids', 'domain',
|
operator.itemgetter('model', 'fields', 'ids', 'domain',
|
||||||
'import_compat')(
|
'import_compat')(
|
||||||
simplejson.loads(data))
|
params)
|
||||||
|
|
||||||
Model = request.session.model(model)
|
Model = request.session.model(model)
|
||||||
ids = ids or Model.search(domain, 0, False, False, request.context)
|
context = dict(req.context or {}, **params.get('context', {}))
|
||||||
|
ids = ids or Model.search(domain, 0, False, False, context)
|
||||||
|
|
||||||
field_names = map(operator.itemgetter('name'), fields)
|
field_names = map(operator.itemgetter('name'), fields)
|
||||||
import_data = Model.export_data(ids, field_names, self.raw_data, context=request.context).get('datas',[])
|
import_data = Model.export_data(ids, field_names, self.raw_data, context=context).get('datas',[])
|
||||||
|
|
||||||
if import_compat:
|
if import_compat:
|
||||||
columns_headers = field_names
|
columns_headers = field_names
|
||||||
|
|
|
@ -406,6 +406,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
||||||
fields: exported_fields,
|
fields: exported_fields,
|
||||||
ids: this.ids_to_export,
|
ids: this.ids_to_export,
|
||||||
domain: this.domain,
|
domain: this.domain,
|
||||||
|
context: this.dataset.context,
|
||||||
import_compat: !!this.$el.find("#import_compat").val(),
|
import_compat: !!this.$el.find("#import_compat").val(),
|
||||||
})},
|
})},
|
||||||
complete: instance.web.unblockUI,
|
complete: instance.web.unblockUI,
|
||||||
|
|
|
@ -487,7 +487,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
||||||
*/
|
*/
|
||||||
setup_global_completion: function () {
|
setup_global_completion: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.autocomplete = new instance.web.search.AutoComplete(this, {
|
this.autocomplete = new instance.web.search.AutoComplete(this, {
|
||||||
source: this.proxy('complete_global_search'),
|
source: this.proxy('complete_global_search'),
|
||||||
select: this.proxy('select_completion'),
|
select: this.proxy('select_completion'),
|
||||||
|
|
|
@ -522,7 +522,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
||||||
self.dataset.index = 0;
|
self.dataset.index = 0;
|
||||||
}
|
}
|
||||||
} else if (self.dataset.index >= self.records.length) {
|
} else if (self.dataset.index >= self.records.length) {
|
||||||
self.dataset.index = 0;
|
self.dataset.index = self.records.length ? 0 : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.compute_aggregates();
|
self.compute_aggregates();
|
||||||
|
|
|
@ -423,14 +423,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
||||||
attrs.value = [attrs.value];
|
attrs.value = [attrs.value];
|
||||||
}
|
}
|
||||||
attrs.value = _.range(grouped_on.length).map(function (i) {
|
attrs.value = _.range(grouped_on.length).map(function (i) {
|
||||||
|
var grp = grouped_on[i],
|
||||||
|
field = self.fields[grp];
|
||||||
if (attrs.value[i] === false) {
|
if (attrs.value[i] === false) {
|
||||||
return _t('Undefined');
|
return _t('Undefined');
|
||||||
} else if (attrs.value[i] instanceof Array) {
|
} else if (attrs.value[i] instanceof Array) {
|
||||||
return attrs.value[i][1];
|
return attrs.value[i][1];
|
||||||
}else if (grouped_on && self.fields[grouped_on].type === 'selection'){
|
} else if (field && field.type === 'selection') {
|
||||||
var selection = self.fields[grouped_on].selection;
|
var selected = _.where(field.selection, {0: attrs.value[i]})[0];
|
||||||
var value_lookup = _.where(selection, {0:attrs.value[i]});
|
return selected ? selected[1] : attrs.value[i];
|
||||||
return value_lookup ? value_lookup[0][1] : _t('Undefined');
|
|
||||||
}
|
}
|
||||||
return attrs.value[i];
|
return attrs.value[i];
|
||||||
});
|
});
|
||||||
|
|
|
@ -310,6 +310,8 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
|
||||||
var kgroup = new instance.web_kanban.KanbanGroup(self, records, null, self.dataset);
|
var kgroup = new instance.web_kanban.KanbanGroup(self, records, null, self.dataset);
|
||||||
if (!_.isEmpty(self.dataset.ids) && (self.dataset.index === null || self.dataset.index >= self.dataset.ids.length)) {
|
if (!_.isEmpty(self.dataset.ids) && (self.dataset.index === null || self.dataset.index >= self.dataset.ids.length)) {
|
||||||
self.dataset.index = 0;
|
self.dataset.index = 0;
|
||||||
|
} else if (_.isEmpty(self.dataset.ids)){
|
||||||
|
self.dataset.index = null;
|
||||||
}
|
}
|
||||||
self.do_add_groups([kgroup]).done(function() {
|
self.do_add_groups([kgroup]).done(function() {
|
||||||
if (_.isEmpty(records)) {
|
if (_.isEmpty(records)) {
|
||||||
|
|
|
@ -131,8 +131,8 @@
|
||||||
<!-- modal end -->
|
<!-- modal end -->
|
||||||
<h3>World Map<button class="btn btn-link" data-toggle="modal" data-target=".partner_map_modal"><span class="fa fa-external-link" /></button></h3>
|
<h3>World Map<button class="btn btn-link" data-toggle="modal" data-target=".partner_map_modal"><span class="fa fa-external-link" /></button></h3>
|
||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
<iframe t-attf-src="/google_map/?width=260&height=240&partner_ids=#{ google_map_partner_ids }&partner_url=/partners/"
|
<iframe t-attf-src="/google_map?width=260&height=240&partner_ids=#{ google_map_partner_ids }&partner_url=/partners/"
|
||||||
style="width:260px; height:240px; border:0; padding:0; margin:0;"></iframe>
|
style="width:260px; height:240px; border:0; padding:0; margin:0;" scrolling="no"></iframe>
|
||||||
</ul>
|
</ul>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -59,8 +59,11 @@ class WebsiteCustomer(http.Controller):
|
||||||
partner_count = partner_obj.search_count(cr, openerp.SUPERUSER_ID, domain, context=request.context)
|
partner_count = partner_obj.search_count(cr, openerp.SUPERUSER_ID, domain, context=request.context)
|
||||||
|
|
||||||
# pager
|
# pager
|
||||||
|
url = '/customers/'
|
||||||
|
if country_id:
|
||||||
|
url += 'country/%s' % country_id
|
||||||
pager = request.website.pager(
|
pager = request.website.pager(
|
||||||
url="/customers", total=partner_count, page=page, step=self._references_per_page,
|
url=url, total=partner_count, page=page, step=self._references_per_page,
|
||||||
scope=7, url_args=post
|
scope=7, url_args=post
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -84,8 +84,8 @@
|
||||||
<!-- modal end -->
|
<!-- modal end -->
|
||||||
<h3>World Map<button class="btn btn-link" data-toggle="modal" data-target=".customer_map_modal"><span class="fa fa-external-link" /></button></h3>
|
<h3>World Map<button class="btn btn-link" data-toggle="modal" data-target=".customer_map_modal"><span class="fa fa-external-link" /></button></h3>
|
||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
<iframe t-attf-src="/google_map/?width=260&height=240&partner_ids=#{ google_map_partner_ids }&partner_url=/customers/"
|
<iframe t-attf-src="/google_map?width=260&height=240&partner_ids=#{ google_map_partner_ids }&partner_url=/customers/"
|
||||||
style="width:260px; height:240px; border:0; padding:0; margin:0;"></iframe>
|
style="width:260px; height:240px; border:0; padding:0; margin:0;" scrolling="no"></iframe>
|
||||||
</ul>
|
</ul>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -90,9 +90,12 @@ class website_event(http.Controller):
|
||||||
if searches["type"] != 'all':
|
if searches["type"] != 'all':
|
||||||
current_type = type_obj.browse(cr, uid, int(searches['type']), context=context)
|
current_type = type_obj.browse(cr, uid, int(searches['type']), context=context)
|
||||||
domain_search["type"] = [("type", "=", int(searches["type"]))]
|
domain_search["type"] = [("type", "=", int(searches["type"]))]
|
||||||
if searches["country"] != 'all':
|
|
||||||
|
if searches["country"] != 'all' and searches["country"] != 'online':
|
||||||
current_country = country_obj.browse(cr, uid, int(searches['country']), context=context)
|
current_country = country_obj.browse(cr, uid, int(searches['country']), context=context)
|
||||||
domain_search["country"] = [("country_id", "=", int(searches["country"]))]
|
domain_search["country"] = ['|', ("country_id", "=", int(searches["country"])), ("country_id", "=", False)]
|
||||||
|
elif searches["country"] == 'online':
|
||||||
|
domain_search["country"] = [("country_id", "=", False)]
|
||||||
|
|
||||||
def dom_without(without):
|
def dom_without(without):
|
||||||
domain = [('state', "in", ['draft','confirm','done'])]
|
domain = [('state', "in", ['draft','confirm','done'])]
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
<div itemscope="itemscope" itemtype="http://schema.org/Event" class="media-body">
|
<div itemscope="itemscope" itemtype="http://schema.org/Event" class="media-body">
|
||||||
<h4 class="media-heading">
|
<h4 class="media-heading">
|
||||||
<a itemprop="url" t-att-class="event.state == 'done' and 'text-success'" t-attf-href="/event/#{ slug(event) }/#{(not event.menu_id) and 'register' or ''}"><span itemprop="name" t-field="event.name"> </span></a>
|
<a itemprop="url" t-att-class="event.state == 'done' and 'text-success'" t-attf-href="/event/#{ slug(event) }/#{(not event.menu_id) and 'register' or ''}"><span itemprop="name" t-field="event.name"> </span></a>
|
||||||
|
<small t-if="not event.address_id" class="label label-info">Online</small>
|
||||||
<small t-if="not event.website_published" class="label label-danger">not published</small>
|
<small t-if="not event.website_published" class="label label-danger">not published</small>
|
||||||
</h4>
|
</h4>
|
||||||
<div>
|
<div>
|
||||||
|
@ -179,7 +180,13 @@
|
||||||
<ul class="nav nav-pills nav-stacked mt32">
|
<ul class="nav nav-pills nav-stacked mt32">
|
||||||
<t t-foreach="countries" t-as="country">
|
<t t-foreach="countries" t-as="country">
|
||||||
<li t-if="country['country_id']" t-att-class="searches.get('country') == str(country['country_id'] and country['country_id'][0]) and 'active' or ''">
|
<li t-if="country['country_id']" t-att-class="searches.get('country') == str(country['country_id'] and country['country_id'][0]) and 'active' or ''">
|
||||||
<a t-attf-href="/event?{{ keep_query('type', 'data', country=country['country_id'][0]) }}"><t t-esc="country['country_id'][1]"/>
|
<a t-attf-href="/event?{{ keep_query('type', 'date', country=country['country_id'][0]) }}"><t t-esc="country['country_id'][1]"/>
|
||||||
|
<span class="badge pull-right"><t t-esc="country['country_id_count']"/></span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li t-if="not country['country_id']" t-att-class="searches.get('country') == 'online' and 'active' or ''">
|
||||||
|
<a t-attf-href="/event?{{ keep_query('type', 'date', country='online') }}">
|
||||||
|
<span>Online Events</span>
|
||||||
<span class="badge pull-right"><t t-esc="country['country_id_count']"/></span>
|
<span class="badge pull-right"><t t-esc="country['country_id_count']"/></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -29,19 +29,18 @@
|
||||||
<h4>Choose your Delivery Method</h4>
|
<h4>Choose your Delivery Method</h4>
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li t-foreach="deliveries" t-as="delivery">
|
<li t-foreach="deliveries" t-as="delivery">
|
||||||
<label>
|
<t t-if="delivery.available">
|
||||||
<input t-att-value="delivery.id" type="radio" name="delivery_type"
|
<label>
|
||||||
t-att-checked="order.carrier_id and order.carrier_id.id == delivery.id and 'checked' or False"
|
<input t-att-value="delivery.id" type="radio" name="delivery_type"
|
||||||
t-att-disabled="delivery.available and '0' or '1'"/>
|
t-att-checked="order.carrier_id and order.carrier_id.id == delivery.id and 'checked' or False"/>
|
||||||
<span t-field="delivery.name"/>
|
<span t-field="delivery.name"/>
|
||||||
<t t-if="delivery.available">
|
|
||||||
<span class="badge" t-field="delivery.price"
|
<span class="badge" t-field="delivery.price"
|
||||||
t-field-options='{
|
t-field-options='{
|
||||||
"widget": "monetary",
|
"widget": "monetary",
|
||||||
"display_currency": "website.pricelist_id.currency_id"
|
"display_currency": "website.pricelist_id.currency_id"
|
||||||
}'/>
|
}'/>
|
||||||
</t>
|
</label>
|
||||||
</label>
|
</t>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -160,8 +160,8 @@ class ir_cron(osv.osv):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
with api.Environment.manage():
|
with api.Environment.manage():
|
||||||
now = fields.datetime.context_timestamp(job_cr, SUPERUSER_ID, datetime.now())
|
now = fields.datetime.context_timestamp(job_cr, job['user_id'], datetime.now())
|
||||||
nextcall = fields.datetime.context_timestamp(job_cr, SUPERUSER_ID, datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT))
|
nextcall = fields.datetime.context_timestamp(job_cr, job['user_id'], datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT))
|
||||||
numbercall = job['numbercall']
|
numbercall = job['numbercall']
|
||||||
|
|
||||||
ok = False
|
ok = False
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
<group col="4">
|
<group col="4">
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="shortcut"/>
|
<field name="shortcut"/>
|
||||||
<field name="domain"/>
|
|
||||||
</group>
|
</group>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
|
@ -183,8 +182,7 @@
|
||||||
<field name="fax"/>
|
<field name="fax"/>
|
||||||
<field name="user_ids" invisible="1"/>
|
<field name="user_ids" invisible="1"/>
|
||||||
<field name="email" widget="email" attrs="{'required': [('user_ids','!=', [])]}"/>
|
<field name="email" widget="email" attrs="{'required': [('user_ids','!=', [])]}"/>
|
||||||
<field name="title" domain="[('domain','=','contact')]" options='{"no_open": True}' attrs="{'invisible': [('is_company','=',True)]}" context="{'default_domain': 'contact'}"/>
|
<field name="title" domain="[('domain', '=', 'contact')]" options='{"no_open": True}'/>
|
||||||
<field name="title" domain="[('domain','=','partner')]" options='{"no_open": True}' attrs="{'invisible': [('is_company','=',False)]}" context="{'default_domain': 'partner'}"/>
|
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
|
|
@ -3168,6 +3168,11 @@ class BaseModel(object):
|
||||||
env = self.env
|
env = self.env
|
||||||
cr, user, context = env.args
|
cr, user, context = env.args
|
||||||
|
|
||||||
|
# FIXME: The query construction needs to be rewritten using the internal Query
|
||||||
|
# object, as in search(), to avoid ambiguous column references when
|
||||||
|
# reading/sorting on a table that is auto_joined to another table with
|
||||||
|
# common columns (e.g. the magical columns)
|
||||||
|
|
||||||
# Construct a clause for the security rules.
|
# Construct a clause for the security rules.
|
||||||
# 'tables' holds the list of tables necessary for the SELECT, including
|
# 'tables' holds the list of tables necessary for the SELECT, including
|
||||||
# the ir.rule clauses, and contains at least self._table.
|
# the ir.rule clauses, and contains at least self._table.
|
||||||
|
|
|
@ -466,17 +466,16 @@ class datetime(_column):
|
||||||
registry = openerp.modules.registry.RegistryManager.get(cr.dbname)
|
registry = openerp.modules.registry.RegistryManager.get(cr.dbname)
|
||||||
user = registry['res.users'].browse(cr, SUPERUSER_ID, uid)
|
user = registry['res.users'].browse(cr, SUPERUSER_ID, uid)
|
||||||
tz_name = user.tz
|
tz_name = user.tz
|
||||||
|
utc_timestamp = pytz.utc.localize(timestamp, is_dst=False) # UTC = no DST
|
||||||
if tz_name:
|
if tz_name:
|
||||||
try:
|
try:
|
||||||
utc = pytz.utc
|
|
||||||
context_tz = pytz.timezone(tz_name)
|
context_tz = pytz.timezone(tz_name)
|
||||||
utc_timestamp = utc.localize(timestamp, is_dst=False) # UTC = no DST
|
|
||||||
return utc_timestamp.astimezone(context_tz)
|
return utc_timestamp.astimezone(context_tz)
|
||||||
except Exception:
|
except Exception:
|
||||||
_logger.debug("failed to compute context/client-specific timestamp, "
|
_logger.debug("failed to compute context/client-specific timestamp, "
|
||||||
"using the UTC value",
|
"using the UTC value",
|
||||||
exc_info=True)
|
exc_info=True)
|
||||||
return timestamp
|
return utc_timestamp
|
||||||
|
|
||||||
class binary(_column):
|
class binary(_column):
|
||||||
_type = 'binary'
|
_type = 'binary'
|
||||||
|
|
Loading…
Reference in New Issue