Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Romain Courteaud
erp5
Commits
f97e908a
Commit
f97e908a
authored
Sep 28, 2020
by
Tatuya Kamada
Browse files
Options
Browse Files
Download
Plain Diff
erp5_tabular_data_tool: Add portal_tabular (Tabular Data Tool)
See merge request
!1222
parents
92062f69
43affc49
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
1134 additions
and
0 deletions
+1134
-0
bt5/erp5_tabular_data_tool/DocumentTemplateItem/portal_components/tool.erp5.TabularDataTool.py
...mplateItem/portal_components/tool.erp5.TabularDataTool.py
+196
-0
bt5/erp5_tabular_data_tool/DocumentTemplateItem/portal_components/tool.erp5.TabularDataTool.xml
...plateItem/portal_components/tool.erp5.TabularDataTool.xml
+127
-0
bt5/erp5_tabular_data_tool/PortalTypeTemplateItem/portal_types/Tabular%20Data%20Tool.xml
...alTypeTemplateItem/portal_types/Tabular%20Data%20Tool.xml
+60
-0
bt5/erp5_tabular_data_tool/ToolTemplateItem/portal_tabular.xml
...rp5_tabular_data_tool/ToolTemplateItem/portal_tabular.xml
+20
-0
bt5/erp5_tabular_data_tool/bt/dependency_list
bt5/erp5_tabular_data_tool/bt/dependency_list
+1
-0
bt5/erp5_tabular_data_tool/bt/template_document_id_list
bt5/erp5_tabular_data_tool/bt/template_document_id_list
+1
-0
bt5/erp5_tabular_data_tool/bt/template_format_version
bt5/erp5_tabular_data_tool/bt/template_format_version
+1
-0
bt5/erp5_tabular_data_tool/bt/template_portal_type_id_list
bt5/erp5_tabular_data_tool/bt/template_portal_type_id_list
+1
-0
bt5/erp5_tabular_data_tool/bt/template_tool_id_list
bt5/erp5_tabular_data_tool/bt/template_tool_id_list
+1
-0
bt5/erp5_tabular_data_tool/bt/template_update_tool
bt5/erp5_tabular_data_tool/bt/template_update_tool
+1
-0
bt5/erp5_tabular_data_tool/bt/title
bt5/erp5_tabular_data_tool/bt/title
+1
-0
bt5/erp5_tabular_data_tool_test/TestTemplateItem/portal_components/test.erp5.testTabularDataTool.py
...teItem/portal_components/test.erp5.testTabularDataTool.py
+591
-0
bt5/erp5_tabular_data_tool_test/TestTemplateItem/portal_components/test.erp5.testTabularDataTool.xml
...eItem/portal_components/test.erp5.testTabularDataTool.xml
+127
-0
bt5/erp5_tabular_data_tool_test/bt/dependency_list
bt5/erp5_tabular_data_tool_test/bt/dependency_list
+3
-0
bt5/erp5_tabular_data_tool_test/bt/template_format_version
bt5/erp5_tabular_data_tool_test/bt/template_format_version
+1
-0
bt5/erp5_tabular_data_tool_test/bt/template_test_id_list
bt5/erp5_tabular_data_tool_test/bt/template_test_id_list
+1
-0
bt5/erp5_tabular_data_tool_test/bt/title
bt5/erp5_tabular_data_tool_test/bt/title
+1
-0
No files found.
bt5/erp5_tabular_data_tool/DocumentTemplateItem/portal_components/tool.erp5.TabularDataTool.py
0 → 100644
View file @
f97e908a
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
from
Products.ERP5Type.Globals
import
InitializeClass
from
Products.ERP5Type.Tool.BaseTool
import
BaseTool
import
pandas
as
pd
MARKER
=
object
()
DEFAULT_FILL_STRING
=
''
DEFAULT_FILL_NUMBER
=
0.0
DEFAULT_FILL_UID
=
-
1
class
TabularDataTool
(
BaseTool
):
"""
Tabular Data Tool is a Tool to handle tabular data (2-dimentional table data) in erp5.
The tabular data type is currently a plain pandas DataFrame. It is intended to
use with ERP5 Reports to create spread sheets (ODS/Excel).
With Tabular Data Tool, we can do those things on reporting:
- transform dict-list, portal-catalog-result and document-list into a tabular data
- joining/grouping/sorting the tabular data
- using vectorizing function to optimise time consuming reports
"""
id
=
'portal_tabular'
title
=
'Tabular Data Tool'
meta_type
=
'ERP5 Tabular Data Tool'
portal_type
=
'Tabular Data Tool'
allowed_types
=
()
# Declarative Security
security
=
ClassSecurityInfo
()
# The empty DataFrame marker
def
_createEmptyDataFrame
(
self
):
return
pd
.
DataFrame
()
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'fillna'
)
def
fillna
(
self
,
tabular
,
fillna_on_string
=
MARKER
,
fillna_on_number
=
MARKER
,
fillna_on_uid
=
MARKER
):
"""
Fill NA/NaN values on the given tabular (a dataframe).
Keyword arguments:
tabular -- the dataframe to fill empty values
fillna_on_string -- Fill given value for empty string
fillna_on_number -- Fill given value for empty numbers (int or float)
fillna_on_uid -- Fill given value for empty uid, which overrides fillna_on_numbers for uid
"""
if
tabular
is
None
:
return
tabular
string_filler
=
DEFAULT_FILL_STRING
if
fillna_on_string
is
MARKER
else
fillna_on_string
number_filler
=
DEFAULT_FILL_NUMBER
if
fillna_on_number
is
MARKER
else
fillna_on_number
uid_filler
=
DEFAULT_FILL_UID
if
fillna_on_uid
is
MARKER
else
fillna_on_uid
fillna_setting_dict
=
{}
string_column_list
=
tabular
.
select_dtypes
(
include
=
[
object
]).
columns
.
tolist
()
string_none_column_list
=
[]
if
fillna_on_string
is
None
:
# pandas.dataframe.fillna(None) raises error, so use .replace() instead
string_none_column_list
=
string_column_list
string_column_list
=
[]
number_column_list
=
tabular
.
select_dtypes
(
include
=
[
int
,
float
]).
columns
.
tolist
()
uid_column_list
=
[
column
for
column
in
tabular
.
columns
.
tolist
()
if
column
.
endswith
(
'_uid'
)]
number_column_list
=
list
(
set
(
number_column_list
)
-
set
(
uid_column_list
))
string_column_list
=
list
(
set
(
string_column_list
)
-
set
(
uid_column_list
))
fillna_setting_dict
.
update
(
dict
.
fromkeys
(
string_column_list
,
string_filler
))
fillna_setting_dict
.
update
(
dict
.
fromkeys
(
number_column_list
,
number_filler
))
fillna_setting_dict
.
update
(
dict
.
fromkeys
(
uid_column_list
,
uid_filler
))
filled_tabular
=
tabular
.
fillna
(
value
=
fillna_setting_dict
)
if
string_none_column_list
:
replace_dict
=
dict
.
fromkeys
(
string_none_column_list
,
{
""
:
None
})
filled_tabular
=
filled_tabular
.
replace
(
replace_dict
)
return
filled_tabular
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getTabular'
)
def
getTabular
(
self
,
data_list
,
fillna_on_string
=
MARKER
,
fillna_on_number
=
MARKER
,
fillna_on_uid
=
MARKER
,
additional_property_name_list
=
MARKER
):
"""
Create a tabular from dict list with filling values for convenience in ERP5.
Currently the tabular data type is pandas DataFrame.
Keyword arguments:
data_list -- A dict list or brain_list to convert it to dataframe
fillna_on_string -- Fill given value for empty string
fillna_on_numbers -- Fill given value for empty numbers (int or float)
fillna_on_uid -- Fill given value for empty uid, which overrides fillna_on_numbers for uid
additional_property_name_list -- Additional property name list of brain object
"""
if
data_list
is
None
or
len
(
data_list
)
==
0
:
return
self
.
_createEmptyDataFrame
()
df
=
None
if
isinstance
(
data_list
[
0
],
dict
):
df
=
pd
.
DataFrame
.
from_dict
(
data_list
)
# Expect Shared.ZRDB.Results
elif
getattr
(
data_list
,
'dictionaries'
,
None
)
is
not
None
:
if
additional_property_name_list
is
not
MARKER
:
new_data_dict_list
=
[]
for
(
data_
,
record_dict
)
in
zip
(
data_list
,
data_list
.
dictionaries
()):
property_dict
=
self
.
_getPropertyDict
(
data_
,
additional_property_name_list
,
False
,
False
)
property_dict
.
update
(
record_dict
)
new_data_dict_list
.
append
(
property_dict
)
df
=
self
.
getTabular
(
new_data_dict_list
)
else
:
df
=
self
.
getTabular
(
data_list
.
dictionaries
())
if
df
is
not
None
:
return
self
.
fillna
(
df
,
fillna_on_string
=
fillna_on_string
,
fillna_on_number
=
fillna_on_number
,
fillna_on_uid
=
fillna_on_uid
)
raise
ValueError
(
"The type is not supported, {}"
.
format
(
data_list
))
def
_getPropertyDict
(
self
,
document
,
property_name_list
,
is_category_as_uid
,
add_category_title
):
portal_type
=
document
.
getPortalType
()
base_type
=
self
.
getPortalObject
().
portal_types
[
portal_type
]
base_category_list
=
base_type
.
getInstanceBaseCategoryList
()
if
property_name_list
is
MARKER
:
property_name_list
=
list
(
base_type
.
getInstancePropertySet
())
else
:
# If property_name_list is explicitly passed, respect the name list in category
base_category_list
=
list
(
set
(
base_category_list
).
intersection
(
set
(
property_name_list
)))
property_dict
=
{}
for
property_name
in
property_name_list
:
property_dict
[
property_name
]
=
document
.
getProperty
(
property_name
)
for
base_category_id
in
base_category_list
:
category_name
=
"{}_uid"
.
format
(
base_category_id
)
if
is_category_as_uid
else
base_category_id
property_dict
[
category_name
]
=
document
.
getProperty
(
category_name
)
if
add_category_title
:
category_title
=
"{}_title"
.
format
(
base_category_id
)
property_dict
[
category_title
]
=
document
.
getProperty
(
category_title
)
return
property_dict
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getFromDocumentList'
)
def
getFromDocumentList
(
self
,
document_list
,
property_name_list
=
MARKER
,
fillna_on_string
=
MARKER
,
fillna_on_number
=
MARKER
,
fillna_on_uid
=
MARKER
,
is_category_as_uid
=
True
,
add_category_title
=
True
):
"""
Create tabular data from document list
Keyword arguments:
property_name_list -- Explict to specify the property name list of document
If not specified all properties and categories of the portal type is applied
fillna_on_string -- Fill given value for empty string
fillna_on_numbers -- Fill given value for empty numbers (int or float)
fillna_on_uid -- Fill given value for empty uid, which overrides fill_on_numbers for uid
is_category_as_uid -- Store uid on {base_category}_uid, instead of store the url on {base_category}
add_category_title -- Add {category}_title columns into the tabular
Note: It takes O(N) time.
"""
if
document_list
is
None
or
len
(
document_list
)
==
0
:
return
self
.
_createEmptyDataFrame
()
# raise Attribute error if given document does not have portal_type
portal_type_set
=
set
([
x
.
getPortalType
()
for
x
in
document_list
])
if
len
(
portal_type_set
)
!=
1
:
raise
ValueError
(
'Given documents do not have the same portal type:{}'
.
format
(
portal_type_set
))
dict_list
=
[
self
.
_getPropertyDict
(
x
,
property_name_list
,
is_category_as_uid
,
add_category_title
)
for
x
in
document_list
]
return
self
.
getTabular
(
dict_list
,
fillna_on_string
=
fillna_on_string
,
fillna_on_number
=
fillna_on_number
,
fillna_on_uid
=
fillna_on_uid
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'searchResults'
)
def
searchResults
(
self
,
select_dict
=
None
,
fillna_on_string
=
MARKER
,
fillna_on_number
=
MARKER
,
fillna_on_uid
=
MARKER
,
**
kw
):
"""
Create tabular data based on the portal_catalog.searchResult()
select_dict -- If select_dict is None, specify all the column ids of catalog table.
"""
if
select_dict
is
None
:
portal
=
self
.
getPortalObject
()
catalog_id
=
portal
.
portal_catalog
.
getDefaultErp5CatalogId
()
default_erp5_catalog
=
portal
.
portal_catalog
[
catalog_id
]
column_id_set
=
set
(
default_erp5_catalog
.
getResultColumnIds
())
sql_search_result_keys_set
=
set
(
default_erp5_catalog
.
getSqlSearchResultKeysList
())
all_column_id_set
=
column_id_set
-
sql_search_result_keys_set
select_dict
=
dict
([(
column_id
,
None
)
for
column_id
in
all_column_id_set
if
column_id
.
startswith
(
'catalog.'
)])
search_result
=
portal
.
portal_catalog
(
select_dict
=
select_dict
,
**
kw
)
return
self
.
getTabular
(
search_result
,
fillna_on_string
=
fillna_on_string
,
fillna_on_number
=
fillna_on_number
,
fillna_on_uid
=
fillna_on_uid
)
__call__
=
getTabular
InitializeClass
(
TabularDataTool
)
\ No newline at end of file
bt5/erp5_tabular_data_tool/DocumentTemplateItem/portal_components/tool.erp5.TabularDataTool.xml
0 → 100644
View file @
f97e908a
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Tool Component"
module=
"erp5.portal_type"
/>
</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>
TabularDataTool
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
tool.erp5.TabularDataTool
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Tool Component
</string>
</value>
</item>
<item>
<key>
<string>
sid
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
text_content_error_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
text_content_warning_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
version
</string>
</key>
<value>
<string>
erp5
</string>
</value>
</item>
<item>
<key>
<string>
workflow_history
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAM=
</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>
<pickle>
<dictionary>
<item>
<key>
<string>
data
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
component_validation_workflow
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAQ=
</string>
</persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"4"
aka=
"AAAAAAAAAAQ="
>
<pickle>
<global
name=
"WorkflowHistoryList"
module=
"Products.ERP5Type.Workflow"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_log
</string>
</key>
<value>
<list>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<string>
validate
</string>
</value>
</item>
<item>
<key>
<string>
validation_state
</string>
</key>
<value>
<string>
validated
</string>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_tabular_data_tool/PortalTypeTemplateItem/portal_types/Tabular%20Data%20Tool.xml
0 → 100644
View file @
f97e908a
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Base Type"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
acquire_local_roles
</string>
</key>
<value>
<int>
1
</int>
</value>
</item>
<item>
<key>
<string>
content_icon
</string>
</key>
<value>
<string>
folder_icon.gif
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<string>
Tabular Data Tool is for handling tabular data (2-dimentional table data) .
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
Tabular Data Tool
</string>
</value>
</item>
<item>
<key>
<string>
init_script
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
permission
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Base Type
</string>
</value>
</item>
<item>
<key>
<string>
type_class
</string>
</key>
<value>
<string>
TabularDataTool
</string>
</value>
</item>
<item>
<key>
<string>
type_interface
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
type_mixin
</string>
</key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_tabular_data_tool/ToolTemplateItem/portal_tabular.xml
0 → 100644
View file @
f97e908a
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Tabular Data Tool"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
portal_tabular
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Tabular Data Tool
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_tabular_data_tool/bt/dependency_list
0 → 100644
View file @
f97e908a
erp5_base
\ No newline at end of file
bt5/erp5_tabular_data_tool/bt/template_document_id_list
0 → 100644
View file @
f97e908a
tool.erp5.TabularDataTool
\ No newline at end of file
bt5/erp5_tabular_data_tool/bt/template_format_version
0 → 100644
View file @
f97e908a
1
\ No newline at end of file
bt5/erp5_tabular_data_tool/bt/template_portal_type_id_list
0 → 100644
View file @
f97e908a
Tabular Data Tool
\ No newline at end of file
bt5/erp5_tabular_data_tool/bt/template_tool_id_list
0 → 100644
View file @
f97e908a
portal_tabular
\ No newline at end of file
bt5/erp5_tabular_data_tool/bt/template_update_tool
0 → 100644
View file @
f97e908a
1
\ No newline at end of file
bt5/erp5_tabular_data_tool/bt/title
0 → 100644
View file @
f97e908a
erp5_tabular_data_tool
\ No newline at end of file
bt5/erp5_tabular_data_tool_test/TestTemplateItem/portal_components/test.erp5.testTabularDataTool.py
0 → 100644
View file @
f97e908a
# coding: utf-8
##############################################################################
#
# Copyright (c) 2002-2020 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# 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
Products.ERP5Type.tests.ERP5TypeTestCase
import
ERP5TypeTestCase
from
Products.ERP5Type.tests.Sequence
import
SequenceList
from
Products.ERP5Type.tests.utils
import
createZODBPythonScript
import
math
class
TestTabularDataTool
(
ERP5TypeTestCase
):
"""
Test for Tabular Data Tool
"""
#maxDiff = None
def
getTitle
(
self
):
return
"TestTabularDataTool"
def
getBusinessTemplateList
(
self
):
"""
Tuple of Business Templates we need to install
"""
return
(
'erp5_trade'
,)
def
beforeTearDown
(
self
):
"""
Remove this test related documents (for livetest in the real environment)
"""
organisation_module
=
self
.
portal
.
organisation_module
internal_packing_list_module
=
self
.
portal
.
internal_packing_list_module
product_module
=
self
.
portal
.
product_module
delete_module_list
=
[
organisation_module
,
internal_packing_list_module
,
product_module
]
def
isDelete
(
document
):
if
document
.
getTitle
()
is
None
:
return
False
return
document
.
getTitle
().
startswith
(
self
.
_getTestDocumentTitlePrefix
())
for
module
in
delete_module_list
:
delete_id_list
=
[
id_
for
id_
in
module
.
objectIds
()
if
isDelete
(
module
[
id_
])]
module
.
manage_delObjects
(
delete_id_list
)
rule_reference_script
=
'InternalPackingList_getRuleReference'
if
self
.
portal
.
portal_skins
.
custom
.
get
(
rule_reference_script
,
None
)
is
not
None
:
self
.
portal
.
portal_skins
.
custom
.
manage_delObjects
([
rule_reference_script
])
self
.
commit
()
def
_getTestDocumentTitlePrefix
(
self
):
return
self
.
getTitle
()
def
_getTestDocumentTitle
(
self
,
reference
):
return
"{}_{}"
.
format
(
self
.
_getTestDocumentTitlePrefix
(),
reference
)
def
testSearchResults
(
self
):
"""
Test portal_tabular.searchResults() which uses portal_catalog.searchResults()
as the given data.
"""
organisationA_title
=
self
.
_getTestDocumentTitle
(
'organisationA'
)
organisation_description
=
'(description default value is empty string)'
self
.
portal
.
organisation_module
.
newContent
(
portal_type
=
'Organisation'
,
description
=
organisation_description
,
title
=
organisationA_title
)
self
.
portal
.
organisation_module
.
newContent
(
portal_type
=
'Organisation'
,
description
=
organisation_description
,
title
=
self
.
_getTestDocumentTitle
(
'organisationB'
))
self
.
tic
()
result_list
=
self
.
portal
.
portal_catalog
(
portal_type
=
'Organisation'
,
title
=
self
.
_getTestDocumentTitle
(
'organisation%'
))
self
.
assertEqual
(
len
(
result_list
),
2
)
organisation_tabular
=
self
.
portal
.
portal_tabular
.
searchResults
(
portal_type
=
'Organisation'
,
title
=
self
.
_getTestDocumentTitle
(
'organisation%'
),
fillna_on_string
=
None
)
self
.
assertEqual
(
len
(
organisation_tabular
),
2
)
self
.
assertTrue
(
'title'
in
organisation_tabular
.
columns
.
tolist
())
organisationA_tabular
=
organisation_tabular
[
organisation_tabular
[
'title'
]
==
organisationA_title
]
self
.
assertEqual
(
len
(
organisationA_tabular
),
1
)
# only 'description' has empty string default value, so check this separatedly
self
.
assertEqual
(
organisationA_tabular
.
iloc
[
0
][
'description'
],
organisation_description
)
catalog_column_list
=
[
'uid'
,
'security_uid'
,
'owner'
,
'viewable_owner'
,
'path'
,
'relative_url'
,
'parent_uid'
,
'id'
,
'description'
,
'title'
,
'meta_type'
,
'portal_type'
,
'opportunity_state'
,
'corporate_registration_code'
,
'ean13_code'
,
'validation_state'
,
'simulation_state'
,
'causality_state'
,
'invoice_state'
,
'payment_state'
,
'event_state'
,
'immobilisation_state'
,
'reference'
,
'grouping_reference'
,
'grouping_date'
,
'source_reference'
,
'destination_reference'
,
'string_index'
,
'int_index'
,
'float_index'
,
'has_cell_content'
,
'creation_date'
,
'modification_date'
,
'indexation_timestamp'
]
self
.
assertTrue
(
len
(
organisationA_tabular
.
columns
.
tolist
())
>=
len
(
catalog_column_list
))
# catalog result has both uid and path by default so ignore them
select_dict
=
dict
.
fromkeys
(
set
(
catalog_column_list
)
-
set
([
'uid'
,
'path'
]),
None
)
catalog_search_result
=
self
.
portal
.
portal_catalog
.
searchResults
(
portal_type
=
'Organisation'
,
title
=
self
.
_getTestDocumentTitle
(
'organisation%'
),
select_dict
=
select_dict
)
organisationA_result
=
[
r
for
r
in
catalog_search_result
if
r
.
getTitle
()
==
organisationA_title
][
0
]
for
catalog_column
in
catalog_column_list
:
self
.
assertEqual
(
organisationA_tabular
.
iloc
[
0
][
catalog_column
],
organisationA_result
.
getProperty
(
catalog_column
),
"Not equal on {} expect:{}, result:{}"
.
format
(
catalog_column
,
organisationA_tabular
.
iloc
[
0
][
catalog_column
],
organisationA_result
.
getProperty
(
catalog_column
)
))
def
stepSetTestDocumentTitleNode1
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
sequence
.
edit
(
node_title
=
self
.
_getTestDocumentTitle
(
'node1'
))
def
stepSetTestDocumentTitleResource1
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
sequence
.
edit
(
resource_title
=
self
.
_getTestDocumentTitle
(
'resource1'
))
def
stepAddNode
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
node_title
=
sequence
.
get
(
'node_title'
)
node_value
=
self
.
portal
.
organisation_module
.
newContent
(
portal_type
=
'Organisation'
,
title
=
node_title
)
sequence
.
edit
(
node_value
=
node_value
)
def
stepAddResource
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
resource_title
=
sequence
.
get
(
'resource_title'
)
resource_value
=
self
.
portal
.
product_module
.
newContent
(
portal_type
=
'Product'
,
title
=
resource_title
)
sequence
.
edit
(
resource_value
=
resource_value
)
def
stepSetTestDocumentTitleMovement1
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
sequence
.
edit
(
movement_title
=
self
.
_getTestDocumentTitle
(
'movement1'
))
def
stepAddInternalPackingList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
movement_title
=
sequence
.
get
(
'movement_title'
)
resource_value
=
sequence
.
get
(
'resource_value'
)
node_value
=
sequence
.
get
(
'node_value'
)
ipl
=
self
.
portal
.
internal_packing_list_module
.
newContent
(
portal_type
=
'Internal Packing List'
,
source_value
=
node_value
,
title
=
movement_title
)
ipl
.
newContent
(
portal_type
=
'Internal Packing List Line'
,
title
=
movement_title
,
quantity
=
10
,
resource_value
=
resource_value
)
sequence
.
edit
(
internal_packing_list
=
ipl
)
def
stepConfirmInternalPackingList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
internal_packing_list
=
sequence
.
get
(
'internal_packing_list'
)
internal_packing_list
.
confirm
()
self
.
assertEqual
(
internal_packing_list
.
getSimulationState
(),
'confirmed'
)
def
stepGetInventoryList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
resource_value
=
sequence
.
get
(
'resource_value'
)
node_value
=
sequence
.
get
(
'node_value'
)
title_prefix
=
sequence
.
get
(
'title_prefix'
,
None
)
if
title_prefix
is
None
:
title_prefix
=
self
.
_getTestDocumentTitlePrefix
()
inventory_list
=
self
.
portal
.
portal_simulation
.
getInventoryList
(
title
=
"{}%"
.
format
(
title_prefix
),
portal_type
=
'Internal Packing List Line'
,
resource_uid
=
resource_value
.
getUid
(),
node_uid
=
node_value
.
getUid
())
sequence
.
edit
(
inventory_list
=
inventory_list
)
def
stepGetAllResourceInventoryList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
title_prefix
=
sequence
.
get
(
'title_prefix'
,
None
)
node_value
=
sequence
.
get
(
'node_value'
)
if
title_prefix
is
None
:
title_prefix
=
self
.
_getTestDocumentTitlePrefix
()
inventory_list
=
self
.
portal
.
portal_simulation
.
getInventoryList
(
title
=
"{}%"
.
format
(
title_prefix
),
portal_type
=
'Internal Packing List Line'
,
node_uid
=
node_value
.
getUid
())
sequence
.
edit
(
inventory_list
=
inventory_list
)
def
stepCheckWithGetFromDocumentListAgainstInventoryList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
node_title
=
sequence
.
get
(
'node_title'
)
movement_title
=
sequence
.
get
(
'movement_title'
)
inventory_list
=
sequence
.
get
(
'inventory_list'
)
self
.
assertEqual
(
len
(
inventory_list
),
1
)
inventory_tabular
=
self
.
portal
.
portal_tabular
.
getFromDocumentList
(
inventory_list
,
property_name_list
=
[
"node_title"
,
"title"
])
self
.
assertEqual
(
len
(
inventory_tabular
),
1
)
self
.
assertTrue
(
'node_title'
in
inventory_tabular
.
columns
.
tolist
())
self
.
assertTrue
(
'title'
in
inventory_tabular
.
columns
.
tolist
())
# if explicitly specifies property_name_list,
# the tabular only has the specified columns
self
.
assertEqual
(
len
(
inventory_tabular
.
columns
.
tolist
()),
2
)
self
.
assertEqual
(
inventory_tabular
.
iloc
[
0
][
'node_title'
],
node_title
)
self
.
assertEqual
(
inventory_tabular
.
iloc
[
0
][
'title'
],
movement_title
)
default_inventory_tabular
=
self
.
portal
.
portal_tabular
.
getFromDocumentList
(
inventory_list
)
self
.
assertEqual
(
len
(
default_inventory_tabular
),
1
)
# The inventory list is ragarged as Internal Packing Line List, so does not have node_title
self
.
assertFalse
(
'node_title'
in
default_inventory_tabular
.
columns
.
tolist
())
self
.
assertTrue
(
'title'
in
default_inventory_tabular
.
columns
.
tolist
())
# If do not specify the property_names, it automatically add
# all the Sale Packing List Line property and category names based on the portal type
# configuration, so the number of columns is bigger than 2. (can be > 200)
self
.
assertTrue
(
len
(
default_inventory_tabular
.
columns
.
tolist
())
>
2
)
self
.
assertEqual
(
default_inventory_tabular
.
iloc
[
0
][
'title'
],
movement_title
)
self
.
assertTrue
(
'source_title'
in
default_inventory_tabular
.
columns
.
tolist
())
# The inventory list is regarded as Sale Packing Line List, so it has source_title
self
.
assertEqual
(
default_inventory_tabular
.
iloc
[
0
][
'source_title'
],
node_title
)
def
stepCheckWithGetTabularAgainstInventoryList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
inventory_list
=
sequence
.
get
(
'inventory_list'
)
node_title
=
sequence
.
get
(
'node_title'
)
node_value
=
sequence
.
get
(
'node_value'
)
resource_value
=
sequence
.
get
(
'resource_value'
)
resource_title
=
sequence
.
get
(
'resource_title'
)
movement_title
=
sequence
.
get
(
'movement_title'
)
# Test with portal_tabular() whitch is an alias of portal_tabular.getTabular()
# at first check without passing additonal_property_name_list parameter
inventory_tabular_without_name
=
self
.
portal
.
portal_tabular
(
inventory_list
)
property_name_list
=
[
'node_title'
,
'title'
,
'resource_title'
]
self
.
assertEqual
(
len
(
inventory_tabular_without_name
),
1
)
for
property_name
in
property_name_list
:
self
.
assertTrue
(
property_name
not
in
inventory_tabular_without_name
.
columns
.
tolist
(),
"{} is in the columns:{}"
.
format
(
property_name
,
inventory_tabular_without_name
.
columns
.
tolist
()))
# They have uid because Resource_zGetInventoryList returns them in the brain
self
.
assertEqual
(
inventory_tabular_without_name
.
iloc
[
0
][
'node_uid'
],
node_value
.
getUid
())
self
.
assertEqual
(
inventory_tabular_without_name
.
iloc
[
0
][
'resource_uid'
],
resource_value
.
getUid
())
# check with additional_property_name_list parameter
inventory_tabular_with_name
=
self
.
portal
.
portal_tabular
(
inventory_list
,
additional_property_name_list
=
property_name_list
)
self
.
assertEqual
(
len
(
inventory_tabular_with_name
),
1
)
self
.
assertEqual
(
len
(
inventory_tabular_with_name
.
columns
.
tolist
()),
len
(
inventory_tabular_without_name
.
columns
.
tolist
())
+
len
(
property_name_list
))
for
property_name
in
property_name_list
:
self
.
assertTrue
(
property_name
in
inventory_tabular_with_name
.
columns
.
tolist
(),
"{} is not in the columns:{}"
.
format
(
property_name
,
inventory_tabular_with_name
.
columns
.
tolist
()))
self
.
assertEqual
(
inventory_tabular_with_name
.
iloc
[
0
][
'node_title'
],
node_title
)
self
.
assertEqual
(
inventory_tabular_with_name
.
iloc
[
0
][
'title'
],
movement_title
)
self
.
assertEqual
(
inventory_tabular_with_name
.
iloc
[
0
][
'resource_title'
],
resource_title
)
def
testGetInventoryList
(
self
):
sequence_list
=
SequenceList
()
sequence_string
=
"""
DisableSimulationOnInternalPackingList
SetTestDocumentTitleNode1
AddNode
SetTestDocumentTitleResource1
AddResource
SetTestDocumentTitleMovement1
AddInternalPackingList
ConfirmInternalPackingList
Tic
GetInventoryList
CheckWithGetFromDocumentListAgainstInventoryList
CheckWithGetTabularAgainstInventoryList
"""
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
)
def
testFillnaOnString
(
self
):
"""
Test fillna_on_string parameter
"""
dict_list
=
[{
"test"
:
"a"
},
{
"test"
:
None
},
{
"test"
:
""
},
{
"test"
:
"d"
},
{
"test"
:
None
}]
# by default it is empty
df1
=
self
.
portal
.
portal_tabular
(
dict_list
)
empty_value
=
""
self
.
assertEqual
(
df1
.
iloc
[
0
][
"test"
],
"a"
)
self
.
assertEqual
(
df1
.
iloc
[
1
][
"test"
],
empty_value
)
self
.
assertEqual
(
df1
.
iloc
[
2
][
"test"
],
""
)
self
.
assertEqual
(
df1
.
iloc
[
3
][
"test"
],
"d"
)
self
.
assertEqual
(
df1
.
iloc
[
4
][
"test"
],
empty_value
)
empty_value_2
=
"""[No Value]"""
df2
=
self
.
portal
.
portal_tabular
(
dict_list
,
fillna_on_string
=
empty_value_2
)
self
.
assertEqual
(
df2
.
iloc
[
0
][
"test"
],
"a"
)
self
.
assertEqual
(
df2
.
iloc
[
1
][
"test"
],
empty_value_2
)
self
.
assertEqual
(
df2
.
iloc
[
2
][
"test"
],
""
)
self
.
assertEqual
(
df2
.
iloc
[
3
][
"test"
],
"d"
)
self
.
assertEqual
(
df2
.
iloc
[
4
][
"test"
],
empty_value_2
)
def
testFillnaOnNumber
(
self
):
"""
Test fillna_on_number
"""
dict_list
=
[{
"test"
:
0
},
{
"test"
:
None
},
{
"test"
:
2
},
{
"test"
:
3
},
{
"test"
:
None
}]
# by default it is empty
df1
=
self
.
portal
.
portal_tabular
(
dict_list
)
empty_value
=
0.0
self
.
assertEqual
(
df1
.
iloc
[
0
][
"test"
],
0
)
self
.
assertEqual
(
df1
.
iloc
[
1
][
"test"
],
empty_value
)
self
.
assertEqual
(
df1
.
iloc
[
2
][
"test"
],
2
)
self
.
assertEqual
(
df1
.
iloc
[
3
][
"test"
],
3
)
self
.
assertEqual
(
df1
.
iloc
[
4
][
"test"
],
empty_value
)
empty_value_2
=
-
1
df2
=
self
.
portal
.
portal_tabular
(
dict_list
,
fillna_on_number
=
empty_value_2
)
self
.
assertEqual
(
df2
.
iloc
[
0
][
"test"
],
0
)
self
.
assertEqual
(
df2
.
iloc
[
1
][
"test"
],
empty_value_2
)
self
.
assertEqual
(
df2
.
iloc
[
2
][
"test"
],
2
)
self
.
assertEqual
(
df2
.
iloc
[
3
][
"test"
],
3
)
self
.
assertEqual
(
df2
.
iloc
[
4
][
"test"
],
empty_value_2
)
def
testGetFromDocumentList
(
self
):
"""
Check to specify accessor
"""
organisation_list
=
[]
for
_title
in
(
'testAccesssor1'
,
'testAccesssor2'
):
organisation_title
=
self
.
_getTestDocumentTitle
(
_title
)
organisation
=
self
.
portal
.
organisation_module
.
newContent
(
portal_type
=
'Organisation'
,
title
=
organisation_title
,
activity_code
=
'test activity code'
)
organisation_list
.
append
(
organisation
)
organisation_tabular
=
self
.
portal
.
portal_tabular
.
getFromDocumentList
(
organisation_list
)
self
.
assertEqual
(
len
(
organisation_tabular
),
2
)
self
.
assertEqual
(
organisation_tabular
.
iloc
[
0
][
'activity_code'
],
'test activity code'
)
def
testFillnaOnUid
(
self
):
"""
Check fillna_on_uid parameter
"""
node_title
=
self
.
_getTestDocumentTitle
(
"test_node_fillna_on_uid_1"
)
node_value
=
self
.
portal
.
organisation_module
.
newContent
(
portal_type
=
'Organisation'
,
title
=
node_title
)
spl_title
=
self
.
_getTestDocumentTitle
(
"test_spl_fillna_on_uid_1"
)
spl
=
self
.
portal
.
sale_packing_list_module
.
newContent
(
portal_type
=
'Sale Packing List'
,
source_value
=
node_value
,
title
=
spl_title
)
sale_packing_list_list
=
[
spl
]
sale_packing_list_tabular
=
self
.
portal
.
portal_tabular
.
getFromDocumentList
(
sale_packing_list_list
)
self
.
assertEqual
(
len
(
sale_packing_list_tabular
),
1
)
self
.
assertEqual
(
sale_packing_list_tabular
.
iloc
[
0
][
'destination_uid'
],
-
1
)
self
.
assertEqual
(
sale_packing_list_tabular
.
iloc
[
0
][
'source_uid'
],
node_value
.
getUid
())
empty_uid
=
-
99999999
sale_packing_list_tabular2
=
self
.
portal
.
portal_tabular
.
getFromDocumentList
(
sale_packing_list_list
,
fillna_on_uid
=
empty_uid
)
self
.
assertEqual
(
len
(
sale_packing_list_tabular2
),
1
)
self
.
assertEqual
(
sale_packing_list_tabular2
.
iloc
[
0
][
'destination_uid'
],
empty_uid
)
self
.
assertEqual
(
sale_packing_list_tabular2
.
iloc
[
0
][
'source_uid'
],
node_value
.
getUid
())
def
testFillna
(
self
):
"""
Test portal_tabular.fillna() method
"""
dict_list
=
[{
'test'
:
0
},
{
'test'
:
None
},
{
'test'
:
2
},
{
'test'
:
3
},
{
'test'
:
None
}]
# by default it is empty
df1
=
self
.
portal
.
portal_tabular
(
dict_list
)
numeric_empty_value
=
0.0
self
.
assertEqual
(
df1
.
iloc
[
0
][
'test'
],
0
)
self
.
assertEqual
(
df1
.
iloc
[
1
][
'test'
],
numeric_empty_value
)
self
.
assertEqual
(
df1
.
iloc
[
2
][
'test'
],
2
)
self
.
assertEqual
(
df1
.
iloc
[
3
][
'test'
],
3
)
self
.
assertEqual
(
df1
.
iloc
[
4
][
'test'
],
numeric_empty_value
)
# add new column into the dataframe
df1
[
'test_numeric'
]
=
[
None
,
100
,
None
,
200
,
300
]
# So by default Na value of numeric is NaN in pandas dataframe
self
.
assertTrue
(
math
.
isnan
(
df1
.
iloc
[
0
][
'test_numeric'
]))
self
.
assertEqual
(
df1
.
iloc
[
1
][
'test_numeric'
],
100
)
self
.
assertTrue
(
math
.
isnan
(
df1
.
iloc
[
2
][
'test_numeric'
]))
self
.
assertEqual
(
df1
.
iloc
[
3
][
'test_numeric'
],
200
)
self
.
assertEqual
(
df1
.
iloc
[
4
][
'test_numeric'
],
300
)
df1
[
'test_string'
]
=
[
'x'
,
None
,
'y'
,
None
,
'z'
]
# The default Na value of string is None in pandas dataframe
self
.
assertEqual
(
df1
.
iloc
[
0
][
'test_string'
],
'x'
)
self
.
assertEqual
(
df1
.
iloc
[
1
][
'test_string'
],
None
)
self
.
assertEqual
(
df1
.
iloc
[
2
][
'test_string'
],
'y'
)
self
.
assertEqual
(
df1
.
iloc
[
3
][
'test_string'
],
None
)
self
.
assertEqual
(
df1
.
iloc
[
4
][
'test_string'
],
'z'
)
# Fill Na/NaN values with portal_tabular.fillna()
df2
=
self
.
portal
.
portal_tabular
.
fillna
(
df1
)
self
.
assertEqual
(
df2
.
iloc
[
0
][
'test_numeric'
],
numeric_empty_value
)
self
.
assertEqual
(
df2
.
iloc
[
1
][
'test_numeric'
],
100
)
self
.
assertEqual
(
df2
.
iloc
[
2
][
'test_numeric'
],
numeric_empty_value
)
self
.
assertEqual
(
df2
.
iloc
[
3
][
'test_numeric'
],
200
)
self
.
assertEqual
(
df2
.
iloc
[
4
][
'test_numeric'
],
300
)
string_empty_value
=
''
# Test they are filled with the default string filler ''
self
.
assertEqual
(
df2
.
iloc
[
0
][
'test_string'
],
'x'
)
self
.
assertEqual
(
df2
.
iloc
[
1
][
'test_string'
],
string_empty_value
)
self
.
assertEqual
(
df2
.
iloc
[
2
][
'test_string'
],
'y'
)
self
.
assertEqual
(
df2
.
iloc
[
3
][
'test_string'
],
string_empty_value
)
self
.
assertEqual
(
df2
.
iloc
[
4
][
'test_string'
],
'z'
)
# portal_tabular.fillna() with specifying the empty values
numeric_empty_value_2
=
-
1
string_empty_value_2
=
"""[No Value]"""
df3
=
self
.
portal
.
portal_tabular
.
fillna
(
df1
,
fillna_on_number
=
numeric_empty_value_2
,
fillna_on_string
=
string_empty_value_2
)
# Test with the specified filler
self
.
assertEqual
(
df3
.
iloc
[
0
][
'test_numeric'
],
numeric_empty_value_2
)
self
.
assertEqual
(
df3
.
iloc
[
1
][
'test_numeric'
],
100
)
self
.
assertEqual
(
df3
.
iloc
[
2
][
'test_numeric'
],
numeric_empty_value_2
)
self
.
assertEqual
(
df3
.
iloc
[
3
][
'test_numeric'
],
200
)
self
.
assertEqual
(
df3
.
iloc
[
4
][
'test_numeric'
],
300
)
self
.
assertEqual
(
df3
.
iloc
[
0
][
'test_string'
],
'x'
)
self
.
assertEqual
(
df3
.
iloc
[
1
][
'test_string'
],
string_empty_value_2
)
self
.
assertEqual
(
df3
.
iloc
[
2
][
'test_string'
],
'y'
)
self
.
assertEqual
(
df3
.
iloc
[
3
][
'test_string'
],
string_empty_value_2
)
self
.
assertEqual
(
df3
.
iloc
[
4
][
'test_string'
],
'z'
)
def
stepDisableSimulationOnInternalPackingList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
# Do not care simulation in this test, so return None
# for the rule reference of Internal Packing List
script_container
=
self
.
portal
.
portal_skins
.
custom
code
=
'return None'
createZODBPythonScript
(
script_container
,
'InternalPackingList_getRuleReference'
,
'**kw'
,
code
)
def
stepSetTestDocumentTitleNode2
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
sequence
.
edit
(
node_title
=
self
.
_getTestDocumentTitle
(
'node2'
))
def
stepSetTestDocumentTitleResource2
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
sequence
.
edit
(
resource_title
=
self
.
_getTestDocumentTitle
(
'resource2'
))
def
stepSetTestDocumentTitleTestReportMovement1
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
sequence
.
edit
(
movement_title
=
self
.
_getTestDocumentTitle
(
'test_report_movement1'
))
def
stepSetTestDocumentTitleTestReportMovement2
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
sequence
.
edit
(
movement_title
=
self
.
_getTestDocumentTitle
(
'test_report_movement2'
))
def
stepSetTestDocumentTitleTestReportMovement3
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
sequence
.
edit
(
movement_title
=
self
.
_getTestDocumentTitle
(
'test_report_movement3'
))
def
stepSetTestDocumentTitleTestReportMovement4
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
sequence
.
edit
(
movement_title
=
self
.
_getTestDocumentTitle
(
'test_report_movement4'
))
def
stepConfirmAllInternalPackingList
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
title
=
"{}_{}%"
.
format
(
self
.
_getTestDocumentTitlePrefix
(),
'test_report_movement'
)
result
=
self
.
portal
.
portal_catalog
(
portal_type
=
'Internal Packing List'
,
title
=
title
)
for
r
in
result
:
internal_packing_list
=
r
.
getObject
()
internal_packing_list
.
confirm
()
self
.
assertEqual
(
internal_packing_list
.
getSimulationState
(),
'confirmed'
)
def
stepSetTitlePrefix
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
title_prefix
=
"{}_{}"
.
format
(
self
.
_getTestDocumentTitlePrefix
(),
'test_report_movement'
)
sequence
.
edit
(
title_prefix
=
title_prefix
)
def
stepCheckToCreateReport
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
inventory_list
=
sequence
.
get
(
'inventory_list'
)
additional_property_name_list
=
[
'resource_title'
,
'node_title'
,
'title'
]
inventory_tabular
=
self
.
portal
.
portal_tabular
(
inventory_list
,
additional_property_name_list
=
additional_property_name_list
)
self
.
assertEqual
(
len
(
inventory_tabular
),
4
)
node_value
=
sequence
.
get
(
'node_value'
)
for
i
in
range
(
4
):
self
.
assertEqual
(
inventory_tabular
.
iloc
[
i
][
'node_title'
],
node_value
.
getTitle
())
self
.
assertEqual
(
inventory_tabular
.
iloc
[
i
][
'inventory'
],
-
10
)
"""
node1, resource1, movement1, -10
node1, resource1, movement2, -10
node1, resource2, movement3, -10
node1, resource2, movement4, -10
"""
# Aggregate the result grouping by resource_title and node_title,
# then sorting by resource_title, and summing the inventory.
report_tabular
=
inventory_tabular
.
groupby
(
[
'resource_title'
,
'node_title'
,
]
).
agg
(
dict
(
inventory
=
'sum'
)).
reset_index
().
sort_values
(
by
=
[
'resource_title'
])
self
.
assertEqual
(
len
(
report_tabular
),
2
)
self
.
assertEqual
(
report_tabular
.
iloc
[
0
][
'inventory'
],
-
20
)
self
.
assertEqual
(
report_tabular
.
iloc
[
1
][
'inventory'
],
-
20
)
title_prefix
=
self
.
_getTestDocumentTitlePrefix
()
# The result is ordered by resource title
self
.
assertEqual
(
report_tabular
.
iloc
[
0
][
'resource_title'
],
"{}_{}"
.
format
(
title_prefix
,
'resource1'
))
self
.
assertEqual
(
report_tabular
.
iloc
[
1
][
'resource_title'
],
"{}_{}"
.
format
(
title_prefix
,
'resource2'
))
# Turn into dict to show in listbox for example
report_dict_list
=
report_tabular
.
to_dict
(
"records"
)
for
report_dict
in
report_dict_list
:
self
.
assertTrue
(
isinstance
(
report_dict
,
dict
))
self
.
assertEqual
(
report_dict
[
'node_title'
],
node_value
.
getTitle
())
self
.
assertEqual
(
report_dict
[
'inventory'
],
-
20
)
self
.
assertTrue
(
'resource_title'
in
report_dict
)
def
testReport
(
self
):
"""
Test tabular data result for reports such as groupby, join, and sorting
"""
sequence_list
=
SequenceList
()
sequence_string
=
"""
DisableSimulationOnInternalPackingList
Tic
SetTestDocumentTitleNode1
AddNode
SetTestDocumentTitleResource1
AddResource
SetTestDocumentTitleTestReportMovement1
AddInternalPackingList
SetTestDocumentTitleTestReportMovement2
AddInternalPackingList
SetTestDocumentTitleResource2
AddResource
SetTestDocumentTitleTestReportMovement3
AddInternalPackingList
SetTestDocumentTitleTestReportMovement4
AddInternalPackingList
ConfirmAllInternalPackingList
Tic
SetTitlePrefix
GetAllResourceInventoryList
CheckToCreateReport
"""
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
)
def
testEncoding
(
self
):
"""
Test portal_tabular returns utf-8 string not unicode string
"""
dict_list
=
[{
'test'
:
None
},
{
'test'
:
'あ'
},
{
'test'
:
''
},
{
'test'
:
'ç'
},
{
'test'
:
None
}]
# by default it is empty
df1
=
self
.
portal
.
portal_tabular
(
dict_list
)
string_empty_value
=
''
self
.
assertEqual
(
df1
.
iloc
[
0
][
'test'
],
string_empty_value
)
self
.
assertEqual
(
df1
.
iloc
[
1
][
'test'
],
'あ'
)
self
.
assertEqual
(
df1
.
iloc
[
2
][
'test'
],
string_empty_value
)
self
.
assertEqual
(
df1
.
iloc
[
3
][
'test'
],
'ç'
)
self
.
assertEqual
(
df1
.
iloc
[
4
][
'test'
],
string_empty_value
)
def
testEmptyTabular
(
self
):
"""
Test updating empty tabular does not update different empty tabular
"""
empty_tabular
=
self
.
portal
.
portal_tabular
(
data_list
=
[])
empty_tabular
[
'a'
]
=
[
1
,
2
,
3
]
empty_tabular2
=
self
.
portal
.
portal_tabular
(
data_list
=
[])
self
.
assertNotEquals
(
len
(
empty_tabular
.
columns
),
len
(
empty_tabular2
.
columns
))
self
.
assertNotEquals
(
len
(
empty_tabular
),
len
(
empty_tabular2
))
\ No newline at end of file
bt5/erp5_tabular_data_tool_test/TestTemplateItem/portal_components/test.erp5.testTabularDataTool.xml
0 → 100644
View file @
f97e908a
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Test Component"
module=
"erp5.portal_type"
/>
</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>
testTabularDataTool
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
test.erp5.testTabularDataTool
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Test Component
</string>
</value>
</item>
<item>
<key>
<string>
sid
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
text_content_error_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
text_content_warning_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
version
</string>
</key>
<value>
<string>
erp5
</string>
</value>
</item>
<item>
<key>
<string>
workflow_history
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAM=
</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>
<pickle>
<dictionary>
<item>
<key>
<string>
data
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
component_validation_workflow
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAQ=
</string>
</persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"4"
aka=
"AAAAAAAAAAQ="
>
<pickle>
<global
name=
"WorkflowHistoryList"
module=
"Products.ERP5Type.Workflow"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_log
</string>
</key>
<value>
<list>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<string>
validate
</string>
</value>
</item>
<item>
<key>
<string>
validation_state
</string>
</key>
<value>
<string>
validated
</string>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
bt5/erp5_tabular_data_tool_test/bt/dependency_list
0 → 100644
View file @
f97e908a
erp5_trade
erp5_full_text_mroonga_catalog
erp5_tabular_data_tool
\ No newline at end of file
bt5/erp5_tabular_data_tool_test/bt/template_format_version
0 → 100644
View file @
f97e908a
1
\ No newline at end of file
bt5/erp5_tabular_data_tool_test/bt/template_test_id_list
0 → 100644
View file @
f97e908a
test.erp5.testTabularDataTool
\ No newline at end of file
bt5/erp5_tabular_data_tool_test/bt/title
0 → 100644
View file @
f97e908a
erp5_tabular_data_tool_test
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment