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
Labels
Merge Requests
16
Merge Requests
16
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
nexedi
slapos.core
Commits
edef233e
Commit
edef233e
authored
Oct 02, 2024
by
Romain Courteaud
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
slapos_panel: action to change a Subscription price
parent
c1b7e30f
Pipeline
#37252
passed with stage
in 0 seconds
Changes
10
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1215 additions
and
0 deletions
+1215
-0
master/bt5/slapos_erp5/TestTemplateItem/portal_components/test.erp5.testSlapOSCodingStyle.py
...Item/portal_components/test.erp5.testSlapOSCodingStyle.py
+1
-0
master/bt5/slapos_erp5/TestTemplateItem/portal_components/test.erp5.testSlapOSERP5SubscriptionScenario.py
...omponents/test.erp5.testSlapOSERP5SubscriptionScenario.py
+326
-0
master/bt5/slapos_panel/ActionTemplateItem/portal_types/Subscription%20Request/change_slapos_submitted_price.xml
.../Subscription%20Request/change_slapos_submitted_price.xml
+96
-0
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_changeFromPayableToFree.py
...apos_panel/SubscriptionRequest_changeFromPayableToFree.py
+116
-0
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_changeFromPayableToFree.xml
...pos_panel/SubscriptionRequest_changeFromPayableToFree.xml
+62
-0
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_changeSlaposSubmittedPrice.py
...s_panel/SubscriptionRequest_changeSlaposSubmittedPrice.py
+75
-0
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_changeSlaposSubmittedPrice.xml
..._panel/SubscriptionRequest_changeSlaposSubmittedPrice.xml
+62
-0
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_viewChangeSlaposSubmittedPriceDialog.xml
...scriptionRequest_viewChangeSlaposSubmittedPriceDialog.xml
+160
-0
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_viewChangeSlaposSubmittedPriceDialog/your_price.xml
...quest_viewChangeSlaposSubmittedPriceDialog/your_price.xml
+316
-0
master/bt5/slapos_panel/bt/template_action_path_list
master/bt5/slapos_panel/bt/template_action_path_list
+1
-0
No files found.
master/bt5/slapos_erp5/TestTemplateItem/portal_components/test.erp5.testSlapOSCodingStyle.py
View file @
edef233e
...
...
@@ -272,6 +272,7 @@ def makeTestSlapOSCodingStyleTestCase(tested_business_template):
'slapos_panel/SoftwareInstance_getNewsDict'
,
'slapos_panel/SoftwareProduct_addSlapOSSoftwareRelease'
,
'slapos_panel/SoftwareProduct_addSlapOSSoftwareType'
,
'slapos_panel/SubscriptionRequest_changeSlaposSubmittedPrice'
,
'slapos_panel/SubscriptionRequest_jumpToPaymentPage'
,
'slapos_panel/Ticket_addSlapOSEvent'
,
'slapos_panel/Ticket_closeSlapOS'
,
...
...
master/bt5/slapos_erp5/TestTemplateItem/portal_components/test.erp5.testSlapOSERP5SubscriptionScenario.py
View file @
edef233e
...
...
@@ -553,3 +553,329 @@ class TestSlapOSSubscriptionScenario(TestSlapOSSubscriptionScenarioMixin):
# 2 subscription requests
self
.
assertRelatedObjectCount
(
project
,
24
)
self
.
checkERP5StateBeforeExit
()
def
checkInstanceAllocationFromPayableToFree
(
self
,
person_user_id
,
person_reference
,
instance_title
,
software_release
,
software_type
,
server
,
project_reference
,
deposit_amount
,
currency
,
sale_person
):
self
.
login
(
person_user_id
)
self
.
personRequestInstanceNotReady
(
software_release
=
software_release
,
software_type
=
software_type
,
partition_reference
=
instance_title
,
project_reference
=
project_reference
)
self
.
tic
()
instance_tree
=
self
.
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
"Instance Tree"
,
title
=
instance_title
,
follow_up__reference
=
project_reference
)
person
=
instance_tree
.
getDestinationSectionValue
()
self
.
assertEqual
(
person
.
getUserId
(),
person_user_id
)
subscription_request
=
self
.
checkServiceSubscriptionRequest
(
instance_tree
,
'submitted'
)
self
.
assertEqual
(
subscription_request
.
getTotalPrice
(),
deposit_amount
)
self
.
tic
()
outstanding_amount_list
=
person
.
Entity_getOutstandingDepositAmountList
(
currency
.
getUid
(),
ledger_uid
=
subscription_request
.
getLedgerUid
())
self
.
assertEqual
(
sum
([
i
.
total_price
for
i
in
outstanding_amount_list
]),
deposit_amount
)
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
self
.
logout
()
self
.
login
(
sale_person
.
getUserId
())
#previous_trade_condition = subscription_request.getSpecialiseValue()
subscription_request
.
SubscriptionRequest_changeFromPayableToFree
(
None
)
self
.
tic
()
self
.
logout
()
self
.
login
(
person
.
getUserId
())
# Ensure to pay from the website
#outstanding_amount = self.web_site.restrictedTraverse(outstanding_amount_list[0].getRelativeUrl())
#outstanding_amount.Base_createExternalPaymentTransactionFromOutstandingAmountAndRedirect()
self
.
tic
()
self
.
logout
()
self
.
login
()
payment_transaction
=
self
.
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
"Payment Transaction"
,
destination_section_uid
=
person
.
getUid
(),
simulation_state
=
"started"
)
self
.
assertEqual
(
payment_transaction
,
None
)
self
.
login
(
person_user_id
)
self
.
checkServiceSubscriptionRequest
(
instance_tree
,
'cancelled'
)
amount
=
sum
([
i
.
total_price
for
i
in
person
.
Entity_getOutstandingDepositAmountList
(
currency
.
getUid
(),
ledger_uid
=
subscription_request
.
getLedgerUid
())])
self
.
assertEqual
(
0
,
amount
)
self
.
login
(
person_user_id
)
self
.
personRequestInstance
(
software_release
=
software_release
,
software_type
=
software_type
,
partition_reference
=
instance_title
,
project_reference
=
project_reference
)
# now instantiate it on compute_node and set some nice connection dict
self
.
simulateSlapgridCP
(
server
)
# let's find instances of user and check connection strings
instance_tree_list
=
[
q
.
getObject
()
for
q
in
self
.
_getCurrentInstanceTreeList
()
if
q
.
getTitle
()
==
instance_title
]
self
.
assertEqual
(
1
,
len
(
instance_tree_list
))
instance_tree
=
instance_tree_list
[
0
]
software_instance
=
instance_tree
.
getSuccessorValue
()
self
.
assertEqual
(
software_instance
.
getTitle
(),
instance_tree
.
getTitle
())
connection_dict
=
software_instance
.
getConnectionXmlAsDict
()
self
.
assertSameSet
((
'url_1'
,
'url_2'
),
connection_dict
.
keys
())
self
.
login
()
partition
=
software_instance
.
getAggregateValue
()
self
.
assertSameSet
(
[
'http://%s/'
%
q
.
getIpAddress
()
for
q
in
partition
.
contentValues
(
portal_type
=
'Internet Protocol Address'
)],
connection_dict
.
values
())
def
test_virtual_master_with_accounting_scenario_from_payable_to_free
(
self
):
with
PinnedDateTime
(
self
,
DateTime
(
'2024/02/17'
)):
currency
,
_
,
_
,
sale_person
,
_
=
self
.
bootstrapVirtualMasterTest
()
self
.
logout
()
# lets join as slapos administrator, which will manager the project
project_owner_reference
=
'project-%s'
%
self
.
generateNewId
()
self
.
joinSlapOS
(
self
.
web_site
,
project_owner_reference
)
self
.
login
()
project_owner_person
=
self
.
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
"ERP5 Login"
,
reference
=
project_owner_reference
).
getParentValue
()
# owner_person.setCareerSubordinationValue(seller_organisation)
self
.
tic
()
self
.
logout
()
self
.
login
(
sale_person
.
getUserId
())
project_relative_url
=
self
.
addProject
(
is_accountable
=
True
,
person
=
project_owner_person
,
currency
=
currency
)
self
.
logout
()
self
.
login
()
project
=
self
.
portal
.
restrictedTraverse
(
project_relative_url
)
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
()
]
)
public_server_software
=
self
.
generateNewSoftwareReleaseUrl
()
public_instance_type
=
'public type'
software_product
,
release_variation
,
type_variation
=
self
.
addSoftwareProduct
(
"instance product"
,
project
,
public_server_software
,
public_instance_type
)
self
.
logout
()
self
.
login
(
sale_person
.
getUserId
())
sale_supply
=
self
.
portal
.
sale_supply_module
.
newContent
(
portal_type
=
"Sale Supply"
,
title
=
"price for %s"
%
project
.
getRelativeUrl
(),
source_project_value
=
project
,
price_currency_value
=
currency
)
sale_supply
.
newContent
(
portal_type
=
"Sale Supply Line"
,
base_price
=
9
,
resource_value
=
software_product
)
sale_supply
.
newContent
(
portal_type
=
"Sale Supply Line"
,
base_price
=
99
,
resource
=
"service_module/slapos_compute_node_subscription"
)
sale_supply
.
validate
()
self
.
tic
()
# some preparation
self
.
logout
()
# lets join as slapos administrator, which will own few compute_nodes
owner_reference
=
'owner-%s'
%
self
.
generateNewId
()
self
.
joinSlapOS
(
self
.
web_site
,
owner_reference
)
self
.
login
()
owner_person
=
self
.
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
"ERP5 Login"
,
reference
=
owner_reference
).
getParentValue
()
# first slapos administrator assignment can only be created by
# the erp5 manager
self
.
addProjectProductionManagerAssignment
(
owner_person
,
project
)
self
.
tic
()
# hooray, now it is time to create compute_nodes
self
.
login
(
owner_person
.
getUserId
())
public_server_title
=
'Public Server for %s'
%
owner_reference
public_server_id
=
self
.
requestComputeNode
(
public_server_title
,
project
.
getReference
())
public_server
=
self
.
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'Compute Node'
,
reference
=
public_server_id
)
self
.
setAccessToMemcached
(
public_server
)
self
.
assertNotEqual
(
None
,
public_server
)
self
.
setServerOpenPublic
(
public_server
)
public_server
.
generateCertificate
()
self
.
addAllocationSupply
(
"for compute node"
,
public_server
,
software_product
,
release_variation
,
type_variation
)
# and install some software on them
self
.
supplySoftware
(
public_server
,
public_server_software
)
# format the compute_nodes
self
.
formatComputeNode
(
public_server
)
self
.
logout
()
self
.
login
(
project_owner_person
.
getUserId
())
# Pay deposit to validate virtual master + one computer
deposit_amount
=
42.0
+
99.0
ledger
=
self
.
portal
.
portal_categories
.
ledger
.
automated
outstanding_amount_list
=
project_owner_person
.
Entity_getOutstandingDepositAmountList
(
currency
.
getUid
(),
ledger_uid
=
ledger
.
getUid
())
amount
=
sum
([
i
.
total_price
for
i
in
outstanding_amount_list
])
self
.
assertEqual
(
amount
,
deposit_amount
)
# Ensure to pay from the website
outstanding_amount
=
self
.
web_site
.
restrictedTraverse
(
outstanding_amount_list
[
0
].
getRelativeUrl
())
outstanding_amount
.
Base_createExternalPaymentTransactionFromOutstandingAmountAndRedirect
()
self
.
tic
()
self
.
logout
()
self
.
login
()
payment_transaction
=
self
.
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
"Payment Transaction"
,
destination_section_uid
=
project_owner_person
.
getUid
(),
simulation_state
=
"started"
)
self
.
assertEqual
(
payment_transaction
.
getSpecialiseValue
().
getTradeConditionType
(),
"deposit"
)
# payzen/wechat or accountant will only stop the payment
payment_transaction
.
stop
()
self
.
tic
()
assert
payment_transaction
.
receivable
.
getGroupingReference
(
None
)
is
not
None
self
.
login
(
project_owner_person
.
getUserId
())
amount
=
sum
([
i
.
total_price
for
i
in
project_owner_person
.
Entity_getOutstandingDepositAmountList
(
currency
.
getUid
(),
ledger_uid
=
ledger
.
getUid
())])
self
.
assertEqual
(
0
,
amount
)
self
.
logout
()
# join as the another visitor and request software instance on public
# compute_node
self
.
logout
()
public_reference
=
'public-%s'
%
self
.
generateNewId
()
self
.
joinSlapOS
(
self
.
web_site
,
public_reference
)
self
.
login
()
public_person
=
self
.
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
"ERP5 Login"
,
reference
=
public_reference
).
getParentValue
()
with
PinnedDateTime
(
self
,
DateTime
(
'2024/02/17 01:01'
)):
public_instance_title
=
'Public title %s'
%
self
.
generateNewId
()
# Request a payable instance without deposit
# Change the subscription from payable to free
self
.
checkInstanceAllocationFromPayableToFree
(
public_person
.
getUserId
(),
public_reference
,
public_instance_title
,
public_server_software
,
public_instance_type
,
public_server
,
project
.
getReference
(),
9.0
,
currency
,
sale_person
)
self
.
login
()
public_person
=
self
.
portal
.
portal_catalog
.
getResultValue
(
portal_type
=
'ERP5 Login'
,
reference
=
public_reference
).
getParentValue
()
self
.
login
(
owner_person
.
getUserId
())
# and the instances
self
.
checkInstanceUnallocation
(
public_person
.
getUserId
(),
public_reference
,
public_instance_title
,
public_server_software
,
public_instance_type
,
public_server
,
project
.
getReference
())
# and uninstall some software on them
self
.
logout
()
self
.
login
(
owner_person
.
getUserId
())
self
.
supplySoftware
(
public_server
,
public_server_software
,
state
=
'destroyed'
)
self
.
logout
()
# Uninstall from compute_node
self
.
login
()
self
.
simulateSlapgridSR
(
public_server
)
self
.
tic
()
# 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'
:
None
,
'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
)
==
0
,
len
(
transaction_list
)
self
.
login
()
# Ensure no unexpected object has been created
# 2 accounting transaction / line
# 3 allocation supply / line / cell
# 1 compute node
# 2 credential request
# 2 event
# 1 instance tree
# 6 open sale order / line
# 5 (can reduce to 2) assignment
# 10 simulation mvt
# 3 packing list / line
# 3 sale supply / line
# 3 sale trade condition
# 1 software installation
# 1 software instance
# 1 software product
# 1 subscription change request
# 4 subscription requests
self
.
assertRelatedObjectCount
(
project
,
49
)
self
.
checkERP5StateBeforeExit
()
master/bt5/slapos_panel/ActionTemplateItem/portal_types/Subscription%20Request/change_slapos_submitted_price.xml
0 → 100644
View file @
edef233e
<?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>
<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>
change_slapos_submitted_price
</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>
60.0
</float>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string>
Change Submitted Price
</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}/SubscriptionRequest_viewChangeSlaposSubmittedPriceDialog
</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(\'subscription_change_request_module\', \'Add portal content\') and (context.getSimulationState() == \'submitted\')
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_changeFromPayableToFree.py
0 → 100644
View file @
edef233e
portal
=
context
.
getPortalObject
()
Base_translateString
=
portal
.
Base_translateString
subscription_request
=
context
from
zExceptions
import
Unauthorized
if
REQUEST
is
not
None
:
raise
Unauthorized
batch
=
(
dialog_id
is
None
)
trade_condition_type
=
'manual'
if
activate_kw
is
None
:
activate_kw
=
{}
if
not
'tag'
in
activate_kw
:
activate_kw
[
'tag'
]
=
script
.
id
if
not
(
subscription_request
.
hasSourceSection
()
and
(
0
<
subscription_request
.
getPrice
(
0
))):
keep_items
=
{
'portal_status_level'
:
'warning'
,
'portal_status_message'
:
Base_translateString
(
'The Subscription Request is not a payable one'
)
}
if
batch
:
return
subscription_request
return
context
.
Base_renderForm
(
dialog_id
,
keep_items
=
keep_items
)
# Create the Subscription Change Request
item
=
subscription_request
.
getAggregateValue
()
if
item
.
getPortalType
()
==
'Project'
:
project
=
item
else
:
project
=
subscription_request
.
getSourceProjectValue
()
customer
=
subscription_request
.
getDestinationValue
()
try
:
subscription_change_request
=
subscription_request
.
getResourceValue
().
Resource_createSubscriptionRequest
(
customer
,
# [software_type, software_release],
subscription_request
.
getVariationCategoryList
(),
project
,
currency_value
=
subscription_request
.
getPriceCurrencyValue
(),
temp_object
=
True
,
item_value
=
item
,
causality_value
=
subscription_request
,
# XXX .getCausalityValue(),
portal_type
=
'Subscription Change Request'
,
trade_condition_type
=
trade_condition_type
)
except
AssertionError
:
current_trade_condition
=
None
else
:
current_trade_condition
=
subscription_change_request
.
getSpecialiseValue
()
new_sale_trade_condition
=
None
if
(
current_trade_condition
is
None
):
# Create a dedicated trade condition for the customer
# to define free price
previous_title
=
subscription_request
.
getTitle
()
specialise_trade_condition
=
subscription_request
.
getSpecialiseValue
()
while
(
specialise_trade_condition
.
hasSourceSection
())
or
(
specialise_trade_condition
.
hasDestination
()):
previous_title
=
specialise_trade_condition
.
getTitle
()
specialise_trade_condition
=
specialise_trade_condition
.
getSpecialiseValue
()
new_sale_trade_condition
=
portal
.
sale_trade_condition_module
.
newContent
(
portal_type
=
'Sale Trade Condition'
,
specialise_value
=
specialise_trade_condition
,
title
=
'%s for %s'
%
(
previous_title
,
customer
.
getTitle
()),
destination_value
=
customer
,
destination_section_value
=
customer
,
source_project
=
subscription_request
.
getSourceProject
(),
source
=
subscription_request
.
getSource
(),
price_currency
=
subscription_request
.
getPriceCurrency
(),
trade_condition_type
=
trade_condition_type
,
activate_kw
=
activate_kw
)
new_sale_trade_condition
.
validate
()
subscription_request
.
activate
(
after_tag
=
activate_kw
[
'tag'
]).
SubscriptionRequest_changeFromPayableToFree
(
None
)
keep_items
=
{
'portal_status_message'
:
Base_translateString
(
'Creating a free dedicated Trade Condition for the customer'
)
}
if
batch
:
return
new_sale_trade_condition
return
new_sale_trade_condition
.
Base_redirect
(
keep_items
=
keep_items
)
elif
(
current_trade_condition
.
getDestination
()
==
customer
.
getRelativeUrl
())
and
\
(
current_trade_condition
.
getSourceSection
(
None
)
is
None
):
# There is already a manual trade condition
# without any source section (free)
new_sale_trade_condition
=
current_trade_condition
subscription_change_request
=
subscription_request
.
getResourceValue
().
Resource_createSubscriptionRequest
(
customer
,
# [software_type, software_release],
subscription_request
.
getVariationCategoryList
(),
project
,
currency_value
=
subscription_request
.
getPriceCurrencyValue
(),
item_value
=
item
,
causality_value
=
subscription_request
,
portal_type
=
'Subscription Change Request'
,
trade_condition_type
=
trade_condition_type
)
keep_items
=
{
'portal_status_message'
:
Base_translateString
(
'Creating a Subscription Change Request'
)
}
if
batch
:
return
subscription_change_request
return
subscription_change_request
.
Base_redirect
(
keep_items
=
keep_items
)
else
:
keep_items
=
{
'portal_status_level'
:
'error'
,
'portal_status_message'
:
Base_translateString
(
'This customer already has an incompatible dedicated Trade Condition'
)
}
if
batch
:
raise
ValueError
(
keep_items
[
'portal_status_message'
])
return
current_trade_condition
.
Base_redirect
(
keep_items
=
keep_items
)
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_changeFromPayableToFree.xml
0 → 100644
View file @
edef233e
<?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>
dialog_id, activate_kw=None, REQUEST=None, **kw
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
SubscriptionRequest_changeFromPayableToFree
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_changeSlaposSubmittedPrice.py
0 → 100644
View file @
edef233e
from
DateTime
import
DateTime
portal
=
context
.
getPortalObject
()
Base_translateString
=
portal
.
Base_translateString
subscription_request
=
context
from
zExceptions
import
Unauthorized
if
REQUEST
is
not
None
:
raise
Unauthorized
batch
=
(
dialog_id
is
None
)
if
activate_kw
is
None
:
activate_kw
=
{}
tag
=
activate_kw
.
get
(
'tag'
,
script
.
id
)
activate_kw
[
'tag'
]
=
tag
######################################################
# Prevent some mistakes
if
subscription_request
.
getSimulationState
()
!=
'submitted'
:
keep_items
=
{
'portal_status_level'
:
'warning'
,
'portal_status_message'
:
Base_translateString
(
'Can only change submitted subscription request'
)
}
if
batch
:
raise
ValueError
(
keep_items
[
'portal_status_message'
])
return
subscription_request
.
Base_redirect
(
keep_items
=
keep_items
)
current_price
=
subscription_request
.
getPrice
()
if
not
current_price
:
keep_items
=
{
'portal_status_level'
:
'warning'
,
'portal_status_message'
:
Base_translateString
(
'Can not make a free subscription to a payable one'
)
}
if
batch
:
raise
ValueError
(
keep_items
[
'portal_status_message'
])
return
subscription_request
.
Base_redirect
(
keep_items
=
keep_items
)
######################################################
# From payable to free
if
not
price
:
return
subscription_request
.
SubscriptionRequest_changeFromPayableToFree
(
dialog_id
)
######################################################
# Change price
portal_type
=
'Subscription Change Request'
subscription_change_request
=
portal
.
getDefaultModule
(
portal_type
).
newContent
(
portal_type
=
portal_type
,
causality_value
=
subscription_request
,
start_date
=
DateTime
(),
price
=
price
,
# Copy all other properties
destination
=
subscription_request
.
getDestination
(),
destination_section
=
subscription_request
.
getDestinationSection
(),
destination_decision
=
subscription_request
.
getDestinationDecision
(),
destination_project
=
subscription_request
.
getDestinationProject
(),
resource
=
subscription_request
.
getResource
(),
aggregate
=
subscription_request
.
getAggregate
(),
variation_category_list
=
subscription_request
.
getVariationCategoryList
(),
quantity_unit
=
subscription_request
.
getQuantityUnit
(),
quantity
=
subscription_request
.
getQuantity
(),
ledger
=
subscription_request
.
getLedger
(),
source
=
subscription_request
.
getSource
(),
source_section
=
subscription_request
.
getSourceSection
(),
source_project
=
subscription_request
.
getSourceProject
(),
price_currency
=
subscription_request
.
getPriceCurrency
(),
specialise
=
subscription_request
.
getSpecialise
(),
)
subscription_change_request
.
submit
()
keep_items
=
{
'portal_status_message'
:
Base_translateString
(
'Subscription Change Request created'
)
}
if
batch
:
return
subscription_change_request
return
subscription_change_request
.
Base_redirect
(
keep_items
=
keep_items
)
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_changeSlaposSubmittedPrice.xml
0 → 100644
View file @
edef233e
<?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>
price, dialog_id, activate_kw=None, REQUEST=None, **kw
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
SubscriptionRequest_changeSlaposSubmittedPrice
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_viewChangeSlaposSubmittedPriceDialog.xml
0 → 100644
View file @
edef233e
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"ERP5 Form"
module=
"erp5.portal_type"
/>
</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/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key>
<string>
_objects
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
action
</string>
</key>
<value>
<string>
SubscriptionRequest_changeSlaposSubmittedPrice
</string>
</value>
</item>
<item>
<key>
<string>
action_title
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
edit_order
</string>
</key>
<value>
<list/>
</value>
</item>
<item>
<key>
<string>
encoding
</string>
</key>
<value>
<string>
UTF-8
</string>
</value>
</item>
<item>
<key>
<string>
enctype
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
group_list
</string>
</key>
<value>
<list>
<string>
left
</string>
<string>
right
</string>
<string>
center
</string>
<string>
bottom
</string>
<string>
hidden
</string>
</list>
</value>
</item>
<item>
<key>
<string>
groups
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
bottom
</string>
</key>
<value>
<list/>
</value>
</item>
<item>
<key>
<string>
center
</string>
</key>
<value>
<list/>
</value>
</item>
<item>
<key>
<string>
hidden
</string>
</key>
<value>
<list/>
</value>
</item>
<item>
<key>
<string>
left
</string>
</key>
<value>
<list>
<string>
your_price
</string>
</list>
</value>
</item>
<item>
<key>
<string>
right
</string>
</key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
SubscriptionRequest_viewChangeSlaposSubmittedPriceDialog
</string>
</value>
</item>
<item>
<key>
<string>
method
</string>
</key>
<value>
<string>
POST
</string>
</value>
</item>
<item>
<key>
<string>
name
</string>
</key>
<value>
<string>
SubscriptionRequest_viewChangeSlaposSubmittedPriceDialog
</string>
</value>
</item>
<item>
<key>
<string>
pt
</string>
</key>
<value>
<string>
form_dialog
</string>
</value>
</item>
<item>
<key>
<string>
row_length
</string>
</key>
<value>
<int>
4
</int>
</value>
</item>
<item>
<key>
<string>
stored_encoding
</string>
</key>
<value>
<string>
UTF-8
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string>
Change Submitted Price
</string>
</value>
</item>
<item>
<key>
<string>
unicode_mode
</string>
</key>
<value>
<int>
0
</int>
</value>
</item>
<item>
<key>
<string>
update_action
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
update_action_title
</string>
</key>
<value>
<string></string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_panel/SkinTemplateItem/portal_skins/slapos_panel/SubscriptionRequest_viewChangeSlaposSubmittedPriceDialog/your_price.xml
0 → 100644
View file @
edef233e
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"FloatField"
module=
"Products.Formulator.StandardFields"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
your_price
</string>
</value>
</item>
<item>
<key>
<string>
message_values
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
external_validator_failed
</string>
</key>
<value>
<string>
The input failed the external validator.
</string>
</value>
</item>
<item>
<key>
<string>
not_float
</string>
</key>
<value>
<string>
You did not enter a floating point number.
</string>
</value>
</item>
<item>
<key>
<string>
required_not_found
</string>
</key>
<value>
<string>
Input is required but no input given.
</string>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key>
<string>
overrides
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
alternate_name
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
css_class
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
default
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
display_maxwidth
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
display_width
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
editable
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
enabled
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
external_validator
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
extra
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
hidden
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
input_style
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
precision
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
required
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
whitespace_preserve
</string>
</key>
<value>
<string></string>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key>
<string>
tales
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
alternate_name
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
autocomplete
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
css_class
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
default
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAI=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
display_maxwidth
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
display_width
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAM=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
editable
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
enabled
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
external_validator
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
extra
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
hidden
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
input_style
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAQ=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
input_type
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
precision
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAU=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
required
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
whitespace_preserve
</string>
</key>
<value>
<string></string>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key>
<string>
values
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
alternate_name
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
css_class
</string>
</key>
<value>
<string>
figure
</string>
</value>
</item>
<item>
<key>
<string>
default
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<string>
A typical price of a unit.
</string>
</value>
</item>
<item>
<key>
<string>
display_maxwidth
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
display_width
</string>
</key>
<value>
<int>
20
</int>
</value>
</item>
<item>
<key>
<string>
editable
</string>
</key>
<value>
<int>
1
</int>
</value>
</item>
<item>
<key>
<string>
enabled
</string>
</key>
<value>
<int>
1
</int>
</value>
</item>
<item>
<key>
<string>
external_validator
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
extra
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
hidden
</string>
</key>
<value>
<int>
0
</int>
</value>
</item>
<item>
<key>
<string>
input_style
</string>
</key>
<value>
<string>
-1 234.5
</string>
</value>
</item>
<item>
<key>
<string>
precision
</string>
</key>
<value>
<string></string>
</value>
</item>
<item>
<key>
<string>
required
</string>
</key>
<value>
<int>
0
</int>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string>
Price
</string>
</value>
</item>
<item>
<key>
<string>
whitespace_preserve
</string>
</key>
<value>
<int>
0
</int>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"2"
aka=
"AAAAAAAAAAI="
>
<pickle>
<global
name=
"TALESMethod"
module=
"Products.Formulator.TALESField"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_text
</string>
</key>
<value>
<string>
here/getPrice
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"3"
aka=
"AAAAAAAAAAM="
>
<pickle>
<global
name=
"TALESMethod"
module=
"Products.Formulator.TALESField"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_text
</string>
</key>
<value>
<string>
python: preferences.getPreference(\'preferred_money_quantity_field_width\', 10)
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"4"
aka=
"AAAAAAAAAAQ="
>
<pickle>
<global
name=
"TALESMethod"
module=
"Products.Formulator.TALESField"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_text
</string>
</key>
<value>
<string>
python: preferences.getPreference(\'preferred_money_quantity_style\', \'-1 234.5\')
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"5"
aka=
"AAAAAAAAAAU="
>
<pickle>
<global
name=
"TALESMethod"
module=
"Products.Formulator.TALESField"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_text
</string>
</key>
<value>
<string>
here/getPricePrecision
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_panel/bt/template_action_path_list
View file @
edef233e
...
...
@@ -96,6 +96,7 @@ Software Product | slapos_panel_view
Software Release Module | slapos_panel_view
Software Release | slapos_panel_view
Subscription Request Module | slapos_panel_view
Subscription Request | change_slapos_submitted_price
Subscription Request | jump_pay_my_slapos_sale_invoice_transaction
Subscription Request | slapos_panel_view
Support Request Module | slapos_panel_view
...
...
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