[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):
|
||||
nb_inv_in_partial_rec = max_invoice_id = 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.currency_id == self.currency_id:
|
||||
self.residual += line.amount_residual_currency
|
||||
|
@ -1397,8 +1397,7 @@ class account_invoice_line(models.Model):
|
|||
res = []
|
||||
for line in inv.invoice_line:
|
||||
mres = self.move_line_get_item(line)
|
||||
if not mres:
|
||||
continue
|
||||
mres['invl_id'] = line.id
|
||||
res.append(mres)
|
||||
tax_code_found = False
|
||||
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')
|
||||
# calculate and write down the possible price difference between invoice price and product price
|
||||
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
|
||||
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:
|
||||
|
|
|
@ -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
|
||||
@http.route('/calendar/notify', type='json', auth="none")
|
||||
def notify(self):
|
||||
registry = openerp.modules.registry.RegistryManager.get(request.session.db)
|
||||
registry = request.registry
|
||||
uid = request.session.uid
|
||||
context = request.session.context
|
||||
with registry.cursor() as cr:
|
||||
|
@ -63,7 +63,7 @@ class meeting_invitation(http.Controller):
|
|||
|
||||
@http.route('/calendar/notify_ack', type='json', auth="none")
|
||||
def notify_ack(self, type=''):
|
||||
registry = openerp.modules.registry.RegistryManager.get(request.session.db)
|
||||
registry = request.registry
|
||||
uid = request.session.uid
|
||||
context = request.session.context
|
||||
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)
|
||||
sent_emails = self._build_email_kwargs_list
|
||||
email_to_lst = [
|
||||
['b@b.b', 'c@c.c'], ['"Administrator" <admin@yourcompany.example.com>'],
|
||||
['"Raoul Grosbedon" <raoul@raoul.fr>'], ['"Bert Tartignole" <bert@bert.fr>']]
|
||||
['b@b.b', 'c@c.c'], ['Administrator <admin@yourcompany.example.com>'],
|
||||
['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')
|
||||
for email in sent_emails:
|
||||
self.assertIn(email['email_to'], email_to_lst, 'email_template: send_mail: wrong email_recipients')
|
||||
|
|
|
@ -468,7 +468,7 @@
|
|||
<field name="expiration_date" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="insurer_id" />
|
||||
<field name="insurer_id" context="{'default_supplier': True}"/>
|
||||
<field name="purchaser_id" />
|
||||
<field name="ins_ref" />
|
||||
</group>
|
||||
|
@ -676,7 +676,7 @@
|
|||
<field name="date" />
|
||||
<field name="purchaser_id" />
|
||||
<field name="inv_ref" />
|
||||
<field name="vendor_id" />
|
||||
<field name="vendor_id" context="{'default_supplier': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Notes">
|
||||
|
@ -778,7 +778,7 @@
|
|||
<group string="Additional Details">
|
||||
<field name="date" />
|
||||
<field name="purchaser_id" />
|
||||
<field name="vendor_id" />
|
||||
<field name="vendor_id" context="{'default_supplier': True}"/>
|
||||
<field name="inv_ref" />
|
||||
</group>
|
||||
</group>
|
||||
|
|
|
@ -194,7 +194,7 @@ class gamification_goal(osv.Model):
|
|||
|
||||
_columns = {
|
||||
'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"),
|
||||
'challenge_id': fields.related('line_id', 'challenge_id',
|
||||
string="Challenge",
|
||||
|
@ -239,7 +239,7 @@ class gamification_goal(osv.Model):
|
|||
'state': 'draft',
|
||||
'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):
|
||||
"""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 = {
|
||||
'coda_fname': lambda *a: '',
|
||||
'coda_fname': 'coda.txt',
|
||||
}
|
||||
|
||||
def coda_parsing(self, cr, uid, ids, context=None, batch=False, codafile=None, codafilename=None):
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
import base64
|
||||
import logging
|
||||
from email.utils import formataddr
|
||||
from urlparse import urljoin
|
||||
|
||||
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):
|
||||
"""Forge the email_to with the following heuristic:
|
||||
- if 'partner' and mail is a notification on a document: followers (Followers of 'Doc' <email>)
|
||||
- elif 'partner', no notificatoin or no doc: recipient specific (Partner Name <email>)
|
||||
- if 'partner', recipient specific (Partner Name <email>)
|
||||
- else fallback on mail.email_to splitting """
|
||||
if partner:
|
||||
email_to = ['"%s" <%s>' % (partner.name, partner.email)]
|
||||
email_to = [formataddr((partner.name, partner.email))]
|
||||
else:
|
||||
email_to = tools.email_split(mail.email_to)
|
||||
return email_to
|
||||
|
|
|
@ -24,6 +24,7 @@ import logging
|
|||
from openerp import tools
|
||||
|
||||
from email.header import decode_header
|
||||
from email.utils import formataddr
|
||||
from openerp import SUPERUSER_ID, api
|
||||
from openerp.osv import osv, orm, fields
|
||||
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):
|
||||
this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
||||
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:
|
||||
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."))
|
||||
|
||||
def _get_default_author(self, cr, uid, context=None):
|
||||
|
|
|
@ -37,6 +37,7 @@ import time
|
|||
import xmlrpclib
|
||||
import re
|
||||
from email.message import Message
|
||||
from email.utils import formataddr
|
||||
from urllib import urlencode
|
||||
|
||||
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))
|
||||
# compute name of reply-to
|
||||
company_name = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).company_id.name
|
||||
res.update(
|
||||
dict((res_id, '"%(company_name)s%(document_name)s" <%(email)s>' %
|
||||
{'company_name': company_name,
|
||||
'document_name': doc_names.get(res_id) and ' ' + re.sub(r'[^\w+.]+', '-', doc_names[res_id]) or '',
|
||||
'email': aliases[res_id]
|
||||
} or False) for res_id in aliases.keys()))
|
||||
for res_id in aliases.keys():
|
||||
email_name = '%s%s' % (company_name, doc_names.get(res_id) and (' ' + doc_names[res_id]) or '')
|
||||
email_addr = aliases[res_id]
|
||||
res[res_id] = formataddr((email_name, email_addr))
|
||||
left_ids = set(ids).difference(set(aliases.keys()))
|
||||
if left_ids and default:
|
||||
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!')
|
||||
|
||||
# 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>']
|
||||
self.assertEqual(len(sent_emails), 2,
|
||||
'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')
|
||||
self.assertIn(sent_email['email_to'][0], test_emailto,
|
||||
'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')
|
||||
self.assertEqual(_subject, sent_email['subject'],
|
||||
'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!')
|
||||
|
||||
# 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>']
|
||||
# self.assertEqual(len(sent_emails), 3, 'sent_email number of sent emails incorrect')
|
||||
for sent_email in sent_emails:
|
||||
|
|
|
@ -81,7 +81,7 @@ class TestMailMessage(TestMail):
|
|||
alias_domain = 'schlouby.fr'
|
||||
raoul_from = 'Raoul Grosbedon <raoul@raoul.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
|
||||
|
@ -151,7 +151,7 @@ class TestMailMessage(TestMail):
|
|||
msg_id = self.mail_message.create(cr, user_raoul_id, {})
|
||||
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
|
||||
# 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')
|
||||
|
||||
# Do: create a mail_mail
|
||||
|
|
|
@ -42,8 +42,8 @@ class AcquirerPaypal(osv.Model):
|
|||
_columns = {
|
||||
'paypal_email_account': fields.char('Paypal Email ID', required_if_provider='paypal'),
|
||||
'paypal_seller_account': fields.char(
|
||||
'Paypal Seller ID',
|
||||
help='The Seller ID is used to ensure communications coming from Paypal are valid and secured.'),
|
||||
'Paypal Merchant ID',
|
||||
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'),
|
||||
# Server 2 server
|
||||
'paypal_api_enabled': fields.boolean('Use Rest API'),
|
||||
|
|
|
@ -902,7 +902,7 @@
|
|||
<br />
|
||||
<t t-esc="widget.pos.company.name"/><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 />
|
||||
<br />
|
||||
<t t-if="widget.pos.config.receipt_header">
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.osv import osv, fields
|
||||
from openerp import SUPERUSER_ID
|
||||
|
||||
|
||||
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):
|
||||
result = dict.fromkeys(ids, False)
|
||||
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:
|
||||
result[this.id] = payment_acquirer.render_payment_block(
|
||||
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_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_voucher,account.voucher,account_voucher.model_account_voucher,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_sale_shop,sale.shop,sale.model_sale_shop,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_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_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">
|
||||
<field name="name">Portal Personal Quotations/Sales Orders</field>
|
||||
<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 eval="1" name="perm_unlink"/>
|
||||
<field eval="1" name="perm_write"/>
|
||||
|
@ -26,17 +26,32 @@ their documents through the portal.</field>
|
|||
<field eval="0" name="perm_create"/>
|
||||
</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">
|
||||
<field name="name">Portal Personal Account Invoices</field>
|
||||
<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'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_personal_contact" model="ir.rule">
|
||||
<field name="name">Portal Personal Contacts</field>
|
||||
<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 name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
##############################################################################
|
||||
|
||||
import time
|
||||
from psycopg2 import OperationalError
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.osv import fields, osv
|
||||
|
@ -193,13 +194,14 @@ class procurement_order(osv.osv):
|
|||
def reset_to_confirmed(self, cr, uid, ids, context=None):
|
||||
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:
|
||||
#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
|
||||
#will fetch all the ids again)
|
||||
procurement = self.browse(cr, uid, procurement_id, context=context)
|
||||
if procurement.state not in ("running", "done"):
|
||||
try:
|
||||
if self._assign(cr, uid, procurement, context=context):
|
||||
procurement.refresh()
|
||||
res = self._run(cr, uid, procurement, context=context or {})
|
||||
|
@ -210,14 +212,31 @@ class procurement_order(osv.osv):
|
|||
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)
|
||||
if autocommit:
|
||||
cr.commit()
|
||||
except OperationalError:
|
||||
if autocommit:
|
||||
cr.rollback()
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
return True
|
||||
|
||||
def check(self, cr, uid, ids, context=None):
|
||||
def check(self, cr, uid, ids, autocommit=False, context=None):
|
||||
done_ids = []
|
||||
for procurement in self.browse(cr, uid, ids, context=context):
|
||||
try:
|
||||
result = self._check(cr, uid, procurement, context=context)
|
||||
if result:
|
||||
done_ids.append(procurement.id)
|
||||
if autocommit:
|
||||
cr.commit()
|
||||
except OperationalError:
|
||||
if autocommit:
|
||||
cr.rollback()
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
if done_ids:
|
||||
self.write(cr, uid, done_ids, {'state': 'done'}, context=context)
|
||||
return done_ids
|
||||
|
@ -291,11 +310,14 @@ class procurement_order(osv.osv):
|
|||
dom = [('state', '=', 'confirmed')]
|
||||
if company_id:
|
||||
dom += [('company_id', '=', company_id)]
|
||||
prev_ids = []
|
||||
while True:
|
||||
ids = self.search(cr, SUPERUSER_ID, dom, context=context)
|
||||
if not ids:
|
||||
if not ids or prev_ids == ids:
|
||||
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:
|
||||
cr.commit()
|
||||
|
||||
|
@ -304,12 +326,14 @@ class procurement_order(osv.osv):
|
|||
dom = [('state', '=', 'running')]
|
||||
if company_id:
|
||||
dom += [('company_id', '=', company_id)]
|
||||
prev_ids = []
|
||||
while True:
|
||||
ids = self.search(cr, SUPERUSER_ID, dom, offset=offset, context=context)
|
||||
if not ids:
|
||||
if not ids or prev_ids == ids:
|
||||
break
|
||||
done = self.check(cr, SUPERUSER_ID, ids, context=context)
|
||||
offset += len(ids) - len(done)
|
||||
else:
|
||||
prev_ids = ids
|
||||
self.check(cr, SUPERUSER_ID, ids, autocommit=use_new_cursor, context=context)
|
||||
if use_new_cursor:
|
||||
cr.commit()
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FO
|
|||
from openerp import SUPERUSER_ID
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from datetime import datetime
|
||||
from psycopg2 import OperationalError
|
||||
import openerp
|
||||
|
||||
class procurement_group(osv.osv):
|
||||
|
@ -204,8 +205,8 @@ class procurement_order(osv.osv):
|
|||
return True
|
||||
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
|
||||
|
||||
def run(self, cr, uid, ids, context=None):
|
||||
res = super(procurement_order, self).run(cr, uid, ids, context=context)
|
||||
def run(self, cr, uid, ids, autocommit=False, context=None):
|
||||
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
|
||||
#(we do that in batch because it fasts the picking assignation and the picking state computation)
|
||||
move_to_confirm_ids = []
|
||||
|
@ -335,12 +336,14 @@ class procurement_order(osv.osv):
|
|||
orderpoint_obj = self.pool.get('stock.warehouse.orderpoint')
|
||||
|
||||
procurement_obj = self.pool.get('procurement.order')
|
||||
offset = 0
|
||||
ids = [1]
|
||||
dom = company_id and [('company_id', '=', company_id)] or []
|
||||
while ids:
|
||||
ids = orderpoint_obj.search(cr, uid, dom, offset=offset, limit=100)
|
||||
orderpoint_ids = orderpoint_obj.search(cr, uid, dom)
|
||||
prev_ids = []
|
||||
while orderpoint_ids:
|
||||
ids = orderpoint_ids[:100]
|
||||
del orderpoint_ids[:100]
|
||||
for op in orderpoint_obj.browse(cr, uid, ids, context=context):
|
||||
try:
|
||||
prods = self._product_virtual_get(cr, uid, op)
|
||||
if prods is None:
|
||||
continue
|
||||
|
@ -362,9 +365,22 @@ class procurement_order(osv.osv):
|
|||
context=context)
|
||||
self.check(cr, uid, [proc_id])
|
||||
self.run(cr, uid, [proc_id])
|
||||
offset += len(ids)
|
||||
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:
|
||||
cr.commit()
|
||||
if prev_ids == ids:
|
||||
break
|
||||
else:
|
||||
prev_ids = ids
|
||||
|
||||
if use_new_cursor:
|
||||
cr.commit()
|
||||
cr.close()
|
||||
|
|
|
@ -1418,16 +1418,18 @@ class ExportFormat(object):
|
|||
raise NotImplementedError()
|
||||
|
||||
def base(self, data, token):
|
||||
params = simplejson.loads(data)
|
||||
model, fields, ids, domain, import_compat = \
|
||||
operator.itemgetter('model', 'fields', 'ids', 'domain',
|
||||
'import_compat')(
|
||||
simplejson.loads(data))
|
||||
params)
|
||||
|
||||
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)
|
||||
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:
|
||||
columns_headers = field_names
|
||||
|
|
|
@ -406,6 +406,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
fields: exported_fields,
|
||||
ids: this.ids_to_export,
|
||||
domain: this.domain,
|
||||
context: this.dataset.context,
|
||||
import_compat: !!this.$el.find("#import_compat").val(),
|
||||
})},
|
||||
complete: instance.web.unblockUI,
|
||||
|
|
|
@ -487,7 +487,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
*/
|
||||
setup_global_completion: function () {
|
||||
var self = this;
|
||||
|
||||
this.autocomplete = new instance.web.search.AutoComplete(this, {
|
||||
source: this.proxy('complete_global_search'),
|
||||
select: this.proxy('select_completion'),
|
||||
|
|
|
@ -522,7 +522,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
self.dataset.index = 0;
|
||||
}
|
||||
} else if (self.dataset.index >= self.records.length) {
|
||||
self.dataset.index = 0;
|
||||
self.dataset.index = self.records.length ? 0 : null;
|
||||
}
|
||||
|
||||
self.compute_aggregates();
|
||||
|
|
|
@ -423,14 +423,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
attrs.value = [attrs.value];
|
||||
}
|
||||
attrs.value = _.range(grouped_on.length).map(function (i) {
|
||||
var grp = grouped_on[i],
|
||||
field = self.fields[grp];
|
||||
if (attrs.value[i] === false) {
|
||||
return _t('Undefined');
|
||||
} else if (attrs.value[i] instanceof Array) {
|
||||
return attrs.value[i][1];
|
||||
}else if (grouped_on && self.fields[grouped_on].type === 'selection'){
|
||||
var selection = self.fields[grouped_on].selection;
|
||||
var value_lookup = _.where(selection, {0:attrs.value[i]});
|
||||
return value_lookup ? value_lookup[0][1] : _t('Undefined');
|
||||
} else if (field && field.type === 'selection') {
|
||||
var selected = _.where(field.selection, {0: attrs.value[i]})[0];
|
||||
return selected ? selected[1] : 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);
|
||||
if (!_.isEmpty(self.dataset.ids) && (self.dataset.index === null || self.dataset.index >= self.dataset.ids.length)) {
|
||||
self.dataset.index = 0;
|
||||
} else if (_.isEmpty(self.dataset.ids)){
|
||||
self.dataset.index = null;
|
||||
}
|
||||
self.do_add_groups([kgroup]).done(function() {
|
||||
if (_.isEmpty(records)) {
|
||||
|
|
|
@ -131,8 +131,8 @@
|
|||
<!-- 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>
|
||||
<ul class="nav">
|
||||
<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>
|
||||
<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;" scrolling="no"></iframe>
|
||||
</ul>
|
||||
</xpath>
|
||||
</template>
|
||||
|
|
|
@ -59,8 +59,11 @@ class WebsiteCustomer(http.Controller):
|
|||
partner_count = partner_obj.search_count(cr, openerp.SUPERUSER_ID, domain, context=request.context)
|
||||
|
||||
# pager
|
||||
url = '/customers/'
|
||||
if country_id:
|
||||
url += 'country/%s' % country_id
|
||||
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
|
||||
)
|
||||
|
||||
|
|
|
@ -84,8 +84,8 @@
|
|||
<!-- 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>
|
||||
<ul class="nav">
|
||||
<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>
|
||||
<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;" scrolling="no"></iframe>
|
||||
</ul>
|
||||
</xpath>
|
||||
</template>
|
||||
|
|
|
@ -90,9 +90,12 @@ class website_event(http.Controller):
|
|||
if searches["type"] != 'all':
|
||||
current_type = type_obj.browse(cr, uid, int(searches['type']), context=context)
|
||||
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)
|
||||
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):
|
||||
domain = [('state', "in", ['draft','confirm','done'])]
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
<div itemscope="itemscope" itemtype="http://schema.org/Event" class="media-body">
|
||||
<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>
|
||||
<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>
|
||||
</h4>
|
||||
<div>
|
||||
|
@ -179,7 +180,13 @@
|
|||
<ul class="nav nav-pills nav-stacked mt32">
|
||||
<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 ''">
|
||||
<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>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -29,19 +29,18 @@
|
|||
<h4>Choose your Delivery Method</h4>
|
||||
<ul class="list-unstyled">
|
||||
<li t-foreach="deliveries" t-as="delivery">
|
||||
<t t-if="delivery.available">
|
||||
<label>
|
||||
<input t-att-value="delivery.id" type="radio" name="delivery_type"
|
||||
t-att-checked="order.carrier_id and order.carrier_id.id == delivery.id and 'checked' or False"
|
||||
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"/>
|
||||
<t t-if="delivery.available">
|
||||
<span class="badge" t-field="delivery.price"
|
||||
t-field-options='{
|
||||
"widget": "monetary",
|
||||
"display_currency": "website.pricelist_id.currency_id"
|
||||
}'/>
|
||||
</t>
|
||||
</label>
|
||||
</t>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -160,8 +160,8 @@ class ir_cron(osv.osv):
|
|||
"""
|
||||
try:
|
||||
with api.Environment.manage():
|
||||
now = fields.datetime.context_timestamp(job_cr, SUPERUSER_ID, datetime.now())
|
||||
nextcall = fields.datetime.context_timestamp(job_cr, SUPERUSER_ID, datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT))
|
||||
now = fields.datetime.context_timestamp(job_cr, job['user_id'], datetime.now())
|
||||
nextcall = fields.datetime.context_timestamp(job_cr, job['user_id'], datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT))
|
||||
numbercall = job['numbercall']
|
||||
|
||||
ok = False
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
<group col="4">
|
||||
<field name="name"/>
|
||||
<field name="shortcut"/>
|
||||
<field name="domain"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -183,8 +182,7 @@
|
|||
<field name="fax"/>
|
||||
<field name="user_ids" invisible="1"/>
|
||||
<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','=','partner')]" options='{"no_open": True}' attrs="{'invisible': [('is_company','=',False)]}" context="{'default_domain': 'partner'}"/>
|
||||
<field name="title" domain="[('domain', '=', 'contact')]" options='{"no_open": True}'/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
|
|
|
@ -3168,6 +3168,11 @@ class BaseModel(object):
|
|||
env = self.env
|
||||
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.
|
||||
# 'tables' holds the list of tables necessary for the SELECT, including
|
||||
# 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)
|
||||
user = registry['res.users'].browse(cr, SUPERUSER_ID, uid)
|
||||
tz_name = user.tz
|
||||
utc_timestamp = pytz.utc.localize(timestamp, is_dst=False) # UTC = no DST
|
||||
if tz_name:
|
||||
try:
|
||||
utc = pytz.utc
|
||||
context_tz = pytz.timezone(tz_name)
|
||||
utc_timestamp = utc.localize(timestamp, is_dst=False) # UTC = no DST
|
||||
return utc_timestamp.astimezone(context_tz)
|
||||
except Exception:
|
||||
_logger.debug("failed to compute context/client-specific timestamp, "
|
||||
"using the UTC value",
|
||||
exc_info=True)
|
||||
return timestamp
|
||||
return utc_timestamp
|
||||
|
||||
class binary(_column):
|
||||
_type = 'binary'
|
||||
|
|
Loading…
Reference in New Issue