Demurrage
This commit is contained in:
@@ -31,6 +31,8 @@ canonique seulement quand elle est reprise dans une page thematique.
|
||||
</li>
|
||||
<li style="margin:0.38rem 0;">Les contrats Sale et Purchase ont un onglet <code>Charter Conditions</code> au niveau entete et ligne. Une ligne sans conditions propres herite des conditions de l'entete; des conditions de ligne remplacent l'heritage.
|
||||
</li>
|
||||
<li style="margin:0.38rem 0;">Les conditions creees depuis une Sale ou une Sale Line sont limitees au role <code>Customer</code>; celles creees depuis une Purchase ou Purchase Line sont limitees au role <code>Supplier</code>. Les conditions creees depuis une Charter Party ne peuvent pas utiliser les roles <code>Supplier</code> ou <code>Customer</code> afin d'eviter la confusion entre conditions armateur/charte et conditions contractuelles achat/vente.
|
||||
</li>
|
||||
<li style="margin:0.38rem 0;">Les shipments et SOF exposent les conditions Owner, Supplier et Customer retrouvees depuis le charter party et les lots/lignes physiques.
|
||||
</li>
|
||||
<li style="margin:0.38rem 0;">Le calcul SOF privilegie la condition appliquee: laytime allowed, turn time, pumping rate, rate demurrage et rate despatch. A defaut, il garde les anciens champs legacy demurrage/pumping.
|
||||
|
||||
@@ -23,6 +23,12 @@ canonique seulement quand elle est reprise dans une page thematique.
|
||||
- Les contrats Sale et Purchase ont un onglet `Charter Conditions` au
|
||||
niveau entete et ligne. Une ligne sans conditions propres herite des
|
||||
conditions de l'entete; des conditions de ligne remplacent l'heritage.
|
||||
- Les conditions creees depuis une Sale ou une Sale Line sont limitees au
|
||||
role `Customer`; celles creees depuis une Purchase ou Purchase Line sont
|
||||
limitees au role `Supplier`. Les conditions creees depuis une
|
||||
Charter Party ne peuvent pas utiliser les roles `Supplier` ou `Customer`
|
||||
afin d'eviter la confusion entre conditions armateur/charte et conditions
|
||||
contractuelles achat/vente.
|
||||
- Les shipments et SOF exposent les conditions Owner, Supplier et Customer
|
||||
retrouvees depuis le charter party et les lots/lignes physiques.
|
||||
- Le calcul SOF privilegie la condition appliquee: laytime allowed,
|
||||
|
||||
@@ -481,15 +481,7 @@ class CharterCondition(ModelSQL, ModelView):
|
||||
"Charter Condition"
|
||||
__name__ = 'charter.condition'
|
||||
|
||||
name = fields.Char("Name")
|
||||
charter_party = fields.Many2One(
|
||||
'stock.charter.party', "Charter Party", ondelete='CASCADE')
|
||||
purchase = fields.Many2One(
|
||||
'purchase.purchase', "Purchase", ondelete='CASCADE')
|
||||
purchase_line = fields.Many2One(
|
||||
'purchase.line', "Purchase Line", ondelete='CASCADE')
|
||||
party = fields.Many2One('party.party', "Party")
|
||||
party_role = fields.Selection([
|
||||
_party_role_selection = [
|
||||
(None, ''),
|
||||
('owner', 'Owner'),
|
||||
('charterer', 'Charterer'),
|
||||
@@ -499,7 +491,18 @@ class CharterCondition(ModelSQL, ModelView):
|
||||
('agent', 'Agent'),
|
||||
('terminal', 'Terminal'),
|
||||
('other', 'Other'),
|
||||
], "Party Role")
|
||||
]
|
||||
|
||||
name = fields.Char("Name")
|
||||
charter_party = fields.Many2One(
|
||||
'stock.charter.party', "Charter Party", ondelete='CASCADE')
|
||||
purchase = fields.Many2One(
|
||||
'purchase.purchase', "Purchase", ondelete='CASCADE')
|
||||
purchase_line = fields.Many2One(
|
||||
'purchase.line', "Purchase Line", ondelete='CASCADE')
|
||||
party = fields.Many2One('party.party', "Party")
|
||||
party_role = fields.Selection(
|
||||
'get_party_roles', "Party Role")
|
||||
responsibility = fields.Selection([
|
||||
(None, ''),
|
||||
('ours', 'Ours'),
|
||||
@@ -546,6 +549,45 @@ class CharterCondition(ModelSQL, ModelView):
|
||||
def default_all_time_saved():
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def default_party_role():
|
||||
role_context = Transaction().context.get('charter_condition_role')
|
||||
if role_context in {'purchase', 'purchase_line', 'supplier'}:
|
||||
return 'supplier'
|
||||
if role_context in {'sale', 'sale_line', 'customer'}:
|
||||
return 'customer'
|
||||
if role_context == 'charter_party':
|
||||
return 'owner'
|
||||
|
||||
@fields.depends(
|
||||
'charter_party', 'purchase', 'purchase_line', 'sale', 'sale_line')
|
||||
def get_party_roles(self):
|
||||
role_context = Transaction().context.get('charter_condition_role')
|
||||
if (role_context in {'purchase', 'purchase_line', 'supplier'}
|
||||
or getattr(self, 'purchase', None)
|
||||
or getattr(self, 'purchase_line', None)):
|
||||
return [(None, ''), ('supplier', 'Supplier')]
|
||||
if (role_context in {'sale', 'sale_line', 'customer'}
|
||||
or getattr(self, 'sale', None)
|
||||
or getattr(self, 'sale_line', None)):
|
||||
return [(None, ''), ('customer', 'Customer')]
|
||||
if role_context == 'charter_party' or getattr(
|
||||
self, 'charter_party', None):
|
||||
return [
|
||||
item for item in self._party_role_selection
|
||||
if item[0] not in {'supplier', 'customer'}]
|
||||
return self._party_role_selection
|
||||
|
||||
@classmethod
|
||||
def validate(cls, conditions):
|
||||
super().validate(conditions)
|
||||
for condition in conditions:
|
||||
allowed_roles = {role for role, _ in condition.get_party_roles()}
|
||||
if condition.party_role not in allowed_roles:
|
||||
raise UserError(
|
||||
"This charter condition party role is not allowed "
|
||||
"for its source.")
|
||||
|
||||
|
||||
class CharterParty(ModelSQL, ModelView):
|
||||
"Charter Party"
|
||||
|
||||
@@ -9,6 +9,7 @@ from trytond.pool import Pool
|
||||
from trytond.pyson import Eval
|
||||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||||
from trytond.exceptions import UserError
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.modules.purchase_trade import valuation as valuation_module
|
||||
from trytond.modules.purchase_trade import lot as lot_module
|
||||
from trytond.modules.purchase_trade import purchase as purchase_module
|
||||
@@ -150,6 +151,44 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
||||
|
||||
self.assertEqual(rate.basis, 'per_day')
|
||||
|
||||
@with_transaction()
|
||||
def test_charter_condition_role_defaults_from_context(self):
|
||||
'charter condition role defaults to the business source context'
|
||||
Condition = Pool().get('charter.condition')
|
||||
|
||||
with Transaction().set_context(charter_condition_role='sale'):
|
||||
self.assertEqual(Condition.default_party_role(), 'customer')
|
||||
condition = Condition()
|
||||
self.assertEqual(
|
||||
condition.get_party_roles(),
|
||||
[(None, ''), ('customer', 'Customer')])
|
||||
|
||||
with Transaction().set_context(charter_condition_role='purchase'):
|
||||
self.assertEqual(Condition.default_party_role(), 'supplier')
|
||||
condition = Condition()
|
||||
self.assertEqual(
|
||||
condition.get_party_roles(),
|
||||
[(None, ''), ('supplier', 'Supplier')])
|
||||
|
||||
with Transaction().set_context(charter_condition_role='charter_party'):
|
||||
self.assertEqual(Condition.default_party_role(), 'owner')
|
||||
condition = Condition()
|
||||
roles = {role for role, _ in condition.get_party_roles()}
|
||||
self.assertNotIn('supplier', roles)
|
||||
self.assertNotIn('customer', roles)
|
||||
|
||||
@with_transaction()
|
||||
def test_charter_condition_role_rejects_invalid_source_role(self):
|
||||
'charter condition role is constrained by its source'
|
||||
Condition = Pool().get('charter.condition')
|
||||
condition = Condition()
|
||||
condition.name = 'Invalid supplier condition on sale'
|
||||
condition.party_role = 'supplier'
|
||||
|
||||
with Transaction().set_context(charter_condition_role='sale'):
|
||||
with self.assertRaises(UserError):
|
||||
Condition.validate([condition])
|
||||
|
||||
@with_transaction()
|
||||
def test_sof_calculation_reads_applied_condition_rates(self):
|
||||
'sof demurrage calculation uses the selected charter condition rates'
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<field name="laycan_to"/>
|
||||
</page>
|
||||
<page string="Conditions" id="conditions">
|
||||
<field name="conditions" colspan="4" mode="tree,form" view_ids="purchase_trade.charter_condition_view_tree,purchase_trade.charter_condition_view_form"/>
|
||||
<field name="conditions" colspan="4" mode="tree,form" context="{'charter_condition_role': 'charter_party'}" view_ids="purchase_trade.charter_condition_view_tree,purchase_trade.charter_condition_view_form"/>
|
||||
</page>
|
||||
<page string="Legal" col="4" id="legal">
|
||||
<label name="governing_law"/>
|
||||
|
||||
@@ -56,7 +56,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</xpath>
|
||||
<xpath expr="/form/notebook/page[@id='purchase']" position="after">
|
||||
<page string="Charter Conditions" id="charter_conditions">
|
||||
<field name="charter_conditions" colspan="4" mode="tree,form" view_ids="purchase_trade.charter_condition_view_tree,purchase_trade.charter_condition_view_form"/>
|
||||
<field name="charter_conditions" colspan="4" mode="tree,form" context="{'charter_condition_role': 'purchase'}" view_ids="purchase_trade.charter_condition_view_tree,purchase_trade.charter_condition_view_form"/>
|
||||
</page>
|
||||
<page string="Contract Clauses" col="4" id="contract_clauses">
|
||||
<label name="contract_template"/>
|
||||
|
||||
@@ -69,7 +69,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="premium_decomposition" colspan="4" mode="tree,form" view_ids="purchase_trade.premium_composition_view_tree,purchase_trade.premium_composition_view_form"/>
|
||||
</page>
|
||||
<page string="Charter Conditions" id="charter_conditions">
|
||||
<field name="charter_conditions" colspan="4" mode="tree,form" view_ids="purchase_trade.charter_condition_view_tree,purchase_trade.charter_condition_view_form"/>
|
||||
<field name="charter_conditions" colspan="4" mode="tree,form" context="{'charter_condition_role': 'purchase_line'}" view_ids="purchase_trade.charter_condition_view_tree,purchase_trade.charter_condition_view_form"/>
|
||||
</page>
|
||||
</xpath>
|
||||
<xpath expr="/form/notebook/page[@id='taxes']" position="before">
|
||||
|
||||
@@ -56,7 +56,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</xpath>
|
||||
<xpath expr="/form/notebook/page[@id='sale']" position="after">
|
||||
<page string="Charter Conditions" id="charter_conditions">
|
||||
<field name="charter_conditions" colspan="4" mode="tree,form" view_ids="purchase_trade.charter_condition_view_tree,purchase_trade.charter_condition_view_form"/>
|
||||
<field name="charter_conditions" colspan="4" mode="tree,form" context="{'charter_condition_role': 'sale'}" view_ids="purchase_trade.charter_condition_view_tree,purchase_trade.charter_condition_view_form"/>
|
||||
</page>
|
||||
<page string="Contract Clauses" col="4" id="contract_clauses">
|
||||
<label name="contract_template"/>
|
||||
|
||||
@@ -69,7 +69,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="premium_decomposition" colspan="4" mode="tree,form" view_ids="purchase_trade.premium_composition_view_tree,purchase_trade.premium_composition_view_form"/>
|
||||
</page>
|
||||
<page string="Charter Conditions" id="charter_conditions">
|
||||
<field name="charter_conditions" colspan="4" mode="tree,form" view_ids="purchase_trade.charter_condition_view_tree,purchase_trade.charter_condition_view_form"/>
|
||||
<field name="charter_conditions" colspan="4" mode="tree,form" context="{'charter_condition_role': 'sale_line'}" view_ids="purchase_trade.charter_condition_view_tree,purchase_trade.charter_condition_view_form"/>
|
||||
</page>
|
||||
</xpath>
|
||||
<xpath expr="/form/notebook/page[@id='taxes']" position="before">
|
||||
|
||||
@@ -123,7 +123,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</page>
|
||||
</notebook>
|
||||
<newline/>
|
||||
<field name="sof" colspan="4" mode="form,tree" view_ids="purchase_trade.view_form_sof,purchase_trade.view_list_sof"/>
|
||||
<field name="sof" colspan="4" mode="tree,form" view_ids="purchase_trade.view_list_sof,purchase_trade.view_form_sof"/>
|
||||
<newline/>
|
||||
<button name="compute" string="compute"/>
|
||||
</page>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<label name="sailing_time"/>
|
||||
<field name="sailing_time"/>
|
||||
<newline/>
|
||||
<field name="sof_events" colspan="4" mode="tree" view_ids="purchase_trade.view_sof_event_tree"/>
|
||||
<field name="sof_events" colspan="4" mode="tree,form" view_ids="purchase_trade.view_sof_event_tree,purchase_trade.view_sof_event_form"/>
|
||||
</page>
|
||||
|
||||
<page string="Calculation" id="calcul">
|
||||
|
||||
Reference in New Issue
Block a user