Packing exception: allow to duplicate cancelled moves

This commit is contained in:
Bertrand Chenal
2009-02-03 00:06:50 +01:00
parent 1be0a286f7
commit be8b69a4e2
2 changed files with 219 additions and 33 deletions
+171 -28
View File
@@ -7,7 +7,7 @@ from decimal import Decimal
import datetime
from trytond.netsvc import LocalService
from trytond.report import CompanyReport
from trytond.wizard import Wizard
from trytond.wizard import Wizard, WizardOSV
from trytond.sql_db import table_handler
_STATES = {
@@ -815,6 +815,9 @@ class PurchaseLine(OSV):
readonly=True, select=1)
moves_ignored = fields.Many2Many('stock.move', 'purchase_line_moves_ignored_rel',
'purchase_line', 'move', 'Moves Ignored', readonly=True)
moves_duplicated = fields.Many2Many('stock.move',
'purchase_line_moves_duplicated_rel', 'purchase_line', 'move',
'Moves Duplicated', readonly=True)
move_done = fields.Function('get_move_done', type='boolean',
string='Moves Done')
move_exception = fields.Function('get_move_exception', type='boolean',
@@ -860,11 +863,12 @@ class PurchaseLine(OSV):
if line.product.type == 'service':
res[line.id] = True
continue
ignored_ids = [x.id for x in line.moves_ignored]
skip_ids = set(x.id for x in line.moves_ignored)
skip_ids.update(x.id for x in line.moves_duplicated)
quantity = line.quantity
for move in line.moves:
if move.state != 'done' \
and move.id not in ignored_ids:
and move.id not in skip_ids:
val = False
break
quantity -= uom_obj.compute_qty(cursor, user, move.uom,
@@ -879,10 +883,11 @@ class PurchaseLine(OSV):
res = {}
for line in self.browse(cursor, user, ids, context=context):
val = False
ignored_ids = [x.id for x in line.moves_ignored]
skip_ids = set(x.id for x in line.moves_ignored)
skip_ids.update(x.id for x in line.moves_duplicated)
for move in line.moves:
if move.state == 'cancel' \
and move.id not in ignored_ids:
and move.id not in skip_ids:
val = True
break
res[line.id] = val
@@ -1105,10 +1110,12 @@ class PurchaseLine(OSV):
return
if line.product.type == 'service':
return
skip_ids = set(x.id for x in line.moves_duplicated)
quantity = line.quantity
for move in line.moves:
quantity -= uom_obj.compute_qty(cursor, user, move.uom,
move.quantity, line.unit, context=context)
if move.id not in skip_ids:
quantity -= uom_obj.compute_qty(cursor, user, move.uom,
move.quantity, line.unit, context=context)
if quantity <= 0.0:
return
if not line.purchase.party.supplier_location:
@@ -1393,6 +1400,11 @@ class PackingIn(OSV):
self.incoming_moves.add_remove + ", " \
"('supplier', '=', supplier)]"
self._error_messages.update({
'reset_move': 'You cannot reset to draft a move generated '\
'by a purchase.',
})
def write(self, cursor, user, ids, vals, context=None):
workflow_service = LocalService('workflow')
purchase_line_obj = self.pool.get('purchase.line')
@@ -1422,6 +1434,15 @@ class PackingIn(OSV):
purchase_id, 'packing_update', cursor, context=context)
return res
def button_draft(self, cursor, user, ids, context=None):
for packing in self.browse(cursor, user, ids, context=context):
for move in packing.incoming_moves:
if move.state == 'cancel' and move.purchase_line:
self.raise_user_error(cursor, 'reset_move')
return super(PackingIn, self).button_draft(
cursor, user, ids, context=context)
PackingIn()
@@ -1466,6 +1487,10 @@ class Move(OSV):
relation='party.party', string='Supplier',
fnct_search='search_supplier', select=1)
exception_state = fields.Function('get_exception_state', type='selection',
selection=[('ignored', 'Ignored'), ('duplicated', 'Duplicated')],
string='Exception State')
def get_purchase(self, cursor, user, ids, name, arg, context=None):
purchase_obj = self.pool.get('purchase.purchase')
@@ -1487,6 +1512,17 @@ class Move(OSV):
res[i] = False
return res
def get_exception_state(self, cursor, user, ids, name, arg, context=None):
res = {}.fromkeys(ids, False)
for move in self.browse(cursor, user, ids, context=context):
if not move.purchase_line:
continue
if move.id in (x.id for x in move.purchase_line.moves_duplicated):
res[move.id] = 'duplicated'
if move.id in (x.id for x in move.purchase_line.moves_ignored):
res[move.id] = 'ignored'
return res
def search_purchase(self, cursor, user, name, args, context=None):
args2 = []
i = 0
@@ -1606,6 +1642,33 @@ class Move(OSV):
Move()
class Invoice(OSV):
_name = 'account.invoice'
def __init__(self):
super(Invoice, self).__init__()
self._error_messages.update({
'delete_purchase_invoice': 'You can not delete invoices ' \
'that comes from a purchase!',
})
def delete(self, cursor, user, ids, context=None):
if not ids:
return True
if isinstance(ids, (int, long)):
ids = [ids]
cursor.execute('SELECT id FROM purchase_invoices_rel ' \
'WHERE invoice IN (' + ','.join(['%s' for x in ids]) + ')',
ids)
if cursor.rowcount:
self.raise_user_error(cursor, 'delete_purchase_invoice',
context=context)
return super(Invoice, self).delete(cursor, user, ids,
context=context)
Invoice()
class OpenSupplier(Wizard):
'Open Suppliers'
_name = 'purchase.open_supplier'
@@ -1653,28 +1716,108 @@ class OpenSupplier(Wizard):
OpenSupplier()
class Invoice(OSV):
_name = 'account.invoice'
class HandlePackingExceptionAsk(WizardOSV):
'Packing Exception Ask'
_name = 'purchase.handle.packing.exception.ask'
_description = __doc__
def __init__(self):
super(Invoice, self).__init__()
self._error_messages.update({
'delete_purchase_invoice': 'You can not delete invoices ' \
'that comes from a purchase!',
})
duplicate_moves = fields.Many2Many(
'stock.move', None, None, None, 'Duplicate Moves',
domain="[('id', 'in', domain_moves)]", depends=['domain_moves'])
domain_moves = fields.Many2Many(
'stock.move', None, None, None, 'Domain Moves')
def delete(self, cursor, user, ids, context=None):
if not ids:
return True
if isinstance(ids, (int, long)):
ids = [ids]
cursor.execute('SELECT id FROM purchase_invoices_rel ' \
'WHERE invoice IN (' + ','.join(['%s' for x in ids]) + ')',
ids)
if cursor.rowcount:
self.raise_user_error(cursor, 'delete_purchase_invoice',
context=context)
return super(Invoice, self).delete(cursor, user, ids,
def default_duplicate_moves(self, cursor, user, data, context=None):
return self.default_domain_moves(cursor, user, data, context=context)
def default_domain_moves(self, cursor, user, data, context=None):
purchase_line_obj = self.pool.get('purchase.line')
line_ids = purchase_line_obj.search(
cursor, user, [('purchase', '=', data['active_id'])],
context=context)
lines = purchase_line_obj.browse(cursor, user, line_ids, context=context)
domain_moves = []
for line in lines:
skip_ids = set(x.id for x in line.moves_ignored)
skip_ids.update(x.id for x in line.moves_duplicated)
for move in line.moves:
if move.state == 'cancel' and move.id not in skip_ids:
domain_moves.append(move.id)
return domain_moves
HandlePackingExceptionAsk()
class HandlePackingException(Wizard):
'Handle Packing Exception'
_name = 'purchase.handle.packing.exception'
states = {
'init': {
'actions': [],
'result': {
'type': 'form',
'object': 'purchase.handle.packing.exception.ask',
'state': [
('end', 'Cancel', 'tryton-cancel'),
('ok', 'Ok', 'tryton-ok', True),
],
},
},
'ok': {
'result': {
'type': 'action',
'action': '_handle_moves',
'state': 'end',
},
},
}
def _handle_moves(self, cursor, user, data, context=None):
workflow_service = LocalService('workflow')
purchase_line_obj = self.pool.get('purchase.line')
move_obj = self.pool.get('stock.move')
to_duplicate = data['form']['duplicate_moves'][0][1]
domain_moves = data['form']['domain_moves'][0][1]
line_ids = purchase_line_obj.search(
cursor, user, [('purchase', '=', data['id'])],
context=context)
lines = purchase_line_obj.browse(cursor, user, line_ids, context=context)
duplicate_all = []
for line in lines:
moves_ignored = []
moves_duplicated = []
skip_ids = set(x.id for x in line.moves_ignored)
skip_ids.update(x.id for x in line.moves_duplicated)
for move in line.moves:
if move.id not in domain_moves or move.id in skip_ids:
continue
if move.id in to_duplicate:
moves_duplicated.append(move.id)
else:
moves_ignored.append(move.id)
duplicate_all.extend(moves_duplicated)
purchase_line_obj.write(
cursor, user, line.id,
{'moves_ignored': [('add', moves_ignored)],
'moves_duplicated': [('add', moves_duplicated)]},
context=context)
Invoice()
default = {
'state': 'draft',
'packing_in': False,
'packing_out': False,
'packing_in_return': False,
'packing_out_return': False,
'packing_internal': False,
}
move_obj.copy(
cursor, user, duplicate_all, default=default, context=context)
workflow_service.trg_validate(user, 'purchase.purchase', data['id'],
'packing_ok', cursor, context=context)
HandlePackingException()
+48 -5
View File
@@ -11,6 +11,12 @@ this repository contains the full copyright notices and license terms. -->
<field name="groups" eval="[('add', ref('group_purchase'))]"/>
</record>
<record model="ir.action.wizard" id="wizard_packing_handle_exception">
<field name="name">Handle Packing Exception</field>
<field name="wiz_name">purchase.handle.packing.exception</field>
<field name="model">purchase.purchase</field>
</record>
<record model="ir.ui.view" id="purchase_view_form">
<field name="model">purchase.purchase</field>
<field name="type">form</field>
@@ -79,9 +85,11 @@ this repository contains the full copyright notices and license terms. -->
<button name="invoice_ok" string="Ignore Invoice Exception"
states="{'invisible': '''invoice_state != 'exception' or state == 'cancel' ''', 'readonly': '''%(group_purchase)d not in groups'''}"
icon="tryton-go-next"/>
<button name="packing_ok" string="Ignore Packing Exception"
states="{'invisible': '''packing_state != 'exception' or state == 'cancel' ''', 'readonly': '''%(group_purchase)d not in groups'''}"
icon="tryton-go-next"/>
<button name="%(wizard_packing_handle_exception)d"
string="Handle Packing Exception"
type="action"
states="{'invisible': '''packing_state != 'exception' or state == 'cancel' ''', 'readonly': '''%(group_purchase)d not in groups'''}"
icon="tryton-go-next"/>
<button name="confirm" string="Confirm"
states="{'invisible': '''state != 'quotation' ''', 'readonly': '''%(group_purchase)d not in groups'''}"
icon="tryton-ok"/>
@@ -100,7 +108,18 @@ this repository contains the full copyright notices and license terms. -->
<field name="invoices" colspan="4" widget="one2many"/>
</page>
<page string="Packings" id="packings">
<field name="moves" colspan="4" widget="one2many"/>
<field name="moves" colspan="4" widget="one2many">
<tree string="Moves">
<field name="product"/>
<field name="from_location"/>
<field name="to_location"/>
<field name="quantity"/>
<field name="uom"/>
<field name="state"/>
<field name="exception_state"/>
<field name="unit_digits" tree_invisible="1"/>
</tree>
</field>
<field name="packings" colspan="4" widget="one2many"/>
</page>
</notebook>
@@ -134,6 +153,30 @@ this repository contains the full copyright notices and license terms. -->
</field>
</record>
<record model="ir.ui.view" id="handle_packing_exception_view_form">
<field name="model">purchase.handle.packing.exception.ask</field>
<field name="type">form</field>
<field name="arch" type="xml">
<![CDATA[
<form string="Handle packing Exception" col="2">
<image name="tryton-dialog-information"/>
<group col="1" colspan="1" id="moves">
<separator string="Choose move to duplicate"
id="choose"/>
<field name="duplicate_moves">
<tree string="Duplicate Moves" fill="1">
<field name="product"/>
<field name="quantity"/>
<field name="uom"/>
<field name="unit_digits" tree_invisible="1"/>
</tree>
</field>
</group>
</form>
]]>
</field>
</record>
<record model="ir.action.act_window" id="act_purchase_form">
<field name="name">Purchases</field>
<field name="res_model">purchase.purchase</field>
@@ -321,7 +364,7 @@ this repository contains the full copyright notices and license terms. -->
<field name="name">Waiting Packing</field>
<field name="workflow" ref="purchase_workflow"/>
<field name="kind">function</field>
<field name="action">write({'packing_state': 'waiting'})&#10;ignore_packing_exception()&#10;create_move()</field>
<field name="action">write({'packing_state': 'waiting'})&#10;create_move()</field>
</record>
<record model="workflow.activity" id="purchase_activity_packing_exception">
<field name="name">Packing Exception</field>