Commit 06ad7526 authored by Romain Courteaud's avatar Romain Courteaud

Script to create reversal invoice.

It can only be applied in case of manual payment for now.
parent 01dbb5cf
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Sale Trade Condition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Author</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>slapos_manual_accounting_trade_condition</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_manual_accounting_trade_condition</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Trade Condition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>SlapOS Manual Accounting Sale Trade Condition</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>start_date</string> </key>
<value>
<tuple>
<none/>
<none/>
</tuple>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="6" aka="AAAAAAAAAAY=">
<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="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>_body</string> </key>
<value> <string>""" Create a reversal transaction from current payzen transaction. """\n
from zExceptions import Unauthorized\n
if REQUEST is not None:\n
raise Unauthorized\n
\n
portal = context.getPortalObject()\n
\n
# Check that we are in state that we are waiting for user manual payment\n
assert context.getPortalType() == \'Sale Invoice Transaction\'\n
assert context.getPaymentMode() == \'payzen\'\n
assert context.getSimulationState() == \'stopped\'\n
assert context.getTotalPrice() != 0\n
assert context.getSpecialise() == "sale_trade_condition_module/slapos_aggregated_trade_condition"\n
\n
paid = True\n
for line in context.getMovementList(portal.getPortalAccountingMovementTypeList()):\n
node_value = line.getSourceValue(portal_type=\'Account\')\n
if node_value.getAccountType() == \'asset/receivable\':\n
if not line.hasGroupingReference():\n
paid = False\n
break\n
assert not paid\n
\n
payment = portal.portal_catalog.getResultValue(\n
portal_type="Payment Transaction",\n
simulation_state="started",\n
default_causality_uid=context.getUid(),\n
default_payment_mode_uid=portal.portal_categories.payment_mode.payzen.getUid(),\n
)\n
assert payment is not None\n
assert payment.getSimulationState() == \'started\'\n
assert payment.getPaymentMode() == \'payzen\'\n
assert payment.PaymentTransaction_getPayzenId()[1] is None\n
\n
# Should be safe now to fix everything\n
context.edit(payment_mode=None)\n
payment.edit(payment_mode=None)\n
reversal_transaction = context.Base_createCloneDocument(batch_mode=1)\n
payment.cancel(\n
comment="Reversal sale invoice transaction created %s" % reversal_transaction.getRelativeUrl())\n
\n
reversal_transaction.edit(\n
title="Reversal Transaction for %s" % context.getTitle(),\n
causality_value=context,\n
description="Reversal Transaction for %s" % context.getTitle(),\n
specialise_value=portal.sale_trade_condition_module.slapos_manual_accounting_trade_condition,\n
)\n
\n
for line in context.getMovementList():\n
line.edit(quantity=(-line.getQuantity()))\n
\n
reversal_transaction.confirm(comment="Automatic because of reversal creation")\n
reversal_transaction.stop(comment="Automatic because of reversal creation")\n
\n
return reversal_transaction\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SaleInvoiceTransaction_createReversalPayzenTransaction</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -687,3 +687,184 @@ class TestSlapOSPayzenBase_getPayzenServiceRelativeUrl(testSlapOSMixin): ...@@ -687,3 +687,184 @@ class TestSlapOSPayzenBase_getPayzenServiceRelativeUrl(testSlapOSMixin):
def test_getPayzenServiceRelativeUrl_default_result(self): def test_getPayzenServiceRelativeUrl_default_result(self):
result = self.portal.Base_getPayzenServiceRelativeUrl() result = self.portal.Base_getPayzenServiceRelativeUrl()
self.assertEquals(result, 'portal_secure_payments/slapos_payzen_test') self.assertEquals(result, 'portal_secure_payments/slapos_payzen_test')
class TestSlapOSPayzenSaleInvoiceTransaction_createReversalPayzenTransaction(
testSlapOSMixin):
def beforeTearDown(self):
transaction.abort()
def createPayzenSaleInvoiceTransaction(self):
new_title = self.generateNewId()
new_reference = self.generateNewId()
new_source_reference = self.generateNewId()
new_destination_reference = self.generateNewId()
invoice = self.portal.accounting_module.newContent(
portal_type="Sale Invoice Transaction",
title=new_title,
start_date=DateTime(),
reference=new_reference,
source_reference=new_source_reference,
destination_reference=new_destination_reference,
payment_mode="payzen",
specialise="sale_trade_condition_module/slapos_aggregated_trade_condition",
created_by_builder=1 # to prevent init script to create lines
)
self.portal.portal_workflow._jumpToStateFor(invoice, 'stopped')
invoice.newContent(
title="",
portal_type="Invoice Line",
quantity=-2,
price=2,
)
invoice.newContent(
portal_type="Sale Invoice Transaction Line",
source="account_module/receivable",
quantity=-3,
)
payment = self.portal.accounting_module.newContent(
portal_type="Payment Transaction",
payment_mode="payzen",
causality_value=invoice,
created_by_builder=1 # to prevent init script to create lines
)
self.portal.portal_workflow._jumpToStateFor(payment, 'started')
return invoice
def test_createReversalPayzenTransaction_REQUEST_disallowed(self):
self.assertRaises(
Unauthorized,
self.portal.SaleInvoiceTransaction_createReversalPayzenTransaction,
REQUEST={})
def test_createReversalPayzenTransaction_bad_portal_type(self):
self.assertRaises(
AssertionError,
self.portal.SaleInvoiceTransaction_createReversalPayzenTransaction)
def test_createReversalPayzenTransaction_bad_payment_mode(self):
invoice = self.createPayzenSaleInvoiceTransaction()
invoice.edit(payment_mode="cash")
self.tic()
self.assertRaises(
AssertionError,
invoice.SaleInvoiceTransaction_createReversalPayzenTransaction)
def test_createReversalPayzenTransaction_bad_state(self):
invoice = self.createPayzenSaleInvoiceTransaction()
self.portal.portal_workflow._jumpToStateFor(invoice, 'delivered')
self.tic()
self.assertRaises(
AssertionError,
invoice.SaleInvoiceTransaction_createReversalPayzenTransaction)
def test_createReversalPayzenTransaction_zero_price(self):
invoice = self.createPayzenSaleInvoiceTransaction()
invoice.manage_delObjects(invoice.contentIds())
self.tic()
self.assertRaises(
AssertionError,
invoice.SaleInvoiceTransaction_createReversalPayzenTransaction)
def test_createReversalPayzenTransaction_wrong_trade_condition(self):
invoice = self.createPayzenSaleInvoiceTransaction()
invoice.edit(specialise=None)
self.tic()
self.assertRaises(
AssertionError,
invoice.SaleInvoiceTransaction_createReversalPayzenTransaction)
def test_createReversalPayzenTransaction_paid(self):
invoice = self.createPayzenSaleInvoiceTransaction()
line = invoice.contentValues(portal_type="Sale Invoice Transaction Line")[0]
line.edit(grouping_reference="azerty")
self.tic()
self.assertRaises(
AssertionError,
invoice.SaleInvoiceTransaction_createReversalPayzenTransaction)
def test_createReversalPayzenTransaction_no_payment(self):
invoice = self.createPayzenSaleInvoiceTransaction()
# Do not reindex payment. portal_catalog will not find it.
self.assertRaises(
AssertionError,
invoice.SaleInvoiceTransaction_createReversalPayzenTransaction)
def test_createReversalPayzenTransaction_no_payzen_payment(self):
invoice = self.createPayzenSaleInvoiceTransaction()
self.tic()
payment = invoice.getCausalityRelatedValue()
payment.edit(payment_mode="cash")
self.assertRaises(
AssertionError,
invoice.SaleInvoiceTransaction_createReversalPayzenTransaction)
def test_createReversalPayzenTransaction_no_payment_state(self):
invoice = self.createPayzenSaleInvoiceTransaction()
self.tic()
payment = invoice.getCausalityRelatedValue()
self.portal.portal_workflow._jumpToStateFor(payment, 'cancelled')
self.assertRaises(
AssertionError,
invoice.SaleInvoiceTransaction_createReversalPayzenTransaction)
def test_createReversalPayzenTransaction_registered_payment(self):
invoice = self.createPayzenSaleInvoiceTransaction()
self.tic()
payment = invoice.getCausalityRelatedValue()
payment.PaymentTransaction_generatePayzenId()
self.assertRaises(
AssertionError,
invoice.SaleInvoiceTransaction_createReversalPayzenTransaction)
def test_createReversalPayzenTransaction_ok(self):
invoice = self.createPayzenSaleInvoiceTransaction()
self.tic()
payment = invoice.getCausalityRelatedValue()
reversale_invoice = invoice.\
SaleInvoiceTransaction_createReversalPayzenTransaction()
self.assertEqual(invoice.getPaymentMode(""), "")
self.assertEqual(payment.getPaymentMode(""), "")
self.assertEqual(payment.getSimulationState(), "cancelled")
self.assertEqual(reversale_invoice.getTitle(),
"Reversal Transaction for %s" % invoice.getTitle())
self.assertEqual(reversale_invoice.getDescription(),
"Reversal Transaction for %s" % invoice.getTitle())
self.assertEqual(reversale_invoice.getCausality(),
invoice.getRelativeUrl())
self.assertEqual(reversale_invoice.getSimulationState(), "stopped")
self.assertEqual(invoice.getSimulationState(), "stopped")
invoice_line_id = invoice.contentValues(portal_type="Invoice Line")[0].getId()
transaction_line_id = invoice.contentValues(
portal_type="Sale Invoice Transaction Line")[0].getId()
self.assertEqual(invoice[invoice_line_id].getQuantity(),
-reversale_invoice[invoice_line_id].getQuantity())
self.assertEqual(invoice[transaction_line_id].getQuantity(),
-reversale_invoice[transaction_line_id].getQuantity())
self.assertEqual(len(invoice.getMovementList()), 2)
# Both invoice should have a grouping reference
self.assertNotEqual(invoice[transaction_line_id].getGroupingReference(""),
"")
self.assertEqual(
invoice[transaction_line_id].getGroupingReference("1"),
reversale_invoice[transaction_line_id].getGroupingReference("2"))
# All references should be regenerated
self.assertNotEqual(invoice.getReference(""),
reversale_invoice.getReference(""))
self.assertNotEqual(invoice.getSourceReference(""),
reversale_invoice.getSourceReference(""))
self.assertNotEqual(invoice.getDestinationReference(""),
reversale_invoice.getDestinationReference(""))
# Another trade condition
self.assertEqual(
reversale_invoice.getSpecialise(),
"sale_trade_condition_module/slapos_manual_accounting_trade_condition")
self.tic()
108 109
\ No newline at end of file \ No newline at end of file
...@@ -14,3 +14,4 @@ portal_orders/slapos_payment_transaction_builder/** ...@@ -14,3 +14,4 @@ portal_orders/slapos_payment_transaction_builder/**
portal_secure_payments/slapos_payzen_test portal_secure_payments/slapos_payzen_test
portal_secure_payments/slapos_payzen_test/** portal_secure_payments/slapos_payzen_test/**
sale_trade_condition_module/payzen_sale_trade_condition sale_trade_condition_module/payzen_sale_trade_condition
sale_trade_condition_module/slapos_manual_accounting_trade_condition
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment