- |
+
+
+ on
+ |
@@ -158,7 +161,7 @@
|
- on
+
|
1:
+ message = _('You cannot use the same serial number twice. Please correct the serial numbers encoded.')
+ elif self.lot_id:
+ counter = Counter(move_lines_to_check.mapped('lot_id.id'))
+ if counter.get(self.lot_id.id) and counter[self.lot_id.id] > 1:
+ message = _('You cannot use the same serial number twice. Please correct the serial numbers encoded.')
+
if message:
res['warning'] = {'title': _('Warning'), 'message': message}
return res
+ @api.onchange('qty_done')
+ def _onchange_qty_done(self):
+ """ When the user is encoding a move line for a tracked product, we apply some logic to
+ help him. This onchange will warn him if he set `qty_done` to a non-supported value.
+ """
+ res = {}
+ if self.product_id.tracking == 'serial':
+ if float_compare(self.qty_done, 1.0, precision_rounding=self.move_id.product_id.uom_id.rounding) != 0:
+ message = _('You can only process 1.0 %s for products with unique serial number.') % self.product_id.uom_id.name
+ res['warning'] = {'title': _('Warning'), 'message': message}
+ return res
+
@api.constrains('qty_done')
def _check_positive_qty_done(self):
if any([ml.qty_done < 0 for ml in self]):
raise ValidationError(_('You can not enter negative quantities!'))
- @api.constrains('lot_id', 'lot_name', 'qty_done')
- def _check_unique_serial_number(self):
- for ml in self.filtered(lambda ml: ml.move_id.product_id.tracking == 'serial' and (ml.lot_id or ml.lot_name)):
- move_lines_to_check = ml._get_similar_move_lines()
- message = move_lines_to_check._check_for_duplicated_serial_numbers()
- if message:
- raise ValidationError(message)
- if float_compare(ml.qty_done, 1.0, precision_rounding=ml.move_id.product_id.uom_id.rounding) == 1:
- raise UserError(_(
- 'You can only process 1.0 %s for products with unique serial number.') % ml.product_id.uom_id.name)
- if ml.lot_name:
- already_exist = self.env['stock.production.lot'].search(
- [('name', '=', ml.lot_name), ('product_id', '=', ml.product_id.id)])
- if already_exist:
- return _('You have already assigned this serial number to this product. Please correct the serial numbers encoded.')
-
def _get_similar_move_lines(self):
self.ensure_one()
lines = self.env['stock.move.line']
@@ -147,25 +160,6 @@ class StockMoveLine(models.Model):
lines |= picking_id.move_line_ids.filtered(lambda ml: ml.product_id == self.product_id and (ml.lot_id or ml.lot_name))
return lines
- def _check_for_duplicated_serial_numbers(self):
- """ This method is used in _check_unique_serial_number and in onchange_serial_number to check that a same serial number is not used twice amongst the recordset passed.
-
- :return: an error message directed to the user if needed else False
- """
- if self.mapped('lot_id'):
- lots_map = [(ml.product_id.id, ml.lot_id.name) for ml in self]
- recorded_serials_counter = Counter(lots_map)
- for (product_id, lot_id), occurrences in recorded_serials_counter.items():
- if occurrences > 1 and lot_id is not False:
- return _('You cannot use the same serial number twice. Please correct the serial numbers encoded.')
- elif self.mapped('lot_name'):
- lots_map = [(ml.product_id.id, ml.lot_name) for ml in self]
- recorded_serials_counter = Counter(lots_map)
- for (product_id, lot_id), occurrences in recorded_serials_counter.items():
- if occurrences > 1 and lot_id is not False:
- return _('You cannot use the same serial number twice. Please correct the serial numbers encoded.')
- return False
-
@api.model
def create(self, vals):
vals['ordered_qty'] = vals.get('product_uom_qty')
diff --git a/addons/stock/views/stock_picking_views.xml b/addons/stock/views/stock_picking_views.xml
index 82b74d5f32e..7da23c0b44d 100644
--- a/addons/stock/views/stock_picking_views.xml
+++ b/addons/stock/views/stock_picking_views.xml
@@ -246,7 +246,7 @@
-
+
diff --git a/doc/cla/corporate/bas-solutions.md b/doc/cla/corporate/bas-solutions.md
deleted file mode 100644
index f0d49c7facf..00000000000
--- a/doc/cla/corporate/bas-solutions.md
+++ /dev/null
@@ -1,16 +0,0 @@
-Netherlands, 8-2-2015
-
-BAS Solutions agrees to the terms of the Odoo Corporate Contributor License
-Agreement v1.0.
-
-I declare that I am authorized and able to make this agreement and sign this
-declaration.
-
-Signed,
-
-Erwin van der Ploeg erwin@bas-solutions.nl https://github.com/erwin-bas-solutions
-
-List of contributors:
-
-Erwin van der Ploeg erwin@bas-solutions.nl https://github.com/erwin-bas-solutions
-Ruchir Shukla ruchir@bas-solutions.nl https://github.com/ruchir-bas-solutions
\ No newline at end of file
diff --git a/doc/cla/corporate/odooexperts.md b/doc/cla/corporate/odooexperts.md
new file mode 100644
index 00000000000..3a73e799b87
--- /dev/null
+++ b/doc/cla/corporate/odooexperts.md
@@ -0,0 +1,16 @@
+Netherlands, 18-1-2018
+
+Odoo Experts agrees to the terms of the Odoo Corporate Contributor License
+Agreement v1.0.
+
+I declare that I am authorized and able to make this agreement and sign this
+declaration.
+
+Signed,
+
+Erwin van der Ploeg erwin@bas-solutions.nl https://github.com/erwin-bas-solutions
+
+List of contributors:
+
+Erwin van der Ploeg erwin@odooexperts.nl https://github.com/ploegvde
+Yenthe Van Ginneken yenthe@odooexperts.nl https://github.com/Yenthe666
diff --git a/doc/cla/individual/nguyenductamlhp.md b/doc/cla/individual/nguyenductamlhp.md
new file mode 100644
index 00000000000..898f465c52b
--- /dev/null
+++ b/doc/cla/individual/nguyenductamlhp.md
@@ -0,0 +1,11 @@
+Vietnam, 2018-01-16,
+
+I hereby agree to the terms of the Odoo Individual Contributor License
+Agreement v1.0.
+
+I declare that I am authorized and able to make this agreement and sign this
+declaration.
+
+Signed,
+
+Nguyen Duc Tam nguyenductamlhp@gmail.com https://github.com/nguyenductamlhp
diff --git a/doc/setup/install.rst b/doc/setup/install.rst
index 71a6ea7edb7..99871bda78f 100644
--- a/doc/setup/install.rst
+++ b/doc/setup/install.rst
@@ -360,13 +360,6 @@ Source installation requires manually installing dependencies:
Install ``psycopg`` using the installer here
http://www.stickpeople.com/projects/python/win-psycopg/
- Then edit the requirements.txt file:
-
- - remove ``psycopg2`` as you already have it.
- - remove the optional ``python-ldap``, ``gevent`` and ``psutil`` because
- they require compilation.
- - add ``pypiwin32`` because it's needed under windows.
-
Then use pip to install the dependencies using the following
command from a cmd.exe prompt (replace ``\YourOdooPath`` by the actual
path where you downloaded Odoo):
diff --git a/doc/webservices/iap.rst b/doc/webservices/iap.rst
index 186daf772b6..23467c267c3 100644
--- a/doc/webservices/iap.rst
+++ b/doc/webservices/iap.rst
@@ -82,8 +82,9 @@ Overview
The Credits
Every service provided through the In-App platform can be used by the
- clients with tokens or *credits*. The monetary value of a credit depends
- on the service and is decided by the provider. This could be:
+ clients with tokens or *credits*. The credits are an integer unit and
+ their monetary value depends on the service and is decided by the
+ provider. This could be:
* for an sms service: 1 credit = 1 sms,
* for an add service: 1 credit = 1 add,
@@ -210,14 +211,20 @@ The credit packages are essentially a product with 4 characteristics.
* Credits: the amount of credits the client is entitled to when buying the package,
* Price: the price in *EUROS* for the time being (USD support is planned).
-.. image:: images/package.png
- :align: center
-
.. note::
+ Odoo takes a 25% commission on all package sales. Adjust your selling price accordingly.
+
+
+.. note::
+
Depending on the strategy, the price per credit can vary from one
package to another.
+
+.. image:: images/package.png
+ :align: center
+
.. _iap-odoo-app:
Odoo App
@@ -309,15 +316,22 @@ perform the service within:
.. todo:: "My Account" > "Your InApp Services"?
+
The :class:`~odoo.addons.iap.models.iap.charge` helper will:
+.. note::
+
+ Since the 15th of January 2018, a new functionality that allows one to capture a different amount than autorized has been added.
+ See :ref:`Charging `
+
1. authorize (create) a transaction with the specified number of credits,
if the account does not have enough credits it will raise the relevant
error
2. execute the body of the ``with`` statement
-3. if the body of the ``with`` executes succesfully, capture (confirm) the
- transaction
-4. otherwise if an error is raised from the body of the ``with`` cancel the
+3. (NEW) if the body of the ``with`` executes succesfully, update the price
+ of the transaction if needed
+4. capture (confirm) the transaction
+5. otherwise if an error is raised from the body of the ``with`` cancel the
transaction (and release the hold on the credits)
.. danger::
@@ -420,10 +434,12 @@ Capture
:param TransactionToken token:
:param ServiceKey key:
+ :param int credit_to_capture: (new - 15 Jan 2018) optional parameter to capture a smaller amount of credits than authorized
:raises: :class:`~odoo.exceptions.AccessError`
.. code-block:: python
-
+ :emphasize-lines: 8
+
r2 = requests.post(ODOO + '/iap/1/capture', json={
'jsonrpc': '2.0',
'id': None,
@@ -431,6 +447,7 @@ Capture
'params': {
'token': tx,
'key': SERVICE_KEY,
+ 'credit_to_capture': credit or False,
}
}).json()
if 'error' in r:
@@ -523,9 +540,17 @@ Odoo Helpers
For convenience, if you are implementing your service using Odoo the ``iap``
module provides a few helpers to make IAP flow even simpler:
+.. _iap-charging:
+
Charging
--------
+.. note::
+
+ A new functionality was introduced to capture a different amount of credits than reserved.
+ As this patch was added on the 15th of January 2018, you will need to upgrade your ``iap`` module in order to use it.
+ The specifics of the new functionality are highlighted in the code.
+
.. class:: odoo.addons.iap.models.iap.charge(env, key, account_token, credit[, description, credit_template])
A *context manager* for authorizing and automatically capturing or
@@ -544,8 +569,10 @@ Charging
:param UserToken token:
:param int credit:
:param str description:
+ :param Qweb template credit_template:
.. code-block:: python
+ :emphasize-lines: 10,13,14,15
@route('/deathstar/superlaser', type='json')
def superlaser(self, user_account,
@@ -556,8 +583,11 @@ Charging
0.0 is none, 1.0 is full power
"""
credits = int(MAXIMUM_POWER * factor)
- with charge(request.env, SERVICE_KEY, user_account, credits):
+ with charge(request.env, SERVICE_KEY, user_account, credits) as transaction:
# TODO: allow other targets
+ transaction.credit = max(credits, 2)
+ # Sales ongoing one the energy price,
+ # a maximum of 2 credits will be charged/captured.
self.env['systems.planets'].search([
('grid', '=', 'M-10'),
('name', '=', 'Alderaan'),
diff --git a/odoo/addons/base/data/res_country_data.xml b/odoo/addons/base/data/res_country_data.xml
index 031af455c5b..819082fb27d 100644
--- a/odoo/addons/base/data/res_country_data.xml
+++ b/odoo/addons/base/data/res_country_data.xml
@@ -1597,7 +1597,7 @@
tl
-
+
Turkey
diff --git a/odoo/addons/base/models/ir_actions_report.py b/odoo/addons/base/models/ir_actions_report.py
index f4e3648b578..3d66287289a 100644
--- a/odoo/addons/base/models/ir_actions_report.py
+++ b/odoo/addons/base/models/ir_actions_report.py
@@ -678,7 +678,7 @@ class IrActionsReport(models.Model):
"""
discard_logo_check = self.env.context.get('discard_logo_check')
if (self.env.uid == SUPERUSER_ID) and ((not self.env.user.company_id.external_report_layout) or (not discard_logo_check and not self.env.user.company_id.logo)) and config:
- template = self.env.ref('base.view_company_report_form_with_print')
+ template = self.env.ref('base.view_company_report_form_with_print') if self.env.context.get('from_transient_model', False) else self.env.ref('base.view_company_report_form')
return {
'name': _('Choose Your Document Layout'),
'type': 'ir.actions.act_window',
diff --git a/requirements.txt b/requirements.txt
index 311aaea0e8b..27127c70862 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,22 +3,23 @@ decorator==4.0.10
docutils==0.12
ebaysdk==2.1.5
feedparser==5.2.1
-gevent==1.1.2
+gevent==1.1.2 ; sys_platform != 'win32'
greenlet==0.4.10
html2text==2016.9.19
Jinja2==2.8
-lxml==3.5.0
+lxml==3.7.1 ; sys_platform != 'win32'
+lxml ; sys_platform == 'win32'
Mako==1.0.4
MarkupSafe==0.23
mock==2.0.0
num2words==0.5.4
ofxparse==0.16
passlib==1.6.5
-Pillow==3.4.1
-psutil==4.3.1
-psycopg2==2.7.3.1
+Pillow==4.0.0
+psutil==4.3.1; sys_platform != 'win32'
+psycopg2==2.7.3.1; sys_platform != 'win32'
pydot==1.2.3
-pyldap==2.4.28
+pyldap==2.4.28; sys_platform != 'win32'
pyparsing==2.1.10
PyPDF2==1.26.0
pyserial==3.1.1
@@ -29,11 +30,11 @@ PyYAML==3.12
qrcode==5.3
reportlab==3.3.0
requests==2.11.1
-six==1.10.0
suds-jurko==0.6
vatnumber==1.2
vobject==0.9.3
-Werkzeug==0.11.11
+Werkzeug==0.11.15
XlsxWriter==0.9.3
xlwt==1.3.*
xlrd==1.0.0
+pypiwin32 ; sys_platform == 'win32'
| |