[REF] crm_claim_rma: refactor to improve the management of the claims

This commit is contained in:
Benoit Guillot
2012-09-12 11:29:21 +02:00
parent 0d5f7fb0e1
commit febe2df617
19 changed files with 769 additions and 293 deletions

View File

@@ -25,3 +25,4 @@ import wizard
import crm_claim_rma
import account_invoice
import stock
import res_company

View File

@@ -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': [

View File

@@ -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()

View File

@@ -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:

View File

@@ -6,16 +6,16 @@
<field name="name">CRM Claim</field>
<field name="code">crm.claim.rma</field>
</record>
<record id="seq_claim" model="ir.sequence">
<field name="name">CRM Claim</field>
<field name="code">crm.claim.rma</field>
<field eval="5" name="padding"/>
<field name="prefix">RMA-%(year)s/</field>
</record>
<!-- Claims Categories -->
<record model="crm.case.categ" id="categ_claim1">
<field name="name">Factual Claims</field>
<field name="section_id" ref="crm.section_sales_department"/>
@@ -33,11 +33,11 @@
<field name="section_id" ref="crm.section_sales_department"/>
<field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/>
</record>
<!--
Case Category2
-->
<record model="crm.case.resource.type" id="type_claim1">
<field name="name">Corrective</field>
<field name="section_id" ref="crm.section_sales_department"/>
@@ -47,11 +47,11 @@
<field name="name">Preventive</field>
<field name="section_id" ref="crm.section_sales_department"/>
</record>
<!--
Case Stage
-->
<record model="crm.case.stage" id="stage_claim1">
<field name="name">Accepted as Claim</field>
<field name="sequence">1</field>
@@ -79,5 +79,46 @@
<field name="code">Sales</field>
<field name="stage_ids" eval="[(4, ref('stage_claim1')), (4, ref('stage_claim2')), (4, ref('stage_claim3')), (4, ref('stage_claim5'))]"/>
</record>
<!--
Default Values for : RMA Case
-->
<record id="case1" model="claim.rma.case">
<field name="name">No Inventory</field>
</record>
<record id="case2" model="claim.rma.case">
<field name="name">Customer Return</field>
</record>
<record id="case3" model="claim.rma.case">
<field name="name">Buyer Cancelled</field>
</record>
<record id="case4" model="claim.rma.case">
<field name="name">General Adjustement</field>
</record>
<record id="case5" model="claim.rma.case">
<field name="name">Could Not Ship</field>
</record>
<record id="case6" model="claim.rma.case">
<field name="name">Different Item</field>
</record>
<record id="case7" model="claim.rma.case">
<field name="name">Merchandise Not Received</field>
</record>
<record id="case8" model="claim.rma.case">
<field name="name">Merchandise Not As Described</field>
</record>
<record id="case9" model="claim.rma.case">
<field name="name">Pricing Error</field>
</record>
<record id="case10" model="claim.rma.case">
<field name="name">Shipping Address Undeliverable</field>
</record>
<record id="case11" model="claim.rma.case">
<field name="name">Delivered Late by Carrier</field>
</record>
<record id="case12" model="claim.rma.case">
<field name="name">Missed Fulfilment Promise</field>
</record>
</data>
</openerp>

View File

@@ -37,13 +37,13 @@
<filter icon="terp-camera_test"
string="In Progress"
domain="[('state','in',('confirmed','in_to_control','in_to_treate'))]"
separator="1" help="In Progress Claims"/>
separator="1" help="In Progress Claims"/>
<separator orientation="vertical"/>
<field name="state" select='1'/>
<field name="substate_id" select='1'/>
<field name="substate_id" select='1'/>
<field name="name" select='1'/>
<field name="warning" select='1'/>
<field name="invoice_id" select='1'/>
<field name="invoice_line_id" select='1'/>
<field name="product_id" select='1'/>
<field name="prodlot_id" select='1'/>
<newline/>
@@ -57,10 +57,10 @@
<group expand="0" string="Group By...">
<filter string="Invoice" icon="terp-dolar"
domain="[]" help="Invoice"
context="{'group_by':'invoice_id'}" />
context="{'group_by':'invoice_id'}" />
<filter string="Product" icon="terp-product"
domain="[]" help="Product"
context="{'group_by':'product_id'}" />
context="{'group_by':'product_id'}" />
<separator orientation="vertical"/>
<filter string="Substate" icon="terp-stage"
domain="[]" context="{'group_by':'substate_id'}" />
@@ -70,7 +70,7 @@
</search>
</field>
</record>
<!-- TREE -->
<record model="ir.ui.view" id="crm_claim_line_tree_view">
<field name="name">CRM - Claims Tree</field>
@@ -78,12 +78,9 @@
<field name="type">tree</field>
<field name="arch" type="xml">
<tree editable="top" string="Returned lines">
<field name="selected"/>
<field name="state"/>
<field name="substate_id"/>
<field name="name"/>
<field name="invoice_id"/>
<field name="product_id"/>
<field name="prodlot_id"/>
<field name="warning"/>
<field name="product_returned_quantity"/>
@@ -101,29 +98,30 @@
<field name="name"/>
<separator string="Returned good" colspan="4"/>
<group col="6" colspan="4">
<field name="invoice_id"/> <!-- domain="[('type', '=', 'out_invoice')]" -->
<field name="name"/>
<field name="invoice_line_id"/> <!-- domain="[('type', '=', 'out_invoice')]" -->
<field name="product_id"/>
<field name="prodlot_id"/>
<field name="product_returned_quantity"/>
<field name="unit_sale_price"/>
<field name="return_value"/>
<field name="return_value"/>
</group>
<!-- button name="%(action_get_empty_serial)d" string="Get possible values for empty serial" states="draft,confirmed" type="action" target="new"/ -->
<separator string="Problem" colspan="4"/>
<field name="claim_origine" nolabel="1" colspan="4"/>
<field name="claim_origine" nolabel="1" colspan="4"/>
<field name="claim_descr" nolabel="1" colspan="4"/>
<separator string="Warranty" colspan="4"/>
<button name="set_warranty" string="Calculate warranty state" type="object" colspan="4"/>
<button name="set_warranty" string="Calculate warranty state" type="object" colspan="4"/>
<field name="guarantee_limit"/>
<field name="warning"/>
<field name="warning"/>
<field name="warranty_return_partner"/>
<field name="warranty_type"/>
<separator string="State" colspan="4"/>
<separator string="State" colspan="4"/>
<group col="6" colspan="4">
<field name="state"/>
<field name="substate_id" widget='selection' />
<field name="last_state_change"/>
</group>
<field name="last_state_change"/>
</group>
</form>
</field>
</record>
@@ -139,8 +137,8 @@
<field name="picking_id"/>
<field name="related_picking_state"/>
<field name="related_picking_due_date"/>
<field name="related_picking_delivered_date"/>
<field name="name"/>
<field name="related_picking_delivered_date"/>
<field name="name"/>
</tree>
</field>
</record>
@@ -155,95 +153,97 @@
<field name="related_picking_state"/>
<field name="related_picking_due_date"/>
<field name="related_picking_delivered_date"/>
<field name="name"/>
<field name="name"/>
</form>
</field>
</record>
<!-- PRODUCT EXCHANGE -->
<!-- TREE -->
<record model="ir.ui.view" id="crm_product_exchange_tree_view">
<field name="name">CRM - Product exchange Tree</field>
<field name="model">product.exchange</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Product exchanges" editable="top" >
<field name="selected"/>
<field name="state"/>
<field name="exchange_send_date"/>
<field name="returned_product"/>
<field name="returned_product_serial"/>
<field name="replacement_product"/>
<field name="replacement_product_serial"/>
<field name="returned_value"/>
<field name="replacement_value"/>
<field name="name"/>
</tree>
</field>
</record>
<!-- <record model="ir.ui.view" id="crm_product_exchange_tree_view">-->
<!-- <field name="name">CRM - Product exchange Tree</field>-->
<!-- <field name="model">product.exchange</field>-->
<!-- <field name="type">tree</field>-->
<!-- <field name="arch" type="xml">-->
<!-- <tree string="Product exchanges" editable="top" >-->
<!-- <field name="selected"/>-->
<!-- <field name="state"/>-->
<!-- <field name="exchange_send_date"/>-->
<!-- <field name="returned_product"/> -->
<!-- <field name="returned_product_serial"/>-->
<!-- <field name="replacement_product"/>-->
<!-- <field name="replacement_product_serial"/>-->
<!-- <field name="returned_value"/>-->
<!-- <field name="replacement_value"/>-->
<!-- <field name="name"/> -->
<!-- </tree>-->
<!-- </field>-->
<!-- </record>-->
<!-- FORM -->
<record model="ir.ui.view" id="crm_product_exchange_form_view">
<field name="name">CRM - Product exchange Form</field>
<field name="model">product.exchange</field>
<field name="arch" type="xml">
<form string="Product exchange">
<field name="state"/>
<field name="exchange_send_date"/>
<separator string="Returned product" colspan="2"/>
<separator string="Replacement product" colspan="2"/>
<field name="returned_product"/>
<field name="replacement_product"/>
<field name="returned_product_serial"/>
<field name="replacement_product_serial"/>
<field name="returned_product_qty"/>
<field name="replacement_product_qty"/>
<field name="returned_unit_sale_price"/>
<field name="replacement_unit_sale_price"/>
<field name="returned_value"/>
<field name="replacement_value"/>
<separator string="Comment" colspan="2"/>
<field name="name" colspan="4" nolabel="1"/>
</form>
</field>
</record>
<!-- <record model="ir.ui.view" id="crm_product_exchange_form_view">-->
<!-- <field name="name">CRM - Product exchange Form</field>-->
<!-- <field name="model">product.exchange</field>-->
<!-- <field name="arch" type="xml">-->
<!-- <form string="Product exchange">-->
<!-- <field name="state"/>-->
<!-- <field name="exchange_send_date"/>-->
<!-- <separator string="Returned product" colspan="2"/>-->
<!-- <separator string="Replacement product" colspan="2"/>-->
<!-- <field name="returned_product"/> -->
<!-- <field name="replacement_product"/>-->
<!-- <field name="returned_product_serial"/>-->
<!-- <field name="replacement_product_serial"/> -->
<!-- <field name="returned_product_qty"/> -->
<!-- <field name="replacement_product_qty"/>-->
<!-- <field name="returned_unit_sale_price"/>-->
<!-- <field name="replacement_unit_sale_price"/>-->
<!-- <field name="returned_value"/>-->
<!-- <field name="replacement_value"/>-->
<!-- <separator string="Comment" colspan="2"/>-->
<!-- <field name="name" colspan="4" nolabel="1"/> -->
<!-- </form>-->
<!-- </field>-->
<!-- </record>-->
<!-- -->
<!-- CLAIM VIEWS -->
<record model="ir.ui.view" id="crm_claim_rma_form_view">
<field name="name">CRM - Claim product return Form</field>
<field name="model">crm.claim</field>
<field name="inherit_id" ref="crm_claim.crm_case_claims_form_view"/>
<field name="arch" type="xml">
<field name="arch" type="xml">
<xpath expr="/form/group/notebook/page[@string='Communication &amp; History']/field" position="after">
<field name="invoice_ids" colspan="4" nolabel="1" readonly="1"/>
<field name="picking_ids" colspan="4" nolabel="1" readonly="1"/>
</xpath>
<page string="Communication &amp; History" position="after">
<page string="Product return">
<field name="claim_line_ids" nolabel="1" colspan="4"/>
<field name="invoice_id" colspan="1" on_change="onchange_invoice_id(invoice_id, context)" domain="[('partner_id','=',partner_id)]" />
<field name="claim_line_ids" nolabel="1" colspan="4"/>
<group col="1" rowspan="3">
<separator string="Add lines" colspan="4"/>
<button name="%(action_create_return_serial)d" string="Mass return from serial/lot n°" states="draft,open" type="action" target="new"/>
<button name="%(action_create_return_inv)d" string="Mass return from invoice" states="draft,open" type="action" target="new"/>
<!-- <button name="(action_create_return_inv)d" string="Mass return from invoice" states="draft,open" type="action" target="new"/> -->
</group>
<group col="1" rowspan="3">
<separator string="Line selection" colspan="4"/>
<button name="select_all" string="Select all" states="draft,open" type="object"/>
<button name="unselect_all" string="Select none" states="draft,open" type="object"/>
</group>
<!-- <group col="1" rowspan="3"> -->
<!-- <separator string="Line selection" colspan="4"/> -->
<!-- <button name="select_all" string="Select all" states="draft,open" type="object"/> -->
<!-- <button name="unselect_all" string="Select none" states="draft,open" type="object"/> -->
<!-- </group> -->
<group col="2" rowspan="3">
<separator string="From selected lines" colspan="4"/>
<button name="%(action_picking_in_from_returned_lines)d" string="New picking IN" states="draft,open" type="action" target="new"/>
<button name="%(action_picking_out_from_returned_lines)d" string="New picking OUT" states="draft,open" type="action" target="new"/>
<button name="%(account.action_account_invoice_refund)d" type='action' string='New Refund' states='draft,open' icon="gtk-execute" context="{'active_ids': '1'}"/>
<!--<button name="%(action_exchange_from_returned_lines)d" string="New exchange" states="draft,open" type="action" target="new"/>-->
</group>
<button name="%(action_claim_picking_in)d" string="New picking IN" states="draft,open" type="action" target="new" context="{'warehouse_id': warehouse_id}"/>
<button name="%(action_claim_picking_out)d" string="New picking OUT" states="draft,open" type="action" target="new" context="{'warehouse_id': warehouse_id, 'customer_id': partner_id}"/>
<button name="%(action_claim_picking_loss)d" string="New Product Loss" states="draft,open" type="action" target="new" context="{'warehouse_id': warehouse_id}"/>
<button name="%(account.action_account_invoice_refund)d" type='action' string='New Refund' states='draft,open' icon="gtk-execute" context="{'invoice_ids': [invoice_id], 'claim_line_ids': claim_line_ids}"/>
<!--<button name="(action_exchange_from_returned_lines)d" string="New exchange" states="draft,open" type="action" target="new"/> -->
</group>
</page>
<!--
<page string="Product exchange">
<field name="product_exchange_ids" nolabel="1" colspan="4"/>
<button name="%(action_picking_out_from_exchange_lines)d" string="New picking OUT from exchange" states="draft,open" type="action" target="new"/>
<button name="(action_picking_out_from_exchange_lines)d" string="New picking OUT from exchange" states="draft,open" type="action" target="new"/>
</page>
page string="Aftersale outsourcing">
<button name="create_picking_out" string="New picking OUT from selected lines" states="draft,open" type="object"/>
@@ -271,8 +271,10 @@
<field name="inherit_id" ref="crm_claim.crm_case_claims_form_view"/>
<field name="arch" type="xml">
<field name="date_deadline" position="after">
<field name="sequence"/>
<field name="number"/>
<field name="claim_type"/>
<field name="case_id" />
<field name="warehouse_id" />
</field>
</field>
</record>
@@ -358,10 +360,10 @@
<field name="view_type">form</field>
<!-- field name="view_id" ref="crm.crm_case_categ_tree-view"/ -->
</record>
<!-- Menu -->
<!-- Menu -->
<menuitem name="Return lines" id="menu_crm_case_claims_claim_lines"
parent="base.menu_aftersale" action="act_crm_case_claim_lines" sequence="2"/>
<menuitem name="Returned line substates" id="menu_crm_case_claims_claim_line_substates"
parent="crm_claim.menu_config_claim" action="act_crm_claim_substates" sequence="2"/>
parent="crm_claim.menu_config_claim" action="act_crm_claim_substates" sequence="2"/>
</data>
</openerp>

View File

@@ -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 <http://www.gnu.org/licenses/>. #
#########################################################################
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()

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
crm_claim_rma for OpenERP
Copyright (C) 2011 Akretion Benoît Guillot <benoit.guillot@akretion.com>
The licence is in the file __openerp__.py
-->
<openerp>
<data>
<!-- INHERITED VIEW FOR THE OBJECT : res_company -->
<record id="crm_claim_rma.company_form" model="ir.ui.view">
<field name="name">crm_claim_rma.company_form</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form" />
<field eval="16" name="priority"/>
<field name="type">form</field>
<field name="arch" type="xml">
<data>
<field name="company_registry" position="after">
<separator string="Crm product return address" colspan="4"/>
<field name="crm_return_address_id"/>
</field>
</data>
</field>
</record>
</data>
</openerp>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" ?>
<openerp>
<data>
<data>
<!-- Sequences for crm.claim -->
<record id="seq_type_crm_claim" model="ir.sequence.type">
<field name="name">CRM claim</field>
@@ -14,52 +14,52 @@
<field name="padding">5</field>
</record>
<!-- STANDARD SUBSTATE FOR CLAIM RMA -->
<!-- STANDARD SUBSTATE FOR CLAIM RMA -->
<!-- TO TREATE -->
<record id="rma_to_treate_refund" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;To refund&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product has to be refunded&quot;&quot;&quot;" />
</record>
<record id="rma_to_treate_exchange" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;To exchange&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product has to be exchanged&quot;&quot;&quot;" />
</record>
<record id="rma_to_treate_repair" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;To repair&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product has to be repaired&quot;&quot;&quot;" />
</record>
<record id="rma_to_treate_send_supplier" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;To send back to supplier&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product has to be sent back to supplier&quot;&quot;&quot;" />
</record>
<record id="rma_to_treate_back_from_supplier" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Back from supplier, to send to customer&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product has to be sent back from supplier and is to be sent back to customer&quot;&quot;&quot;" />
</record>
<!-- TREATED -->
<record id="rma_treated_refund" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Refunded and stock&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product refunded and sent back to stock&quot;&quot;&quot;" />
</record>
<record id="rma_treated_refund_waste" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Refunded and waste&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product refunded and sent to waste&quot;&quot;&quot;" />
</record>
<record id="rma_treated_exchange" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Exchanged&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product exchanged&quot;&quot;&quot;" />
</record>
<record id="rma_treated_repair" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Repaired&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product repaired&quot;&quot;&quot;" />
</record>
<record id="rma_treated_sent_to_supplier" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Sent to supplier, pending&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product sent to supplier. Waiting for supplier response&quot;&quot;&quot;" />
</record>
<record id="rma_treated_repaired_by_supplier" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Repaired by supplier and sent back to customer&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product repaired by supplier and sent back to customer&quot;&quot;&quot;" />
</record>
</data>
<record id="rma_to_treate_refund" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;To refund&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product has to be refunded&quot;&quot;&quot;" />
</record>
<record id="rma_to_treate_exchange" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;To exchange&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product has to be exchanged&quot;&quot;&quot;" />
</record>
<record id="rma_to_treate_repair" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;To repair&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product has to be repaired&quot;&quot;&quot;" />
</record>
<record id="rma_to_treate_send_supplier" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;To send back to supplier&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product has to be sent back to supplier&quot;&quot;&quot;" />
</record>
<record id="rma_to_treate_back_from_supplier" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Back from supplier, to send to customer&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product has to be sent back from supplier and is to be sent back to customer&quot;&quot;&quot;" />
</record>
<!-- TREATED -->
<record id="rma_treated_refund" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Refunded and stock&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product refunded and sent back to stock&quot;&quot;&quot;" />
</record>
<record id="rma_treated_refund_waste" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Refunded and waste&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product refunded and sent to waste&quot;&quot;&quot;" />
</record>
<record id="rma_treated_exchange" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Exchanged&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product exchanged&quot;&quot;&quot;" />
</record>
<record id="rma_treated_repair" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Repaired&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product repaired&quot;&quot;&quot;" />
</record>
<record id="rma_treated_sent_to_supplier" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Sent to supplier, pending&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product sent to supplier. Waiting for supplier response&quot;&quot;&quot;" />
</record>
<record id="rma_treated_repaired_by_supplier" model="substate.substate">
<field name="name" eval="&quot;&quot;&quot;Repaired by supplier and sent back to customer&quot;&quot;&quot;"/>
<field name="substate_descr" eval="&quot;&quot;&quot;Returned product repaired by supplier and sent back to customer&quot;&quot;&quot;" />
</record>
</data>
</openerp>

View File

@@ -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",
1 id name model_id group_id perm_read perm_write perm_create perm_unlink
2 access_substate_user substate.substate.user substate.substate base.group_sale_salesman_all_leads True True True
3 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
4 access_substate_manager substate.substate.manager substate.substate base.group_sale_manager True True True True
5 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
6 access_substate_user substate.substate.user substate.substate base.group_sale_salesman True True True
7 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

View File

@@ -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'),
}

View File

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

View File

@@ -9,8 +9,8 @@
<data>
<!-- INHERITED VIEW FOR THE OBJECT : stock_picking -->
<record id="crm_claim_rma.picking_form" model="ir.ui.view">
<field name="name">crm_claim_rma.picking_form</field>
<record id="crm_claim_rma.picking_in_form" model="ir.ui.view">
<field name="name">crm_claim_rma.picking_in_form</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_in_form" />
<field eval="16" name="priority"/>
@@ -18,7 +18,39 @@
<field name="arch" type="xml">
<data>
<xpath expr="/form/notebook/page[@string='Additional Info']/field[@name='type']" position="after">
<field name="claim_id" attrs="{'invisible':[('type','!=','in')]}"/>
<field name="claim_id" />
</xpath>
</data>
</field>
</record>
<record id="crm_claim_rma.picking_out_form" model="ir.ui.view">
<field name="name">crm_claim_rma.picking_out_form</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_out_form" />
<field eval="16" name="priority"/>
<field name="type">form</field>
<field name="arch" type="xml">
<data>
<xpath expr="/form/notebook/page[@string='Additional info']/field[@name='type']" position="after">
<field name="claim_id" />
</xpath>
</data>
</field>
</record>
<record id="crm_claim_rma.warehouse_form" model="ir.ui.view">
<field name="name">crm_claim_rma.warehouse_form</field>
<field name="model">stock.warehouse</field>
<field name="inherit_id" ref="stock.view_warehouse" />
<field eval="16" name="priority"/>
<field name="type">form</field>
<field name="arch" type="xml">
<data>
<xpath expr="/form/field[@name='lot_output_id']" position="after">
<field name="lot_rma_id"/>
<field name="lot_carrier_loss_id"/>
<field name="lot_breakage_loss_id"/>
</xpath>
</data>
</field>

