Add ir.message and use custom exceptions

issue3672
This commit is contained in:
Cédric Krier committed 2018-12-29 14:20:29 +01:00
1 parent 191b26972d
commit a67d1952a7
11 files changed
+213 -143

No files matched your search

+28
View File
@@ -0,0 +1,28 @@
# 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.exceptions import UserError, UserWarning
from trytond.model.exceptions import ValidationError
class AssignError(UserError):
pass
class LocationValidationError(ValidationError):
pass
class PeriodCloseError(UserError):
pass
class InventoryValidationError(ValidationError):
pass
class InventoryCountWarning(UserWarning):
pass
class MoveOriginWarning(UserWarning):
pass
+24 -32
View File
@@ -2,12 +2,16 @@
# this repository contains the full copyright notices and license terms.
from sql import Null
from trytond.i18n import gettext
from trytond.model import Workflow, Model, ModelView, ModelSQL, fields, Check
from trytond.model.exceptions import AccessError
from trytond.pyson import Eval, Bool, If
from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.wizard import Wizard, StateView, StateTransition, Button
from .exceptions import InventoryValidationError, InventoryCountWarning
__all__ = ['Inventory', 'InventoryLine',
'Count', 'CountSearch', 'CountQuantity']
@@ -72,12 +76,6 @@ class Inventory(Workflow, ModelSQL, ModelView):
def __setup__(cls):
super(Inventory, cls).__setup__()
cls._order.insert(0, ('date', 'DESC'))
cls._error_messages.update({
'delete_cancel': ('Inventory "%s" must be canceled before '
'deletion.'),
'unique_line': ('Line "%s" is not unique '
'on Inventory "%s".'),
})
cls._transitions |= set((
('draft', 'done'),
('draft', 'cancel'),
@@ -136,7 +134,9 @@ class Inventory(Workflow, ModelSQL, ModelView):
cls.cancel(inventories)
for inventory in inventories:
if inventory.state != 'cancel':
cls.raise_user_error('delete_cancel', inventory.rec_name)
raise AccessError(
gettext('stock.msg_inventory_delete_cancel',
inventory=inventory.rec_name))
super(Inventory, cls).delete(inventories)
@classmethod
@@ -150,8 +150,10 @@ class Inventory(Workflow, ModelSQL, ModelView):
for line in inventory.lines:
key = line.unique_key
if key in keys:
cls.raise_user_error('unique_line',
(line.rec_name, inventory.rec_name))
raise InventoryValidationError(
gettext('stock.msg_inventory_line_unique',
line=line.rec_name,
inventory=inventory.rec_name))
keys.add(key)
move = line.get_move()
if move:
@@ -330,15 +332,9 @@ class InventoryLine(ModelSQL, ModelView):
t = cls.__table__()
cls._sql_constraints += [
('check_line_qty_pos', Check(t, t.quantity >= 0),
'Line quantity must be positive.'),
'stock.msg_inventory_line_quantity_positive'),
]
cls._order.insert(0, ('product', 'ASC'))
cls._error_messages.update({
'missing_empty_quantity': ('An option for empty quantity is '
'missing for inventory "%(inventory)s".'),
'delete_cancel_draft': ('The line "%(line)s" must be on '
'canceled or draft inventory to be deleted.'),
})
@classmethod
def __register__(cls, module_name):
@@ -428,9 +424,9 @@ class InventoryLine(ModelSQL, ModelView):
qty = self.quantity
if qty is None:
if self.inventory.empty_quantity is None:
self.raise_user_error('missing_empty_quantity', {
'inventory': self.inventory.rec_name,
})
raise InventoryValidationError(
gettext('stock.msg_inventory_missing_empty_quantity',
inventory=self.inventory.rec_name))
if self.inventory.empty_quantity == 'keep':
return
else:
@@ -483,9 +479,10 @@ class InventoryLine(ModelSQL, ModelView):
def delete(cls, lines):
for line in lines:
if line.inventory_state not in {'cancel', 'draft'}:
cls.raise_user_error('delete_cancel_draft', {
'line': line.rec_name,
})
raise AccessError(
gettext('stock.msg_inventory_line_delete_cancel',
line=line.rec_name,
inventory=line.inventory.rec_name))
super(InventoryLine, cls).delete(lines)
@@ -508,17 +505,11 @@ class Count(Wizard):
])
add = StateTransition()
@classmethod
def __setup__(cls):
super(Count, cls).__setup__()
cls._error_messages.update({
'create_line': "No existing line found for %(search)s.",
})
def default_quantity(self, fields):
pool = Pool()
Inventory = pool.get('stock.inventory')
InventoryLine = pool.get('stock.inventory.line')
Warning = pool.get('res.user.warning')
context = Transaction().context
inventory = Inventory(context['active_id'])
values = {}
@@ -526,9 +517,10 @@ class Count(Wizard):
if not lines:
warning_name = '%s.%s.count_create' % (
inventory, self.search.search)
self.raise_user_warning(warning_name, 'create_line', {
'search': self.search.search.rec_name,
})
if Warning.check(warning_name):
raise InventoryCountWarning(warning_name,
gettext('stock.msg_inventory_count_create_line',
search=self.search.search.rec_name))
line, = InventoryLine.create([self.get_line_values(inventory)])
else:
line, = lines
+15 -19
View File
@@ -4,6 +4,7 @@ import datetime
import operator
from decimal import Decimal
from trytond.i18n import gettext
from trytond.model import (
ModelView, ModelSQL, MatchMixin, ValueMixin, DeactivableMixin, fields,
sequence_ordered, tree)
@@ -14,6 +15,8 @@ from trytond.pool import Pool, PoolMeta
from trytond.tools import grouped_slice
from trytond.tools.multivalue import migrate_property
from .exceptions import LocationValidationError
__all__ = ['Location', 'Party', 'PartyLocation', 'ProductsByLocationsContext',
'LocationLeadTime']
@@ -47,6 +50,7 @@ class Location(DeactivableMixin, tree(), ModelSQL, ModelView):
('drop', 'Drop'),
('view', 'View'),
], 'Location type', states=STATES, depends=DEPENDS)
type_string = type.translated('type')
parent = fields.Many2One("stock.location", "Parent", select=True,
left="left", right="right",
states={
@@ -133,16 +137,6 @@ class Location(DeactivableMixin, tree(), ModelSQL, ModelView):
def __setup__(cls):
super(Location, cls).__setup__()
cls._order.insert(0, ('name', 'ASC'))
cls._error_messages.update({
'invalid_type_for_moves': ('Location "%s" with existing moves '
'cannot be changed to a type that does not support moves.'
),
'child_of_warehouse': ('Location "%(location)s" must be a '
'child of warehouse "%(warehouse)s".'),
'inactive_location_with_moves': (
"The location '%(location)s' must be empty "
"to be deactivated."),
})
parent_domain = [
['OR',
@@ -220,8 +214,10 @@ class Location(DeactivableMixin, tree(), ModelSQL, ModelView):
('state', 'not in', ['staging', 'draft']),
])
if moves:
self.raise_user_error(
'invalid_type_for_moves', (self.rec_name,))
raise LocationValidationError(
gettext('stock.msg_location_invalid_type_for_moves',
location=self.rec_name,
type=self.type_string))
@classmethod
def check_inactive(cls, locations):
@@ -230,9 +226,9 @@ class Location(DeactivableMixin, tree(), ModelSQL, ModelView):
empty = cls.get_empty_locations(locations)
non_empty = set(locations) - set(empty)
if non_empty:
cls.raise_user_error('inactive_location_with_moves', {
'location': next(iter(non_empty)).rec_name,
})
raise LocationValidationError(
gettext('stock.msg_location_inactive_not_empty',
location=next(iter(non_empty)).rec_name))
@classmethod
def get_empty_locations(cls, locations=None):
@@ -466,10 +462,10 @@ class Location(DeactivableMixin, tree(), ModelSQL, ModelView):
('parent', 'child_of', warehouse.id),
]))
if location not in childs:
cls.raise_user_error('child_of_warehouse', {
'location': location.rec_name,
'warehouse': warehouse.rec_name,
})
raise LocationValidationError(
gettext('stock.msg_location_child_of_warehouse',
location=location.rec_name,
warehouse=warehouse.rec_name))
@classmethod
def copy(cls, locations, default=None):
+80
View File
@@ -0,0 +1,80 @@
<?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. -->
<tryton>
<data group="1">
<record model="ir.message" id="msg_product_change_default_uom">
<field name="text">You cannot change the default UOM of a product which is associated to stock moves.</field>
</record>
<record model="ir.message" id="msg_product_change_type">
<field name="text">You cannot change the type of a product which is associated to stock moves.</field>
</record>
<record model="ir.message" id="msg_location_invalid_type_for_moves">
<field name="text">You cannot change the type of location "%(location)s" to "%(type)s"
because the type does not support moves and location has existing moves.</field>
</record>
<record model="ir.message" id="msg_location_child_of_warehouse">
<field name="text">To set location "%(location)s" as storage/input/output of warehouse "%(warehouse)s", it must be in the warehouse.</field>
</record>
<record model="ir.message" id="msg_location_inactive_not_empty">
<field name="text">To inactivate location "%(location)s", you must empty it.</field>
</record>
<record model="ir.message" id="msg_period_close_date">
<field name="text">You cannot close periods with a date in the future or today.</field>
</record>
<record model="ir.message" id="msg_period_close_assigned_move">
<field name="text">You cannot close periods with assigned moves in it.</field>
</record>
<record model="ir.message" id="msg_shipment_delete_cancel">
<field name="text">To delete shipment "%(shipment)s" you must cancel it.</field>
</record>
<record model="ir.message" id="msg_inventory_delete_cancel">
<field name="text">To delete inventory "%(inventory)s" you must cancel it.</field>
</record>
<record model="ir.message" id="msg_inventory_missing_empty_quantity">
<field name="text">To confirm the inventory "%(inventory)s" you must select an option for empty quantity.</field>
</record>
<record model="ir.message" id="msg_inventory_line_unique">
<field name="text">Inventory line "%(line)s" is not unique on inventory "%(inventory)s".</field>
</record>
<record model="ir.message" id="msg_inventory_line_quantity_positive">
<field name="text">Inventory line quantity must be positive.</field>
</record>
<record model="ir.message" id="msg_inventory_line_delete_cancel">
<field name="text">To delete inventory line "%(line)s" you must cancel inventory "%(inventory)s".</field>
</record>
<record model="ir.message" id="msg_inventory_count_create_line">
<field name="text">No existing line found for "%(search)s".</field>
</record>
<record model="ir.message" id="msg_erase_party_shipment">
<field name="text">You cannot erase party "%(party)s" while they have pending shipments with company "%(company)s".</field>
</record>
<record model="ir.message" id="msg_move_delete_draft_cancel">
<field name="text">To delete stock move "%(move)s" you must cancel it or reset its state to draft.</field>
</record>
<record model="ir.message" id="msg_move_modify_period_close">
<field name="text">To modify stock move "%(move)s" you must reopen period "%(period)s".</field>
</record>
<record model="ir.message" id="msg_move_modify_assigned">
<field name="text">To modify stock move "%(move)s" you must reset its state to draft.</field>
</record>
<record model="ir.message" id="msg_move_modify_done">
<field name="text">You cannot modify stock move "%(move)s" because it is done.</field>
</record>
<record model="ir.message" id="msg_move_modify_cancel">
<field name="text">You cannot modify stock move "%(move)s" because it is cancelled.</field>
</record>
<record model="ir.message" id="msg_move_no_origin">
<field name="text">Stock moves "%(moves)s" have no origin.</field>
</record>
<record model="ir.message" id="msg_move_quantity_positive">
<field name="text">Move quantity must be positive.</field>
</record>
<record model="ir.message" id="msg_move_internal_quantity_positive">
<field name="text">Internal move quantity must be positive.</field>
</record>
<record model="ir.message" id="msg_move_from_to_location">
<field name="text">The source and destination of stock move must be different.</field>
</record>
</data>
</tryton>
+26 -28
View File
@@ -11,7 +11,9 @@ from sql import Literal, Union, Column, Null, For
from sql.aggregate import Sum
from sql.conditionals import Coalesce, Case
from trytond.i18n import gettext
from trytond.model import Workflow, Model, ModelView, ModelSQL, fields, Check
from trytond.model.exceptions import AccessError
from trytond.pyson import Eval, If, Bool
from trytond.tools import reduce_ids
from trytond.transaction import Transaction
@@ -19,6 +21,8 @@ from trytond.pool import Pool
from trytond.modules.product import price_digits
from .exceptions import MoveOriginWarning
__all__ = ['StockMixin', 'Move']
STATES = {
@@ -265,31 +269,15 @@ class Move(Workflow, ModelSQL, ModelView):
t = cls.__table__()
cls._sql_constraints += [
('check_move_qty_pos', Check(t, t.quantity >= 0),
'Move quantity must be positive'),
'stock.msg_move_quantity_positive'),
('check_move_internal_qty_pos',
Check(t, t.internal_quantity >= 0),
'Internal move quantity must be positive'),
'stock.msg_move_internal_quantity_positive'),
('check_from_to_locations',
Check(t, t.from_location != t.to_location),
'Source and destination location must be different'),
'stock.msg_move_from_to_location'),
]
cls._order[0] = ('id', 'DESC')
cls._error_messages.update({
'set_state_draft': ('You can not set stock move "%s" to draft '
'state.'),
'set_state_assigned': ('You can not set stock move "%s" to '
'assigned state.'),
'set_state_done': 'You can not set stock move "%s" to done state.',
'delele_state': ('You can not delete stock move "%s" because '
'it is not in staging, draft nor cancelled state.'),
'period_closed': ('You can not modify move "%(move)s" because '
'period "%(period)s" is closed.'),
'modify_assigned': ('You can not modify stock move "%s" because '
'it is in "Assigned" state.'),
'modify_done_cancel': ('You can not modify stock move "%s" '
'because it is in "Done" or "Cancel" state.'),
'no_origin': 'The stock moves "%s" have no origin.',
})
cls._transitions |= set((
('staging', 'draft'),
('staging', 'cancel'),
@@ -492,10 +480,10 @@ class Move(Workflow, ModelSQL, ModelView):
date = (move.effective_date if move.effective_date
else move.planned_date)
if date and date <= period.date:
cls.raise_user_error('period_closed', {
'move': move.rec_name,
'period': period.rec_name,
})
raise AccessError(
gettext('stock.msg_move_modify_period_close',
move=move.rec_name,
period=period.rec_name))
def get_rec_name(self, name):
return ("%s%s %s"
@@ -701,12 +689,15 @@ class Move(Workflow, ModelSQL, ModelView):
if cls._deny_modify_assigned & vals_set:
for move in moves:
if move.state == 'assigned':
cls.raise_user_error('modify_assigned', move.rec_name)
raise AccessError(
gettext('stock.msg_move_modify_assigned',
move=move.rec_name))
if cls._deny_modify_done_cancel & vals_set:
for move in moves:
if move.state in ('done', 'cancel'):
cls.raise_user_error('modify_done_cancel',
(move.rec_name,))
raise AccessError(
gettext('stock.msg_move_modify_%s' % move.state,
move=move.rec_name))
super(Move, cls).write(*args)
@@ -731,7 +722,9 @@ class Move(Workflow, ModelSQL, ModelView):
def delete(cls, moves):
for move in moves:
if move.state not in {'staging', 'draft', 'cancel'}:
cls.raise_user_error('delele_state', (move.rec_name,))
raise AccessError(
gettext('stock.msg_move_delete_draft_cancel',
move=move.rec_name))
super(Move, cls).delete(moves)
@staticmethod
@@ -741,6 +734,8 @@ class Move(Workflow, ModelSQL, ModelView):
@classmethod
def check_origin(cls, moves, types=None):
pool = Pool()
Warning = pool.get('res.user.warning')
if types is None:
types = cls.check_origin_types()
if not types:
@@ -757,7 +752,10 @@ class Move(Workflow, ModelSQL, ModelView):
names += '...'
warning_name = '%s.done' % hashlib.md5(
str(moves).encode('utf-8')).hexdigest()
cls.raise_user_warning(warning_name, 'no_origin', names)
if Warning.check(warning_name):
raise MoveOriginWarning(warning_name,
gettext('stock.msg_move_no_origin',
moves=names))
def pick_product(self, location_quantities):
"""
+7 -14
View File
@@ -1,7 +1,10 @@
# 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.i18n import gettext
from trytond.pool import PoolMeta, Pool
from trytond.modules.party.exceptions import EraseError
__all__ = ['PartyReplace', 'PartyErase']
@@ -21,16 +24,6 @@ class PartyReplace(metaclass=PoolMeta):
class PartyErase(metaclass=PoolMeta):
__name__ = 'party.erase'
@classmethod
def __setup__(cls):
super(PartyErase, cls).__setup__()
cls._error_messages.update({
'pending_shipment': (
'The party "%(party)s" can not be erased '
'because he has pending shipments '
'for the company "%(company)s".'),
})
def check_erase_company(self, party, company):
pool = Pool()
ShipmentIn = pool.get('stock.shipment.in')
@@ -50,7 +43,7 @@ class PartyErase(metaclass=PoolMeta):
('state', 'not in', ['done', 'cancel']),
])
if shipments:
self.raise_user_error('pending_shipment', {
'party': party.rec_name,
'company': company.rec_name,
})
raise EraseError(
gettext('stock.msg_erase_party_shipment',
party=party.rec_name,
company=company.rec_name))
+7 -9
View File
@@ -4,12 +4,15 @@ from itertools import chain
from sql import Literal, For
from trytond.i18n import gettext
from trytond.model import Workflow, ModelView, ModelSQL, fields
from trytond.pyson import Eval, If
from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.tools import grouped_slice
from .exceptions import PeriodCloseError
__all__ = ['Period', 'Cache']
@@ -37,13 +40,6 @@ class Period(Workflow, ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(Period, cls).__setup__()
cls._error_messages.update({
'close_period_future_today': ('You can not close a period '
'in the future or today.'),
'close_period_assigned_move': (
'You can not close a period when '
'there still are assigned moves.'),
})
cls._transitions |= set((
('draft', 'closed'),
('closed', 'draft'),
@@ -125,7 +121,8 @@ class Period(Workflow, ModelSQL, ModelView):
recent_date = max(period.date for period in periods)
if recent_date >= today:
cls.raise_user_error('close_period_future_today')
raise PeriodCloseError(
gettext('stock.msg_period_close_date'))
if Move.search([
('state', '=', 'assigned'),
['OR', [
@@ -134,7 +131,8 @@ class Period(Workflow, ModelSQL, ModelView):
],
('effective_date', '<=', recent_date),
]]):
cls.raise_user_error('close_period_assigned_move')
raise PeriodCloseError(
gettext('stock.msg_period_close_assigned_move'))
for grouping in cls.groupings():
Cache = cls.get_cache(grouping)
+7 -11
View File
@@ -10,7 +10,9 @@ from sql.aggregate import Max
from sql.functions import CurrentTimestamp
from sql.conditionals import Coalesce
from trytond.i18n import gettext
from trytond.model import ModelSQL, ModelView, fields
from trytond.model.exceptions import AccessError
from trytond.wizard import Wizard, StateTransition
from trytond.pyson import Eval, Or
from trytond.transaction import Transaction
@@ -41,7 +43,7 @@ def check_no_move(func):
],
limit=1, order=[])
if moves:
return True
return moves
return False
@functools.wraps(func)
@@ -53,10 +55,10 @@ def check_no_move(func):
and transaction.context.get('_check_access')):
actions = iter(args)
for records, values in zip(actions, actions):
for field, error in Template._modify_no_move:
for field, msg in Template._modify_no_move:
if field in values:
if find_moves(cls, records):
Template.raise_user_error(error)
raise AccessError(gettext(msg))
# No moves for those records
break
func(cls, *args)
@@ -86,19 +88,13 @@ class Template(metaclass=PoolMeta):
@classmethod
def __setup__(cls):
super(Template, cls).__setup__()
cls._error_messages.update({
'change_default_uom': ('You cannot change the default uom for '
'a product which is associated to stock moves.'),
'change_type': ('You cannot change the type for a product '
'which is associated to stock moves.'),
})
cls.cost_price.states['required'] = Or(
cls.cost_price.states.get('required', True),
Eval('type').in_(['goods', 'assets']))
cls.cost_price.depends.append('type')
cls._modify_no_move = [
('default_uom', 'change_default_uom'),
('type', 'change_type'),
('default_uom', 'stock.msg_product_change_default_uom'),
('type', 'stock.msg_product_change_type'),
]
@classmethod
+17 -29
View File
@@ -7,7 +7,9 @@ from functools import partial
from sql import Null
from trytond.i18n import gettext
from trytond.model import Workflow, ModelView, ModelSQL, fields
from trytond.model.exceptions import AccessError
from trytond.modules.company import CompanyReport
from trytond.wizard import Wizard, StateTransition, StateView, Button
from trytond.pyson import Eval, If, Id, Bool
@@ -183,14 +185,6 @@ class ShipmentIn(Workflow, ModelSQL, ModelView):
def __setup__(cls):
super(ShipmentIn, cls).__setup__()
cls._order[0] = ('id', 'DESC')
cls._error_messages.update({
'incoming_move_input_dest': ('Incoming Moves must have '
'the warehouse input location as destination location.'),
'inventory_move_input_source': ('Inventory Moves must '
'have the warehouse input location as source location.'),
'delete_cancel': ('Supplier Shipment "%s" must be cancelled '
'before deletion.'),
})
cls._transitions |= set((
('draft', 'received'),
('received', 'done'),
@@ -426,7 +420,9 @@ class ShipmentIn(Workflow, ModelSQL, ModelView):
cls.cancel(shipments)
for shipment in shipments:
if shipment.state != 'cancel':
cls.raise_user_error('delete_cancel', shipment.rec_name)
raise AccessError(
gettext('stock.msg_shipment_delete_cancel',
shipment=shipment.rec_name))
Move.delete([m for s in shipments for m in s.moves])
super(ShipmentIn, cls).delete(shipments)
@@ -575,10 +571,6 @@ class ShipmentInReturn(Workflow, ModelSQL, ModelView):
def __setup__(cls):
super(ShipmentInReturn, cls).__setup__()
cls._order[0] = ('id', 'DESC')
cls._error_messages.update({
'delete_cancel': ('Supplier Return Shipment "%s" must be '
'cancelled before deletion.'),
})
cls._transitions |= set((
('draft', 'waiting'),
('waiting', 'assigned'),
@@ -702,7 +694,9 @@ class ShipmentInReturn(Workflow, ModelSQL, ModelView):
cls.cancel(shipments)
for shipment in shipments:
if shipment.state != 'cancel':
cls.raise_user_error('delete_cancel', shipment.rec_name)
raise AccessError(
gettext('stock.msg_shipment_delete_cancel',
shipment=shipment.rec_name))
Move.delete([m for s in shipments for m in s.moves])
super(ShipmentInReturn, cls).delete(shipments)
@@ -921,10 +915,6 @@ class ShipmentOut(Workflow, ModelSQL, ModelView):
def __setup__(cls):
super(ShipmentOut, cls).__setup__()
cls._order[0] = ('id', 'DESC')
cls._error_messages.update({
'delete_cancel': ('Customer Shipment "%s" must be cancelled '
'before deletion.'),
})
cls._transitions |= set((
('draft', 'waiting'),
('waiting', 'assigned'),
@@ -1338,7 +1328,9 @@ class ShipmentOut(Workflow, ModelSQL, ModelView):
cls.cancel(shipments)
for shipment in shipments:
if shipment.state != 'cancel':
cls.raise_user_error('delete_cancel', shipment.rec_name)
raise AccessError(
gettext('stock.msg_shipment_delete_cancel',
shipment=shipment.rec_name))
Move.delete([m for s in shipments for m in s.moves])
super(ShipmentOut, cls).delete(shipments)
@@ -1494,10 +1486,6 @@ class ShipmentOutReturn(Workflow, ModelSQL, ModelView):
def __setup__(cls):
super(ShipmentOutReturn, cls).__setup__()
cls._order[0] = ('id', 'DESC')
cls._error_messages.update({
'delete_cancel': ('Customer Return Shipment "%s" must be '
'cancelled before deletion.'),
})
cls._transitions |= set((
('draft', 'received'),
('received', 'done'),
@@ -1689,7 +1677,9 @@ class ShipmentOutReturn(Workflow, ModelSQL, ModelView):
cls.cancel(shipments)
for shipment in shipments:
if shipment.state != 'cancel':
cls.raise_user_error('delete_cancel', shipment.rec_name)
raise AccessError(
gettext('stock.msg_shipment_delete_cancel',
shipment=shipment.rec_name))
Move.delete([m for s in shipments for m in s.moves])
super(ShipmentOutReturn, cls).delete(shipments)
@@ -1994,10 +1984,6 @@ class ShipmentInternal(Workflow, ModelSQL, ModelView):
def __setup__(cls):
super(ShipmentInternal, cls).__setup__()
cls._order[0] = ('id', 'DESC')
cls._error_messages.update({
'delete_cancel': ('Internal Shipment "%s" must be cancelled '
'before deletion.'),
})
cls._transitions |= set((
('request', 'draft'),
('draft', 'waiting'),
@@ -2166,7 +2152,9 @@ class ShipmentInternal(Workflow, ModelSQL, ModelView):
cls.cancel(shipments)
for shipment in shipments:
if shipment.state != 'cancel':
cls.raise_user_error('delete_cancel', shipment.rec_name)
raise AccessError(
gettext('stock.msg_shipment_delete_cancel',
shipment=shipment.rec_name))
Move.delete([m for s in shipments for m in s.moves])
super(ShipmentInternal, cls).delete(shipments)
+1 -1
View File
@@ -76,7 +76,7 @@ Count inventory::
>>> count.execute('quantity') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
UserWarning: ...
InventoryCountWarning: ...
>>> Model.get('res.user.warning')(user=config.user,
... name='stock.inventory,%s.product.product,%s.count_create' % (
+1
View File
@@ -16,3 +16,4 @@ xml:
party.xml
configuration.xml
period.xml
message.xml