Commit 9985bb44 authored by Rafael Monnerat's avatar Rafael Monnerat

slapos_accounting: Use script to fetch organisation as SHADOW User

   Organisation is usually linked as Source Section or Destination
   Section.

   The user don't have access to the Organisations so use Shadow User
   (via script) to get the required information for the printout.
parent 5f8786f3
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
person = portal.portal_membership.getAuthenticatedMember().getUserValue()
assert context.getPortalType() == 'Sale Invoice Transaction'
# The source_section is usually not accessible from the user,
# So to not leak information, we rely on Shadow User to retrive
# the information rather them flex security.
def wrapShadowFunction(invoice, base_category):
document_list = invoice.getValueList(base_category)
if not document_list:
return {'title': ''}
document = document_list[0]
printout_dict = {
'title': document.getTitle(),
'default_address': document.getDefaultAddressText(),
'default_region': document.getDefaultRegionTitle()
}
if document.getPortalType() == 'Organisation':
printout_dict.update({
"registration_code": document.getCorporateRegistrationCode(),
"vat_code": document.getVatCode(),
'corportate_name': document.getCorporateName()
})
return printout_dict
if person is not None:
return person.Person_restrictMethodAsShadowUser(
shadow_document=person,
callable_object=wrapShadowFunction,
argument_list=[context, base_category])
return wrapShadowFunction(context, base_category)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>base_category, REQUEST=None, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SaleInvoiceTransaction_getBaseCategoryDictForPrintout</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -126,6 +126,7 @@ table.resource td { font-size: 90% } ...@@ -126,6 +126,7 @@ table.resource td { font-size: 90% }
/* aside h1 { border: none; border-width: 0 0 1px; margin: 0 0 1em; }*/ /* aside h1 { border: none; border-width: 0 0 1px; margin: 0 0 1em; }*/
aside h1 { text-align: left; padding-bottom: 10px;} aside h1 { text-align: left; padding-bottom: 10px;}
aside {margin-top: 20px;} aside {margin-top: 20px;}
aside p.note { font-size: 75%; padding-top: 10px; padding-bottom: 10px }
/* bottom */ /* bottom */
......
...@@ -24,21 +24,27 @@ ...@@ -24,21 +24,27 @@
<img alt="" tal:attributes="src python: context.getPortalObject().absolute_url() + '/web_site_module/hostingjs/gadget_slapos_invoice_logo.png?format='" style="max-height: 25%; max-width: 70%;"/> <img alt="" tal:attributes="src python: context.getPortalObject().absolute_url() + '/web_site_module/hostingjs/gadget_slapos_invoice_logo.png?format='" style="max-height: 25%; max-width: 70%;"/>
</tal:block> </tal:block>
</tal:block> </tal:block>
<h1 class="company" tal:content="python: context.getSourceSectionTitle('SlapOS Company')"></h1> <tal:block define="source_section_dict python: context.SaleInvoiceTransaction_getBaseCategoryDictForPrintout('source_section')">
<tal:block tal:define="source_section_organisation python: context.getSourceSectionValue()"> <h1 class="company" tal:content="python: source_section_dict['title']"></h1>
<p tal:condition="python: source_section_organisation is not None"> <p tal:condition="python: source_section_dict.get('default_address')">
<tal:block tal:repeat="line python: source_section_organisation.getDefaultAddressText('').split('\n')"> <tal:block tal:repeat="line python: source_section_dict.get('default_address', '').split('\n')">
<span style="display:block;float:none;margin:0" tal:content="line"></span> <span style="display:block;float:none;margin:0" tal:content="line"></span>
</tal:block> </tal:block>
<tal:block tal:content="python: source_section_organisation.getDefaultRegionTitle()"></tal:block> <tal:block tal:condition="python: source_section_dict.get('default_region')">
<tal:block tal:content="python: source_section_dict.get('default_region')"></tal:block>
</tal:block>
</p> </p>
<p tal:condition="python: source_section_organisation is not None"> <p tal:condition="python: source_section_dict.get('description')">
<tal:block tal:repeat="line python: source_section_organisation.getDescription('').split('\n')"> <tal:block tal:repeat="line python: source_section_dict.get('description', '').split('\n')">
<span style="display:block;float:none;margin:0" tal:content="line"></span> <span style="display:block;float:none;margin:0" tal:content="line"></span>
</tal:block> </tal:block>
</p> </p>
<p tal:content="python: 'Corporate Registration Code: %s' % source_section_organisation.getCorporateRegistrationCode()"></p> <tal:block tal:condition="python: source_section_dict.get('registration_code')">
<p tal:content="python: 'VAT Code: %s' % source_section_organisation.getVatCode()"></p> <p tal:content="python: 'Corporate Registration Code: %s' % source_section_dict.get('registration_code')"></p>
</tal:block>
<tal:block tal:condition="python: source_section_dict.get('vat_code')">
<p tal:content="python: 'VAT Code: %s' % source_section_dict.get('vat_code')"></p>
</tal:block>
</tal:block> </tal:block>
</address> </address>
<address class="right"> <address class="right">
...@@ -49,36 +55,25 @@ ...@@ -49,36 +55,25 @@
<article> <article>
<h2>To</h2> <h2>To</h2>
<address> <address>
<tal:block tal:define="destination_section_organisation python: context.getDestinationSectionValue()"> <tal:block tal:define="destination_section_dict python: context.SaleInvoiceTransaction_getBaseCategoryDictForPrintout('destination_section')">
<tal:block tal:condition="python: destination_section_organisation is not None"> <tal:block tal:condition="python: destination_section_dict.get('corportate_name')">
<tal:block tal:condition="python: destination_section_organisation.getPortalType() == 'Organisation'"> <p tal:content="python: destination_section_dict.get('corportate_name')"></p>
<p tal:content="python: destination_section_organisation.getCorporateName() or destination_section_organisation.getTitle() or ''"></p> </tal:block>
<p tal:content="python: destination_section_organisation.getTitle() or ''"></p> <p tal:content="python: destination_section_dict['title']"></p>
<p tal:content="python: destination_section_organisation.getDefaultEmailText('') or destination_section_organisation.getDefaultEmailText('')"></p> <p tal:content="python: destination_section_dict.get('default_email_address_text', '')"></p>
<p> <p tal:condition="python: destination_section_dict.get('default_address')">
<tal:block tal:repeat="line python: destination_section_organisation.getDefaultAddressText('').split('\n')"> <tal:block tal:repeat="line python: destination_section_dict.get('default_address', '').split('\n')">
<span style="display:block" tal:content="line"></span> <span style="display:block" tal:content="line"></span>
</tal:block> </tal:block>
<tal:block tal:content="python: destination_section_organisation.getDefaultRegionTitle()"></tal:block> <tal:block tal:condition="python: destination_section_dict.get('default_region')">
</p> <tal:block tal:content="python: destination_section_dict.get('default_region')"></tal:block>
<tal:block tal:condition="python: destination_section_organisation.getCorporateRegistrationCode() is not None">
<p tal:content="python: 'Corporate Registration Code: %s' % destination_section_organisation.getCorporateRegistrationCode()"></p>
</tal:block>
<tal:block tal:condition="python: destination_section_organisation.getVatCode() is not None">
<p tal:content="python: 'VAT Code: %s' % destination_section_organisation.getVatCode()"></p>
</tal:block>
</tal:block>
<tal:block tal:condition="python: destination_section_organisation.getPortalType() != 'Organisation'">
<p tal:content="python: destination_section_organisation.getTitle() or ''"></p>
<p tal:content="python: destination_section_organisation.getDefaultEmailText('')"></p>
<p>
<tal:block tal:repeat="line python: destination_section_organisation.getDefaultAddressText('').split('\n')">
<span style="display:block" tal:content="line"></span>
</tal:block> </tal:block>
<tal:block tal:content="python: destination_section_organisation.getDefaultRegionTitle()"></tal:block>
</p> </p>
<tal:block tal:condition="python: destination_section_dict.get('registration_code')">
<p tal:content="python: 'Corporate Registration Code: %s' % destination_section_dict.get('registration_code')"></p>
</tal:block> </tal:block>
<tal:block tal:condition="python: destination_section_dict.get('vat_code')">
<p tal:content="python: 'VAT Code: %s' % destination_section_dict.get('vat_code')"></p>
</tal:block> </tal:block>
</tal:block> </tal:block>
</address> </address>
...@@ -155,52 +150,50 @@ ...@@ -155,52 +150,50 @@
</div> </div>
</aside--> </aside-->
<tal:block tal:define="invoice_line_list python: context.contentValues(portal_type='Invoice Line', checked_permission='View'); <tal:block tal:define="invoice_line_list python: context.contentValues(portal_type='Invoice Line');
filter_portal_type python: {'portal_type': ['Instance Tree', 'Compute Node', 'Project']}; filter_portal_type python: {'portal_type': ['Instance Tree', 'Compute Node', 'Project']};
invoice_line_aggregate_list python: [i for i in invoice_line_list if i.getAggregate(portal_type='Subscription Request') and i.getAggregate(**filter_portal_type)]; invoice_line_aggregate_list python: [i for i in invoice_line_list if i.getAggregate(portal_type='Hosting Subscription') and i.getAggregate(**filter_portal_type)];
item_dict python: {}"> item_dict python: {}">
<tal:block tal:condition="python: invoice_line_aggregate_list"> <tal:block tal:condition="python: invoice_line_aggregate_list">
<p class='line'>&nbsp;</p>
<aside> <aside>
<h1><span>Subscription Details</span></h1> <h1>Subscription Details</h1>
<p class='note'>
Period : <span tal:content="python: context.getStartDate().strftime('%B %e, %G')"></span>
to <span tal:content="python: context.getStopDate().strftime('%B %e, %G')"></span>
</p>
<tal:block tal:repeat="line python: invoice_line_aggregate_list"> <tal:block tal:repeat="line python: invoice_line_aggregate_list">
<tal:block tal:define="aggregate python: line.getAggregateValue(**filter_portal_type); <tal:block tal:define="aggregate python: line.getAggregateValue(**filter_portal_type);
item_uid python: aggregate.getUid(); item_uid python: aggregate.getUid();
item_title python: aggregate.getTitle(); item_title python: aggregate.getTitle();
start_date python: line.getStartDate();
stop_date python: line.getStopDate();
quantity python: line.getQuantity(); quantity python: line.getQuantity();
dummy_init python: item_dict.setdefault(item_uid, [item_title, start_date, stop_date, 0]); dummy_init python: item_dict.setdefault(item_uid, [item_title, 0]);
dummy_update python: item_dict.update({item_uid: [item_title, dummy_update python: item_dict.update({item_uid: [item_title,
min(item_dict[item_uid][1], start_date), sum([item_dict[item_uid][1], quantity])]});">
max(item_dict[item_uid][2], stop_date),
sum([item_dict[item_uid][3], quantity])]});">
</tal:block> </tal:block>
</tal:block> </tal:block>
<table> <table>
<thead> <thead>
<tr> <tr>
<th><span>Instance</span></th> <th><span>Item</span></th>
<th><span>From</span></th>
<th><span>To</span></th>
<th><span>Quantity</span></th> <th><span>Quantity</span></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr tal:repeat="item_tuple python: item_dict.values()"> <tr tal:repeat="item_tuple python: item_dict.values()">
<td tal:content="python: item_tuple[0]"></td> <td tal:content="python: item_tuple[0]"></td>
<td tal:content="python: item_tuple[1].strftime('%B %e, %G')"></td> <td tal:content="python: quantity_renderer(item_tuple[1])"></td>
<td tal:content="python: item_tuple[2].strftime('%B %e, %G')"></td>
<td tal:content="python: quantity_renderer(item_tuple[3])"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</aside> </aside>
</tal:block> </tal:block>
<tal:block tal:condition="python: invoice_resource_document is not None">
<p class='line page-break'>&nbsp;</p> <p class='line page-break'>&nbsp;</p>
<tal:block tal:condition="python: invoice_resource_document is not None" tal:content="structure python: invoice_resource_document.getData()"> <tal:block tal:content="structure python: invoice_resource_document.getData()">
</tal:block>
</tal:block> </tal:block>
</tal:block> </tal:block>
<p class='line'>&nbsp;</p>
<footer>Generated with ERP5 - Open Source ERP suite (erp5.nexedi.com)</footer> <footer>Generated with ERP5 - Open Source ERP suite (erp5.nexedi.com)</footer>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -154,6 +154,7 @@ def makeTestSlapOSCodingStyleTestCase(tested_business_template): ...@@ -154,6 +154,7 @@ def makeTestSlapOSCodingStyleTestCase(tested_business_template):
'slapos_accounting/PaymentTransaction_acceptDepositPayment', 'slapos_accounting/PaymentTransaction_acceptDepositPayment',
'slapos_accounting/PaymentTransaction_getExternalPaymentId', 'slapos_accounting/PaymentTransaction_getExternalPaymentId',
'slapos_accounting/PaymentTransaction_postOrderBuild', 'slapos_accounting/PaymentTransaction_postOrderBuild',
'slapos_accounting/SaleInvoiceTransaction_getBaseCategoryDictForPrintout',
'slapos_accounting/SaleInvoiceTransaction_init', 'slapos_accounting/SaleInvoiceTransaction_init',
'slapos_accounting/SaleInvoiceTransaction_isTotalPriceEqualAccounting', 'slapos_accounting/SaleInvoiceTransaction_isTotalPriceEqualAccounting',
'slapos_accounting/SaleInvoiceTransaction_isTotalPriceMatchingSalePackingList', 'slapos_accounting/SaleInvoiceTransaction_isTotalPriceMatchingSalePackingList',
......
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