View File

@@ -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

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
#########################################################################
# #
# crm_claim_rma for OpenERP #
# Copyright (C) 2012 Akretion, #
# 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 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:

View File

@@ -0,0 +1,149 @@
# -*- 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 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:

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
crm_claim_rma for OpenERP
Copyright (C) 2011 Akretion Benoît GUILLOT <benoit.guillot@akretion.com>
The licence is in the file __openerp__.py
-->
<openerp>
<data>
<record id="view_claim_picking" model="ir.ui.view">
<field name="name">claim_picking</field>
<field name="model">claim_make_picking.wizard</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Select exchange lines to add in picking">
<separator string="Locations" colspan="4"/>
<field name="claim_line_source_location" nolabel="1" />
<field name="claim_line_dest_location" nolabel="1" />
<separator string="Select lines for picking" colspan="4"/>
<field name="claim_line_ids" nolabel="1" colspan="4"/>
<group col="4" colspan="2">
<button special="cancel" string="Cancel" name="action_cancel" type="object" icon='gtk-cancel'/>
<button name="action_create_picking" string="Create picking" icon='gtk-ok' type="object"/>
</group>
</form>
</field>
</record>
<record id="action_claim_picking_in" model="ir.actions.act_window">
<field name="name">action_claim_picking_in</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">claim_make_picking.wizard</field>
<field name="src_model">crm.claim</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context">{'picking_type': 'in'}</field>
</record>
<record id="action_claim_picking_out" model="ir.actions.act_window">
<field name="name">action_claim_picking_out</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">claim_make_picking.wizard</field>
<field name="src_model">crm.claim</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context">{'picking_type': 'out'}</field>
</record>
<record id="action_claim_picking_loss" model="ir.actions.act_window">
<field name="name">action_claim_picking_loss</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">claim_make_picking.wizard</field>
<field name="src_model">crm.claim</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context">{'picking_type': 'loss'}</field>
</record>
</data>
</openerp>

View File

@@ -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,

View File

@@ -60,8 +60,8 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Select return lines to create">
<separator string="Select return lines to create " colspan="4"/>
<field name="claim_line_ids" nolabel="1" colspan="4"/>
<separator string="Select return lines to create" colspan="4"/>
<field name="claim_line_ids" nolabel="1" colspan="4"/>
<group col="4" colspan="2">
<button special="cancel" string="Cancel" name="action_cancel" type="object" icon='gtk-cancel'/>
<button name="action_create_returns" string="Create selected returns" icon='gtk-ok' type="object"/>