Merge pull request #67 from vauxoo-dev/8.0-crm_rma_stock_location-oca

[8.0] Improved module crm_rma_stock_location
This commit is contained in:
Nhomar Hernández [Vauxoo]
2015-12-02 15:40:29 -06:00
39 changed files with 1587 additions and 839 deletions

View File

@@ -1,65 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2013 Camptocamp
# Copyright 2009-2013 Akretion,
# Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, Joel Grand-Guillaume
#
# 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/>.
#
##############################################################################
{'name': 'RMA Claims Advance Location',
'version': '1.0',
'category': 'Generic Modules/CRM & SRM',
'depends': ['crm_claim_rma',
'crm_rma_stock_location',
],
'author': "Akretion,Odoo Community Association (OCA)",
'license': 'AGPL-3',
'website': 'http://www.akretion.com',
'description': """
RMA Claim Advance Location
==========================
This module adds the following location on warehouses :
* Carrier Loss
* RMA
* Breakage Loss
* Refurbish
* Mistake Loss
And also various wizards on icoming deliveries that allow you to move your goods easily in those
new locations from a done reception.
Using this module make the logistic flow of return a bit more complexe:
* Returning product goes into RMA location with a incoming shipment
* From the incoming shipment, forward them to another places (stock, loss,...)
WARNING: Use with caution, this module is currently not yet completely debugged and is waiting his author to be.
""",
'images': [],
'demo': [],
'data': ['wizard/claim_make_picking_from_picking_view.xml',
'wizard/claim_make_picking_view.xml',
'stock_view.xml',
'stock_data.xml',
'claim_rma_view.xml',
],
'installable': False,
'application': True,
}

View File

@@ -1,20 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="crm_claim_rma_form_view">
<field name="name">CRM - Claim product return Form</field>
<field name="model">crm.claim</field>
<field name="inherit_id" ref="crm_claim_rma.crm_claim_rma_form_view"/>
<field name="arch" type="xml">
<xpath expr="//button[@string='New Delivery']" position="after">
<button name="%(action_claim_picking_loss)d"
string="New Product Loss" states="open"
type="action" target="new"
context="{'warehouse_id': warehouse_id,
'partner_id': partner_id}"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@@ -1,122 +0,0 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * crm_rma_advance_location
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-11-15 13:27+0000\n"
"PO-Revision-Date: 2013-11-15 13:27+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: crm_rma_advance_location
#: model:ir.actions.act_window,name:crm_rma_advance_location.action_claim_picking_loss
msgid "Create Products Loss"
msgstr ""
#. module: crm_rma_advance_location
#: model:ir.actions.act_window,name:crm_rma_advance_location.action_used_picking_from_claim_picking
msgid "Create Incomming Shipment to Refurbish Location"
msgstr ""
#. module: crm_rma_advance_location
#: view:claim_make_picking_from_picking.wizard:0
msgid "Locations"
msgstr ""
#. module: crm_rma_advance_location
#: view:claim_make_picking_from_picking.wizard:0
msgid "Select lines for picking"
msgstr ""
#. module: crm_rma_advance_location
#: model:stock.location,name:crm_rma_advance_location.stock_location_breakage_loss
msgid "Breakage Loss"
msgstr ""
#. module: crm_rma_advance_location
#: model:ir.model,name:crm_rma_advance_location.model_claim_make_picking_wizard
msgid "Wizard to create pickings from claim lines"
msgstr ""
#. module: crm_rma_advance_location
#: model:stock.location,name:crm_rma_advance_location.stock_location_carrier_loss
msgid "Carrier Loss"
msgstr ""
#. module: crm_rma_advance_location
#: model:stock.location,name:crm_rma_advance_location.stock_location_mistake_loss
msgid "Mistake Loss"
msgstr ""
#. module: crm_rma_advance_location
#: model:ir.actions.act_window,name:crm_rma_advance_location.action_loss_picking_from_claim_picking
msgid "Create Incomming Shipment to Breakkage Loss Location"
msgstr ""
#. module: crm_rma_advance_location
#: view:stock.picking.in:0
msgid "Product to refurbish stock"
msgstr ""
#. module: crm_rma_advance_location
#: model:ir.model,name:crm_rma_advance_location.model_stock_warehouse
msgid "Warehouse"
msgstr ""
#. module: crm_rma_advance_location
#: model:stock.location,name:crm_rma_advance_location.stock_location_rma
msgid "RMA"
msgstr ""
#. module: crm_rma_advance_location
#: model:stock.location,name:crm_rma_advance_location.stock_location_refurbish
msgid "Refurbish"
msgstr ""
#. module: crm_rma_advance_location
#: view:stock.picking.in:0
msgid "Product to stock"
msgstr ""
#. module: crm_rma_advance_location
#: model:ir.actions.act_window,name:crm_rma_advance_location.action_stock_picking_from_claim_picking
msgid "Create Incomming Shipment to Stock"
msgstr ""
#. module: crm_rma_advance_location
#: view:claim_make_picking_from_picking.wizard:0
msgid "Create picking"
msgstr ""
#. module: crm_rma_advance_location
#: view:claim_make_picking_from_picking.wizard:0
msgid "Cancel"
msgstr ""
#. module: crm_rma_advance_location
#: view:crm.claim:0
msgid "New Product Loss"
msgstr ""
#. module: crm_rma_advance_location
#: model:ir.model,name:crm_rma_advance_location.model_claim_make_picking_from_picking_wizard
msgid "Wizard to create pickings from picking lines"
msgstr ""
#. module: crm_rma_advance_location
#: view:stock.picking.in:0
msgid "Product to Loss"
msgstr ""
#. module: crm_rma_advance_location
#: view:claim_make_picking_from_picking.wizard:0
msgid "Select lines to add in picking"
msgstr ""

View File

@@ -1,36 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<!--
Default Values for : Stock Location
-->
<record id="stock_location_carrier_loss" model="stock.location">
<field name="name">Carrier Loss</field>
<field name="usage">internal</field>
<field name="location_id" ref="stock.stock_location_company"/>
</record>
<record id="stock_location_breakage_loss" model="stock.location">
<field name="name">Breakage Loss</field>
<field name="usage">internal</field>
<field name="location_id" ref="stock.stock_location_company"/>
</record>
<record id="stock_location_refurbish" model="stock.location">
<field name="name">Refurbish</field>
<field name="usage">internal</field>
<field name="location_id" ref="stock.stock_location_company"/>
</record>
<record id="stock_location_mistake_loss" model="stock.location">
<field name="name">Mistake Loss</field>
<field name="usage">internal</field>
<field name="location_id" ref="stock.stock_location_company"/>
</record>
<!--
Default Values for : Stock Warehouse
-->
<record id="stock.warehouse0" model="stock.warehouse">
<field name="lot_breakage_loss_id" ref="stock_location_breakage_loss"/>
<field name="lot_carrier_loss_id" ref="stock_location_carrier_loss"/>
<field name="lot_refurbish_id" ref="stock_location_refurbish"/>
</record>
</data>
</openerp>

View File

@@ -1,53 +0,0 @@
# -*- coding: utf-8 -*-
#########################################################################
# #
# #
#########################################################################
# #
# crm_claim_rma for OpenERP #
# Copyright (C) 2009-2012 Akretion, Emmanuel Samyn, #
# Benoît GUILLOT <benoit.guillot@akretion.com> #
#This program is free software: you can redistribute it and/or modify #
#it under the terms of the GNU 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 General Public License for more details. #
# #
#You should have received a copy of the GNU General Public License #
#along with this program. If not, see <http://www.gnu.org/licenses/>. #
#########################################################################
from openerp.osv import orm
class claim_make_picking(orm.TransientModel):
_inherit = 'claim_make_picking.wizard'
def _get_dest_loc(self, cr, uid, context=None):
""" Get default destination location """
loc_id = super(claim_make_picking, self)._get_dest_loc(cr, uid, context=context)
if context is None:
context = {}
warehouse_obj = self.pool.get('stock.warehouse')
warehouse_id = context.get('warehouse_id')
if context.get('picking_type') == 'in':
loc_id = warehouse_obj.read(
cr, uid,
warehouse_id,
['lot_rma_id'],
context=context)['lot_rma_id'][0]
elif context.get('picking_type') == 'loss':
loc_id = warehouse_obj.read(
cr, uid,
warehouse_id,
['lot_carrier_loss_id'],
context=context)['lot_carrier_loss_id'][0]
return loc_id
_defaults = {
'claim_line_dest_location': _get_dest_loc,
}

View File

