Commit f7b7f1dd authored by Romain Courteaud's avatar Romain Courteaud

slapos_accounting: generate one open order per instance tree

parent 15412044
...@@ -2,11 +2,132 @@ from zExceptions import Unauthorized ...@@ -2,11 +2,132 @@ from zExceptions import Unauthorized
if REQUEST is not None: if REQUEST is not None:
raise Unauthorized raise Unauthorized
if context.getCausalityState() == 'diverged': from DateTime import DateTime
person = context.getDestinationSectionValue(portal_type="Person") portal = context.getPortalObject()
instance_tree = context
now = DateTime()
tag = '%s_%s' % (instance_tree.getUid(), script.id)
activate_kw = {'tag': tag}
if portal.portal_activities.countMessageWithTag(tag) > 0:
# nothing to do
return
def storeWorkflowComment(document, comment):
portal.portal_workflow.doActionFor(document, 'edit_action', comment=comment)
def newOpenOrder(open_sale_order):
open_sale_order_template = portal.restrictedTraverse(
portal.portal_preferences.getPreferredOpenSaleOrderTemplate())
open_order_edit_kw = {
'effective_date': DateTime(),
'activate_kw': activate_kw,
'source': open_sale_order_template.getSource(),
'source_section': open_sale_order_template.getSourceSection()
}
if open_sale_order is None:
new_open_sale_order = open_sale_order_template.Base_createCloneDocument(batch_mode=1)
open_order_edit_kw.update({
'destination': person.getRelativeUrl(),
'destination_decision': person.getRelativeUrl(),
'title': "%s SlapOS Subscription" % person.getTitle(),
})
else:
new_open_sale_order = open_sale_order.Base_createCloneDocument(batch_mode=1)
open_sale_order.setExpirationDate(now, activate_kw=activate_kw)
new_open_sale_order.edit(**open_order_edit_kw)
new_open_sale_order.order(activate_kw=activate_kw)
new_open_sale_order.validate(activate_kw=activate_kw)
return new_open_sale_order
if instance_tree.getCausalityState() == 'diverged':
person = instance_tree.getDestinationSectionValue(portal_type="Person")
# Template document does not have person relation # Template document does not have person relation
if person is not None: if person is not None:
person.Person_storeOpenSaleOrderJournal()
# Search an existing related open order
open_order_line = portal.portal_catalog.getResultValue(
portal_type='Open Sale Order Line',
default_aggregate_uid=instance_tree.getUid())
is_open_order_creation_needed = False
# Simply check that it has never been simulated
if instance_tree.getSlapState() == 'destroy_requested':
# Line should be deleted
if (open_order_line is not None) and (open_order_line.getValidationState() == "invalidated"):
instance_tree.converge(comment="Last open order: %s" % open_order_line.getRelativeUrl())
elif open_order_line is None:
# User has no Open Sale Order (likely), so we add the line to remove later. This allow us to charge
# eventual usage between the runs of the alarm.
is_open_order_creation_needed = True
elif open_order_line is None:
# Let's add
is_open_order_creation_needed = True
# Let's create the open order
if is_open_order_creation_needed:
open_sale_order = newOpenOrder(None)
open_order_explanation = ""
# Add lines
open_sale_order_line_template = portal.restrictedTraverse(
portal.portal_preferences.getPreferredOpenSaleOrderLineTemplate())
open_sale_order_line = open_sale_order_line_template.Base_createCloneDocument(batch_mode=1,
destination=open_sale_order)
start_date = instance_tree.InstanceTree_calculateSubscriptionStartDate()
edit_kw = {}
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:
# Copy from Subscription Condition the source and Source Section into the line
# RAFAEL: As the model is use single Open Order, it isn't possible to use multiple
# companies per region, so we rely on Subscription Conditions to Describe the
# providers.
edit_kw["source"] = subscription_request.getSource()
edit_kw["source_section"] = subscription_request.getSourceSection()
# Quantity is double because the first invoice has to
# charge for 2 months
edit_kw['quantity'] = subscription_request.getQuantity()
edit_kw['price'] = subscription_request.getPrice()
edit_kw['price_currency'] = subscription_request.getPriceCurrency()
# While create move the start date to be at least 1 months
# So we can charge 3 months at once
# You can increase 65 days to generate 3 months
# You can increase 32 days to generate 2 months
# You can increase 0 days to keep generating one month only
# start_date_delta = 0
open_sale_order_line.edit(
activate_kw=activate_kw,
title=instance_tree.getTitle(),
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,
# stop_date=calculateOpenOrderLineStopDate(open_sale_order_line,
# instance_tree, start_date_delta=start_date_delta),
aggregate_value=instance_tree,
**edit_kw
)
storeWorkflowComment(open_sale_order_line, "Created for %s" % instance_tree.getRelativeUrl())
# instance_tree.converge(comment="Last open order: %s" % open_sale_order_line.getRelativeUrl())
open_order_explanation = "Added %s." % str(open_sale_order_line.getId())
storeWorkflowComment(open_sale_order, open_order_explanation)
else:
open_sale_order = open_order_line.getParentValue()
open_sale_order.OpenSaleOrder_updatePeriod()
# Person_storeOpenSaleOrderJournal should fix all divergent Instance Tree in one run # Person_storeOpenSaleOrderJournal should fix all divergent Instance Tree in one run
assert context.getCausalityState() == 'solved' assert instance_tree.getCausalityState() == 'solved'
...@@ -2,7 +2,86 @@ from zExceptions import Unauthorized ...@@ -2,7 +2,86 @@ from zExceptions import Unauthorized
if REQUEST is not None: if REQUEST is not None:
raise Unauthorized raise Unauthorized
if context.getValidationState() == 'validated': from erp5.component.module.DateUtils import addToDate
person = context.getDestinationDecisionValue(portal_type="Person") from DateTime import DateTime
portal = context.getPortalObject()
open_sale_order = context
now = DateTime()
tag = '%s_%s' % (open_sale_order.getUid(), script.id)
activate_kw = {'tag': tag}
if portal.portal_activities.countMessageWithTag(tag) > 0:
# nothing to do
return
def storeWorkflowComment(document, comment):
portal.portal_workflow.doActionFor(document, 'edit_action', comment=comment)
def calculateOpenOrderLineStopDate(open_order_line, instance_tree, start_date_delta, next_stop_date_delta=0):
end_date = instance_tree.InstanceTree_calculateSubscriptionStopDate()
if end_date is None:
# Be sure that start date is different from stop date
# Consider the first period longer (delta), this allow us to change X days/months
# On a first invoice.
next_stop_date = instance_tree.getNextPeriodicalDate(
instance_tree.InstanceTree_calculateSubscriptionStartDate() + start_date_delta)
current_stop_date = next_stop_date
# Ensure the invoice is generated 15 days in advance of the next period.
while next_stop_date < now + next_stop_date_delta:
# Return result should be < now, it order to provide stability in simulation (destruction if it happen should be >= now)
current_stop_date = next_stop_date
next_stop_date = \
instance_tree.getNextPeriodicalDate(current_stop_date)
return addToDate(current_stop_date, to_add={'second': -1})
else:
stop_date = end_date
return stop_date
if open_sale_order.getValidationState() == 'validated':
person = open_sale_order.getDestinationDecisionValue(portal_type="Person")
if person is not None: if person is not None:
person.Person_storeOpenSaleOrderJournal()
for open_order_line in open_sale_order.contentValues(
portal_type='Open Sale Order Line'):
current_start_date = open_order_line.getStartDate()
current_stop_date = open_order_line.getStopDate()
# Prevent mistakes
assert current_start_date is not None
assert current_stop_date is not None
assert current_start_date < current_stop_date
instance_tree = open_order_line.getAggregateValue(portal_type='Instance Tree')
assert current_start_date == instance_tree.InstanceTree_calculateSubscriptionStartDate()
subscription_request = instance_tree.getAggregateRelatedValue(portal_type="Subscription Request")
# Define the start date of the period, this can variates with the time.
next_stop_date_delta = 0
if subscription_request is not None:
next_stop_date_delta = 46
# First check if the instance tree has been correctly simulated (this script may run only once per year...)
stop_date = calculateOpenOrderLineStopDate(open_order_line, instance_tree,
start_date_delta=0, next_stop_date_delta=next_stop_date_delta)
if current_stop_date < stop_date:
# Bingo, new subscription to generate
open_order_line.edit(
stop_date=stop_date,
activate_kw=activate_kw)
storeWorkflowComment(open_order_line,
'Stop date updated to %s' % stop_date)
if instance_tree.getSlapState() == 'destroy_requested':
# Line should be deleted
assert instance_tree.getCausalityState() == 'diverged'
instance_tree.converge(comment="Last open order: %s" % open_order_line.getRelativeUrl())
open_sale_order.archive()
storeWorkflowComment(open_sale_order, "Instance Tree destroyed: %s" % instance_tree.getRelativeUrl())
elif (instance_tree.getCausalityState() == 'diverged'):
instance_tree.converge(comment="Nothing to do on open order.")
from erp5.component.module.DateUtils import addToDate
from DateTime import DateTime
portal = context.getPortalObject()
now = DateTime()
person = context
tag = '%s_%s' % (person.getUid(), script.id)
activate_kw = {'tag': tag}
if portal.portal_activities.countMessageWithTag(tag) > 0:
# nothing to do
return
def newOpenOrder(open_sale_order):
open_sale_order_template = portal.restrictedTraverse(
portal.portal_preferences.getPreferredOpenSaleOrderTemplate())
open_order_edit_kw = {
'effective_date': DateTime(),
'activate_kw': activate_kw,
'source': open_sale_order_template.getSource(),
'source_section': open_sale_order_template.getSourceSection()
}
if open_sale_order is None:
new_open_sale_order = open_sale_order_template.Base_createCloneDocument(batch_mode=1)
open_order_edit_kw.update({
'destination': person.getRelativeUrl(),
'destination_decision': person.getRelativeUrl(),
'title': "%s SlapOS Subscription" % person.getTitle(),
})
else:
new_open_sale_order = open_sale_order.Base_createCloneDocument(batch_mode=1)
open_sale_order.setExpirationDate(now, activate_kw=activate_kw)
new_open_sale_order.edit(**open_order_edit_kw)
new_open_sale_order.order(activate_kw=activate_kw)
new_open_sale_order.validate(activate_kw=activate_kw)
return new_open_sale_order
def storeWorkflowComment(document, comment):
portal.portal_workflow.doActionFor(document, 'edit_action', comment=comment)
def calculateOpenOrderLineStopDate(open_order_line, instance_tree, start_date_delta, next_stop_date_delta=0):
end_date = instance_tree.InstanceTree_calculateSubscriptionStopDate()
if end_date is None:
# Be sure that start date is different from stop date
# Consider the first period longer (delta), this allow us to change X days/months
# On a first invoice.
next_stop_date = instance_tree.getNextPeriodicalDate(
instance_tree.InstanceTree_calculateSubscriptionStartDate() + start_date_delta)
current_stop_date = next_stop_date
# Ensure the invoice is generated 15 days in advance of the next period.
while next_stop_date < now + next_stop_date_delta:
# Return result should be < now, it order to provide stability in simulation (destruction if it happen should be >= now)
current_stop_date = next_stop_date
next_stop_date = \
instance_tree.getNextPeriodicalDate(current_stop_date)
return addToDate(current_stop_date, to_add={'second': -1})
else:
stop_date = end_date
return stop_date
# Prevent concurrent transaction to update the open order
context.serialize()
# First, check the existing open order. Does some lines need to be removed, updated?
open_sale_order_list = portal.portal_catalog(
default_destination_uid=person.getUid(),
portal_type="Open Sale Order",
validation_state="validated",
limit=2,
)
open_sale_order_count = len(open_sale_order_list)
if open_sale_order_count == 0:
open_sale_order = None
elif open_sale_order_count == 1:
open_sale_order = open_sale_order_list[0].getObject()
else:
raise ValueError, "Too many open order '%s' found: %s" % (person.getRelativeUrl(), [x.path for x in open_sale_order_list])
delete_line_list = []
add_line_list = []
updated_instance_tree_dict = {}
deleted_instance_tree_dict = {}
if open_sale_order is not None:
for open_order_line in open_sale_order.contentValues(
portal_type='Open Sale Order Line'):
current_start_date = open_order_line.getStartDate()
current_stop_date = open_order_line.getStopDate()
# Prevent mistakes
assert current_start_date is not None
assert current_stop_date is not None
assert current_start_date < current_stop_date
instance_tree = open_order_line.getAggregateValue(portal_type='Instance Tree')
assert current_start_date == instance_tree.InstanceTree_calculateSubscriptionStartDate()
subscription_request = instance_tree.getAggregateRelatedValue(portal_type="Subscription Request")
# Define the start date of the period, this can variates with the time.
next_stop_date_delta = 0
if subscription_request is not None:
next_stop_date_delta = 46
# First check if the instance tree has been correctly simulated (this script may run only once per year...)
stop_date = calculateOpenOrderLineStopDate(open_order_line, instance_tree,
start_date_delta=0, next_stop_date_delta=next_stop_date_delta)
if current_stop_date < stop_date:
# Bingo, new subscription to generate
open_order_line.edit(
stop_date=stop_date,
activate_kw=activate_kw)
storeWorkflowComment(open_order_line,
'Stop date updated to %s' % stop_date)
if instance_tree.getSlapState() == 'destroy_requested':
# Line should be deleted
assert instance_tree.getCausalityState() == 'diverged'
delete_line_list.append(open_order_line.getId())
instance_tree.converge(comment="Last open order: %s" % open_order_line.getRelativeUrl())
deleted_instance_tree_dict[instance_tree.getRelativeUrl()] = None
updated_instance_tree_dict[instance_tree.getRelativeUrl()] = None
elif (instance_tree.getCausalityState() == 'diverged'):
instance_tree.converge(comment="Nothing to do on open order.")
updated_instance_tree_dict[instance_tree.getRelativeUrl()] = None
# Time to check the open order line to add (remaining diverged Hosting
# Subscription normally)
for instance_tree in portal.portal_catalog(
portal_type='Instance Tree',
default_destination_section_uid=context.getUid(),
causality_state="diverged"):
instance_tree = instance_tree.getObject()
if instance_tree.getCausalityState() == 'diverged':
# Simply check that it has never been simulated
if instance_tree.getSlapState() == 'destroy_requested':
# Line should be deleted
open_order_line = portal.portal_catalog.getResultValue(
portal_type='Open Sale Order Line',
default_aggregate_uid=instance_tree.getUid())
if open_order_line is not None and open_order_line.getValidationState() == "invalidated":
instance_tree.converge(comment="Last open order: %s" % open_order_line.getRelativeUrl())
elif open_order_line is None:
# User has no Open Sale Order (likely), so we add the line to remove later. This allow us to charge
# eventual usage between the runs of the alarm.
add_line_list.append(instance_tree)
else:
assert len(portal.portal_catalog(
portal_type='Open Sale Order Line',
default_aggregate_uid=instance_tree.getUid(),
limit=1)) == 0
# Let's add
add_line_list.append(instance_tree)
else:
# Should be in the list of lines to remove
assert (instance_tree.getRelativeUrl() in deleted_instance_tree_dict) or \
(instance_tree.getRelativeUrl() in updated_instance_tree_dict)
manual_archive = False
if (add_line_list):
# No need to create a new open order to add lines
if open_sale_order is None:
open_sale_order = newOpenOrder(None)
manual_archive = True
open_order_explanation = ""
# Add lines
added_line_list = []
open_sale_order_line_template = portal.restrictedTraverse(
portal.portal_preferences.getPreferredOpenSaleOrderLineTemplate())
for instance_tree in add_line_list:
open_sale_order_line = open_sale_order_line_template.Base_createCloneDocument(batch_mode=1,
destination=open_sale_order)
start_date = instance_tree.InstanceTree_calculateSubscriptionStartDate()
edit_kw = {}
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:
# Copy from Subscription Condition the source and Source Section into the line
# RAFAEL: As the model is use single Open Order, it isn't possible to use multiple
# companies per region, so we rely on Subscription Conditions to Describe the
# providers.
edit_kw["source"] = subscription_request.getSource()
edit_kw["source_section"] = subscription_request.getSourceSection()
# Quantity is double because the first invoice has to
# charge for 2 months
edit_kw['quantity'] = subscription_request.getQuantity()
edit_kw['price'] = subscription_request.getPrice()
edit_kw['price_currency'] = subscription_request.getPriceCurrency()
# While create move the start date to be at least 1 months
# So we can charge 3 months at once
# You can increase 65 days to generate 3 months
# You can increase 32 days to generate 2 months
# You can increase 0 days to keep generating one month only
start_date_delta = 0
open_sale_order_line.edit(
activate_kw=activate_kw,
title=instance_tree.getTitle(),
start_date=start_date,
stop_date=calculateOpenOrderLineStopDate(open_sale_order_line,
instance_tree, start_date_delta=start_date_delta),
aggregate_value=instance_tree,
**edit_kw
)
storeWorkflowComment(open_sale_order_line, "Created for %s" % instance_tree.getRelativeUrl())
if (instance_tree.getSlapState() == 'destroy_requested'):
# Added line to delete immediately
delete_line_list.append(open_sale_order_line.getId())
instance_tree.converge(comment="Last open order: %s" % open_sale_order_line.getRelativeUrl())
else:
instance_tree.converge(comment="First open order: %s" % open_sale_order_line.getRelativeUrl())
added_line_list.append(open_sale_order_line.getId())
open_order_explanation += "Added %s." % str(added_line_list)
new_open_sale_order = None
if (delete_line_list):
# All Verifications done. Time to clone/create open order
new_open_sale_order = newOpenOrder(open_sale_order)
if manual_archive == True:
open_sale_order.archive()
open_order_explanation = ""
# Remove lines
new_open_sale_order.deleteContent(delete_line_list)
open_order_explanation += "Removed %s." % str(delete_line_list)
storeWorkflowComment(new_open_sale_order, open_order_explanation)
open_sale_order = new_open_sale_order
if open_sale_order is not None:
if not len(open_sale_order.contentValues(
portal_type='Open Sale Order Line')):
open_sale_order.archive()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_storeOpenSaleOrderJournal</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -107,22 +107,6 @@ class TestOpenSaleOrderAlarm(SlapOSTestCaseMixin): ...@@ -107,22 +107,6 @@ class TestOpenSaleOrderAlarm(SlapOSTestCaseMixin):
default_destination_uid=person.getUid() default_destination_uid=person.getUid()
)) ))
def test_OSO_after_Person_updateOpenSaleOrder(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
self.tic()
person.Person_storeOpenSaleOrderJournal()
self.tic()
open_sale_order_list = self.portal.portal_catalog(
validation_state='validated',
portal_type='Open Sale Order',
default_destination_uid=person.getUid()
)
# No need to create any open order without instance tree
self.assertEqual(0, len(open_sale_order_list))
@simulateByEditWorkflowMark('InstanceTree_requestUpdateOpenSaleOrder') @simulateByEditWorkflowMark('InstanceTree_requestUpdateOpenSaleOrder')
def test_alarm_HS_diverged(self): def test_alarm_HS_diverged(self):
subscription = self.portal.instance_tree_module\ subscription = self.portal.instance_tree_module\
...@@ -291,28 +275,22 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin): ...@@ -291,28 +275,22 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin):
default_destination_uid=person.getUid() default_destination_uid=person.getUid()
) )
self.assertEqual(2, len(open_sale_order_list)) self.assertEqual(1, len(open_sale_order_list))
validated_open_sale_order_list = [q for q in open_sale_order_list validated_open_sale_order_list = [q for q in open_sale_order_list
if q.getValidationState() == 'validated'] if q.getValidationState() == 'validated']
archived_open_sale_order_list = [q for q in open_sale_order_list archived_open_sale_order_list = [q for q in open_sale_order_list
if q.getValidationState() == 'archived'] if q.getValidationState() == 'archived']
self.assertEqual(0, len(validated_open_sale_order_list)) self.assertEqual(0, len(validated_open_sale_order_list))
self.assertEqual(2, len(archived_open_sale_order_list)) self.assertEqual(1, len(archived_open_sale_order_list))
archived_open_sale_order_list.sort(key=lambda x: x.getCreationDate())
last_open_sale_order = archived_open_sale_order_list[-1].getObject()
archived_open_sale_order = archived_open_sale_order_list[0]\ archived_open_sale_order = archived_open_sale_order_list[0]\
.getObject() .getObject()
self.assertEqual(open_sale_order.getRelativeUrl(), self.assertEqual(open_sale_order.getRelativeUrl(),
archived_open_sale_order.getRelativeUrl()) archived_open_sale_order.getRelativeUrl())
last_line_list = last_open_sale_order.contentValues(
portal_type='Open Sale Order Line')
archived_line_list = archived_open_sale_order.contentValues( archived_line_list = archived_open_sale_order.contentValues(
portal_type='Open Sale Order Line') portal_type='Open Sale Order Line')
self.assertEqual(0, len(last_line_list))
self.assertEqual(1, len(archived_line_list)) self.assertEqual(1, len(archived_line_list))
archived_line = archived_line_list[0].getObject() archived_line = archived_line_list[0].getObject()
...@@ -376,7 +354,7 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin): ...@@ -376,7 +354,7 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin):
default_destination_uid=person.getUid() default_destination_uid=person.getUid()
) )
self.assertEqual(2, len(open_sale_order_list)) self.assertEqual(1, len(open_sale_order_list))
archived_open_sale_order_list = [x for x in open_sale_order_list \ archived_open_sale_order_list = [x for x in open_sale_order_list \
if x.getValidationState() != 'validated' and \ if x.getValidationState() != 'validated' and \
len(x.objectValues()) > 0] len(x.objectValues()) > 0]
...@@ -421,7 +399,7 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin): ...@@ -421,7 +399,7 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin):
self.assertEqual('archived', new_open_sale_order.getValidationState()) self.assertEqual('archived', new_open_sale_order.getValidationState())
open_sale_order_line_list = new_open_sale_order.contentValues( open_sale_order_line_list = new_open_sale_order.contentValues(
portal_type='Open Sale Order Line') portal_type='Open Sale Order Line')
self.assertEqual(0, len(open_sale_order_line_list)) self.assertEqual(1, len(open_sale_order_line_list))
def test_two_InstanceTree(self): def test_two_InstanceTree(self):
person = self.portal.person_module.template_member\ person = self.portal.person_module.template_member\
...@@ -517,18 +495,23 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin): ...@@ -517,18 +495,23 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin):
default_destination_uid=person.getUid() default_destination_uid=person.getUid()
) )
self.assertEqual(1, len(open_sale_order_list)) self.assertEqual(2, len(open_sale_order_list))
validated_open_sale_order_list = [q for q in open_sale_order_list validated_open_sale_order_list = [q for q in open_sale_order_list
if q.getValidationState() == 'validated'] if q.getValidationState() == 'validated']
archived_open_sale_order_list = [q for q in open_sale_order_list archived_open_sale_order_list = [q for q in open_sale_order_list
if q.getValidationState() == 'archived'] if q.getValidationState() == 'archived']
self.assertEqual(1, len(validated_open_sale_order_list)) self.assertEqual(2, len(validated_open_sale_order_list))
self.assertEqual(0, len(archived_open_sale_order_list)) self.assertEqual(0, len(archived_open_sale_order_list))
validated_open_sale_order = validated_open_sale_order_list[0].getObject()
validated_line_list = validated_open_sale_order.contentValues(
open_sale_order_2 = [x for x in validated_open_sale_order_list if x.getRelativeUrl() != open_sale_order.getRelativeUrl()][0]
self.assertEqual(open_sale_order.getRelativeUrl(), [x for x in validated_open_sale_order_list if x.getRelativeUrl() == open_sale_order.getRelativeUrl()][0].getRelativeUrl())
validated_line_list = open_sale_order_2.contentValues(
portal_type='Open Sale Order Line') portal_type='Open Sale Order Line')
self.assertEqual(2, len(validated_line_list)) self.assertEqual(1, len(validated_line_list))
validated_line_2 = validated_line_list[0]
validated_line_1 = line
self.assertEqual(open_sale_order_line_template.getQuantity(), self.assertEqual(open_sale_order_line_template.getQuantity(),
line.getQuantity()) line.getQuantity())
...@@ -543,10 +526,8 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin): ...@@ -543,10 +526,8 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin):
next_stop_date_2 = addToDate(stop_date_2, to_add={'month': 1}) next_stop_date_2 = addToDate(stop_date_2, to_add={'month': 1})
stop_date_2 = addToDate(stop_date_2, to_add={'second': -1}) stop_date_2 = addToDate(stop_date_2, to_add={'second': -1})
validated_line_1 = [q for q in validated_line_list if q.getAggregate() == \ self.assertEqual(validated_line_1.getAggregate(), subscription.getRelativeUrl())
subscription.getRelativeUrl()][0] self.assertEqual(validated_line_2.getAggregate(), subscription2.getRelativeUrl())
validated_line_2 = [q for q in validated_line_list if q.getAggregate() == \
subscription2.getRelativeUrl()][0]
self.assertTrue(all([q in validated_line_1.getCategoryList() \ self.assertTrue(all([q in validated_line_1.getCategoryList() \
for q in open_sale_order_line_template.getCategoryList()])) for q in open_sale_order_line_template.getCategoryList()]))
...@@ -667,7 +648,7 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin): ...@@ -667,7 +648,7 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin):
default_destination_uid=person.getUid() default_destination_uid=person.getUid()
) )
self.assertEqual(2,len(open_sale_order_list)) self.assertEqual(1,len(open_sale_order_list))
archived_open_sale_order_list = [x for x in open_sale_order_list \ archived_open_sale_order_list = [x for x in open_sale_order_list \
if x.getValidationState() != 'validated'] if x.getValidationState() != 'validated']
...@@ -680,7 +661,6 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin): ...@@ -680,7 +661,6 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin):
portal_type='Open Sale Order Line') portal_type='Open Sale Order Line')
self.assertEqual(1, len(open_sale_order_line_list)) self.assertEqual(1, len(open_sale_order_line_list))
effective_date = open_sale_order.getEffectiveDate()
line = open_sale_order_line_list[0].getObject() line = open_sale_order_line_list[0].getObject()
self.assertEqual(subscription.getRelativeUrl(), line.getAggregate()) self.assertEqual(subscription.getRelativeUrl(), line.getAggregate())
...@@ -698,19 +678,6 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin): ...@@ -698,19 +678,6 @@ class TestInstanceTree_requestUpdateOpenSaleOrder(SlapOSTestCaseMixin):
self.assertEqual(addToDate(line.getStartDate(), to_add={'day': 1}), self.assertEqual(addToDate(line.getStartDate(), to_add={'day': 1}),
line.getStopDate()) line.getStopDate())
archived_open_sale_order_list = [x for x in open_sale_order_list \
if x.getValidationState() != 'validated']
archived_open_sale_order_list.sort(key=lambda x: x.getCreationDate())
new_open_sale_order = archived_open_sale_order_list[-1].getObject()
self.assertEqual('archived', new_open_sale_order.getValidationState())
new_effective_date = new_open_sale_order.getEffectiveDate()
open_sale_order_line_list = new_open_sale_order.contentValues(
portal_type='Open Sale Order Line')
self.assertEqual(0, len(open_sale_order_line_list))
self.assertTrue(new_effective_date > effective_date,
"%s <= %s" % (new_effective_date, effective_date))
class TestSlapOSTriggerBuildAlarm(SlapOSTestCaseMixin): class TestSlapOSTriggerBuildAlarm(SlapOSTestCaseMixin):
@simulateByTitlewMark('SimulationMovement_buildSlapOS') @simulateByTitlewMark('SimulationMovement_buildSlapOS')
...@@ -1262,14 +1229,11 @@ class TestSlapOSUpdateOpenSaleOrderPeriod(SlapOSTestCaseMixin): ...@@ -1262,14 +1229,11 @@ class TestSlapOSUpdateOpenSaleOrderPeriod(SlapOSTestCaseMixin):
open_order.edit( open_order.edit(
destination_decision_value=person, destination_decision_value=person,
) )
open_order.newContent(
portal_type="Open Sale Order Line"
)
script_name = "Person_storeOpenSaleOrderJournal" self.assertRaises(AssertionError, open_order.OpenSaleOrder_updatePeriod)
self._simulateScript(script_name)
try:
open_order.OpenSaleOrder_updatePeriod()
finally:
self._dropScript(script_name)
self.assertScriptVisited(person, script_name)
def test_updatePeriod_invalidated(self): def test_updatePeriod_invalidated(self):
open_order = self.createOpenOrder() open_order = self.createOpenOrder()
...@@ -1279,14 +1243,10 @@ class TestSlapOSUpdateOpenSaleOrderPeriod(SlapOSTestCaseMixin): ...@@ -1279,14 +1243,10 @@ class TestSlapOSUpdateOpenSaleOrderPeriod(SlapOSTestCaseMixin):
destination_decision_value=person, destination_decision_value=person,
) )
open_order.invalidate() open_order.invalidate()
open_order.newContent(
script_name = "Person_storeOpenSaleOrderJournal" portal_type="Open Sale Order Line"
self._simulateScript(script_name) )
try:
open_order.OpenSaleOrder_updatePeriod() open_order.OpenSaleOrder_updatePeriod()
finally:
self._dropScript(script_name)
self.assertScriptNotVisited(person, script_name)
def test_alarm(self): def test_alarm(self):
open_order = self.createOpenOrder() open_order = self.createOpenOrder()
......
...@@ -617,18 +617,19 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin): ...@@ -617,18 +617,19 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin):
self.assertEqual(0, len(open_sale_order_list)) self.assertEqual(0, len(open_sale_order_list))
return return
self.assertEqual(2, len(open_sale_order_list)) self.assertEqual(len(instance_tree_list), len(open_sale_order_list))
archived_open_sale_order_list = [q for q in open_sale_order_list archived_open_sale_order_list = [q for q in open_sale_order_list
if q.getValidationState() == 'archived'] if q.getValidationState() == 'archived']
self.assertEqual(len(instance_tree_list), len(archived_open_sale_order_list))
archived_open_sale_order_list.sort(key=lambda x: x.getCreationDate()) line_list = []
for open_sale_order in archived_open_sale_order_list:
# Select the first archived archived_line_list = open_sale_order.contentValues(
open_sale_order = archived_open_sale_order_list[0]
line_list = open_sale_order.contentValues(
portal_type='Open Sale Order Line') portal_type='Open Sale Order Line')
self.assertEqual(1, len(archived_line_list))
line_list.extend(archived_line_list)
self.assertEqual(len(instance_tree_list), len(line_list)) self.assertEqual(len(instance_tree_list), len(line_list))
self.assertSameSet( self.assertSameSet(
[q.getRelativeUrl() for q in instance_tree_list], [q.getRelativeUrl() for q in instance_tree_list],
...@@ -637,15 +638,9 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin): ...@@ -637,15 +638,9 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin):
validated_open_sale_order_list = [q for q in open_sale_order_list validated_open_sale_order_list = [q for q in open_sale_order_list
if q.getValidationState() == 'validated'] if q.getValidationState() == 'validated']
# if no line, all open orders are kept archived # if no line, all open orders are kept archived
self.assertEqual(len(validated_open_sale_order_list), 0) self.assertEqual(len(validated_open_sale_order_list), 0)
latest_open_sale_order = archived_open_sale_order_list[-1]
line_list = latest_open_sale_order.contentValues(
portal_type='Open Sale Order Line')
self.assertEqual(len(line_list), 0)
def findMessage(self, email, body): def findMessage(self, email, body):
for candidate in reversed(self.portal.MailHost.getMessageList()): for candidate in reversed(self.portal.MailHost.getMessageList()):
if [q for q in candidate[1] if email in q] and body in candidate[2]: if [q for q in candidate[1] if email in q] and body in candidate[2]:
......
...@@ -1652,8 +1652,12 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans ...@@ -1652,8 +1652,12 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
software_type="default", software_type="default",
partition_reference="_test_subscription_scenario_with_existing_user_extra_instance", partition_reference="_test_subscription_scenario_with_existing_user_extra_instance",
) )
self.non_subscription_related_instance_amount = 1 self.non_subscription_related_instance_amount = 1
# Trigger open order creation
self.portal.portal_alarms.slapos_request_update_instance_tree_open_sale_order.activeSense()
self.tic()
self.login() self.login()
self.requestAndCheckInstanceTree( self.requestAndCheckInstanceTree(
amount, name, default_email_text) amount, name, default_email_text)
......
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