Merge pull request #12 from gurneyalex/8.0

8.0: ported 7.0  changes
This commit is contained in:
Alexandre Fayolle
2014-09-08 14:44:11 +02:00
12 changed files with 120 additions and 79 deletions

View File

@@ -3,42 +3,25 @@
language: python
python:
# - "pypy" # not supported by odoo 8
# - "3.4" # not supported by odoo 8
# - "3.3" # not supported by odoo 8
- "2.7"
# - "2.6" # not supported by odoo 8
env:
- ODOO="https://github.com/savoirfairelinux/odoo/archive/setuptools-addons.tar.gz" # Temp until https://github.com/odoo/odoo/issues/185 or https://github.com/odoo/odoo/issues/441 is fixed
# - ODOO="https://github.com/odoo/odoo/archive/master.tar.gz"
# - ODOO="https://github.com/OCA/OCB/archive/master.zip"
- VERSION="8.0" ODOO_REPO="odoo/odoo"
- VERSION="8.0" ODOO_REPO="OCA/OCB"
# Need coveralls for coverage reports
# Need flake8 for pep8 testing
# Manually get PyChart
# Install tested version of odoo (official or ocb)
# Get modules from other repos which have dependencies (in this case travel requires modules from lp:partner-contact-management and lp:openerp-hr
install:
- pip install coveralls flake8
- pip install http://download.gna.org/pychart/PyChart-1.39.tar.gz
- pip install ${ODOO}
virtualenv:
system_site_packages: true
# Create databae
# Pre-install modules and dependencies
before_script:
- createdb test
install:
- git clone https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools
- export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
- travis_install_nightly
- git clone https://github.com/OCA/stock-logistics-tracking -b ${VERSION} $HOME/stock-logistics-tracking
- git clone https://github.com/OCA/stock-logistics-barcode -b ${VERSION} $HOME/stock-logistics-barcode
# Test with flake, ignore F401 for __init__.py files, use a max length of 120
# Run tests with coverage
# Only test modules in repo (list populated by directories in repo)
# Preload modules before testing to only run tests of repo's modules
# Include current directory and dependent repos in addons-path as well as official addons
script:
- flake8 . --max-line-length=120 --filename=__init__.py --ignore=F401
- flake8 . --max-line-length=120 --exclude=__init__.py
- odoo.py -d test --stop-after-init --init=$(python -c 'import os; print(",".join(x for x in os.listdir(".") if os.path.isdir(x) and not x.startswith(".") and not x.endswith(".unported")))') --addons-path=$(pwd),`python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"`/addons
- coverage run $(which odoo.py) -d test --test-enable --log-level=test --stop-after-init --init=$(python -c 'import os; print(",".join(x for x in os.listdir(".") if os.path.isdir(x) and not x.startswith(".") and not x.endswith("_unported")))') --addons-path=$(pwd),`python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"`/addons
- travis_run_flake8
- travis_run_tests
after_success:
coveralls

View File

