SHipment cancel

This commit is contained in:
2026-05-25 15:55:42 +02:00
parent 4da56e4b8a
commit 8b4daeac84
2 changed files with 95 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
# 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.model import fields
from trytond.model import fields, Workflow
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval, Id
from trytond.model import (ModelSQL, ModelView)
@@ -470,13 +470,65 @@ class ShipmentIn(metaclass=PoolMeta):
agent = fields.Many2One('party.party',"Booking Agent")
service_order_key = fields.Integer("Service Order Key")
@classmethod
def __setup__(cls):
super().__setup__()
cls._buttons.update({
'compute': {},
'send': {},
})
@classmethod
def __setup__(cls):
super().__setup__()
cls._transitions |= set((
('started', 'cancelled'),
))
cls._buttons.update({
'compute': {},
'send': {},
})
@classmethod
def _stock_move_origin(cls, move):
return 'stock.move,%s' % move.id
@classmethod
def _delete_draft_account_moves_for_stock_moves(cls, moves):
moves = [move for move in moves if getattr(move, 'id', None)]
if not moves:
return
AccountMove = Pool().get('account.move')
account_moves = AccountMove.search([
('origin', 'in', [cls._stock_move_origin(move) for move in moves]),
])
posted = [
move for move in account_moves
if getattr(move, 'state', None) == 'posted']
if posted:
names = ', '.join(move.rec_name for move in posted[:5])
if len(posted) > 5:
names += '...'
raise UserError(
"Cannot cancel started shipment because stock accounting "
"move(s) are already posted: %s" % names)
draft_moves = [
move for move in account_moves
if getattr(move, 'state', None) != 'posted']
if draft_moves:
AccountMove.delete(draft_moves)
@classmethod
@ModelView.button
@Workflow.transition('cancelled')
def cancel(cls, shipments):
moves = [
move for shipment in shipments
for move in shipment.incoming_moves + shipment.inventory_moves]
cls._delete_draft_account_moves_for_stock_moves(moves)
super().cancel(shipments)
started_shipments = [
shipment for shipment in shipments
if shipment.state == 'started']
if started_shipments:
cls.write(started_shipments, {
'start_date': None,
'started_by': None,
})
def get_vessel_type(self,name=None):
if self.vessel:

View File

@@ -969,6 +969,41 @@ class PurchaseTradeTestCase(ModuleTestCase):
fee_model.save.assert_not_called()
product_model.get_by_name.assert_not_called()
def test_shipment_started_cancel_deletes_draft_stock_account_moves(self):
'started shipment cancel removes draft account moves linked to stock moves'
ShipmentIn = Pool().get('stock.shipment.in')
draft_move = Mock(state='draft')
account_move = Mock()
account_move.search.return_value = [draft_move]
stock_moves = [Mock(id=10), Mock(id=20)]
with patch('trytond.modules.purchase_trade.stock.Pool') as PoolMock:
PoolMock.return_value.get.return_value = account_move
ShipmentIn._delete_draft_account_moves_for_stock_moves(stock_moves)
account_move.search.assert_called_once_with([
('origin', 'in', ['stock.move,10', 'stock.move,20']),
])
account_move.delete.assert_called_once_with([draft_move])
def test_shipment_started_cancel_refuses_posted_stock_account_moves(self):
'started shipment cancel is blocked by posted stock account moves'
ShipmentIn = Pool().get('stock.shipment.in')
posted_move = Mock(state='posted', rec_name='STJ/1')
account_move = Mock()
account_move.search.return_value = [posted_move]
with patch('trytond.modules.purchase_trade.stock.Pool') as PoolMock:
PoolMock.return_value.get.return_value = account_move
with self.assertRaises(UserError):
ShipmentIn._delete_draft_account_moves_for_stock_moves([
Mock(id=10),
])
account_move.delete.assert_not_called()
@with_transaction()
def test_shipment_in_type_detects_dropship(self):
'shipment type is dropship from supplier directly to customer'