Adding exception state on the purchase requests
issue5107 review16811002
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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'
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user