Commit 465de5a5 authored by Rafael Monnerat's avatar Rafael Monnerat 👻

Update from upstream/master

parents a8562e40 9fa162e8
Pipeline #40089 failed with stage
in 0 seconds
Changes
=======
0.4.77 (2025-02-18)
-------------------
* testnode:
- fix handling of shebang like '#!/bin/sh -e'
* remove totally webchecker
0.4.76 (2024-05-07)
-------------------
......
......@@ -163,7 +163,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
group_by_node=1,
group_by_resource=1,
**default_inventory_params):
if inventory.total_price and inventory.total_quantity:
if inventory.total_price or inventory.total_quantity:
stock_list.append(
dict(destination_uid=node_uid,
destination_section_uid=section_uid,
......@@ -193,7 +193,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
group_by_mirror_section=1,
group_by_resource=1,
**default_inventory_params):
if inventory.total_price and inventory.total_quantity:
if inventory.total_price or inventory.total_quantity:
stock_list.append(
dict(destination_uid=node_uid,
destination_section_uid=section_uid,
......@@ -224,7 +224,7 @@ class BalanceTransaction(AccountingTransaction, Inventory):
group_by_payment=1,
group_by_resource=1,
**default_inventory_params):
if inventory.total_price and inventory.total_quantity:
if inventory.total_price or inventory.total_quantity:
stock_list.append(
dict(destination_uid=node_uid,
destination_section_uid=section_uid,
......
......@@ -14,6 +14,8 @@
<string>columns</string>
<string>count_method</string>
<string>default_params</string>
<string>domain_root_list</string>
<string>domain_tree</string>
<string>editable_columns</string>
<string>list_method</string>
<string>portal_types</string>
......@@ -282,6 +284,21 @@
<list/>
</value>
</item>
<item>
<key> <string>domain_root_list</string> </key>
<value>
<list>
<tuple>
<string>ledger</string>
<string>Ledger</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>domain_tree</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>editable_columns</string> </key>
<value>
......
......@@ -2240,6 +2240,160 @@ class TestClosingPeriod(AccountingTestCase):
balance_transaction.reindexObject()
self.tic()
def test_createBalanceTransactionZeroInAccountingTransactionCurrencyNextYear(self):
pl = self.portal.account_module.newContent(
portal_type='Account', account_type='equity')
bank_account = self.section.newContent(portal_type='Bank Account')
organisation_module = self.organisation_module
period = self.section.newContent(portal_type='Accounting Period')
period.setStartDate(DateTime(2006, 1, 1))
period.setStopDate(DateTime(2006, 12, 31))
self._makeOne(
start_date=DateTime(2006, 1, 1),
title='Yen',
resource='currency_module/yen',
destination_section_value=organisation_module.client_1,
portal_type='Sale Invoice Transaction',
simulation_state='delivered',
lines=(
dict(
source_value=self.account_module.goods_sales,
source_asset_debit=1,
source_debit=70,
),
dict(
source_value=self.account_module.stocks,
source_asset_credit=1,
source_credit=30,
),
# account by node
dict(
source_value=self.account_module.stocks,
source_asset_credit=0,
source_debit=70,
),
# account by mirror_section
dict(
source_value=self.account_module.receivable,
source_asset_credit=0,
source_debit=30,
),
# account by payment
dict(
source_value=self.account_module.bank,
source_payment_value=bank_account,
source_asset_credit=0,
source_credit=100,
),
))
self.tic()
period.AccountingPeriod_createBalanceTransaction(
profit_and_loss_account=pl.getRelativeUrl())
self.tic()
accounting_transaction_list = self.accounting_module.contentValues()
self.assertEqual(2, len(accounting_transaction_list))
balance_transaction, = self.accounting_module.contentValues(
portal_type='Balance Transaction')
self.assertEqual(
self.section, balance_transaction.getDestinationSectionValue())
self.assertEqual(None, balance_transaction.getSourceSection())
self.assertEqual(DateTime(2007, 1, 1), balance_transaction.getStartDate())
self.assertEqual('currency_module/euro', balance_transaction.getResource())
def check_balance_transaction_lines(bt):
self.assertEqual(
sorted(
[
(
line.getDestinationDebit(),
line.getDestinationCredit(),
line.getDestinationInventoriatedTotalAssetDebit(),
line.getDestinationInventoriatedTotalAssetCredit(),
line.getResourceTitle(),
line.getDestinationValue(),
line.getDestinationPaymentValue(),
line.getSourceSectionValue(),
) for line in bt.contentValues()
]), [
(
0.0,
100.0,
0.0,
0.0,
'Yen',
self.account_module.bank,
bank_account,
None,
),
(
1.0,
0.0,
1.0,
0.0,
'Euro',
pl,
None,
None,
),
(
30.0,
0.0,
0.0,
0.0,
'Yen',
self.account_module.receivable,
None,
organisation_module.client_1,
),
(
40.0,
0.0,
0.0,
1.0,
'Yen',
self.portal.account_module.stocks,
None,
None,
),
])
check_balance_transaction_lines(balance_transaction)
q = self.portal.erp5_sql_connection.manage_test
self.assertEqual(
1,
q(
"SELECT count(*) FROM stock WHERE portal_type="
"'Balance Transaction Line'")[0][0])
self.assertEqual(
1,
q(
"SELECT total_price FROM stock WHERE portal_type="
"'Balance Transaction Line'")[0][0])
self.assertEqual(
1,
q(
"SELECT quantity FROM stock WHERE portal_type="
"'Balance Transaction Line'")[0][0])
# next year, if there are no transactions during period, closing should produce
# the same balance transaction.
period_next_year = self.section.newContent(portal_type='Accounting Period')
period_next_year.setStartDate(DateTime(2007, 1, 1))
period_next_year.setStopDate(DateTime(2007, 12, 31))
period_next_year.AccountingPeriod_createBalanceTransaction(
profit_and_loss_account=pl.getRelativeUrl())
accounting_transaction_list = self.accounting_module.contentValues()
self.assertEqual(3, len(accounting_transaction_list))
balance_transaction_next_year, = [bt for bt in self.accounting_module.contentValues(
portal_type='Balance Transaction') if bt != balance_transaction]
check_balance_transaction_lines(balance_transaction_next_year)
# we can reindex again
balance_transaction.reindexObject()
balance_transaction_next_year.reindexObject()
self.tic()
def test_AccountingPeriodWorkflow(self):
"""Tests that accounting_period_workflow creates a balance transaction.
......
......@@ -652,9 +652,7 @@ class TestCurrencyExchangeCell(CurrencyExchangeTestCase):
self.tic()
# we need a base for asContext, we use the currency, but in real code you
# might want to use a more meaningful context.
context = euro.asContext(
context = self._getPriceContext(
categories=['resource/%s' % euro.getRelativeUrl(),
'price_currency/%s' % usd.getRelativeUrl(),
'currency_exchange_type/type_a'])
......
......@@ -48,7 +48,7 @@ if not shopping_cart_id in session.keys():
"Modify portal content",
"View"])
context.WebSection_updateShoppingCartTradeCondition(shopping_cart, None)
user = context.ERP5Site_getAuthenticatedMemberPersonValue()
user = context.portal_membership.getAuthenticatedMember().getUserValue()
if user:
shopping_cart.setDestinationValue(user)
shopping_cart.setPriceCurrency(shopping_cart.getSpecialiseValue().getPriceCurrency())
......
......@@ -112,6 +112,10 @@
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>autocomplete</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
......@@ -154,6 +158,10 @@
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
......@@ -267,7 +275,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: here.ERP5Site_getAuthenticatedMemberPersonValue().getDefaultAddressCity() or context.Base_translateString("Missing")</string> </value>
<value> <string>python: here.portal_membership.getAuthenticatedMember().getUserValue().getDefaultAddressCity() or context.Base_translateString("Missing")</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -112,6 +112,10 @@
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>autocomplete</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
......@@ -154,6 +158,10 @@
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
......@@ -267,7 +275,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: here.ERP5Site_getAuthenticatedMemberPersonValue().getDefaultAddressRegionTitle() or context.Base_translateString("Missing")</string> </value>
<value> <string>python: here.portal_membership.getAuthenticatedMember().getUserValue().getDefaultAddressRegionTitle() or context.Base_translateString("Missing")</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -112,6 +112,10 @@
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>autocomplete</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
......@@ -154,6 +158,10 @@
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
......@@ -267,7 +275,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: here.ERP5Site_getAuthenticatedMemberPersonValue().getDefaultAddressStreetAddress() or context.Base_translateString("Missing")</string> </value>
<value> <string>python: here.portal_membership.getAuthenticatedMember().getUserValue().getDefaultAddressStreetAddress() or context.Base_translateString("Missing")</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -112,6 +112,10 @@
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>autocomplete</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
......@@ -154,6 +158,10 @@
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
......@@ -267,7 +275,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: here.ERP5Site_getAuthenticatedMemberPersonValue().getDefaultAddressZipCode() or context.Base_translateString("Missing")</string> </value>
<value> <string>python: here.portal_membership.getAuthenticatedMember().getUserValue().getDefaultAddressZipCode() or context.Base_translateString("Missing")</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -112,6 +112,10 @@
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>autocomplete</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
......@@ -154,6 +158,10 @@
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
......@@ -267,7 +275,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: here.ERP5Site_getAuthenticatedMemberPersonValue().getDefaultEmailText() or context.Base_translateString("Missing")</string> </value>
<value> <string>python: here.portal_membership.getAuthenticatedMember().getUserValue().getDefaultEmailText() or context.Base_translateString("Missing")</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -112,6 +112,10 @@
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>autocomplete</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
......@@ -156,6 +160,10 @@
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
......@@ -269,7 +277,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: here.ERP5Site_getAuthenticatedMemberPersonValue().getDefaultTelephoneText()</string> </value>
<value> <string>python: here.portal_membership.getAuthenticatedMember().getUserValue().getDefaultTelephoneText()</string> </value>
</item>
</dictionary>
</pickle>
......@@ -282,7 +290,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: here.ERP5Site_getAuthenticatedMemberPersonValue().getDefaultTelephoneText() is not None</string> </value>
<value> <string>python: here.portal_membership.getAuthenticatedMember().getUserValue().getDefaultTelephoneText() is not None</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -112,6 +112,10 @@
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>autocomplete</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
......@@ -154,6 +158,10 @@
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
......@@ -267,7 +275,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: here.ERP5Site_getAuthenticatedMemberPersonValue().getTitle() or context.Base_translateString("Missing")</string> </value>
<value> <string>python: here.portal_membership.getAuthenticatedMember().getUserValue().getTitle() or context.Base_translateString("Missing")</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -23,7 +23,7 @@ if sale_order.getSimulationState() == "draft":
for amount in sale_order.getAggregatedAmountList():
if 'base_amount/loyalty_program/using_point' in amount.getBaseApplicationList():
user = context.ERP5Site_getAuthenticatedMemberPersonValue()
user = context.portal_membership.getAuthenticatedMember().getUserValue()
loyalty_transaction = context.loyalty_transaction_module.newContent(
portal_type='Loyalty Transaction',
destination_section_value=user,
......
import random
translateString = context.Base_translateString
person = context.ERP5Site_getAuthenticatedMemberPersonValue()
person = context.portal_membership.getAuthenticatedMember().getUserValue()
if person is None:
......
......@@ -12,7 +12,7 @@ reference='no_loyalty_reward'
if context.REQUEST.get("loyalty_reward", "") == "enable" and context.getSiteLoyaltyExplanationTemplate():
# this is double check.
# a trade condition should properly configured for anonymous
if context.ERP5Site_getAuthenticatedMemberPersonValue():
if context.portal_membership.getAuthenticatedMember().getUserValue():
reference= 'loyalty_reward'
if payment_mode:
......
<tal:block tal:define="enable_reward_discount python: request.get('loyalty_reward', '') == 'enable';">
<div class="promotional_information" tal:condition="python: here.ERP5Site_getAuthenticatedMemberPersonValue() and here.getSiteLoyaltyExplanationTemplate()">
<tal:block tal:condition="python: here.ERP5Site_getAuthenticatedMemberPersonValue().Person_getTotalLoyaltyPoint() >= 0">
<div class="promotional_information" tal:condition="python: here.portal_membership.getAuthenticatedMember().getUserValue() and here.getSiteLoyaltyExplanationTemplate()">
<tal:block tal:condition="python: here.portal_membership.getAuthenticatedMember().getUserValue().Person_getTotalLoyaltyPoint() >= 0">
<span i18n:translate="" i18n:domain="ui">You should overwrite this page template.</span>
<br />
<a tal:condition="python: enable_reward_discount"
......
<tal:block tal:define="isAnon here/portal_membership/isAnonymousUser">
<tal:block tal:condition="not: isAnon"
tal:define="customer here/ERP5Site_getAuthenticatedMemberPersonValue;
tal:define="customer python: here.portal_membership.getAuthenticatedMember().getUserValue();
login customer/getReference | string: ;
website here/getWebSiteValue">
......
......@@ -314,7 +314,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: not here.getPortalObject().portal_membership.isAnonymousUser() and here.ERP5Site_getAuthenticatedMemberPersonValue().checkConsistency()</string> </value>
<value> <string>python: not here.getPortalObject().portal_membership.isAnonymousUser() and here.portal_membership.getAuthenticatedMember().getUserValue().checkConsistency()</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -197,7 +197,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: not here.getPortalObject().portal_membership.isAnonymousUser() and not here.SaleOrder_isShoppingCartEmpty() and len(here.ERP5Site_getAuthenticatedMemberPersonValue().checkConsistency()) == 0 and here.SaleOrder_getSelectedShippingResource() is not None</string> </value>
<value> <string>python: not here.getPortalObject().portal_membership.isAnonymousUser() and not here.SaleOrder_isShoppingCartEmpty() and len(here.portal_membership.getAuthenticatedMember().getUserValue().checkConsistency()) == 0 and here.SaleOrder_getSelectedShippingResource() is not None</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -199,7 +199,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: not here.getPortalObject().portal_membership.isAnonymousUser() and not here.SaleOrder_isShoppingCartEmpty() and len(here.ERP5Site_getAuthenticatedMemberPersonValue().checkConsistency())</string> </value>
<value> <string>python: not here.getPortalObject().portal_membership.isAnonymousUser() and not here.SaleOrder_isShoppingCartEmpty() and len(here.portal_membership.getAuthenticatedMember().getUserValue().checkConsistency())</string> </value>
</item>
</dictionary>
</pickle>
......@@ -212,7 +212,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: "%s:method" % here.ERP5Site_getAuthenticatedMemberPersonValue().getRelativeUrl()</string> </value>
<value> <string>python: "%s:method" % here.portal_membership.getAuthenticatedMember().getUserValue().getRelativeUrl()</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -311,7 +311,7 @@
<key> <string>_text</string> </key>
<value> <string encoding="cdata"><![CDATA[
python: "<a href=%s/person_module/%s?login_come_from_url=%s> %s </a>" % (context.getWebSiteValue().absolute_url(),context.getPortalObject().ERP5Site_getAuthenticatedMemberPersonValue().getId(), context.getWebSectionValue().absolute_url(), context.Base_translateString("Change your informations"))
python: "<a href=%s/person_module/%s?login_come_from_url=%s> %s </a>" % (context.getWebSiteValue().absolute_url(),context.getPortalObject().portal_membership.getAuthenticatedMember().getUserValue().getId(), context.getWebSectionValue().absolute_url(), context.Base_translateString("Change your informations"))
]]></string> </value>
</item>
......
......@@ -29,7 +29,7 @@
</tal:block>
<tal:block tal:condition="not: isAnon"
tal:define="customer here/ERP5Site_getAuthenticatedMemberPersonValue;
tal:define="customer python: here.portal_membership.getAuthenticatedMember().getUserValue();
login customer/getReference | string: ;
website here/getWebSiteValue">
......
payment_mode = payment_mode.lower()
person = context.ERP5Site_getAuthenticatedMemberPersonValue()
person = context.portal_membership.getAuthenticatedMember().getUserValue()
sale_order = context.WebSection_persistShoppingCart(shopping_cart, person)
if payment_mode == 'paypal':
......
erp5_advanced_ecommerce
erp5_ui_test_core
erp5_configurator_standard_categories
erp5_configurator_standard_trade_template
erp5_simulation_test
\ No newline at end of file
"""This script is used to know if quantity can be edited by user.
* If this is not a movement (line containing lines or cell), user
cannot edit this line which is just a container, but no actual movement.
* If items are used, quantity is set by the item quantity.
"""
if not context.isMovement():
return False
return not (context.getResource() and context.getResourceValue().getAggregatedPortalTypeList())
<?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></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Movement_isQuantityEditable</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -23,6 +23,12 @@ def sort_key(exchange_line):
if movement is None:
return context.Resource_getPriceCalculationOperandDict(**kw)
else:
portal = context.getPortalObject()
if (not movement.hasResource()
and movement.getPortalType() in portal.getPortalInvoiceMovementTypeList()):
# XXX Invoice have a currency as resource and this resource is acquired on lines, but we don't want
# to lookup a price using the currency exchange line for such lines.
return None
if validation_state is None:
validation_state = 'validated'
kw.setdefault('portal_type', 'Currency Exchange Line')
......@@ -31,7 +37,7 @@ else:
# and that searchPredicateList does not accept.
kw.pop('categories', None)
predicate_list = context.portal_domains.searchPredicateList(
predicate_list = portal.portal_domains.searchPredicateList(
context=movement,
validation_state=validation_state,
test=True,
......
erp5_trade
erp5_base
erp5_configurator_standard_categories
\ No newline at end of file
erp5_base
\ No newline at end of file
......@@ -2,4 +2,5 @@ erp5_commerce_loyalty_program
erp5_simulation_test
erp5_configurator_standard_trade_template
erp5_configurator_standard_invoicing_template
erp5_configurator_standard_categories
erp5_simplified_invoicing
\ No newline at end of file
......@@ -7211,6 +7211,53 @@ class TestBusinessTemplate(BusinessTemplateMixin):
self.assertEqual(module_content_uid, self.portal.geek_module['1'].uid)
self.assertEqual('kept', self.portal.geek_module['1'].title)
def test_update_business_template_with_module_removed(self):
"""Updating business template with a module removed keeps the module if it contains documents
"""
self.portal.newContent(
portal_type='Person Module',
id='kept_module',
).newContent(
portal_type='Person',
id='keep',
)
self.portal.newContent(portal_type='Person Module', id='removed_module')
self.tic()
# install a bt containing two modules
bt = self.portal.portal_templates.newContent(
portal_type='Business Template',
title=self.id(),
template_module_id_list=['kept_module', 'removed_module'])
bt.build()
self.tic()
bt.install()
self.tic()
# in next version, both modules are removed
bt = self.portal.portal_templates.newContent(
portal_type='Business Template',
title=self.id(),
)
bt.build()
self.tic()
export_dir = tempfile.mkdtemp()
try:
bt.export(path=export_dir, local=True)
self.tic()
new_bt = self.portal.portal_templates.download(
url='file://%s' % export_dir)
finally:
shutil.rmtree(export_dir)
self.assertEqual(
new_bt.preinstall(),
{
'removed_module': ('Removed', 'Module'),
'kept_module': ('Removed but should be kept', 'Module'),
})
def test_BusinessTemplateWithTest(self):
sequence_list = SequenceList()
sequence_string = '\
......
......@@ -74,6 +74,10 @@ class TestDateUtils(unittest.TestCase):
addToDate(march_31, month=1).toZone('UTC').ISO())
self.assertEqual(DateTime('2001/05/1 %s' % self.timezone).toZone('UTC').ISO(),
addToDate(march_31, month=1, day=1).toZone('UTC').ISO())
self.assertEqual(DateTime('2001/05/1 %s' % self.timezone).toZone('UTC').ISO(),
addToDate(march_31, month=1, hour=24).toZone('UTC').ISO())
self.assertEqual(DateTime('2001/05/1 %s' % self.timezone).toZone('UTC').ISO(),
addToDate(march_31, hour=24*31).toZone('UTC').ISO())
def test_negative_add_to_date(self):
date = DateTime('2000/01/01 %s' % self.timezone)
......@@ -97,6 +101,10 @@ class TestDateUtils(unittest.TestCase):
may_31 = DateTime('2000/05/31 %s' % self.timezone)
self.assertEqual(DateTime('2000/04/30 %s' % self.timezone).toZone('UTC').ISO(),
addToDate(may_31, month=-1).toZone('UTC').ISO())
self.assertEqual(DateTime('2001/02/27 %s' % self.timezone).toZone('UTC').ISO(),
addToDate(march_31, month=-1, hour=-24).toZone('UTC').ISO())
self.assertEqual(DateTime('2001/02/27 %s' % self.timezone).toZone('UTC').ISO(),
addToDate(march_31, hour=-24*32).toZone('UTC').ISO())
def test_float_add_to_date(self):
date = DateTime('2000/01/01 %s' % self.timezone)
......
......@@ -13,6 +13,7 @@ if portal_type_list:
searchAndActivate(
portal_type=portal_type_list,
validation_state='submitted',
activate_kw={'tag': tag}
)
credential_update_destination_decision_portal_type_list = []
......@@ -25,4 +26,9 @@ if credential_update_destination_decision_portal_type_list:
portal_type='Credential Update',
destination_decision_portal_type=credential_update_destination_decision_portal_type_list,
validation_state='submitted',
activate_kw={'tag': tag}
)
# Do not prevent the alarm to run again if one activity fails
# Fixing this requires to review the credential scripts
# context.activate(after_tag=tag).getId()
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
<value> <string>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
......@@ -7333,6 +7333,9 @@ msgstr "Mouvements"
msgid "Multiple (${document_count}) documents ${document_reference} - ${document_language} - ${document_version} already exists."
msgstr "Plusieurs (${document_count}) documents ${document_reference} - ${document_language} - ${document_version} existent déjà."
msgid "My Account"
msgstr "Mon compte"
msgid "My Contacts"
msgstr "Mes contacts"
......
......@@ -135,11 +135,11 @@
<string>Sender or Provider</string>
</tuple>
<tuple>
<string>start_date_range_min</string>
<string>predicate.start_date_range_min</string>
<string>Valid from</string>
</tuple>
<tuple>
<string>start_date_range_max</string>
<string>predicate.start_date_range_max</string>
<string>Valid until</string>
</tuple>
<tuple>
......@@ -238,6 +238,14 @@
<string>modification_date</string>
<string>Modification Date</string>
</tuple>
<tuple>
<string>predicate.start_date_range_min</string>
<string>Valid from</string>
</tuple>
<tuple>
<string>predicate.start_date_range_max</string>
<string>Valid until</string>
</tuple>
</list>
</value>
</item>
......@@ -300,6 +308,14 @@
<string>modification_date</string>
<string>Modification Date</string>
</tuple>
<tuple>
<string>predicate.start_date_range_min</string>
<string>Valid from</string>
</tuple>
<tuple>
<string>predicate.start_date_range_max</string>
<string>Valid until</string>
</tuple>
</list>
</value>
</item>
......
......@@ -109,11 +109,11 @@
<string>Recipient or Beneficiary</string>
</tuple>
<tuple>
<string>start_date_range_min</string>
<string>predicate.start_date_range_min</string>
<string>Valid from</string>
</tuple>
<tuple>
<string>start_date_range_max</string>
<string>predicate.start_date_range_max</string>
<string>Valid until</string>
</tuple>
<tuple>
......
......@@ -84,8 +84,8 @@
<key> <string>hidden</string> </key>
<value>
<list>
<string>listbox_start_date_range_max</string>
<string>listbox_start_date_range_min</string>
<string>listbox_predicate_start_date_range_max</string>
<string>listbox_predicate_start_date_range_min</string>
</list>
</value>
</item>
......
......@@ -8,7 +8,7 @@
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>listbox_start_date_range_max</string> </value>
<value> <string>listbox_predicate_start_date_range_max</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
......
......@@ -14,7 +14,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox_start_date_range_min</string> </value>
<value> <string>listbox_predicate_start_date_range_min</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
......
......@@ -74,8 +74,8 @@
<key> <string>hidden</string> </key>
<value>
<list>
<string>listbox_start_date_range_max</string>
<string>listbox_start_date_range_min</string>
<string>listbox_predicate_start_date_range_max</string>
<string>listbox_predicate_start_date_range_min</string>
</list>
</value>
</item>
......
......@@ -10,7 +10,7 @@
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>editable_columns</string>
<string>sort</string>
</list>
</value>
</item>
......@@ -77,21 +77,6 @@
<list/>
</value>
</item>
<item>
<key> <string>editable_columns</string> </key>
<value>
<list>
<tuple>
<string>start_date_range_min</string>
<string>Valid from</string>
</tuple>
<tuple>
<string>start_date_range_max</string>
<string>Valid until</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_purchase_supplies_listbox</string> </value>
......@@ -100,6 +85,12 @@
<key> <string>form_id</string> </key>
<value> <string>Base_viewPDMFieldLibrary</string> </value>
</item>
<item>
<key> <string>sort</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
......
......@@ -6,9 +6,15 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox_start_date_range_max</string> </value>
<value> <string>listbox_predicate_start_date_range_max</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
......
......@@ -14,7 +14,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox_start_date_range_min</string> </value>
<value> <string>listbox_predicate_start_date_range_min</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
......
......@@ -74,8 +74,8 @@
<key> <string>hidden</string> </key>
<value>
<list>
<string>listbox_start_date_range_max</string>
<string>listbox_start_date_range_min</string>
<string>listbox_predicate_start_date_range_max</string>
<string>listbox_predicate_start_date_range_min</string>
</list>
</value>
</item>
......
......@@ -8,7 +8,7 @@
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>listbox_start_date_range_max</string> </value>
<value> <string>listbox_predicate_start_date_range_max</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
......
......@@ -14,7 +14,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox_start_date_range_min</string> </value>
<value> <string>listbox_predicate_start_date_range_min</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
......
......@@ -1499,6 +1499,51 @@ self.portal.getDefaultModule(self.packing_list_portal_type).newContent(
sale_invoice_brain, = self.portal.portal_catalog(uid=sale_invoice.getUid(), select_list=["specialise_trade_condition_title"], limit=1)
self.assertEqual(sale_invoice_brain.specialise_trade_condition_title, trade_condition_title)
def test_invoice_movement_getPrice(self):
resource = self.portal.product_module.newContent(
portal_type='Product',
title='Resource %s' % self.id(),
)
resource.setSaleSupplyLineBasePrice(123)
resource.setPurchaseSupplyLineBasePrice(123)
currency = self.portal.currency_module.newContent(
portal_type='Currency', title='Currency %s' % self.id())
currency.newContent(
portal_type='Currency Exchange Line',
price_currency_value=currency,
base_price=1,
).validate()
client = self.portal.organisation_module.newContent(
portal_type='Organisation', title='Client')
vendor = self.portal.organisation_module.newContent(
portal_type='Organisation', title='Vendor')
self.tic()
invoice = self.portal.accounting_module.newContent(
portal_type=self.invoice_portal_type,
source_value=vendor,
source_section_value=vendor,
destination_value=client,
destination_section_value=client,
start_date=DateTime(2008, 10, 21),
price_currency_value=currency,
resource_value=currency,
)
invoice_line = invoice.newContent(
portal_type=self.invoice_line_portal_type,
resource_value=resource,
quantity=1)
self.assertEqual(invoice_line.getPrice(), 123)
invoice_line_without_resource = invoice.newContent(
portal_type=self.invoice_line_portal_type, quantity=1)
self.assertIsNone(invoice_line_without_resource.getPrice())
invoice_cell_without_resource = invoice_line_without_resource.newContent(
portal_type=self.invoice_line_portal_type, quantity=1)
self.assertIsNone(invoice_cell_without_resource.getPrice())
class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase):
"""Tests for sale invoice.
"""
......
"""This script is used to know if quantity can be edited by user.
* If this is not a movement (line containing lines or cell), user
cannot edit this line which is just a container, but no actual movement.
"""
This script is used to know if quantity can be edited by user.
* If this line has variation category list, then it means it's a line that
will contain cell, so it's already not possible to set quantity, user have
to create cells and set quantities on cells.
* If quantity is not enabled on the movement, quantity cannot be set.
* If items are used, quantity is set by the item quantity.
* If items are required, quantity is set by the item quantity.
"""
if not context.isMovement():
return False
if context.getVariationCategoryList(omit_optional_variation=1) and not 'Cell' in context.getPortalType():
if not context.Movement_isQuantityEnabled():
return False
return not (context.getResource() and context.getResourceValue().getAggregatedPortalTypeList())
return not (context.getResource() and context.getResourceValue().getRequiredAggregatedPortalTypeList())
return context.isMovement() and not context.getVariationCategoryList()
"""
This script is used to know if quantity should be shown to the user. Usually, not showing quantity happens when a total quantity is shown instead, meaning the line uses cells.
* If this is not a movement (line containing lines or cell), user cannot see quantity for this line which is just a container, but no actual movement.
* If this line has required variation category list, then it means it's a line that will contain cell, so total quantity will be used instead.
* If this line has optional variation category list, and already contain cells, total quantity should also be used.
"""
if not context.isMovement():
return False
if not 'Cell' in context.getPortalType() and \
(context.getVariationCategoryList(omit_optional_variation=1) or \
context.hasCellContent(base_id='movement')):
return False
return True
......@@ -37,16 +37,15 @@
hour = minute * 60,
day = hour * 24,
week = day * 7,
year = day * 365,
time_format = new Intl.RelativeTimeFormat(language);
diff = date.getFullYear() - current_date.getFullYear();
if (diff !== 0) {
return time_format.format(diff, 'year');
}
diff = date - current_date;
abs = Math.abs(diff);
// "year", "quarter", "month", "week", "day", "hour", "minute", "second"
if (abs > year) {
return time_format.format(Math.floor(diff / year), 'year');
}
if (abs > (week * 2)) {
return time_format.format(Math.floor(diff / week), 'week');
}
......
......@@ -238,7 +238,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>1017.21412.29767.13277</string> </value>
<value> <string>1017.42673.18426.35652</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -258,7 +258,7 @@
</tuple>
<state>
<tuple>
<float>1718640624.19</float>
<float>1735815864.25</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -38,7 +38,7 @@ from slapos.grid.utils import md5digest
def dealShebang(run_test_suite_path):
with open(run_test_suite_path) as f:
if f.read(2) == '#!':
return f.readline().split(None, 1)
return f.readline().rstrip().split(None, 1)
return []
class UnitTestRunner(object):
......
......@@ -426,9 +426,13 @@ CREATE TABLE %s (
0,
)[1]
else:
# MariaDB often choose processing_node_priority_date index
# but node2_priority_date is much faster if there exist
# many node < 0 non-groupable activities.
subquery = lambda *a, **k: str2bytes(bytes2str(b"("
b"SELECT 3*priority{} AS effective_priority, date"
b" FROM %s"
b" FORCE INDEX (node2_priority_date)"
b" WHERE"
b" {} AND"
b" processing_node=0 AND"
......@@ -781,9 +785,17 @@ CREATE TABLE %s (
0,
))
else:
if group_method_id:
force_index = ''
else:
# MariaDB often choose processing_node_priority_date index
# but node2_priority_date is much faster if there exist
# many node < 0 non-groupable activities.
force_index = b'FORCE INDEX (node2_priority_date)'
subquery = lambda *a, **k: str2bytes(bytes2str(b"("
b"SELECT *, 3*priority{} AS effective_priority"
b" FROM %s"
b" {}"
b" WHERE"
b" {} AND"
b" processing_node=0 AND"
......@@ -799,11 +811,11 @@ CREATE TABLE %s (
b" UNION ALL ".join(
chain(
(
subquery('-1', 'node = %i' % processing_node),
subquery('', 'node=0'),
subquery('-1', force_index, 'node = %i' % processing_node),
subquery('', force_index, 'node=0'),
),
(
subquery('-1', 'node = %i' % x)
subquery('-1', force_index, 'node = %i' % x)
for x in node_set
),
),
......@@ -821,7 +833,7 @@ CREATE TABLE %s (
# sorted set to filter negative node values.
# This is why this query is only executed when the previous one
# did not find anything.
result = Results(query(subquery('+1', 'node>0'), 0))
result = Results(query(subquery('+1', force_index, 'node>0'), 0))
if result:
# Reserve messages.
uid_list = [x.uid for x in result]
......
......@@ -3775,6 +3775,20 @@ class ModuleTemplateItem(BaseTemplateItem):
xml_data = self.generateXml(path=key)
bta.addObject(xml_data, name=key, path=path)
def preinstall(self, context, installed_item, **kw):
"""Keep modules when they are not empty.
"""
_modified_object_dict = super(ModuleTemplateItem, self).preinstall(context, installed_item, **kw)
portal = context.getPortalObject()
modified_object_dict = {}
for module_id, (action, item_class) in _modified_object_dict.items():
if action == 'Removed':
module = portal._getOb(module_id, None)
if module is not None and len(module.objectValues()):
action = 'Removed but should be kept'
modified_object_dict[module_id] = (action, item_class)
return modified_object_dict
def install(self, context, trashbin, **kw):
portal = context.getPortalObject()
update_dict = kw.get('object_to_update')
......
......@@ -109,9 +109,8 @@ def addToDate(date, to_add=None, **kw):
return_value[key] = return_value[key] - number_of_in_dict[key]
return_value[larger_key_dict[key]] = return_value[larger_key_dict[key]] + 1
month_in_to_add = to_add.get('month', None)
for key in key_list:
if key == 'day':
continue
if to_add.get(key, None) is not None:
return_value[key] = return_value[key] + to_add[key]
del to_add[key]
......@@ -126,13 +125,7 @@ def addToDate(date, to_add=None, **kw):
for local_key in return_value.keys():
if local_key not in ('day', 'year'):
treatPositiveValues(return_value, local_key)
day_to_add = min(
return_value['day'],
getNumberOfDayInMonth(
DateTime(return_value['year'], int(return_value['month']), 1)
)
) - 1
day_to_add = return_value['day'] - 1
if to_add.get('day', None) is not None:
day_to_add += to_add['day']
return_value['day'] = 1
......@@ -143,6 +136,9 @@ def addToDate(date, to_add=None, **kw):
return_value['minute'],
return_value['second'],
date.timezone()))
overflow_day = date.day() - getNumberOfDayInMonth(return_date)
if (month_in_to_add is not None) and (overflow_day > 0):
day_to_add -= overflow_day
return_date += day_to_add
return return_date
......
......@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
import glob
import os
version = '0.4.76'
version = '0.4.77'
name = 'erp5.util'
long_description = open("README.erp5.util.txt").read() + "\n"
......
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