Commit 18f817c6 authored by Rafael Monnerat's avatar Rafael Monnerat

slapos_subscription_request&accounting: Support Service Variation for Reservation Fee

   The goal is define pricing based on the Service Individual Variation in order to support multiple reservation fee prices.

   Introduce a CDN case with different reservation fee and monthly fee pricing.
parent a4348853
......@@ -7,21 +7,43 @@
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
</value>
</item>
<item>
<key> <string>base_price</string> </key>
<value> <float>188.0</float> </value>
</item>
<item>
<key> <string>base_price_per_slice</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>base_unit_price</string> </key>
<value> <float>0.0</float> </value>
......@@ -45,6 +67,12 @@
<key> <string>id</string> </key>
<value> <string>3</string> </value>
</item>
<item>
<key> <string>index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAc=</string> </persistent>
</value>
</item>
<item>
<key> <string>mapped_value_property_list</string> </key>
<value>
......@@ -62,6 +90,14 @@
</tuple>
</value>
</item>
<item>
<key> <string>p_variation_base_category</string> </key>
<value>
<tuple>
<string>variation</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Supply Line</string> </value>
......@@ -69,13 +105,19 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAg=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -90,7 +132,15 @@
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -105,7 +155,37 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="6" aka="AAAAAAAAAAY=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="7" aka="AAAAAAAAAAc=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>path</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAk=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="8" aka="AAAAAAAAAAg=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -118,7 +198,7 @@
<item>
<key> <string>edit_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAo=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -127,7 +207,29 @@
</dictionary>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<record id="9" aka="AAAAAAAAAAk=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <int>0</int> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAs=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="10" aka="AAAAAAAAAAo=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......@@ -149,7 +251,7 @@
<item>
<key> <string>comment</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
<none/>
</value>
</item>
<item>
......@@ -158,7 +260,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>0.0.0.0</string> </value>
<value> <string>990.40474.59911.19558</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -176,7 +278,7 @@
</tuple>
<state>
<tuple>
<float>1615216741.56</float>
<float>1615430173.55</float>
<string>UTC</string>
</tuple>
</state>
......@@ -190,35 +292,23 @@
</dictionary>
</pickle>
</record>
<record id="6" aka="AAAAAAAAAAY=">
<record id="11" aka="AAAAAAAAAAs=">
<pickle>
<global name="Message" module="Products.ERP5Type.Message"/>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default</string> </key>
<value> <string>Object copied from ${source_item}</string> </value>
</item>
<item>
<key> <string>domain</string> </key>
<value> <string>erp5_ui</string> </value>
</item>
<item>
<key> <string>mapping</string> </key>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>source_item</string> </key>
<value> <string>/erp5/sale_trade_condition_module/slapos_reservation_trade_condition/3</string> </value>
<key> <string>variation/service_module/slapos_reservation_fee/1</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>message</string> </key>
<value> <string>Object copied from ${source_item}</string> </value>
</item>
</dictionary>
</pickle>
</record>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Sale Supply Cell" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>base_id</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>base_id</string> </key>
<value> <string>path</string> </value>
</item>
<item>
<key> <string>base_price</string> </key>
<value> <float>8.0</float> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>variation/service_module/slapos_reservation_fee/1</string>
</tuple>
</value>
</item>
<item>
<key> <string>criterion_property</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>path_0</string> </value>
</item>
<item>
<key> <string>mapped_value_property_list</string> </key>
<value>
<tuple>
<string>base_price</string>
<string>base_unit_price</string>
<string>slice_base_price</string>
<string>slice_quantity_range</string>
</tuple>
</value>
</item>
<item>
<key> <string>membership_criterion_base_category</string> </key>
<value>
<tuple>
<string>variation</string>
</tuple>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple>
<string>variation/service_module/slapos_reservation_fee/1</string>
</tuple>
</value>
</item>
<item>
<key> <string>multimembership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Supply Cell</string> </value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</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/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -7,21 +7,43 @@
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
</value>
</item>
<item>
<key> <string>base_price</string> </key>
<value> <float>20.8333333</float> </value>
</item>
<item>
<key> <string>base_price_per_slice</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>base_unit_price</string> </key>
<value> <float>0.0</float> </value>
......@@ -43,7 +65,13 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>2</string> </value>
<value> <string>4</string> </value>
</item>
<item>
<key> <string>index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAc=</string> </persistent>
</value>
</item>
<item>
<key> <string>mapped_value_property_list</string> </key>
......@@ -62,6 +90,14 @@
</tuple>
</value>
</item>
<item>
<key> <string>p_variation_base_category</string> </key>
<value>
<tuple>
<string>variation</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Supply Line</string> </value>
......@@ -69,13 +105,19 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAg=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -90,7 +132,15 @@
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -105,7 +155,37 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="6" aka="AAAAAAAAAAY=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="7" aka="AAAAAAAAAAc=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>path</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAk=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="8" aka="AAAAAAAAAAg=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -118,7 +198,7 @@
<item>
<key> <string>edit_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAo=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -127,7 +207,29 @@
</dictionary>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<record id="9" aka="AAAAAAAAAAk=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <int>0</int> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAs=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="10" aka="AAAAAAAAAAo=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......@@ -158,7 +260,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>990.37108.24891.38007</string> </value>
<value> <string>990.39744.34313.3089</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -176,7 +278,7 @@
</tuple>
<state>
<tuple>
<float>1615231657.59</float>
<float>1615386397.5</float>
<string>UTC</string>
</tuple>
</state>
......@@ -190,4 +292,24 @@
</dictionary>
</pickle>
</record>
<record id="11" aka="AAAAAAAAAAs=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>variation/service_module/slapos_reservation_fee/1</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Sale Supply Cell" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>base_id</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>base_id</string> </key>
<value> <string>path</string> </value>
</item>
<item>
<key> <string>base_price</string> </key>
<value> <float>0.8333333333</float> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>variation/service_module/slapos_reservation_fee/1</string>
</tuple>
</value>
</item>
<item>
<key> <string>criterion_property</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>path_0</string> </value>
</item>
<item>
<key> <string>mapped_value_property_list</string> </key>
<value>
<tuple>
<string>base_price</string>
<string>base_unit_price</string>
<string>slice_base_price</string>
<string>slice_quantity_range</string>
</tuple>
</value>
</item>
<item>
<key> <string>membership_criterion_base_category</string> </key>
<value>
<tuple>
<string>variation</string>
</tuple>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple>
<string>variation/service_module/slapos_reservation_fee/1</string>
</tuple>
</value>
</item>
<item>
<key> <string>multimembership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Supply Cell</string> </value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</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/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -22,4 +22,5 @@ return context.SubscriptionRequestModule_requestSubscriptionProxy(
default_email_text, subscription_reference,
confirmation_required=bool(confirmation_required),
token=token, user_input_dict=user_input_dict,
variation_reference=variation_reference,
target_language=target_language, batch_mode=0)
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>name=None, default_email_text=None, subscription_reference=None, amount=0, token=None, confirmation_required=True, target_language=None, REQUEST=None, **kw</string> </value>
<value> <string>name=None, default_email_text=None, subscription_reference=None, amount=0, token=None, confirmation_required=True, variation_reference=None, target_language=None, REQUEST=None, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
......@@ -61,13 +61,14 @@ subscription_request = context.subscription_request_module.newContent(
subscription_request.setDefaultEmailText(email)
def wrapWithShadow(subscription_request, subscription_reference,
subscription_request_id, contract=contract):
subscription_request_id, variation_reference, contract=contract):
subscription_request.activate(tag="subscription_condition_%s" % subscription_request_id
).SubscriptionRequest_applyCondition(subscription_reference, target_language)
return subscription_request.SubscriptionRequest_requestPaymentTransaction(
tag="subscription_%s" % subscription_request_id,
target_language=target_language,
contract=contract
contract=contract,
variation_reference=variation_reference
)
payment = person.Person_restrictMethodAsShadowUser(
......@@ -75,7 +76,7 @@ payment = person.Person_restrictMethodAsShadowUser(
callable_object=wrapWithShadow,
argument_list=[subscription_request,
subscription_reference, subscription_request.getId(),
contract])
variation_reference, contract])
if batch_mode:
return {'subscription' : subscription_request.getRelativeUrl(),
......
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>email, subscription_reference, confirmation_required=False, token=None, user_input_dict=None, target_language=None, batch_mode=True, REQUEST=None</string> </value>
<value> <string>email, subscription_reference, confirmation_required=False, token=None, user_input_dict=None, variation_reference=None, target_language=None, batch_mode=True, REQUEST=None</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
......
......@@ -20,6 +20,7 @@ if current_invoice is None:
stop_date=payment_transaction.getStopDate(),
)
current_invoice["1"].setVariation(service_variation)
current_invoice["1"].setPrice(price)
current_invoice["1"].setQuantity(context.getQuantity())
......
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>price, tag, payment, template, REQUEST=None</string> </value>
<value> <string>price, tag, payment, template, service_variation, REQUEST=None</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
......
......@@ -6,6 +6,7 @@ portal = context.getPortalObject()
current_invoice = context.getCausalityValue()
current_payment = None
service_variation = None
if current_invoice is None:
if target_language == "zh": # Wechat payment, reservation fee is 188 CNY
......@@ -32,6 +33,13 @@ if current_invoice is None:
tax = 0
else:
invoice_line = invoice_template["1"].asContext()
resource = invoice_line.getResourceValue()
if variation_reference is not None:
for variation in resource.objectValues(portal_type="Service Individual Variation"):
if variation.getReference() == variation_reference:
service_variation = variation.getRelativeUrl()
invoice_line.setVariation(service_variation)
price = invoice_line.getResourceValue().getPrice(
context=invoice_line)
......@@ -64,6 +72,7 @@ if current_invoice is None:
context.reindexObject(activate_kw={'tag': tag})
context.activate(tag=tag).SubscriptionRequest_createRelatedSaleInvoiceTransaction(
price, tag, current_payment.getRelativeUrl(), invoice_template.getRelativeUrl())
price, tag, current_payment.getRelativeUrl(), invoice_template.getRelativeUrl(),
service_variation)
return current_payment
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>tag, target_language, contract=None, REQUEST=None</string> </value>
<value> <string>tag, target_language, contract=None, variation_reference=None, REQUEST=None</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
......
# -*- coding:utf-8 -*-
##############################################################################
#
# Copyright (c) 2019 Nexedi SA and Contributors. All Rights Reserved.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
from erp5.component.test.testSlapOSSubscriptionCDNScenario import TestSlapOSSubscriptionCDNScenarioMixin
from erp5.component.test.SlapOSTestCaseMixin import changeSkin
class TestSlapOSSubscriptionChineseCDNScenarioMixin(TestSlapOSSubscriptionCDNScenarioMixin):
def afterSetUp(self):
self.expected_slapos_organisation = self.expected_zh_slapos_organisation
TestSlapOSSubscriptionCDNScenarioMixin.afterSetUp(self)
self.expected_price_currency = "currency_module/CNY"
self.normal_user = None
self.expected_notification_language = "zh"
self.login()
@changeSkin('Hal')
def _requestSubscription(self, **kw):
return self._requestSubscriptionViaChineseWebsite(**kw)
def createSubscriptionCondition(self, slave=False):
self.subscription_condition = self.createChineseSubscriptionCondition(
slave=slave)
class TestSlapOSSubscriptionCDNChineseScenario(TestSlapOSSubscriptionChineseCDNScenarioMixin):
def test_subscription_scenario_with_single_vm(self):
self._test_subscription_scenario(amount=1)
def test_subscription_with_3_vms_scenario(self):
self._test_subscription_scenario(amount=3)
def test_subscription_scenario_with_reversal_transaction(self):
self._test_subscription_scenario_with_reversal_transaction(amount=1)
def test_two_subscription_scenario(self):
self._test_two_subscription_scenario(amount=1)
def test_subscription_scenario_with_existing_user(self):
self._test_subscription_scenario_with_existing_user(amount=1, language="zh")
def test_subscription_scenario_with_existing_user_with_non_subscription_request(self):
self._test_subscription_scenario_with_existing_user_with_non_subscription_request(amount=1, language="en")
def test_subscription_scenario_with_existing_english_user(self):
# Messages are in chinese, when subscribed via chinese website. Even if the english language is
# english
self._test_subscription_scenario_with_existing_user(amount=1, language="en")
<?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>testSlapOSSubscriptionCDNChineseScenario</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.testSlapOSSubscriptionCDNChineseScenario</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>
# -*- coding:utf-8 -*-
##############################################################################
#
# Copyright (c) 2019 Nexedi SA and Contributors. All Rights Reserved.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
from erp5.component.test.testSlapOSSubscriptionScenario import TestSlapOSSubscriptionScenarioMixin
class TestSlapOSSubscriptionCDNScenarioMixin(TestSlapOSSubscriptionScenarioMixin):
def afterSetUp(self):
TestSlapOSSubscriptionScenarioMixin.afterSetUp(self)
self.expected_individual_price_without_tax = 4.16666666667
self.expected_individual_price_with_tax = 5.0
self.expected_reservation_fee = 1.0
self.expected_reservation_fee_without_tax = 0.83
self.expected_reservation_quantity_tax = 0.833333333333333
self.expected_reservation_tax = 0.166666666666667
self.expected_price_currency = "currency_module/EUR"
self.expected_zh_individual_price_without_tax = 33.333333333333333
self.expected_zh_individual_price_with_tax = 40.0
self.expected_zh_reservation_fee = 8.0
self.expected_zh_reservation_fee_without_tax = 8.0
self.expected_zh_reservation_quantity_tax = 0
self.expected_zh_reservation_tax = 0
self.resource_variation_reference = "CDN"
self.login()
# Overwrite default Subscription Condition.
self.createSubscriptionCondition()
# some preparation
self.logout()
class TestSlapOSSubscriptionCDNScenario(TestSlapOSSubscriptionCDNScenarioMixin):
def test_subscription_scenario_with_single_vm(self):
self._test_subscription_scenario(amount=1)
def test_subscription_with_3_vms_scenario(self):
self._test_subscription_scenario(amount=3)
def test_subscription_scenario_with_reversal_transaction(self):
self._test_subscription_scenario_with_reversal_transaction(amount=1)
def test_two_subscription_scenario(self):
self._test_two_subscription_scenario(amount=1)
def test_subscription_scenario_with_existing_user(self):
self._test_subscription_scenario_with_existing_user(amount=1, language="zh")
def test_subscription_scenario_with_existing_user_with_non_subscription_request(self):
self._test_subscription_scenario_with_existing_user_with_non_subscription_request(amount=1, language="en")
def test_subscription_scenario_with_existing_chinese_user(self):
# Messages are in chinese, when subscribed via chinese website. Even if the english language is
# english
self._test_subscription_scenario_with_existing_user(amount=1, language="zh")
<?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>testSlapOSSubscriptionCDNScenario</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.testSlapOSSubscriptionCDNScenario</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>
......@@ -51,6 +51,7 @@ class TestSlapOSSubscriptionScenarioMixin(DefaultScenarioMixin):
self.expected_source = self.expected_slapos_organisation
self.expected_source_section = self.expected_slapos_organisation
self.cloud_invitation_token = None
self.resource_variation_reference = None
self.expected_free_reservation = 0
self.non_subscription_related_instance_amount = 0
self.skip_destroy_and_check = 0
......@@ -243,7 +244,7 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
description="This is a Chinese test",
url_string=self.generateNewSoftwareReleaseUrl(),
root_slave=slave,
price=1888.00,
price=self.expected_zh_individual_price_with_tax,
price_currency="currency_module/CNY",
default_source_reference="default",
reference="rapidvm%s_zh" % self.new_id,
......@@ -268,7 +269,7 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
description="This is a test",
url_string=self.generateNewSoftwareReleaseUrl(),
root_slave=slave,
price=195.00,
price=self.expected_individual_price_with_tax,
price_currency="currency_module/EUR",
default_source_reference="default",
reference="rapidvm%s" % self.new_id,
......@@ -295,19 +296,19 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
portal_type='Subscription Request')
return subscription_request_list
def checkSubscriptionRequest(self, subscription_request, email, subscription_condition, slave=0):
def checkSubscriptionRequest(self, subscription_request, email, subscription_condition):
self.assertNotEqual(subscription_request, None)
self.assertEqual(subscription_request.getDefaultEmailText(), email)
self.assertEqual(subscription_request.getUrlString(), subscription_condition.getUrlString())
self.assertEqual(subscription_request.getRootSlave(), slave)
self.assertEqual(subscription_request.getRootSlave(), subscription_condition.getRootSlave())
self.assertEqual(subscription_request.getTextContent(),
'<?xml version="1.0" encoding="utf-8"?>\n<instance>\n</instance>')
#self.assertEqual(trial_request.getSlaXml(), '<?xml version="1.0" encoding="utf-8"?>\n<instance>\n</instance>')
self.assertEqual(subscription_request.getSourceReference(), "default")
def checkDraftSubscriptionRequest(self, subscription_request, email, subscription_condition,
slave=0, amount=1):
self.checkSubscriptionRequest(subscription_request, email, subscription_condition, slave=slave)
amount=1):
self.checkSubscriptionRequest(subscription_request, email, subscription_condition)
# XXX This might be diferent
self.assertEqual(subscription_request.getQuantity(), amount)
......@@ -318,25 +319,25 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
self.assertNotEqual(payment, None)
def checkPlannedSubscriptionRequest(self, subscription_request, email,
subscription_condition, slave=0):
subscription_condition):
self.checkSubscriptionRequest(subscription_request, email,
subscription_condition, slave=slave)
subscription_condition)
self.assertEqual(subscription_request.getSimulationState(), "planned")
def checkOrderedSubscriptionRequest(self, subscription_request, email,
subscription_condition, slave=0,
subscription_condition,
notification_message="subscription_request-confirmation-with-password"):
self.checkSubscriptionRequest(subscription_request, email,
subscription_condition, slave=slave)
subscription_condition)
self.assertEqual(subscription_request.getSimulationState(), "ordered")
self.checkBootstrapUser(subscription_request)
self.checkEmailNotification(subscription_request, notification_message)
def checkConfirmedSubscriptionRequest(self, subscription_request, email,
subscription_condition, slave=0,
subscription_condition,
notification_message="subscription_request-payment-is-ready"):
self.checkSubscriptionRequest(subscription_request, email,
subscription_condition, slave=slave)
subscription_condition)
payment = subscription_request.SubscriptionRequest_verifyPaymentBalanceIsReady()
self.assertNotEqual(payment, None)
self.assertEqual(payment.getSimulationState(), 'started')
......@@ -352,17 +353,17 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
self.checkEmailPaymentNotification(subscription_request, notification_message)
def checkStartedSubscriptionRequest(self, subscription_request, email,
subscription_condition, slave=0,
subscription_condition,
notification_message="subscription_request-instance-is-ready"):
self.checkSubscriptionRequest(subscription_request, email,
subscription_condition, slave=slave)
subscription_condition)
self.assertEqual(subscription_request.getSimulationState(), "started")
self.checkEmailInstanceNotification(subscription_request, notification_message)
def checkStoppedSubscriptionRequest(self, subscription_request, email,
subscription_condition, slave=0):
subscription_condition):
self.checkSubscriptionRequest(subscription_request, email,
subscription_condition, slave=slave)
subscription_condition)
self.assertEqual(subscription_request.getSimulationState(), "stopped")
def _getRelatedPaymentValue(self, subscription_request):
......@@ -715,7 +716,7 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
expected_reservation_tax = self.expected_reservation_tax
expected_reservation_fee = self.expected_reservation_fee
self.assertEqual(invoice.getSimulationState(), "stopped")
self.assertEqual(invoice.getSimulationState(), "stopped", invoice.getRelativeUrl())
self.assertEqual(invoice.getCausalityState(), "solved")
self.assertEqual(invoice.getPriceCurrency(),
subscription_request.getPriceCurrency())
......@@ -1029,7 +1030,7 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
self.assertEqual(hosting_subscription.getSourceReference(), "default")
instance_list = hosting_subscription.getSpecialiseRelatedValueList(
portal_type=["Software Instance", "Slave Instace"])
portal_type=["Software Instance", "Slave Instance"])
self.assertEqual(1,len(instance_list))
return instance_list[0]
......@@ -1107,6 +1108,8 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
def _requestSubscription(self, **kw):
if self.cloud_invitation_token is not None:
kw["token"] = self.cloud_invitation_token.getId()
if self.resource_variation_reference is not None:
kw["variation_reference"] = self.resource_variation_reference
return self.web_site.hateoas.SubscriptionRequestModule_requestSubscription(**kw)
@changeSkin('Hal')
......@@ -1115,6 +1118,8 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
kw["token"] = self.cloud_invitation_token.getId()
if 'target_language' not in kw:
kw["target_language"] = "zh"
if self.resource_variation_reference is not None:
kw["variation_reference"] = self.resource_variation_reference
kw["subscription_reference"] = self.subscription_condition.getReference().replace("_zh", "")
original_mode = self.portal.portal_secure_payments.slapos_wechat_test.getWechatMode()
......@@ -1220,7 +1225,8 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
subscription_request.getLanguage())
self.checkDraftSubscriptionRequest(subscription_request,
default_email_text, self.subscription_condition, amount=amount)
default_email_text, self.subscription_condition,
amount=amount)
# Check Payment and pay it.
self.checkAndPaySubscriptionPayment([subscription_request])
......
......@@ -621,7 +621,8 @@ class TestSubscriptionRequest_createRelatedSaleInvoiceTransaction(TestSubscripti
subscription_request.edit(causality_value=current_invoice)
self.assertEqual(current_invoice,
subscription_request.SubscriptionRequest_createRelatedSaleInvoiceTransaction(1, "xx", "___payment__", invoice_template_path))
subscription_request.SubscriptionRequest_createRelatedSaleInvoiceTransaction(
1, "xx", "___payment__", invoice_template_path, None))
def _test_creation_of_related_sale_invoice_transaction(self, quantity):
......
......@@ -12,4 +12,6 @@ test.erp5.testSlapOSSubscriptionInvitationTokenChineseScenario
test.erp5.testSlapOSSubscriptionSecondMonthPaymentScenario
test.erp5.testSlapOSSubscriptionSecondMonthPaymentChineseScenario
test.erp5.testSlapOSSubscriptionDualOrganisationScenario
test.erp5.testSlapOSSubscriptionCancellationScenario
\ No newline at end of file
test.erp5.testSlapOSSubscriptionCancellationScenario
test.erp5.testSlapOSSubscriptionCDNScenario
test.erp5.testSlapOSSubscriptionCDNChineseScenario
\ 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