diff --git a/crm_claim_rma/__openerp__.py b/crm_claim_rma/__openerp__.py
index ded1de47..d1a7dc82 100644
--- a/crm_claim_rma/__openerp__.py
+++ b/crm_claim_rma/__openerp__.py
@@ -27,41 +27,49 @@
Management of Return Merchandise Authorization (RMA)
====================================================
-This module aim to improve the Claims by adding a way to manage the product returns. It
-allows you to create and manage picking from a claim. It also introduce a new object
-the claim lines to better handle that problematic. One Claim can have several lines that concern
-the return of differents products. It's for every of them that you'll be able to check the
-warranty (still running or not).
+This module aims to improve the Claims by adding a way to manage the
+product returns. It allows you to create and manage picking from a
+claim. It also introduces a new object: the claim lines to better
+handle that problematic. One Claim can have several lines that
+concern the return of differents products. It's for every of them
+that you'll be able to check the warranty (still running or not).
-It mainly contain the following features:
+It mainly contains the following features:
* product returns (one by one, mass return by invoice)
* warranty control & return address (based on invoice date and product form)
* product picking in / out
* product refund
-* access to related customer data (orders, invoices, refunds, picking in/out) from a claim
+* access to related customer data (orders, invoices, refunds, picking
+ in/out) from a claim
-Using this module make the logistic flow of return this way:
+Using this module makes the logistic flow of return this way:
-* Returning product goes into Stock or Supplier location with a incoming shipment (depending
- on the settings of the supplier info in the product form)
+* Returning product goes into Stock or Supplier location with a incoming
+ shipment (depending on the settings of the supplier info in the
+ product form)
* You can make a delivery from the RMA to send a new product to the Customer
""",
'author': 'Akretion, Camptocamp',
'website': 'http://www.akretion.com, http://www.camptocamp.com',
- 'depends': ['sale','stock','crm_claim','product_warranty'],
- 'data': [
- 'wizard/claim_make_picking_view.xml',
- 'crm_claim_rma_view.xml',
- 'security/ir.model.access.csv',
- 'account_invoice_view.xml',
- 'stock_view.xml',
- 'crm_claim_rma_data.xml',
- ],
- 'images': ['images/product_return.png', 'images/claim.png','images/return_line.png','images/exchange.png'],
+ 'depends': ['sale',
+ 'stock',
+ 'crm_claim',
+ 'product_warranty',
+ ],
+ 'data': ['wizard/claim_make_picking_view.xml',
+ 'crm_claim_rma_view.xml',
+ 'security/ir.model.access.csv',
+ 'account_invoice_view.xml',
+ 'stock_view.xml',
+ 'crm_claim_rma_data.xml',
+ ],
+ 'images': ['images/product_return.png',
+ 'images/claim.png',
+ 'images/return_line.png',
+ 'images/exchange.png',
+ ],
'installable': True,
- 'active': False,
+ 'auto_install': False,
}
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/crm_claim_rma/account_invoice.py b/crm_claim_rma/account_invoice.py
index aeb0c1df..2d73d25c 100644
--- a/crm_claim_rma/account_invoice.py
+++ b/crm_claim_rma/account_invoice.py
@@ -19,7 +19,7 @@
# along with this program. If not, see .
#
##############################################################################
-from openerp.osv import fields, orm, osv
+from openerp.osv import fields, orm
from tools.translate import _
@@ -32,59 +32,60 @@ class account_invoice(orm.Model):
}
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 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],
- [
- 'invoice_line_id',
- 'product_returned_quantity',
- '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 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
- elif column_type not in ['many2many','one2many']:
- clean_line[field] = inv_line[field]
- elif field == 'invoice_line_tax_id':
- tax_list = []
- for tax in inv_line[field]:
- tax_list.append(tax.id)
- clean_line[field] = [(6,0, tax_list)]
- clean_line['quantity'] = claim_info['product_returned_quantity']
- clean_line['claim_line_id'] = [claim_line_id[1]]
- new_lines.append(clean_line)
- if not new_lines:
- # TODO use custom states to show button of this wizard or
- # 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, invoice, date=None, period_id=None,
- description=None, journal_id=None, context=None):
+ """ Override when from claim to update the quantity and link to the
+ claim line."""
if context is None:
- context={}
- result = super(account_invoice, self)._prepare_refund(cr, uid, invoice,
- date=date, period_id=period_id, description=description,
+ context = {}
+ new_lines = []
+ inv_line_obj = self.pool.get('account.invoice.line')
+ claim_line_obj = self.pool.get('claim.line')
+ # check if is an invoice_line and we are from a claim
+ if not (context.get('claim_line_ids') and lines and
+ lines[0]._name =='account.invoice.line'):
+ return super(account_invoice, self)._refund_cleanup_lines(
+ cr, uid, lines, context=None)
+
+ for __, claim_line_id in context.get('claim_line_ids'):
+ line = claim_line_obj.browse(cr, uid, claim_line_id,
+ context=context)
+ if not line.refund_line_id:
+ # For each lines replace quantity and add claim_line_id
+ inv_line = inv_line_obj.browse(cr, uid,
+ line.invoice_line_id.id,
+ context=context)
+ clean_line = {}
+ for field_name, field in inv_line._all_columns.iteritems():
+ column_type = field.column._type
+ if column_type == 'many2one':
+ clean_line[field_name] = inv_line[field_name].id
+ elif column_type not in ('many2many', 'one2many'):
+ clean_line[field_name] = inv_line[field_name]
+ elif field_name == 'invoice_line_tax_id':
+ tax_list = []
+ for tax in inv_line[field_name]:
+ tax_list.append(tax.id)
+ clean_line[field_name] = [(6, 0, tax_list)]
+ clean_line['quantity'] = line['product_returned_quantity']
+ clean_line['claim_line_id'] = [claim_line_id]
+ new_lines.append(clean_line)
+ if not new_lines:
+ # TODO use custom states to show button of this wizard or
+ # not instead of raise an error
+ raise orm.except_orm(
+ _('Error !'),
+ _('A refund has already been created for this claim !'))
+ return [(0, 0, line) for line in new_lines]
+
+ 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')
+ result['claim_id'] = context['claim_id']
return result
@@ -97,10 +98,11 @@ class account_invoice_line(orm.Model):
if vals.get('claim_line_id'):
claim_line_id = vals['claim_line_id']
del vals['claim_line_id']
- line_id = super(account_invoice_line, self).create(cr, uid,
- vals, context=context)
+ line_id = super(account_invoice_line, self).create(
+ cr, uid, vals, context=context)
if claim_line_id:
claim_line_obj = self.pool.get('claim.line')
- claim_line_obj.write(cr, uid, claim_line_id,
- {'refund_line_id': line_id}, context=context)
+ claim_line_obj.write(cr, uid, claim_line_id,
+ {'refund_line_id': line_id},
+ context=context)
return line_id
diff --git a/crm_claim_rma/crm_claim_rma.py b/crm_claim_rma/crm_claim_rma.py
index 13e4cfd1..f9423bc7 100644
--- a/crm_claim_rma/crm_claim_rma.py
+++ b/crm_claim_rma/crm_claim_rma.py
@@ -2,7 +2,7 @@
##############################################################################
#
# Copyright 2013 Camptocamp
-# Copyright 2009-2013 Akretion,
+# 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
@@ -20,28 +20,24 @@
#
##############################################################################
-from openerp.osv import fields, orm, osv
-# from crm import crm
+import time
+from openerp.osv import fields, orm
from datetime import datetime
from dateutil.relativedelta import relativedelta
-import time
-from tools.translate import _
-from tools import DEFAULT_SERVER_DATE_FORMAT
-from tools.translate import _
+from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
+from openerp.tools.translate import _
-class substate_substate(orm.Model):
- """
- To precise a state (state=refused; substates= reason 1, 2,...)
- """
+class substate_substate(orm.Model):
+ """ To precise a state (state=refused; substates= reason 1, 2,...) """
_name = "substate.substate"
_description = "substate that precise a given state"
_columns = {
- 'name': fields.char('Sub state', size=128, required=True),
- 'substate_descr' : fields.text('Description',
- help="To give more information about the sub state"),
- # ADD OBJECT TO FILTER
- }
+ 'name': fields.char('Sub state', required=True),
+ 'substate_descr': fields.text(
+ 'Description',
+ help="To give more information about the sub state"),
+ }
class claim_line(orm.Model):
@@ -50,18 +46,19 @@ class claim_line(orm.Model):
"""
_name = "claim.line"
_description = "List of product to return"
-
+
# Comment written in a claim.line to know about the warranty status
WARRANT_COMMENT = {
'valid': "Valid",
'expired': "Expired",
'not_define': "Not Defined"}
-
+
# Method to calculate total amount of the line : qty*UP
def _line_total_amount(self, cr, uid, ids, field_name, arg, context=None):
res = {}
- for line in self.browse(cr,uid,ids):
- res[line.id] = line.unit_sale_price*line.product_returned_quantity
+ for line in self.browse(cr, uid, ids, context=context):
+ res[line.id] = (line.unit_sale_price *
+ line.product_returned_quantity)
return res
def copy_data(self, cr, uid, id, default=None, context=None):
@@ -75,134 +72,158 @@ class claim_line(orm.Model):
std_default.update(default)
return super(claim_line, self).copy_data(
cr, uid, id, default=std_default, context=context)
-
+
def get_warranty_return_partner(self, cr, uid, context=None):
seller = self.pool.get('product.supplierinfo')
result = seller.get_warranty_return_partner(cr, uid, context=context)
return result
_columns = {
- 'name': fields.char('Description', size=64,required=True),
- 'claim_origine': fields.selection([('none','Not specified'),
- ('legal','Legal retractation'),
- ('cancellation','Order cancellation'),
- ('damaged','Damaged delivered product'),
- ('error','Shipping error'),
- ('exchange','Exchange request'),
- ('lost','Lost during transport'),
- ('other','Other')],
+ 'name': fields.char('Description', required=True),
+ 'claim_origine': fields.selection(
+ [('none', 'Not specified'),
+ ('legal', 'Legal retractation'),
+ ('cancellation', 'Order cancellation'),
+ ('damaged', 'Damaged delivered product'),
+ ('error', 'Shipping error'),
+ ('exchange', 'Exchange request'),
+ ('lost', 'Lost during transport'),
+ ('other', 'Other')
+ ],
'Claim Subject',
required=True,
help="To describe the line product problem"),
- 'claim_descr' : fields.text('Claim description',
- help="More precise description of the problem"),
- 'product_id': fields.many2one('product.product', 'Product',
+ 'claim_descr': fields.text(
+ 'Claim description',
+ help="More precise description of the problem"),
+ 'product_id': fields.many2one(
+ 'product.product',
+ string='Product',
help="Returned product"),
- 'product_returned_quantity' : fields.float('Quantity', digits=(12,2),
+ 'product_returned_quantity': fields.float(
+ 'Quantity', digits=(12, 2),
help="Quantity of product returned"),
- 'unit_sale_price' : fields.float('Unit sale price', digits=(12,2),
- help="Unit sale price of the product. Auto filed if retrun done by"
- " invoice selection. BE CAREFUL AND CHECK the automatic value "
- "as don't take into account previous refounds, invoice "
+ 'unit_sale_price' : fields.float(
+ 'Unit sale price', digits=(12, 2),
+ help="Unit sale price of the product. Auto filled if retrun done "
+ "by invoice selection. Be careful and check the automatic "
+ "value as don't take into account previous refunds, invoice "
"discount, can be for 0 if product for free,..."),
- 'return_value' : fields.function(_line_total_amount, method=True,
- string='Total return',
- type='float',
+ 'return_value' : fields.function(
+ _line_total_amount, string='Total return', type='float',
help="Quantity returned * Unit sold price",),
- 'prodlot_id': fields.many2one('stock.production.lot', 'Serial/Lot n°',
+ 'prodlot_id': fields.many2one(
+ 'stock.production.lot',
+ string='Serial/Lot n°',
help="The serial/lot of the returned product"),
'applicable_guarantee': fields.selection(
- [
- ('us','Company'),
- ('supplier','Supplier'),
- ('brand','Brand manufacturer')],
+ [('us', 'Company'),
+ ('supplier', 'Supplier'),
+ ('brand', 'Brand manufacturer')],
'Warranty type'),
- 'guarantee_limit': fields.date('Warranty limit',
+ 'guarantee_limit': fields.date(
+ 'Warranty limit',
readonly=True,
help="The warranty limit is computed as: invoice date + warranty "
"defined on selected product."),
- 'warning': fields.char('Warranty', size=64,
+ 'warning': fields.char(
+ 'Warranty',
readonly=True,
help="If warranty has expired"),
- "warranty_type": fields.selection(get_warranty_return_partner,
+ "warranty_type": fields.selection(
+ get_warranty_return_partner,
'Warranty type',
readonly=True,
- help="Who is in charge of the warranty return treatment toward the end customer. "
- "Company will use the current compagny delivery or default address and so on for "
- "supplier and brand manufacturer. Doesn't necessarly mean that the warranty to be "
- "applied is the one of the return partner (ie: can be returned to the company and "
- "be under the brand warranty"),
- "warranty_return_partner" : fields.many2one('res.partner',
- 'Warranty Address',
+ help="Who is in charge of the warranty return treatment towards the end customer. "
+ "Company will use the current company delivery or default address and so on for "
+ "supplier and brand manufacturer. Does not necessarily mean that the warranty to be "
+ "applied is the one of the return partner (ie: can be returned to the company and "
+ "be under the brand warranty"),
+ "warranty_return_partner" : fields.many2one(
+ 'res.partner',
+ string='Warranty Address',
help="Where the customer has to send back the product(s)"),
- 'claim_id': fields.many2one('crm.claim', 'Related claim',
+ 'claim_id': fields.many2one(
+ 'crm.claim', string='Related claim',
help="To link to the case.claim object"),
- 'state' : fields.selection([('draft','Draft'),
- ('refused','Refused'),
- ('confirmed','Confirmed, waiting for product'),
- ('in_to_control','Received, to control'),
- ('in_to_treate','Controlled, to treate'),
- ('treated','Treated')], 'State'),
- 'substate_id': fields.many2one('substate.substate', 'Sub state',
+ 'state' : fields.selection(
+ [('draft', 'Draft'),
+ ('refused', 'Refused'),
+ ('confirmed', 'Confirmed, waiting for product'),
+ ('in_to_control', 'Received, to control'),
+ ('in_to_treate', 'Controlled, to treate'),
+ ('treated', 'Treated')],
+ string='State'),
+ 'substate_id': fields.many2one(
+ 'substate.substate',
+ string='Sub state',
help="Select a sub state to precise the standard state. Example 1: "
"state = refused; substate could be warranty over, not in "
"warranty, no problem,... . Example 2: state = to treate; "
"substate could be to refund, to exchange, to repair,..."),
- 'last_state_change': fields.date('Last change',
+ 'last_state_change': fields.date(
+ string='Last change',
help="To set the last state / substate change"),
- 'invoice_line_id': fields.many2one('account.invoice.line',
- 'Invoice Line',
+ 'invoice_line_id': fields.many2one(
+ 'account.invoice.line',
+ string='Invoice Line',
help='The invoice line related to the returned product'),
- 'refund_line_id': fields.many2one('account.invoice.line',
- 'Refund Line',
+ 'refund_line_id': fields.many2one(
+ 'account.invoice.line',
+ string='Refund Line',
help='The refund line related to the returned product'),
- 'move_in_id': fields.many2one('stock.move',
- 'Move Line from picking in',
+ 'move_in_id': fields.many2one(
+ 'stock.move',
+ string='Move Line from picking in',
help='The move line related to the returned product'),
- 'move_out_id': fields.many2one('stock.move',
- 'Move Line from picking out',
+ 'move_out_id': fields.many2one(
+ 'stock.move',
+ string='Move Line from picking out',
help='The move line related to the returned product'),
- 'location_dest_id': fields.many2one('stock.location',
- 'Return Stock Location',
+ 'location_dest_id': fields.many2one(
+ 'stock.location',
+ string='Return Stock Location',
help='The return stock location of the returned product'),
}
_defaults = {
- 'state': lambda *a: 'draft',
- 'name': lambda *a: 'none',
- }
+ 'state': 'draft',
+ 'name': 'none',
+ }
# 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
- if date_invoice:
- warning = _(self.WARRANT_COMMENT['not_define'])
- date_inv_at_server = datetime.strptime(date_invoice,
- DEFAULT_SERVER_DATE_FORMAT)
- supplier = claim_line.product_id.seller_ids[0]
- if claim_line.claim_id.claim_type == 'supplier':
- waranty_duration = int(supplier.warranty_duration)
- else:
- waranty_duration = int(claim_line.product_id.warranty)
- limit = (date_inv_at_server +
- relativedelta(months=waranty_duration)).strftime(DEFAULT_SERVER_DATE_FORMAT)
- # If waranty period was defined
- if waranty_duration > 0:
- if limit < claim_line.claim_id.date:
- warning = _(self.WARRANT_COMMENT['expired'])
- else:
- warning = _(self.WARRANT_COMMENT['valid'])
- self.write(cr,uid,ids,{
- 'guarantee_limit' : limit,
- 'warning' : warning,
- })
+ if not date_invoice:
+ raise orm.except_orm(
+ _('Error !'),
+ _('Cannot find any date for invoice. '
+ 'Must be a validated invoice.'))
+ warning = _(self.WARRANT_COMMENT['not_define'])
+ date_inv_at_server = datetime.strptime(date_invoice,
+ DEFAULT_SERVER_DATE_FORMAT)
+ supplier = claim_line.product_id.seller_ids[0]
+ if claim_line.claim_id.claim_type == 'supplier':
+ warranty_duration = int(supplier.warranty_duration)
else:
- raise osv.except_osv(_('Error !'),
- _('Cannot find any date for invoice ! Must be a validated invoice !'))
+ warranty_duration = int(claim_line.product_id.warranty)
+ limit = date_inv_at_server + relativedelta(months=warranty_duration)
+ # If waranty period was defined
+ if warranty_duration > 0:
+ claim_date = datetime.strptime(claim_line.claim_id.date,
+ DEFAULT_SERVER_DATE_FORMAT)
+ if limit < claim_date:
+ warning = _(self.WARRANT_COMMENT['expired'])
+ else:
+ warning = _(self.WARRANT_COMMENT['valid'])
+ self.write(cr, uid, ids,
+ {'guarantee_limit': limit.strftime(DEFAULT_SERVER_DATE_FORMAT),
+ 'warning': warning},
+ context=context)
return True
- def get_destination_location(self, cr, uid, product_id,
- warehouse_id, context=None):
+ 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. Always take 'Supplier' one when return type different
from company."""
@@ -220,41 +241,44 @@ class claim_line(orm.Model):
return location_dest_id
# Method to calculate warranty return address
- def set_warranty_return_address(self, cr, uid, ids,
- claim_line, context=None):
+ def set_warranty_return_address(self, cr, uid, ids, claim_line, context=None):
"""Return the partner to be used as return destination and
the destination stock location of the line in case of return.
+
We can have various case here:
- company or other: return to company partner or crm_return_address_id
if specified
- - supplier: return to the supplier address"""
+ - supplier: return to the supplier address
+
+ """
return_address = None
seller = claim_line.product_id.seller_info_id
claim_company = claim_line.claim_id.company_id
return_address = seller.warranty_return_address.id
return_type = seller.warranty_return_partner
- location_dest_id = self.get_destination_location(cr, uid,
- claim_line.product_id.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,
- 'location_dest_id': location_dest_id})
+ {'warranty_return_partner': return_address,
+ 'warranty_type': return_type,
+ 'location_dest_id': location_dest_id},
+ context=context)
return True
-
- # Method to calculate warranty limit and address
+
def set_warranty(self, cr, uid, ids, context=None):
+ """ Calculate warranty limit and address """
for claim_line in self.browse(cr, uid, ids, context=context):
- if claim_line.product_id and claim_line.invoice_line_id:
- self.set_warranty_limit(cr, uid, ids,
- claim_line, context=context)
- self.set_warranty_return_address(cr, uid, ids,
- claim_line, context=context)
- else:
- raise osv.except_osv(_('Error !'),
- _('PLEASE SET PRODUCT & INVOICE!'))
- return True
+ if not (claim_line.product_id and claim_line.invoice_line_id):
+ raise orm.except_orm(
+ _('Error !'),
+ _('Please set product and invoice.'))
+ self.set_warranty_limit(cr, uid, ids,
+ claim_line, context=context)
+ self.set_warranty_return_address(cr, uid, ids,
+ claim_line, context=context)
+ return True
#TODO add the option to split the claim_line in order to manage the same product separately
@@ -262,18 +286,22 @@ class crm_claim(orm.Model):
_inherit = 'crm.claim'
def _get_sequence_number(self, cr, uid, context=None):
- res = self.pool.get('ir.sequence').get(cr, uid,
- 'crm.claim.rma', context=context) or '/'
+ seq_obj = self.pool.get('ir.sequence')
+ res = seq_obj.get(cr, uid, 'crm.claim.rma', context=context) or '/'
return res
def _get_default_warehouse(self, cr, uid, context=None):
- company_id = self.pool.get('res.users').browse(cr, uid, uid,
- context=context).company_id.id
- wh_ids = self.pool.get('stock.warehouse').search(cr, uid,
- [('company_id','=',company_id)], context=context)
+ user_obj = self.pool.get('res.users')
+ user = user_obj.browse(cr, uid, uid, context=context)
+ company_id = user.company_id.id
+ wh_obj = self.pool.get('stock.warehouse')
+ wh_ids = wh_obj.search(cr, uid,
+ [('company_id', '=', company_id)],
+ context=context)
if not wh_ids:
- raise osv.except_osv(_('Error!'),
- _('There is no warehouse for the current user\'s company!'))
+ raise orm.except_orm(
+ _('Error!'),
+ _('There is no warehouse for the current user\'s company.'))
return wh_ids[0]
def name_get(self, cr, uid, ids, context=None):
@@ -283,9 +311,9 @@ class crm_claim(orm.Model):
return res
def create(self, cr, uid, vals, context=None):
- if ('number' not in vals) or (vals.get('number')=='/'):
+ if ('number' not in vals) or (vals.get('number') == '/'):
vals['number'] = self._get_sequence_number(cr, uid, context=context)
- new_id = super(crm_claim, self).create(cr, uid, vals, context)
+ new_id = super(crm_claim, self).create(cr, uid, vals, context=context)
return new_id
def copy_data(self, cr, uid, id, default=None, context=None):
@@ -301,49 +329,55 @@ class crm_claim(orm.Model):
cr, uid, id, default=std_default, context=context)
_columns = {
- 'number': fields.char('Number', readonly=True,
+ 'number': fields.char(
+ 'Number', readonly=True,
states={'draft': [('readonly', False)]},
required=True,
select=True,
help="Company internal claim unique number"),
- 'claim_type': fields.selection([('customer','Customer'),
- ('supplier','Supplier'),
- ('other','Other')],
- 'Claim type',
+ 'claim_type': fields.selection(
+ [('customer', 'Customer'),
+ ('supplier', 'Supplier'),
+ ('other', 'Other')],
+ string='Claim type',
required=True,
- help="customer = from customer to company ; supplier = from "
- "company to supplier"),
- 'claim_line_ids' : fields.one2many('claim.line', 'claim_id',
- 'Return lines'),
+ help="Customer: from customer to company.\n "
+ "Supplier: from company to supplier."),
+ 'claim_line_ids': fields.one2many(
+ 'claim.line', 'claim_id',
+ string='Return lines'),
'planned_revenue': fields.float('Expected revenue'),
'planned_cost': fields.float('Expected cost'),
'real_revenue': fields.float('Real revenue'),
'real_cost': fields.float('Real cost'),
'invoice_ids': fields.one2many('account.invoice', 'claim_id', 'Refunds'),
'picking_ids': fields.one2many('stock.picking', 'claim_id', 'RMA'),
- 'invoice_id': fields.many2one('account.invoice', 'Invoice',
+ 'invoice_id': fields.many2one(
+ 'account.invoice', string='Invoice',
help='Related original Cusotmer invoice'),
- 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse',
+ 'warehouse_id': fields.many2one(
+ 'stock.warehouse', string='Warehouse',
required=True),
}
_defaults = {
- 'number': lambda self, cr, uid, context: '/',
+ 'number': '/',
'claim_type': 'customer',
'warehouse_id': _get_default_warehouse,
}
_sql_constraints = [
- ('number_uniq', 'unique(number, company_id)', 'Number/Reference must be unique per Company!'),
+ ('number_uniq', 'unique(number, company_id)',
+ 'Number/Reference must be unique per Company!'),
]
- def onchange_partner_address_id(self, cr, uid, ids, add,
- email=False, context=None):
- res = super(crm_claim, self).onchange_partner_address_id(cr, uid, ids,
- add, email=email)
+ def onchange_partner_address_id(self, cr, uid, ids, add, email=False, context=None):
+ res = super(crm_claim, self).onchange_partner_address_id(
+ cr, uid, ids, add, email=email)
if add:
if not res['value']['email_from'] or not res['value']['partner_phone']:
- address = self.pool.get('res.partner').browse(cr, uid, add)
+ partner_obj = self.pool.get('res.partner')
+ address = partner_obj.browse(cr, uid, add, context=context)
for other_add in address.partner_id.address:
if other_add.email and not res['value']['email_from']:
res['value']['email_from'] = other_add.email
@@ -351,29 +385,30 @@ class crm_claim(orm.Model):
res['value']['partner_phone'] = other_add.phone
return res
- def onchange_invoice_id(self, cr, uid, ids, invoice_id,
- warehouse_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)])
+ invoice_line_ids = invoice_line_obj.search(
+ cr, uid,
+ [('invoice_id', '=', invoice_id)],
+ context=context)
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)
+ invoice_lines = invoice_line_obj.browse(cr, uid, invoice_line_ids,
+ context=context)
+ for invoice_line in invoice_lines:
+ 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",
- 'invoice_line_id': invoice_line.id,
- '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}}
-
+ 'name': invoice_line.name,
+ 'claim_origine': "none",
+ 'invoice_line_id': invoice_line.id,
+ '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}}
diff --git a/crm_claim_rma/stock.py b/crm_claim_rma/stock.py
index 500a73be..ae217a6a 100644
--- a/crm_claim_rma/stock.py
+++ b/crm_claim_rma/stock.py
@@ -19,7 +19,7 @@
# along with this program. If not, see .
#
##############################################################################
-from openerp.osv import fields, orm, osv
+from openerp.osv import fields, orm
class stock_picking(orm.Model):
@@ -30,24 +30,24 @@ class stock_picking(orm.Model):
'claim_id': fields.many2one('crm.claim', 'Claim'),
}
- def create(self, cr, user, vals, context=None):
- if ('name' not in vals) or (vals.get('name')=='/'):
- if vals['type'] != 'internal':
- seq_obj_name = 'stock.picking.' + vals['type']
+ def create(self, cr, uid, vals, context=None):
+ if ('name' not in vals) or (vals.get('name') == '/'):
+ sequence_obj = self.pool.get('ir.sequence')
+ if vals['type'] == 'internal':
+ seq_obj_name = self._name
else:
- seq_obj_name = self._name
- vals['name'] = self.pool.get('ir.sequence').get(cr, user,
- seq_obj_name,
- context=context)
- new_id = super(stock_picking, self).create(cr, user, vals,
- context=context)
+ seq_obj_name = 'stock.picking.' + vals['type']
+ vals['name'] = sequence_obj.get(cr, uid, seq_obj_name,
+ context=context)
+ new_id = super(stock_picking, self).create(cr, uid, vals,
+ context=context)
return new_id
class stock_picking_out(orm.Model):
_inherit = "stock.picking.out"
-
+
_columns = {
'claim_id': fields.many2one('crm.claim', 'Claim'),
}
@@ -56,26 +56,27 @@ class stock_picking_out(orm.Model):
class stock_picking_out(orm.Model):
_inherit = "stock.picking.in"
-
+
_columns = {
'claim_id': fields.many2one('crm.claim', 'Claim'),
}
-#This part concern the case of a wrong picking out. We need to create a new
-#stock_move in a picking already open.
-#In order to don't have to confirm the stock_move we override the create and
-#confirm it at the creation only for this case
+# This part concern the case of a wrong picking out. We need to create a new
+# stock_move in a picking already open.
+# In order to don't have to confirm the stock_move we override the create and
+# confirm it at the creation only for this case
class stock_move(orm.Model):
-
+
_inherit = "stock.move"
def create(self, cr, uid, vals, context=None):
move_id = super(stock_move, self).create(cr, uid, vals, context=context)
if vals.get('picking_id'):
- picking = self.pool.get('stock.picking').browse(cr, uid,
- vals['picking_id'], context=context)
+ picking_obj = self.pool.get('stock.picking')
+ picking = picking_obj.browse(cr, uid, vals['picking_id'],
+ context=context)
if picking.claim_id and picking.type == u'in':
- move = self.write(cr, uid, move_id, {'state': 'confirmed'},
- context=context)
+ self.write(cr, uid, move_id, {'state': 'confirmed'},
+ context=context)
return move_id
diff --git a/crm_claim_rma/wizard/account_invoice_refund.py b/crm_claim_rma/wizard/account_invoice_refund.py
index f57b608b..386c6751 100644
--- a/crm_claim_rma/wizard/account_invoice_refund.py
+++ b/crm_claim_rma/wizard/account_invoice_refund.py
@@ -19,26 +19,27 @@
# along with this program. If not, see .
#
##############################################################################
-from openerp.osv import fields, orm
+from openerp.osv import orm
class account_invoice_refund(orm.TransientModel):
-
+
_inherit = "account.invoice.refund"
def compute_refund(self, cr, uid, ids, mode='refund', context=None):
- if context is None: context={}
+ if context is None:
+ context={}
if context.get('invoice_ids'):
context['active_ids'] = context.get('invoice_ids')
- return super(account_invoice_refund, self).compute_refund(cr, uid, ids,
- mode='refund', context=context)
+ return super(account_invoice_refund, self).compute_refund(
+ cr, uid, ids, mode=mode, context=context)
def _get_description(self, cr, uid, context=None):
- if context is None: context = {}
+ if context is None:
+ context = {}
description = context.get('description') or ''
return description
_defaults = {
'description': _get_description,
}
-
diff --git a/crm_claim_rma/wizard/claim_make_picking.py b/crm_claim_rma/wizard/claim_make_picking.py
index c4a0a220..1b25752e 100644
--- a/crm_claim_rma/wizard/claim_make_picking.py
+++ b/crm_claim_rma/wizard/claim_make_picking.py
@@ -2,7 +2,7 @@
##############################################################################
#
# Copyright 2013 Camptocamp
-# Copyright 2009-2013 Akretion,
+# 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
@@ -20,7 +20,7 @@
#
##############################################################################
from openerp.osv import fields, orm, osv
-from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
+from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp import netsvc
from openerp.tools.translate import _
import time
@@ -31,54 +31,62 @@ class claim_make_picking(orm.TransientModel):
_name = 'claim_make_picking.wizard'
_description = 'Wizard to create pickings from claim lines'
_columns = {
- 'claim_line_source_location': fields.many2one('stock.location',
- 'Source Location',
+ 'claim_line_source_location': fields.many2one(
+ 'stock.location',
+ string='Source Location',
help="Location where the returned products are from.",
required=True),
- 'claim_line_dest_location': fields.many2one('stock.location',
- 'Dest. Location',
+ 'claim_line_dest_location': fields.many2one(
+ 'stock.location',
+ string='Dest. Location',
help="Location where the system will stock the returned products.",
required=True),
- 'claim_line_ids': fields.many2many('claim.line',
+ 'claim_line_ids': fields.many2many(
+ 'claim.line',
'claim_line_picking',
'claim_picking_id',
'claim_line_id',
- 'Claim lines'),
+ string='Claim lines'),
}
def _get_claim_lines(self, cr, uid, context):
#TODO use custom states to show buttons of this wizard or not instead of raise an error
- if context is None: context = {}
+ if context is None:
+ context = {}
line_obj = self.pool.get('claim.line')
if context.get('picking_type') == 'out':
move_field = 'move_out_id'
else:
move_field = 'move_in_id'
good_lines = []
- line_ids = line_obj.search(cr, uid,
- [('claim_id', '=', context['active_id'])], context=context)
+ line_ids = line_obj.search(
+ cr, uid,
+ [('claim_id', '=', context['active_id'])],
+ context=context)
for line in line_obj.browse(cr, uid, line_ids, context=context):
if not line[move_field] or line[move_field].state == 'cancel':
good_lines.append(line.id)
if not good_lines:
- raise osv.except_osv(_('Error !'),
- _('A picking has already been created for this claim !'))
+ raise orm.except_orm(
+ _('Error'),
+ _('A picking has already been created for this claim.'))
return good_lines
# Get default source location
def _get_source_loc(self, cr, uid, context):
loc_id = False
- if context is None: context = {}
+ if context is None:
+ context = {}
warehouse_obj = self.pool.get('stock.warehouse')
warehouse_id = context.get('warehouse_id')
if context.get('picking_type') == 'out':
- loc_id = warehouse_obj.read(cr, uid,
- warehouse_id,
+ loc_id = warehouse_obj.read(
+ cr, uid, warehouse_id,
['lot_stock_id'],
context=context)['lot_stock_id'][0]
elif context.get('partner_id'):
- loc_id = self.pool.get('res.partner').read(cr, uid,
- context['partner_id'],
+ loc_id = self.pool.get('res.partner').read(
+ cr, uid, context['partner_id'],
['property_stock_customer'],
context=context)['property_stock_customer']
return loc_id
@@ -92,7 +100,7 @@ class claim_make_picking(orm.TransientModel):
for line in line_obj.browse(cr, uid, line_ids, context=context):
if line.location_dest_id.id not in line_location:
line_location.append(line.location_dest_id.id)
- if len (line_location) == 1:
+ if len(line_location) == 1:
loc_id = line_location[0]
return loc_id
@@ -103,33 +111,33 @@ class claim_make_picking(orm.TransientModel):
line_obj = self.pool.get('claim.line')
line_partner = []
for line in line_obj.browse(cr, uid, line_ids, context=context):
- if (line.warranty_return_partner and line.warranty_return_partner.id
+ if (line.warranty_return_partner and line.warranty_return_partner.id
not in line_partner):
line_partner.append(line.warranty_return_partner.id)
- if len (line_partner) == 1:
+ if len(line_partner) == 1:
partner_id = line_partner[0]
return partner_id
# Get default destination location
def _get_dest_loc(self, cr, uid, context):
"""Return the location_id to use as destination.
- If it's an outoing shippment: take the customer stock property
+ If it's an outoing shippment: take the customer stock property
If it's an incomming shippment take the location_dest_id common to all lines, or
if different, return None."""
- if context is None: context = {}
- warehouse_obj = self.pool.get('stock.warehouse')
- warehouse_id = context.get('warehouse_id')
+ if context is None:
+ context = {}
loc_id = False
if context.get('picking_type') == 'out' and context.get('partner_id'):
- loc_id = self.pool.get('res.partner').read(cr, uid,
- context.get('partner_id'),
+ loc_id = self.pool.get('res.partner').read(
+ cr, uid, context.get('partner_id'),
['property_stock_customer'],
context=context)['property_stock_customer'][0]
elif context.get('picking_type') == 'in' and context.get('partner_id'):
- # Add the case of return to supplier !
+ # Add the case of return to supplier !
line_ids = self._get_claim_lines(cr, uid, context=context)
- loc_id = self._get_common_dest_location_from_line(cr, uid,
- line_ids, context=context)
+ loc_id = self._get_common_dest_location_from_line(cr, uid,
+ line_ids,
+ context=context)
return loc_id
_defaults = {
@@ -138,13 +146,14 @@ class claim_make_picking(orm.TransientModel):
'claim_line_ids': _get_claim_lines,
}
- def action_cancel(self,cr,uid,ids,conect=None):
- return {'type': 'ir.actions.act_window_close',}
+ def action_cancel(self, cr, uid, ids, context=None):
+ return {'type': 'ir.actions.act_window_close'}
# If "Create" button pressed
def action_create_picking(self, cr, uid, ids, context=None):
picking_obj = self.pool.get('stock.picking')
- if context is None: context = {}
+ if context is None:
+ context = {}
view_obj = self.pool.get('ir.ui.view')
name = 'RMA picking out'
if context.get('picking_type') == 'out':
@@ -161,87 +170,96 @@ class claim_make_picking(orm.TransientModel):
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'),
- ('type', '=', 'form'),
- ('name', '=', view_name)
- ], context=context)[0]
+ view_id = view_obj.search(cr, uid,
+ [('xml_id', '=', view_xml_id),
+ ('model', '=', 'stock.picking'),
+ ('type', '=', 'form'),
+ ('name', '=', view_name)
+ ],
+ context=context)[0]
wizard = self.browse(cr, uid, ids[0], context=context)
- claim = self.pool.get('crm.claim').browse(cr, uid,
- context['active_id'], context=context)
+ claim = self.pool.get('crm.claim').browse(cr, uid,
+ context['active_id'],
+ context=context)
partner_id = claim.partner_id.id
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
# or if partner address is different
if context.get('product_return'):
- common_dest_loc_id = self._get_common_dest_location_from_line(cr, uid,
- line_ids, context=context)
+ 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.'))
- common_dest_partner_id = self._get_common_partner_from_line(cr, uid,
- line_ids, context=context)
+ raise orm.except_orm(
+ _('Error !'),
+ _('A product return cannot be created for various '
+ 'destination locations, please choose line with a '
+ 'same destination location.'))
+ common_dest_partner_id = self._get_common_partner_from_line(
+ cr, uid, line_ids, context=context)
if not common_dest_partner_id:
- raise osv.except_osv(_('Error !'),
- _('A product return cannot be created for various destination address, please '
- 'chose line with a same address.'))
- else:
- partner_id = common_dest_partner_id
+ raise orm.except_orm(
+ _('Error !'),
+ _('A product return cannot be created for various '
+ 'destination addresses, please choose line with a '
+ 'same address.'))
+ partner_id = common_dest_partner_id
# create picking
- picking_id = picking_obj.create(cr, uid, {
- 'origin': claim.number,
- 'type': p_type,
- 'move_type': 'one', # direct
- 'state': 'draft',
- 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
- 'partner_id': partner_id,
- 'invoice_state': "none",
- 'company_id': claim.company_id.id,
- 'location_id': wizard.claim_line_source_location.id,
- 'location_dest_id': wizard.claim_line_dest_location.id,
- 'note' : note,
- 'claim_id': claim.id,
- })
+ picking_id = picking_obj.create(
+ cr, uid,
+ {'origin': claim.number,
+ 'type': p_type,
+ 'move_type': 'one', # direct
+ 'state': 'draft',
+ 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
+ 'partner_id': partner_id,
+ 'invoice_state': "none",
+ 'company_id': claim.company_id.id,
+ 'location_id': wizard.claim_line_source_location.id,
+ 'location_dest_id': wizard.claim_line_dest_location.id,
+ 'note': note,
+ 'claim_id': claim.id,
+ },
+ context=context)
# Create picking lines
for wizard_claim_line in wizard.claim_line_ids:
- move_id = self.pool.get('stock.move').create(cr, uid, {
- 'name' : wizard_claim_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_claim_line.product_id.id,
- 'product_qty': wizard_claim_line.product_returned_quantity,
- 'product_uom': wizard_claim_line.product_id.uom_id.id,
- 'partner_id': partner_id,
- 'prodlot_id': wizard_claim_line.prodlot_id.id,
- # 'tracking_id':
- 'picking_id': picking_id,
- 'state': 'draft',
- 'price_unit': wizard_claim_line.unit_sale_price,
- # 'price_currency_id': claim_id.company_id.currency_id.id, # from invoice ???
- 'company_id': claim.company_id.id,
- 'location_id': wizard.claim_line_source_location.id,
- 'location_dest_id': wizard.claim_line_dest_location.id,
- 'note': note,
- })
- self.pool.get('claim.line').write(cr, uid,
- wizard_claim_line.id, {write_field: move_id}, context=context)
+ move_obj = self.pool.get('stock.move')
+ move_id = move_obj.create(
+ cr, uid,
+ {'name': wizard_claim_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_claim_line.product_id.id,
+ 'product_qty': wizard_claim_line.product_returned_quantity,
+ 'product_uom': wizard_claim_line.product_id.uom_id.id,
+ 'partner_id': partner_id,
+ 'prodlot_id': wizard_claim_line.prodlot_id.id,
+ 'picking_id': picking_id,
+ 'state': 'draft',
+ 'price_unit': wizard_claim_line.unit_sale_price,
+ 'company_id': claim.company_id.id,
+ 'location_id': wizard.claim_line_source_location.id,
+ 'location_dest_id': wizard.claim_line_dest_location.id,
+ 'note': note,
+ },
+ context=context)
+ self.pool.get('claim.line').write(
+ cr, uid, wizard_claim_line.id,
+ {write_field: move_id}, context=context)
wf_service = netsvc.LocalService("workflow")
if picking_id:
- wf_service.trg_validate(uid, 'stock.picking',
- picking_id,'button_confirm', cr)
+ 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)
+ 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,
+ 'domain': domain,
'res_model': 'stock.picking',
'res_id': picking_id,
'type': 'ir.actions.act_window',