Commit f984c301 authored by Romain Courteaud's avatar Romain Courteaud

slapos_erp5:

* testSlapOSERP5VirtualMasterScenario: define bank account
* testSlapOSERP5VirtualMasterScenario: Payment Transaction is not built anymore
* TestSlapOSVirtualMasterScenarioMixin
* wip testSlapOSERP5VirtualMasterInvoicingScenario
parent a49a5362
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2022 Nexedi SA and Contributors. All Rights Reserved.
#
##############################################################################
from erp5.component.test.testSlapOSERP5VirtualMasterScenario import TestSlapOSVirtualMasterScenarioMixin
# from DateTime import DateTime
class TestSlapOSVirtualMasterInvoicingScenario(TestSlapOSVirtualMasterScenarioMixin):
def createAccountableProject(self):
# create a default project
project = self.addProject(is_accountable=True)
self.web_site = self.portal.web_site_module.slapos_master_panel
preference = self.portal.portal_preferences.slapos_default_system_preference
preference.edit(
preferred_subscription_assignment_category_list=[
'function/customer',
'role/client',
'destination_project/%s' % project.getRelativeUrl()
]
)
return project, self.web_site
def createProjectAdministrator(self, project, web_site):
self.logout()
login = 'owner-%s' % self.generateNewId()
self.joinSlapOS(web_site, login)
self.login()
person = self.portal.portal_catalog.getResultValue(
portal_type="ERP5 Login",
reference=login).getParentValue()
# first slapos administrator assignment can only be created by
# the erp5 manager
self.addProjectProductionManagerAssignment(person, project)
self.tic()
return person
def createSoftwareProduct(self, project, person):
self.logout()
self.login(person.getUserId())
software_url = self.generateNewSoftwareReleaseUrl()
software_type = 'public type'
return self.addSoftwareProduct(
"instance product", project, software_url, software_type
)
def createPreparedComputeNode(self, project, person, software_product,
release_variation, type_variation):
self.logout()
self.login(person.getUserId())
server_title = 'Server for %s' % project.getReference()
server_id = self.requestComputeNode(server_title, project.getReference())
server = self.portal.portal_catalog.getResultValue(
portal_type='Compute Node', reference=server_id)
self.setAccessToMemcached(server)
self.assertNotEqual(None, server)
self.setServerOpenPublic(server)
self.addAllocationSupply("for compute node", server, software_product,
release_variation, type_variation)
# and install some software on them
self.supplySoftware(server, release_variation.getUrlString())
# format the compute_nodes
self.formatComputeNode(server)
return server
def createSoftwareProductSaleSupply(self, software_product, price=9):
self.logout()
# XXX Use accountant account
self.login()
project = software_product.getFollowUpValue()
sale_supply = self.portal.sale_supply_module.newContent(
portal_type="Sale Supply",
destination_project_value=project,
price_currency_value=project.getSpecialiseValue().getPriceCurrencyValue()
)
# XXX Put price in sale supply module
sale_supply.newContent(
portal_type="Sale Supply Line",
base_price=price,
resource_value=software_product
)
sale_supply.validate()
def bootstrapInvoicingScenario(self):
# Done by ERP5 admin?
project, web_site = self.createAccountableProject()
# lets join as slapos administrator, which will own few compute_nodes
owner_person = self.createProjectAdministrator(project, web_site)
# create a software product
software_product, release_variation, type_variation = self.createSoftwareProduct(project, owner_person)
# create compute_nodes and prepare it
compute_node = self.createPreparedComputeNode(project, owner_person, software_product,
release_variation, type_variation)
# define price
self.createSoftwareProductSaleSupply(software_product)
return project, web_site, software_product, release_variation, type_variation, compute_node
def createProjectCustomer(self, project, web_site):
# join as the another visitor and request software instance on public
# compute_node
self.logout()
login = 'customer-%s' % self.generateNewId()
self.joinSlapOS(web_site, login)
self.login()
person = self.portal.portal_catalog.getResultValue(
portal_type="ERP5 Login",
reference=login).getParentValue()
return person, login
def test_virtual_master_invoice_grouped_per_user(self):
project, web_site, software_product, release_variation, type_variation, public_server = self.bootstrapInvoicingScenario()
public_server_software = release_variation.getUrlString()
public_instance_type = type_variation.getTitle()
# create a customer
public_person, public_reference = self.createProjectCustomer(project, web_site)
public_instance_title = 'Public title %s' % self.generateNewId()
self.checkInstanceAllocation(public_person.getUserId(),
public_reference, public_instance_title,
public_server_software, public_instance_type,
public_server, project.getReference())
# XXX Do this for every scenario tests
self.logout()
for _ in range(20):
self.stepCallAlarmList()
self.tic()
self.tic()
# XXX Do this for every scenario tests
# XXX Do this for every scenario tests
self.logout()
for _ in range(20):
self.stepCallAlarmList()
self.tic()
self.login()
# Check stock
inventory_list = self.portal.portal_simulation.getCurrentInventoryList(**{
'group_by_section': False,
'group_by_node': True,
'group_by_variation': True,
'resource_uid': software_product.getUid(),
'node_uid': public_person.getUid(),
'project_uid': project.getUid(),
'ledger_uid': self.portal.portal_categories.ledger.automated.getUid()
})
assert len(inventory_list) == 1, len(inventory_list)
assert inventory_list[0].quantity == 1, inventory_list[0].quantity
resource_vcl = [
'software_release/%s' % release_variation.getRelativeUrl(),
'software_type/%s' % type_variation.getRelativeUrl()
]
resource_vcl.sort()
assert inventory_list[0].getVariationCategoryList() == resource_vcl, "%s %s" % (resource_vcl, inventory_list[0].getVariationCategoryList())
# Check accounting
transaction_list = self.portal.account_module.receivable.Account_getAccountingTransactionList(mirror_section_uid=public_person.getUid())
assert len(transaction_list) == 1, len(transaction_list)
assert transaction_list[0].total_price == 10.8, transaction_list[0].total_price
self.login()
# Ensure no unexpected object has been created
# 3 (can reduce to 2) assignment, 1 instance tree, 1 compute node, 1 software installation
# 1 software instance
# 2 credential request
# 1 open order
# 1 hosting subscription
# 1 accounting transaction
# 1 packing list
# 7 simulation mvt
# 1 software product
# 1 sale trace condition
# 1 supply, 1 supply line
# 1 open order line / 1 cell
# 3 allocation supply / line / cell
related_object_list = project.Base_getRelatedObjectList(**{'category.category_strict_membership': 1})
assert len(related_object_list) == 29, '%s %s' % (len(related_object_list), [x.getRelativeUrl() for x in related_object_list])
self.stepcheckERP5Consistency()
# after accept, an email is send containing the reset link
last_message = self.portal.MailHost._last_message
assert last_message is None, last_message
<?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>testSlapOSERP5VirtualMasterInvoicingScenario</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testSlapOSERP5VirtualMasterInvoicingScenario</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>
......@@ -8,7 +8,7 @@
from erp5.component.test.SlapOSTestCaseDefaultScenarioMixin import DefaultScenarioMixin
# from DateTime import DateTime
class TestSlapOSVirtualMasterScenario(DefaultScenarioMixin):
class TestSlapOSVirtualMasterScenarioMixin(DefaultScenarioMixin):
def requestRemoteNode(self, project, remote_project, remote_person):
remote_node = self.portal.compute_node_module.newContent(
......@@ -79,6 +79,20 @@ class TestSlapOSVirtualMasterScenario(DefaultScenarioMixin):
if not_consistent_document is not None:
assert not_consistent_document.checkConsistency() == [], not_consistent_document.checkConsistency()[0]
def addInstanceNode(self, title, software_instance):
instance_node = self.portal.compute_node_module.newContent(
portal_type='Instance Node',
title=title,
specialise_value=software_instance,
follow_up_value=software_instance.getFollowUpValue()
)
instance_node.validate()
return instance_node
class TestSlapOSVirtualMasterScenario(TestSlapOSVirtualMasterScenarioMixin):
def test_virtual_master_without_accounting_scenario(self):
# create a default project
project = self.addProject()
......@@ -359,7 +373,7 @@ class TestSlapOSVirtualMasterScenario(DefaultScenarioMixin):
# 1 open order
# 1 hosting subscription
# 2 accounting transaction
# 1 accounting transaction
# 1 packing list
# 7 simulation mvt
......@@ -370,7 +384,7 @@ class TestSlapOSVirtualMasterScenario(DefaultScenarioMixin):
# 3 allocation supply / line / cell
related_object_list = project.Base_getRelatedObjectList(**{'category.category_strict_membership': 1})
assert len(related_object_list) == 30, [x.getRelativeUrl() for x in related_object_list]
assert len(related_object_list) == 29, '%s %s' % (len(related_object_list), [x.getRelativeUrl() for x in related_object_list])
self.stepcheckERP5Consistency()
......@@ -379,17 +393,6 @@ class TestSlapOSVirtualMasterScenario(DefaultScenarioMixin):
assert last_message is None, last_message
def addInstanceNode(self, title, software_instance):
instance_node = self.portal.compute_node_module.newContent(
portal_type='Instance Node',
title=title,
specialise_value=software_instance,
follow_up_value=software_instance.getFollowUpValue()
)
instance_node.validate()
return instance_node
def test_virtual_master_slave_without_accounting_scenario(self):
# create a default project
project = self.addProject()
......@@ -1081,6 +1084,9 @@ class TestSlapOSVirtualMasterScenario(DefaultScenarioMixin):
organisation = self.portal.organisation_module.newContent(
portal_type="Organisation"
)
bank_account = organisation.newContent(
portal_type="Bank Account"
)
sale_trade_condition = project.getSpecialiseValue()
......@@ -1103,6 +1109,7 @@ class TestSlapOSVirtualMasterScenario(DefaultScenarioMixin):
destination_project_value=project,
source_value=organisation,
source_section_value=organisation,
source_payment_value=bank_account,
destination_value=person,
destination_section_value=person,
destination_decision_value=person,
......@@ -1187,6 +1194,9 @@ class TestSlapOSVirtualMasterScenario(DefaultScenarioMixin):
organisation = self.portal.organisation_module.newContent(
portal_type="Organisation"
)
bank_account = organisation.newContent(
portal_type="Bank Account"
)
sale_trade_condition = project.getSpecialiseValue()
......@@ -1226,6 +1236,7 @@ class TestSlapOSVirtualMasterScenario(DefaultScenarioMixin):
destination_project_value=project,
source_value=organisation,
source_section_value=organisation,
source_payment_value=bank_account,
destination_value=person,
destination_section_value=person,
destination_decision_value=person,
......
......@@ -12,4 +12,8 @@ test.erp5.testSlapOSPrecacheManifest
test.erp5.testSlapOSWendelinCoreTwo
test.erp5.testSlapOSXHTML
test.erp5.testSlapOSPrecacheManifest
test.erp5.testSlapOSERP5VirtualMasterInvoicingScenario
test.erp5.testSlapOSERP5VirtualMasterScenario
test.erp5.testSlapOSPrecacheManifest
test.erp5.testSlapOSWendelinCoreTwo
test.erp5.testSlapOSXHTML
\ 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