@@ -33,7 +33,7 @@ Immediately usable is computed : Quantity on Hand - Outgoing Stock.
""",
"website": "http://tinyerp.com/module_account.html",
"category": "Generic Modules/Stock",
"data": ["product_view.xml",
"data": ["product_view.xml",
],
"active": False,
'installable': False

View File

@@ -137,6 +137,6 @@ class product_immediately_usable(orm.Model):
type='float',
string='Immediately Usable',
multi='qty_available',
help="Quantity of products really available for sale." \
help="Quantity of products really available for sale."
"Computed as: Quantity On Hand - Outgoing."),
}

View File

@@ -19,7 +19,6 @@
##############################################################################
from openerp.osv import fields, orm
from openerp.tools.translate import _
class product_product(orm.Model):

View File

@@ -23,7 +23,8 @@
'version': '0.1',
'category': 'Warehouse Management',
'description': """
You can choose which stock moves have to generate inventory valuation accounting entries, by specifying it in the location form.
You can choose which stock moves have to generate inventory valuation
accounting entries, by specifying it in the location form.
""",
'author': 'Agile Business Group',
'website': 'http://www.agilebg.com',

View File

@@ -19,13 +19,16 @@
##############################################################################
from openerp.osv import fields, orm
from openerp.tools.translate import _
class stock_location(orm.Model):
_inherit = "stock.location"
_columns = {
'consider_internal': fields.boolean('Consider internal', help="Consider as internal location for inventory valuation: stock moves from internal to internal will not generate accounting entries"),
'consider_internal': fields.boolean(
'Consider internal',
help="Consider as internal location for inventory valuation: "
"stock moves from internal to internal will not generate "
"accounting entries"),
}
@@ -33,14 +36,18 @@ class stock_move(orm.Model):
_inherit = "stock.move"
def _create_product_valuation_moves(self, cr, uid, move, context=None):
if (move.location_id.company_id and move.location_dest_id.company_id
and move.location_id.company_id != move.location_dest_id.company_id):
return super(stock_move, self)._create_product_valuation_moves(
_super = super(stock_move, self)
location = move.location_id
location_dest = move.location_dest_id
if (location.company_id
and location_dest.company_id
and location.company_id != location_dest.company_id):
return _super._create_product_valuation_moves(
cr, uid, move, context=context)
if (move.location_id.usage == 'internal' or
move.location_id.consider_internal) and (
move.location_dest_id.usage == 'internal' or
move.location_dest_id.consider_internal):
return
return super(stock_move, self)._create_product_valuation_moves(
return _super._create_product_valuation_moves(
cr, uid, move, context=context)

View File

@@ -24,27 +24,37 @@
'version': '0.2',
'category': 'Tools',
'description': """
This module allows to improve reordering rules of stock module.
It works forecasting the stock needed per product for n days of sales, with the next formula:
(( Qty sold in days_stats * (1+forecast_gap)) / days_stats * days_warehouse)
where:
- days_stats = days on wich calculate sales stats;
- forecast_gap = forecast of increase/decrease on sales (%);
- days_warehouse = days of stock to keep in the warehouse.
This module allows to improve reordering rules of stock module.
Usage:
insert days_stats, forecast_gap and days_warehouse vars in product form
and create a reordering rule for the same product, without inserting nothing (neither maximum or
minimum quantity are required). The cron job will be executed daily and will update the maximum
quantity in the reordering rule (you can force it to start changing the date and hour of
execution).
This module doesn't need purchase module to work, but it's useful with that module.'""",
It works forecasting the stock needed per product for n days of sales, with
the following formula:
(( Qty sold in days_stats * (1+forecast_gap)) / days_stats * days_warehouse)
where:
- days_stats = days on wich calculate sales stats;
- forecast_gap = forecast of increase/decrease on sales (%);
- days_warehouse = days of stock to keep in the warehouse.
Usage:
insert days_stats, forecast_gap and days_warehouse vars in product form and
create a reordering rule for the same product, without inserting nothing
(neither maximum or minimum quantity are required). The cron job will be
executed daily and will update the maximum quantity in the reordering rule
(you can force it to start changing the date and hour of execution).
This module doesn't need purchase module to work, but it's useful with that
module.""",
'author': 'Sergio Corato',
'website': 'http://www.icstools.it',
'depends': ['procurement','sale',],
'demo_xml' : [],
'data': ['stock_reord_rule_view.xml','cron_data.xml',],
'depends': ['procurement',
'sale',
],
'demo_xml': [],
'data': ['stock_reord_rule_view.xml',
'cron_data.xml',
],
'images': [],
'active': False,
'installable': False,

View File

@@ -21,39 +21,58 @@
from openerp.osv import orm, fields
class stock_warehouse_orderpoint(orm.Model):
_inherit = "stock.warehouse.orderpoint"
def _qty_orderpoint_days(self, cr, uid, ids, context=None):
"""Calculate quantity to create warehouse stock for n days of sales.
(( Qty sold in days_stats * (1+forecast_gap)) / days_stats * days_warehouse)"""
Qty sold in days_stats * (1+forecast_gap)
/ days_stats * days_warehouse)
"""
obj_product = self.pool.get('product.product')
product_ids = tuple(obj_product.search(cr, uid, [], context=context))
sql= """SELECT sol.product_id AS product_id,
(sum( product_uos_qty )/pp.days_stats*(1+pp.forecast_gap/100) * pp.days_warehouse)
AS quantity FROM sale_order_line sol JOIN sale_order so ON so.id = sol.order_id
JOIN product_product pp ON pp.id = sol.product_id
sql = """
SELECT sol.product_id AS product_id,
(sum(product_uos_qty) / pp.days_stats *
(1 + pp.forecast_gap / 100) * pp.days_warehouse)
AS quantity
FROM sale_order_line sol
JOIN sale_order so ON so.id = sol.order_id
JOIN product_product pp ON pp.id = sol.product_id
JOIN product_template pt ON pt.id = pp.product_tmpl_id
WHERE sol.state in ('done','confirmed') AND pt.type = 'product'
AND sol.product_id IN %s AND date_order > (date(now()) - pp.days_stats)
GROUP BY sol.product_uom, sol.product_id, pp.days_stats, pp.forecast_gap,
pp.days_warehouse;"""
AND sol.product_id IN %s AND date_order > (date(now()) - pp.days_stats)
GROUP BY sol.product_uom,
sol.product_id,
pp.days_stats,
pp.forecast_gap,
pp.days_warehouse;
"""
cr.execute(sql, (product_ids,))
sql_res = cr.fetchall()
if sql_res:
for val in sql_res:
if val:
reord_rules_ids = self.search(cr, uid, [('product_id', '=', val[0])], context=context)
domain = [('product_id', '=', val[0])]
reord_rules_ids = self.search(cr, uid,
domain,
context=context)
if reord_rules_ids:
self.write(cr, uid, reord_rules_ids, {'product_max_qty': val[1]}, context=context)
self.write(cr, uid,
reord_rules_ids,
{'product_max_qty': val[1]},
context=context)
return True
class product_product(orm.Model):
_inherit = "product.product"
_columns = {
'days_warehouse': fields.integer('Days of needed warehouse stock'),
'days_stats': fields.integer('Days of sale statistics'),
'forecast_gap': fields.float('Expected sales variation (percent +/-)', digits=(6,3)),
'forecast_gap': fields.float('Expected sales variation (percent +/-)',
digits=(6, 3)),
}

