Adding exception state on the purchase requests

issue5107
review16811002
This commit is contained in:
Nicolas Évrard
2015-11-17 17:30:42 -03:00
parent 318d7bb912
commit 95ec33db65
8 changed files with 200 additions and 4 deletions
+2
View File
@@ -1,3 +1,5 @@
* Adding exception state on the purchase requests
Version 3.8.0 - 2015-11-02
* Bug fixes (see mercurial logs for details)
* Generate purchase requests even if rounding set the quantity to 0
+4
View File
@@ -7,6 +7,7 @@ from .product import *
from .purchase_request import *
from .shipment import *
from .location import *
from .purchase import *
def register():
@@ -16,12 +17,15 @@ def register():
PurchaseRequest,
CreatePurchaseRequestStart,
CreatePurchaseAskParty,
HandlePurchaseCancellationExceptionStart,
ShipmentInternal,
CreateShipmentInternalStart,
Location,
Purchase,
module='stock_supply', type_='model')
Pool.register(
CreatePurchaseRequest,
CreatePurchase,
CreateShipmentInternal,
HandlePurchaseCancellationException,
module='stock_supply', type_='wizard')
+38
View File
@@ -0,0 +1,38 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.tools import grouped_slice
from trytond.pool import Pool, PoolMeta
class Purchase:
__name__ = 'purchase.purchase'
__metaclass__ = PoolMeta
@classmethod
def __setup__(cls):
super(Purchase, cls).__setup__()
cls._error_messages.update({
'delete_purchase_request': ('You can not delete the purchase'
' "%(purchase)s" because it is linked to at least one'
' purchase request."'),
})
@classmethod
def delete(cls, purchases):
pool = Pool()
PurchaseRequest = pool.get('purchase.request')
purchase_lines = [pl.id
for purchase in purchases for pl in purchase.lines]
for sub_lines in grouped_slice(purchase_lines):
requests = PurchaseRequest.search([
('purchase_line', 'in', list(sub_lines)),
])
if requests:
purchase = requests[0].purchase
cls.raise_user_error('delete_purchase_request', {
'purchase': purchase.rec_name,
})
super(Purchase, cls).delete(purchases)
+69 -3
View File
@@ -19,7 +19,10 @@ from trytond.tools import grouped_slice
__all__ = ['PurchaseRequest',
'CreatePurchaseRequestStart', 'CreatePurchaseRequest',
'CreatePurchaseAskParty', 'CreatePurchase']
'CreatePurchaseAskParty', 'CreatePurchase',
'HandlePurchaseCancellationException',
'HandlePurchaseCancellationExceptionStart',
]
STATES = {
'readonly': Eval('state') != 'draft',
@@ -70,11 +73,13 @@ class PurchaseRequest(ModelSQL, ModelView):
])
origin = fields.Reference('Origin', selection='get_origin', readonly=True,
required=True)
exception_ignored = fields.Boolean('Ignored Exception')
state = fields.Function(fields.Selection([
('purchased', 'Purchased'),
('done', 'Done'),
('draft', 'Draft'),
('cancel', 'Cancel'),
('exception', 'Exception'),
], 'State'), 'get_state', searcher='search_state')
@classmethod
@@ -87,6 +92,11 @@ class PurchaseRequest(ModelSQL, ModelView):
'delete_purchase_line': ('You can not delete purchased '
'request.'),
})
cls._buttons.update({
'handle_purchase_cancellation_exception': {
'invisible': Eval('state') != 'exception',
},
})
@classmethod
def __register__(cls, module_name):
@@ -124,6 +134,10 @@ class PurchaseRequest(ModelSQL, ModelView):
def default_company():
return Transaction().context.get('company')
@staticmethod
def default_exception_ignored():
return False
def get_purchase(self, name):
if self.purchase_line:
return self.purchase_line.purchase.id
@@ -134,7 +148,10 @@ class PurchaseRequest(ModelSQL, ModelView):
def get_state(self, name):
if self.purchase_line:
if self.purchase_line.purchase.state == 'cancel':
if (self.purchase_line.purchase.state == 'cancel'
and not self.exception_ignored):
return 'exception'
elif self.purchase_line.purchase.state == 'cancel':
return 'cancel'
elif self.purchase_line.purchase.state == 'done':
return 'done'
@@ -155,7 +172,10 @@ class PurchaseRequest(ModelSQL, ModelView):
_, operator_, state = clause
Operator = fields.SQL_OPERATORS[operator_]
state_case = Case(
(purchase.state == 'cancel', 'cancel'),
((purchase.state == 'cancel')
& (request.exception_ignored == False), 'exception'),
((purchase.state == 'cancel')
& (request.exception_ignored == True), 'cancel'),
(purchase.state == 'done', 'done'),
(request.purchase_line != Null, 'purchased'),
else_='draft')
@@ -525,6 +545,12 @@ class PurchaseRequest(ModelSQL, ModelView):
cls.raise_user_error('delete_purchase_line')
super(PurchaseRequest, cls).delete(requests)
@classmethod
@ModelView.button_action(
'stock_supply.wizard_purchase_cancellation_handle_exception')
def handle_purchase_cancellation_exception(cls, purchases):
pass
class CreatePurchaseRequestStart(ModelView):
'Create Purchase Request'
@@ -738,3 +764,43 @@ class CreatePurchase(Wizard):
taxes.append(tax.id)
line.taxes = taxes
return line
class HandlePurchaseCancellationException(Wizard):
'Handle Purchase Cancellation Exception'
__name__ = 'purchase.request.handle.purchase.cancellation'
start = StateView('purchase.request.handle.purchase.cancellation.start',
'stock_supply.handle_purchase_cancellation_start', [
Button('Cancel', 'end', 'tryton-cancel'),
Button('Reset to draft', 'reset', 'tryton-clear'),
Button('Cancel Request', 'cancel_request', 'tryton-delete',
default=True),
])
reset = StateTransition()
cancel_request = StateTransition()
def transition_reset(self):
pool = Pool()
PurchaseRequest = pool.get('purchase.request')
requests = PurchaseRequest.browse(Transaction().context['active_ids'])
PurchaseRequest.write(requests, {
'purchase_line': None,
})
return 'end'
def transition_cancel_request(self):
pool = Pool()
PurchaseRequest = pool.get('purchase.request')
requests = PurchaseRequest.browse(Transaction().context['active_ids'])
PurchaseRequest.write(requests, {
'exception_ignored': True,
})
return 'end'
class HandlePurchaseCancellationExceptionStart(ModelView):
'Handle Purchase Cancellation Exception - Start'
__name__ = 'purchase.request.handle.purchase.cancellation.start'
+26
View File
@@ -40,6 +40,14 @@ this repository contains the full copyright notices and license terms. -->
<field name="domain" eval="[('purchase_line', '=', None)]" pyson="1"/>
<field name="act_window" ref="act_purchase_request_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_purchase_request_form_domain_exception">
<field name="name">Exception</field>
<field name="sequence" eval="20"/>
<field name="domain" eval="[('state', '=', 'exception')]"
pyson="1"/>
<field name="act_window" ref="act_purchase_request_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_purchase_request_form_domain_all">
<field name="name">All</field>
@@ -98,6 +106,24 @@ this repository contains the full copyright notices and license terms. -->
<field name="action" ref="wizard_create_purchase"/>
</record>
<record model="ir.ui.view" id="handle_purchase_cancellation_start">
<field name="model">purchase.request.handle.purchase.cancellation.start</field>
<field name="type">form</field>
<field name="name">handle_purchase_cancellation_start_form</field>
</record>
<record model="ir.action.wizard"
id="wizard_purchase_cancellation_handle_exception">
<field name="name">Handle Purchase Cancellation</field>
<field name="wiz_name">purchase.request.handle.purchase.cancellation</field>
<field name="model">purchase.request</field>
</record>
<record model="ir.action.keyword"
id="wizard_purchase_cancellation_handle_exception_keyword">
<field name="action" ref="wizard_purchase_cancellation_handle_exception"/>
<field name="keyword">form_action</field>
<field name="model">purchase.request,-1</field>
</record>
<record model="ir.rule.group" id="rule_group_purchase_request">
<field name="model" search="[('model', '=', 'purchase.request')]"/>
<field name="global_p" eval="True"/>
@@ -43,11 +43,13 @@ Create chart of accounts::
>>> accounts = get_accounts(company)
>>> expense = accounts['expense']
Create a customer::
Create parties::
>>> Party = Model.get('party.party')
>>> customer = Party(name='Customer')
>>> customer.save()
>>> supplier = Party(name='Supplier')
>>> supplier.save()
Create stock admin user::
@@ -163,3 +165,48 @@ There is now a draft purchase request::
True
>>> pr.quantity
1.0
Create the purchase then cancel it::
>>> create_purchase = Wizard('purchase.request.create_purchase',
... [pr])
>>> create_purchase.form.party = supplier
>>> create_purchase.execute('start')
>>> pr.state
'purchased'
>>> Purchase = Model.get('purchase.purchase')
>>> purchase, = Purchase.find()
>>> purchase.click('cancel')
>>> pr.reload()
>>> pr.state
'exception'
Handle the exception::
>>> handle_exception = Wizard(
... 'purchase.request.handle.purchase.cancellation', [pr])
>>> handle_exception.execute('reset')
>>> pr.state
'draft'
Recreate a purchase and cancel it again::
>>> create_purchase = Wizard('purchase.request.create_purchase',
... [pr])
>>> pr.state
'purchased'
>>> purchase, = Purchase.find([('state', '=', 'draft')])
>>> purchase.click('cancel')
>>> pr.reload()
>>> pr.state
'exception'
Handle again the exception::
>>> handle_exception = Wizard(
... 'purchase.request.handle.purchase.cancellation', [pr])
>>> handle_exception.execute('cancel_request')
>>> pr.state
'cancel'
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form string="Handle Purchase Cancellation">
<image name="tryton-dialog-information" xexpand="0" xfill="0"/>
<label string="Do you want to cancel the request or to reset it to draft?"
id="question" yalign="0.0" xalign="0.0" xexpand="1"/>
</form>
+5
View File
@@ -34,4 +34,9 @@ this repository contains the full copyright notices and license terms. -->
<field name="origin"/>
<label name="state"/>
<field name="state"/>
<group col="1" colspan="2" id="buttons">
<button name="handle_purchase_cancellation_exception"
string="Handle Purchase Cancellation"
icon="tryton-go-next"/>
</group>
</form>