mirror of
https://github.com/OCA/rma.git
synced 2025-02-16 17:11:47 +02:00
[FIX] Refund creation
[IMP] on change from invoice selection create line with destination [IMP] Add return location on claim lines
This commit is contained in:
@@ -59,7 +59,6 @@ Using this module make the logistic flow of return this way:
|
||||
'stock_view.xml',
|
||||
'res_company_view.xml',
|
||||
'crm_claim_rma_data.xml',
|
||||
'stock_data.xml',
|
||||
],
|
||||
'images': ['images/product_return.png', 'images/claim.png','images/return_line.png','images/exchange.png'],
|
||||
'installable': True,
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import fields, orm
|
||||
from openerp.osv import fields, orm, osv
|
||||
from tools.translate import _
|
||||
|
||||
|
||||
@@ -31,17 +31,13 @@ class account_invoice(orm.Model):
|
||||
'claim_id': fields.many2one('crm.claim', 'Claim'),
|
||||
}
|
||||
|
||||
def _get_cleanup_fields(self, cr, uid, context=None):
|
||||
fields = super(account_invoice, self)._get_cleanup_fields(cr, uid,
|
||||
context=context)
|
||||
fields = fields + ('claim_line_id',)
|
||||
return fields
|
||||
|
||||
def _refund_cleanup_lines(self, cr, uid, lines, context=None):
|
||||
"""Override when from claim to update the quantity and link
|
||||
to the claim line."""
|
||||
if context is None: context = {}
|
||||
new_lines = []
|
||||
# check if is an invoice_line
|
||||
if context.get('claim_line_ids') and lines and 'product_id' in lines[0]:
|
||||
# check if is an invoice_line and we are from a claim
|
||||
if context.get('claim_line_ids') and lines and lines[0]._name =='account.invoice.line' :
|
||||
for claim_line_id in context.get('claim_line_ids'):
|
||||
claim_info = self.pool.get('claim.line').read(cr, uid,
|
||||
claim_line_id[1],
|
||||
@@ -51,12 +47,13 @@ class account_invoice(orm.Model):
|
||||
'refund_line_id'],
|
||||
context=context)
|
||||
if not claim_info['refund_line_id']:
|
||||
#For each lines replace quantity and add clain_line_id
|
||||
inv_line_obj = self.pool.get('account.invoice.line')
|
||||
inv_line = inv_line_obj.browse(cr, uid,
|
||||
[claim_info['invoice_line_id'][0]],
|
||||
context=context)[0]
|
||||
clean_line = {}
|
||||
for field in invoice_line_info._all_columns.keys():
|
||||
for field in inv_line._all_columns.keys():
|
||||
column_type = inv_line._all_columns[field].column._type
|
||||
if column_type == 'many2one':
|
||||
clean_line[field] = inv_line[field].id
|
||||
@@ -75,15 +72,22 @@ class account_invoice(orm.Model):
|
||||
# not instead of raise an error
|
||||
raise osv.except_osv(_('Error !'),
|
||||
_('A refund has already been created for this claim !'))
|
||||
else:
|
||||
return super(account_invoice, self)._refund_cleanup_lines(cr, uid, lines, context=None)
|
||||
return map(lambda x: (0,0,x), new_lines)
|
||||
|
||||
def _prepare_refund(self, cr, uid, *args, **kwargs):
|
||||
result = super(account_invoice, self)._prepare_refund(cr, uid,
|
||||
*args, **kwargs)
|
||||
if kwargs.get('context') and kwargs['context'].get('claim_id'):
|
||||
result['claim_id'] = kwargs['context']['claim_id']
|
||||
def _prepare_refund(self, cr, uid, invoice, date=None, period_id=None,
|
||||
description=None, journal_id=None, context=None):
|
||||
if context is None:
|
||||
context={}
|
||||
result = super(account_invoice, self)._prepare_refund(cr, uid, invoice,
|
||||
date=date, period_id=period_id, description=description,
|
||||
journal_id=journal_id, context=context)
|
||||
if context.get('claim_id'):
|
||||
result['claim_id'] = context.get('claim_id')
|
||||
return result
|
||||
|
||||
|
||||
class account_invoice_line(orm.Model):
|
||||
|
||||
_inherit = "account.invoice.line"
|
||||
|
||||
@@ -54,7 +54,7 @@ class claim_line(orm.Model):
|
||||
# Comment written in a claim.line to know about the warranty status
|
||||
WARRANT_COMMENT = {
|
||||
'valid': "Valid",
|
||||
'expired': "Expired"
|
||||
'expired': "Expired",
|
||||
'not_define': "Not Defined"}
|
||||
|
||||
# Method to calculate total amount of the line : qty*UP
|
||||
@@ -163,11 +163,6 @@ class claim_line(orm.Model):
|
||||
'name': lambda *a: 'none',
|
||||
}
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
res = super(claim_line, self).write(cr, uid, ids, vals, context=context)
|
||||
self.set_warranty(cr, uid, ids, context=context)
|
||||
return res
|
||||
|
||||
# Method to calculate warranty limit
|
||||
def set_warranty_limit(self, cr, uid, ids, claim_line, context=None):
|
||||
date_invoice = claim_line.invoice_line_id.invoice_id.date_invoice
|
||||
@@ -181,7 +176,7 @@ class claim_line(orm.Model):
|
||||
else:
|
||||
waranty_duration = int(claim_line.product_id.warranty)
|
||||
limit = (date_inv_at_server +
|
||||
relativedelta(month=waranty_duration).strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||
relativedelta(month=waranty_duration)).strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||
# If waranty period was defined
|
||||
if waranty_duration > 0:
|
||||
if limit < claim_line.claim_id.date:
|
||||
@@ -197,6 +192,24 @@ class claim_line(orm.Model):
|
||||
_('Cannot find any date for invoice ! Must be a validated invoice !'))
|
||||
return True
|
||||
|
||||
def get_destination_location(self, cr, uid, product_id,
|
||||
warehouse_id, context=None):
|
||||
"""Compute and return the destination location ID to take
|
||||
for a return."""
|
||||
prod_obj = self.pool.get('product.product')
|
||||
prod = prod_obj.browse(cr, uid, product_id, context=context)
|
||||
wh_obj = self.pool.get('stock.warehouse')
|
||||
wh = wh_obj.browse(cr, uid, warehouse_id, context=context)
|
||||
location_dest_id = wh.lot_stock_id.id
|
||||
return_type = 'company'
|
||||
if prod:
|
||||
seller = prod.seller_info_id
|
||||
if seller:
|
||||
return_type = seller.warranty_return_partner
|
||||
if return_type == 'supplier':
|
||||
location_dest_id = seller.name.property_stock_supplier.id
|
||||
return location_dest_id
|
||||
|
||||
# Method to calculate warranty return address
|
||||
def set_warranty_return_address(self, cr, uid, ids,
|
||||
claim_line, context=None):
|
||||
@@ -207,7 +220,6 @@ class claim_line(orm.Model):
|
||||
if specified
|
||||
- supplier: return to the supplier address"""
|
||||
return_address = None
|
||||
location_dest_id = claim_line.warehouse_id.lot_stock_id.id
|
||||
return_type = 'company'
|
||||
seller = claim_line.product_id.seller_info_id
|
||||
claim_company = claim_line.claim_id.company_id
|
||||
@@ -219,7 +231,10 @@ class claim_line(orm.Model):
|
||||
return_type = seller.warranty_return_partner
|
||||
if return_type == 'supplier':
|
||||
return_address = seller.warranty_return_address.id
|
||||
location_dest_id = seller.property_stock_supplier.id
|
||||
location_dest_id = self.get_destination_location(cr, uid,
|
||||
claim_line.product_id.id,
|
||||
claim_line.claim_id.warehouse_id.id,
|
||||
context=context)
|
||||
self.write(cr, uid, ids,
|
||||
{'warranty_return_partner': return_address,
|
||||
'warranty_type': return_type,
|
||||
@@ -334,12 +349,20 @@ class crm_claim(orm.Model):
|
||||
res['value']['partner_phone'] = other_add.phone
|
||||
return res
|
||||
|
||||
def onchange_invoice_id(self, cr, uid, ids, invoice_id, context=None):
|
||||
def onchange_invoice_id(self, cr, uid, ids, invoice_id,
|
||||
warehouse_id, context=None):
|
||||
invoice_line_obj = self.pool.get('account.invoice.line')
|
||||
claim_line_obj = self.pool.get('claim.line')
|
||||
invoice_line_ids = invoice_line_obj.search(cr, uid,
|
||||
[('invoice_id','=',invoice_id)])
|
||||
claim_lines = []
|
||||
if not warehouse_id:
|
||||
warehouse_id = self._get_default_warehouse(cr, uid, context=context)
|
||||
for invoice_line in invoice_line_obj.browse(cr,uid,invoice_line_ids):
|
||||
location_dest_id = claim_line_obj.get_destination_location(cr, uid,
|
||||
invoice_line.product_id.id,
|
||||
warehouse_id,
|
||||
context=context)
|
||||
claim_lines.append({
|
||||
'name': invoice_line.name,
|
||||
'claim_origine' : "none",
|
||||
@@ -347,6 +370,7 @@ class crm_claim(orm.Model):
|
||||
'product_id' : invoice_line.product_id.id,
|
||||
'product_returned_quantity' : invoice_line.quantity,
|
||||
'unit_sale_price' : invoice_line.price_unit,
|
||||
'location_dest_id': location_dest_id,
|
||||
'state' : 'draft',
|
||||
})
|
||||
return {'value' : {'claim_line_ids' : claim_lines}}
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
<field name="substate_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="name"/>
|
||||
<field name="product_id"/>
|
||||
<field name="prodlot_id"/>
|
||||
<field name="warning"/>
|
||||
<field name="location_dest_id"/>
|
||||
@@ -147,7 +146,7 @@
|
||||
<group name="Product Return">
|
||||
<separator string="Product Return" colspan="4"/>
|
||||
<group>
|
||||
<field name="invoice_id" on_change="onchange_invoice_id(invoice_id, context)" domain="[('partner_id','=',partner_id)]" />
|
||||
<field name="invoice_id" on_change="onchange_invoice_id(invoice_id,warehouse_id,context)" domain="[('partner_id','=',partner_id)]" />
|
||||
</group>
|
||||
<group>
|
||||
<!-- Place for mass return button from crm_rma_lot_mass_return -->
|
||||
|
||||
@@ -21,4 +21,3 @@
|
||||
##############################################################################
|
||||
from . import claim_make_picking
|
||||
from . import account_invoice_refund
|
||||
from . import claim_make_picking_from_picking
|
||||
|
||||
@@ -133,11 +133,11 @@ class claim_make_picking(orm.TransientModel):
|
||||
picking_obj = self.pool.get('stock.picking')
|
||||
if context is None: context = {}
|
||||
view_obj = self.pool.get('ir.ui.view')
|
||||
name = 'RMA picking out'
|
||||
if context.get('picking_type') == 'out':
|
||||
p_type = 'out'
|
||||
write_field = 'move_out_id'
|
||||
note = 'RMA picking out'
|
||||
name = 'Customer picking out'
|
||||
view_xml_id = 'stock_picking_form'
|
||||
view_name = 'stock.picking.form'
|
||||
else:
|
||||
@@ -147,6 +147,7 @@ class claim_make_picking(orm.TransientModel):
|
||||
write_field = 'move_in_id'
|
||||
if context.get('picking_type'):
|
||||
note = 'RMA picking ' + str(context.get('picking_type'))
|
||||
name = note
|
||||
view_id = view_obj.search(cr, uid, [
|
||||
('xml_id', '=', view_xml_id),
|
||||
('model', '=', 'stock.picking'),
|
||||
@@ -157,13 +158,16 @@ class claim_make_picking(orm.TransientModel):
|
||||
claim = self.pool.get('crm.claim').browse(cr, uid,
|
||||
context['active_id'], context=context)
|
||||
partner_id = claim.partner_id.id
|
||||
|
||||
common_dest_loc_id = self._get_common_dest_location_from_line(cr, uid,
|
||||
line_ids, context=context)
|
||||
if not common_dest_loc_id:
|
||||
raise osv.except_osv(_('Error !'),
|
||||
_('A picking cannot be created for various destination location, please '
|
||||
'chose line with a same destination location.'))
|
||||
line_ids = [x.id for x in wizard.claim_line_ids]
|
||||
# In case of product return, we don't allow one picking for various
|
||||
# product if location are different
|
||||
if context.get('product_return'):
|
||||
common_dest_loc_id = self._get_common_dest_location_from_line(cr, uid,
|
||||
line_ids, context=context)
|
||||
if not common_dest_loc_id:
|
||||
raise osv.except_osv(_('Error !'),
|
||||
_('A product return cannot be created for various destination location, please '
|
||||
'chose line with a same destination location.'))
|
||||
# create picking
|
||||
picking_id = picking_obj.create(cr, uid, {
|
||||
'origin': claim.number,
|
||||
|
||||
@@ -1,164 +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_DATE_FORMAT, 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_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 = context.get('warehouse_id')
|
||||
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_obj = self.pool.get('stock.warehouse')
|
||||
warehouse_id = context.get('warehouse_id')
|
||||
print warehouse_id
|
||||
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:
|
||||
@@ -34,7 +34,7 @@
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'picking_type': 'in'}</field>
|
||||
<field name="context">{'picking_type': 'in','product_return': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="action_claim_picking_out" model="ir.actions.act_window">
|
||||
|
||||
Reference in New Issue
Block a user