Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Titouan Soulard
slapos.core
Commits
371645ab
Commit
371645ab
authored
Mar 24, 2023
by
Romain Courteaud
🐸
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
slapos_subscription_request: add testSlapOSERP5VirtualMasterSubscriptionRequestScenario
parent
41b77d45
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
611 additions
and
11 deletions
+611
-11
master/bt5/slapos_subscription_request/TestTemplateItem/portal_components/test.erp5.testSlapOSERP5VirtualMasterSubscriptionRequestScenario.py
...testSlapOSERP5VirtualMasterSubscriptionRequestScenario.py
+487
-0
master/bt5/slapos_subscription_request/TestTemplateItem/portal_components/test.erp5.testSlapOSERP5VirtualMasterSubscriptionRequestScenario.xml
...estSlapOSERP5VirtualMasterSubscriptionRequestScenario.xml
+112
-0
master/bt5/slapos_subscription_request/bt/template_test_id_list
.../bt5/slapos_subscription_request/bt/template_test_id_list
+12
-11
No files found.
master/bt5/slapos_subscription_request/TestTemplateItem/portal_components/test.erp5.testSlapOSERP5VirtualMasterSubscriptionRequestScenario.py
0 → 100644
View file @
371645ab
# -*- 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
TestSlapOSVirtualMasterSubscriptionRequestScenario
(
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
addSaleManagerAssignment
(
self
,
person
):
person
.
newContent
(
portal_type
=
'Assignment'
,
function
=
'function/sale/manager'
).
open
()
def
createSaleAdministrator
(
self
,
web_site
):
self
.
logout
()
login
=
'sale-%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
.
addSaleManagerAssignment
(
person
)
# Remove customer project assignment
#person.manage_delObjects(ids=[x.getId() for x in person.contentValues(portal_type="Assignment") if x.getFunction() == 'customer'])
self
.
tic
()
return
person
"""
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
,
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
bootstrapSubscriptionRequestScenario
(
self
):
# Done by ERP5 admin?
# XXX XXX to drop. First project is created on UI
self
.
web_site
=
self
.
portal
.
web_site_module
.
slapos_master_panel
web_site
=
self
.
web_site
sale_person
=
self
.
createSaleAdministrator
(
web_site
)
currency
=
self
.
portal
.
currency_module
.
newContent
(
portal_type
=
'Currency'
,
title
=
"fake currency"
)
currency
.
validate
()
return
web_site
,
currency
,
sale_person
def
test_virtual_master_subscribe_to_project
(
self
):
_
,
currency
,
sale_person
=
self
.
bootstrapSubscriptionRequestScenario
()
self
.
tic
()
#################################
# Prepare saling virtual master
#################################
self
.
logout
()
self
.
login
(
sale_person
.
getUserId
())
now
=
DateTime
()
seller_organisation
=
self
.
portal
.
organisation_module
.
newContent
(
portal_type
=
"Organisation"
,
title
=
"seller-orga"
)
seller_organisation
.
validate
()
sale_person
.
setCareerSubordinationValue
(
seller_organisation
)
internal_trade_condition
=
self
.
portal
.
sale_trade_condition_module
.
newContent
(
portal_type
=
"Sale Trade Condition"
,
reference
=
'internal_for_%s'
%
seller_organisation
.
getTitle
(),
# XXX hardcoded
specialise
=
"business_process_module/slapos_ultimate_business_process"
,
source_value
=
seller_organisation
,
source_section_value
=
seller_organisation
,
destination_section_value
=
seller_organisation
,
effective_date
=
now
.
earliestTime
(),
price_currency_value
=
currency
)
internal_trade_condition
.
validate
()
"""
virtual_master_sale_supply = self.portal.sale_supply_module.newContent(
portal_type="Sale Supply"
)
virtual_master_sale_supply.validate()
"""
self
.
tic
()
#################################
# Buy the first project
#################################
# XXX How to list possible service to sell?
# Search product with `time` unit ?
service
=
self
.
portal
.
restrictedTraverse
(
'service_module/slapos_virtual_master_subscription'
)
# XXX This is a script like: Product_submitSubscriptionRequest()
source_decision_value
=
self
.
portal
.
portal_membership
.
getAuthenticatedMember
().
getUserValue
()
source_section_value
=
seller_organisation
#source_decision_value#source_decision_value.getCareerSubordinationValue() or source_decision_value
source_section_value
=
source_decision_value
.
getCareerSubordinationValue
(
source_decision_value
)
# Find trade condition / price
order_portal_type
=
'Sale Order'
line_portal_type
=
'Sale Order Line'
#cell_portal_type = 'Sale Order Cell'
#base_id = 'movement'
module
=
self
.
portal
.
sale_order_module
temp_order
=
1
#aggregate_value_list = []
open_sale_order
=
module
.
newContent
(
portal_type
=
order_portal_type
,
temp_object
=
temp_order
,
#effective_date=now+1,
start_date
=
now
,
# Ensure stop date value is higher than start date
# it will be updated by OpenSaleOrder_updatePeriod
# stop_date=now + 2,
destination_value
=
source_decision_value
,
destination_section_value
=
source_section_value
,
#destination_decision_value=source_decision_value,
ledger_value
=
self
.
portal
.
portal_categories
.
ledger
.
automated
,
# XXX XXX destination_project_value=instance_tree.getFollowUpValue(),
)
"""
resource_vcl = [
'software_release/%s' % software_release.getRelativeUrl(),
'software_type/%s' % software_type.getRelativeUrl()
]
resource_vcl.sort()
assert len(resource_vcl) == 2, service
"""
# Add lines
open_order_line
=
open_sale_order
.
newContent
(
portal_type
=
line_portal_type
,
temp_object
=
temp_order
,
resource_value
=
service
,
#variation_category_list=resource_vcl,
quantity_unit
=
service
.
getQuantityUnit
(),
base_contribution_list
=
service
.
getBaseContributionList
(),
use
=
service
.
getUse
(),
# stop_date=calculateOpenOrderLineStopDate(open_sale_order_line,
# instance_tree, start_date_delta=start_date_delta),
#activate_kw=activate_kw
quantity
=
1
)
"""
subscription_request = instance_tree.getAggregateRelatedValue(portal_type="Subscription Request")
# Define the start date of the period, this can variates with the time.
# start_date_delta = 0
if subscription_request is not None:
# Quantity is double because the first invoice has to
# charge for 2 months
edit_kw['quantity'] = subscription_request.getQuantity()
"""
"""
cell_key = list(open_order_line.getCellKeyList(base_id=base_id))[0]
open_order_cell = open_order_line.newCell(
base_id=base_id,
portal_type=cell_portal_type,
temp_object=temp_order,
*cell_key
)
open_order_cell.edit(
mapped_value_property_list=['price','quantity'],
quantity=1,
predicate_category_list=cell_key,
variation_category_list=cell_key,
aggregate_value_list=aggregate_value_list,
activate_kw=activate_kw
)
"""
open_sale_order
.
SaleOrder_applySaleTradeCondition
(
batch_mode
=
1
,
force
=
1
)
price
=
open_order_line
.
getPrice
()
open_order_line
.
edit
(
price
=
price
)
subscription_request
=
self
.
portal
.
subscription_request_module
.
newContent
(
portal_type
=
'Subscription Request'
,
source_value
=
source_decision_value
,
source_section_value
=
source_section_value
,
source_decision_value
=
source_decision_value
,
start_date
=
now
,
effective_date
=
now
,
resource_value
=
service
,
quantity_unit_value
=
open_order_line
.
getQuantityUnitValue
(),
ledger
=
"automated"
,
specialise_value
=
open_sale_order
.
getSpecialiseValue
(),
destination_value
=
open_sale_order
.
getSourceValue
(),
destination_section_value
=
open_sale_order
.
getSourceSectionValue
(),
price_currency_value
=
open_sale_order
.
getPriceCurrencyValue
()
)
"""
invoicing_type=invoicing_type,
number_tag=number_tag,
number_clip=number_clip,
insured_vehicle_count=insured_vehicle_count,
license_plate_number_list=license_plate_number_list,
free_subscription_dict_json=dumps(free_subscription_dict_json),
promotion_code=promotion_code,
member_reference=member_reference,
role=role,
company_title=company_title,
vat_code=vat_code,
social_title=social_title,
first_name=first_name,
last_name=last_name,
date_of_birth=date_of_birth,
default_email_text=default_email_text,
mobile_telephone_telephone_country=mobile_telephone_telephone_country,
mobile_telephone_telephone_number=mobile_telephone_text,
default_telephone_telephone_country=default_telephone_telephone_country,
default_address_zip_code=default_address_zip_code,
default_address_street_address='
\
n
'.join((default_address_text2, default_address_text3, default_address_text1, default_address_text4)),
default_address_city=default_address_city,
default_address_region=default_address_region or None,
language=language,
client_address=request.getClientAddr(),
destination_reference=destination_reference,
accept_opteven_info=accept_opteven_info,
delivery_mode=delivery_mode,
price_list_json=dumps(price_list),
source_reference=tag_reference, # to lookup by catalog
pack_reference=pack_reference,
# Following fields are hidden and autocompleted by DQE result.
# So it is not passed in the parameters and we read it be REQUEST form
default_address_autocompleted=bool(int(request_form.get('field_your_default_address_autocompleted', "0"))),
delivery_address_autocompleted=has_delivery_address and bool(int(request_form.get('field_your_delivery_address_autocompleted', "0"))),
)
"""
subscription_request
.
submit
()
self
.
tic
()
#payment_transaction = None
self
.
logout
()
self
.
login
()
#################################
# Alarm / Sale Person validate the request
#################################
item
=
self
.
portal
.
project_module
.
newContent
(
portal_type
=
"Project"
,
title
=
"new title"
,
)
item
.
validate
()
subscription_request
.
getSourceDecisionValue
().
newContent
(
portal_type
=
"Assignment"
,
destination_project_value
=
item
,
function
=
'production/manager'
).
open
()
hosting_subscription
=
self
.
portal
.
hosting_subscription_module
.
newContent
(
portal_type
=
"Hosting Subscription"
,
title
=
"hosting %s"
%
item
.
getTitle
(),
#follow_up_value=instance_tree.getFollowUpValue(),
ledger_value
=
self
.
portal
.
portal_categories
.
ledger
.
automated
,
)
hosting_subscription
.
validate
()
start_date
=
hosting_subscription
.
HostingSubscription_calculateSubscriptionStartDate
()
open_sale_order
=
self
.
portal
.
open_sale_order_module
.
newContent
(
portal_type
=
"Open Sale Order"
,
start_date
=
start_date
,
# Ensure stop date value is higher than start date
# it will be updated by OpenSaleOrder_updatePeriod
stop_date
=
start_date
+
1
,
specialise_value
=
subscription_request
.
getSpecialiseValue
(),
destination_value
=
subscription_request
.
getSourceValue
(),
destination_section_value
=
subscription_request
.
getSourceSectionValue
(),
destination_decision_value
=
subscription_request
.
getSourceDecisionValue
(),
ledger_value
=
self
.
portal
.
portal_categories
.
ledger
.
automated
,
causality_value
=
subscription_request
)
open_sale_order
.
SaleOrder_applySaleTradeCondition
(
batch_mode
=
1
)
# Add lines
service
=
subscription_request
.
getResourceValue
()
open_order_line
=
open_sale_order
.
newContent
(
portal_type
=
"Open Sale Order Line"
,
resource_value
=
service
,
#variation_category_list=resource_vcl,
quantity_unit_value
=
subscription_request
.
getQuantityUnitValue
(),
base_contribution_list
=
service
.
getBaseContributionList
(),
use
=
service
.
getUse
(),
# stop_date=calculateOpenOrderLineStopDate(open_sale_order_line,
# instance_tree, start_date_delta=start_date_delta),
#activate_kw=activate_kw
quantity
=
1
,
price
=
subscription_request
.
getPrice
(),
aggregate_value_list
=
[
hosting_subscription
,
item
]
)
open_sale_order
.
plan
()
open_sale_order
.
validate
()
subscription_request
.
validate
()
"""
payment_transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
#start_date=context.getStopDate(),
#resource='currency_module/EUR',
#source_section=sanef_fr_relative_url,
#source_payment_value=bank_account,
causality_value=subscription_request,
#specialise_value=direct_debit_mandate,
# destination_section_value=customer,
#destination_payment=direct_debit_mandate.getSourcePayment(),
#payment_mode='direct_debit',
ledger="automated",
created_by_builder=1, # XXX this prevent init script from creating lines.
#activate_kw={'tag':'%s_init' % context.getDestinationReference()}
)
"""
"""
getAccountForUse = context.Base_getAccountForUse
# receivable
payment_transaction.newContent(
id='receivable',
portal_type='Accounting Transaction Line',
quantity=total_price,
source_value=getAccountForUse('asset_receivable_subscriber'),
)
# bank
payment_transaction.newContent(
id='bank',
portal_type='Accounting Transaction Line',
quantity=-total_price,
source_value=getAccountForUse('collection'),
aggregate_value=payment_transaction_group_value,
)
tag = '%s_update' % context.getDestinationReference()
payment_transaction.confirm(activate_kw={'tag': tag})
payment_transaction.activate(after_tag=tag).stop()
"""
#assert payment_transaction is not None
#################################
# And finally, allow customer to buy a virtual master
#################################
# virtual master subscription is NOT PUBLIC (too complex for anonymous?)
"""
customer, _ = self.createProjectCustomer(web_site)
self.logout()
self.login(customer.getUserId())
"""
self
.
logout
()
for
_
in
range
(
20
):
self
.
stepCallAlarmList
()
self
.
tic
()
self
.
login
()
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
\ No newline at end of file
master/bt5/slapos_subscription_request/TestTemplateItem/portal_components/test.erp5.testSlapOSERP5VirtualMasterSubscriptionRequestScenario.xml
0 → 100644
View file @
371645ab
<?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>
testSlapOSERP5VirtualMasterSubscriptionRequestScenario
</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.testSlapOSERP5VirtualMasterSubscriptionRequestScenario
</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>
master/bt5/slapos_subscription_request/bt/template_test_id_list
View file @
371645ab
test.erp5.testSlapOSERP5VirtualMasterSubscriptionRequestScenario
test.erp5.testSlapOSSubscriptionAlarm
test.erp5.testSlapOSSubscriptionSkins
test.erp5.testSlapOSSubscriptionScenario
test.erp5.testSlapOSSubscriptionCDNChineseScenario
test.erp5.testSlapOSSubscriptionCDNScenario
test.erp5.testSlapOSSubscriptionCancellationScenario
test.erp5.testSlapOSSubscriptionChineseScenario
test.erp5.testSlapOSSubscriptionNewTemplateScenario
test.erp5.testSlapOSSubscriptionNewTemplateChineseScenario
test.erp5.testSlapOSSubscriptionInvitationTokenScenario
test.erp5.testSlapOSSubscriptionDualOrganisationScenario
test.erp5.testSlapOSSubscriptionInvitationTokenChineseScenario
test.erp5.testSlapOSSubscriptionSecondMonthPaymentScenario
test.erp5.testSlapOSSubscriptionInvitationTokenScenario
test.erp5.testSlapOSSubscriptionNewTemplateChineseScenario
test.erp5.testSlapOSSubscriptionNewTemplateScenario
test.erp5.testSlapOSSubscriptionPerUserTradeConditionScenario
test.erp5.testSlapOSSubscriptionScenario
test.erp5.testSlapOSSubscriptionSecondMonthPaymentChineseScenario
test.erp5.testSlapOSSubscriptionDualOrganisationScenario
test.erp5.testSlapOSSubscriptionCancellationScenario
test.erp5.testSlapOSSubscriptionCDNScenario
test.erp5.testSlapOSSubscriptionCDNChineseScenario
test.erp5.testSlapOSSubscriptionPerUserTradeConditionScenario
\ No newline at end of file
test.erp5.testSlapOSSubscriptionSecondMonthPaymentScenario
test.erp5.testSlapOSSubscriptionSkins
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment