[FIX] pep8, review

This commit is contained in:
Guewen Baconnier
2013-12-03 09:29:41 +01:00
parent 07a2e3c768
commit 05bc2a662f
6 changed files with 436 additions and 371 deletions

View File

@@ -27,41 +27,49 @@
Management of Return Merchandise Authorization (RMA) Management of Return Merchandise Authorization (RMA)
==================================================== ====================================================
This module aim to improve the Claims by adding a way to manage the product returns. It This module aims to improve the Claims by adding a way to manage the
allows you to create and manage picking from a claim. It also introduce a new object product returns. It allows you to create and manage picking from a
the claim lines to better handle that problematic. One Claim can have several lines that concern claim. It also introduces a new object: the claim lines to better
the return of differents products. It's for every of them that you'll be able to check the handle that problematic. One Claim can have several lines that
warranty (still running or not). concern the return of differents products. It's for every of them
that you'll be able to check the warranty (still running or not).
It mainly contain the following features: It mainly contains the following features:
* product returns (one by one, mass return by invoice) * product returns (one by one, mass return by invoice)
* warranty control & return address (based on invoice date and product form) * warranty control & return address (based on invoice date and product form)
* product picking in / out * product picking in / out
* product refund * product refund
* access to related customer data (orders, invoices, refunds, picking in/out) from a claim * access to related customer data (orders, invoices, refunds, picking
in/out) from a claim
Using this module make the logistic flow of return this way: Using this module makes the logistic flow of return this way:
* Returning product goes into Stock or Supplier location with a incoming shipment (depending * Returning product goes into Stock or Supplier location with a incoming
on the settings of the supplier info in the product form) shipment (depending on the settings of the supplier info in the
product form)
* You can make a delivery from the RMA to send a new product to the Customer * You can make a delivery from the RMA to send a new product to the Customer
""", """,
'author': 'Akretion, Camptocamp', 'author': 'Akretion, Camptocamp',
'website': 'http://www.akretion.com, http://www.camptocamp.com', 'website': 'http://www.akretion.com, http://www.camptocamp.com',
'depends': ['sale','stock','crm_claim','product_warranty'], 'depends': ['sale',
'data': [ 'stock',
'wizard/claim_make_picking_view.xml', 'crm_claim',
'crm_claim_rma_view.xml', 'product_warranty',
'security/ir.model.access.csv', ],
'account_invoice_view.xml', 'data': ['wizard/claim_make_picking_view.xml',
'stock_view.xml', 'crm_claim_rma_view.xml',
'crm_claim_rma_data.xml', 'security/ir.model.access.csv',
], 'account_invoice_view.xml',
'images': ['images/product_return.png', 'images/claim.png','images/return_line.png','images/exchange.png'], 'stock_view.xml',
'crm_claim_rma_data.xml',
],
'images': ['images/product_return.png',
'images/claim.png',
'images/return_line.png',
'images/exchange.png',
],
'installable': True, 'installable': True,
'active': False, 'auto_install': False,
} }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@@ -19,7 +19,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################## ##############################################################################
from openerp.osv import fields, orm, osv from openerp.osv import fields, orm
from tools.translate import _ from tools.translate import _
@@ -32,59 +32,60 @@ class account_invoice(orm.Model):
} }
def _refund_cleanup_lines(self, cr, uid, lines, context=None): def _refund_cleanup_lines(self, cr, uid, lines, context=None):
"""Override when from claim to update the quantity and link """ Override when from claim to update the quantity and link to the
to the claim line.""" claim line."""
if context is None: context = {}
new_lines = []
# check if is an invoice_line and we are from a claim
if context.get('claim_line_ids') and lines and lines[0]._name =='account.invoice.line' :
for claim_line_id in context.get('claim_line_ids'):
claim_info = self.pool.get('claim.line').read(cr, uid,
claim_line_id[1],
[
'invoice_line_id',
'product_returned_quantity',
'refund_line_id'],
context=context)
if not claim_info['refund_line_id']:
#For each lines replace quantity and add clain_line_id
inv_line_obj = self.pool.get('account.invoice.line')
inv_line = inv_line_obj.browse(cr, uid,
[claim_info['invoice_line_id'][0]],
context=context)[0]
clean_line = {}
for field in inv_line._all_columns.keys():
column_type = inv_line._all_columns[field].column._type
if column_type == 'many2one':
clean_line[field] = inv_line[field].id
elif column_type not in ['many2many','one2many']:
clean_line[field] = inv_line[field]
elif field == 'invoice_line_tax_id':
tax_list = []
for tax in inv_line[field]:
tax_list.append(tax.id)
clean_line[field] = [(6,0, tax_list)]
clean_line['quantity'] = claim_info['product_returned_quantity']
clean_line['claim_line_id'] = [claim_line_id[1]]
new_lines.append(clean_line)
if not new_lines:
# TODO use custom states to show button of this wizard or
# not instead of raise an error
raise osv.except_osv(_('Error !'),
_('A refund has already been created for this claim !'))
else:
return super(account_invoice, self)._refund_cleanup_lines(cr, uid, lines, context=None)
return map(lambda x: (0,0,x), new_lines)
def _prepare_refund(self, cr, uid, invoice, date=None, period_id=None,
description=None, journal_id=None, context=None):
if context is None: if context is None:
context={} context = {}
result = super(account_invoice, self)._prepare_refund(cr, uid, invoice, new_lines = []
date=date, period_id=period_id, description=description, inv_line_obj = self.pool.get('account.invoice.line')
claim_line_obj = self.pool.get('claim.line')
# check if is an invoice_line and we are from a claim
if not (context.get('claim_line_ids') and lines and
lines[0]._name =='account.invoice.line'):
return super(account_invoice, self)._refund_cleanup_lines(
cr, uid, lines, context=None)
for __, claim_line_id in context.get('claim_line_ids'):
line = claim_line_obj.browse(cr, uid, claim_line_id,
context=context)
if not line.refund_line_id:
# For each lines replace quantity and add claim_line_id
inv_line = inv_line_obj.browse(cr, uid,
line.invoice_line_id.id,
context=context)
clean_line = {}
for field_name, field in inv_line._all_columns.iteritems():
column_type = field.column._type
if column_type == 'many2one':
clean_line[field_name] = inv_line[field_name].id
elif column_type not in ('many2many', 'one2many'):
clean_line[field_name] = inv_line[field_name]
elif field_name == 'invoice_line_tax_id':
tax_list = []
for tax in inv_line[field_name]:
tax_list.append(tax.id)
clean_line[field_name] = [(6, 0, tax_list)]
clean_line['quantity'] = line['product_returned_quantity']
clean_line['claim_line_id'] = [claim_line_id]
new_lines.append(clean_line)
if not new_lines:
# TODO use custom states to show button of this wizard or
# not instead of raise an error
raise orm.except_orm(
_('Error !'),
_('A refund has already been created for this claim !'))
return [(0, 0, line) for line in new_lines]
def _prepare_refund(self, cr, uid, invoice, date=None, period_id=None,
description=None, journal_id=None, context=None):
if context is None:
context = {}
result = super(account_invoice, self)._prepare_refund(
cr, uid, invoice,
date=date, period_id=period_id, description=description,
journal_id=journal_id, context=context) journal_id=journal_id, context=context)
if context.get('claim_id'): if context.get('claim_id'):
result['claim_id'] = context.get('claim_id') result['claim_id'] = context['claim_id']
return result return result
@@ -97,10 +98,11 @@ class account_invoice_line(orm.Model):
if vals.get('claim_line_id'): if vals.get('claim_line_id'):
claim_line_id = vals['claim_line_id'] claim_line_id = vals['claim_line_id']
del vals['claim_line_id'] del vals['claim_line_id']
line_id = super(account_invoice_line, self).create(cr, uid, line_id = super(account_invoice_line, self).create(
vals, context=context) cr, uid, vals, context=context)
if claim_line_id: if claim_line_id:
claim_line_obj = self.pool.get('claim.line') claim_line_obj = self.pool.get('claim.line')
claim_line_obj.write(cr, uid, claim_line_id, claim_line_obj.write(cr, uid, claim_line_id,
{'refund_line_id': line_id}, context=context) {'refund_line_id': line_id},
context=context)
return line_id return line_id

View File

@@ -2,7 +2,7 @@
############################################################################## ##############################################################################
# #
# Copyright 2013 Camptocamp # Copyright 2013 Camptocamp
# Copyright 2009-2013 Akretion, # Copyright 2009-2013 Akretion,
# Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, Joel Grand-Guillaume # Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, Joel Grand-Guillaume
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
@@ -20,28 +20,24 @@
# #
############################################################################## ##############################################################################
from openerp.osv import fields, orm, osv import time
# from crm import crm from openerp.osv import fields, orm
from datetime import datetime from datetime import datetime
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
import time from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from tools.translate import _ from openerp.tools.translate import _
from tools import DEFAULT_SERVER_DATE_FORMAT
from tools.translate import _
class substate_substate(orm.Model): class substate_substate(orm.Model):
""" """ To precise a state (state=refused; substates= reason 1, 2,...) """
To precise a state (state=refused; substates= reason 1, 2,...)
"""
_name = "substate.substate" _name = "substate.substate"
_description = "substate that precise a given state" _description = "substate that precise a given state"
_columns = { _columns = {
'name': fields.char('Sub state', size=128, required=True), 'name': fields.char('Sub state', required=True),
'substate_descr' : fields.text('Description', 'substate_descr': fields.text(
help="To give more information about the sub state"), 'Description',
# ADD OBJECT TO FILTER help="To give more information about the sub state"),
} }
class claim_line(orm.Model): class claim_line(orm.Model):
@@ -50,18 +46,19 @@ class claim_line(orm.Model):
""" """
_name = "claim.line" _name = "claim.line"
_description = "List of product to return" _description = "List of product to return"
# Comment written in a claim.line to know about the warranty status # Comment written in a claim.line to know about the warranty status
WARRANT_COMMENT = { WARRANT_COMMENT = {
'valid': "Valid", 'valid': "Valid",
'expired': "Expired", 'expired': "Expired",
'not_define': "Not Defined"} 'not_define': "Not Defined"}
# Method to calculate total amount of the line : qty*UP # Method to calculate total amount of the line : qty*UP
def _line_total_amount(self, cr, uid, ids, field_name, arg, context=None): def _line_total_amount(self, cr, uid, ids, field_name, arg, context=None):
res = {} res = {}
for line in self.browse(cr,uid,ids): for line in self.browse(cr, uid, ids, context=context):
res[line.id] = line.unit_sale_price*line.product_returned_quantity res[line.id] = (line.unit_sale_price *
line.product_returned_quantity)
return res return res
def copy_data(self, cr, uid, id, default=None, context=None): def copy_data(self, cr, uid, id, default=None, context=None):
@@ -75,134 +72,158 @@ class claim_line(orm.Model):
std_default.update(default) std_default.update(default)
return super(claim_line, self).copy_data( return super(claim_line, self).copy_data(
cr, uid, id, default=std_default, context=context) cr, uid, id, default=std_default, context=context)
def get_warranty_return_partner(self, cr, uid, context=None): def get_warranty_return_partner(self, cr, uid, context=None):
seller = self.pool.get('product.supplierinfo') seller = self.pool.get('product.supplierinfo')
result = seller.get_warranty_return_partner(cr, uid, context=context) result = seller.get_warranty_return_partner(cr, uid, context=context)
return result return result
_columns = { _columns = {
'name': fields.char('Description', size=64,required=True), 'name': fields.char('Description', required=True),
'claim_origine': fields.selection([('none','Not specified'), 'claim_origine': fields.selection(
('legal','Legal retractation'), [('none', 'Not specified'),
('cancellation','Order cancellation'), ('legal', 'Legal retractation'),
('damaged','Damaged delivered product'), ('cancellation', 'Order cancellation'),
('error','Shipping error'), ('damaged', 'Damaged delivered product'),
('exchange','Exchange request'), ('error', 'Shipping error'),
('lost','Lost during transport'), ('exchange', 'Exchange request'),
('other','Other')], ('lost', 'Lost during transport'),
('other', 'Other')
],
'Claim Subject', 'Claim Subject',
required=True, required=True,
help="To describe the line product problem"), help="To describe the line product problem"),
'claim_descr' : fields.text('Claim description', 'claim_descr': fields.text(
help="More precise description of the problem"), 'Claim description',
'product_id': fields.many2one('product.product', 'Product', help="More precise description of the problem"),
'product_id': fields.many2one(
'product.product',
string='Product',
help="Returned product"), help="Returned product"),
'product_returned_quantity' : fields.float('Quantity', digits=(12,2), 'product_returned_quantity': fields.float(
'Quantity', digits=(12, 2),
help="Quantity of product returned"), help="Quantity of product returned"),
'unit_sale_price' : fields.float('Unit sale price', digits=(12,2), 'unit_sale_price' : fields.float(
help="Unit sale price of the product. Auto filed if retrun done by" 'Unit sale price', digits=(12, 2),
" invoice selection. BE CAREFUL AND CHECK the automatic value " help="Unit sale price of the product. Auto filled if retrun done "
"as don't take into account previous refounds, invoice " "by invoice selection. Be careful and check the automatic "
"value as don't take into account previous refunds, invoice "
"discount, can be for 0 if product for free,..."), "discount, can be for 0 if product for free,..."),
'return_value' : fields.function(_line_total_amount, method=True, 'return_value' : fields.function(
string='Total return', _line_total_amount, string='Total return', type='float',
type='float',
help="Quantity returned * Unit sold price",), help="Quantity returned * Unit sold price",),
'prodlot_id': fields.many2one('stock.production.lot', 'Serial/Lot n°', 'prodlot_id': fields.many2one(
'stock.production.lot',
string='Serial/Lot n°',
help="The serial/lot of the returned product"), help="The serial/lot of the returned product"),
'applicable_guarantee': fields.selection( 'applicable_guarantee': fields.selection(
[ [('us', 'Company'),
('us','Company'), ('supplier', 'Supplier'),
('supplier','Supplier'), ('brand', 'Brand manufacturer')],
('brand','Brand manufacturer')],
'Warranty type'), 'Warranty type'),
'guarantee_limit': fields.date('Warranty limit', 'guarantee_limit': fields.date(
'Warranty limit',
readonly=True, readonly=True,
help="The warranty limit is computed as: invoice date + warranty " help="The warranty limit is computed as: invoice date + warranty "
"defined on selected product."), "defined on selected product."),
'warning': fields.char('Warranty', size=64, 'warning': fields.char(
'Warranty',
readonly=True, readonly=True,
help="If warranty has expired"), help="If warranty has expired"),
"warranty_type": fields.selection(get_warranty_return_partner, "warranty_type": fields.selection(
get_warranty_return_partner,
'Warranty type', 'Warranty type',
readonly=True, readonly=True,
help="Who is in charge of the warranty return treatment toward the end customer. " help="Who is in charge of the warranty return treatment towards the end customer. "
"Company will use the current compagny delivery or default address and so on for " "Company will use the current company delivery or default address and so on for "
"supplier and brand manufacturer. Doesn't necessarly mean that the warranty to be " "supplier and brand manufacturer. Does not necessarily mean that the warranty to be "
"applied is the one of the return partner (ie: can be returned to the company and " "applied is the one of the return partner (ie: can be returned to the company and "
"be under the brand warranty"), "be under the brand warranty"),
"warranty_return_partner" : fields.many2one('res.partner', "warranty_return_partner" : fields.many2one(
'Warranty Address', 'res.partner',
string='Warranty Address',
help="Where the customer has to send back the product(s)"), help="Where the customer has to send back the product(s)"),
'claim_id': fields.many2one('crm.claim', 'Related claim', 'claim_id': fields.many2one(
'crm.claim', string='Related claim',
help="To link to the case.claim object"), help="To link to the case.claim object"),
'state' : fields.selection([('draft','Draft'), 'state' : fields.selection(
('refused','Refused'), [('draft', 'Draft'),
('confirmed','Confirmed, waiting for product'), ('refused', 'Refused'),
('in_to_control','Received, to control'), ('confirmed', 'Confirmed, waiting for product'),
('in_to_treate','Controlled, to treate'), ('in_to_control', 'Received, to control'),
('treated','Treated')], 'State'), ('in_to_treate', 'Controlled, to treate'),
'substate_id': fields.many2one('substate.substate', 'Sub state', ('treated', 'Treated')],
string='State'),
'substate_id': fields.many2one(
'substate.substate',
string='Sub state',
help="Select a sub state to precise the standard state. Example 1: " help="Select a sub state to precise the standard state. Example 1: "
"state = refused; substate could be warranty over, not in " "state = refused; substate could be warranty over, not in "
"warranty, no problem,... . Example 2: state = to treate; " "warranty, no problem,... . Example 2: state = to treate; "
"substate could be to refund, to exchange, to repair,..."), "substate could be to refund, to exchange, to repair,..."),
'last_state_change': fields.date('Last change', 'last_state_change': fields.date(
string='Last change',
help="To set the last state / substate change"), help="To set the last state / substate change"),
'invoice_line_id': fields.many2one('account.invoice.line', 'invoice_line_id': fields.many2one(
'Invoice Line', 'account.invoice.line',
string='Invoice Line',
help='The invoice line related to the returned product'), help='The invoice line related to the returned product'),
'refund_line_id': fields.many2one('account.invoice.line', 'refund_line_id': fields.many2one(
'Refund Line', 'account.invoice.line',
string='Refund Line',
help='The refund line related to the returned product'), help='The refund line related to the returned product'),
'move_in_id': fields.many2one('stock.move', 'move_in_id': fields.many2one(
'Move Line from picking in', 'stock.move',
string='Move Line from picking in',
help='The move line related to the returned product'), help='The move line related to the returned product'),
'move_out_id': fields.many2one('stock.move', 'move_out_id': fields.many2one(
'Move Line from picking out', 'stock.move',
string='Move Line from picking out',
help='The move line related to the returned product'), help='The move line related to the returned product'),
'location_dest_id': fields.many2one('stock.location', 'location_dest_id': fields.many2one(
'Return Stock Location', 'stock.location',
string='Return Stock Location',
help='The return stock location of the returned product'), help='The return stock location of the returned product'),
} }
_defaults = { _defaults = {
'state': lambda *a: 'draft', 'state': 'draft',
'name': lambda *a: 'none', 'name': 'none',
} }
# Method to calculate warranty limit # Method to calculate warranty limit
def set_warranty_limit(self, cr, uid, ids, claim_line, context=None): def set_warranty_limit(self, cr, uid, ids, claim_line, context=None):
date_invoice = claim_line.invoice_line_id.invoice_id.date_invoice date_invoice = claim_line.invoice_line_id.invoice_id.date_invoice
if date_invoice: if not date_invoice:
warning = _(self.WARRANT_COMMENT['not_define']) raise orm.except_orm(
date_inv_at_server = datetime.strptime(date_invoice, _('Error !'),
DEFAULT_SERVER_DATE_FORMAT) _('Cannot find any date for invoice. '
supplier = claim_line.product_id.seller_ids[0] 'Must be a validated invoice.'))
if claim_line.claim_id.claim_type == 'supplier': warning = _(self.WARRANT_COMMENT['not_define'])
waranty_duration = int(supplier.warranty_duration) date_inv_at_server = datetime.strptime(date_invoice,
else: DEFAULT_SERVER_DATE_FORMAT)
waranty_duration = int(claim_line.product_id.warranty) supplier = claim_line.product_id.seller_ids[0]
limit = (date_inv_at_server + if claim_line.claim_id.claim_type == 'supplier':
relativedelta(months=waranty_duration)).strftime(DEFAULT_SERVER_DATE_FORMAT) warranty_duration = int(supplier.warranty_duration)
# If waranty period was defined
if waranty_duration > 0:
if limit < claim_line.claim_id.date:
warning = _(self.WARRANT_COMMENT['expired'])
else:
warning = _(self.WARRANT_COMMENT['valid'])
self.write(cr,uid,ids,{
'guarantee_limit' : limit,
'warning' : warning,
})
else: else:
raise osv.except_osv(_('Error !'), warranty_duration = int(claim_line.product_id.warranty)
_('Cannot find any date for invoice ! Must be a validated invoice !')) limit = date_inv_at_server + relativedelta(months=warranty_duration)
# If waranty period was defined
if warranty_duration > 0:
claim_date = datetime.strptime(claim_line.claim_id.date,
DEFAULT_SERVER_DATE_FORMAT)
if limit < claim_date:
warning = _(self.WARRANT_COMMENT['expired'])
else:
warning = _(self.WARRANT_COMMENT['valid'])
self.write(cr, uid, ids,
{'guarantee_limit': limit.strftime(DEFAULT_SERVER_DATE_FORMAT),
'warning': warning},
context=context)
return True return True
def get_destination_location(self, cr, uid, product_id, def get_destination_location(self, cr, uid, product_id,
warehouse_id, context=None): warehouse_id, context=None):
"""Compute and return the destination location ID to take """Compute and return the destination location ID to take
for a return. Always take 'Supplier' one when return type different for a return. Always take 'Supplier' one when return type different
from company.""" from company."""
@@ -220,41 +241,44 @@ class claim_line(orm.Model):
return location_dest_id return location_dest_id
# Method to calculate warranty return address # Method to calculate warranty return address
def set_warranty_return_address(self, cr, uid, ids, def set_warranty_return_address(self, cr, uid, ids, claim_line, context=None):
claim_line, context=None):
"""Return the partner to be used as return destination and """Return the partner to be used as return destination and
the destination stock location of the line in case of return. the destination stock location of the line in case of return.
We can have various case here: We can have various case here:
- company or other: return to company partner or crm_return_address_id - company or other: return to company partner or crm_return_address_id
if specified if specified
- supplier: return to the supplier address""" - supplier: return to the supplier address
"""
return_address = None return_address = None
seller = claim_line.product_id.seller_info_id seller = claim_line.product_id.seller_info_id
claim_company = claim_line.claim_id.company_id claim_company = claim_line.claim_id.company_id
return_address = seller.warranty_return_address.id return_address = seller.warranty_return_address.id
return_type = seller.warranty_return_partner return_type = seller.warranty_return_partner
location_dest_id = self.get_destination_location(cr, uid, location_dest_id = self.get_destination_location(
claim_line.product_id.id, cr, uid, claim_line.product_id.id,
claim_line.claim_id.warehouse_id.id, claim_line.claim_id.warehouse_id.id,
context=context) context=context)
self.write(cr, uid, ids, self.write(cr, uid, ids,
{'warranty_return_partner': return_address, {'warranty_return_partner': return_address,
'warranty_type': return_type, 'warranty_type': return_type,
'location_dest_id': location_dest_id}) 'location_dest_id': location_dest_id},
context=context)
return True return True
# Method to calculate warranty limit and address
def set_warranty(self, cr, uid, ids, context=None): def set_warranty(self, cr, uid, ids, context=None):
""" Calculate warranty limit and address """
for claim_line in self.browse(cr, uid, ids, context=context): for claim_line in self.browse(cr, uid, ids, context=context):
if claim_line.product_id and claim_line.invoice_line_id: if not (claim_line.product_id and claim_line.invoice_line_id):
self.set_warranty_limit(cr, uid, ids, raise orm.except_orm(
claim_line, context=context) _('Error !'),
self.set_warranty_return_address(cr, uid, ids, _('Please set product and invoice.'))
claim_line, context=context) self.set_warranty_limit(cr, uid, ids,
else: claim_line, context=context)
raise osv.except_osv(_('Error !'), self.set_warranty_return_address(cr, uid, ids,
_('PLEASE SET PRODUCT & INVOICE!')) claim_line, context=context)
return True return True
#TODO add the option to split the claim_line in order to manage the same product separately #TODO add the option to split the claim_line in order to manage the same product separately
@@ -262,18 +286,22 @@ class crm_claim(orm.Model):
_inherit = 'crm.claim' _inherit = 'crm.claim'
def _get_sequence_number(self, cr, uid, context=None): def _get_sequence_number(self, cr, uid, context=None):
res = self.pool.get('ir.sequence').get(cr, uid, seq_obj = self.pool.get('ir.sequence')
'crm.claim.rma', context=context) or '/' res = seq_obj.get(cr, uid, 'crm.claim.rma', context=context) or '/'
return res return res
def _get_default_warehouse(self, cr, uid, context=None): def _get_default_warehouse(self, cr, uid, context=None):
company_id = self.pool.get('res.users').browse(cr, uid, uid, user_obj = self.pool.get('res.users')
context=context).company_id.id user = user_obj.browse(cr, uid, uid, context=context)
wh_ids = self.pool.get('stock.warehouse').search(cr, uid, company_id = user.company_id.id
[('company_id','=',company_id)], context=context) wh_obj = self.pool.get('stock.warehouse')
wh_ids = wh_obj.search(cr, uid,
[('company_id', '=', company_id)],
context=context)
if not wh_ids: if not wh_ids:
raise osv.except_osv(_('Error!'), raise orm.except_orm(
_('There is no warehouse for the current user\'s company!')) _('Error!'),
_('There is no warehouse for the current user\'s company.'))
return wh_ids[0] return wh_ids[0]
def name_get(self, cr, uid, ids, context=None): def name_get(self, cr, uid, ids, context=None):
@@ -283,9 +311,9 @@ class crm_claim(orm.Model):
return res return res
def create(self, cr, uid, vals, context=None): def create(self, cr, uid, vals, context=None):
if ('number' not in vals) or (vals.get('number')=='/'): if ('number' not in vals) or (vals.get('number') == '/'):
vals['number'] = self._get_sequence_number(cr, uid, context=context) vals['number'] = self._get_sequence_number(cr, uid, context=context)
new_id = super(crm_claim, self).create(cr, uid, vals, context) new_id = super(crm_claim, self).create(cr, uid, vals, context=context)
return new_id return new_id
def copy_data(self, cr, uid, id, default=None, context=None): def copy_data(self, cr, uid, id, default=None, context=None):
@@ -301,49 +329,55 @@ class crm_claim(orm.Model):
cr, uid, id, default=std_default, context=context) cr, uid, id, default=std_default, context=context)
_columns = { _columns = {
'number': fields.char('Number', readonly=True, 'number': fields.char(
'Number', readonly=True,
states={'draft': [('readonly', False)]}, states={'draft': [('readonly', False)]},
required=True, required=True,
select=True, select=True,
help="Company internal claim unique number"), help="Company internal claim unique number"),
'claim_type': fields.selection([('customer','Customer'), 'claim_type': fields.selection(
('supplier','Supplier'), [('customer', 'Customer'),
('other','Other')], ('supplier', 'Supplier'),
'Claim type', ('other', 'Other')],
string='Claim type',
required=True, required=True,
help="customer = from customer to company ; supplier = from " help="Customer: from customer to company.\n "
"company to supplier"), "Supplier: from company to supplier."),
'claim_line_ids' : fields.one2many('claim.line', 'claim_id', 'claim_line_ids': fields.one2many(
'Return lines'), 'claim.line', 'claim_id',
string='Return lines'),
'planned_revenue': fields.float('Expected revenue'), 'planned_revenue': fields.float('Expected revenue'),
'planned_cost': fields.float('Expected cost'), 'planned_cost': fields.float('Expected cost'),
'real_revenue': fields.float('Real revenue'), 'real_revenue': fields.float('Real revenue'),
'real_cost': fields.float('Real cost'), 'real_cost': fields.float('Real cost'),
'invoice_ids': fields.one2many('account.invoice', 'claim_id', 'Refunds'), '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', 'invoice_id': fields.many2one(
'account.invoice', string='Invoice',
help='Related original Cusotmer invoice'), help='Related original Cusotmer invoice'),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', 'warehouse_id': fields.many2one(
'stock.warehouse', string='Warehouse',
required=True), required=True),
} }
_defaults = { _defaults = {
'number': lambda self, cr, uid, context: '/', 'number': '/',
'claim_type': 'customer', 'claim_type': 'customer',
'warehouse_id': _get_default_warehouse, 'warehouse_id': _get_default_warehouse,
} }
_sql_constraints = [ _sql_constraints = [
('number_uniq', 'unique(number, company_id)', 'Number/Reference must be unique per Company!'), ('number_uniq', 'unique(number, company_id)',
'Number/Reference must be unique per Company!'),
] ]
def onchange_partner_address_id(self, cr, uid, ids, add, def onchange_partner_address_id(self, cr, uid, ids, add, email=False, context=None):
email=False, context=None): res = super(crm_claim, self).onchange_partner_address_id(
res = super(crm_claim, self).onchange_partner_address_id(cr, uid, ids, cr, uid, ids, add, email=email)
add, email=email)
if add: if add:
if not res['value']['email_from'] or not res['value']['partner_phone']: if not res['value']['email_from'] or not res['value']['partner_phone']:
address = self.pool.get('res.partner').browse(cr, uid, add) partner_obj = self.pool.get('res.partner')
address = partner_obj.browse(cr, uid, add, context=context)
for other_add in address.partner_id.address: for other_add in address.partner_id.address:
if other_add.email and not res['value']['email_from']: if other_add.email and not res['value']['email_from']:
res['value']['email_from'] = other_add.email res['value']['email_from'] = other_add.email
@@ -351,29 +385,30 @@ class crm_claim(orm.Model):
res['value']['partner_phone'] = other_add.phone res['value']['partner_phone'] = other_add.phone
return res return res
def onchange_invoice_id(self, cr, uid, ids, invoice_id, def onchange_invoice_id(self, cr, uid, ids, invoice_id, warehouse_id, context=None):
warehouse_id, context=None):
invoice_line_obj = self.pool.get('account.invoice.line') invoice_line_obj = self.pool.get('account.invoice.line')
claim_line_obj = self.pool.get('claim.line') claim_line_obj = self.pool.get('claim.line')
invoice_line_ids = invoice_line_obj.search(cr, uid, invoice_line_ids = invoice_line_obj.search(
[('invoice_id','=',invoice_id)]) cr, uid,
[('invoice_id', '=', invoice_id)],
context=context)
claim_lines = [] claim_lines = []
if not warehouse_id: if not warehouse_id:
warehouse_id = self._get_default_warehouse(cr, uid, context=context) warehouse_id = self._get_default_warehouse(cr, uid, context=context)
for invoice_line in invoice_line_obj.browse(cr,uid,invoice_line_ids): invoice_lines = invoice_line_obj.browse(cr, uid, invoice_line_ids,
location_dest_id = claim_line_obj.get_destination_location(cr, uid, context=context)
invoice_line.product_id.id, for invoice_line in invoice_lines:
warehouse_id, location_dest_id = claim_line_obj.get_destination_location(
context=context) cr, uid, invoice_line.product_id.id,
warehouse_id, context=context)
claim_lines.append({ claim_lines.append({
'name': invoice_line.name, 'name': invoice_line.name,
'claim_origine' : "none", 'claim_origine': "none",
'invoice_line_id': invoice_line.id, 'invoice_line_id': invoice_line.id,
'product_id' : invoice_line.product_id.id, 'product_id': invoice_line.product_id.id,
'product_returned_quantity' : invoice_line.quantity, 'product_returned_quantity': invoice_line.quantity,
'unit_sale_price' : invoice_line.price_unit, 'unit_sale_price': invoice_line.price_unit,
'location_dest_id': location_dest_id, 'location_dest_id': location_dest_id,
'state' : 'draft', 'state': 'draft',
}) })
return {'value' : {'claim_line_ids' : claim_lines}} return {'value': {'claim_line_ids': claim_lines}}

View File

@@ -19,7 +19,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################## ##############################################################################
from openerp.osv import fields, orm, osv from openerp.osv import fields, orm
class stock_picking(orm.Model): class stock_picking(orm.Model):
@@ -30,24 +30,24 @@ class stock_picking(orm.Model):
'claim_id': fields.many2one('crm.claim', 'Claim'), 'claim_id': fields.many2one('crm.claim', 'Claim'),
} }
def create(self, cr, user, vals, context=None): def create(self, cr, uid, vals, context=None):
if ('name' not in vals) or (vals.get('name')=='/'): if ('name' not in vals) or (vals.get('name') == '/'):
if vals['type'] != 'internal': sequence_obj = self.pool.get('ir.sequence')
seq_obj_name = 'stock.picking.' + vals['type'] if vals['type'] == 'internal':
seq_obj_name = self._name
else: else:
seq_obj_name = self._name seq_obj_name = 'stock.picking.' + vals['type']
vals['name'] = self.pool.get('ir.sequence').get(cr, user, vals['name'] = sequence_obj.get(cr, uid, seq_obj_name,
seq_obj_name, context=context)
context=context) new_id = super(stock_picking, self).create(cr, uid, vals,
new_id = super(stock_picking, self).create(cr, user, vals, context=context)
context=context)
return new_id return new_id
class stock_picking_out(orm.Model): class stock_picking_out(orm.Model):
_inherit = "stock.picking.out" _inherit = "stock.picking.out"
_columns = { _columns = {
'claim_id': fields.many2one('crm.claim', 'Claim'), 'claim_id': fields.many2one('crm.claim', 'Claim'),
} }
@@ -56,26 +56,27 @@ class stock_picking_out(orm.Model):
class stock_picking_out(orm.Model): class stock_picking_out(orm.Model):
_inherit = "stock.picking.in" _inherit = "stock.picking.in"
_columns = { _columns = {
'claim_id': fields.many2one('crm.claim', 'Claim'), 'claim_id': fields.many2one('crm.claim', 'Claim'),
} }
#This part concern the case of a wrong picking out. We need to create a new # This part concern the case of a wrong picking out. We need to create a new
#stock_move in a picking already open. # stock_move in a picking already open.
#In order to don't have to confirm the stock_move we override the create and # In order to don't have to confirm the stock_move we override the create and
#confirm it at the creation only for this case # confirm it at the creation only for this case
class stock_move(orm.Model): class stock_move(orm.Model):
_inherit = "stock.move" _inherit = "stock.move"
def create(self, cr, uid, vals, context=None): def create(self, cr, uid, vals, context=None):
move_id = super(stock_move, self).create(cr, uid, vals, context=context) move_id = super(stock_move, self).create(cr, uid, vals, context=context)
if vals.get('picking_id'): if vals.get('picking_id'):
picking = self.pool.get('stock.picking').browse(cr, uid, picking_obj = self.pool.get('stock.picking')
vals['picking_id'], context=context) picking = picking_obj.browse(cr, uid, vals['picking_id'],
context=context)
if picking.claim_id and picking.type == u'in': if picking.claim_id and picking.type == u'in':
move = self.write(cr, uid, move_id, {'state': 'confirmed'}, self.write(cr, uid, move_id, {'state': 'confirmed'},
context=context) context=context)
return move_id return move_id

View File

@@ -19,26 +19,27 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################## ##############################################################################
from openerp.osv import fields, orm from openerp.osv import orm
class account_invoice_refund(orm.TransientModel): class account_invoice_refund(orm.TransientModel):
_inherit = "account.invoice.refund" _inherit = "account.invoice.refund"
def compute_refund(self, cr, uid, ids, mode='refund', context=None): def compute_refund(self, cr, uid, ids, mode='refund', context=None):
if context is None: context={} if context is None:
context={}
if context.get('invoice_ids'): if context.get('invoice_ids'):
context['active_ids'] = context.get('invoice_ids') context['active_ids'] = context.get('invoice_ids')
return super(account_invoice_refund, self).compute_refund(cr, uid, ids, return super(account_invoice_refund, self).compute_refund(
mode='refund', context=context) cr, uid, ids, mode=mode, context=context)
def _get_description(self, cr, uid, context=None): def _get_description(self, cr, uid, context=None):
if context is None: context = {} if context is None:
context = {}
description = context.get('description') or '' description = context.get('description') or ''
return description return description
_defaults = { _defaults = {
'description': _get_description, 'description': _get_description,
} }

View File

@@ -2,7 +2,7 @@
############################################################################## ##############################################################################
# #
# Copyright 2013 Camptocamp # Copyright 2013 Camptocamp
# Copyright 2009-2013 Akretion, # Copyright 2009-2013 Akretion,
# Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, Joel Grand-Guillaume # Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau, Joel Grand-Guillaume
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
@@ -20,7 +20,7 @@
# #
############################################################################## ##############################################################################
from openerp.osv import fields, orm, osv from openerp.osv import fields, orm, osv
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp import netsvc from openerp import netsvc
from openerp.tools.translate import _ from openerp.tools.translate import _
import time import time
@@ -31,54 +31,62 @@ class claim_make_picking(orm.TransientModel):
_name = 'claim_make_picking.wizard' _name = 'claim_make_picking.wizard'
_description = 'Wizard to create pickings from claim lines' _description = 'Wizard to create pickings from claim lines'
_columns = { _columns = {
'claim_line_source_location': fields.many2one('stock.location', 'claim_line_source_location': fields.many2one(
'Source Location', 'stock.location',
string='Source Location',
help="Location where the returned products are from.", help="Location where the returned products are from.",
required=True), required=True),
'claim_line_dest_location': fields.many2one('stock.location', 'claim_line_dest_location': fields.many2one(
'Dest. Location', 'stock.location',
string='Dest. Location',
help="Location where the system will stock the returned products.", help="Location where the system will stock the returned products.",
required=True), required=True),
'claim_line_ids': fields.many2many('claim.line', 'claim_line_ids': fields.many2many(
'claim.line',
'claim_line_picking', 'claim_line_picking',
'claim_picking_id', 'claim_picking_id',
'claim_line_id', 'claim_line_id',
'Claim lines'), string='Claim lines'),
} }
def _get_claim_lines(self, cr, uid, context): def _get_claim_lines(self, cr, uid, context):
#TODO use custom states to show buttons of this wizard or not instead of raise an error #TODO use custom states to show buttons of this wizard or not instead of raise an error
if context is None: context = {} if context is None:
context = {}
line_obj = self.pool.get('claim.line') line_obj = self.pool.get('claim.line')
if context.get('picking_type') == 'out': if context.get('picking_type') == 'out':
move_field = 'move_out_id' move_field = 'move_out_id'
else: else:
move_field = 'move_in_id' move_field = 'move_in_id'
good_lines = [] good_lines = []
line_ids = line_obj.search(cr, uid, line_ids = line_obj.search(
[('claim_id', '=', context['active_id'])], context=context) cr, uid,
[('claim_id', '=', context['active_id'])],
context=context)
for line in line_obj.browse(cr, uid, line_ids, context=context): for line in line_obj.browse(cr, uid, line_ids, context=context):
if not line[move_field] or line[move_field].state == 'cancel': if not line[move_field] or line[move_field].state == 'cancel':
good_lines.append(line.id) good_lines.append(line.id)
if not good_lines: if not good_lines:
raise osv.except_osv(_('Error !'), raise orm.except_orm(
_('A picking has already been created for this claim !')) _('Error'),
_('A picking has already been created for this claim.'))
return good_lines return good_lines
# Get default source location # Get default source location
def _get_source_loc(self, cr, uid, context): def _get_source_loc(self, cr, uid, context):
loc_id = False loc_id = False
if context is None: context = {} if context is None:
context = {}
warehouse_obj = self.pool.get('stock.warehouse') warehouse_obj = self.pool.get('stock.warehouse')
warehouse_id = context.get('warehouse_id') warehouse_id = context.get('warehouse_id')
if context.get('picking_type') == 'out': if context.get('picking_type') == 'out':
loc_id = warehouse_obj.read(cr, uid, loc_id = warehouse_obj.read(
warehouse_id, cr, uid, warehouse_id,
['lot_stock_id'], ['lot_stock_id'],
context=context)['lot_stock_id'][0] context=context)['lot_stock_id'][0]
elif context.get('partner_id'): elif context.get('partner_id'):
loc_id = self.pool.get('res.partner').read(cr, uid, loc_id = self.pool.get('res.partner').read(
context['partner_id'], cr, uid, context['partner_id'],
['property_stock_customer'], ['property_stock_customer'],
context=context)['property_stock_customer'] context=context)['property_stock_customer']
return loc_id return loc_id
@@ -92,7 +100,7 @@ class claim_make_picking(orm.TransientModel):
for line in line_obj.browse(cr, uid, line_ids, context=context): for line in line_obj.browse(cr, uid, line_ids, context=context):
if line.location_dest_id.id not in line_location: if line.location_dest_id.id not in line_location:
line_location.append(line.location_dest_id.id) line_location.append(line.location_dest_id.id)
if len (line_location) == 1: if len(line_location) == 1:
loc_id = line_location[0] loc_id = line_location[0]
return loc_id return loc_id
@@ -103,33 +111,33 @@ class claim_make_picking(orm.TransientModel):
line_obj = self.pool.get('claim.line') line_obj = self.pool.get('claim.line')
line_partner = [] line_partner = []
for line in line_obj.browse(cr, uid, line_ids, context=context): for line in line_obj.browse(cr, uid, line_ids, context=context):
if (line.warranty_return_partner and line.warranty_return_partner.id if (line.warranty_return_partner and line.warranty_return_partner.id
not in line_partner): not in line_partner):
line_partner.append(line.warranty_return_partner.id) line_partner.append(line.warranty_return_partner.id)
if len (line_partner) == 1: if len(line_partner) == 1:
partner_id = line_partner[0] partner_id = line_partner[0]
return partner_id return partner_id
# Get default destination location # Get default destination location
def _get_dest_loc(self, cr, uid, context): def _get_dest_loc(self, cr, uid, context):
"""Return the location_id to use as destination. """Return the location_id to use as destination.
If it's an outoing shippment: take the customer stock property If it's an outoing shippment: take the customer stock property
If it's an incomming shippment take the location_dest_id common to all lines, or If it's an incomming shippment take the location_dest_id common to all lines, or
if different, return None.""" if different, return None."""
if context is None: context = {} if context is None:
warehouse_obj = self.pool.get('stock.warehouse') context = {}
warehouse_id = context.get('warehouse_id')
loc_id = False loc_id = False
if context.get('picking_type') == 'out' and context.get('partner_id'): if context.get('picking_type') == 'out' and context.get('partner_id'):
loc_id = self.pool.get('res.partner').read(cr, uid, loc_id = self.pool.get('res.partner').read(
context.get('partner_id'), cr, uid, context.get('partner_id'),
['property_stock_customer'], ['property_stock_customer'],
context=context)['property_stock_customer'][0] context=context)['property_stock_customer'][0]
elif context.get('picking_type') == 'in' and context.get('partner_id'): elif context.get('picking_type') == 'in' and context.get('partner_id'):
# Add the case of return to supplier ! # Add the case of return to supplier !
line_ids = self._get_claim_lines(cr, uid, context=context) line_ids = self._get_claim_lines(cr, uid, context=context)
loc_id = self._get_common_dest_location_from_line(cr, uid, loc_id = self._get_common_dest_location_from_line(cr, uid,
line_ids, context=context) line_ids,
context=context)
return loc_id return loc_id
_defaults = { _defaults = {
@@ -138,13 +146,14 @@ class claim_make_picking(orm.TransientModel):
'claim_line_ids': _get_claim_lines, 'claim_line_ids': _get_claim_lines,
} }
def action_cancel(self,cr,uid,ids,conect=None): def action_cancel(self, cr, uid, ids, context=None):
return {'type': 'ir.actions.act_window_close',} return {'type': 'ir.actions.act_window_close'}
# If "Create" button pressed # If "Create" button pressed
def action_create_picking(self, cr, uid, ids, context=None): def action_create_picking(self, cr, uid, ids, context=None):
picking_obj = self.pool.get('stock.picking') picking_obj = self.pool.get('stock.picking')
if context is None: context = {} if context is None:
context = {}
view_obj = self.pool.get('ir.ui.view') view_obj = self.pool.get('ir.ui.view')
name = 'RMA picking out' name = 'RMA picking out'
if context.get('picking_type') == 'out': if context.get('picking_type') == 'out':
@@ -161,87 +170,96 @@ class claim_make_picking(orm.TransientModel):
if context.get('picking_type'): if context.get('picking_type'):
note = 'RMA picking ' + str(context.get('picking_type')) note = 'RMA picking ' + str(context.get('picking_type'))
name = note name = note
view_id = view_obj.search(cr, uid, [ view_id = view_obj.search(cr, uid,
('xml_id', '=', view_xml_id), [('xml_id', '=', view_xml_id),
('model', '=', 'stock.picking'), ('model', '=', 'stock.picking'),
('type', '=', 'form'), ('type', '=', 'form'),
('name', '=', view_name) ('name', '=', view_name)
], context=context)[0] ],
context=context)[0]
wizard = self.browse(cr, uid, ids[0], context=context) wizard = self.browse(cr, uid, ids[0], context=context)
claim = self.pool.get('crm.claim').browse(cr, uid, claim = self.pool.get('crm.claim').browse(cr, uid,
context['active_id'], context=context) context['active_id'],
context=context)
partner_id = claim.partner_id.id partner_id = claim.partner_id.id
line_ids = [x.id for x in wizard.claim_line_ids] line_ids = [x.id for x in wizard.claim_line_ids]
# In case of product return, we don't allow one picking for various # In case of product return, we don't allow one picking for various
# product if location are different # product if location are different
# or if partner address is different # or if partner address is different
if context.get('product_return'): if context.get('product_return'):
common_dest_loc_id = self._get_common_dest_location_from_line(cr, uid, common_dest_loc_id = self._get_common_dest_location_from_line(
line_ids, context=context) cr, uid, line_ids, context=context)
if not common_dest_loc_id: if not common_dest_loc_id:
raise osv.except_osv(_('Error !'), raise orm.except_orm(
_('A product return cannot be created for various destination location, please ' _('Error !'),
'chose line with a same destination location.')) _('A product return cannot be created for various '
common_dest_partner_id = self._get_common_partner_from_line(cr, uid, 'destination locations, please choose line with a '
line_ids, context=context) 'same destination location.'))
common_dest_partner_id = self._get_common_partner_from_line(
cr, uid, line_ids, context=context)
if not common_dest_partner_id: if not common_dest_partner_id:
raise osv.except_osv(_('Error !'), raise orm.except_orm(
_('A product return cannot be created for various destination address, please ' _('Error !'),
'chose line with a same address.')) _('A product return cannot be created for various '
else: 'destination addresses, please choose line with a '
partner_id = common_dest_partner_id 'same address.'))
partner_id = common_dest_partner_id
# create picking # create picking
picking_id = picking_obj.create(cr, uid, { picking_id = picking_obj.create(
'origin': claim.number, cr, uid,
'type': p_type, {'origin': claim.number,
'move_type': 'one', # direct 'type': p_type,
'state': 'draft', 'move_type': 'one', # direct
'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT), 'state': 'draft',
'partner_id': partner_id, 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'invoice_state': "none", 'partner_id': partner_id,
'company_id': claim.company_id.id, 'invoice_state': "none",
'location_id': wizard.claim_line_source_location.id, 'company_id': claim.company_id.id,
'location_dest_id': wizard.claim_line_dest_location.id, 'location_id': wizard.claim_line_source_location.id,
'note' : note, 'location_dest_id': wizard.claim_line_dest_location.id,
'claim_id': claim.id, 'note': note,
}) 'claim_id': claim.id,
},
context=context)
# Create picking lines # Create picking lines
for wizard_claim_line in wizard.claim_line_ids: for wizard_claim_line in wizard.claim_line_ids:
move_id = self.pool.get('stock.move').create(cr, uid, { move_obj = self.pool.get('stock.move')
'name' : wizard_claim_line.product_id.name_template, # Motif : crm id ? stock_picking_id ? move_id = move_obj.create(
'priority': '0', cr, uid,
#'create_date': {'name': wizard_claim_line.product_id.name_template,
'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT), 'priority': '0',
'date_expected': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT), 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'product_id': wizard_claim_line.product_id.id, 'date_expected': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'product_qty': wizard_claim_line.product_returned_quantity, 'product_id': wizard_claim_line.product_id.id,
'product_uom': wizard_claim_line.product_id.uom_id.id, 'product_qty': wizard_claim_line.product_returned_quantity,
'partner_id': partner_id, 'product_uom': wizard_claim_line.product_id.uom_id.id,
'prodlot_id': wizard_claim_line.prodlot_id.id, 'partner_id': partner_id,
# 'tracking_id': 'prodlot_id': wizard_claim_line.prodlot_id.id,
'picking_id': picking_id, 'picking_id': picking_id,
'state': 'draft', 'state': 'draft',
'price_unit': wizard_claim_line.unit_sale_price, '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,
'company_id': claim.company_id.id, 'location_id': wizard.claim_line_source_location.id,
'location_id': wizard.claim_line_source_location.id, 'location_dest_id': wizard.claim_line_dest_location.id,
'location_dest_id': wizard.claim_line_dest_location.id, 'note': note,
'note': note, },
}) context=context)
self.pool.get('claim.line').write(cr, uid, self.pool.get('claim.line').write(
wizard_claim_line.id, {write_field: move_id}, context=context) cr, uid, wizard_claim_line.id,
{write_field: move_id}, context=context)
wf_service = netsvc.LocalService("workflow") wf_service = netsvc.LocalService("workflow")
if picking_id: if picking_id:
wf_service.trg_validate(uid, 'stock.picking', wf_service.trg_validate(uid, 'stock.picking',
picking_id,'button_confirm', cr) picking_id, 'button_confirm', cr)
picking_obj.action_assign(cr, uid, [picking_id]) picking_obj.action_assign(cr, uid, [picking_id])
domain = "[('type','=','%s'),('partner_id','=',%s)]"%(p_type, partner_id) domain = ("[('type', '=', '%s'), ('partner_id', '=', %s)]" %
(p_type, partner_id))
return { return {
'name': '%s' % name, 'name': '%s' % name,
'view_type': 'form', 'view_type': 'form',
'view_mode': 'form', 'view_mode': 'form',
'view_id': view_id, 'view_id': view_id,
'domain' : domain, 'domain': domain,
'res_model': 'stock.picking', 'res_model': 'stock.picking',
'res_id': picking_id, 'res_id': picking_id,
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',