Commit f090874c authored by Rafael Monnerat's avatar Rafael Monnerat

slapos_*: Don't rely on Related started Payment Transaction

  Drop builder and alarm for update Confirmed Payment transaction
  Update Payment state gadget (JIO)
  Generate the link from the Sale Invoice Transaction rather them Payment (since they might not exist)
  crm: Update from Unpaid Payments to Unpaid Invoices
  Now we rely on lettered/non lettered invoices rather than payments.
parent f38a583a
......@@ -42,19 +42,27 @@ else:
elif context.getTotalPrice() == 0:
result = "Free!"
else:
# Check if there is an ongoing SlapOS payment
payment = context.SaleInvoiceTransaction_getSlapOSPaymentRelatedValue()
if payment is None:
result = "Unpaid"
else:
result = "Pay Now"
# Search to know if there are some payment waiting for confirmation
payment = portal.portal_catalog.getResultValue(
portal_type="Payment Transaction",
simulation_state="started",
default_causality_uid=context.getUid(),
default_payment_mode_uid=[portal.portal_categories.payment_mode.payzen.getUid(),
portal.portal_categories.payment_mode.wechat.getUid()],
)
if payment is not None:
# Check if mapping exists
external_payment_id = person.Person_restrictMethodAsShadowUser(
shadow_document=person,
callable_object=payment.PaymentTransaction_getExternalPaymentId,
argument_list=[])[0]
if external_payment_id is None:
result = "Pay Now"
if person is not None:
external_payment_id = person.Person_restrictMethodAsShadowUser(
shadow_document=person,
callable_object=payment.PaymentTransaction_getExternalPaymentId,
argument_list=[])[0]
else:
external_payment_id = payment.PaymentTransaction_getExternalPaymentId()
if external_payment_id is not None:
result = "Waiting for payment confirmation"
return result
payment_transaction = context.SaleInvoiceTransaction_getSlapOSPaymentRelatedValue()
if payment_transaction is not None:
return payment_transaction.getRelativeUrl()
<?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>**kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SaleInvoiceTransaction_getSlapOSPaymentRelated</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
return portal.portal_catalog.getResultValue(
portal_type="Payment Transaction",
simulation_state="started",
default_causality_uid=context.getUid(),
default_payment_mode_uid=[portal.portal_categories.payment_mode.payzen.getUid(),
portal.portal_categories.payment_mode.wechat.getUid()],
)
<?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>**kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SaleInvoiceTransaction_getSlapOSPaymentRelatedValue</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -36,7 +36,7 @@ class TestSlapOSEntityCreatePaymentMixin(SlapOSTestCaseMixin):
def assertPayment(self, payment, invoice):
self.assertEqual(self.sumReceivable(invoice), payment\
.PaymentTransaction_getTotalPayablePrice())
self.assertEqual('confirmed', payment.getSimulationState())
self.assertEqual('started', payment.getSimulationState())
self.assertSameSet([], payment.checkConsistency())
self.assertSameSet([invoice], payment.getCausalityValueList())
self.assertSameSet([], payment.getCausalityRelatedValueList(
......
# -*- coding: utf-8 -*-
# -*- coding:utf-8 -*-
##############################################################################
#
# Copyright (c) 2012 Nexedi SA and Contributors. All Rights Reserved.
# 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.
#
##############################################################################
......@@ -649,8 +663,7 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin):
self.assertEqual(None, to_click_message)
@changeSkin('RJS')
def useWechatManually(self, web_site, user_id, is_email_expected=True):
def usePaymentManually(self, web_site, user_id, is_email_expected=True, subscription_request=None):
person = self.portal.portal_catalog.getResultValue(
portal_type="Person",
user_id=user_id)
......@@ -658,37 +671,24 @@ class DefaultScenarioMixin(TestSlapOSSecurityMixin):
self.assertNotEqual(person, None)
self.assertInvoiceNotification(person, is_email_expected)
# If you are using live test, be aware that the call of the alarm can be
# not enough for the number of objects on the site.
document_id = self.portal.portal_catalog.getResultValue(
portal_type="Payment Transaction",
simulation_state="started",
destination_section_uid=person.getUid()
).getId()
web_site.accounting_module[document_id].\
PaymentTransaction_redirectToManualWechatPayment()
@changeSkin('RJS')
def usePayzenManually(self, web_site, user_id, is_email_expected=True):
person = self.portal.portal_catalog.getResultValue(
portal_type="Person",
user_id=user_id)
self.assertNotEqual(person, None)
self.assertInvoiceNotification(person, is_email_expected)
# Pay to payzen...
# If you are using live test, be aware that the call of the alarm can be
# not enough for the number of objects on the site.
document_id = self.portal.portal_catalog.getResultValue(
portal_type="Payment Transaction",
simulation_state="started",
destination_section_uid=person.getUid()
).getId()
invoice_list = person.Entity_getOutstandingAmountList()
if subscription_request is not None:
expected_causality = subscription_request.getRelativeUrl()
filtered_invoice_list = []
for invoice in invoice_list:
spl = invoice.getCausalityValue()
if spl is not None and spl.getCausality() == expected_causality:
filtered_invoice_list.append(invoice)
self.assertEqual(len(filtered_invoice_list), 1)
invoice_list = filtered_invoice_list
else:
self.assertEqual(len(invoice_list), 1)
document_id = invoice_list[0].getId()
web_site.accounting_module[document_id].\
PaymentTransaction_redirectToManualPayzenPayment()
SaleInvoiceTransaction_redirectToManualSlapOSPayment()
self.tic()
def assertSubscriptionStopped(self, person):
self.login()
......
......@@ -614,15 +614,6 @@ class SlapOSTestCaseMixin(testSlapOSMixin):
source="account_module/receivable",
quantity=-3,
)
payment = self.portal.accounting_module.newContent(
portal_type="Payment Transaction",
payment_mode=payment_mode,
causality_value=invoice,
destination_section=destination_section,
created_by_builder=1 # to prevent init script to create lines
)
self.portal.portal_workflow._jumpToStateFor(payment, 'started')
return invoice
......
......@@ -6,12 +6,6 @@
</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>SlapOSTestCaseMixin</string> </value>
......@@ -55,28 +49,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -89,7 +68,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -98,7 +77,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
......@@ -28,12 +28,12 @@ outstanding_amount = person.Entity_statSlapOSOutstandingAmount()
# Amount to be ignored, as it comes from the first invoice generated
# after the subscription. We do not take it into account as no service
# was provided yet.
unpaid_payment_amount = 0
for payment in person.Person_getSubscriptionRequestFirstUnpaidPaymentList():
unpaid_payment_amount += payment.PaymentTransaction_getTotalPayablePrice()
unpaid_invoice_amount = 0
for invoice in person.Person_getSubscriptionRequestFirstUnpaidInvoiceList():
unpaid_invoice_amount += invoice.getTotalPrice()
# It can't be smaller, we are considernig all open invoices are from unpaid_payment_amount
if round(float(outstanding_amount), 2) == round(-float(unpaid_payment_amount), 2):
if round(float(outstanding_amount), 2) == round(float(unpaid_invoice_amount), 2):
return ticket, None
if int(outstanding_amount) > 0:
......
......@@ -12,8 +12,8 @@ subscription_request_list = portal.portal_catalog(
creation_date=Query(creation_date=addToDate(DateTime(), to_add={'day': -20}), range="min"))
for subscription_request in subscription_request_list:
first_period_payment = subscription_request.SubscriptionRequest_verifyPaymentBalanceIsReady()
if first_period_payment is not None and first_period_payment.getSimulationState() == "started":
unpaid_list.append(first_period_payment)
first_invoice = subscription_request.SubscriptionRequest_verifyPaymentBalanceIsReady()
if first_invoice is not None and not first_invoice.SaleInvoiceTransaction_isLettered():
unpaid_list.append(first_invoice)
return unpaid_list
......@@ -54,7 +54,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_getSubscriptionRequestFirstUnpaidPaymentList</string> </value>
<value> <string>Person_getSubscriptionRequestFirstUnpaidInvoiceList</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -13,12 +13,12 @@ outstanding_amount = person.Entity_statSlapOSOutstandingAmount()
# Amount to be ignored, as it comes from the first invoice generated
# after the subscription. We do not take it into account as no service
# was provided yet.
unpaid_payment_amount = 0
for payment in person.Person_getSubscriptionRequestFirstUnpaidPaymentList():
unpaid_payment_amount += payment.PaymentTransaction_getTotalPayablePrice()
unpaid_invoice_amount = 0
for invoice in person.Person_getSubscriptionRequestFirstUnpaidInvoiceList():
unpaid_invoice_amount += invoice.getTotalPrice()
# It can't be smaller, we are considernig all open invoices are from unpaid_payment_amount
if round(float(outstanding_amount), 2) == round(-float(unpaid_payment_amount), 2):
if round(float(outstanding_amount), 2) == round(float(unpaid_invoice_amount), 2):
context.invalidate(comment="Automatically disabled as balance is %s" % outstanding_amount)
return
......
......@@ -27,6 +27,52 @@ from DateTime import DateTime
class TestSlapOSCRMCreateRegularisationRequest(SlapOSTestCaseMixin):
def createFinalInvoice(self, person):
template = self.portal.restrictedTraverse(
self.portal.portal_preferences.getPreferredDefaultPrePaymentSubscriptionInvoiceTemplate())
current_invoice = template.Base_createCloneDocument(batch_mode=1)
current_invoice.edit(
destination_value=person,
destination_section_value=person,
destination_decision_value=person,
start_date=DateTime('2019/10/20'),
stop_date=DateTime('2019/10/20'),
title='Fake Invoice for Demo User Functional',
price_currency="currency_module/EUR",
reference='1')
cell = current_invoice["1"]["movement_0"]
cell.edit(quantity=1)
cell.setPrice(1)
current_invoice.plan()
current_invoice.confirm()
current_invoice.startBuilding()
current_invoice.reindexObject()
current_invoice.stop()
self.tic()
current_invoice.Delivery_manageBuildingCalculatingDelivery()
self.tic()
applied_rule = current_invoice.getCausalityRelated(portal_type="Applied Rule")
for sm in self.portal.portal_catalog(portal_type='Simulation Movement',
simulation_state=['draft', 'planned', None],
left_join_list=['delivery_uid'],
delivery_uid=None,
path="%%%s%%" % applied_rule):
if sm.getDelivery() is not None:
continue
root_applied_rule = sm.getRootAppliedRule()
root_applied_rule_path = root_applied_rule.getPath()
sm.getCausalityValue(portal_type='Business Link').build(
path='%s/%%' % root_applied_rule_path)
return current_invoice
def test_alarm_expected_person(self):
new_id = self.generateNewId()
person = self.portal.person_module.newContent(
......@@ -35,14 +81,7 @@ class TestSlapOSCRMCreateRegularisationRequest(SlapOSTestCaseMixin):
)
person.validate()
payment = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Payment Transaction for TestSlapOSCRMCreateRegularisationRequest person %s" % new_id,
destination_section=person.getRelativeUrl(),
start_date=DateTime()
)
payment.confirm()
payment.start()
self.createFinalInvoice(person)
self.tic()
alarm = self.portal.portal_alarms.\
......@@ -56,17 +95,9 @@ class TestSlapOSCRMCreateRegularisationRequest(SlapOSTestCaseMixin):
title="Test person %s" % new_id
)
person.validate()
self.createFinalInvoice(person)
person.invalidate()
payment = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Payment Transaction for TestSlapOSCRMCreateRegularisationRequest person %s" % new_id,
destination_section=person.getRelativeUrl(),
start_date=DateTime()
)
payment.confirm()
payment.start()
self.tic()
alarm = self.portal.portal_alarms.\
slapos_crm_create_regularisation_request
......@@ -79,23 +110,31 @@ class TestSlapOSCRMCreateRegularisationRequest(SlapOSTestCaseMixin):
title="Test person %s" % new_id
)
person.validate()
current_invoice = self.createFinalInvoice(person)
payment_template = self.portal.restrictedTraverse(
self.portal.portal_preferences.getPreferredDefaultPrePaymentTemplate())
payment = payment_template.Base_createCloneDocument(batch_mode=1)
for line in payment.contentValues():
if line.getSource() == "account_module/payment_to_encash":
line.setQuantity(-1)
elif line.getSource() == "account_module/receivable":
line.setQuantity(1)
payment = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Payment Transaction for TestSlapOSCRMCreateRegularisationRequest person %s" % new_id,
destination_section=person.getRelativeUrl(),
start_date=DateTime()
)
payment.confirm()
payment.start()
payment.setCausalityValue(current_invoice)
payment.setDestinationSectionValue(person)
payment.stop()
self.tic()
self.tic()
alarm = self.portal.portal_alarms.\
slapos_crm_create_regularisation_request
self._test_alarm_not_visited(alarm, person, "Person_checkToCreateRegularisationRequest")
def test_alarm_payment_confirmed(self):
def test_alarm_payment_started(self):
new_id = self.generateNewId()
person = self.portal.person_module.newContent(
portal_type='Person',
......@@ -103,18 +142,26 @@ class TestSlapOSCRMCreateRegularisationRequest(SlapOSTestCaseMixin):
)
person.validate()
payment = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Payment Transaction for TestSlapOSCRMCreateRegularisationRequest person %s" % new_id,
destination_section=person.getRelativeUrl(),
start_date=DateTime()
)
current_invoice = self.createFinalInvoice(person)
payment_template = self.portal.restrictedTraverse(
self.portal.portal_preferences.getPreferredDefaultPrePaymentTemplate())
payment = payment_template.Base_createCloneDocument(batch_mode=1)
for line in payment.contentValues():
if line.getSource() == "account_module/payment_to_encash":
line.setQuantity(-1)
elif line.getSource() == "account_module/receivable":
line.setQuantity(1)
payment.confirm()
payment.start()
payment.setCausalityValue(current_invoice)
payment.setDestinationSectionValue(person)
self.tic()
alarm = self.portal.portal_alarms.\
slapos_crm_create_regularisation_request
self._test_alarm_not_visited(alarm, person, "Person_checkToCreateRegularisationRequest")
self._test_alarm(alarm, person, "Person_checkToCreateRegularisationRequest")
class TestSlapOSCrmInvalidateSuspendedRegularisationRequest(SlapOSTestCaseMixinWithAbort):
......
......@@ -149,7 +149,7 @@ def makeTestSlapOSCodingStyleTestCase(tested_business_template):
'slapos_crm_monitoring/Event_checkCustomerAsSourceOrDestinationConsistency',
'slapos_crm_monitoring/SupportRequest_checkCausalitySourceDestinationConsistency',
'slapos_crm_monitoring/SupportRequest_getLastEvent',
'slapos_crm/Person_getSubscriptionRequestFirstUnpaidPaymentList',
'slapos_crm/Person_getSubscriptionRequestFirstUnpaidInvoiceList',
'slapos_crm/RegularisationRequest_afterClone',
'slapos_crm/RegularisationRequest_getResourceItemList',
'slapos_crm/RegularisationRequest_init',
......
# -*- coding: utf-8 -*-
# -*- coding:utf-8 -*-
##############################################################################
#
# Copyright (c) 2012 Nexedi SA and Contributors. All Rights Reserved.
# Copyright (c) 2022 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.
#
##############################################################################
......@@ -249,10 +263,10 @@ class TestSlapOSDefaultScenario(DefaultScenarioMixin):
self.assertPersonDocumentCoverage(person)
self.login(public_person.getUserId())
self.usePayzenManually(self.web_site, public_person.getUserId())
self.usePaymentManually(self.web_site, public_person.getUserId())
self.login(friend_person.getUserId())
self.usePayzenManually(self.web_site, friend_person.getUserId())
self.usePaymentManually(self.web_site, friend_person.getUserId())
class TestSlapOSDefaultCRMEscalation(DefaultScenarioMixin):
......
......@@ -53,6 +53,7 @@
}
if (1 || (result.data.rows[i].hasOwnProperty("id"))) {
value = result.data.rows[i].value.AccountingTransaction_getPaymentStateAsHateoas;
value.jio_key = result.data.rows[i].id;
result.data.rows[i].value.AccountingTransaction_getPaymentStateAsHateoas = {
field_gadget_param : {
css_class: "",
......
......@@ -254,7 +254,7 @@
</tuple>
<state>
<tuple>
<float>1667590788.38</float>
<float>1671074456.17</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -53,6 +53,7 @@
}
if (1 || (result.data.rows[i].hasOwnProperty("id"))) {
value = result.data.rows[i].value.AccountingTransaction_getPaymentStateAsHateoas;
value.jio_key = result.data.rows[i].id;
result.data.rows[i].value.AccountingTransaction_getPaymentStateAsHateoas = {
field_gadget_param : {
css_class: "",
......
......@@ -236,7 +236,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>1004.6631.33059.11776</string> </value>
<value> <string>1004.12379.1853.8140</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -254,7 +254,7 @@
</tuple>
<state>
<tuple>
<float>1667930581.61</float>
<float>1671070228.44</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -160,7 +160,7 @@
"title": result[1][5],
"default": {
state: gadget.state.doc.payment_state,
payment_transaction: gadget.state.doc.payment_transaction
jio_key: gadget.state.jio_key
},
"css_class": "",
"required": 1,
......
......@@ -236,7 +236,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>999.2068.62564.17</string> </value>
<value> <string>1004.12196.28653.10734</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -254,7 +254,7 @@
</tuple>
<state>
<tuple>
<float>1667919626.06</float>
<float>1671070129.29</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -14,16 +14,15 @@
link;
return gadget.getTranslationDict(['Pay Now'])
.push(function (translation_dict) {
if ((gadget.state.payment_transaction !== null) &&
(gadget.state.payment_transaction !== undefined)) {
if (gadget.state.payment_state === 'Pay Now') {
link = domsugar("li", {},
[
domsugar("a", {
class: "ui-btn ui-first-child ui-btn-icon-center",
text: translation_dict["Pay Now"],
href: gadget.state.hateoas_url +
gadget.state.payment_transaction +
"/PaymentTransaction_redirectToManualSlapOSPayment"
gadget.state.jio_key +
"/SaleInvoiceTransaction_redirectToManualSlapOSPayment"
})
]);
} else {
......@@ -41,7 +40,7 @@
return gadget.getSetting("hateoas_url")
.push(function (hateoas_url) {
return gadget.changeState({
payment_transaction: options.value.payment_transaction,
jio_key: options.value.jio_key,
payment_state: options.value.state,
hateoas_url: hateoas_url
});
......
......@@ -254,7 +254,7 @@
</tuple>
<state>
<tuple>
<float>1667929052.34</float>
<float>1671070046.11</float>
<string>UTC</string>
</tuple>
</state>
......
state = context.AccountingTransaction_getPaymentState()
payment_transaction = None
payment_mode = None
if state == "Pay Now":
payment_transaction_value = context.SaleInvoiceTransaction_getSlapOSPaymentRelatedValue()
payment_transaction = payment_transaction_value.getRelativeUrl()
payment_mode = payment_transaction_value.getPaymentMode()
payment_mode = context.getPaymentMode() # ???
return {"state": context.Base_translateString(state),
"payment_mode": payment_mode,
"payment_transaction": payment_transaction}
"payment_mode": payment_mode}
......@@ -100,7 +100,6 @@
<string>my_resource_title</string>
<string>my_payment_transaction_external_id</string>
<string>my_payment_state</string>
<string>my_payment_transaction</string>
</list>
</value>
</item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>default</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_payment_transaction</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>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Payment Transaction</string> </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>python: context.SaleInvoiceTransaction_getSlapOSPaymentRelated()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -76,12 +76,12 @@
</tr>
<tr>
<td>waitForElementPresent</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'PaymentTransaction_redirectToManualSlapOSPayment')]</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'SaleInvoiceTransaction_redirectToManualSlapOSPayment')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'PaymentTransaction_redirectToManualSlapOSPayment')]</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'SaleInvoiceTransaction_redirectToManualSlapOSPayment')]</td>
<td></td>
</tr>
<tr>
......@@ -165,12 +165,12 @@
</tr>
<tr>
<td>waitForElementPresent</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'PaymentTransaction_redirectToManualSlapOSPayment')]</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'SaleInvoiceTransaction_redirectToManualSlapOSPayment')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'PaymentTransaction_redirectToManualSlapOSPayment')]</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'SaleInvoiceTransaction_redirectToManualSlapOSPayment')]</td>
<td></td>
</tr>
<tr>
......@@ -284,12 +284,12 @@
</tr>
<tr>
<td>waitForElementPresent</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'PaymentTransaction_redirectToManualSlapOSPayment')]</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'SaleInvoiceTransaction_redirectToManualSlapOSPayment')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'PaymentTransaction_redirectToManualSlapOSPayment')]</td>
<td> //div[contains(@data-gadget-url, 'gadget_slapos_invoice_state.html')]//a[contains(@href, 'SaleInvoiceTransaction_redirectToManualSlapOSPayment')]</td>
<td></td>
</tr>
<tr>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_updatePayzenConfirmedPaymentTransaction</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_payzen_update_confirmed_payment</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute_frequency</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1288051200.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>sense_method_id</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Handles confirmed Payment Transactions with PayZen interface</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Order Builder" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination/organisation_module/slapos</string>
<string>destination_section/organisation_module/slapos</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>delivery_after_generation_script_id</string> </key>
<value> <string>PaymentTransaction_postOrderBuild</string> </value>
</item>
<item>
<key> <string>delivery_cell_portal_type</string> </key>
<value> <string>Delivery Cell</string> </value>
</item>
<item>
<key> <string>delivery_cell_separate_order</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>delivery_line_portal_type</string> </key>
<value> <string>Accounting Transaction Line</string> </value>
</item>
<item>
<key> <string>delivery_module</string> </key>
<value> <string>accounting_module</string> </value>
</item>
<item>
<key> <string>delivery_portal_type</string> </key>
<value> <string>Payment Transaction</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_payment_transaction_builder</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Order Builder</string> </value>
</item>
<item>
<key> <string>simulation_select_method_id</string> </key>
<value> <string>OrderBuilder_generateUnrelatedInvoiceList</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Payment Builder</string> </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="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Movement Group" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>collect_order_group/delivery</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>category_movement_group_on_delivery</string> </value>
</item>
<item>
<key> <string>int_index</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Movement Group</string> </value>
</item>
<item>
<key> <string>tested_property</string> </key>
<value>
<tuple>
<string>causality</string>
<string>destination_payment</string>
<string>destination_section</string>
<string>price_currency</string>
<string>resource</string>
<string>source_payment</string>
<string>source_section</string>
<string>specialise</string>
<string>payment_mode</string>
</tuple>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>update_always</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Movement Group" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>collect_order_group/line</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>category_movement_group_on_line</string> </value>
</item>
<item>
<key> <string>int_index</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Movement Group</string> </value>
</item>
<item>
<key> <string>tested_property</string> </key>
<value>
<tuple>
<string>destination</string>
<string>source</string>
</tuple>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>update_always</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Property Movement Group" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>collect_order_group/line</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>property_movement_group_on_line</string> </value>
</item>
<item>
<key> <string>int_index</string> </key>
<value> <int>2</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Property Movement Group</string> </value>
</item>
<item>
<key> <string>tested_property</string> </key>
<value>
<tuple>
<string>start_date</string>
<string>stop_date</string>
</tuple>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>property_movement_group_on_line</string> </value>
</item>
<item>
<key> <string>update_always</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
portal.portal_catalog.searchAndActivate(
portal_type="Payment Transaction",
simulation_state=["confirmed"],
causality_state=["draft"],
payment_mode_uid=portal.portal_categories.payment_mode.payzen.getUid(),
method_id='PaymentTransaction_startPayzenPayment',
packet_size=1, # just one to minimise errors
activate_kw={'tag': tag}
)
context.activate(after_tag=tag).getId()
<?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>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_updatePayzenConfirmedPaymentTransaction</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
newTempSimulationMovement = portal.portal_trash.newContent
select_dict = {
'causality_payment_transaction_related_uid': None,
'causality_subscription_request_related_uid': None,
}
select_kw = kwargs.copy()
select_kw.pop('portal_type', None)
select_kw.pop('delivery_relative_url_list', None)
select_kw.update(
portal_type='Sale Invoice Transaction',
simulation_state='stopped',
default_payment_mode_uid=(portal.portal_categories.payment_mode.payzen.getUid(),
portal.portal_categories.payment_mode.wechat.getUid()),
limit=10, # do only some in one shot
select_dict=select_dict,
left_join_list=select_dict.keys(),
causality_payment_transaction_related_uid=None,
causality_subscription_request_related_uid=None
)
default_source_uid=portal.restrictedTraverse('account_module/receivable').getUid()
movement_list = []
_id = 1
for invoice in portal.portal_catalog(**select_kw):
invoice.getObject().serialize() # in order to avoid selection on concurrent transactions
payment_tag = "sale_invoice_transaction_order_builder_%s" % invoice.getObject().getUid()
if context.REQUEST.get(payment_tag, None) is not None or \
context.portal_activities.countMessageWithTag(payment_tag) > 0:
# Invoice was selected before the payment be indexed or it was already created on this transaction
# so skip the invoice for now.
continue
quantity = 0.
for movement in invoice.searchFolder(portal_type='Sale Invoice Transaction Line',
default_source_uid=default_source_uid):
quantity += movement.getQuantity()
temp_movement_kw = dict(
portal_type="Simulation Movement",
causality=invoice.getRelativeUrl(),
source_section=invoice.getSourceSection(),
destination_section=invoice.getDestinationSection(),
resource=invoice.getResource(),
price_currency=invoice.getResource(),
start_date=invoice.getStartDate(),
stop_date=invoice.getStopDate(),
specialise=invoice.getSpecialise(),
payment_mode=invoice.getPaymentMode(),
source_payment='%s/bank_account' % invoice.getSourceSection(), # the other place defnied: business process
)
temp_movement_rec = newTempSimulationMovement(
temp_object=True, id=str(_id),
quantity=-1 * quantity,
source='account_module/receivable',
destination='account_module/payable',
**temp_movement_kw
)
_id += 1
temp_movement_bank = newTempSimulationMovement(
temp_object=True, id=str(_id),
quantity=1 * quantity,
source='account_module/payment_to_encash',
destination='account_module/payment_to_encash',
**temp_movement_kw
)
_id += 1
movement_list.extend([temp_movement_rec, temp_movement_bank])
return movement_list
<?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>*args, **kwargs</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>OrderBuilder_generateUnrelatedInvoiceList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from DateTime import DateTime
state = context.getSimulationState()
transaction_amount = int(round((context.PaymentTransaction_getTotalPayablePrice() * -100), 2))
if (state != 'confirmed') or (context.getPaymentMode() != 'payzen') or (transaction_amount == 0):
if (transaction_amount == 0):
invoice = context.getCausalityValue(portal_types="Sale Invoice Transaction")
if invoice is not None and round(invoice.getTotalPrice(), 2) == 0:
context.edit(payment_mode="wire_transfer")
return
else:
# Request manual payment
context.start(comment='Requested manual payment')
<?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>PaymentTransaction_startPayzenPayment</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved.
# -*- coding:utf-8 -*-
##############################################################################
#
# Copyright (c) 2022 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.SlapOSTestCaseMixin import SlapOSTestCaseMixinWithAbort
from Products.ERP5Type.tests.utils import createZODBPythonScript
from DateTime import DateTime
class TestSlapOSPayzenUpdateConfirmedPayment(SlapOSTestCaseMixinWithAbort):
def _simulatePaymentTransaction_startPayzenPayment(self):
script_name = 'PaymentTransaction_startPayzenPayment'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kwargs',
'# Script body\n'
"""portal_workflow = context.portal_workflow
portal_workflow.doActionFor(context, action='edit_action', comment='Visited by PaymentTransaction_startPayzenPayment') """ )
self.commit()
def _dropPaymentTransaction_startPayzenPayment(self):
script_name = 'PaymentTransaction_startPayzenPayment'
if script_name in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(script_name)
self.commit()
def test_alarm_confirmed_draft_payzen(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="payzen",
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
self.tic()
self._simulatePaymentTransaction_startPayzenPayment()
try:
self.portal.portal_alarms.slapos_payzen_update_confirmed_payment.activeSense()
self.tic()
finally:
self._dropPaymentTransaction_startPayzenPayment()
self.tic()
self.assertEqual(
'Visited by PaymentTransaction_startPayzenPayment',
transaction.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_not_confirmed(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="payzen",
)
self.tic()
self._simulatePaymentTransaction_startPayzenPayment()
try:
self.portal.portal_alarms.slapos_payzen_update_confirmed_payment.activeSense()
self.tic()
finally:
self._dropPaymentTransaction_startPayzenPayment()
self.tic()
self.assertNotEqual(
'Visited by PaymentTransaction_startPayzenPayment',
transaction.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_not_draft(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="payzen",
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
self.portal.portal_workflow._jumpToStateFor(transaction, 'solved')
self.tic()
self._simulatePaymentTransaction_startPayzenPayment()
try:
self.portal.portal_alarms.slapos_payzen_update_confirmed_payment.activeSense()
self.tic()
finally:
self._dropPaymentTransaction_startPayzenPayment()
self.tic()
self.assertNotEqual(
'Visited by PaymentTransaction_startPayzenPayment',
transaction.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_not_payzen(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
self.tic()
self._simulatePaymentTransaction_startPayzenPayment()
try:
self.portal.portal_alarms.slapos_payzen_update_confirmed_payment.activeSense()
self.tic()
finally:
self._dropPaymentTransaction_startPayzenPayment()
self.tic()
self.assertNotEqual(
'Visited by PaymentTransaction_startPayzenPayment',
transaction.workflow_history['edit_workflow'][-1]['comment'])
def _simulatePaymentTransaction_getTotalPayablePrice(self):
script_name = 'PaymentTransaction_getTotalPayablePrice'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kwargs',
'# Script body\n'
"""return 1""")
self.commit()
def _simulatePaymentTransaction_getZeroTotalPayablePrice(self):
script_name = 'PaymentTransaction_getTotalPayablePrice'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kwargs',
'# Script body\n'
"""return 0""")
self.commit()
def _dropPaymentTransaction_getTotalPayablePrice(self):
script_name = 'PaymentTransaction_getTotalPayablePrice'
if script_name in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(script_name)
self.commit()
def test_not_confirmed_payment(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="payzen",
)
simulation_state = transaction.getSimulationState()
modification_date = transaction.getModificationDate()
self._simulatePaymentTransaction_getTotalPayablePrice()
try:
transaction.PaymentTransaction_startPayzenPayment()
finally:
self._dropPaymentTransaction_getTotalPayablePrice()
self.assertEqual(transaction.getSimulationState(), simulation_state)
self.assertEqual(transaction.getModificationDate(), modification_date)
def test_not_payzen_payment(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
simulation_state = transaction.getSimulationState()
modification_date = transaction.getModificationDate()
self._simulatePaymentTransaction_getTotalPayablePrice()
try:
transaction.PaymentTransaction_startPayzenPayment()
finally:
self._dropPaymentTransaction_getTotalPayablePrice()
self.assertEqual(transaction.getSimulationState(), simulation_state)
self.assertEqual(transaction.getModificationDate(), modification_date)
def test_zero_amount_payment(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="payzen",
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
simulation_state = transaction.getSimulationState()
modification_date = transaction.getModificationDate()
self._simulatePaymentTransaction_getZeroTotalPayablePrice()
try:
transaction.PaymentTransaction_startPayzenPayment()
finally:
self._dropPaymentTransaction_getTotalPayablePrice()
self.assertEqual(transaction.getSimulationState(), simulation_state)
self.assertEqual(transaction.getModificationDate(), modification_date)
def test_expected_payment(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="payzen",
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
self._simulatePaymentTransaction_getTotalPayablePrice()
try:
transaction.PaymentTransaction_startPayzenPayment()
finally:
self._dropPaymentTransaction_getTotalPayablePrice()
self.assertEqual(transaction.getSimulationState(), 'started')
class TestSlapOSPayzenUpdateStartedPayment(SlapOSTestCaseMixinWithAbort):
def test_not_started_payment(self):
......
......@@ -6,12 +6,6 @@
</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>testSlapOSPayzenAlarm</string> </value>
......@@ -55,28 +49,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -89,7 +68,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -98,7 +77,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
# Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved.
# -*- coding:utf-8 -*-
##############################################################################
#
# Copyright (c) 2022 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.SlapOSTestCaseMixin import SlapOSTestCaseMixinWithAbort
from DateTime import DateTime
......@@ -831,25 +851,6 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
self.assertEqual("%s/already_registered" % payment.getRelativeUrl(),
redirect)
class TestSlapOSPayzenSaleInvoiceTransaction_getSlapOSPaymentRelatedValue(
SlapOSTestCaseMixinWithAbort):
def test_SaleInvoiceTransaction_getSlapOSPaymentRelatedValue(self):
invoice = self.createPayzenSaleInvoiceTransaction()
self.tic()
payment = invoice.SaleInvoiceTransaction_getSlapOSPaymentRelatedValue()
self.assertNotEqual(None, payment)
self.assertEqual(payment.getSimulationState(), "started")
self.assertEqual(payment.getCausalityValue(), invoice)
self.assertEqual(payment.getPaymentModeUid(),
self.portal.portal_categories.payment_mode.payzen.getUid())
payment.setStartDate(DateTime())
payment.stop()
payment.immediateReindexObject()
payment = invoice.SaleInvoiceTransaction_getSlapOSPaymentRelatedValue()
self.assertEqual(None, payment)
class TestSlapOSPayzenSaleInvoiceTransaction_createReversalPayzenTransaction(
SlapOSTestCaseMixinWithAbort):
......
accounting_module/template_sale_invoice_transaction
accounting_module/template_sale_invoice_transaction/**
portal_alarms/slapos_payzen_update_confirmed_payment
portal_alarms/slapos_payzen_update_started_payment
portal_integrations/slapos_payzen_test_integration
portal_integrations/slapos_payzen_test_integration/Causality
portal_integrations/slapos_payzen_test_integration/Resource
portal_integrations/slapos_payzen_test_integration/Resource/**
portal_integrations/slapos_payzen_test_integration/SourceProject
portal_orders/slapos_payment_transaction_builder
portal_orders/slapos_payment_transaction_builder/**
portal_secure_payments/slapos_payzen_test
portal_secure_payments/slapos_payzen_test/**
sale_trade_condition_module/payzen_sale_trade_condition
......
......@@ -25,7 +25,7 @@ notification_mapping_dict = {
'name': recipient.getTitle(),
'subscription_title': context.getTitle(),
# Possible more actions goes here
'payment_relative_relative_url': payment.getRelativeUrl()}
'payment_relative_relative_url': invoice.getRelativeUrl()}
# Preserve HTML else convert to text
if notification_message.getContentType() == "text/html":
......
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>payment</string> </value>
<value> <string>invoice</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
......@@ -32,19 +32,17 @@ if instance_tree is not None:
context.start(comment=comment)
context.stop(comment=comment)
first_period_payment = context.SubscriptionRequest_verifyPaymentBalanceIsReady()
if not first_period_payment:
# Payment isn't available for the user
invoice = context.SubscriptionRequest_verifyPaymentBalanceIsReady()
if not invoice:
# Invoice isn't available for the user to Pay
return "Skipped (Payment isn't ready)"
if not context.SubscriptionRequest_verifyInstanceIsAllocated():
# Only continue if instance is ready
return "Skipped (Instance isn't ready)"
invoice = first_period_payment.getCausalityValue()
# Link to be sent is the invoice one
if context.SubscriptionRequest_notifyPaymentIsReady(payment=invoice):
if context.SubscriptionRequest_notifyPaymentIsReady(invoice):
context.confirm(comment="Payment is ready for the user")
return "Payment is ready for the user"
......
portal = context.getPortalObject()
payment = context.SubscriptionRequest_verifyPaymentBalanceIsReady()
invoice = context.SubscriptionRequest_verifyPaymentBalanceIsReady()
if payment is not None:
if payment.getSimulationState() in ['stopped', 'delivered']:
# Payment Transaction is payed
if invoice is not None:
if invoice.SaleInvoiceTransaction_isLettered():
# Invoice is payed
return True
person = context.getDestinationSectionValue()
......@@ -18,5 +18,5 @@ if payment is not None:
not (person.Entity_statSlapOSOutstandingAmount() > 0)):
return True
# Payment Transaction isn't payed
# Invoice isn't payed
return False
......@@ -25,12 +25,10 @@ for packing_list in portal.portal_catalog(
):
for invoice in packing_list.getCausalityRelatedValueList(
portal_type="Sale Invoice Transaction"):
for payment in invoice.getCausalityRelatedValueList(
portal_type=["Payment Transaction", "Sale Invoice Transaction"]):
if payment.getSimulationState() in ["stopped", "delivered", "started"]:
# Invoice is already paied so we just move foward
if not payment.checkConsistency():
return payment
# XXX How to check if the invoice is ready to be payed
if invoice.getSimulationState() in ['stopped', 'delivered'] and \
not invoice.checkConsistency():
return invoice
# Payment isn't ready
return
# Invoice inst ready to be payed
......@@ -338,9 +338,9 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
notification_message="subscription_request-payment-is-ready"):
self.checkSubscriptionRequest(subscription_request, email,
subscription_condition)
payment = subscription_request.SubscriptionRequest_verifyPaymentBalanceIsReady()
self.assertNotEqual(payment, None)
self.assertEqual(payment.getSimulationState(), 'started')
invoice = subscription_request.SubscriptionRequest_verifyPaymentBalanceIsReady()
self.assertNotEqual(invoice, None)
self.assertEqual(invoice.getSimulationState(), 'stopped')
# Assert instance is allocated and without error
self.assertEqual(True,
......@@ -375,13 +375,9 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
person = subscription_request.getDestinationSectionValue()
self.login(person.getUserId())
payment = self.portal.portal_catalog.getResultValue(
portal_type="Payment Transaction",
simulation_state="started")
sale_transaction_invoice = payment.getCausalityValue(
portal_type="Sale Invoice Transaction"
)
invoice_list = person.Entity_getOutstandingAmountList()
self.assertEqual(len(invoice_list), 1)
sale_transaction_invoice = invoice_list[0].getObject()
self.logout()
self.login()
......@@ -447,8 +443,11 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
quantity = subscription_request.getQuantity()
self.login(person.getUserId())
self.usePayzenManually(self.web_site, person.getUserId(), is_email_expected=False)
self.usePaymentManually(
self.web_site,
person.getUserId(),
is_email_expected=False,
subscription_request=subscription_request)
self.logout()
self.login()
......@@ -485,7 +484,10 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
quantity = subscription_request.getQuantity()
self.login(person.getUserId())
self.usePayzenManually(self.web_site, person.getUserId())
self.usePaymentManually(
self.web_site,
person.getUserId(),
subscription_request=subscription_request)
self.logout()
self.login()
......@@ -524,7 +526,11 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
self.portal.portal_secure_payments.slapos_wechat_test.setWechatMode("UNITTEST")
self.login(person.getUserId())
self.useWechatManually(self.web_site, person.getUserId(), is_email_expected=False)
self.usePaymentManually(
self.web_site,
person.getUserId(),
is_email_expected=False,
subscription_request=subscription_request)
self.logout()
self.login()
......@@ -556,7 +562,10 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
self.portal.portal_secure_payments.slapos_wechat_test.setWechatMode("UNITTEST")
self.login(person.getUserId())
self.useWechatManually(self.web_site, person.getUserId())
self.usePaymentManually(
self.web_site,
person.getUserId(),
subscription_request=subscription_request)
self.logout()
self.login()
......@@ -972,9 +981,8 @@ return dict(vads_url_already_registered="%s/already_registered" % (payment_trans
"TestSubscriptionSkins Notification Message %s %s" % (
subscription_request.getLanguage(), notification_message),
mail_message.getTitle())
payment = subscription_request.SubscriptionRequest_verifyPaymentBalanceIsReady()
self.assertEqual(payment.getSimulationState(), 'started')
invoice = payment.getCausalityValue()
invoice = subscription_request.SubscriptionRequest_verifyPaymentBalanceIsReady()
self.assertEqual(invoice.getSimulationState(), 'stopped')
self.assertTrue(invoice.getRelativeUrl() in \
mail_message.getTextContent())
self.assertTrue(subscription_request.getDestinationSectionTitle() in \
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_updateWechatConfirmedPaymentTransaction</string> </value>
</item>
<item>
<key> <string>automatic_solve</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_wechat_update_confirmed_payment</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute_frequency</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1288051200.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>sense_method_id</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Handles confirmed Payment Transactions with Wechat interface</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
portal.portal_catalog.searchAndActivate(
portal_type="Payment Transaction",
simulation_state=["confirmed"],
causality_state=["draft"],
payment_mode_uid=portal.portal_categories.payment_mode.wechat.getUid(),
method_id='PaymentTransaction_startWechatPayment',
packet_size=1, # just one to minimise errors
activate_kw={'tag': tag}
)
context.activate(after_tag=tag).getId()
<?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>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_updateWechatConfirmedPaymentTransaction</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from DateTime import DateTime
state = context.getSimulationState()
transaction_amount = int(round((context.PaymentTransaction_getTotalPayablePrice() * -100), 2))
if (state != 'confirmed') or (context.getPaymentMode() != 'wechat') or (transaction_amount == 0):
if (transaction_amount == 0):
invoice = context.getCausalityValue(portal_types="Sale Invoice Transaction")
if invoice is not None and round(invoice.getTotalPrice(), 2) == 0:
context.edit(payment_mode="wire_transfer")
return
else:
# Request manual payment
context.start(comment='Requested manual payment')
<?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>PaymentTransaction_startWechatPayment</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved.
# -*- coding:utf-8 -*-
##############################################################################
#
# Copyright (c) 2022 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.SlapOSTestCaseMixin import SlapOSTestCaseMixinWithAbort
from Products.ERP5Type.tests.utils import createZODBPythonScript
from DateTime import DateTime
class TestSlapOSWechatUpdateConfirmedPayment(SlapOSTestCaseMixinWithAbort):
def _simulatePaymentTransaction_startWechatPayment(self):
script_name = 'PaymentTransaction_startWechatPayment'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kwargs',
'# Script body\n'
"""portal_workflow = context.portal_workflow
portal_workflow.doActionFor(context, action='edit_action', comment='Visited by PaymentTransaction_startWechatPayment') """ )
self.commit()
def _dropPaymentTransaction_startWechatPayment(self):
script_name = 'PaymentTransaction_startWechatPayment'
if script_name in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(script_name)
self.commit()
def test_alarm_confirmed_draft_wechat(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="wechat",
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
self.tic()
self._simulatePaymentTransaction_startWechatPayment()
try:
self.portal.portal_alarms.slapos_wechat_update_confirmed_payment.activeSense()
self.tic()
finally:
self._dropPaymentTransaction_startWechatPayment()
self.tic()
self.assertEqual(
'Visited by PaymentTransaction_startWechatPayment',
transaction.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_not_confirmed(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="wechat",
)
self.tic()
self._simulatePaymentTransaction_startWechatPayment()
try:
self.portal.portal_alarms.slapos_wechat_update_confirmed_payment.activeSense()
self.tic()
finally:
self._dropPaymentTransaction_startWechatPayment()
self.tic()
self.assertNotEqual(
'Visited by PaymentTransaction_startWechatPayment',
transaction.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_not_draft(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="wechat",
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
self.portal.portal_workflow._jumpToStateFor(transaction, 'solved')
self.tic()
self._simulatePaymentTransaction_startWechatPayment()
try:
self.portal.portal_alarms.slapos_wechat_update_confirmed_payment.activeSense()
self.tic()
finally:
self._dropPaymentTransaction_startWechatPayment()
self.tic()
self.assertNotEqual(
'Visited by PaymentTransaction_startWechatPayment',
transaction.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_not_wechat(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
self.tic()
self._simulatePaymentTransaction_startWechatPayment()
try:
self.portal.portal_alarms.slapos_wechat_update_confirmed_payment.activeSense()
self.tic()
finally:
self._dropPaymentTransaction_startWechatPayment()
self.tic()
self.assertNotEqual(
'Visited by PaymentTransaction_startWechatPayment',
transaction.workflow_history['edit_workflow'][-1]['comment'])
def _simulatePaymentTransaction_getTotalPayablePrice(self):
script_name = 'PaymentTransaction_getTotalPayablePrice'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kwargs',
'# Script body\n'
"""return 1""")
self.commit()
def _simulatePaymentTransaction_getZeroTotalPayablePrice(self):
script_name = 'PaymentTransaction_getTotalPayablePrice'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kwargs',
'# Script body\n'
"""return 0""")
self.commit()
def _dropPaymentTransaction_getTotalPayablePrice(self):
script_name = 'PaymentTransaction_getTotalPayablePrice'
if script_name in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(script_name)
self.commit()
def test_not_confirmed_payment(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="wechat",
)
simulation_state = transaction.getSimulationState()
modification_date = transaction.getModificationDate()
self._simulatePaymentTransaction_getTotalPayablePrice()
try:
transaction.PaymentTransaction_startWechatPayment()
finally:
self._dropPaymentTransaction_getTotalPayablePrice()
self.assertEqual(transaction.getSimulationState(), simulation_state)
self.assertEqual(transaction.getModificationDate(), modification_date)
def test_not_wechat_payment(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
simulation_state = transaction.getSimulationState()
modification_date = transaction.getModificationDate()
self._simulatePaymentTransaction_getTotalPayablePrice()
try:
transaction.PaymentTransaction_startWechatPayment()
finally:
self._dropPaymentTransaction_getTotalPayablePrice()
self.assertEqual(transaction.getSimulationState(), simulation_state)
self.assertEqual(transaction.getModificationDate(), modification_date)
def test_zero_amount_payment(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="wechat",
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
simulation_state = transaction.getSimulationState()
modification_date = transaction.getModificationDate()
self._simulatePaymentTransaction_getZeroTotalPayablePrice()
try:
transaction.PaymentTransaction_startWechatPayment()
finally:
self._dropPaymentTransaction_getTotalPayablePrice()
self.assertEqual(transaction.getSimulationState(), simulation_state)
self.assertEqual(transaction.getModificationDate(), modification_date)
def test_expected_payment(self):
new_id = self.generateNewId()
transaction = self.portal.accounting_module.newContent(
portal_type='Payment Transaction',
title="Transaction %s" % new_id,
reference="TESTTRANS-%s" % new_id,
payment_mode="wechat",
)
self.portal.portal_workflow._jumpToStateFor(transaction, 'confirmed')
self._simulatePaymentTransaction_getTotalPayablePrice()
try:
transaction.PaymentTransaction_startWechatPayment()
finally:
self._dropPaymentTransaction_getTotalPayablePrice()
self.assertEqual(transaction.getSimulationState(), 'started')
class TestSlapOSWechatUpdateStartedPayment(SlapOSTestCaseMixinWithAbort):
def test_not_started_payment(self):
......
......@@ -6,12 +6,6 @@
</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>testSlapOSWechatAlarm</string> </value>
......@@ -55,28 +49,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -89,7 +68,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -98,7 +77,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
image_module/wechat**
portal_alarms/slapos_wechat_update_confirmed_payment
portal_alarms/slapos_wechat_update_started_payment
portal_integrations/slapos_wechat_test_integration
portal_integrations/slapos_wechat_test_integration/Causality
......
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