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