@@ -1,169 +0,0 @@
# -*- coding: utf-8 -*-
#########################################################################
# #
# #
#########################################################################
# #
# crm_claim_rma for OpenERP #
# Copyright (C) 2009-2012 Akretion, Emmanuel Samyn, #
# Benoît GUILLOT <benoit.guillot@akretion.com> #
#This program is free software: you can redistribute it and/or modify #
#it under the terms of the GNU 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 General Public License for more details. #
# #
#You should have received a copy of the GNU General Public License #
#along with this program. If not, see <http://www.gnu.org/licenses/>. #
#########################################################################
from openerp.osv import fields, orm
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp import netsvc
import time
class claim_make_picking_from_picking(orm.TransientModel):
_name = 'claim_make_picking_from_picking.wizard'
_description = 'Wizard to create pickings from picking lines'
_columns = {
'picking_line_source_location': fields.many2one('stock.location',
'Source Location',
help="Location where the returned products are from.",
required=True),
'picking_line_dest_location': fields.many2one('stock.location',
'Dest. Location',
help="Location where the system will stock the returned products.",
required=True),
'picking_line_ids': fields.many2many('stock.move',
'claim_picking_line_picking',
'claim_picking_id',
'picking_line_id',
'Picking lines'),
}
def _get_default_warehouse(self, cr, uid, context=None):
warehouse_id=self.pool.get('crm.claim')._get_default_warehouse(cr, uid, context=context)
return warehouse_id
def _get_picking_lines(self, cr, uid, context):
return self.pool.get('stock.picking').read(cr, uid,
context['active_id'], ['move_lines'], context=context)['move_lines']
# Get default source location
def _get_source_loc(self, cr, uid, context):
if context is None:
context = {}
warehouse_obj = self.pool.get('stock.warehouse')
warehouse_id = self._get_default_warehouse(cr, uid, context=context)
return warehouse_obj.read(cr, uid,
warehouse_id, ['lot_rma_id'], context=context)['lot_rma_id'][0]
# Get default destination location
def _get_dest_loc(self, cr, uid, context):
if context is None:
context = {}
warehouse_id = self._get_default_warehouse(cr, uid, context=context)
warehouse_obj = self.pool.get('stock.warehouse')
if context.get('picking_type'):
context_loc = context.get('picking_type')[8:]
loc_field = 'lot_%s_id' %context.get('picking_type')[8:]
loc_id = warehouse_obj.read(cr, uid,
warehouse_id, [loc_field], context=context)[loc_field][0]
return loc_id
_defaults = {
'picking_line_source_location': _get_source_loc,
'picking_line_dest_location': _get_dest_loc,
'picking_line_ids': _get_picking_lines,
}
def action_cancel(self,cr,uid,ids,conect=None):
return {'type': 'ir.actions.act_window_close',}
# If "Create" button pressed
def action_create_picking_from_picking(self, cr, uid, ids, context=None):
picking_obj = self.pool.get('stock.picking')
move_obj = self.pool.get('stock.move')
view_obj = self.pool.get('ir.ui.view')
if context is None:
context = {}
p_type = 'internal'
if context.get('picking_type'):
context_type = context.get('picking_type')[8:]
note = 'Internal picking from RMA to %s' %context_type
name = 'Internal picking to %s' %context_type
view_id = view_obj.search(cr, uid, [
('xml_id', '=', 'view_picking_form'),
('model', '=', 'stock.picking'),
('type', '=', 'form'),
('name', '=', 'stock.picking.form')
], context=context)[0]
wizard = self.browse(cr, uid, ids[0], context=context)
prev_picking = picking_obj.browse(cr, uid,
context['active_id'], context=context)
partner_id = prev_picking.partner_id.id
# create picking
picking_id = picking_obj.create(cr, uid, {
'origin': prev_picking.origin,
'type': p_type,
'move_type': 'one', # direct
'state': 'draft',
'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'partner_id': prev_picking.partner_id.id,
'invoice_state': "none",
'company_id': prev_picking.company_id.id,
'location_id': wizard.picking_line_source_location.id,
'location_dest_id': wizard.picking_line_dest_location.id,
'note' : note,
'claim_id': prev_picking.claim_id.id,
})
# Create picking lines
for wizard_picking_line in wizard.picking_line_ids:
move_id = move_obj.create(cr, uid, {
'name' : wizard_picking_line.product_id.name_template, # Motif : crm id ? stock_picking_id ?
'priority': '0',
#'create_date':
'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'date_expected': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'product_id': wizard_picking_line.product_id.id,
'product_qty': wizard_picking_line.product_qty,
'product_uom': wizard_picking_line.product_uom.id,
'partner_id': prev_picking.partner_id.id,
'prodlot_id': wizard_picking_line.prodlot_id.id,
# 'tracking_id':
'picking_id': picking_id,
'state': 'draft',
'price_unit': wizard_picking_line.price_unit,
# 'price_currency_id': claim_id.company_id.currency_id.id, # from invoice ???
'company_id': prev_picking.company_id.id,
'location_id': wizard.picking_line_source_location.id,
'location_dest_id': wizard.picking_line_dest_location.id,
'note': note,
})
wizard_move = move_obj.write(cr, uid,
wizard_picking_line.id,
{'move_dest_id': move_id},
context=context)
wf_service = netsvc.LocalService("workflow")
if picking_id:
wf_service.trg_validate(uid,
'stock.picking', picking_id,'button_confirm', cr)
picking_obj.action_assign(cr, uid, [picking_id])
domain = "[('type','=','%s'),('partner_id','=',%s)]"%(p_type, partner_id)
return {
'name': '%s' % name,
'view_type': 'form',
'view_mode': 'form',
'view_id': view_id,
'domain' : domain,
'res_model': 'stock.picking',
'res_id': picking_id,
'type': 'ir.actions.act_window',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@@ -0,0 +1,96 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
==================
RMA Stock Location
==================
Allow the user to know how much for a product is available 'On Hand' and how much
is virtually (expected to be) available for RMA locations. Adding for the
different product views (Tree, Form and Kanban) information about it.
Both quantities are computed and include its children locations.
It is useful to use it as a quick snapshot for RMA from product perspective.
It also adds the following location on warehouses :
* Loss
* Refurbished
Several wizards on incoming deliveries that allow you to move your
goods easily in those new locations from a done reception.
Using this module make the logistic flow of return a bit more complex:
* Returning product goes into RMA location with a incoming shipment
* From the incoming shipment, forward them to another places (stock, loss, refurbish)
Installation
============
To install this module, just select it from availables modules.
Configuration
=============
No configuration is needed
Usage
=====
* Go to Sales > After-sale Services and note that 'RMA Quantity On Hand' and
'RMA Forecasted Quantity' has been included and they'll be shown when at least
when a product has either on hand or forecasted quantities available.
* In the other hand, it provides three wizards to make stock moves (transfers)
allowing to do product returns (incoming), send a product to loss or, to a refurbished
location.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/8.0/145
For further information, please visit:
* https://www.odoo.com/forum/help-1
Known issues / Roadmap
======================
* Optimization is possible when searching virtual quantities in the search function
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/rma/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
`here <https://github.com/OCA/rma/issues/new?body=module:%20crm_rma_stock_location%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Credits
=======
Contributors
------------
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
* Yanina Aular <yanina.aular@vauxoo.com>
* Osval Reyes <osval@vauxoo.com>
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit http://odoo-community.org.

View File

@@ -1,8 +1,10 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
# Copyright 2015 Vauxoo
# Copyright 2014 Camptocamp SA
# Author: Guewen Baconnier,
# Osval Reyes
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -19,5 +21,6 @@
#
##############################################################################
from . import stock_warehouse
from . import product
from . import models
from . import wizards
from .init_hooks import post_init_hook

View File

@@ -1,8 +1,13 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
# Copyright 2014 Camptocamp SA
# Copyright 2015 Vauxoo
# Copyright 2013-2014 Camptocamp SA
# Copyright 2009-2013 Akretion,
# Author: Guewen Baconnier,
# Emmanuel Samyn, Raphaël Valyi, Sébastien Beau,
# Joel Grand-Guillaume,
# Yanina Aular, Osval Reyes
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -19,31 +24,35 @@
#
##############################################################################
{'name': 'RMA Stock Location',
'version': '1.0',
'author': "Camptocamp,Odoo Community Association (OCA)",
'maintainer': 'Camptocamp',
'license': 'AGPL-3',
'category': 'Generic Modules/CRM & SRM',
'depends': ['stock',
'procurement',
],
'description': """
RMA Stock Location
==================
A RMA location can be selected on the warehouses.
The product views displays the quantity available and virtual in this
RMA location (including the children locations).
""",
'website': 'http://www.camptocamp.com',
'data': ['stock_data.xml',
'stock_warehouse_view.xml',
'product_view.xml',
],
'test': ['test/quantity.yml',
],
'installable': False,
'auto_install': False,
}
{
'name': 'RMA Stock Location',
'version': '8.0.1.0.0',
'author': "Akretion,Vauxoo,Camptocamp,Odoo Community Association (OCA)",
'maintainer': 'Camptocamp',
'website': 'http://www.camptocamp.com,http://www.vauxoo.com',
'license': 'AGPL-3',
'category': 'Generic Modules/CRM & SRM',
'depends': [
'crm_claim_rma',
'crm_claim',
'stock_account',
'procurement',
'crm_rma_location',
],
'data': [
'wizards/claim_make_picking_from_picking_view.xml',
'wizards/claim_make_picking_view.xml',
'views/product_product.xml',
'views/product_template.xml',
'views/crm_claim.xml',
'views/stock_picking.xml',
'views/stock_warehouse.xml',
],
'demo': [
'demo/stock_location.xml',
'demo/stock_inventory.xml',
],
'post_init_hook': 'post_init_hook',
'installable': True,
'auto_install': False,
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="rma_stock_location_move_01" model="stock.move">
<field name="name">Demo Stock Move: Customer > RMA</field>
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom">1</field>
<field name="product_uom_qty">1000</field>
<field name="company_id" ref="base.main_company"/>
<field name="priority">1</field> <!-- Normal -->
<field name="picking_type_id" ref="stock.picking_type_in"/>
<field name="location_id" ref="stock.stock_location_customers"/>
<field name="location_dest_id" search="[('name', '=', 'RMA'), ('location_id.name', '=', 'WH')]"/>
</record>
<record id="rma_stock_location_move_03" model="stock.move">
<field name="name">Demo Stock Move: RMA > Loss</field>
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom">1</field>
<field name="product_uom_qty">1000</field>
<field name="company_id" ref="base.main_company"/>
<field name="priority">1</field> <!-- Normal -->
<field name="picking_type_id" ref="stock.picking_type_internal"/>
<field name="location_id" search="[('name', '=', 'RMA'), ('location_id.name', '=', 'WH')]"/>
<field name="location_dest_id" ref="stock.stock_location_stock"/>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="location_rma" model="stock.location">
<field name="name">RMA Demo</field>
<field name="usage">internal</field>
</record>
<record id="stock.stock_warehouse_shop0" model="stock.warehouse">
<field name="lot_rma_id" ref="location_rma"/>
</record>
<record id="location_rma_a" model="stock.location">
<field name="name">RMA - Box A</field>
<field name="location_id" ref="location_rma"/>
<field name="usage">internal</field>
</record>
<record id="location_rma_b" model="stock.location">
<field name="name">RMA - Box B</field>
<field name="location_id" ref="location_rma"/>
<field name="usage">internal</field>
</record>
<record id="product_socket" model="product.product">
<field name="name">Socket</field>
<field name="categ_id" ref="product.product_category_1"/>
<field name="standard_price">70.0</field>
<field name="list_price">100.0</field>
<field name="type">product</field>
<field name="uom_id" ref="product.product_uom_unit"/>
<field name="uom_po_id" ref="product.product_uom_unit"/>
</record>
</data>
</openerp>

View File

@@ -1,13 +1,13 @@
# Translation of OpenERP Server.
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_rma_stock_location
# * crm_rma_stock_location
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-09-12 11:27+0000\n"
"PO-Revision-Date: 2014-09-12 11:27+0000\n"
"POT-Creation-Date: 2015-11-25 21:48+0000\n"
"PO-Revision-Date: 2015-11-25 21:48+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -16,39 +16,221 @@ msgstr ""
"Plural-Forms: \n"
#. module: crm_rma_stock_location
#: model:ir.model.fields,field_description:crm_rma_stock_location.field_stock_warehouse_lot_rma_id
#: field:stock.warehouse,lot_rma_id:0
msgid "Location RMA"
#: view:claim.make.picking.from.picking.wizard:crm_rma_stock_location.view_claim_picking_from_picking
msgid "Cancel"
msgstr ""
#. module: crm_rma_stock_location
#: code:_description:0
#: model:ir.model,name:crm_rma_stock_location.model_product_product
#: model:ir.actions.act_window,name:crm_rma_stock_location.action_loss_picking_from_claim_picking
msgid "Create Incoming Shipment to Breakage Loss Location"
msgstr ""
#. module: crm_rma_stock_location
#: model:ir.actions.act_window,name:crm_rma_stock_location.action_used_picking_from_claim_picking
msgid "Create Incoming Shipment to Refurbish Location"
msgstr ""
#. module: crm_rma_stock_location
#: model:ir.actions.act_window,name:crm_rma_stock_location.action_stock_picking_from_claim_picking
msgid "Create Incoming Shipment to Stock"
msgstr ""
#. module: crm_rma_stock_location
#: model:ir.actions.act_window,name:crm_rma_stock_location.action_claim_picking_loss
msgid "Create a Product Loss"
msgstr ""
#. module: crm_rma_stock_location
#: view:claim.make.picking.from.picking.wizard:crm_rma_stock_location.view_claim_picking_from_picking
msgid "Create picking"
msgstr ""
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,create_uid:0
msgid "Created by"
msgstr ""
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,create_date:0
msgid "Created on"
msgstr ""
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/wizards/claim_make_picking_from_picking.py:89
#: field:claim.make.picking.from.picking.wizard,picking_line_dest_location:0
#, python-format
msgid "Dest. Location"
msgstr ""
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,id:0
msgid "ID"
msgstr ""
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,write_uid:0
msgid "Last Updated by"
msgstr ""
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,write_date:0
msgid "Last Updated on"
msgstr ""
#. module: crm_rma_stock_location
#: help:claim.make.picking.from.picking.wizard,picking_line_source_location:0
msgid "Source location where the returned products are"
msgstr ""
#. module: crm_rma_stock_location
#: help:claim.make.picking.from.picking.wizard,picking_line_dest_location:0
msgid "Target location to send returned products"
msgstr ""
#. module: crm_rma_stock_location
#: view:claim.make.picking.from.picking.wizard:crm_rma_stock_location.view_claim_picking_from_picking
msgid "Locations"
msgstr ""
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/models/stock_warehouse.py:62
#, python-format
msgid "Loss"
msgstr ""
#. module: crm_rma_stock_location
#: field:stock.warehouse,loss_loc_id:0
msgid "Loss Location"
msgstr ""
#. module: crm_rma_stock_location
#: view:crm.claim:crm_rma_stock_location.crm_claim_rma_form_view_loss
msgid "New Product Loss"
msgstr ""
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,picking_line_ids:0
msgid "Picking lines"
msgstr ""
#. module: crm_rma_stock_location
#: model:ir.model,name:crm_rma_stock_location.model_product_product
msgid "Product"
msgstr ""
#. module: crm_rma_stock_location
#: model:stock.location,name:crm_rma_stock_location.stock_location_rma
msgid "RMA"
#: model:ir.model,name:crm_rma_stock_location.model_product_template
msgid "Product Template"
msgstr ""
#. module: crm_rma_stock_location
#: model:ir.model.fields,field_description:crm_rma_stock_location.field_product_product_rma_virtual_available
#: field:product.product,rma_virtual_available:0
#: view:product.product:crm_rma_stock_location.rma_product_product_tree_view
msgid "Product Variants"
msgstr ""
#. module: crm_rma_stock_location
#: view:stock.picking:crm_rma_stock_location.picking_in_form
msgid "Product to Loss"
msgstr ""
#. module: crm_rma_stock_location
#: view:stock.picking:crm_rma_stock_location.picking_in_form
msgid "Product to refurbish stock"
msgstr ""
#. module: crm_rma_stock_location
#: view:stock.picking:crm_rma_stock_location.picking_in_form
msgid "Product to stock"
msgstr ""
#. module: crm_rma_stock_location
#: model:stock.location,name:crm_rma_stock_location.location_rma_a
msgid "RMA - Box A"
msgstr ""
#. module: crm_rma_stock_location
#: model:stock.location,name:crm_rma_stock_location.location_rma_b
msgid "RMA - Box B"
msgstr ""
#. module: crm_rma_stock_location
#: view:product.product:crm_rma_stock_location.rma_product_search_view
msgid "RMA Available Products"
msgstr ""
#. module: crm_rma_stock_location
#: model:stock.location,name:crm_rma_stock_location.location_rma
msgid "RMA Demo"
msgstr ""
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/models/product_product.py:42
#, python-format
msgid "RMA Forecasted Quantity"
msgstr ""
#. module: crm_rma_stock_location
#: model:ir.model.fields,field_description:crm_rma_stock_location.field_product_product_rma_qty_available
#: field:product.product,rma_qty_available:0
#: view:product.product:crm_rma_stock_location.rma_product_search_view
msgid "RMA Products"
msgstr ""
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/models/product_product.py:36
#, python-format
msgid "RMA Quantity On Hand"
msgstr ""
#. module: crm_rma_stock_location
#: code:_description:0
#: model:ir.model,name:crm_rma_stock_location.model_stock_warehouse
#: code:addons/crm_rma_stock_location/models/stock_warehouse.py:56
#, python-format
msgid "Refurbish"
msgstr ""
#. module: crm_rma_stock_location
#: field:stock.warehouse,lot_refurbish_id:0
msgid "Refurbish Location"
msgstr ""
#. module: crm_rma_stock_location
#: view:claim.make.picking.from.picking.wizard:crm_rma_stock_location.view_claim_picking_from_picking
msgid "Select lines for picking"
msgstr ""
#. module: crm_rma_stock_location
#: view:claim.make.picking.from.picking.wizard:crm_rma_stock_location.view_claim_picking_from_picking
msgid "Select lines to add in picking"
msgstr ""
#. module: crm_rma_stock_location
#: model:product.template,name:crm_rma_stock_location.product_socket_product_template
msgid "Socket"
msgstr ""
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/wizards/claim_make_picking_from_picking.py:85
#: field:claim.make.picking.from.picking.wizard,picking_line_source_location:0
#, python-format
msgid "Source Location"
msgstr ""
#. module: crm_rma_stock_location
#: model:ir.actions.act_window,name:crm_rma_stock_location.rma_product_variant_action
#: model:ir.ui.menu,name:crm_rma_stock_location.menu_stock_rma
msgid "RMA Stock"
msgstr ""
#. module: crm_rma_stock_location
#: model:ir.model,name:crm_rma_stock_location.model_stock_warehouse
msgid "Warehouse"
msgstr ""
#. module: crm_rma_stock_location
#: model:ir.model,name:crm_rma_stock_location.model_claim_make_picking_wizard
msgid "Wizard to create pickings from claim lines"
msgstr ""
#. module: crm_rma_stock_location
#: model:ir.model,name:crm_rma_stock_location.model_claim_make_picking_from_picking_wizard
msgid "Wizard to create pickings from picking lines"
msgstr ""

View File

@@ -0,0 +1,239 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_rma_stock_location
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-11-25 21:48+0000\n"
"PO-Revision-Date: 2015-11-25 21:48+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: crm_rma_stock_location
#: view:claim.make.picking.from.picking.wizard:crm_rma_stock_location.view_claim_picking_from_picking
msgid "Cancel"
msgstr "Cancelar"
#. module: crm_rma_stock_location
#: model:ir.actions.act_window,name:crm_rma_stock_location.action_loss_picking_from_claim_picking
msgid "Create Incoming Shipment to Breakage Loss Location"
msgstr "Crear un envío de entrada hacia la ubicación de pérdida de productos dañados"
#. module: crm_rma_stock_location
#: model:ir.actions.act_window,name:crm_rma_stock_location.action_used_picking_from_claim_picking
msgid "Create Incoming Shipment to Refurbish Location"
msgstr "Crear un envío de entrada hacia la ubicación de productos restaurados"
#. module: crm_rma_stock_location
#: model:ir.actions.act_window,name:crm_rma_stock_location.action_stock_picking_from_claim_picking
msgid "Create Incoming Shipment to Stock"
msgstr "Crear un envío de entrada a Existencias"
#. module: crm_rma_stock_location
#: model:ir.actions.act_window,name:crm_rma_stock_location.action_claim_picking_loss
msgid "Create a Product Loss"
msgstr "Registrar una pérdida de producto"
#. module: crm_rma_stock_location
#: view:claim.make.picking.from.picking.wizard:crm_rma_stock_location.view_claim_picking_from_picking
msgid "Create picking"
msgstr "Crear un albarán"
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,create_uid:0
msgid "Created by"
msgstr "Creado por"
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,create_date:0
msgid "Created on"
msgstr "Creado el"
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/wizards/claim_make_picking_from_picking.py:89
#: field:claim.make.picking.from.picking.wizard,picking_line_dest_location:0
#, python-format
msgid "Dest. Location"
msgstr "Ubicación destino"
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,id:0
msgid "ID"
msgstr ""
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,write_uid:0
msgid "Last Updated by"
msgstr "Actualizado por"
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,write_date:0
msgid "Last Updated on"
msgstr "Actualizado el"
#. module: crm_rma_stock_location
#: help:claim.make.picking.from.picking.wizard,picking_line_source_location:0
msgid "Source location where the returned products are"
msgstr "Ubicación origen de los productos devueltos"
#. module: crm_rma_stock_location
#: help:claim.make.picking.from.picking.wizard,picking_line_dest_location:0
msgid "Target location to send returned products"
msgstr "Ubicación destino de los productos devueltos"
#. module: crm_rma_stock_location
#: view:claim.make.picking.from.picking.wizard:crm_rma_stock_location.view_claim_picking_from_picking
msgid "Locations"
msgstr "Ubicaciones"
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/models/stock_warehouse.py:62
#, python-format
msgid "Loss"
msgstr "Pérdida"
#. module: crm_rma_stock_location
#: field:stock.warehouse,loss_loc_id:0
msgid "Loss Location"
msgstr "Ubicación de Pérdida"
#. module: crm_rma_stock_location
#: view:crm.claim:crm_rma_stock_location.crm_claim_rma_form_view_loss
msgid "New Product Loss"
msgstr "Nueva Pérdida de Producto"
#. module: crm_rma_stock_location
#: field:claim.make.picking.from.picking.wizard,picking_line_ids:0
msgid "Picking lines"
msgstr "Líneas de albarán"
#. module: crm_rma_stock_location
#: model:ir.model,name:crm_rma_stock_location.model_product_product
msgid "Product"
msgstr "Producto"
#. module: crm_rma_stock_location
#: model:ir.model,name:crm_rma_stock_location.model_product_template
msgid "Product Template"
msgstr "Producto Plantilla"
#. module: crm_rma_stock_location
#: view:product.product:crm_rma_stock_location.rma_product_product_tree_view
msgid "Product Variants"
msgstr "Variantes del Producto"
#. module: crm_rma_stock_location
#: view:stock.picking:crm_rma_stock_location.picking_in_form
msgid "Product to Loss"
msgstr "Producto a Pérdida"
#. module: crm_rma_stock_location
#: view:stock.picking:crm_rma_stock_location.picking_in_form
msgid "Product to refurbish stock"
msgstr "Producto a Existencias de restaurados"
#. module: crm_rma_stock_location
#: view:stock.picking:crm_rma_stock_location.picking_in_form
msgid "Product to stock"
msgstr "Producto a Existencias"
#. module: crm_rma_stock_location
#: model:stock.location,name:crm_rma_stock_location.location_rma_a
msgid "RMA - Box A"
msgstr "RMA - Caja A"
#. module: crm_rma_stock_location
#: model:stock.location,name:crm_rma_stock_location.location_rma_b
msgid "RMA - Box B"
msgstr "RMA - Caja B"
#. module: crm_rma_stock_location
#: view:product.product:crm_rma_stock_location.rma_product_search_view
msgid "RMA Available Products"
msgstr "Productos disponibles en RMA"
#. module: crm_rma_stock_location
#: model:stock.location,name:crm_rma_stock_location.location_rma
msgid "RMA Demo"
msgstr "Demostración RMA"
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/models/product_product.py:42
#: code:addons/crm_rma_stock_location/models/product_template.py:42
#, python-format
msgid "RMA Forecasted Quantity"
msgstr "Pronóstico de Cantidades en RMA"
#. module: crm_rma_stock_location
#: view:product.product:crm_rma_stock_location.rma_product_search_view
msgid "RMA Products"
msgstr "Productos en RMA"
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/models/product_product.py:36
#: code:addons/crm_rma_stock_location/models/product_template.py:36
#, python-format
msgid "RMA Quantity On Hand"
msgstr "Cantidades Disponibles en RMA"
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/models/stock_warehouse.py:56
#, python-format
msgid "Refurbish"
msgstr "Restaurar"
#. module: crm_rma_stock_location
#: field:stock.warehouse,lot_refurbish_id:0
msgid "Refurbish Location"
msgstr "Ubicación de Restaurados"
#. module: crm_rma_stock_location
#: view:claim.make.picking.from.picking.wizard:crm_rma_stock_location.view_claim_picking_from_picking
msgid "Select lines for picking"
msgstr "Seleccionar lineas para albarán"
#. module: crm_rma_stock_location
#: view:claim.make.picking.from.picking.wizard:crm_rma_stock_location.view_claim_picking_from_picking
msgid "Select lines to add in picking"
msgstr "Seleccionar lineas a agregar en albarán"
#. module: crm_rma_stock_location
#: model:product.template,name:crm_rma_stock_location.product_socket_product_template
msgid "Socket"
msgstr "Sócate"
#. module: crm_rma_stock_location
#: code:addons/crm_rma_stock_location/wizards/claim_make_picking_from_picking.py:85
#: field:claim.make.picking.from.picking.wizard,picking_line_source_location:0
#, python-format
msgid "Source Location"
msgstr "Ubicación origen"
#. module: crm_rma_stock_location
#: model:ir.actions.act_window,name:crm_rma_stock_location.rma_product_variant_action
#: model:ir.ui.menu,name:crm_rma_stock_location.menu_stock_rma
msgid "RMA Stock"
msgstr "Existencias en RMA"
#. module: crm_rma_stock_location
#: model:ir.model,name:crm_rma_stock_location.model_stock_warehouse
msgid "Warehouse"
msgstr "Almacén"
#. module: crm_rma_stock_location
#: model:ir.model,name:crm_rma_stock_location.model_claim_make_picking_wizard
msgid "Wizard to create pickings from claim lines"
msgstr "Asistente para create albaranes desde lineas de reclamo"
#. module: crm_rma_stock_location
#: model:ir.model,name:crm_rma_stock_location.model_claim_make_picking_from_picking_wizard
msgid "Wizard to create pickings from picking lines"
msgstr "Asistente para create albaranes desde lineas de albaranes"

View File

@@ -0,0 +1,16 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_rma_stock_location
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-07-18 00:48+0000\n"
"PO-Revision-Date: 2015-07-18 00:48+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"

View File

@@ -0,0 +1,16 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_rma_stock_location
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-07-18 00:48+0000\n"
"PO-Revision-Date: 2015-07-18 00:48+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"

View File

@@ -0,0 +1,16 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_rma_stock_location
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-07-18 00:48+0000\n"
"PO-Revision-Date: 2015-07-18 00:48+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"

View File

@@ -1,9 +1,10 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2013 Camptocamp
# Copyright 2009-2013 Akretion,
# Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, Joel Grand-Guillaume
# Copyright 2015 Vauxoo
# Copyright 2014 Camptocamp SA
# Author: Guewen Baconnier,
# Osval Reyes
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -19,21 +20,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import fields, orm
from openerp import SUPERUSER_ID
class stock_warehouse(orm.Model):
_inherit = "stock.warehouse"
_columns = {
'lot_carrier_loss_id': fields.many2one(
'stock.location',
'Location Carrier Loss'),
'lot_breakage_loss_id': fields.many2one(
'stock.location',
'Location Breakage Loss'),
'lot_refurbish_id': fields.many2one(
'stock.location',
'Location Refurbish'),
}
def post_init_hook(cr, registry):
stock_wh = registry['stock.warehouse']
for wh_id in stock_wh.browse(cr, SUPERUSER_ID,
stock_wh.search(cr, SUPERUSER_ID, [])):
vals = stock_wh.create_locations_rma(cr, SUPERUSER_ID, wh_id)
stock_wh.write(cr, SUPERUSER_ID, wh_id.id, vals)

View File

@@ -1,8 +1,13 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
# Copyright 2014 Camptocamp SA
# Copyright 2015 Vauxoo
# Copyright 2013-2014 Camptocamp SA
# Copyright 2009-2013 Akretion,
# Author: Guewen Baconnier,
# Emmanuel Samyn, Raphaël Valyi, Sébastien Beau,
# Joel Grand-Guillaume,
# Osval Reyes
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -19,12 +24,6 @@
#
##############################################################################
from openerp.osv import orm, fields
class StockWarehouse(orm.Model):
_inherit = 'stock.warehouse'
_columns = {
'lot_rma_id': fields.many2one('stock.location', 'Location RMA'),
}
from . import product_product
from . import product_template
from . import stock_warehouse

View File

@@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
# Copyright 2014 Camptocamp SA
#
# 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 _, api, fields, models
import openerp.addons.decimal_precision as dp
from openerp.tools.float_utils import float_round
from openerp.tools.safe_eval import safe_eval as eval
class ProductProduct(models.Model):
_inherit = 'product.product'
rma_qty_available = fields.Float(
compute='_rma_product_available',
digits_compute=dp.get_precision('Product Unit of Measure'),
search='_search_rma_product_quantity',
string=_('RMA Quantity On Hand'))
rma_virtual_available = fields.Float(
compute='_rma_product_available',
digits_compute=dp.get_precision('Product Unit of Measure'),
search='_search_rma_product_quantity',
string=_('RMA Forecasted Quantity'))
def _search_rma_product_quantity(self, operator, value):
res = []
# to prevent sql injections
assert operator in ('<', '>', '=', '!=',
'<=', '>='), 'Invalid domain operator'
assert isinstance(value, (float, int)), 'Invalid domain right operand'
if operator == '=':
operator = '=='
ids = []
product_ids = self.search([])
if product_ids:
for element in product_ids:
localdict = {'virtual': element.rma_virtual_available,
'qty': element.rma_qty_available,
'value': value}
if eval('qty %s value or virtual %s value' %
(operator, operator), localdict):
ids.append(element.id)
res.append(('id', 'in', ids))
return res
@api.multi
def _rma_product_available(self):
"""
Finds the incoming and outgoing quantity of product for the RMA
locations.
"""
context = self.env.context
warehouse_id = context.get('warehouse_id')
ctx = context.copy()
location_ids = set()
for product in self:
if warehouse_id and warehouse_id.lot_rma_id:
location_ids.add(warehouse_id.lot_rma_id.id)
else:
warehouse_ids = self.env['stock.warehouse'].search([])
if not warehouse_ids:
return
for warehouse_id in warehouse_ids:
if warehouse_id.lot_rma_id:
location_ids.add(warehouse_id.lot_rma_id.id)
if not location_ids:
return
ctx['location'] = list(location_ids)
domain_products = [('product_id', 'in', [product.id])]
domain_quant, domain_move_in, domain_move_out = \
product.with_context(ctx)._get_domain_locations()
domain_move_in += product.with_context(ctx)._get_domain_dates() + \
[('state', 'not in', ('done', 'cancel', 'draft'))] + \
domain_products
domain_move_out += product.with_context(ctx).\
_get_domain_dates() + \
[('state', 'not in', ('done', 'cancel', 'draft'))] + \
domain_products
domain_quant += domain_products
moves_in = []
moves_out = []
lot_id = context.get('lot_id')
if lot_id:
domain_quant.append(('lot_id', '=', lot_id))
else:
moves_in = self.env['stock.move'].\
with_context(ctx).read_group(domain_move_in,
['product_id', 'product_qty'],
['product_id'])
moves_out = self.env['stock.move'].\
with_context(ctx).read_group(domain_move_out,
['product_id', 'product_qty'],
['product_id'])
quants = self.env['stock.quant'].with_context(ctx).read_group(
domain_quant, ['product_id', 'qty'], ['product_id'])
quants = dict([(item.get('product_id')[0],
item.get('qty')) for item in quants])
moves_in = dict([(item.get('product_id')[0],
item.get('product_qty')) for item in moves_in])
moves_out = dict([(item.get('product_id')[0],
item.get('product_qty')) for item in moves_out])
product.rma_qty_available = \
float_round(quants.get(product.id, 0.0),
precision_rounding=product.uom_id.rounding)
product.rma_virtual_available = \
float_round(quants.get(product.id, 0.0) +
moves_in.get(product.id, 0.0) -
moves_out.get(product.id, 0.0),
precision_rounding=product.uom_id.rounding)

View File

@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Copyright 2014 Camptocamp SA
# Author: Guewen Baconnier,
# Osval Reyes
#
# 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 _, api, fields, models
import openerp.addons.decimal_precision as dp
class ProductTemplate(models.Model):
_inherit = 'product.template'
rma_qty_available = fields.Float(compute='_rma_template_available',
digits_compute=dp.
get_precision('Product Unit '
'of Measure'),
string=_('RMA Quantity On Hand'))
rma_virtual_available = fields.Float(compute='_rma_template_available',
digits_compute=dp.
get_precision('Product Unit'
' of Measure'),
string=_('RMA Forecasted Quantity'))
@api.multi
def _rma_template_available(self):
for product in self:
product.rma_qty_available = sum(
product.mapped('product_variant_ids.rma_virtual_available'))
product.rma_virtual_available = sum(
product.mapped('product_variant_ids.rma_virtual_available'))

View File

@@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2013 Camptocamp
# Copyright 2009-2013 Akretion,
# Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau,
# Joel Grand-Guillaume
#
# 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 _, api, fields, models
class StockWarehouse(models.Model):
_inherit = "stock.warehouse"
loss_loc_id = fields.Many2one('stock.location', 'Loss Location')
lot_refurbish_id = fields.Many2one('stock.location', 'Refurbish Location')
@api.model
def create_locations_rma(self, wh_id):
vals = {}
location_obj = self.env['stock.location']
context_with_inactive = self.env.context.copy()
context_with_inactive['active_test'] = False
wh_loc_id = wh_id.view_location_id.id
vals_new = super(StockWarehouse, self).create_locations_rma(wh_id)
loc_vals = {
'location_id': wh_loc_id,
'active': True,
}
if vals.get('company_id'):
loc_vals['company_id'] = vals.get('company_id')
if not wh_id.lot_refurbish_id:
loc_vals.update({
'name': _('Refurbish'),
'usage': 'production'
})
location_id = location_obj.with_context(context_with_inactive).\
create(loc_vals)
vals['lot_refurbish_id'] = location_id.id
if not wh_id.loss_loc_id:
loc_vals.update({
'name': _('Loss'),
'usage': 'inventory'
})
location_id = location_obj.with_context(context_with_inactive).\
create(loc_vals)
vals['loss_loc_id'] = location_id.id
vals.update(vals_new)
return vals

View File

@@ -1,106 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Guewen Baconnier
# Copyright 2014 Camptocamp SA
#
# 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.osv import orm, fields
import openerp.addons.decimal_precision as dp
class ProductProduct(orm.Model):
_inherit = 'product.product'
def _rma_product_available(self, cr, uid, ids, field_names=None, arg=False,
context=None):
""" Finds the incoming and outgoing quantity of product for the RMA
locations.
"""
if field_names is None:
field_names = []
if context is None:
context = {}
warehouse_obj = self.pool['stock.warehouse']
res = {}
for id in ids:
res[id] = {}.fromkeys(field_names, 0.0)
for field in field_names:
ctx = context.copy()
warehouse_id = ctx.get('warehouse_id')
# no dependency on 'sale', the same oddness is done in
# 'stock' so I kept it here
if ctx.get('shop') and self.pool.get('sale.shop'):
shop_obj = self.pool['sale.shop']
shop_id = ctx['shop']
warehouse = shop_obj.read(cr, uid, shop_id,
['warehouse_id'],
context=ctx)
warehouse_id = warehouse['warehouse_id'][0]
if warehouse_id:
rma_id = warehouse_obj.read(cr, uid,
warehouse_id,
['lot_rma_id'],
context=ctx)['lot_rma_id'][0]
if rma_id:
ctx['location'] = rma_id
else:
location_ids = set()
wids = warehouse_obj.search(cr, uid, [], context=context)
if not wids:
return res
for wh in warehouse_obj.browse(cr, uid, wids, context=context):
if wh.lot_rma_id:
location_ids.add(wh.lot_rma_id.id)
if not location_ids:
return res
ctx['location'] = list(location_ids)
ctx['compute_child'] = True
compute = {
'rma_qty_available': {
'states': ('done', ),
'what': ('in', 'out')
},
'rma_virtual_available': {
'states': ('confirmed', 'waiting', 'assigned', 'done'),
'what': ('in', 'out')
}
}
ctx.update(compute[field])
stock = self.get_product_available(cr, uid, ids, context=ctx)
for id in ids:
res[id][field] = stock.get(id, 0.0)
return res
_columns = {
'rma_qty_available': fields.function(
_rma_product_available,
type='float',
multi='rma_qty',
digits_compute=dp.get_precision('Product Unit of Measure'),
string='RMA Quantity On Hand'),
'rma_virtual_available': fields.function(
_rma_product_available,
type='float',
multi='rma_qty',
digits_compute=dp.get_precision('Product Unit of Measure'),
string='RMA Forecasted Quantity'),
}

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<record id="product_product_tree_view" model="ir.ui.view">
<field name="name">product.product.tree</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_product_tree_view"/>
<field name="arch" type="xml">
<field name="virtual_available" position="after">
<field name="rma_qty_available"/>
<field name="rma_virtual_available"/>
</field>
</field>
</record>
<record id="view_normal_procurement_locations_form" model="ir.ui.view">
<field name="name">product.normal.procurement.locations.inherit</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="stock.view_normal_procurement_locations_form"/>
<field name="arch" type="xml">
<field name="virtual_available" position="after">
<field name="rma_qty_available" class="oe_inline"/>
<field name="rma_virtual_available" class="oe_inline"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<record id="stock_location_rma" model="stock.location">
<field name="name">RMA</field>
<field name="usage">internal</field>
<field name="location_id" ref="stock.stock_location_company"/>
</record>
<record id="stock.warehouse0" model="stock.warehouse">
<field name="lot_rma_id" ref="stock_location_rma"/>
</record>
</data>
</openerp>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<record id="view_warehouse_form" model="ir.ui.view">
<field name="name">view_warehouse_form</field>
<field name="model">stock.warehouse</field>
<field name="inherit_id" ref="stock.view_warehouse" />
<field name="arch" type="xml">
<xpath expr="/form/group/group/field[@name='lot_output_id']" position="after">
<field name="lot_rma_id"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@@ -1,72 +0,0 @@
-
I create RMA locations
-
!record {model: stock.location, id: location_rma}:
name: RMA
usage: view
-
!record {model: stock.location, id: location_rma_a}:
name: RMA - Box A
usage: internal
location_id: location_rma
-
!record {model: stock.location, id: location_rma_b}:
name: RMA - Box B
usage: internal
location_id: location_rma
-
I set the RMA location on the warehouse
-
!record {model: stock.warehouse, id: stock.warehouse0}:
lot_rma_id: location_rma
-
I create a product
-
!record {model: product.product, id: product_socket}:
default_code: 002
name: Sockets
type: product
categ_id: product.product_category_1
list_price: 100.0
standard_price: 70.0
uom_id: product.product_uom_unit
uom_po_id: product.product_uom_unit
-
I create a physical inventory with 50 units in Box A and 30 in Box B
-
!record {model: stock.inventory, id: stock_inventory_socket}:
name: Inventory for Sockets
-
!record {model: stock.inventory.line, id: stock_inventory_line_socket_1}:
product_id: product_socket
product_uom: product.product_uom_unit
inventory_id: stock_inventory_socket
product_qty: 50.0
location_id: location_rma_a
-
!record {model: stock.inventory.line, id: stock_inventory_line_socket_2}:
product_id: product_socket
product_uom: product.product_uom_unit
inventory_id: stock_inventory_socket
product_qty: 30.0
location_id: location_rma_b
-
I confirm the physical inventory
-
!python {model: stock.inventory}: |
self.action_confirm(cr, uid, [ref('stock_inventory_socket')], context=context)
-
I confirm the move in Box A
-
!python {model: stock.inventory}: |
inventory = self.browse(cr, uid, ref('stock_inventory_socket'), context=context)
assert len(inventory.move_ids) == len(inventory.inventory_line_id), "moves are not correspond."
for move in inventory.move_ids:
if move.location_dest_id.id == ref('location_rma_a'):
move.action_done()
-
I check my RMA quantities, I should have 50 on hands and 80 forecasted
-
!assert {model: product.product, id: product_socket, string: RMA quantity is wrong}:
- rma_qty_available == 50
- rma_virtual_available == 80

View File

@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2013 Camptocamp
# Copyright 2009-2013 Akretion,
# Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, Joel Grand-Guillaume
# Copyright 2015 Vauxoo
# Author: Yanina Aular, Osval Reyes
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -19,5 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import stock
from . import wizard
from . import test_crm_rma_stock_location
from . import test_make_picking_from_picking

View File

@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Author: Osval Reyes
#
# 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.tests.common import TransactionCase
class TestCrmRmaStockLocation(TransactionCase):
def setUp(self):
super(TestCrmRmaStockLocation, self).setUp()
self.inventory = self.env['stock.inventory']
self.inventory_line = self.env['stock.inventory.line']
self.location_id = self.env['stock.location'].search(
[('name', '=', 'RMA'), ('location_id.name', '=', 'WH')])
self.warehouse_id = self.env['stock.warehouse'].browse(
self.ref('stock.warehouse0'))
self.lot_rma_id = self.warehouse_id.lot_rma_id
self.product_uom_id = self.ref('product.product_uom_unit')
self.product_socket_id = self.env['product.product'].browse(
self.ref('crm_rma_stock_location.product_socket'))
def test_01_test(self):
inventory_id = self.inventory.create({
'name': 'Test Inventory 001',
'location_id': self.location_id.id,
'filter': 'product',
'product_id': self.product_socket_id.id,
})
inventory_line_id_a = self.inventory_line.create({
'inventory_id': inventory_id.id,
'product_id': self.product_socket_id.id,
'product_uom_id': self.product_uom_id,
'product_qty': 100,
'location_id': self.lot_rma_id.id
})
inventory_line_id_b = self.inventory_line.create({
'inventory_id': inventory_id.id,
'product_id': self.product_socket_id.id,
'product_uom_id': self.product_uom_id,
'product_qty': 10,
'location_id': self.lot_rma_id.id
})
inventory_id.prepare_inventory()
inventory_id.action_done()
qty = inventory_line_id_a.product_qty + inventory_line_id_b.product_qty
self.assertEquals(self.product_socket_id.rma_qty_available, qty)
self.assertEquals(self.product_socket_id.rma_virtual_available, qty)
self.assertEquals(
self.product_socket_id.product_tmpl_id.rma_qty_available, qty)
self.assertEquals(
self.product_socket_id.product_tmpl_id.rma_virtual_available, qty)
res = self.product_socket_id._search_rma_product_quantity(
'=',
inventory_line_id_a.product_qty + inventory_line_id_b.product_qty)
self.assertEquals(self.product_socket_id.id, res[0][2][0])

View File

@@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Yanina Aular
# Copyright 2015 Vauxoo
#
# 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.tests.common import TransactionCase
class TestPickingFromPicking(TransactionCase):
def setUp(self):
super(TestPickingFromPicking, self).setUp()
self.stock_warehouse = self.env['stock.warehouse']
self.claim_id = self.create_claim()
self.wizardmakepicking = self.env['claim_make_picking.wizard']
self.claim_picking_wizard = \
self.env['claim.make.picking.from.picking.wizard']
self.get_default_locations()
def create_claim(self):
claim_id = self.env['crm.claim'].browse(
self.ref("crm_claim.crm_claim_6"))
claim_id.write({
'claim_line_ids': [(0, 0, {
'name': str(claim_id.id) + 'test 1',
'claim_origin': u'damaged',
'product_id': self.ref('product.product_product_8')
}), (0, 0, {
'name': str(claim_id.id) + 'test 2',
'claim_origin': u'none',
'product_id': self.ref('product.product_product_6')
})]
})
return claim_id
def get_default_locations(self):
"""
Return locations for RMA, Loss and Refurbish
"""
self.main_warehouse_id = self.stock_warehouse.browse(
self.ref("stock.warehouse0"))
self.loc_rma = self.main_warehouse_id.lot_rma_id
self.loss_loc = self.main_warehouse_id.loss_loc_id
self.loc_refurbish = self.main_warehouse_id.lot_refurbish_id
def test_01_get_dest_loc(self):
# Create Picking from Customers to RMA
# with button New Products Return
wiz_context = {
'active_id': self.claim_id.id,
'warehouse_id': self.claim_id.warehouse_id.id,
'partner_id': self.claim_id.partner_id.id,
'picking_type': self.claim_id.warehouse_id.rma_in_type_id.id,
}
wizard_id = self.wizardmakepicking.with_context(wiz_context).create({})
res = wizard_id.action_create_picking()
stock_picking_id = res.get('res_id')
# Create Picking 'Product to stock'
context = {
'active_id': stock_picking_id,
'picking_type': 'picking_stock',
}
claim_wizard = self.claim_picking_wizard.\
with_context(context).create({})
self.assertEquals(claim_wizard.picking_line_source_location.id,
self.loc_rma.id)
self.assertEquals(claim_wizard.picking_line_dest_location.id,
self.main_warehouse_id.lot_stock_id.id)
self.assertEquals(len(claim_wizard.picking_line_ids),
len(self.claim_id.claim_line_ids))
# Review number of picking lines with claim lines
picking_lines = claim_wizard.picking_line_ids
claim_lines = self.claim_id.claim_line_ids
for num in xrange(0, len(picking_lines)):
band = False
for num2 in xrange(0, len(claim_lines)):
if claim_lines[num].product_id.id == \
picking_lines[num2].product_id.id:
band = True
self.assertEquals(True, band)
claim_wizard.with_context(context).action_create_picking_from_picking()
# Create Picking 'Product to Loss'
claim_wizard = self.claim_picking_wizard.\
with_context({
'active_id': stock_picking_id,
'picking_type': 'picking_loss',
}).create({})
self.assertEquals(claim_wizard.picking_line_source_location.id,
self.loc_rma.id)
self.assertEquals(claim_wizard.picking_line_dest_location.id,
self.loss_loc.id)
def assert_picking_type(self, picking_type_str=''):
new_context = {
'active_id': self.claim_id.id,
'warehouse_id': self.claim_id.warehouse_id.id,
'partner_id': self.claim_id.partner_id.id,
'picking_type': picking_type_str,
}
wizard_id = self.wizardmakepicking.with_context(new_context).create({})
default_location_dest_id = eval(
'self.claim_id.warehouse_id.'
'rma_%s_type_id.default_location_dest_id' % picking_type_str)
self.assertEquals(
wizard_id.claim_line_dest_location_id, default_location_dest_id)
def test_02_picking_types_in_out_int(self):
self.assert_picking_type('in')
self.assert_picking_type('out')
self.assert_picking_type('int')
def test_03_picking_type_loss(self):
new_context = {
'active_id': self.claim_id.id,
'warehouse_id': self.claim_id.warehouse_id.id,
'partner_id': self.claim_id.partner_id.id,
'picking_type': 'loss',
}
wizard_id = self.wizardmakepicking.with_context(new_context).create({})
default_location_dest_id = eval(
'self.claim_id.warehouse_id.loss_loc_id')
self.assertEquals(
wizard_id.claim_line_dest_location_id, default_location_dest_id)

View File

@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="crm_claim_rma_form_view_loss">
<field name="name">CRM - Claim product return Form</field>
<field name="model">crm.claim</field>
<field name="inherit_id" ref="crm_claim_rma.crm_claim_rma_form_view"/>
<field name="arch" type="xml">
<xpath expr="//button[@string='New Delivery']" position="after">
<button name="%(action_claim_picking_loss)d"
string="New Product Loss"
type="action" target="new"
context="{'warehouse_id': warehouse_id,
'partner_id': partner_id}"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="rma_product_product_tree_view" model="ir.ui.view">
<field name="name">product.stock.tree.inherit</field>
<field name="model">product.product</field>
<field name="arch" type="xml">
<tree string="Product Variants" create="false">
<field name="default_code"/>
<field name="name"/>
<field name="attribute_value_ids" widget="many2many_tags"/>
<field name="rma_qty_available"/>
<field name="rma_virtual_available"/>
</tree>
</field>
</record>
<record id="rma_product_search_view" model="ir.ui.view">
<field name="name">product.product.search</field>
<field name="model">product.product</field>
<field name="arch" type="xml">
<search string="RMA Products">
<separator/>
<filter name="rma_available" string="RMA Available Products"
domain="['|', ('rma_qty_available','&gt;',0), ('rma_virtual_available','&gt;',0)]"/>
</search>
</field>
</record>
<record id="rma_product_variant_action" model="ir.actions.act_window">
<field name="name">RMA Stock</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.product</field>
<field name="view_mode">tree</field>
<field name="view_type">form</field>
<field name="view_id" ref="rma_product_product_tree_view"/>
<field name="search_view_id" ref="rma_product_search_view"/>
<field name="context">{'search_default_rma_available': 1}</field>
</record>
<menuitem action="rma_product_variant_action"
id="menu_stock_rma" parent="base.menu_aftersale"
name="RMA Stock"
sequence="100"/>
</data>
</openerp>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_template_property_form" model="ir.ui.view">
<field name="name">product.normal.procurement.locations.inherit</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="stock.view_template_property_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='virtual_available']" position="after">
<field name="rma_qty_available"/>
<field name="rma_virtual_available"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@@ -2,25 +2,23 @@
<openerp>
<data>
<!-- INHERITED VIEW FOR THE OBJECT : stock_picking -->
<record id="picking_in_form" model="ir.ui.view">
<field name="name">crm_claim_rma.picking_in_form</field>
<field name="model">stock.picking.in</field>
<field name="inherit_id" ref="stock.view_picking_in_form" />
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form"/>
<field name="arch" type="xml">
<!-- Those wizard aren't working yet -->
<xpath expr="/form/header/button[@string='Return Products']" position="after">
<button name="%(action_stock_picking_from_claim_picking)d"
<xpath expr="//field[@name='state']" position="before">
<button name="%(action_stock_picking_from_claim_picking)d"
string="Product to stock" type="action"
attrs="{'invisible':['|',
('state','&lt;&gt;','done'),
('claim_id', '=', False)]}"/>
<button name="%(action_loss_picking_from_claim_picking)d"
<button name="%(action_loss_picking_from_claim_picking)d"
string="Product to Loss" type="action"
attrs="{'invisible':['|',
('state','&lt;&gt;','done'),
('claim_id', '=', False)]}"/>
<button name="%(action_used_picking_from_claim_picking)d"
<button name="%(action_used_picking_from_claim_picking)d"
string="Product to refurbish stock" type="action"
attrs="{'invisible':['|',
('state','&lt;&gt;','done'),
@@ -28,20 +26,5 @@
</xpath>
</field>
</record>
<record id="warehouse_form" model="ir.ui.view">
<field name="name">crm_claim_rma.warehouse_form</field>
<field name="model">stock.warehouse</field>
<field name="inherit_id" ref="crm_rma_stock_location.view_warehouse_form" />
<field name="arch" type="xml">
<xpath expr="/form/group/group/field[@name='lot_rma_id']" position="after">
<field name="lot_carrier_loss_id"/>
<field name="lot_breakage_loss_id"/>
<field name="lot_refurbish_id"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="warehouse_form" model="ir.ui.view">
<field name="name">crm_claim_rma.warehouse_form</field>
<field name="model">stock.warehouse</field>
<field name="inherit_id" ref="crm_rma_location.view_warehouse_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='lot_rma_id']" position="after">
<field name="loss_loc_id"/>
<field name="lot_refurbish_id"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@@ -2,8 +2,9 @@
##############################################################################
#
# Copyright 2013 Camptocamp
# Copyright 2009-2013 Akretion,
# Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, Joel Grand-Guillaume
# Copyright 2009-2013 Akretion,
# Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau,
# Joel Grand-Guillaume
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -20,4 +21,4 @@
#
##############################################################################
from . import claim_make_picking_from_picking
from . import claim_make_picking
from . import claim_make_picking

View File

@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Copyright (C) 2009-2012 Akretion
# Author: Emmanuel Samyn, Benoît GUILLOT <benoit.guillot@akretion.com>,
# Osval Reyes
#
# 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 models, fields
class ClaimMakePicking(models.TransientModel):
_inherit = 'claim_make_picking.wizard'
_description = 'Wizard to create pickings from claim lines'
def _default_claim_line_dest_location_id(self):
"""Return the location_id to use as destination.
If it's an outgoing shipment: take the customer stock property
If it's an incoming shipment take the location_dest_id common to all
lines, or if different, return None.
"""
picking_type = self.env.context.get('picking_type')
claim_id = self.env.context.get('active_id')
claim_record = self.env['crm.claim'].browse(claim_id)
if isinstance(picking_type, int):
picking_obj = self.env['stock.picking.type']
return picking_obj.browse(picking_type)\
.default_location_dest_id
if picking_type == 'out':
return claim_record.warehouse_id.rma_out_type_id.\
default_location_dest_id
elif picking_type == 'in':
return claim_record.warehouse_id.rma_in_type_id.\
default_location_dest_id
elif picking_type == 'int':
return claim_record.warehouse_id.rma_int_type_id.\
default_location_dest_id
elif picking_type == 'loss':
return claim_record.warehouse_id.loss_loc_id
return self.env['stock.location']
claim_line_dest_location_id = fields.Many2one(
default=_default_claim_line_dest_location_id)

View File

@@ -0,0 +1,178 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Copyright (C) 2009-2012 Akretion
# Author: Emmanuel Samyn, Benoît GUILLOT <benoit.guillot@akretion.com>,
# Osval Reyes
#
# 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 _, models, fields, api
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp import workflow
import time
class ClaimMakePickingFromPicking(models.TransientModel):
_name = 'claim.make.picking.from.picking.wizard'
_description = 'Wizard to create pickings from picking lines'
@api.model
def _get_default_warehouse(self):
warehouse_id = self.env['crm.claim']._get_default_warehouse()
return warehouse_id
@api.model
def _get_picking_lines(self):
move_lines = self.env['stock.picking'].\
browse(self.env.context.get('active_id')).move_lines
return [mov.id for mov in move_lines]
@api.model
def _get_source_loc(self):
"""
Get default source location
"""
warehouse_id = self._get_default_warehouse()
picking_obj = self.env['stock.picking']
picking_id = self.env.context.get('active_id')
picking_rec = picking_obj.browse(picking_id)
if picking_rec.location_dest_id:
return picking_rec.location_dest_id.id
else:
return warehouse_id.lot_rma_id.id
@api.model
def _get_dest_loc(self):
"""
Get default destination location
"""
warehouse_id = self._get_default_warehouse()
loc_id = self.env['stock.location']
picking_type = self.env.context.get('picking_type')
picking_type_obj = self.env['stock.picking.type']
if isinstance(picking_type, int):
pick_t = picking_type_obj.browse(picking_type)
loc_id = pick_t.default_location_dest_id
else:
if picking_type == 'picking_stock':
loc_id = warehouse_id.lot_stock_id.id
if picking_type == 'picking_loss':
loc_id = warehouse_id.loss_loc_id.id
if picking_type == 'picking_refurbish':
loc_id = warehouse_id.lot_refurbish_id.id
return loc_id
picking_line_source_location = fields.Many2one(
'stock.location', _('Source Location'),
help=_("Source location where the returned products are"),
required=True, default=_get_source_loc)
picking_line_dest_location = fields.Many2one(
'stock.location', _('Dest. Location'),
help=_("Target location to send returned products"),
required=True, default=_get_dest_loc)
picking_line_ids = fields.Many2many(
'stock.move', 'claim_picking_line_picking', 'claim_picking_id',
'picking_line_id', 'Picking lines', default=_get_picking_lines)
@api.multi
def action_cancel(self):
return {'type': 'ir.actions.act_window_close'}
@api.multi
def action_create_picking_from_picking(self):
"""
If "Create" button pressed
"""
picking_obj = self.env['stock.picking']
move_obj = self.env['stock.move']
view_obj = self.env['ir.ui.view']
if self.env.context.get('picking_type'):
context_type = self.env.context.get('picking_type')[8:]
note = 'Internal picking from RMA to %s' % context_type
name = 'Internal picking to %s' % context_type
view_id = view_obj.search([
('model', '=', 'stock.picking'),
('type', '=', 'form'),
('name', '=', 'stock.picking.form')
])[0]
prev_picking = picking_obj.browse(self.env.context.get('active_id'))
partner_id = prev_picking.partner_id.id
# create picking
picking_id = picking_obj.create({
'origin': prev_picking.origin,
'move_type': 'one',
'state': 'draft',
'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'partner_id': prev_picking.partner_id.id,
'invoice_state': "none",
'company_id': prev_picking.company_id.id,
'location_id': self.picking_line_source_location.id,
'location_dest_id': self.picking_line_dest_location.id,
'note': note,
'claim_id': prev_picking.claim_id.id,
'picking_type_id': prev_picking.claim_id.warehouse_id.id,
})
# Create picking lines
for wizard_picking_line in self.picking_line_ids:
move_id = move_obj.create({
'name': wizard_picking_line.product_id.name_template,
'priority': '0',
'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'date_expected': time.strftime(
DEFAULT_SERVER_DATETIME_FORMAT),
'product_id': wizard_picking_line.product_id.id,
'product_uom_qty': wizard_picking_line.product_uom_qty,
'product_uom': wizard_picking_line.product_uom.id,
'partner_id': prev_picking.partner_id.id,
'picking_id': picking_id.id,
'state': 'draft',
'price_unit': wizard_picking_line.price_unit,
'company_id': prev_picking.company_id.id,
'location_id': self.picking_line_source_location.id,
'location_dest_id': self.picking_line_dest_location.id,
'note': note,
'invoice_state': 'none',
})
wizard_picking_line.write(
{'move_dest_id': move_id.id})
wf_service = workflow
if picking_id:
wf_service.trg_validate(
self._uid, 'stock.picking',
picking_id.id,
'button_confirm',
self._cr)
picking_id.action_assign()
domain = "[('picking_type_id','=','%s'),('partner_id','=',%s)]" % (
prev_picking.claim_id.warehouse_id.rma_int_type_id.id, partner_id)
return {
'name': '%s' % name,
'view_type': 'form',
'view_mode': 'form',
'view_id': view_id.id,
'domain': domain,
'res_model': 'stock.picking',
'res_id': picking_id.id,
'type': 'ir.actions.act_window',
}

View File

@@ -6,10 +6,9 @@
-->
<openerp>
<data>
<record id="view_claim_picking_from_picking" model="ir.ui.view">
<field name="name">claim_picking</field>
<field name="model">claim_make_picking_from_picking.wizard</field>
<field name="model">claim.make.picking.from.picking.wizard</field>
<field name="arch" type="xml">
<form string="Select lines to add in picking">
<separator string="Locations" colspan="4"/>
@@ -18,46 +17,52 @@
<separator string="Select lines for picking" colspan="4"/>
<field name="picking_line_ids" nolabel="1" colspan="4"/>
<group col="4" colspan="2">
<button special="cancel" string="Cancel" name="action_cancel" type="object" icon='gtk-cancel'/>
<button name="action_create_picking_from_picking" string="Create picking"
icon='gtk-ok' type="object"/>
<button special="cancel" string="Cancel"
name="action_cancel" type="object"
icon='gtk-cancel'/>
<button name="action_create_picking_from_picking"
string="Create picking"
icon='gtk-ok' type="object"/>
</group>
</form>
</field>
</record>
</record>
<record id="action_stock_picking_from_claim_picking" model="ir.actions.act_window">
<field name="name">Create Incomming Shipment to Stock</field>
<record id="action_stock_picking_from_claim_picking"
model="ir.actions.act_window">
<field name="name">Create Incoming Shipment to Stock</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">claim_make_picking_from_picking.wizard</field>
<field name="res_model">claim.make.picking.from.picking.wizard</field>
<field name="src_model">stock.picking</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="target">new</field>
<field name="context">{'picking_type': 'picking_stock'}</field>
</record>
<record id="action_loss_picking_from_claim_picking" model="ir.actions.act_window">
<field name="name">Create Incomming Shipment to Breakkage Loss Location</field>
<record id="action_loss_picking_from_claim_picking"
model="ir.actions.act_window">
<field name="name">Create Incoming Shipment to Breakage Loss Location</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">claim_make_picking_from_picking.wizard</field>
<field name="res_model">claim.make.picking.from.picking.wizard</field>
<field name="src_model">stock.picking</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context">{'picking_type': 'picking_breakage_loss'}</field>
<field name="target">new</field>
<field name="context">{'picking_type': 'picking_loss'}
</field>
</record>
<record id="action_used_picking_from_claim_picking" model="ir.actions.act_window">
<field name="name">Create Incomming Shipment to Refurbish Location</field>
<record id="action_used_picking_from_claim_picking"
model="ir.actions.act_window">
<field name="name">Create Incoming Shipment to Refurbish Location</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">claim_make_picking_from_picking.wizard</field>
<field name="res_model">claim.make.picking.from.picking.wizard</field>
<field name="src_model">stock.picking</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="target">new</field>
<field name="context">{'picking_type': 'picking_refurbish'}</field>
</record>
</data>
</openerp>

View File

@@ -6,17 +6,15 @@
-->
<openerp>
<data>
<record id="action_claim_picking_loss" model="ir.actions.act_window">
<field name="name">Create Products Loss</field>
<field name="name">Create a Product Loss</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">claim_make_picking.wizard</field>
<field name="src_model">crm.claim</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="target">new</field>
<field name="context">{'picking_type': 'loss'}</field>
</record>
</data>
</openerp>