diff --git a/crm_claim_rma/__init__.py b/crm_claim_rma/__init__.py
index 4a6a0527..bd13e30e 100644
--- a/crm_claim_rma/__init__.py
+++ b/crm_claim_rma/__init__.py
@@ -25,3 +25,4 @@ import wizard
import crm_claim_rma
import account_invoice
import stock
+import res_company
diff --git a/crm_claim_rma/__openerp__.py b/crm_claim_rma/__openerp__.py
index 06706b47..334b8386 100644
--- a/crm_claim_rma/__openerp__.py
+++ b/crm_claim_rma/__openerp__.py
@@ -4,8 +4,8 @@
# #
#########################################################################
# #
-# Copyright (C) 2009-2011 Akretion, Raphaël Valyi, Sébastien Beau, #
-# Emmanuel Samyn #
+# Copyright (C) 2009-2011 Akretion, Raphaël Valyi, Sébastien Beau, #
+# Emmanuel Samyn, Benoît Guillot #
# #
#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 #
@@ -44,17 +44,21 @@ THIS MODULE REPLACES Akretion stock_rma from V6.0
'depends': ['sale','stock','crm_claim','product_warranty'],
'init_xml': ['rma_data.xml',],
'update_xml': [
+ 'wizard/claim_make_picking_view.xml',
'wizard/returned_lines_from_serial_wizard_view.xml',
- 'wizard/returned_lines_from_invoice_wizard_view.xml',
- 'wizard/picking_from_returned_lines_wizard_view.xml',
- 'wizard/refund_from_returned_lines_wizard_view.xml',
- 'wizard/exchange_from_returned_lines_wizard_view.xml',
- 'wizard/picking_from_exchange_lines_wizard_view.xml',
+# 'wizard/returned_lines_from_invoice_wizard_view.xml',
+# 'wizard/picking_from_returned_lines_wizard_view.xml',
+# 'wizard/refund_from_returned_lines_wizard_view.xml',
+# 'wizard/exchange_from_returned_lines_wizard_view.xml',
+# 'wizard/picking_from_exchange_lines_wizard_view.xml',
'wizard/get_empty_serial_view.xml',
'crm_claim_rma_view.xml',
'security/ir.model.access.csv',
'account_invoice_view.xml',
'stock_view.xml',
+ 'res_company_view.xml',
+ 'crm_claim_rma_data.xml',
+ 'stock_data.xml',
# 'report/crm_claim_report_view.xml',
],
'demo_xml': [
diff --git a/crm_claim_rma/account_invoice.py b/crm_claim_rma/account_invoice.py
index c710f968..c664b8f2 100644
--- a/crm_claim_rma/account_invoice.py
+++ b/crm_claim_rma/account_invoice.py
@@ -31,3 +31,15 @@ class account_invoice(osv.osv):
_columns = {
'claim_id': fields.many2one('crm.claim', 'Claim'),
}
+
+ def _refund_cleanup_lines(self, cr, uid, lines, context=None):
+ new_lines = []
+ if context.get('claim_line_ids'):
+ 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'], context=context)
+ invoice_line_info = self.pool.get('account.invoice.line').read(cr, uid, claim_info['invoice_line_id'][0], context=context)
+ invoice_line_info['quantity'] = claim_info['product_returned_quantity']
+ new_lines.append(invoice_line_info)
+ return super(account_invoice, self)._refund_cleanup_lines(cr, uid, new_lines, context=context)
+
+account_invoice()
diff --git a/crm_claim_rma/crm_claim_rma.py b/crm_claim_rma/crm_claim_rma.py
index 92a079f3..9677903a 100644
--- a/crm_claim_rma/crm_claim_rma.py
+++ b/crm_claim_rma/crm_claim_rma.py
@@ -27,6 +27,7 @@ from datetime import datetime
from dateutil.relativedelta import relativedelta
import time
from tools.translate import _
+from tools import DEFAULT_SERVER_DATE_FORMAT
#===== TO REFACTORED IN A GENERIC MODULE
class substate_substate(osv.osv):
@@ -57,14 +58,15 @@ class claim_line(osv.osv):
res[line.id] = line.unit_sale_price*line.product_returned_quantity
return res
- def _get_claim_seq(self, cr, uid, ids, field_name, arg,context):
- res = {}
- for line in self.browse(cr,uid,ids):
- res[line.id] = line.claim_id.sequence
- return res
+# def _get_claim_seq(self, cr, uid, ids, field_name, arg,context):
+# res = {}
+# for line in self.browse(cr,uid,ids):
+# res[line.id] = line.claim_id.sequence
+# return res
_columns = {
- 'name': fields.function(_get_claim_seq, method=True, string='Claim n°', type='char', size=64,store=True),
+ 'name': fields.char('Description', size=64,required=True),
+# 'name': fields.function(_get_claim_seq, method=True, string='Claim n°', type='char', size=64,store=True),
'claim_origine': fields.selection([('none','Not specified'),
('legal','Legal retractation'),
('cancellation','Order cancellation'),
@@ -74,7 +76,8 @@ class claim_line(osv.osv):
('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"),
- 'invoice_id': fields.many2one('account.invoice', 'Invoice',help="The invoice related to the returned product"),
+#use the invoice line instead of the invoice
+# 'invoice_id': fields.many2one('account.invoice', 'Invoice',help="The invoice related to the returned product"),
'product_id': fields.many2one('product.product', 'Product',help="Returned product"),
'product_returned_quantity' : fields.float('Quantity', digits=(12,2), help="Quantity of product returned"),
@@ -87,7 +90,6 @@ class claim_line(osv.osv):
'warranty_type': fields.char('Warranty type', size=64, readonly=True,help="from product form"),
"warranty_return_partner" : fields.many2one('res.partner.address', 'Warranty return',help="Where the customer has to send back the product(s)"),
'claim_id': fields.many2one('crm.claim', 'Related claim',help="To link to the case.claim object"),
- 'selected' : fields.boolean('s', help="Check to select"),
'state' : fields.selection([('draft','Draft'),
('refused','Refused'),
('confirmed','Confirmed, waiting for product'),
@@ -96,6 +98,9 @@ class claim_line(osv.osv):
('treated','Treated')], 'State'),
'substate_id': fields.many2one('substate.substate', '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', help="To set the last state / substate change"),
+ 'invoice_line_id': fields.many2one('account.invoice.line', 'Invoice Line', help='The invoice line related to the returned product'),
+ 'refund_line_id': fields.many2one('account.invoice.line', 'Refund Line', help='The refund line related to the returned product'),
+ 'move_line_id': fields.many2one('stock.move', 'Move Line', help='The move line related to the returned product'),
}
_defaults = {
@@ -104,16 +109,17 @@ class claim_line(osv.osv):
}
# Method to calculate warranty limit
- def set_warranty_limit(self, cr, uid, ids,context,claim_line):
- if claim_line.invoice_id.date_invoice:
+ def set_warranty_limit(self, cr, uid, ids, context, claim_line):
+ date_invoice = claim_line.invoice_line_id.invoice_id.date_invoice
+ if date_invoice:
warning = "Valid"
if claim_line.claim_id.claim_type == 'supplier':
if claim_line.prodlot_id :
- limit = (datetime.strptime(claim_line.invoice_id.date_invoice, '%Y-%m-%d') + relativedelta(months=int(claim_line.product_id.seller_ids[0].warranty_duration))).strftime('%Y-%m-%d') # TO BE IMPLEMENTED !!!
+ limit = (datetime.strptime(date_invoice, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(months=int(claim_line.product_id.seller_ids[0].warranty_duration))).strftime(DEFAULT_SERVER_DATE_FORMAT) # TO BE IMPLEMENTED !!!
else :
- limit = (datetime.strptime(claim_line.invoice_id.date_invoice, '%Y-%m-%d') + relativedelta(months=int(claim_line.product_id.seller_ids[0].warranty_duration))).strftime('%Y-%m-%d')
+ limit = (datetime.strptime(date_invoice, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(months=int(claim_line.product_id.seller_ids[0].warranty_duration))).strftime(DEFAULT_SERVER_DATE_FORMAT)
else :
- limit = (datetime.strptime(claim_line.invoice_id.date_invoice, '%Y-%m-%d') + relativedelta(months=int(claim_line.product_id.warranty))).strftime('%Y-%m-%d')
+ limit = (datetime.strptime(date_invoice, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(months=int(claim_line.product_id.warranty))).strftime(DEFAULT_SERVER_DATE_FORMAT)
if limit < claim_line.claim_id.date:
warning = 'Expired'
self.write(cr,uid,ids,{
@@ -124,135 +130,126 @@ class claim_line(osv.osv):
raise osv.except_osv(_('Error !'), _('Cannot find any date for invoice ! Must be a validated invoice !'))
return True
- # Method to return the partner delivery address or if none, the default address
- def _get_partner_address(self, cr, uid, ids, context,partner):
- # dedicated_delivery_address stand for the case a new type of address more particularly dedicated to return delivery would be implemented.
- dedicated_delivery_address_id = self.pool.get('res.partner.address').search(cr, uid, [('partner_id','=',partner.id),('type','like','dedicated_delivery')])
- if dedicated_delivery_address_id:
- return dedicated_delivery_address_id
- else:
- delivery_address_id = self.pool.get('res.partner.address').search(cr, uid, [('partner_id','=',partner.id),('type','like','delivery')])
- if delivery_address_id: # if delivery address set, use it
- return delivery_address_id
- else:
- default_address_id = self.pool.get('res.partner.address').search(cr, uid, [('partner_id','=',partner.id),('type','like','default')])
- if default_address_id: # if default address set, use it
- return default_address_id
- else:
- raise osv.except_osv(_('Error !'), _('Cannot find any address for this product partner !'))
-
# Method to calculate warranty return address
- def set_warranty_return_address(self, cr, uid, ids,context,claim_line):
+ def set_warranty_return_address(self, cr, uid, ids, context, claim_line):
return_address = None
warranty_type = 'company'
- if claim_line.product_id.seller_ids:
- # default : use first supplier method
- seller = claim_line.product_id.seller_ids[0]
- if len(claim_line.product_id.seller_ids) > 1 :
- # multi supplier method
- print "TO BE IMPLEMENTED"
- print "lenght: ",len(claim_line.product_id.seller_ids)
- #seller = set right seller line
- if seller.warranty_return_partner:
- return_partner = seller.warranty_return_partner
- if return_partner == 'company':
- return_address = self._get_partner_address(cr, uid, ids, context,claim_line.claim_id.company_id.partner_id)[0]
- elif return_partner == 'supplier':
- return_address = self._get_partner_address(cr, uid, ids, context,claim_line.product_id.seller_ids[0].name)[0]
- warranty_type = 'supplier'
- elif return_partner == 'brand':
- return_address = self._get_partner_address(cr, uid, ids, context, claim_line.product_id.product_brand_id.partner_id)[0]
- warranty_type = 'brand'
- else :
- warranty_type = 'other'
- # TO BE IMPLEMENTED if something to do...
- else :
+ seller = claim_line.product_id.seller_info_id
+ if seller:
+ return_partner = seller.warranty_return_partner
+ if return_partner:
+ warranty_type = return_partner
+ else:
+ warranty_type = 'company'
+ return_address = seller.warranty_return_address.id
+# if return_partner == 'company':
+# return_address = self._get_partner_address(cr, uid, ids, context,claim_line.claim_id.company_id.partner_id)[0]
+# elif return_partner == 'supplier':
+# return_address = self._get_partner_address(cr, uid, ids, context,claim_line.product_id.seller_ids[0].name)[0]
+# warranty_type = 'supplier'
+# elif return_partner == 'brand':
+# return_address = self._get_partner_address(cr, uid, ids, context, claim_line.product_id.product_brand_id.partner_id)[0]
+# warranty_type = 'brand'
+# else :
+# warranty_type = 'other'
+# # TO BE IMPLEMENTED if something to do...
+# else :
+# warranty_type = 'company'
+# return_address = self._get_default_company_address(cr, uid, claim_line.claim_id.company_id, context=context)
#TODO fix me use default address
- self.write(cr,uid,ids,{'warranty_return_partner':1,'warranty_type': 'company'})
- return True
+# self.write(cr,uid,ids,{'warranty_return_partner':1,'warranty_type': 'company'})
+# return True
#raise osv.except_osv(_('Error !'), _('Cannot find any warranty return partner for this product !'))
else :
+ warranty_type = 'company'
+ if claim_line.claim_id.company_id.crm_return_address_id:
+ return_address = [claim_line.claim_id.company_id.crm_return_address_id.id]
+ else:
+ return_address = [claim_line.claim_id.company_id.partner_id.address[0].id]
+# return_address = self._get_default_company_address(cr, uid, claim_line.claim_id.company_id, context=context)
#TODO fix me use default address
- self.write(cr,uid,ids,{'warranty_return_partner':1,'warranty_type': 'company'})
- return True
+# self.write(cr,uid,ids,{'warranty_return_partner':1,'warranty_type': 'company'})
+# return True
#raise osv.except_osv(_('Error !'), _('Cannot find any supplier for this product !'))
self.write(cr,uid,ids,{'warranty_return_partner':return_address,'warranty_type':warranty_type})
return True
# Method to calculate warranty limit and validity
def set_warranty(self, cr, uid, ids,context=None):
- for claim_line in self.browse(cr,uid,ids):
- if claim_line.product_id and claim_line.invoice_id:
- self.set_warranty_limit(cr, uid, ids,context,claim_line)
- self.set_warranty_return_address(cr, uid, ids,context,claim_line)
+ 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, context, claim_line)
+ self.set_warranty_return_address(cr, uid, ids, context, claim_line)
else:
- raise osv.except_osv(_('Error !'), _('PLEASE SET PRODUCT & INVOICE!'))
+ raise osv.except_osv(_('Error !'), _('PLEASE SET PRODUCT & INVOICE!'))
return True
+#TODO add the option split the claim_line in order to manage the same product separately
+
claim_line()
-#=====
-class product_exchange(osv.osv):
- """
- Class to manage product exchanges history
- """
- _name = "product.exchange"
- _description = "exchange history line"
-
- # Method to calculate total amount of the line : qty*UP
- def total_amount_returned(self, cr, uid, ids, field_name, arg,context):
- res = {}
- for line in self.browse(cr,uid,ids):
- res[line.id] = line.returned_unit_sale_price*line.returned_product_qty
- return res
+#===== deprecated everything is based on the claim_line so product_exchange is useless
+#class product_exchange(osv.osv):
+# """
+# Class to manage product exchanges history
+# """
+# _name = "product.exchange"
+# _description = "exchange history line"
+#
+# # Method to calculate total amount of the line : qty*UP
+# def total_amount_returned(self, cr, uid, ids, field_name, arg,context):
+# res = {}
+# for line in self.browse(cr,uid,ids):
+# res[line.id] = line.returned_unit_sale_price*line.returned_product_qty
+# return res
- # Method to calculate total amount of the line : qty*UP
- def total_amount_replacement(self, cr, uid, ids, field_name, arg,context):
- res = {}
- for line in self.browse(cr,uid,ids):
- res[line.id] = line.replacement_unit_sale_price*line.replacement_product_qty
- return res
+# # Method to calculate total amount of the line : qty*UP
+# def total_amount_replacement(self, cr, uid, ids, field_name, arg,context):
+# res = {}
+# for line in self.browse(cr,uid,ids):
+# res[line.id] = line.replacement_unit_sale_price*line.replacement_product_qty
+# return res
- # Method to get the replacement product unit price
- def get_replacement_price(self, cr, uid, ids, field_name, arg,context):
- res = {}
- for line in self.browse(cr,uid,ids):
- res[line.id] = line.replacement_product.list_price
- return res
-
- _columns = {
- 'name': fields.char('Comment', size=128, required=True),
- 'exchange_send_date' : fields.date('Exchange date'),
- 'returned_product' : fields.many2one('product.product', 'Returned product', required=True), # ADD FILTER ON RETURNED PROD
- 'returned_product_serial' : fields.many2one('stock.production.lot', 'Returned serial/Lot n°'),
- 'returned_product_qty' : fields.float('Returned quantity', digits=(12,2), help="Quantity of product returned"),
- 'replacement_product' : fields.many2one('product.product', 'Replacement product', required=True),
- 'replacement_product_serial' : fields.many2one('stock.production.lot', 'Replacement serial/Lot n°'),
- 'replacement_product_qty' : fields.float('Replacement quantity', digits=(12,2), help="Quantity of product replaced"),
- 'claim_return_id' : fields.many2one('crm.claim', 'Related claim'), # To link to the case.claim object
- 'selected' : fields.boolean('s', help="Check to select"),
- 'state' : fields.selection([('draft','Draft'),
- ('confirmed','Confirmed'),
- ('to_send','To send'),
- ('sent','Sent')], 'State'),
- 'returned_unit_sale_price' : fields.float('Unit sale price', digits=(12,2)),
- 'returned_value' : fields.function(total_amount_returned, method=True, string='Total return', type='float', help="Quantity exchanged * Unit sold price",),
- 'replacement_unit_sale_price' : fields.function(get_replacement_price, method=True, string='Unit sale price', type='float',),
- 'replacement_value' : fields.function(total_amount_replacement, method=True, string='Total return', type='float', help="Quantity replaced * Unit sold price",),
- }
- _defaults = {
- 'state': lambda *a: 'draft',
- }
-
-product_exchange()
+# # Method to get the replacement product unit price
+# def get_replacement_price(self, cr, uid, ids, field_name, arg,context):
+# res = {}
+# for line in self.browse(cr,uid,ids):
+# res[line.id] = line.replacement_product.list_price
+# return res
+#
+# _columns = {
+# 'name': fields.char('Comment', size=128, required=True),
+# 'exchange_send_date' : fields.date('Exchange date'),
+# 'returned_product' : fields.many2one('product.product', 'Returned product', required=True), # ADD FILTER ON RETURNED PROD
+# 'returned_product_serial' : fields.many2one('stock.production.lot', 'Returned serial/Lot n°'),
+# 'returned_product_qty' : fields.float('Returned quantity', digits=(12,2), help="Quantity of product returned"),
+# 'replacement_product' : fields.many2one('product.product', 'Replacement product', required=True),
+# 'replacement_product_serial' : fields.many2one('stock.production.lot', 'Replacement serial/Lot n°'),
+# 'replacement_product_qty' : fields.float('Replacement quantity', digits=(12,2), help="Quantity of product replaced"),
+# 'claim_return_id' : fields.many2one('crm.claim', 'Related claim'), # To link to the case.claim object
+# 'selected' : fields.boolean('s', help="Check to select"),
+# 'state' : fields.selection([('draft','Draft'),
+# ('confirmed','Confirmed'),
+# ('to_send','To send'),
+# ('sent','Sent')], 'State'),
+# 'returned_unit_sale_price' : fields.float('Unit sale price', digits=(12,2)),
+# 'returned_value' : fields.function(total_amount_returned, method=True, string='Total return', type='float', help="Quantity exchanged * Unit sold price",),
+# 'replacement_unit_sale_price' : fields.function(get_replacement_price, method=True, string='Unit sale price', type='float',),
+# 'replacement_value' : fields.function(total_amount_replacement, method=True, string='Total return', type='float', help="Quantity replaced * Unit sold price",),
+# }
+# _defaults = {
+# 'state': lambda *a: 'draft',
+# }
+#
+#product_exchange()
+#==========
-#==========
class crm_claim(osv.osv):
_inherit = 'crm.claim'
_columns = {
- 'sequence': fields.char('Sequence', size=128,readonly=True,states={'draft': [('readonly', False)]},required=True, help="Company internal claim unique number"),
+ 'number': fields.char('Number', size=128,readonly=True,states={'draft': [('readonly', False)]},required=True, help="Company internal claim unique number"),
'claim_type': fields.selection([('customer','Customer'),
('supplier','Supplier'),
('other','Other')], 'Claim type', required=True, help="customer = from customer to company ; supplier = from company to supplier"),
@@ -268,26 +265,30 @@ class crm_claim(osv.osv):
'real_revenue': fields.float('Real revenue'), # A VOIR SI COMPTA ANA ou lien vers compte ana ?
'real_cost': fields.float('Real cost'), # A VOIR SI COMPTA ANA ou lien vers compte ana ?
'invoice_ids': fields.one2many('account.invoice', 'claim_id', 'Refunds'),
- 'picking_ids': fields.one2many('stock.picking', 'claim_id', 'RMA')
+ 'picking_ids': fields.one2many('stock.picking', 'claim_id', 'RMA'),
+ 'invoice_id': fields.many2one('account.invoice', 'Invoice', help='Related invoice'),
+ 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True),
+ 'case_id': fields.many2one('claim.rma.case', 'Case'),
}
_defaults = {
- 'sequence': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'crm.claim'),
- 'claim_type': lambda *a: 'customer',}
-
- #===== Method to select all returned lines =====
- def select_all(self,cr, uid, ids,context):
- return_obj = self.pool.get('claim.line')
- for line in self.browse(cr,uid,ids)[0].claim_line_ids:
- return_obj.write(cr,uid,line.id,{'selected':True})
- return True
-
- #===== Method to unselect all returned lines =====
- def unselect_all(self,cr, uid, ids,context):
- return_obj = self.pool.get('claim.line')
- for line in self.browse(cr,uid,ids)[0].claim_line_ids:
- return_obj.write(cr,uid,line.id,{'selected':False})
- return True
-
+ 'number': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'crm.claim'),
+ 'claim_type': lambda *a: 'customer',
+ 'warehouse_id': lambda *a: 1,
+ }
+# #===== Method to select all returned lines =====
+# def select_all(self,cr, uid, ids,context):
+# return_obj = self.pool.get('claim.line')
+# for line in self.browse(cr,uid,ids)[0].claim_line_ids:
+# return_obj.write(cr,uid,line.id,{'selected':True})
+# return True
+
+# #===== Method to unselect all returned lines =====
+# def unselect_all(self,cr, uid, ids,context):
+# return_obj = self.pool.get('claim.line')
+# for line in self.browse(cr,uid,ids)[0].claim_line_ids:
+# return_obj.write(cr,uid,line.id,{'selected':False})
+# return True
+
# === deprecated if we use the refund wizard of the account module ===
# def refund(self, cr, uid, ids, context=None):
# mod_obj = self.pool.get('ir.model.data')
@@ -297,7 +298,41 @@ class crm_claim(osv.osv):
# result = act_obj.read(cr, uid, id, context=context)
# print 'result', result
# return result
-
-crm_claim()
+
+ def onchange_invoice_id(self, cr, uid, ids, invoice_id, context=None):
+ invoice_line_obj = self.pool.get('account.invoice.line')
+ invoice_line_ids = invoice_line_obj.search(cr, uid, [('invoice_id', '=', invoice_id)])
+ claim_lines = []
+ for invoice_line in invoice_line_obj.browse(cr,uid,invoice_line_ids):
+# claim_line_obj = self.pool.get('claim.line')
+ 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,
+# 'prodlot_id' : invoice_line.,
+ 'state' : 'draft',
+ })
+# for line in claim_line_obj.browse(cr,uid,[line_id],context):
+# line.set_warranty()
+ return {'value' : {'claim_line_ids' : claim_lines}}
+
+crm_claim()
+
+class claim_rma_case(osv.osv):
+ _name = "claim.rma.case"
+ _description = "List of RMA cases"
+
+ _columns = {
+ 'name': fields.char('Description', size=64, required=True),
+ }
+
+ _defaults = {
+ }
+
+claim_rma_case()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/crm_claim_rma/crm_claim_rma_data.xml b/crm_claim_rma/crm_claim_rma_data.xml
index bf3a4447..cd7dcf95 100644
--- a/crm_claim_rma/crm_claim_rma_data.xml
+++ b/crm_claim_rma/crm_claim_rma_data.xml
@@ -6,16 +6,16 @@
CRM Claim
crm.claim.rma
-
+
CRM Claim
crm.claim.rma
RMA-%(year)s/
-
+
-
+
Factual Claims
@@ -33,11 +33,11 @@
-
+
-
+
Corrective
@@ -47,11 +47,11 @@
Preventive
-
+
-
+
Accepted as Claim
1
@@ -79,5 +79,46 @@
Sales
+
+
+
+
+ No Inventory
+
+
+ Customer Return
+
+
+ Buyer Cancelled
+
+
+ General Adjustement
+
+
+ Could Not Ship
+
+
+ Different Item
+
+
+ Merchandise Not Received
+
+
+ Merchandise Not As Described
+
+
+ Pricing Error
+
+
+ Shipping Address Undeliverable
+
+
+ Delivered Late by Carrier
+
+
+ Missed Fulfilment Promise
+
diff --git a/crm_claim_rma/crm_claim_rma_view.xml b/crm_claim_rma/crm_claim_rma_view.xml
index 80ad4406..f1010280 100644
--- a/crm_claim_rma/crm_claim_rma_view.xml
+++ b/crm_claim_rma/crm_claim_rma_view.xml
@@ -37,13 +37,13 @@
+ separator="1" help="In Progress Claims"/>
-
+
-
+
@@ -57,10 +57,10 @@
+ context="{'group_by':'invoice_id'}" />
+ context="{'group_by':'product_id'}" />
@@ -70,7 +70,7 @@
-
+
CRM - Claims Tree
@@ -78,12 +78,9 @@
tree
-
-
-
@@ -101,29 +98,30 @@
-
+
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
@@ -139,8 +137,8 @@
-
-
+
+
@@ -155,95 +153,97 @@
-
+
-
- CRM - Product exchange Tree
- product.exchange
- tree
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- CRM - Product exchange Form
- product.exchange
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
CRM - Claim product return Form
crm.claim
-
+
-
+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
+
+ parent="crm_claim.menu_config_claim" action="act_crm_claim_substates" sequence="2"/>
diff --git a/crm_claim_rma/res_company.py b/crm_claim_rma/res_company.py
new file mode 100644
index 00000000..8c41d327
--- /dev/null
+++ b/crm_claim_rma/res_company.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+#########################################################################
+# #
+# #
+#########################################################################
+# #
+# Copyright (C) 2009-2011 Akretion, Raphaël Valyi, Sébastien Beau, #
+# Emmanuel Samyn, Benoît Guillot #
+# #
+#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 . #
+#########################################################################
+
+from osv import fields, osv
+
+class res_company(osv.osv):
+ _inherit = "res.company"
+
+ _columns = {
+ 'crm_return_address_id': fields.many2one('res.partner.address', 'Crm return address', help="Default address where the customers has to send back the returned product in a crm claim. If empty the address is the company address"),
+ }
+
+res_company()
diff --git a/crm_claim_rma/res_company_view.xml b/crm_claim_rma/res_company_view.xml
new file mode 100644
index 00000000..c75338be
--- /dev/null
+++ b/crm_claim_rma/res_company_view.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+ crm_claim_rma.company_form
+ res.company
+
+
+ form
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/crm_claim_rma/rma_data.xml b/crm_claim_rma/rma_data.xml
index e597cbd2..a48e2e41 100644
--- a/crm_claim_rma/rma_data.xml
+++ b/crm_claim_rma/rma_data.xml
@@ -1,6 +1,6 @@
-
+
CRM claim
@@ -14,52 +14,52 @@
5
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/crm_claim_rma/security/ir.model.access.csv b/crm_claim_rma/security/ir.model.access.csv
index 05e5a710..c9b933a0 100644
--- a/crm_claim_rma/security/ir.model.access.csv
+++ b/crm_claim_rma/security/ir.model.access.csv
@@ -1,10 +1,7 @@
"id","name","model_id","group_id","perm_read","perm_write","perm_create","perm_unlink"
"access_substate_user","substate.substate.user","substate.substate","base.group_sale_salesman_all_leads","True","True","True",
"access_claim_line_user","claim.line.user","claim.line","base.group_sale_salesman_all_leads","True","True","True",
-"access_exchange_user","product.exchange.user","product.exchange","base.group_sale_salesman_all_leads","True","True","True",
"access_substate_manager","substate.substate.manager","substate.substate","base.group_sale_manager","True","True","True","True"
"access_claim_line_manager","claim.line.manager","claim.line","base.group_sale_manager","True","True","True","True"
-"access_exchange_manager","product.exchange.manager","product.exchange","base.group_sale_manager","True","True","True","True"
"access_substate_user","substate.substate.user","substate.substate","base.group_sale_salesman","True","True","True",
"access_claim_line_user","claim.line.user","claim.line","base.group_sale_salesman","True","True","True",
-"access_exchange_user","product.exchange.user","product.exchange","base.group_sale_salesman","True","True","True",
diff --git a/crm_claim_rma/stock.py b/crm_claim_rma/stock.py
index ac7522b6..c1515fa4 100644
--- a/crm_claim_rma/stock.py
+++ b/crm_claim_rma/stock.py
@@ -31,3 +31,14 @@ class stock_picking(osv.osv):
_columns = {
'claim_id': fields.many2one('crm.claim', 'Claim'),
}
+
+class stock_warehouse(osv.osv):
+
+ _inherit = "stock.warehouse"
+
+
+ _columns = {
+ 'lot_rma_id': fields.many2one('stock.location', 'Location RMA'),
+ 'lot_carrier_loss_id': fields.many2one('stock.location', 'Location Carrier Loss'),
+ 'lot_breakage_loss_id': fields.many2one('stock.location', 'Location Breakage Loss'),
+ }
diff --git a/crm_claim_rma/stock_data.xml b/crm_claim_rma/stock_data.xml
new file mode 100644
index 00000000..e0d0bc67
--- /dev/null
+++ b/crm_claim_rma/stock_data.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+ Carrier Loss
+ internal
+
+
+
+ RMA
+ internal
+
+
+
+ Breakage Loss
+ internal
+
+
+
+
+
+
+
+
+
+
diff --git a/crm_claim_rma/stock_view.xml b/crm_claim_rma/stock_view.xml
index c6191a3e..aa108cd2 100644
--- a/crm_claim_rma/stock_view.xml
+++ b/crm_claim_rma/stock_view.xml
@@ -9,8 +9,8 @@
-
- crm_claim_rma.picking_form
+
+ crm_claim_rma.picking_in_form
stock.picking
@@ -18,7 +18,39 @@
-
+
+
+
+
+
+
+
+ crm_claim_rma.picking_out_form
+ stock.picking
+
+
+ form
+
+
+
+
+
+
+
+
+
+
+ crm_claim_rma.warehouse_form
+ stock.warehouse
+
+
+ form
+
+
+
+
+
+
diff --git a/crm_claim_rma/wizard/__init__.py b/crm_claim_rma/wizard/__init__.py
index 194b9140..71935e4b 100644
--- a/crm_claim_rma/wizard/__init__.py
+++ b/crm_claim_rma/wizard/__init__.py
@@ -22,9 +22,12 @@
#########################################################################
import returned_lines_from_serial
-import returned_lines_from_invoice
-import picking_from_returned_lines
-import refund_from_returned_lines
-import exchange_from_returned_lines
-import picking_from_exchange_lines
+#import returned_lines_from_invoice
+#import picking_from_returned_lines
+#import refund_from_returned_lines
+#import exchange_from_returned_lines
+#import picking_from_exchange_lines
import get_empty_serial
+
+import claim_make_picking
+import account_invoice_refund
diff --git a/crm_claim_rma/wizard/account_invoice_refund.py b/crm_claim_rma/wizard/account_invoice_refund.py
new file mode 100644
index 00000000..e72b2830
--- /dev/null
+++ b/crm_claim_rma/wizard/account_invoice_refund.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+#########################################################################
+# #
+# crm_claim_rma for OpenERP #
+# Copyright (C) 2012 Akretion, #
+# Benoît GUILLOT #
+#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 . #
+#########################################################################
+
+from osv import fields, osv
+
+class account_invoice_refund(osv.osv_memory):
+ _inherit = "account.invoice.refund"
+
+ def compute_refund(self, cr, uid, ids, mode='refund', context=None):
+ context['active_ids'] = context['invoice_ids']
+ return super(account_invoice_refund, self).compute_refund(cr, uid, ids, mode='refund', context=context)
+
+account_invoice_refund()
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/crm_claim_rma/wizard/claim_make_picking.py b/crm_claim_rma/wizard/claim_make_picking.py
new file mode 100644
index 00000000..abcc0fab
--- /dev/null
+++ b/crm_claim_rma/wizard/claim_make_picking.py
@@ -0,0 +1,149 @@
+# -*- coding: utf-8 -*-
+#########################################################################
+# #
+# #
+#########################################################################
+# #
+# crm_claim_rma for OpenERP #
+# Copyright (C) 2009-2012 Akretion, Emmanuel Samyn, #
+# Benoît GUILLOT #
+#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 . #
+#########################################################################
+
+from osv import fields, osv
+import time
+from tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
+
+class claim_make_picking(osv.osv_memory):
+ _name='claim_make_picking.wizard'
+ _description='Wizard to create pickings from claim lines'
+ _columns = {
+ 'claim_line_source_location' : fields.many2one('stock.location', 'Source Location',help="Location where the returned products are from.", required=True),
+ 'claim_line_dest_location' : fields.many2one('stock.location', 'Dest. Location',help="Location where the system will stock the returned products.", required=True),
+ 'claim_line_ids' : fields.many2many('claim.line', 'claim_line_picking', 'claim_picking_id', 'claim_line_id', 'Claim lines'),
+ }
+
+ def _get_claim_lines(self, cr, uid, context):
+ return self.pool.get('crm.claim').read(cr, uid, context['active_id'], ['claim_line_ids'], context=context)['claim_line_ids']
+
+ # Get default source location
+ def _get_source_loc(self, cr, uid, context):
+ warehouse_obj = self.pool.get('stock.warehouse')
+ warehouse_id = context['warehouse_id']
+ if context.get('picking_type') == 'out':
+ loc_id = warehouse_obj.read(cr, uid, warehouse_id, ['lot_stock_id'], context=context)['lot_stock_id'][0]
+ elif context.get('picking_type') in ['in', 'loss']:
+ loc_id = warehouse_obj.read(cr, uid, warehouse_id, ['lot_output_id'], context=context)['lot_output_id'][0]
+ return loc_id
+
+ # Get default destination location
+ def _get_dest_loc(self, cr, uid, context):
+ warehouse_obj = self.pool.get('stock.warehouse')
+ warehouse_id = context['warehouse_id']
+ if context.get('picking_type') == 'out':
+ loc_id = self.pool.get('res.partner').read(cr, uid, context.get('customer_id'), ['property_stock_customer'], context=context)['property_stock_customer'][0]
+ elif 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_source_location': _get_source_loc,
+ 'claim_line_dest_location': _get_dest_loc,
+ 'claim_line_ids': _get_claim_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(self, cr, uid, ids, context=None):
+ if context is None: context = {}
+ view_obj = self.pool.get('ir.ui.view')
+ if context.get('picking_type') in ['in', 'loss']:
+ p_type = 'in'
+ view_xml_id = 'view_picking_in_form'
+ view_name = 'stock.picking.in.form'
+ if context.get('picking_type') == 'in':
+ note = 'RMA picking in'
+ name = 'Customer picking in'
+ elif context.get('picking_type') == 'loss':
+ name = 'Customer product loss'
+ note = 'RMA product loss'
+ elif context.get('picking_type') == 'out':
+ p_type = 'out'
+ note = 'RMA picking out'
+ name = 'Customer picking out'
+ view_xml_id = 'view_picking_in_form'
+ view_name = 'stock.picking.in.form'
+ 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)
+ partner_id = claim.partner_id.id
+ # create picking
+ picking_id = self.pool.get('stock.picking').create(cr, uid, {
+ 'origin': claim.number,
+ 'type': p_type,
+ 'move_type': 'one', # direct
+ 'state': 'draft',
+ 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
+ 'address_id': claim.partner_address_id.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,
+ })
+ # 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,
+ 'address_id': claim.partner_address_id.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,
+ })
+ return {
+ 'name': '%s' % name,
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'view_id': view_id,
+ 'domain' : "[('type', '=', '%s'),('partner_id','=',%s)]" % (p_type, partner_id),
+ 'res_model': 'stock.picking',
+ 'res_id': picking_id,
+ 'type': 'ir.actions.act_window',
+ }
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/crm_claim_rma/wizard/claim_make_picking_view.xml b/crm_claim_rma/wizard/claim_make_picking_view.xml
new file mode 100644
index 00000000..dd131caf
--- /dev/null
+++ b/crm_claim_rma/wizard/claim_make_picking_view.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+ claim_picking
+ claim_make_picking.wizard
+ form
+
+
+
+
+
+
+ action_claim_picking_in
+ ir.actions.act_window
+ claim_make_picking.wizard
+ crm.claim
+ form
+ form
+ new
+ {'picking_type': 'in'}
+
+
+
+ action_claim_picking_out
+ ir.actions.act_window
+ claim_make_picking.wizard
+ crm.claim
+ form
+ form
+ new
+ {'picking_type': 'out'}
+
+
+
+ action_claim_picking_loss
+ ir.actions.act_window
+ claim_make_picking.wizard
+ crm.claim
+ form
+ form
+ new
+ {'picking_type': 'loss'}
+
+
+
+
diff --git a/crm_claim_rma/wizard/picking_from_returned_lines.py b/crm_claim_rma/wizard/picking_from_returned_lines.py
index ae79a1b4..b7f936c6 100644
--- a/crm_claim_rma/wizard/picking_from_returned_lines.py
+++ b/crm_claim_rma/wizard/picking_from_returned_lines.py
@@ -145,7 +145,7 @@ class picking_out_from_returned_lines(osv.osv_memory):
if True: # line.selected:
M2M.append(self.pool.get('temp.claim.line').create(cr, uid, {
'claim_origine' : "none",
- 'invoice_id' : line.invoice_id.id,
+ 'invoice_id' : line.invoice_line_id.invoice_id.id,
'product_id' : line.product_id.id,
'product_returned_quantity' : line.product_returned_quantity,
'prodlot_id' : line.prodlot_id.id,
diff --git a/crm_claim_rma/wizard/returned_lines_from_invoice_wizard_view.xml b/crm_claim_rma/wizard/returned_lines_from_invoice_wizard_view.xml
index 6ecad059..2ae90c6e 100644
--- a/crm_claim_rma/wizard/returned_lines_from_invoice_wizard_view.xml
+++ b/crm_claim_rma/wizard/returned_lines_from_invoice_wizard_view.xml
@@ -60,8 +60,8 @@
form