summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2015-06-18 19:41:31 +0200
committerChristophe Simonis <chs@odoo.com>2015-06-18 19:41:31 +0200
commit13468c271f47f694149dac1adcdf06b2e90db752 (patch)
tree774c26f2c8bb68f62d2d8cf6f3c0441f3c8de284 /addons
parent1b7c49bf1e0843c1d11c856ef5474ebfc2c261d1 (diff)
parented3065e3c6613162513638945e760f686fea2b55 (diff)
[MERGE] forward port of branch 8.0 up to ed3065e
Diffstat (limited to 'addons')
-rw-r--r--addons/account/account_invoice.py4
-rw-r--r--addons/account/views/report_vat.xml2
-rw-r--r--addons/auth_signup/controllers/main.py1
-rw-r--r--addons/calendar/calendar.py10
-rw-r--r--addons/l10n_be/l10n_be_sequence.xml1
-rw-r--r--addons/mail/mail_thread.py21
-rw-r--r--addons/membership/membership_view.xml3
-rw-r--r--addons/mrp/mrp.py4
-rw-r--r--addons/point_of_sale/point_of_sale.py20
-rw-r--r--addons/point_of_sale/point_of_sale_demo.xml112
-rw-r--r--addons/point_of_sale/static/img/partners/acsone.pngbin0 -> 24970 bytes
-rw-r--r--addons/point_of_sale/static/img/partners/bhc.jpgbin0 -> 21618 bytes
-rw-r--r--addons/point_of_sale/static/img/partners/camptocamp.pngbin0 -> 25879 bytes
-rw-r--r--addons/point_of_sale/static/img/partners/datalp.jpgbin0 -> 53998 bytes
-rw-r--r--addons/point_of_sale/static/img/partners/eezee-it.pngbin0 -> 29984 bytes
-rw-r--r--addons/point_of_sale/static/img/partners/eggs-solutions.jpgbin0 -> 33740 bytes
-rw-r--r--addons/point_of_sale/static/img/partners/ekomurz.gifbin0 -> 1820 bytes
-rw-r--r--addons/point_of_sale/static/img/partners/openbig.jpgbin0 -> 18401 bytes
-rw-r--r--addons/point_of_sale/static/img/partners/opusvl.pngbin0 -> 8265 bytes
-rw-r--r--addons/point_of_sale/static/img/partners/services.jpgbin0 -> 24486 bytes
-rw-r--r--addons/point_of_sale/static/img/partners/vauxoo.pngbin0 -> 9121 bytes
-rw-r--r--addons/product/product.py27
-rw-r--r--addons/purchase/purchase.py8
-rw-r--r--addons/sale/sale.py11
-rw-r--r--addons/stock/stock.py23
-rw-r--r--addons/stock_account/wizard/stock_valuation_history.py40
-rw-r--r--addons/web/controllers/main.py8
-rw-r--r--addons/web/static/src/css/base.css4
-rw-r--r--addons/web/static/src/css/base.sass4
-rw-r--r--addons/website_forum/controllers/main.py2
-rw-r--r--addons/website_sale/controllers/main.py5
-rw-r--r--addons/website_sale/models/sale_order.py3
-rw-r--r--addons/website_sale_delivery/models/sale_order.py12
33 files changed, 248 insertions, 77 deletions
diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py
index 9e8bcd330c2..215a9eccec0 100644
--- a/addons/account/account_invoice.py
+++ b/addons/account/account_invoice.py
@@ -1326,9 +1326,9 @@ class account_invoice_line(models.Model):
raise UserError(_("You must first select a partner!"))
if not product:
if type in ('in_invoice', 'in_refund'):
- return {'value': {}, 'domain': {'product_uom': []}}
+ return {'value': {}, 'domain': {'uos_id': []}}
else:
- return {'value': {'price_unit': 0.0}, 'domain': {'product_uom': []}}
+ return {'value': {'price_unit': 0.0}, 'domain': {'uos_id': []}}
values = {}
diff --git a/addons/account/views/report_vat.xml b/addons/account/views/report_vat.xml
index 1f9a240099f..d29c3038b33 100644
--- a/addons/account/views/report_vat.xml
+++ b/addons/account/views/report_vat.xml
@@ -39,7 +39,7 @@
</tr>
</thead>
<tbody>
- <tr t-foreach="get_lines(data['form']['based_on'], data['form']['company_id'])" t-as="taxline">
+ <tr t-foreach="get_lines(data['form']['based_on'], data['form']['company_id'], data['form']['chart_tax_id'])" t-as="taxline">
<t t-if="len(taxline['level']) > 5">
<t t-set="style" t-value="'font-weight:normal;'"/>
</t>
diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py
index 09d5b324370..849293ce1e9 100644
--- a/addons/auth_signup/controllers/main.py
+++ b/addons/auth_signup/controllers/main.py
@@ -114,6 +114,7 @@ class AuthSignupHome(openerp.addons.web.controllers.main.Home):
values = dict((key, qcontext.get(key)) for key in ('login', 'name', 'password'))
assert any([k for k in values.values()]), "The form was not properly filled in."
assert values.get('password') == qcontext.get('confirm_password'), "Passwords do not match; please retype them."
+ values['lang'] = request.lang
self._signup_with_values(qcontext.get('token'), values)
request.cr.commit()
diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py
index 4bcd2e58905..e8b56ef7f0c 100644
--- a/addons/calendar/calendar.py
+++ b/addons/calendar/calendar.py
@@ -657,18 +657,18 @@ class ir_model(osv.Model):
original_exp_report = openerp.service.report.exp_report
-def exp_report(db, uid, object, ids, data=None, context=None):
+def exp_report(db, uid, object, ids, datas=None, context=None):
"""
Export Report
"""
if object == 'printscreen.list':
- original_exp_report(db, uid, object, ids, data, context)
+ original_exp_report(db, uid, object, ids, datas, context)
new_ids = []
for id in ids:
new_ids.append(calendar_id2real_id(id))
- if data.get('id', False):
- data['id'] = calendar_id2real_id(data['id'])
- return original_exp_report(db, uid, object, new_ids, data, context)
+ if datas.get('id', False):
+ datas['id'] = calendar_id2real_id(datas['id'])
+ return original_exp_report(db, uid, object, new_ids, datas, context)
openerp.service.report.exp_report = exp_report
diff --git a/addons/l10n_be/l10n_be_sequence.xml b/addons/l10n_be/l10n_be_sequence.xml
index f6a9bcec651..8ce7eef4239 100644
--- a/addons/l10n_be/l10n_be_sequence.xml
+++ b/addons/l10n_be/l10n_be_sequence.xml
@@ -8,6 +8,7 @@
<field name="name">Declarantnum</field>
<field name="code">declarantnum</field>
<field name="padding">5</field>
+ <field name="company_id" eval="False"/>
</record>
</data>
diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py
index 2a7529759ea..48cf100e578 100644
--- a/addons/mail/mail_thread.py
+++ b/addons/mail/mail_thread.py
@@ -388,13 +388,6 @@ class mail_thread(osv.AbstractModel):
name = ir_model_pool.read(cr, uid, ids, ['name'], context=context)[0]['name']
self.message_post(cr, uid, thread_id, body=_('%s created') % name, context=context)
- # auto_subscribe: take values and defaults into account
- create_values = dict(values)
- for key, val in context.iteritems():
- if key.startswith('default_') and key[8:] not in create_values:
- create_values[key[8:]] = val
- self.message_auto_subscribe(cr, uid, [thread_id], create_values.keys(), context=context, values=create_values)
-
# track values
track_ctx = dict(context)
if 'lang' not in track_ctx:
@@ -404,6 +397,14 @@ class mail_thread(osv.AbstractModel):
if tracked_fields:
initial_values = {thread_id: dict.fromkeys(tracked_fields, False)}
self.message_track(cr, uid, [thread_id], tracked_fields, initial_values, context=track_ctx)
+
+ # auto_subscribe: take values and defaults into account
+ create_values = dict(values)
+ for key, val in context.iteritems():
+ if key.startswith('default_') and key[8:] not in create_values:
+ create_values[key[8:]] = val
+ self.message_auto_subscribe(cr, uid, [thread_id], create_values.keys(), context=context, values=create_values)
+
return thread_id
def write(self, cr, uid, ids, values, context=None):
@@ -428,14 +429,16 @@ class mail_thread(osv.AbstractModel):
initial_values = dict((record.id, dict((key, getattr(record, key)) for key in tracked_fields))
for record in records)
- # Perform write, update followers
+ # Perform write
result = super(mail_thread, self).write(cr, uid, ids, values, context=context)
- self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context, values=values)
# Perform the tracking
if tracked_fields:
self.message_track(cr, uid, ids, tracked_fields, initial_values, context=track_ctx)
+ # update followers
+ self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context, values=values)
+
return result
def unlink(self, cr, uid, ids, context=None):
diff --git a/addons/membership/membership_view.xml b/addons/membership/membership_view.xml
index 0267ae88cb3..0a1949fa12c 100644
--- a/addons/membership/membership_view.xml
+++ b/addons/membership/membership_view.xml
@@ -157,7 +157,8 @@
<field name="priority">50</field>
<field name="arch" type="xml">
<search string="Membership Partners">
- <field name="name" string="Members"/>
+ <field name="name"
+ filter_domain="['|','|',('name','ilike',self),('parent_id','ilike',self),('ref','=',self)]"/>
<field name="category_id"/>
<field name="membership_start" invisible="1"/>
<field name="membership_stop" string="End Membership Date"/>
diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py
index 851f7368497..8145f0f1542 100644
--- a/addons/mrp/mrp.py
+++ b/addons/mrp/mrp.py
@@ -975,7 +975,7 @@ class mrp_production(osv.osv):
location_id=produce_product.location_id.id, restrict_lot_id=lot_id, context=context)
stock_mov_obj.write(cr, uid, new_moves, {'production_id': production_id}, context=context)
remaining_qty = subproduct_factor * production_qty_uom - qty
- if not float_is_zero(remaining_qty, precision_rounding=precision):
+ if not float_is_zero(remaining_qty, precision_digits=precision):
# In case you need to make more than planned
#consumed more in wizard than previously planned
extra_move_id = stock_mov_obj.copy(cr, uid, produce_product.id, default={'product_uom_qty': remaining_qty,
@@ -1006,7 +1006,7 @@ class mrp_production(osv.osv):
stock_mov_obj.action_consume(cr, uid, [raw_material_line.id], consumed_qty, raw_material_line.location_id.id,
restrict_lot_id=consume['lot_id'], consumed_for=main_production_move, context=context)
remaining_qty -= consumed_qty
- if not float_is_zero(remaining_qty, precision_rounding=precision):
+ if not float_is_zero(remaining_qty, precision_digits=precision):
#consumed more in wizard than previously planned
product = self.pool.get('product.product').browse(cr, uid, consume['product_id'], context=context)
extra_move_id = self._make_consume_line_from_data(cr, uid, production, product, product.uom_id.id, remaining_qty, False, 0, context=context)
diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py
index a84b12a70f3..09ca3903d96 100644
--- a/addons/point_of_sale/point_of_sale.py
+++ b/addons/point_of_sale/point_of_sale.py
@@ -576,6 +576,16 @@ class pos_order(osv.osv):
_description = "Point of Sale"
_order = "id desc"
+ def _amount_line_tax(self, cr, uid, line, context=None):
+ account_tax_obj = self.pool['account.tax']
+ taxes_ids = [tax for tax in line.product_id.taxes_id if tax.company_id.id == line.order_id.company_id.id]
+ price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
+ taxes = account_tax_obj.compute_all(cr, uid, taxes_ids, price, line.qty, product=line.product_id, partner=line.order_id.partner_id or False)['taxes']
+ val = 0.0
+ for c in taxes:
+ val += c.get('amount', 0.0)
+ return val
+
def _order_fields(self, cr, uid, ui_order, context=None):
process_line = partial(self.pool['pos.order.line']._order_line_fields, cr, uid, context=context)
return {
@@ -695,10 +705,10 @@ class pos_order(osv.osv):
res[order.id]['amount_paid'] += payment.amount
res[order.id]['amount_return'] += (payment.amount < 0 and payment.amount or 0)
for line in order.lines:
- val1 += line.price_subtotal_incl
+ val1 += self._amount_line_tax(cr, uid, line, context=context)
val2 += line.price_subtotal
- res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val1-val2)
- res[order.id]['amount_total'] = cur_obj.round(cr, uid, cur, val1)
+ res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val1)
+ res[order.id]['amount_total'] = cur_obj.round(cr, uid, cur, val1+val2)
return res
_columns = {
@@ -1321,8 +1331,8 @@ class pos_order_line(osv.osv):
taxes = account_tax_obj.compute_all(cr, uid, taxes_ids, price, line.qty, product=line.product_id, partner=line.order_id.partner_id or False)
cur = line.order_id.pricelist_id.currency_id
- res[line.id]['price_subtotal'] = cur_obj.round(cr, uid, cur, taxes['total'])
- res[line.id]['price_subtotal_incl'] = cur_obj.round(cr, uid, cur, taxes['total_included'])
+ res[line.id]['price_subtotal'] = taxes['total']
+ res[line.id]['price_subtotal_incl'] = taxes['total_included']
return res
def onchange_product_id(self, cr, uid, ids, pricelist, product_id, qty=0, partner_id=False, context=None):
diff --git a/addons/point_of_sale/point_of_sale_demo.xml b/addons/point_of_sale/point_of_sale_demo.xml
index d176c9ff060..32a02f48357 100644
--- a/addons/point_of_sale/point_of_sale_demo.xml
+++ b/addons/point_of_sale/point_of_sale_demo.xml
@@ -65,6 +65,10 @@
<field name="name">Food</field>
<field name="image" type="base64" file="point_of_sale/static/img/food-image.jpg"/>
</record>
+ <record id="partner_services" model="pos.category">
+ <field name="name">Partner Services</field>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/services.jpg"/>
+ </record>
<record id="fruits" model="pos.category">
<field name="name">Fresh Fruits</field>
<field name="image" type="base64" file="point_of_sale/static/img/fruits-image.jpg"/>
@@ -1085,6 +1089,114 @@
<field name="pos_categ_id" ref="food"/>
<field name="image" type="base64" file="point_of_sale/static/img/ijsboerke_dame_blanche_2,5l-image.jpg"/>
</record>
+
+ <record id="partner_product_1" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">850.00</field>
+ <field name="name">Odoo Start Workshop</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/openbig.jpg"/>
+ </record>
+
+ <record id="partner_product_2" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">999.99</field>
+ <field name="name">Odoo Consulting</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/bhc.jpg"/>
+ </record>
+
+ <record id="partner_product_3" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">999.99</field>
+ <field name="name">Eezee-It</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/eezee-it.png"/>
+ </record>
+
+ <record id="partner_product_4" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">999.99</field>
+ <field name="name">Ekomurz.nl</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/ekomurz.gif"/>
+ </record>
+
+ <record id="partner_product_5" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">999.99</field>
+ <field name="name">Acsone.eu</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/acsone.png"/>
+ </record>
+
+ <record id="partner_product_6" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">999.99</field>
+ <field name="name">Vauxoo.com</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/vauxoo.png"/>
+ </record>
+
+ <record id="partner_product_7" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">999.99</field>
+ <field name="name">Datalp.com</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/datalp.jpg"/>
+ </record>
+
+ <record id="partner_product_8" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">999.99</field>
+ <field name="name">camptocamp.com</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/camptocamp.png"/>
+ </record>
+
+ <record id="partner_product_9" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">999.99</field>
+ <field name="name">EGGS-solutions.fr</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/eggs-solutions.jpg"/>
+ </record>
+
+ <record id="partner_product_10" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">3500.00</field>
+ <field name="name">Odoo primary scoping &amp; analysis package (£900, £450, £30)</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/opusvl.png"/>
+ </record>
+
+ <record id="partner_product_11" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">900.00</field>
+ <field name="name">3rd party system analysis</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/opusvl.png"/>
+ </record>
+
+ <record id="partner_product_12" model="product.product">
+ <field name="available_in_pos">True</field>
+ <field name="list_price">30.00</field>
+ <field name="name">Odoo enterprise agreement</field>
+ <field name="type">service</field>
+ <field name="pos_categ_id" ref="partner_services"/>
+ <field name="image" type="base64" file="point_of_sale/static/img/partners/opusvl.png"/>
+ </record>
+
<!-- The electronic products shouldn't be present in the point of sale for the demo -->
diff --git a/addons/point_of_sale/static/img/partners/acsone.png b/addons/point_of_sale/static/img/partners/acsone.png
new file mode 100644
index 00000000000..f6ec989338e
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/acsone.png
Binary files differ
diff --git a/addons/point_of_sale/static/img/partners/bhc.jpg b/addons/point_of_sale/static/img/partners/bhc.jpg
new file mode 100644
index 00000000000..30005451d2a
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/bhc.jpg
Binary files differ
diff --git a/addons/point_of_sale/static/img/partners/camptocamp.png b/addons/point_of_sale/static/img/partners/camptocamp.png
new file mode 100644
index 00000000000..0cb138e1ceb
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/camptocamp.png
Binary files differ
diff --git a/addons/point_of_sale/static/img/partners/datalp.jpg b/addons/point_of_sale/static/img/partners/datalp.jpg
new file mode 100644
index 00000000000..9ef1f913c9a
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/datalp.jpg
Binary files differ
diff --git a/addons/point_of_sale/static/img/partners/eezee-it.png b/addons/point_of_sale/static/img/partners/eezee-it.png
new file mode 100644
index 00000000000..2e975e5a9b6
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/eezee-it.png
Binary files differ
diff --git a/addons/point_of_sale/static/img/partners/eggs-solutions.jpg b/addons/point_of_sale/static/img/partners/eggs-solutions.jpg
new file mode 100644
index 00000000000..b15656b0578
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/eggs-solutions.jpg
Binary files differ
diff --git a/addons/point_of_sale/static/img/partners/ekomurz.gif b/addons/point_of_sale/static/img/partners/ekomurz.gif
new file mode 100644
index 00000000000..73905684838
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/ekomurz.gif
Binary files differ
diff --git a/addons/point_of_sale/static/img/partners/openbig.jpg b/addons/point_of_sale/static/img/partners/openbig.jpg
new file mode 100644
index 00000000000..88be89bfbbd
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/openbig.jpg
Binary files differ
diff --git a/addons/point_of_sale/static/img/partners/opusvl.png b/addons/point_of_sale/static/img/partners/opusvl.png
new file mode 100644
index 00000000000..7d7ab158331
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/opusvl.png
Binary files differ
diff --git a/addons/point_of_sale/static/img/partners/services.jpg b/addons/point_of_sale/static/img/partners/services.jpg
new file mode 100644
index 00000000000..915f21fc0c4
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/services.jpg
Binary files differ
diff --git a/addons/point_of_sale/static/img/partners/vauxoo.png b/addons/point_of_sale/static/img/partners/vauxoo.png
new file mode 100644
index 00000000000..be52bd1f444
--- /dev/null
+++ b/addons/point_of_sale/static/img/partners/vauxoo.png
Binary files differ
diff --git a/addons/product/product.py b/addons/product/product.py
index d8af26f83a3..6e28ab26c0b 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -25,8 +25,7 @@ import time
from _common import ceiling
-from openerp import SUPERUSER_ID
-from openerp import tools
+from openerp import api, tools, SUPERUSER_ID
from openerp.osv import osv, fields, expression
from openerp.tools.translate import _
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
@@ -225,19 +224,17 @@ class product_ul(osv.osv):
#----------------------------------------------------------
class product_category(osv.osv):
- def name_get(self, cr, uid, ids, context=None):
- if isinstance(ids, (list, tuple)) and not len(ids):
- return []
- if isinstance(ids, (long, int)):
- ids = [ids]
- reads = self.read(cr, uid, ids, ['name','parent_id'], context=context)
- res = []
- for record in reads:
- name = record['name']
- if record['parent_id']:
- name = record['parent_id'][1]+' / '+name
- res.append((record['id'], name))
- return res
+ @api.multi
+ def name_get(self):
+ def get_names(cat):
+ """ Return the list [cat.name, cat.parent_id.name, ...] """
+ res = []
+ while cat:
+ res.append(cat.name)
+ cat = cat.parent_id
+ return res
+
+ return [(cat.id, " / ".join(reversed(get_names(cat)))) for cat in self]
def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
if not args:
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 465b54a297f..aa6816c6b13 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -1259,8 +1259,12 @@ class procurement_order(osv.osv):
return super(procurement_order, self).run(cr, uid, list(set_others), context=context)
def _check(self, cr, uid, procurement, context=None):
- if procurement.purchase_line_id and procurement.purchase_line_id.order_id.shipped: # TOCHECK: does it work for several deliveries?
- return True
+ if procurement.purchase_line_id:
+ if procurement.purchase_line_id.order_id.shipped:
+ return True
+ elif procurement.move_ids:
+ moves = self.pool.get('stock.move').browse(cr, uid, [x.id for x in procurement.move_ids], context=context)
+ return all(move.state == 'done' for move in moves)
return super(procurement_order, self)._check(cr, uid, procurement, context=context)
def _check_supplier_info(self, cr, uid, ids, context=None):
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index b7ca0e79a6b..1515e2cd02b 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -295,12 +295,11 @@ class sale_order(osv.osv):
def onchange_delivery_id(self, cr, uid, ids, company_id, partner_id, delivery_id, fiscal_position, context=None):
r = {'value': {}}
- if not fiscal_position:
- if not company_id:
- company_id = self._get_default_company(cr, uid, context=context)
- fiscal_position = self.pool['account.fiscal.position'].get_fiscal_position(cr, uid, company_id, partner_id, delivery_id, context=context)
- if fiscal_position:
- r['value']['fiscal_position'] = fiscal_position
+ if not company_id:
+ company_id = self._get_default_company(cr, uid, context=context)
+ fiscal_position = self.pool['account.fiscal.position'].get_fiscal_position(cr, uid, company_id, partner_id, delivery_id, context=context)
+ if fiscal_position:
+ r['value']['fiscal_position'] = fiscal_position
return r
def onchange_partner_id(self, cr, uid, ids, part, context=None):
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index a4a03af3822..f5e10c45d0d 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -1952,7 +1952,7 @@ class stock_move(osv.osv):
self.write(cr, uid, [move.id], {'state': 'confirmed'}, context=context)
def _prepare_procurement_from_move(self, cr, uid, move, context=None):
- origin = (move.group_id and (move.group_id.name + ":") or "") + (move.rule_id and move.rule_id.name or move.origin or "/")
+ origin = (move.group_id and (move.group_id.name + ":") or "") + (move.rule_id and move.rule_id.name or move.origin or move.picking_id.name or "/")
group_id = move.group_id and move.group_id.id or False
if move.rule_id:
if move.rule_id.group_propagation_option == 'fixed' and move.rule_id.group_id:
@@ -2155,6 +2155,19 @@ class stock_move(osv.osv):
result['location_dest_id'] = loc_dest_id
return {'value': result}
+ def _prepare_picking_assign(self, cr, uid, move, context=None):
+ """ Prepares a new picking for this move as it could not be assigned to
+ another picking. This method is designed to be inherited.
+ """
+ values = {
+ 'origin': move.origin,
+ 'company_id': move.company_id and move.company_id.id or False,
+ 'move_type': move.group_id and move.group_id.move_type or 'direct',
+ 'partner_id': move.partner_id.id or False,
+ 'picking_type_id': move.picking_type_id and move.picking_type_id.id or False,
+ }
+ return values
+
@api.cr_uid_ids_context
def _picking_assign(self, cr, uid, move_ids, procurement_group, location_from, location_to, context=None):
"""Assign a picking on the given move_ids, which is a list of move supposed to share the same procurement_group, location_from and location_to
@@ -2170,13 +2183,7 @@ class stock_move(osv.osv):
pick = picks[0]
else:
move = self.browse(cr, uid, move_ids, context=context)[0]
- values = {
- 'origin': move.origin,
- 'company_id': move.company_id and move.company_id.id or False,
- 'move_type': move.group_id and move.group_id.move_type or 'direct',
- 'partner_id': move.partner_id.id or False,
- 'picking_type_id': move.picking_type_id and move.picking_type_id.id or False,
- }
+ values = self._prepare_picking_assign(cr, uid, move, context=context)
pick = pick_obj.create(cr, uid, values, context=context)
return self.write(cr, uid, move_ids, {'picking_id': pick}, context=context)
diff --git a/addons/stock_account/wizard/stock_valuation_history.py b/addons/stock_account/wizard/stock_valuation_history.py
index a6223b443e4..e1ae51c79eb 100644
--- a/addons/stock_account/wizard/stock_valuation_history.py
+++ b/addons/stock_account/wizard/stock_valuation_history.py
@@ -46,21 +46,39 @@ class stock_history(osv.osv):
if context is None:
context = {}
date = context.get('history_date')
- prod_dict = {}
if 'inventory_value' in fields:
+ group_lines = {}
+ for line in res:
+ domain = line.get('__domain', [])
+ group_lines.setdefault(str(domain), self.search(cr, uid, domain, context=context))
+ line_ids = set()
+ for ids in group_lines.values():
+ for product_id in ids:
+ line_ids.add(product_id)
+ line_ids = list(line_ids)
+ cr.execute('SELECT id, product_id, price_unit_on_quant, company_id, quantity FROM stock_history WHERE id in %s', (tuple(line_ids),))
+ lines_rec = cr.dictfetchall()
+ lines_dict = dict((line['id'], line) for line in lines_rec)
+ product_ids = list(set(line_rec['product_id'] for line_rec in lines_rec))
+ products_rec = self.pool['product.product'].read(cr, uid, product_ids, ['cost_method', 'product_tmpl_id'], context=context)
+ products_dict = dict((product['id'], product) for product in products_rec)
+ cost_method_product_tmpl_ids = list(set(product['product_tmpl_id'][0] for product in products_rec if product['cost_method'] != 'real'))
+ cr.execute('SELECT DISTINCT ON (product_template_id, company_id) product_template_id, company_id, cost FROM product_price_history WHERE product_template_id in %s AND datetime <= %s ORDER BY product_template_id, company_id, datetime DESC', (tuple(cost_method_product_tmpl_ids), date))
+ histories = cr.dictfetchall()
+ histories_dict = {}
+ for history in histories:
+ histories_dict[(history['product_template_id'], history['company_id'])] = history['cost']
for line in res:
- lines = self.search(cr, uid, line.get('__domain', []), context=context)
inv_value = 0.0
- product_tmpl_obj = self.pool.get("product.template")
- lines_rec = self.browse(cr, uid, lines, context=context)
- for line_rec in lines_rec:
- if line_rec.product_id.cost_method == 'real':
- price = line_rec.price_unit_on_quant
+ lines = group_lines.get(str(line.get('__domain', [])))
+ for line_id in lines:
+ line_rec = lines_dict[line_id]
+ product = products_dict[line_rec['product_id']]
+ if product['cost_method'] == 'real':
+ price = line_rec['price_unit_on_quant']
else:
- if not line_rec.product_id.id in prod_dict:
- prod_dict[line_rec.product_id.id] = product_tmpl_obj.get_history_price(cr, uid, line_rec.product_id.product_tmpl_id.id, line_rec.company_id.id, date=date, context=context)
- price = prod_dict[line_rec.product_id.id]
- inv_value += price * line_rec.quantity
+ price = histories_dict.get((product['product_tmpl_id'][0], line_rec['company_id']), 0.0)
+ inv_value += price * line_rec['quantity']
line['inventory_value'] = inv_value
return res
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index d72404e4314..894faec7e51 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -312,12 +312,12 @@ def set_cookie_and_redirect(redirect_url):
def login_redirect():
url = '/web/login?'
- if request.debug:
- url += 'debug&'
+ # built the redirect url, keeping all the query parameters of the url
+ redirect_url = '%s?%s' % (request.httprequest.base_url, werkzeug.urls.url_encode(request.params))
return """<html><head><script>
- window.location = '%sredirect=' + encodeURIComponent(window.location);
+ window.location = '%sredirect=' + encodeURIComponent("%s");
</script></head></html>
- """ % (url,)
+ """ % (url, redirect_url)
def load_actions_from_ir_values(key, key2, models, meta):
Values = request.session.model('ir.values')
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css
index d9c17ea6465..14edf1cf14d 100644
--- a/addons/web/static/src/css/base.css
+++ b/addons/web/static/src/css/base.css
@@ -577,6 +577,7 @@
border-radius: 3px;
background: #f0f0fa;
color: #4C4C4C;
+ word-break: break-word;
}
.openerp .oe_tag_dark {
background: #7C7BAD;
@@ -620,7 +621,8 @@
width: 100% !important;
}
.openerp .oe_tags .text-core {
- min-height: 22px;
+ height: initial !important;
+ word-break: break-word;
}
.openerp .oe_tags .text-core .text-wrap .text-dropdown .text-list .text-suggestion em {
font-style: italic;
diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass
index ac4742f2598..30ff7e83c0e 100644
--- a/addons/web/static/src/css/base.sass
+++ b/addons/web/static/src/css/base.sass
@@ -514,6 +514,7 @@ $sheet-padding: 16px
@include radius(3px)
background: $tag-bg-light
color: #4C4C4C
+ word-break: break-word
.oe_tag_dark
background: $tag-bg-dark
color: #eee
@@ -547,7 +548,8 @@ $sheet-padding: 16px
textarea
width: 100% !important
.text-core
- min-height: 22px
+ height: initial !important
+ word-break: break-word
.text-wrap .text-dropdown .text-list .text-suggestion em
font-style: italic
text-decoration: none
diff --git a/addons/website_forum/controllers/main.py b/addons/website_forum/controllers/main.py
index f1ef56be907..2438767e075 100644
--- a/addons/website_forum/controllers/main.py
+++ b/addons/website_forum/controllers/main.py
@@ -308,7 +308,7 @@ class WebsiteForum(http.Controller):
})
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), post_parent and slug(post_parent) or new_question.id))
- @http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/comment', type='http', auth="public", methods=['POST'], website=True)
+ @http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/comment', type='http', auth="public", website=True)
def post_comment(self, forum, post, **kwargs):
if not request.session.uid:
return login_redirect()
diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index e5232cedff2..54061771cf6 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -280,7 +280,7 @@ class website_sale(http.Controller):
}
return request.website.render("website_sale.product", values)
- @http.route(['/shop/product/comment/<int:product_template_id>'], type='http', auth="public", methods=['POST'], website=True)
+ @http.route(['/shop/product/comment/<int:product_template_id>'], type='http', auth="public", website=True)
def product_comment(self, product_template_id, **post):
if not request.session.uid:
return login_redirect()
@@ -292,7 +292,7 @@ class website_sale(http.Controller):
type='comment',
subtype='mt_comment',
context=dict(context, mail_create_nosubscribe=True))
- return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
+ return werkzeug.utils.redirect('/shop/product/%s#comments' % product_template_id)
@http.route(['/shop/pricelist'], type='http', auth="public", website=True)
def pricelist(self, promo, **post):
@@ -716,6 +716,7 @@ class website_sale(http.Controller):
if tx.state == 'draft': # button cliked but no more info -> rewrite on tx or create a new one ?
tx.write({
'acquirer_id': acquirer_id,
+ 'amount': order.amount_total,
})
tx_id = tx.id
else:
diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py
index 0b2b4b9e16d..608e50a787b 100644
--- a/addons/website_sale/models/sale_order.py
+++ b/addons/website_sale/models/sale_order.py
@@ -197,7 +197,8 @@ class website(orm.Model):
values.update(sale_order.onchange_pricelist_id(pricelist_id, None)['value'])
sale_order.write(values)
for line in sale_order.order_line:
- sale_order._cart_update(product_id=line.product_id.id, line_id=line.id, add_qty=0)
+ if line.exists():
+ sale_order._cart_update(product_id=line.product_id.id, line_id=line.id, add_qty=0)
# update browse record
if (code and code != sale_order.pricelist_id.code) or sale_order.partner_id.id != partner.id:
diff --git a/addons/website_sale_delivery/models/sale_order.py b/addons/website_sale_delivery/models/sale_order.py
index d9821d1391c..7c8ea80edc2 100644
--- a/addons/website_sale_delivery/models/sale_order.py
+++ b/addons/website_sale_delivery/models/sale_order.py
@@ -124,3 +124,15 @@ class SaleOrder(orm.Model):
values['deliveries'] = DeliveryCarrier.browse(cr, SUPERUSER_ID, delivery_ids, context=delivery_ctx)
return values
+
+ def _cart_update(self, cr, uid, ids, product_id=None, line_id=None, add_qty=0, set_qty=0, context=None, **kwargs):
+ """ Override to update carrier quotation if quantity changed """
+
+ values = super(SaleOrder, self)._cart_update(
+ cr, uid, ids, product_id, line_id, add_qty, set_qty, context, **kwargs)
+
+ if add_qty or set_qty is not None:
+ for sale_order in self.browse(cr, uid, ids, context=context):
+ self._check_carrier_quotation(cr, uid, sale_order, context=context)
+
+ return values