View File

@@ -19,7 +19,7 @@
#
##############################################################################
from openerp.osv import orm, fields
from openerp.osv import orm
class product_product(orm.Model):

View File

@@ -134,7 +134,9 @@ class stock_reservation(orm.Model):
return super(stock_reservation, self).unlink(cr, uid, ids,
context=context)
def onchange_product_id(self, cr, uid, ids, product_id=False, context=None):
def onchange_product_id(self, cr, uid, ids,
product_id=False,
context=None):
move_obj = self.pool.get('stock.move')
if ids:
reserv = self.read(cr, uid, ids, ['move_id'], context=context,
@@ -146,7 +148,6 @@ class stock_reservation(orm.Model):
cr, uid, move_ids, prod_id=product_id, loc_id=False,
loc_dest_id=False, partner_id=False)
if result.get('value'):
vals = result['value']
# only keep the existing fields on the view
keep = ('product_uom', 'name')
result['value'] = dict((key, value) for key, value in
@@ -154,7 +155,10 @@ class stock_reservation(orm.Model):
key in keep)
return result
def onchange_quantity(self, cr, uid, ids, product_id, product_qty, context=None):
def onchange_quantity(self, cr, uid, ids,
product_id,
product_qty,
context=None):
""" On change of product quantity avoid negative quantities """
if not product_id or product_qty <= 0.0:
return {'value': {'product_qty': 0.0}}

View File

@@ -117,9 +117,22 @@ class sale_order_line(orm.Model):
reserv_obj.release(cr, uid, reserv_ids, context=context)
return True
def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
uom=False, qty_uos=0, uos=False, name='', partner_id=False,
lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None):
def product_id_change(self, cr, uid, ids,
pricelist,
product,
qty=0,
uom=False,
qty_uos=0,
uos=False,
name='',
partner_id=False,
lang=False,
update_tax=True,
date_order=False,
packaging=False,
fiscal_position=False,
flag=False,
context=None):
result = super(sale_order_line, self).product_id_change(
cr, uid, ids, pricelist, product, qty=qty, uom=uom,
qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
@@ -146,9 +159,13 @@ class sale_order_line(orm.Model):
return result
def write(self, cr, uid, ids, vals, context=None):
block_on_reserve = ('product_id', 'product_uom', 'product_uos',
block_on_reserve = ('product_id',
'product_uom',
'product_uos',
'type')
update_on_reserve = ('price_unit', 'product_uom_qty', 'product_uos_qty')
update_on_reserve = ('price_unit',
'product_uom_qty',
'product_uos_qty')
keys = set(vals.keys())
test_block = keys.intersection(block_on_reserve)
test_update = keys.intersection(update_on_reserve)
@@ -162,7 +179,9 @@ class sale_order_line(orm.Model):
'of lines with a stock reservation. '
'Release the reservation '
'before changing the product.'))
res = super(sale_order_line, self).write(cr, uid, ids, vals, context=context)
res = super(sale_order_line, self).write(cr, uid, ids,
vals,
context=context)
if test_update:
for line in self.browse(cr, uid, ids, context=context):
if not line.reservation_ids:

View File

@@ -98,7 +98,6 @@ class sale_stock_reserve(orm.TransientModel):
if not (active_model and active_ids):
return close
line_obj = self.pool.get('sale.order.line')
if active_model == 'sale.order':
sale_obj = self.pool.get('sale.order')
sales = sale_obj.browse(cr, uid, active_ids, context=context)