Commit 83ff9883 authored by Romain Courteaud's avatar Romain Courteaud

slapos_accounting:

* disable packing list generation from tioxml
  Everything is broken currently...
* drop testSlapOSContractAlarm
* drop create_new_cloud_contract action
* drop jump_to_cloud_contract action
* test: SoftwareInstance_requestValidationPayment was dropped
* drop CloudContractLine_getRemainingInvoiceCredit
* drop Person_isAllowedToAllocate
* drop Entity_statSlapOSOutstandingAmount
* test: change class inheritance
  do not inherit from a class with existing test, as it forces subclass to keep exactly the same test function name
* lint: do not redefine id variable
parent cc8ae8bf
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>create_new_cloud_contract</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>50.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Create Cloud Contract</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Person_generateCloudContract</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_jump</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_jump</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>jump_to_cloud_contract</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>21.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Cloud Contract</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string encoding="cdata"><![CDATA[
string:${object_url}/Base_jumpToRelatedObject?base_category=destination_section&portal_type=Cloud+Contract
]]></string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>python: portal.Base_checkPermission(\'cloud_contract_module\', \'View\')</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -10,6 +10,10 @@
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_searchSubmittedConsumptionTioXMLFileList</string> </value>
</item>
<item>
<key> <string>automatic_solve</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
......@@ -18,7 +22,7 @@
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
......
......@@ -3,7 +3,7 @@
specific use. Returns the Account object
'''
id = {
account_id = {
'asset_receivable_subscriber': 'receivable',
'asset_deposit_subscriber': 'deposit',
'collection': 'payment_to_encash',
......@@ -12,7 +12,7 @@ id = {
account, = context.getPortalObject().portal_catalog(
portal_type='Account',
id=id,
id=account_id,
validation_state='validated',
limit=2,
)
......
person = context.getParentValue().getDestinationSectionValue()
amount = person.Entity_statOutstandingAmount(
resource_uid=context.getPriceCurrencyUid())
return context.getMaximumInvoiceCredit() - amount
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>CloudContractLine_getRemainingInvoiceCredit</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -409,10 +409,6 @@
<string>maximum_invoice_credit</string>
<string>Maximum Invoice Credit</string>
</tuple>
<tuple>
<string>CloudContractLine_getRemainingInvoiceCredit</string>
<string>Remaining Credit</string>
</tuple>
</list>
</value>
</item>
......
portal = context.getPortalObject()
from DateTime import DateTime
if contract is None:
contract = portal.portal_catalog.getResultValue(
portal_type="Cloud Contract",
default_destination_section_uid=context.getUid(),
validation_state=['invalidated', 'validated'],
)
if contract is None:
return context.Entity_statOutstandingAmount()
# We evaluate Multiple scenarios
amount = context.Entity_statOutstandingAmount()
# All payed so just return
if not amount:
return amount
maximum_invoice_delay = contract.getMaximumInvoiceDelay()
maximum_invoice_credit = 0.0
# For now we only support those 2 currencies
currency_uid_list = [
portal.currency_module.EUR.getUid(),
portal.currency_module.CNY.getUid(),
]
contract_line_list = contract.objectValues(
portal_type="Cloud Contract Line")
if not len(contract_line_list):
return context.Entity_statOutstandingAmount(
at_date=at_date)
for currency_uid in currency_uid_list:
for line in contract_line_list:
if line.getPriceCurrencyUid() == currency_uid:
maximum_invoice_credit = line.getMaximumInvoiceCredit()
amount_per_currency = context.Entity_statOutstandingAmount(
at_date=at_date, resource_uid=currency_uid)
if amount_per_currency > maximum_invoice_credit:
return amount_per_currency - maximum_invoice_credit
# We exceed maximum amount because
# user already requested too much
if maximum_invoice_delay:
# Recalculate now ignoring the all invoices from lastest days.
at_date = DateTime()-maximum_invoice_delay
return context.Entity_statOutstandingAmount(
at_date=at_date)
return amount
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>contract=None, at_date=None, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Entity_statSlapOSOutstandingAmount</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
if context.getPortalType() != "Person":
raise ValueError("This script can only be called under person context")
payment_portal_type = "Payment Transaction"
contract_portal_type = "Cloud Contract"
tag = "%s_requestValidationPayment_inProgress" % context.getUid()
if (portal.portal_activities.countMessageWithTag(tag) > 0):
# The cloud contract is already under creation but can not be fetched from catalog
# As it is not possible to fetch informations, it is better to raise an error
return None
contract = portal.portal_catalog.getResultValue(
portal_type=contract_portal_type,
default_destination_section_uid=context.getUid(),
validation_state=['invalidated', 'validated'],
)
msg = context.Base_translateString("Cloud Contract related to %s" % context.getTitle())
if (contract is None):
# Prevent concurrent transaction to create 2 contracts for the same person
context.serialize()
# Time to create the contract
contract = portal.cloud_contract_module.newContent(
portal_type=contract_portal_type,
title='Contract for "%s"' % context.getTitle(),
destination_section_value=context
)
contract.validate(comment='New automatic contract for %s' % context.getTitle())
contract.invalidate(comment='New automatic contract for %s' % context.getTitle())
contract.reindexObject(activate_kw={'tag': tag})
msg = context.Base_translateString("Cloud Contract created.")
if (contract.getValidationState() == "invalidated"):
# search if the user already paid anything
payment = portal.portal_catalog.getResultValue(
portal_type=payment_portal_type,
default_destination_section_uid=context.getUid(),
simulation_state=['stopped'],
)
if (payment is not None):
# Found one payment, the contract can be validated
comment = "Contract validated as paid payment %s found" % payment.getRelativeUrl()
contract.validate(comment=comment)
contract.reindexObject(activate_kw={'tag': tag})
if batch:
return contract
return contract.Base_redirect(
keep_items={"portal_status_message": msg})
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>batch=False</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_generateCloudContract</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# XXX TODO cloud contract is not global to ERP5, but per virtual master
return True
portal = context.getPortalObject()
if not portal.portal_preferences.getPreferredCloudContractEnabled():
return True
person = context
contract_portal_type = "Cloud Contract"
contract = portal.portal_catalog.getResultValue(
portal_type=contract_portal_type,
default_destination_section_uid=person.getUid(),
validation_state='validated',
)
if (contract is not None) and (contract.getValidationState() == "validated"):
return True
else:
return False
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_isAllowedToAllocate</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -11,7 +11,8 @@ from DateTime import DateTime
def convertCategoryList(base, l):
return ['%s/%s' % (base, q) for q in l]
class TestSlapOSSalePackingListBuilder(SlapOSTestCaseMixin):
class TestSlapOSBuilderMixin(SlapOSTestCaseMixin):
def checkSimulationMovement(self, simulation_movement):
self.assertEqual(1.0, simulation_movement.getDeliveryRatio())
......@@ -88,6 +89,9 @@ class TestSlapOSSalePackingListBuilder(SlapOSTestCaseMixin):
+ category_list,
delivery.getCategoryList())
class TestSlapOSSalePackingListBuilder(TestSlapOSBuilderMixin):
def test(self):
resource, _, _, _, _, instance_tree = self.bootstrapAllocableInstanceTree(is_accountable=True)
project = instance_tree.getFollowUpValue()
......@@ -172,7 +176,7 @@ class TestSlapOSSalePackingListBuilder(SlapOSTestCaseMixin):
self.checkDelivery(simulation_movement_2, delivery_2, **delivery_kw)
class TestSlapOSSaleInvoiceBuilder(TestSlapOSSalePackingListBuilder):
class TestSlapOSSaleInvoiceBuilder(TestSlapOSBuilderMixin):
def test(self, causality1=None, causality2=None): # pylint: disable=arguments-differ
resource, _, _, _, _, instance_tree = self.bootstrapAllocableInstanceTree(is_accountable=True)
......@@ -1105,7 +1109,7 @@ class TestSlapOSSaleInvoiceBuilder(TestSlapOSSalePackingListBuilder):
)
class TestSlapOSSaleInvoiceTransactionBuilder(TestSlapOSSalePackingListBuilder):
class TestSlapOSSaleInvoiceTransactionBuilder(TestSlapOSBuilderMixin):
def checkSimulationMovement(self, simulation_movement):
self.assertNotEqual(0.0, simulation_movement.getDeliveryRatio())
self.assertEqual(0.0, simulation_movement.getDeliveryError())
......@@ -1635,7 +1639,7 @@ class TestSlapOSSaleInvoiceTransactionBuilder(TestSlapOSSalePackingListBuilder):
self.assertEqual('solved', invoice_2.getCausalityState())
self.assertEqual('confirmed', invoice_2.getSimulationState())
class TestSlapOSSaleInvoiceTransactionTradeModelBuilder(TestSlapOSSalePackingListBuilder):
class TestSlapOSSaleInvoiceTransactionTradeModelBuilder(TestSlapOSBuilderMixin):
def checkSimulationMovement(self, simulation_movement):
self.assertNotEqual(0.0, simulation_movement.getDeliveryRatio())
self.assertEqual(0.0, simulation_movement.getDeliveryError())
......
# Copyright (c) 2013 Nexedi SA and Contributors. All Rights Reserved.
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin
class TestSlapOSRequestValidationPayment(SlapOSTestCaseMixin):
def test_alarm_software_instance_unallocated(self):
self._makeTree()
preference = self.portal.portal_preferences.getActiveSystemPreference()
preference.setPreferredCloudContractEnabled(True)
self.tic()
script_name = "SoftwareInstance_requestValidationPayment"
alarm = self.portal.portal_alarms.slapos_contract_request_validation_payment
self._test_alarm(
alarm, self.software_instance, script_name)
def test_alarm_slave_instance_unallocated(self):
self._makeSlaveTree()
preference = self.portal.portal_preferences.getActiveSystemPreference()
preference.setPreferredCloudContractEnabled(True)
self.tic()
script_name = "SoftwareInstance_requestValidationPayment"
alarm = self.portal.portal_alarms.slapos_contract_request_validation_payment
self._test_alarm(
alarm, self.software_instance, script_name)
def test_alarm_software_instance_unallocated_disable_cloud_contract(self):
self._makeTree()
preference = self.portal.portal_preferences.getActiveSystemPreference()
preference.setPreferredCloudContractEnabled(False)
self.tic()
script_name = "SoftwareInstance_requestValidationPayment"
alarm = self.portal.portal_alarms.slapos_contract_request_validation_payment
self._test_alarm_not_visited(
alarm, self.software_instance, script_name)
def test_alarm_slave_instance_unallocated_disable_cloud_contract(self):
self._makeSlaveTree()
preference = self.portal.portal_preferences.getActiveSystemPreference()
preference.setPreferredCloudContractEnabled(False)
self.tic()
script_name = "SoftwareInstance_requestValidationPayment"
alarm = self.portal.portal_alarms.slapos_contract_request_validation_payment
self._test_alarm_not_visited(
alarm, self.software_instance, script_name)
def test_alarm_software_instance_allocated(self):
self._makeTree()
preference = self.portal.portal_preferences.getActiveSystemPreference()
preference.setPreferredCloudContractEnabled(True)
self.tic()
self._makeComputeNode()
self.software_instance.setAggregate(self.partition.getRelativeUrl())
self.tic()
script_name = "SoftwareInstance_requestValidationPayment"
alarm = self.portal.portal_alarms.slapos_contract_request_validation_payment
self._test_alarm_not_visited(
alarm, self.software_instance, script_name)
def test_alarm_slave_instance_allocated(self):
self._makeSlaveTree()
preference = self.portal.portal_preferences.getActiveSystemPreference()
preference.setPreferredCloudContractEnabled(True)
self.tic()
self._makeComputeNode()
self.software_instance.setAggregate(self.partition.getRelativeUrl())
self.tic()
script_name = "SoftwareInstance_requestValidationPayment"
alarm = self.portal.portal_alarms.slapos_contract_request_validation_payment
self._test_alarm_not_visited(
alarm, self.software_instance, script_name)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testSlapOSContractAlarm</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testSlapOSContractAlarm</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# Copyright (c) 2013 Nexedi SA and Contributors. All Rights Reserved.
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixinWithAbort, simulate
from DateTime import DateTime
from zExceptions import Unauthorized
class TestSlapOSSoftwareInstance_requestValidationPayment(SlapOSTestCaseMixinWithAbort):
def createCloudContract(self):
new_id = self.generateNewId()
contract = self.portal.cloud_contract_module.newContent(
portal_type='Cloud Contract',
title="Contract %s" % new_id,
reference="TESTCONTRACT-%s" % new_id,
)
self.portal.portal_workflow._jumpToStateFor(contract, 'invalidated')
return contract
def createPaymentTransaction(self):
new_id = self.generateNewId()
return self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Payment %s" % new_id,
reference="TESTPAY-%s" % new_id,
)
def createInvoiceTransaction(self):
new_id = self.generateNewId()
return self.portal.accounting_module.newContent(
portal_type='Sale Invoice Transaction',
title="Invoice %s" % new_id,
reference="TESTINV-%s" % new_id,
created_by_builder=1,
)
def createNeededDocuments(self):
new_id = self.generateNewId()
person = self.portal.person_module.newContent(
portal_type='Person',
title="Person %s" % new_id,
reference="TESTPERS-%s" % new_id,
)
subscription = self.portal.instance_tree_module.newContent(
portal_type='Instance Tree',
title="Subscription %s" % new_id,
reference="TESTSUB-%s" % new_id,
destination_section_value=person,
)
instance = self.portal.software_instance_module.newContent(
portal_type='Software Instance',
title="Instance %s" % new_id,
reference="TESTINST-%s" % new_id,
specialise_value=subscription,
)
return person, instance, subscription
def test_requestValidationPayment_REQUEST_disallowed(self):
_, instance, _ = self.createNeededDocuments()
self.assertRaises(
Unauthorized,
instance.SoftwareInstance_requestValidationPayment,
REQUEST={})
def test_prevent_concurrency(self):
person, instance, _ = self.createNeededDocuments()
tag = "%s_requestValidationPayment_inProgress" % person.getUid()
person.reindexObject(activate_kw={'tag': tag})
self.commit()
result = instance.SoftwareInstance_requestValidationPayment()
self.assertEqual(result, None)
def test_addCloudContract(self):
person, instance, _ = self.createNeededDocuments()
contract = instance.SoftwareInstance_requestValidationPayment()
# Default property
self.assertEqual(contract.getPortalType(), 'Cloud Contract')
self.assertEqual(contract.getValidationState(), 'invalidated')
self.assertEqual(contract.getDestinationSection(), person.getRelativeUrl())
self.assertEqual(contract.getTitle(),
'Contract for "%s"' % person.getTitle())
def test_addCloudContract_do_not_duplicate_contract_if_not_reindexed(self):
_, instance, _ = self.createNeededDocuments()
contract = instance.SoftwareInstance_requestValidationPayment()
self.commit()
contract2 = instance.SoftwareInstance_requestValidationPayment()
self.assertNotEqual(contract, None)
self.assertEqual(contract2, None)
def test_addCloudContract_existing_invalidated_contract(self):
_, instance, _ = self.createNeededDocuments()
contract = instance.SoftwareInstance_requestValidationPayment()
self.commit()
self.tic()
contract2 = instance.SoftwareInstance_requestValidationPayment()
self.assertNotEqual(contract, None)
self.assertEqual(contract2.getRelativeUrl(), contract.getRelativeUrl())
def test_addCloudContract_existing_validated_contract(self):
_, instance, _ = self.createNeededDocuments()
contract = instance.SoftwareInstance_requestValidationPayment()
contract.validate()
self.commit()
self.tic()
contract2 = instance.SoftwareInstance_requestValidationPayment()
self.assertNotEqual(contract, None)
self.assertEqual(contract2.getRelativeUrl(), contract.getRelativeUrl())
def test_do_nothing_if_validated_contract(self):
person, instance, _ = self.createNeededDocuments()
contract = self.createCloudContract()
contract.edit(destination_section_value=person)
contract.validate()
self.tic()
contract2 = instance.SoftwareInstance_requestValidationPayment()
self.assertEqual(contract2.getRelativeUrl(), contract.getRelativeUrl())
self.assertEqual(contract2.getCausality(""), "")
self.assertEqual(contract2.getValidationState(), "validated")
def test_validate_contract_if_payment_found(self):
person, instance, _ = self.createNeededDocuments()
contract = self.createCloudContract()
contract.edit(destination_section_value=person)
payment = self.createPaymentTransaction()
payment.edit(
default_destination_section_value=person,
)
self.portal.portal_workflow._jumpToStateFor(payment, 'stopped')
self.assertEqual(contract.getValidationState(), "invalidated")
self.tic()
contract2 = instance.SoftwareInstance_requestValidationPayment()
self.assertEqual(contract2.getRelativeUrl(), contract.getRelativeUrl())
self.assertEqual(contract2.getCausality(""), "")
self.assertEqual(contract2.getValidationState(), "validated")
def test_do_nothing_if_invoice_is_ongoing(self):
person, instance, _ = self.createNeededDocuments()
contract = self.createCloudContract()
invoice = self.createInvoiceTransaction()
self.portal.portal_workflow._jumpToStateFor(invoice, 'confirmed')
contract.edit(
destination_section_value=person,
causality_value=invoice,
)
self.assertEqual(contract.getValidationState(), "invalidated")
self.tic()
contract2 = instance.SoftwareInstance_requestValidationPayment()
self.assertEqual(contract2.getRelativeUrl(), contract.getRelativeUrl())
self.assertEqual(contract2.getCausality(""), invoice.getRelativeUrl())
self.assertEqual(contract2.getValidationState(), "invalidated")
def test_dont_forget_current_grouped_invoice(self):
person, instance, _ = self.createNeededDocuments()
contract = self.createCloudContract()
invoice = self.createInvoiceTransaction()
line = invoice.newContent(
portal_type="Sale Invoice Transaction Line",
source="account_module/receivable",
grouping_reference="foo",
)
line.getSourceValue().getAccountType()
self.portal.portal_workflow._jumpToStateFor(invoice, 'stopped')
contract.edit(
destination_section_value=person,
causality_value=invoice,
)
self.assertEqual(contract.getValidationState(), "invalidated")
self.tic()
contract2 = instance.SoftwareInstance_requestValidationPayment()
self.assertEqual(contract2.getRelativeUrl(), contract.getRelativeUrl())
self.assertEqual(contract2.getCausality(""), invoice.getRelativeUrl())
self.assertEqual(contract2.getValidationState(), "invalidated")
def test_do_nothing_if_invoice_is_not_grouped(self):
person, instance, _ = self.createNeededDocuments()
contract = self.createCloudContract()
invoice = self.createInvoiceTransaction()
invoice.newContent(
portal_type="Sale Invoice Transaction Line",
source="account_module/receivable",
)
self.portal.portal_workflow._jumpToStateFor(invoice, 'stopped')
contract.edit(
destination_section_value=person,
causality_value=invoice,
)
self.assertEqual(contract.getValidationState(), "invalidated")
self.tic()
contract2 = instance.SoftwareInstance_requestValidationPayment()
self.assertEqual(contract2.getRelativeUrl(), contract.getRelativeUrl())
self.assertEqual(contract2.getCausality(""), invoice.getRelativeUrl())
self.assertEqual(contract2.getValidationState(), "invalidated")
class TestSlapOSPerson_isAllowedToAllocate(SlapOSTestCaseMixinWithAbort):
def createPerson(self):
new_id = self.generateNewId()
return self.portal.person_module.newContent(
portal_type='Person',
title="Person %s" % new_id,
reference="TESTPERS-%s" % new_id,
)
def createCloudContract(self):
new_id = self.generateNewId()
return self.portal.cloud_contract_module.newContent(
portal_type='Cloud Contract',
title="Contract %s" % new_id,
reference="TESTCONTRACT-%s" % new_id,
)
def test_not_allowed_by_default(self):
preference = self.portal.portal_preferences.getActiveSystemPreference()
person = self.createPerson()
preference.setPreferredCloudContractEnabled(True)
result = person.Person_isAllowedToAllocate()
self.assertEqual(result, False)
def test_not_allowed_by_default_with_disabled_preference(self):
preference = self.portal.portal_preferences.getActiveSystemPreference()
person = self.createPerson()
# If Contract is disabled, anyone can allocate
preference.setPreferredCloudContractEnabled(False)
result = person.Person_isAllowedToAllocate()
self.assertEqual(result, True)
def test_allowed_if_has_a_validated_contract(self):
preference = self.portal.portal_preferences.getActiveSystemPreference()
person = self.createPerson()
contract = self.createCloudContract()
contract.edit(
destination_section_value=person
)
self.portal.portal_workflow._jumpToStateFor(contract, 'validated')
preference.setPreferredCloudContractEnabled(True)
self.tic()
result = person.Person_isAllowedToAllocate()
self.assertEqual(result, True)
def test_allowed_if_has_a_validated_contract_with_disabled_preference(self):
preference = self.portal.portal_preferences.getActiveSystemPreference()
person = self.createPerson()
contract = self.createCloudContract()
contract.edit(
destination_section_value=person
)
self.portal.portal_workflow._jumpToStateFor(contract, 'validated')
preference.setPreferredCloudContractEnabled(0)
self.tic()
result = person.Person_isAllowedToAllocate()
# If Contract is disabled, anyone can allocate
self.assertEqual(result, True)
def test_not_allowed_if_has_an_invalidated_contract(self):
preference = self.portal.portal_preferences.getActiveSystemPreference()
person = self.createPerson()
contract = self.createCloudContract()
contract.edit(
destination_section_value=person
)
self.portal.portal_workflow._jumpToStateFor(contract, 'invalidated')
preference.setPreferredCloudContractEnabled(True)
self.tic()
result = person.Person_isAllowedToAllocate()
self.assertEqual(result, False)
def test_not_allowed_if_has_an_invalidated_contract_with_disabled_preference(self):
preference = self.portal.portal_preferences.getActiveSystemPreference()
person = self.createPerson()
contract = self.createCloudContract()
contract.edit(
destination_section_value=person
)
self.portal.portal_workflow._jumpToStateFor(contract, 'invalidated')
preference.setPreferredCloudContractEnabled(False)
self.tic()
result = person.Person_isAllowedToAllocate()
# If Contract is disabled, anyone can allocate
self.assertEqual(result, True)
def test_not_allowed_if_no_related_contract(self):
preference = self.portal.portal_preferences.getActiveSystemPreference()
person = self.createPerson()
contract = self.createCloudContract()
preference.setPreferredCloudContractEnabled(True)
self.portal.portal_workflow._jumpToStateFor(contract, 'validated')
self.tic()
result = person.Person_isAllowedToAllocate()
self.assertEqual(result, False)
def test_not_allowed_if_no_related_contract_with_disabled_preference(self):
preference = self.portal.portal_preferences.getActiveSystemPreference()
person = self.createPerson()
contract = self.createCloudContract()
preference.setPreferredCloudContractEnabled(0)
self.portal.portal_workflow._jumpToStateFor(contract, 'validated')
self.tic()
result = person.Person_isAllowedToAllocate()
# If Contract is disabled, anyone can allocate
self.assertEqual(result, True)
class TestSlapOSEntity_statSlapOSOutstandingAmount(SlapOSTestCaseMixinWithAbort):
def createPerson(self):
new_id = self.generateNewId()
return self.portal.person_module.newContent(
portal_type='Person',
title="Person %s" % new_id,
reference="TESTPERS-%s" % new_id,
)
def createCloudContract(self):
new_id = self.generateNewId()
return self.portal.cloud_contract_module.newContent(
portal_type='Cloud Contract',
title="Contract %s" % new_id,
reference="TESTCONTRACT-%s" % new_id,
)
@simulate("Entity_statOutstandingAmount", "*args, **kwargs",
"return 'simulated_result'")
def test_outstanding_amount_missing_cloud_contract(self):
person = self.createPerson()
self.assertEqual('simulated_result',
person.Entity_statSlapOSOutstandingAmount())
@simulate("Entity_statOutstandingAmount", "*args, **kwargs",
"return None")
def test_outstanding_with_cloud_contract_but_no_amount(self):
person = self.createPerson()
cloud_contract = self.createCloudContract()
cloud_contract.setDestinationSection(person.getRelativeUrl())
cloud_contract.validate()
# Provide contract w/o indexation
self.assertEqual(None,
person.Entity_statSlapOSOutstandingAmount(contract=cloud_contract))
self.tic()
# Provide contract w/o indexation
self.assertEqual(None,
person.Entity_statSlapOSOutstandingAmount())
@simulate("Entity_statOutstandingAmount", "*args, **kwargs",
"return kwargs.get('at_date', 195.0)")
def test_outstanding_with_cloud_contract_but_no_line(self):
person = self.createPerson()
cloud_contract = self.createCloudContract()
cloud_contract.setDestinationSection(person.getRelativeUrl())
cloud_contract.validate()
self.tic()
# Without Lines the result uses at_date
at_date=DateTime()
self.assertEqual(at_date,
person.Entity_statSlapOSOutstandingAmount(at_date=at_date))
@simulate("Entity_statOutstandingAmount", "at_date=None, resource_uid=None",
"""
from DateTime import DateTime
assert at_date in (None, DateTime().earliestTime()-1)
if at_date == DateTime().earliestTime()-1:
return -999
if resource_uid in (None, context.currency_module.EUR.getUid()):
return 195.0
else:
return 0""")
def test_outstanding_with_cloud_contract_with_linein_euro(self):
person = self.createPerson()
cloud_contract = self.createCloudContract()
cloud_contract.setDestinationSection(person.getRelativeUrl())
cloud_contract.validate()
line = cloud_contract.newContent(
price_currency_value=self.portal.currency_module.CNY,
maximum_invoice_credit=10.0
)
self.tic()
# Without Lines the result uses at_date
self.assertEqual(195.0,
person.Entity_statSlapOSOutstandingAmount())
line.edit(
price_currency_value=self.portal.currency_module.EUR,
)
# Without Lines the result uses at_date
self.assertEqual(185.0,
person.Entity_statSlapOSOutstandingAmount())
line.setMaximumInvoiceCredit(200)
# Without Lines the result uses at_date
self.assertEqual(195.0,
person.Entity_statSlapOSOutstandingAmount())
# We need at least one day
cloud_contract.setMaximumInvoiceDelay(1)
self.pinDateTime(DateTime().earliestTime())
self.addCleanup(self.unpinDateTime)
# Without Lines the result uses at_date
self.assertEqual(-999,
person.Entity_statSlapOSOutstandingAmount())
self.unpinDateTime()
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testSlapOSContractSkins</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testSlapOSContractSkins</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -8,8 +8,6 @@ Consumption Document Module | view
Hosting Subscription | periodicity
Instance Tree | jump_to_related_open_order_line
Payment Transaction | related_payzen_event
Person | create_new_cloud_contract
Person | jump_to_cloud_contract
Root Applied Rule Causality Causality Movement Group | view
Sale Invoice Transaction | create_slapos_reversal
Sale Packing List | jump_related_aggregated_packing_list
......
test.erp5.testSlapOSConsumptionSkins
test.erp5.testSlapOSSaleSupply
test.erp5.testSlapOSAccountingConstraint
test.erp5.testSlapOSAccountingRule
test.erp5.testSlapOSAccountingAlarm
test.erp5.testSlapOSAccountingBuilder
test.erp5.testSlapOSContractSkins
test.erp5.testSlapOSAccountingConstraint
test.erp5.testSlapOSAccountingInteractionWorkflow
test.erp5.testSlapOSAccountingRule
test.erp5.testSlapOSAccountingSkins
test.erp5.testSlapOSAccountingAlarm
test.erp5.testSlapOSContractAlarm
test.erp5.testSlapOSEntityCreatePayment
\ No newline at end of file
test.erp5.testSlapOSConsumptionSkins
test.erp5.testSlapOSEntityCreatePayment
test.erp5.testSlapOSSaleSupply
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment