[MERGE] forward port of branch saas-5 up to 0739bc4
This commit is contained in:
commit
ae65be2b2a
|
@ -177,6 +177,8 @@ class account_invoice(models.Model):
|
|||
def _compute_payments(self):
|
||||
partial_lines = lines = self.env['account.move.line']
|
||||
for line in self.move_id.line_id:
|
||||
if line.account_id != self.account_id:
|
||||
continue
|
||||
if line.reconcile_id:
|
||||
lines |= line.reconcile_id.line_id
|
||||
elif line.reconcile_partial_id:
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<record id="email_template_edi_invoice" model="email.template">
|
||||
<field name="name">Invoice - Send by Email</field>
|
||||
<field name="email_from">${(object.user_id.email or object.company_id.email or 'noreply@localhost')|safe}</field>
|
||||
<field name="subject">${object.company_id.name} Invoice (Ref ${object.number or 'n/a'})</field>
|
||||
<field name="subject">${object.company_id.name|safe} Invoice (Ref ${object.number or 'n/a'})</field>
|
||||
<field name="partner_to">${object.partner_id.id}</field>
|
||||
<field name="model_id" ref="account.model_account_invoice"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
<separator/>
|
||||
<filter string="Invoice" domain="['|', ('type','=','out_invoice'),('type','=','in_invoice')]"/>
|
||||
<filter string="Refund" domain="['|', ('type','=','out_refund'),('type','=','in_refund')]"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="user_id" />
|
||||
<field name="categ_id" filter_domain="[('categ_id', 'child_of', self)]"/>
|
||||
<group expand="1" string="Group By">
|
||||
|
|
|
@ -133,7 +133,7 @@ class account_fiscalyear_close(osv.osv_memory):
|
|||
FROM account_account a
|
||||
LEFT JOIN account_account_type t ON (a.user_type = t.id)
|
||||
WHERE a.active
|
||||
AND a.type != 'view'
|
||||
AND a.type not in ('view', 'consolidation')
|
||||
AND a.company_id = %s
|
||||
AND t.close_method = %s''', (company_id, 'unreconciled', ))
|
||||
account_ids = map(lambda x: x[0], cr.fetchall())
|
||||
|
@ -184,7 +184,7 @@ class account_fiscalyear_close(osv.osv_memory):
|
|||
FROM account_account a
|
||||
LEFT JOIN account_account_type t ON (a.user_type = t.id)
|
||||
WHERE a.active
|
||||
AND a.type != 'view'
|
||||
AND a.type not in ('view', 'consolidation')
|
||||
AND a.company_id = %s
|
||||
AND t.close_method = %s''', (company_id, 'detail', ))
|
||||
account_ids = map(lambda x: x[0], cr.fetchall())
|
||||
|
@ -213,7 +213,7 @@ class account_fiscalyear_close(osv.osv_memory):
|
|||
FROM account_account a
|
||||
LEFT JOIN account_account_type t ON (a.user_type = t.id)
|
||||
WHERE a.active
|
||||
AND a.type != 'view'
|
||||
AND a.type not in ('view', 'consolidation')
|
||||
AND a.company_id = %s
|
||||
AND t.close_method = %s''', (company_id, 'balance', ))
|
||||
account_ids = map(lambda x: x[0], cr.fetchall())
|
||||
|
|
|
@ -210,7 +210,7 @@ class account_analytic_plan_instance(osv.osv):
|
|||
ana_plan_instance_obj = self.pool.get('account.analytic.plan.instance')
|
||||
acct_anal_acct = self.pool.get('account.analytic.account')
|
||||
acct_anal_plan_line_obj = self.pool.get('account.analytic.plan.line')
|
||||
if context and 'journal_id' in context:
|
||||
if context and context.get('journal_id'):
|
||||
journal = journal_obj.browse(cr, uid, context['journal_id'], context=context)
|
||||
|
||||
pids = ana_plan_instance_obj.search(cr, uid, [('name','=',vals['name']), ('code','=',vals['code']), ('plan_id','<>',False)], context=context)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
##############################################################################
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools.float_utils import float_round as round
|
||||
|
||||
class account_invoice_line(osv.osv):
|
||||
_inherit = "account.invoice.line"
|
||||
|
@ -36,11 +37,12 @@ class account_invoice_line(osv.osv):
|
|||
company_currency = inv.company_id.currency_id.id
|
||||
def get_price(cr, uid, inv, company_currency, i_line, price_unit):
|
||||
cur_obj = self.pool.get('res.currency')
|
||||
decimal_precision = self.pool.get('decimal.precision')
|
||||
if inv.currency_id.id != company_currency:
|
||||
price = cur_obj.compute(cr, uid, company_currency, inv.currency_id.id, price_unit * i_line.quantity, context={'date': inv.date_invoice})
|
||||
else:
|
||||
price = price_unit * i_line.quantity
|
||||
return price
|
||||
return round(price, decimal_precision.precision_get(cr, uid, 'Account'))
|
||||
|
||||
if inv.type in ('out_invoice','out_refund'):
|
||||
for i_line in inv.invoice_line:
|
||||
|
@ -118,6 +120,8 @@ class account_invoice_line(osv.osv):
|
|||
fpos = i_line.invoice_id.fiscal_position or False
|
||||
a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, oa)
|
||||
diff_res = []
|
||||
decimal_precision = self.pool.get('decimal.precision')
|
||||
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']:
|
||||
|
@ -132,14 +136,14 @@ class account_invoice_line(osv.osv):
|
|||
if valuation_stock_move:
|
||||
valuation_price_unit = stock_move_obj.browse(cr, uid, valuation_stock_move[0], context=context).price_unit
|
||||
if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc:
|
||||
price_diff = i_line.price_unit - valuation_price_unit
|
||||
line.update({'price': valuation_price_unit * line['quantity']})
|
||||
price_diff = round(i_line.price_unit - valuation_price_unit, account_prec)
|
||||
line.update({'price': round(valuation_price_unit * line['quantity'], account_prec)})
|
||||
diff_res.append({
|
||||
'type': 'src',
|
||||
'name': i_line.name[:64],
|
||||
'price_unit': price_diff,
|
||||
'quantity': line['quantity'],
|
||||
'price': price_diff * line['quantity'],
|
||||
'price': round(price_diff * line['quantity'], account_prec),
|
||||
'account_id': acc,
|
||||
'product_id': line['product_id'],
|
||||
'uos_id': line['uos_id'],
|
||||
|
|
|
@ -1044,7 +1044,8 @@ class account_voucher(osv.osv):
|
|||
'period_id': voucher.period_id.id,
|
||||
'partner_id': voucher.partner_id.id,
|
||||
'currency_id': company_currency <> current_currency and current_currency or False,
|
||||
'amount_currency': company_currency <> current_currency and sign * voucher.amount or 0.0,
|
||||
'amount_currency': (sign * abs(voucher.amount) # amount < 0 for refunds
|
||||
if company_currency != current_currency else 0.0),
|
||||
'date': voucher.date,
|
||||
'date_maturity': voucher.date_due
|
||||
}
|
||||
|
@ -1210,7 +1211,7 @@ class account_voucher(osv.osv):
|
|||
if line.amount == line.amount_unreconciled:
|
||||
if not line.move_line_id:
|
||||
raise osv.except_osv(_('Wrong voucher line'),_("The invoice you are willing to pay is not valid anymore."))
|
||||
sign = voucher.type in ('payment', 'purchase') and -1 or 1
|
||||
sign = line.type =='dr' and -1 or 1
|
||||
currency_rate_difference = sign * (line.move_line_id.amount_residual - amount)
|
||||
else:
|
||||
currency_rate_difference = 0.0
|
||||
|
@ -1268,8 +1269,7 @@ class account_voucher(osv.osv):
|
|||
# otherwise we use the rates of the system
|
||||
amount_currency = currency_obj.compute(cr, uid, company_currency, line.move_line_id.currency_id.id, move_line['debit']-move_line['credit'], context=ctx)
|
||||
if line.amount == line.amount_unreconciled:
|
||||
sign = voucher.type in ('payment', 'purchase') and -1 or 1
|
||||
foreign_currency_diff = sign * line.move_line_id.amount_residual_currency + amount_currency
|
||||
foreign_currency_diff = line.move_line_id.amount_residual_currency - abs(amount_currency)
|
||||
|
||||
move_line['amount_currency'] = amount_currency
|
||||
voucher_line = move_line_obj.create(cr, uid, move_line)
|
||||
|
|
|
@ -307,7 +307,7 @@ class account_analytic_account(osv.osv):
|
|||
dom = []
|
||||
for name2 in name.split('/'):
|
||||
name = name2.strip()
|
||||
account_ids = self.search(cr, uid, dom + [('name', 'ilike', name)] + args, limit=limit, context=context)
|
||||
account_ids = self.search(cr, uid, dom + [('name', operator, name)] + args, limit=limit, context=context)
|
||||
if not account_ids: break
|
||||
dom = [('parent_id','in',account_ids)]
|
||||
else:
|
||||
|
|
|
@ -901,6 +901,15 @@ class calendar_event(osv.Model):
|
|||
'partner_ids': fields.many2many('res.partner', 'calendar_event_res_partner_rel', string='Attendees', states={'done': [('readonly', True)]}),
|
||||
'alarm_ids': fields.many2many('calendar.alarm', 'calendar_alarm_calendar_event_rel', string='Reminders', ondelete="restrict", copy=False),
|
||||
}
|
||||
|
||||
def _get_default_partners(self, cr, uid, ctx=None):
|
||||
ret = [self.pool['res.users'].browse(cr, uid, uid, context=ctx).partner_id.id]
|
||||
active_id = ctx.get('active_id')
|
||||
if ctx.get('active_model') == 'res.partner' and active_id:
|
||||
if active_id not in ret:
|
||||
ret.append(active_id)
|
||||
return ret
|
||||
|
||||
_defaults = {
|
||||
'end_type': 'count',
|
||||
'count': 1,
|
||||
|
@ -913,7 +922,7 @@ class calendar_event(osv.Model):
|
|||
'interval': 1,
|
||||
'active': 1,
|
||||
'user_id': lambda self, cr, uid, ctx: uid,
|
||||
'partner_ids': lambda self, cr, uid, ctx: [self.pool['res.users'].browse(cr, uid, [uid], context=ctx)[0].partner_id.id]
|
||||
'partner_ids': _get_default_partners,
|
||||
}
|
||||
|
||||
def _check_closing_date(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<h1>
|
||||
<field name="name"/>
|
||||
</h1>
|
||||
<label for="partner_ids" class="oe_edit_only"/>
|
||||
<label for="partner_ids" string="Attendees" class="oe_edit_only"/>
|
||||
<h2>
|
||||
<field name="partner_ids" widget="many2manyattendee"
|
||||
context="{'force_email':True}"
|
||||
|
|
|
@ -6,6 +6,7 @@ import htmlentitydefs
|
|||
import itertools
|
||||
import logging
|
||||
import operator
|
||||
import psycopg2
|
||||
import re
|
||||
from ast import literal_eval
|
||||
from openerp.tools import mute_logger
|
||||
|
@ -186,28 +187,29 @@ class MergePartnerAutomatic(osv.TransientModel):
|
|||
for partner_id in partner_ids:
|
||||
cr.execute(query, (dst_partner.id, partner_id, dst_partner.id))
|
||||
else:
|
||||
cr.execute("SAVEPOINT recursive_partner_savepoint")
|
||||
try:
|
||||
query = 'UPDATE "%(table)s" SET %(column)s = %%s WHERE %(column)s IN %%s' % query_dic
|
||||
cr.execute(query, (dst_partner.id, partner_ids,))
|
||||
with mute_logger('openerp.sql_db'), cr.savepoint():
|
||||
query = 'UPDATE "%(table)s" SET %(column)s = %%s WHERE %(column)s IN %%s' % query_dic
|
||||
cr.execute(query, (dst_partner.id, partner_ids,))
|
||||
|
||||
if column == proxy._parent_name and table == 'res_partner':
|
||||
query = """
|
||||
WITH RECURSIVE cycle(id, parent_id) AS (
|
||||
SELECT id, parent_id FROM res_partner
|
||||
UNION
|
||||
SELECT cycle.id, res_partner.parent_id
|
||||
FROM res_partner, cycle
|
||||
WHERE res_partner.id = cycle.parent_id AND
|
||||
cycle.id != cycle.parent_id
|
||||
)
|
||||
SELECT id FROM cycle WHERE id = parent_id AND id = %s
|
||||
"""
|
||||
cr.execute(query, (dst_partner.id,))
|
||||
if cr.fetchall():
|
||||
cr.execute("ROLLBACK TO SAVEPOINT recursive_partner_savepoint")
|
||||
finally:
|
||||
cr.execute("RELEASE SAVEPOINT recursive_partner_savepoint")
|
||||
if column == proxy._parent_name and table == 'res_partner':
|
||||
query = """
|
||||
WITH RECURSIVE cycle(id, parent_id) AS (
|
||||
SELECT id, parent_id FROM res_partner
|
||||
UNION
|
||||
SELECT cycle.id, res_partner.parent_id
|
||||
FROM res_partner, cycle
|
||||
WHERE res_partner.id = cycle.parent_id AND
|
||||
cycle.id != cycle.parent_id
|
||||
)
|
||||
SELECT id FROM cycle WHERE id = parent_id AND id = %s
|
||||
"""
|
||||
cr.execute(query, (dst_partner.id,))
|
||||
except psycopg2.Error:
|
||||
# updating fails, most likely due to a violated unique constraint
|
||||
# keeping record with nonexistent partner_id is useless, better delete it
|
||||
query = 'DELETE FROM %(table)s WHERE %(column)s = %%s' % query_dic
|
||||
cr.execute(query, (partner_id,))
|
||||
|
||||
def _update_reference_fields(self, cr, uid, src_partners, dst_partner, context=None):
|
||||
_logger.debug('_update_reference_fields for dst_partner: %s for src_partners: %r', dst_partner.id, list(map(operator.attrgetter('id'), src_partners)))
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
<group colspan="2" col="2" groups="base.group_user">
|
||||
<separator colspan="2" string="Responsibilities"/>
|
||||
<field name="user_fault"/>
|
||||
<field name="categ_id" widget="selection"
|
||||
<field name="categ_id" options="{'no_create': True, 'no_open': True}"
|
||||
domain="[('object_id.model', '=', 'crm.claim')]"/>
|
||||
<field name="ref"/>
|
||||
</group>
|
||||
|
|
|
@ -34,9 +34,34 @@ from openerp import tools, api
|
|||
from openerp.tools.translate import _
|
||||
from urllib import urlencode, quote as quote
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def format_tz(pool, cr, uid, dt, tz=False, format=False, context=None):
|
||||
context = dict(context or {})
|
||||
if tz:
|
||||
context['tz'] = tz or pool.get('res.users').read(cr, SUPERUSER_ID, uid, ['tz'])['tz'] or "UTC"
|
||||
timestamp = datetime.datetime.strptime(dt, tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
ts = fields.datetime.context_timestamp(cr, uid, timestamp, context)
|
||||
|
||||
if format:
|
||||
return ts.strftime(format)
|
||||
else:
|
||||
lang = context.get("lang")
|
||||
lang_params = {}
|
||||
if lang:
|
||||
res_lang = pool.get('res.lang')
|
||||
ids = res_lang.search(cr, uid, [("code", "=", lang)])
|
||||
if ids:
|
||||
lang_params = res_lang.read(cr, uid, ids[0], ["date_format", "time_format"])
|
||||
format_date = lang_params.get("date_format", '%B-%d-%Y')
|
||||
format_time = lang_params.get("time_format", '%I-%M %p')
|
||||
|
||||
fdate = ts.strftime(format_date)
|
||||
ftime = ts.strftime(format_time)
|
||||
return "%s %s (%s)" % (fdate, ftime, tz)
|
||||
|
||||
try:
|
||||
# We use a jinja2 sandboxed environment to render mako templates.
|
||||
# Note that the rendering does not cover all the mako syntax, in particular
|
||||
|
@ -165,6 +190,7 @@ class email_template(osv.osv):
|
|||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
records = self.pool[model].browse(cr, uid, res_ids, context=context) or [None]
|
||||
variables = {
|
||||
'format_tz': lambda dt, tz=False, format=False: format_tz(self.pool, cr, uid, dt, tz, format, context),
|
||||
'user': user,
|
||||
'ctx': context, # context kw would clash with mako internals
|
||||
}
|
||||
|
|
|
@ -640,7 +640,7 @@
|
|||
<field name="style_overwrite" eval="2"/>
|
||||
</record>
|
||||
<record id="account_financial_report_bnficepertedelexcerciceavantimpts1" model="account.financial.report">
|
||||
<field name="name">Bénéfice (Perte) de l'excercice avant impôts</field>
|
||||
<field name="name">Bénéfice (Perte) de l'exercice avant impôts</field>
|
||||
<field eval="8" name="sequence"/>
|
||||
<field name="parent_id" ref="account_financial_report_belgiumpl0"/>
|
||||
<field name="display_detail">no_detail</field>
|
||||
|
@ -674,7 +674,7 @@
|
|||
<field name="style_overwrite" eval="2"/>
|
||||
</record>
|
||||
<record id="account_financial_report_bnficepertedelexcercice1" model="account.financial.report">
|
||||
<field name="name">Bénéfice (Perte) de l'excercice</field>
|
||||
<field name="name">Bénéfice (Perte) de l'exercice</field>
|
||||
<field eval="12" name="sequence"/>
|
||||
<field name="parent_id" ref="account_financial_report_belgiumpl0"/>
|
||||
<field name="display_detail">no_detail</field>
|
||||
|
|
|
@ -67,6 +67,7 @@ class mail_followers(osv.Model):
|
|||
self.invalidate_cache(cr, uid, context=context)
|
||||
return res
|
||||
|
||||
_sql_constraints = [('mail_followers_res_partner_res_model_id_uniq','unique(res_model,res_id,partner_id)','Error, a partner cannot follow twice the same object.')]
|
||||
|
||||
class mail_notification(osv.Model):
|
||||
""" Class holding notifications pushed to partners. Followers and partners
|
||||
|
|
|
@ -50,10 +50,11 @@
|
|||
<t t-if="!widget.options.view_mailbox">
|
||||
<div class="field_text oe_compact oe_compact_record">
|
||||
<a class="oe_compose_post" t-if="widget.options.compose_placeholder"><t t-raw="widget.options.compose_placeholder"/></a>
|
||||
<a class="oe_compose_post" t-if="!widget.options.compose_placeholder and !widget.options.view_mailbox">Send a message</a>
|
||||
<a class="oe_compose_post" t-if="!widget.options.compose_placeholder and !widget.options.view_mailbox"
|
||||
title="Send a message to all followers of the document">Send a message</a>
|
||||
<t t-if="widget.options.display_log_button">
|
||||
<span class="oe_grey oe_sep_word">or</span>
|
||||
<a class="oe_compose_log">Log an internal note</a>
|
||||
<a class="oe_compose_log" title="Log a note for this document. No notification will be sent">Log an internal note</a>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
|
|
@ -40,13 +40,21 @@ class PaypalController(http.Controller):
|
|||
Once data is validated, process it. """
|
||||
res = False
|
||||
new_post = dict(post, cmd='_notify-validate')
|
||||
urequest = urllib2.Request("https://www.sandbox.paypal.com/cgi-bin/webscr", werkzeug.url_encode(new_post))
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
reference = post.get('item_number')
|
||||
tx = None
|
||||
if reference:
|
||||
tx_ids = request.registry['payment.transaction'].search(cr, uid, [('reference', '=', reference)], context=context)
|
||||
if tx_ids:
|
||||
tx = request.registry['payment.transaction'].browse(cr, uid, tx_ids[0], context=context)
|
||||
paypal_urls = request.registry['payment.acquirer']._get_paypal_urls(cr, uid, tx and tx.acquirer_id and tx.acquirer_id.env or 'prod', context=context)
|
||||
validate_url = paypal_urls['paypal_form_url']
|
||||
urequest = urllib2.Request(validate_url, werkzeug.url_encode(new_post))
|
||||
uopen = urllib2.urlopen(urequest)
|
||||
resp = uopen.read()
|
||||
if resp == 'VERIFIED':
|
||||
_logger.info('Paypal: validated data')
|
||||
cr, uid, context = request.cr, SUPERUSER_ID, request.context
|
||||
res = request.registry['payment.transaction'].form_feedback(cr, uid, post, 'paypal', context=context)
|
||||
res = request.registry['payment.transaction'].form_feedback(cr, SUPERUSER_ID, post, 'paypal', context=context)
|
||||
elif resp == 'INVALID':
|
||||
_logger.warning('Paypal: answered INVALID on data verification')
|
||||
else:
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
</div>
|
||||
<field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator"/>
|
||||
</group>
|
||||
<div class="oe_clear"/>
|
||||
</page>
|
||||
<page string="Payments">
|
||||
<field name="statement_ids" colspan="4" nolabel="1">
|
||||
|
|
|
@ -900,7 +900,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.user.name"/><br />
|
||||
User: <t t-esc="widget.pos.cashier.name"/><br />
|
||||
Shop: <t t-esc="widget.pos.shop.name"/><br />
|
||||
<br />
|
||||
<t t-if="widget.pos.config.receipt_header">
|
||||
|
|
|
@ -19,3 +19,4 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
import portal_claim
|
|
@ -0,0 +1,44 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.osv import osv
|
||||
|
||||
|
||||
class crm_claim(osv.osv):
|
||||
_inherit = "crm.claim"
|
||||
|
||||
def _get_default_partner_id(self, cr, uid, context=None):
|
||||
""" Gives default partner_id """
|
||||
if context is None:
|
||||
context = {}
|
||||
if context.get('portal'):
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
# Special case for portal users, as they are not allowed to call name_get on res.partner
|
||||
# We save this call for the web client by returning it in default get
|
||||
return self.pool['res.partner'].name_get(cr, SUPERUSER_ID, [user.partner_id.id], context=context)[0]
|
||||
return False
|
||||
|
||||
_defaults = {
|
||||
'partner_id': lambda s, cr, uid, c: s._get_default_partner_id(cr, uid, c),
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -7,7 +7,7 @@
|
|||
<record id="email_template_edi_sale" model="email.template">
|
||||
<field name="name">Sales Order - Send by Email (Portal)</field>
|
||||
<field name="email_from">${(object.user_id.email or '')|safe}</field>
|
||||
<field name="subject">${object.company_id.name} ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'} (Ref ${object.name or 'n/a' })</field>
|
||||
<field name="subject">${object.company_id.name|safe} ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'} (Ref ${object.name or 'n/a' })</field>
|
||||
<field name="partner_to">${object.partner_invoice_id.id}</field>
|
||||
<field name="model_id" ref="sale.model_sale_order"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
@ -98,7 +98,7 @@
|
|||
<record id="email_template_edi_invoice" model="email.template">
|
||||
<field name="name">Invoice - Send by Email (Portal)</field>
|
||||
<field name="email_from">${(object.user_id.email or object.company_id.email or 'noreply@localhost')|safe}</field>
|
||||
<field name="subject">${object.company_id.name} Invoice (Ref ${object.number or 'n/a' })</field>
|
||||
<field name="subject">${object.company_id.name|safe} Invoice (Ref ${object.number or 'n/a' })</field>
|
||||
<field name="partner_to">${object.partner_id.id}</field>
|
||||
<field name="model_id" ref="account.model_account_invoice"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
<!--Email template -->
|
||||
<record id="email_template_edi_purchase" model="email.template">
|
||||
<field name="name">RFQ - Send by Email</field>
|
||||
<field name="email_from">${object.validator.email or ''}</field>
|
||||
<field name="subject">${object.company_id.name} Order (Ref ${object.name or 'n/a' })</field>
|
||||
<field name="email_from">${(object.validator.email or '')|safe}</field>
|
||||
<field name="subject">${object.company_id.name|safe} Order (Ref ${object.name or 'n/a' })</field>
|
||||
<field name="partner_to">${object.partner_id.id}</field>
|
||||
<field name="model_id" ref="purchase.model_purchase_order"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<record id="email_template_edi_sale" model="email.template">
|
||||
<field name="name">Sales Order - Send by Email</field>
|
||||
<field name="email_from">${(object.user_id.email or '')|safe}</field>
|
||||
<field name="subject">${object.company_id.name} ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'} (Ref ${object.name or 'n/a' })</field>
|
||||
<field name="subject">${object.company_id.name|safe} ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'} (Ref ${object.name or 'n/a' })</field>
|
||||
<field name="partner_to">${object.partner_invoice_id.id}</field>
|
||||
<field name="model_id" ref="sale.model_sale_order"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
|
|
@ -1950,13 +1950,12 @@ class stock_move(osv.osv):
|
|||
product = self.pool.get('product.product').browse(cr, uid, [prod_id], context=ctx)[0]
|
||||
uos_id = product.uos_id and product.uos_id.id or False
|
||||
result = {
|
||||
'name': product.partner_ref,
|
||||
'product_uom': product.uom_id.id,
|
||||
'product_uos': uos_id,
|
||||
'product_uom_qty': 1.00,
|
||||
'product_uos_qty': self.pool.get('stock.move').onchange_quantity(cr, uid, ids, prod_id, 1.00, product.uom_id.id, uos_id)['value']['product_uos_qty'],
|
||||
}
|
||||
if not ids:
|
||||
result['name'] = product.partner_ref
|
||||
if loc_id:
|
||||
result['location_id'] = loc_id
|
||||
if loc_dest_id:
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "EntypoRegular";
|
||||
src: url("/web/static/src/font/entypo-webfont.eot") format("eot");
|
||||
|
@ -1264,6 +1263,9 @@
|
|||
.openerp .oe_view_manager_inline > .oe_view_manager_header, .openerp .oe_view_manager_inlineview > .oe_view_manager_header {
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_popup_form {
|
||||
display: table;
|
||||
}
|
||||
.openerp .oe_popup_form .oe_formview .oe_form_pager {
|
||||
display: none !important;
|
||||
}
|
||||
|
@ -2994,7 +2996,6 @@
|
|||
top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.kitten-mode-activated {
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
|
|
|
@ -1071,6 +1071,7 @@ $sheet-padding: 16px
|
|||
// }}}
|
||||
// FormPopup {{{
|
||||
.oe_popup_form
|
||||
display: table
|
||||
.oe_formview .oe_form_pager
|
||||
display: none !important
|
||||
// Customize label weight for popup wizard appear from another wizard according bootstrap3
|
||||
|
|
|
@ -5714,6 +5714,20 @@ instance.web.form.FieldBinaryImage = instance.web.form.FieldBinary.extend({
|
|||
this._super.apply(this, arguments);
|
||||
this.render_value();
|
||||
this.set_filename('');
|
||||
},
|
||||
set_value: function(value_){
|
||||
var changed = value_ !== this.get_value();
|
||||
this._super.apply(this, arguments);
|
||||
// By default, on binary images read, the server returns the binary size
|
||||
// This is possible that two images have the exact same size
|
||||
// Therefore we trigger the change in case the image value hasn't changed
|
||||
// So the image is re-rendered correctly
|
||||
if (!changed){
|
||||
this.trigger("change:value", this, {
|
||||
oldValue: value_,
|
||||
newValue: value_
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
// ----------------------------------------------------------------------
|
||||
// this.measures: list of measure [measure], measure = {field: _, string: _, type: _}
|
||||
// this.rows.groupby, this.cols.groupby : list of groupbys used for describing rows (...),
|
||||
// a groupby is also {field:_, string:_, type:_}
|
||||
// a groupby is also {field:_, string:_, type:_}
|
||||
// If its type is date/datetime, field can have the corresponding interval in its description,
|
||||
// for example 'create_date:week'.
|
||||
set_measures: function (measures) {
|
||||
|
@ -65,7 +65,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
}
|
||||
var row_gb_changed = !_.isEqual(row_groupby, this.rows.groupby),
|
||||
col_gb_changed = !_.isEqual(col_groupby, this.cols.groupby);
|
||||
|
||||
|
||||
this.domain = domain;
|
||||
this.rows.groupby = row_groupby;
|
||||
this.cols.groupby = col_groupby;
|
||||
|
@ -80,7 +80,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
// Cells manipulation methods
|
||||
// ----------------------------------------------------------------------
|
||||
// cells are objects {x:_, y:_, values:_} where x < y and values is an array
|
||||
// of values (one for each measure). The condition x < y might look
|
||||
// of values (one for each measure). The condition x < y might look
|
||||
// unnecessary, but it makes the rest of the code simpler: headers
|
||||
// don't krow if they are rows or cols, they just know their id, so
|
||||
// it is useful that a call get_values(id1, id2) is the same as get_values(id2, id1)
|
||||
|
@ -103,9 +103,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
// ----------------------------------------------------------------------
|
||||
// Headers/Rows/Cols manipulation methods
|
||||
// ----------------------------------------------------------------------
|
||||
// this.rows.headers, this.cols.headers = [header] describe the tree structure
|
||||
// this.rows.headers, this.cols.headers = [header] describe the tree structure
|
||||
// of rows/cols. Headers are objects
|
||||
// {
|
||||
// {
|
||||
// id:_, (unique id obviously)
|
||||
// path: [...], (array of all parents title, with its own title at the end)
|
||||
// title:_, (name of the row/col)
|
||||
|
@ -150,12 +150,12 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
get_rows_leaves: function () {
|
||||
return _.where(this.rows.headers, {expanded:false});
|
||||
},
|
||||
|
||||
|
||||
// return all non expanded cols
|
||||
get_cols_leaves: function () {
|
||||
return _.where(this.cols.headers, {expanded:false});
|
||||
},
|
||||
|
||||
|
||||
get_ancestors: function (header) {
|
||||
var self = this;
|
||||
if (!header.children) return [];
|
||||
|
@ -181,7 +181,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
},
|
||||
|
||||
main_row: function () { return this.rows.headers[0]; },
|
||||
|
||||
|
||||
main_col: function () { return this.cols.headers[0]; },
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
@ -255,7 +255,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
// Data updating methods
|
||||
// ----------------------------------------------------------------------
|
||||
// update_data will try to preserve the expand/not expanded status of each
|
||||
// column/row. If you want to expand all, then set this.cols.headers/this.rows.headers
|
||||
// column/row. If you want to expand all, then set this.cols.headers/this.rows.headers
|
||||
// to null before calling update_data.
|
||||
update_data: function () {
|
||||
var self = this;
|
||||
|
@ -289,7 +289,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
data_pts.forEach(function (data_pt) {
|
||||
var row_value = (prefix || []).concat(data_pt.attributes.value.slice(0,index));
|
||||
var col_value = data_pt.attributes.value.slice(index);
|
||||
|
||||
|
||||
if (expand && !_.find(col_headers, function (hdr) {return self.isEqual(col_value, hdr.path);})) {
|
||||
return;
|
||||
}
|
||||
|
@ -427,6 +427,10 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
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');
|
||||
}
|
||||
return attrs.value[i];
|
||||
});
|
||||
|
@ -445,8 +449,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({
|
|||
isEqual: function (path1, path2) {
|
||||
if (path1.length !== path2.length) { return false; }
|
||||
for (var i = 0; i < path1.length; i++) {
|
||||
if (path1[i] !== path2[i]) {
|
||||
return false;
|
||||
if (path1[i] !== path2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -308,6 +308,9 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
|
|||
self.do_clear_groups();
|
||||
self.dataset.read_slice(self.fields_keys.concat(['__last_update']), { 'limit': self.limit }).done(function(records) {
|
||||
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;
|
||||
}
|
||||
self.do_add_groups([kgroup]).done(function() {
|
||||
if (_.isEmpty(records)) {
|
||||
self.no_result();
|
||||
|
@ -429,8 +432,8 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
|
|||
stop: function(event, ui) {
|
||||
var stop_index = ui.item.index();
|
||||
if (start_index !== stop_index) {
|
||||
var $start_column = $('.oe_kanban_groups_records .oe_kanban_column').eq(start_index);
|
||||
var $stop_column = $('.oe_kanban_groups_records .oe_kanban_column').eq(stop_index);
|
||||
var $start_column = self.$('.oe_kanban_groups_records .oe_kanban_column').eq(start_index);
|
||||
var $stop_column = self.$('.oe_kanban_groups_records .oe_kanban_column').eq(stop_index);
|
||||
var method = (start_index > stop_index) ? 'insertBefore' : 'insertAfter';
|
||||
$start_column[method]($stop_column);
|
||||
var tmp_group = self.groups.splice(start_index, 1)[0];
|
||||
|
@ -1152,7 +1155,7 @@ instance.web_kanban.KanbanRecord = instance.web.Widget.extend({
|
|||
*/
|
||||
instance.web_kanban.QuickCreate = instance.web.Widget.extend({
|
||||
template: 'KanbanView.quick_create',
|
||||
|
||||
|
||||
/**
|
||||
* close_btn: If true, the widget will display a "Close" button able to trigger
|
||||
* a "close" event.
|
||||
|
|
|
@ -359,14 +359,12 @@ class Website(openerp.addons.web.controllers.main.Home):
|
|||
@http.route(['/website/seo_suggest/<keywords>'], type='http', auth="public", website=True)
|
||||
def seo_suggest(self, keywords):
|
||||
url = "http://google.com/complete/search"
|
||||
param = {
|
||||
'ie': 'utf8',
|
||||
'oe': 'utf8',
|
||||
'output': 'toolbar',
|
||||
'q': keywords
|
||||
}
|
||||
req = urllib2.Request("%s?%s" % (url, werkzeug.url_encode(param)))
|
||||
request = urllib2.urlopen(req)
|
||||
try:
|
||||
req = urllib2.Request("%s?%s" % (url, werkzeug.url_encode({
|
||||
'ie': 'utf8', 'oe': 'utf8', 'output': 'toolbar', 'q': keywords})))
|
||||
request = urllib2.urlopen(req)
|
||||
except (urllib2.HTTPError, urllib2.URLError):
|
||||
return []
|
||||
xmlroot = ET.fromstring(request.read())
|
||||
return json.dumps([sugg[0].attrib['data'] for sugg in xmlroot if len(sugg) and sugg[0].attrib['data']])
|
||||
|
||||
|
@ -399,10 +397,15 @@ class Website(openerp.addons.web.controllers.main.Home):
|
|||
The requested field is assumed to be base64-encoded image data in
|
||||
all cases.
|
||||
"""
|
||||
response = werkzeug.wrappers.Response()
|
||||
return request.registry['website']._image(
|
||||
request.cr, request.uid, model, id, field, response, max_width, max_height)
|
||||
|
||||
try:
|
||||
response = werkzeug.wrappers.Response()
|
||||
return request.registry['website']._image(
|
||||
request.cr, request.uid, model, id, field, response, max_width, max_height)
|
||||
except Exception:
|
||||
logger.exception("Cannot render image field %r of record %s[%s] at size(%s,%s)",
|
||||
field, model, id, max_width, max_height)
|
||||
response = werkzeug.wrappers.Response()
|
||||
return self.placeholder(response)
|
||||
|
||||
#------------------------------------------------------
|
||||
# Server actions
|
||||
|
|
|
@ -546,10 +546,8 @@ class website(osv.osv):
|
|||
response.mimetype = Image.MIME[image.format]
|
||||
|
||||
w, h = image.size
|
||||
try:
|
||||
max_w, max_h = int(max_width), int(max_height)
|
||||
except:
|
||||
max_w, max_h = (maxint, maxint)
|
||||
max_w = int(max_width) if max_width else maxint
|
||||
max_h = int(max_height) if max_height else maxint
|
||||
|
||||
if w < max_w and h < max_h:
|
||||
response.data = data
|
||||
|
|
|
@ -99,10 +99,10 @@
|
|||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','_gaw');
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
_gaw('create',_.str.trim('<t t-esc="website.google_analytics_key"/>'));
|
||||
_gaw('send','pageview');
|
||||
ga('create',_.str.trim('<t t-esc="website.google_analytics_key"/>'));
|
||||
ga('send','pageview');
|
||||
</script>
|
||||
</t>
|
||||
</head>
|
||||
|
@ -651,7 +651,6 @@
|
|||
<div class="oe_structure">
|
||||
<h1 class="container mt32"><t t-esc="status_code"/>: <t t-esc="status_message"/></h1>
|
||||
</div>
|
||||
|
||||
<div class="container" t-if="views">
|
||||
<div class="alert alert-danger" t-if="qweb_exception and editable">
|
||||
<h4>Template fallback</h4>
|
||||
|
|
|
@ -64,11 +64,14 @@ class sale_quote_line(osv.osv):
|
|||
def on_change_product_id(self, cr, uid, ids, product, context=None):
|
||||
vals = {}
|
||||
product_obj = self.pool.get('product.product').browse(cr, uid, product, context=context)
|
||||
name = product_obj.name
|
||||
if product_obj.description_sale:
|
||||
name += '\n' + product_obj.description_sale
|
||||
vals.update({
|
||||
'price_unit': product_obj.list_price,
|
||||
'product_uom_id': product_obj.uom_id.id,
|
||||
'website_description': product_obj.website_description,
|
||||
'name': product_obj.name,
|
||||
'name': name,
|
||||
})
|
||||
return {'value': vals}
|
||||
|
||||
|
|
|
@ -24,9 +24,14 @@ import time
|
|||
import psycopg2
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import pytz
|
||||
|
||||
import openerp
|
||||
<<<<<<< HEAD
|
||||
from openerp import SUPERUSER_ID, netsvc, api
|
||||
=======
|
||||
from openerp import netsvc, SUPERUSER_ID
|
||||
>>>>>>> 0739bc4edabab7e74571087c01a2da68ccadb10e
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.tools.safe_eval import safe_eval as eval
|
||||
|
@ -159,8 +164,8 @@ class ir_cron(osv.osv):
|
|||
"""
|
||||
try:
|
||||
with api.Environment.manage():
|
||||
now = datetime.now()
|
||||
nextcall = datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
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))
|
||||
numbercall = job['numbercall']
|
||||
|
||||
ok = False
|
||||
|
@ -176,7 +181,7 @@ class ir_cron(osv.osv):
|
|||
if not numbercall:
|
||||
addsql = ', active=False'
|
||||
cron_cr.execute("UPDATE ir_cron SET nextcall=%s, numbercall=%s"+addsql+" WHERE id=%s",
|
||||
(nextcall.strftime(DEFAULT_SERVER_DATETIME_FORMAT), numbercall, job['id']))
|
||||
(nextcall.astimezone(pytz.UTC).strftime(DEFAULT_SERVER_DATETIME_FORMAT), numbercall, job['id']))
|
||||
self.invalidate_cache(cr, SUPERUSER_ID)
|
||||
|
||||
finally:
|
||||
|
|
|
@ -192,7 +192,9 @@ class rml_parse(object):
|
|||
elif (hasattr(obj, '_field') and\
|
||||
isinstance(obj._field, (float_field, function_field)) and\
|
||||
obj._field.digits):
|
||||
d = obj._field.digits[1] or DEFAULT_DIGITS
|
||||
d = obj._field.digits[1]
|
||||
if not d and d is not 0:
|
||||
d = DEFAULT_DIGITS
|
||||
return d
|
||||
|
||||
def formatLang(self, value, digits=None, date=False, date_time=False, grouping=True, monetary=False, dp=False, currency_obj=False):
|
||||
|
|
|
@ -461,16 +461,15 @@ class YamlInterpreter(object):
|
|||
result = getattr(model, match.group(1))(self.cr, SUPERUSER_ID, [], *args)
|
||||
|
||||
for key, val in (result or {}).get('value', {}).items():
|
||||
assert key in fg, (
|
||||
"The field %r returned from the onchange call %r "
|
||||
"does not exist in the source view %r (of object "
|
||||
"%r). This field will be ignored (and thus not "
|
||||
"populated) when clients saves the new record" % (
|
||||
key, match.group(1), view_info.get('name', '?'), model._name
|
||||
))
|
||||
if key not in fields:
|
||||
# do not shadow values explicitly set in yaml.
|
||||
record_dict[key] = process_val(key, val)
|
||||
if key in fg:
|
||||
if key not in fields:
|
||||
# do not shadow values explicitly set in yaml.
|
||||
record_dict[key] = process_val(key, val)
|
||||
else:
|
||||
_logger.debug("The returning field '%s' from your on_change call '%s'"
|
||||
" does not exist either on the object '%s', either in"
|
||||
" the view '%s'",
|
||||
key, match.group(1), model._name, view_info['name'])
|
||||
else:
|
||||
nodes = list(el) + nodes
|
||||
else:
|
||||
|
|
Loading…
Reference in New Issue