Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
cubicweb
cubes
fresh
Commits
3345c9ec936d
Commit
02fe8980
authored
Jul 18, 2021
by
Nicolas Chauvat
Browse files
style: get back to black
parent
8da13d641e0d
Pipeline
#69242
failed with stages
in 56 seconds
Changes
17
Pipelines
3
Hide whitespace changes
Inline
Side-by-side
cubicweb_fresh/__pkginfo__.py
View file @
3345c9ec
# pylint: disable-msg=W0622
"""cubicweb-fresh application packaging information"""
modname
=
'
fresh
'
distname
=
'
cubicweb-fresh
'
modname
=
"
fresh
"
distname
=
"
cubicweb-fresh
"
numversion
=
(
1
,
1
,
0
)
version
=
'.'
.
join
(
str
(
num
)
for
num
in
numversion
)
version
=
"."
.
join
(
str
(
num
)
for
num
in
numversion
)
license
=
'
LGPL
'
author
=
'
Logilab
'
author_email
=
'
contact@logilab.fr
'
description
=
'
expense tracking application built on the CubicWeb framework
'
web
=
'
http://www.cubicweb.org/project/%s
'
%
distname
license
=
"
LGPL
"
author
=
"
Logilab
"
author_email
=
"
contact@logilab.fr
"
description
=
"
expense tracking application built on the CubicWeb framework
"
web
=
"
http://www.cubicweb.org/project/%s
"
%
distname
classifiers
=
[
'
Environment :: Web Environment
'
,
'
Framework :: CubicWeb
'
,
'
Programming Language :: Python
'
,
'
Programming Language :: JavaScript
'
,
]
"
Environment :: Web Environment
"
,
"
Framework :: CubicWeb
"
,
"
Programming Language :: Python
"
,
"
Programming Language :: JavaScript
"
,
]
__depends__
=
{
'
cubicweb[pyramid]
'
:
">=3.31.0,<3.32.0"
,
'
cubicweb-expense
'
:
">=0.9.0,<0.10.0"
,
'
cubicweb-workcase
'
:
">=0.8.0,<0.9.0"
,
'
cubicweb-searchui
'
:
">=0.4.0,<0.5.0"
,
'
cubicweb-rqlcontroller
'
:
">=0.7.0,<0.8.0"
,
'
cubicweb-signedrequest
'
:
">=1.0.0,<1.1.0"
,
'
cubicweb-sentry
'
:
">=0.5.0,<0.6.0"
,
'
cubicweb-card
'
:
">=1.1.0,<1.2.0"
,
'
cubicweb-oauth2
'
:
">=0.3.0,<0.4.0"
,
'
reportlab
'
:
">=3.5.0,<3.6.0"
,
'
cwclientlib
'
:
">=1.1.0,<1.2.0"
,
"
cubicweb[pyramid]
"
:
">=3.31.0,<3.32.0"
,
"
cubicweb-expense
"
:
">=0.9.0,<0.10.0"
,
"
cubicweb-workcase
"
:
">=0.8.0,<0.9.0"
,
"
cubicweb-searchui
"
:
">=0.4.0,<0.5.0"
,
"
cubicweb-rqlcontroller
"
:
">=0.7.0,<0.8.0"
,
"
cubicweb-signedrequest
"
:
">=1.0.0,<1.1.0"
,
"
cubicweb-sentry
"
:
">=0.5.0,<0.6.0"
,
"
cubicweb-card
"
:
">=1.1.0,<1.2.0"
,
"
cubicweb-oauth2
"
:
">=0.3.0,<0.4.0"
,
"
reportlab
"
:
">=3.5.0,<3.6.0"
,
"
cwclientlib
"
:
">=1.1.0,<1.2.0"
,
}
cubicweb_fresh/entities.py
View file @
3345c9ec
...
...
@@ -4,11 +4,10 @@ from cubicweb_expense.entities import ExpenseLine as BaseExpenseLine
class
ExpenseLine
(
BaseExpenseLine
):
@
property
def
workcase
(
self
):
rql
=
'
Any R WHERE E has_lines EL, EL eid %(el)s, E spent_for W, W ref R
'
rset
=
self
.
_cw
.
execute
(
rql
,
{
'
el
'
:
self
.
eid
})
rql
=
"
Any R WHERE E has_lines EL, EL eid %(el)s, E spent_for W, W ref R
"
rset
=
self
.
_cw
.
execute
(
rql
,
{
"
el
"
:
self
.
eid
})
if
rset
:
return
rset
[
0
][
0
]
return
None
cubicweb_fresh/hooks.py
View file @
3345c9ec
...
...
@@ -6,13 +6,13 @@ from cubicweb.server.sources import storages
class
ServerStartupHook
(
hook
.
Hook
):
__regid__
=
'
drh.serverstartup
'
events
=
(
'
server_startup
'
,
'
server_maintenance
'
)
__regid__
=
"
drh.serverstartup
"
events
=
(
"
server_startup
"
,
"
server_maintenance
"
)
def
__call__
(
self
):
bfssdir
=
join
(
self
.
repo
.
config
.
appdatahome
,
'
bfss
'
)
bfssdir
=
join
(
self
.
repo
.
config
.
appdatahome
,
"
bfss
"
)
if
not
exists
(
bfssdir
):
makedirs
(
bfssdir
)
print
(
'
created
'
,
bfssdir
)
print
(
"
created
"
,
bfssdir
)
storage
=
storages
.
BytesFileSystemStorage
(
bfssdir
)
storages
.
set_attribute_storage
(
self
.
repo
,
'
File
'
,
'
data
'
,
storage
)
storages
.
set_attribute_storage
(
self
.
repo
,
"
File
"
,
"
data
"
,
storage
)
cubicweb_fresh/migration/0.5.0_Any.py
View file @
3345c9ec
sync_schema_props_perms
(
'
spent_for
'
)
sync_schema_props_perms
(
"
spent_for
"
)
cubicweb_fresh/migration/0.5.1_Any.py
View file @
3345c9ec
sync_schema_props_perms
(
'
spent_for
'
,
syncprops
=
False
)
sync_schema_props_perms
(
"
spent_for
"
,
syncprops
=
False
)
cubicweb_fresh/migration/0.7.0_Any.py
View file @
3345c9ec
add_entity_type
(
'
Training
'
)
add_entity_type
(
"
Training
"
)
cubicweb_fresh/migration/0.7.1_Any.py
View file @
3345c9ec
if
'
Training
'
not
in
schema
:
add_entity_type
(
'
Training
'
)
if
"
Training
"
not
in
schema
:
add_entity_type
(
"
Training
"
)
# workflows doen't understand yams inheritance
rql
(
'SET WF workflow_of ET, ET default_workflow WF '
'WHERE WF workflow_of WC, WC name "Workcase", ET name "Training"'
)
rql
(
"SET WF workflow_of ET, ET default_workflow WF "
'WHERE WF workflow_of WC, WC name "Workcase", ET name "Training"'
)
commit
()
cubicweb_fresh/migration/1.0.1_Any.py
View file @
3345c9ec
add_cube
(
'
sentry
'
)
add_cube
(
"
sentry
"
)
cubicweb_fresh/migration/1.1.0_Any.py
View file @
3345c9ec
add_cube
(
'
oauth2
'
)
drop_cube
(
'
trustedauth
'
)
add_cube
(
"
oauth2
"
)
drop_cube
(
"
trustedauth
"
)
cubicweb_fresh/migration/postcreate.py
View file @
3345c9ec
# -*- coding: utf-8 -*-
# postcreate script. You could setup a workflow here for example
for
login
in
(
u
'alf'
,
u
'syt'
,
u
'nico'
,
u
'jphc'
,
u
'ocy'
,
u
'auc'
,
u
'katia'
,
u
'graz'
,
u
'dede'
,
u
'juj'
,
u
'ludal'
,
u
'steph'
,
u
'arthur'
,
u
'david'
,
u
'joel'
,
u
'gaston'
,
u
'adim'
):
rql
(
'INSERT CWUser E: E login %(login)s, E upassword %(login)s, E in_group G '
'WHERE G name "users"'
,
{
'login'
:
login
})
rql
(
'INSERT PaidByAccount P: P label %(label)s, P associated_to U WHERE U login %(login)s'
,
{
'label'
:
u
"refund account - %s"
%
login
,
'login'
:
login
})
rql
(
'INSERT PaidForAccount P: P label %(label)s'
,
{
'label'
:
u
"charge account - %s"
%
login
})
for
login
in
(
u
"alf"
,
u
"syt"
,
u
"nico"
,
u
"jphc"
,
u
"ocy"
,
u
"auc"
,
u
"katia"
,
u
"graz"
,
u
"dede"
,
u
"juj"
,
u
"ludal"
,
u
"steph"
,
u
"arthur"
,
u
"david"
,
u
"joel"
,
u
"gaston"
,
u
"adim"
,
):
rql
(
"INSERT CWUser E: E login %(login)s, E upassword %(login)s, E in_group G "
'WHERE G name "users"'
,
{
"login"
:
login
},
)
rql
(
"INSERT PaidByAccount P: P label %(label)s, P associated_to U WHERE U login %(login)s"
,
{
"label"
:
u
"refund account - %s"
%
login
,
"login"
:
login
},
)
rql
(
"INSERT PaidForAccount P: P label %(label)s"
,
{
"label"
:
u
"charge account - %s"
%
login
},
)
for
label
in
(
u
'Logilab - CB Nicolas'
,
u
'Logilab - CB Alexandre'
,
u
'Logilab - CB Olivier'
,
u
'Logilab - Espèces'
):
rql
(
'INSERT PaidByAccount P: P label %(label)s'
,
{
'label'
:
label
})
for
label
in
(
u
"Logilab - CB Nicolas"
,
u
"Logilab - CB Alexandre"
,
u
"Logilab - CB Olivier"
,
u
"Logilab - Espèces"
,
):
rql
(
"INSERT PaidByAccount P: P label %(label)s"
,
{
"label"
:
label
})
cubicweb_fresh/schema.py
View file @
3345c9ec
...
...
@@ -9,11 +9,14 @@ class Training(Workcase):
class
spent_for
(
RelationDefinition
):
subject
=
'
Expense
'
object
=
'
Workcase
'
cardinality
=
'
?*
'
subject
=
"
Expense
"
object
=
"
Workcase
"
cardinality
=
"
?*
"
__permissions__
=
{
'read'
:
(
'managers'
,
'users'
),
'add'
:
(
'managers'
,
RRQLExpression
(
'NOT (S in_state ST, ST name "accepted")'
)),
'delete'
:
(
'managers'
,
RRQLExpression
(
'NOT (S in_state ST, ST name "accepted")'
)),
}
"read"
:
(
"managers"
,
"users"
),
"add"
:
(
"managers"
,
RRQLExpression
(
'NOT (S in_state ST, ST name "accepted")'
)),
"delete"
:
(
"managers"
,
RRQLExpression
(
'NOT (S in_state ST, ST name "accepted")'
),
),
}
cubicweb_fresh/sobjects.py
View file @
3345c9ec
...
...
@@ -7,12 +7,13 @@ from cubicweb.dataimport import stores, importer
# XXX class copied in crm/fresh, should be kepts sync
class
CWClientLibDataFeedParser
(
datafeed
.
DataFeedParser
):
"""Base class for parsers that search for distant entities using cwclientlib.
"""
"""Base class for parsers that search for distant entities using cwclientlib."""
def
process_urls
(
self
,
*
args
,
**
kwargs
):
"""IDataFeedParser main entry point."""
os
.
environ
[
'CWCLCONF'
]
=
os
.
path
.
join
(
self
.
_cw
.
vreg
.
config
.
apphome
,
'cwclientlibrc'
)
os
.
environ
[
"CWCLCONF"
]
=
os
.
path
.
join
(
self
.
_cw
.
vreg
.
config
.
apphome
,
"cwclientlibrc"
)
self
.
_source_uris
=
{}
error
=
super
(
CWClientLibDataFeedParser
,
self
).
process_urls
(
*
args
,
**
kwargs
)
if
not
error
:
...
...
@@ -22,44 +23,53 @@ class CWClientLibDataFeedParser(datafeed.DataFeedParser):
def
process
(
self
,
url
,
raise_on_error
=
False
):
"""Called once by process_urls (several URL are not expected with this parser)."""
# ensure url ends with a single slash for proper extid generation
url
=
url
.
rstrip
(
'/'
)
+
'/'
url
=
url
.
rstrip
(
"/"
)
+
"/"
eeimporter
=
self
.
build_importer
(
raise_on_error
)
entities
=
self
.
extentities_generator
(
url
)
set_cwuri
=
importer
.
use_extid_as_cwuri
(
eeimporter
.
extid2eid
)
eeimporter
.
import_entities
(
set_cwuri
(
entities
))
self
.
stats
[
'
created
'
]
=
eeimporter
.
created
self
.
stats
[
'
updated
'
]
=
eeimporter
.
updated
self
.
stats
[
"
created
"
]
=
eeimporter
.
created
self
.
stats
[
"
updated
"
]
=
eeimporter
.
updated
def
build_importer
(
self
,
raise_on_error
):
"""Instantiate and configure an importer"""
etypes
,
extid2eid
=
self
.
init_extid2eid
()
existing_relations
=
self
.
init_existing_relations
()
store
=
stores
.
NoHookRQLObjectStore
(
self
.
_cw
,
metagen
=
stores
.
MetaGenerator
(
self
.
_cw
,
source
=
self
.
source
))
return
importer
.
ExtEntitiesImporter
(
self
.
_cw
.
vreg
.
schema
,
store
,
extid2eid
=
extid2eid
,
existing_relations
=
existing_relations
,
etypes_order_hint
=
etypes
,
import_log
=
self
.
import_log
,
raise_on_error
=
raise_on_error
)
store
=
stores
.
NoHookRQLObjectStore
(
self
.
_cw
,
metagen
=
stores
.
MetaGenerator
(
self
.
_cw
,
source
=
self
.
source
)
)
return
importer
.
ExtEntitiesImporter
(
self
.
_cw
.
vreg
.
schema
,
store
,
extid2eid
=
extid2eid
,
existing_relations
=
existing_relations
,
etypes_order_hint
=
etypes
,
import_log
=
self
.
import_log
,
raise_on_error
=
raise_on_error
,
)
def
handle_deletion
(
self
,
*
args
,
**
kwargs
):
for
extid
,
(
eid
,
etype
)
in
self
.
_source_uris
.
items
():
self
.
_cw
.
entity_from_eid
(
eid
,
etype
).
cw_delete
()
def
existing_entities
(
self
,
etype
):
rset
=
self
.
_cw
.
execute
(
'Any XURI, X WHERE X cwuri XURI, X is {0},'
' X cw_source S, S eid %(s)s'
.
format
(
etype
),
{
's'
:
self
.
source
.
eid
})
rset
=
self
.
_cw
.
execute
(
"Any XURI, X WHERE X cwuri XURI, X is {0},"
" X cw_source S, S eid %(s)s"
.
format
(
etype
),
{
"s"
:
self
.
source
.
eid
},
)
for
extid
,
eid
in
rset
:
self
.
_source_uris
[
extid
]
=
(
eid
,
etype
)
yield
extid
,
eid
def
states_map
(
self
,
etype
):
return
dict
(
self
.
_cw
.
execute
(
'Any SN,S WHERE S name SN, S state_of WF, '
'ET default_workflow WF, ET name %(etype)s'
,
{
'etype'
:
etype
}))
return
dict
(
self
.
_cw
.
execute
(
"Any SN,S WHERE S name SN, S state_of WF, "
"ET default_workflow WF, ET name %(etype)s"
,
{
"etype"
:
etype
},
)
)
def
ext_entity
(
self
,
url
,
etype
,
eid
,
values
):
extid
=
url
+
text_type
(
eid
)
...
...
@@ -69,13 +79,14 @@ class CWClientLibDataFeedParser(datafeed.DataFeedParser):
class
DataFeedFreshActivity
(
CWClientLibDataFeedParser
):
"""Parser to import workcases from crm."""
__regid__
=
'fresh.workcases'
__regid__
=
"fresh.workcases"
def
init_extid2eid
(
self
):
# put state eids in extid2eid as we'll want to link to them
extid2eid
=
dict
(
self
.
_cw
.
execute
(
'
Any X,X WHERE X is State
'
))
extid2eid
=
dict
(
self
.
_cw
.
execute
(
"
Any X,X WHERE X is State
"
))
# map existing orders and workorders from our souce
etypes
=
(
'
Workcase
'
,)
etypes
=
(
"
Workcase
"
,)
for
etype
in
etypes
:
for
extid
,
eid
in
self
.
existing_entities
(
etype
):
extid2eid
[
extid
]
=
eid
...
...
@@ -84,9 +95,10 @@ class DataFeedFreshActivity(CWClientLibDataFeedParser):
def
init_existing_relations
(
self
):
existing_relations
=
{}
rset
=
self
.
_cw
.
execute
(
'Any O,OS WHERE O in_state OS, O is Workcase, O cw_source S, S eid %(s)s'
,
{
's'
:
self
.
source
.
eid
})
existing_relations
[
'in_state'
]
=
set
(
tuple
(
x
)
for
x
in
rset
)
"Any O,OS WHERE O in_state OS, O is Workcase, O cw_source S, S eid %(s)s"
,
{
"s"
:
self
.
source
.
eid
},
)
existing_relations
[
"in_state"
]
=
set
(
tuple
(
x
)
for
x
in
rset
)
return
existing_relations
def
extentities_generator
(
self
,
url
):
...
...
@@ -94,16 +106,17 @@ class DataFeedFreshActivity(CWClientLibDataFeedParser):
proxy
=
cwclientlib
.
cwproxy_for
(
url
)
# XXX check modification_date > last_update
# information necessary to relate order to a state
states_map
=
self
.
states_map
(
'
Workcase
'
)
states_map
=
self
.
states_map
(
"
Workcase
"
)
for
args
in
proxy
.
execute
(
'Any W,SN,WR,WS WHERE W is_instance_of Workcase, '
'W ref WR, W subject WS, W in_state S, S name SN'
):
"Any W,SN,WR,WS WHERE W is_instance_of Workcase, "
"W ref WR, W subject WS, W in_state S, S name SN"
):
eid
=
args
.
pop
(
0
)
state
=
args
.
pop
(
0
)
values
=
values_dict
(
args
,
[
'
ref
'
,
'
subject
'
])
values
[
'
in_state
'
]
=
set
([
states_map
[
state
]])
yield
self
.
ext_entity
(
url
,
'
Workcase
'
,
eid
,
values
)
values
=
values_dict
(
args
,
[
"
ref
"
,
"
subject
"
])
values
[
"
in_state
"
]
=
set
([
states_map
[
state
]])
yield
self
.
ext_entity
(
url
,
"
Workcase
"
,
eid
,
values
)
def
values_dict
(
values_list
,
attributes
):
...
...
cubicweb_fresh/views/__init__.py
View file @
3345c9ec
...
...
@@ -5,19 +5,28 @@ from cubicweb.web.views.ajaxcontroller import ajaxfunc
_afs
=
uicfg
.
autoform_section
_affk
=
uicfg
.
autoform_field_kwargs
_afs
.
tag_subject_of
((
'Expense'
,
'spent_for'
,
'*'
),
'main'
,
'attributes'
)
_afs
.
tag_subject_of
((
'Expense'
,
'spent_for'
,
'*'
),
'muledit'
,
'attributes'
)
_affk
.
tag_subject_of
((
'Expense'
,
'spent_for'
,
'*'
),
{
'widget'
:
fw
.
LazyRestrictedAutoCompletionWidget
(
autocomplete_initfunc
=
'get_concerned_by'
,
autocomplete_settings
=
{
'limit'
:
100
,
'delay'
:
300
})})
_afs
.
tag_subject_of
((
"Expense"
,
"spent_for"
,
"*"
),
"main"
,
"attributes"
)
_afs
.
tag_subject_of
((
"Expense"
,
"spent_for"
,
"*"
),
"muledit"
,
"attributes"
)
_affk
.
tag_subject_of
(
(
"Expense"
,
"spent_for"
,
"*"
),
{
"widget"
:
fw
.
LazyRestrictedAutoCompletionWidget
(
autocomplete_initfunc
=
"get_concerned_by"
,
autocomplete_settings
=
{
"limit"
:
100
,
"delay"
:
300
},
)
},
)
@
ajaxfunc
(
output_type
=
'
json
'
)
@
ajaxfunc
(
output_type
=
"
json
"
)
def
get_concerned_by
(
self
):
term
=
self
.
_cw
.
form
[
'q'
]
limit
=
self
.
_cw
.
form
.
get
(
'limit'
,
50
)
return
[{
'value'
:
eid
,
'label'
:
ref
}
for
eid
,
ref
in
self
.
_cw
.
execute
(
'DISTINCT Any W,R ORDERBY R LIMIT %s WHERE W ref R,'
'W ref ILIKE %%(term)s'
%
limit
,
{
'term'
:
u
'%%%s%%'
%
term
})]
term
=
self
.
_cw
.
form
[
"q"
]
limit
=
self
.
_cw
.
form
.
get
(
"limit"
,
50
)
return
[
{
"value"
:
eid
,
"label"
:
ref
}
for
eid
,
ref
in
self
.
_cw
.
execute
(
"DISTINCT Any W,R ORDERBY R LIMIT %s WHERE W ref R,"
"W ref ILIKE %%(term)s"
%
limit
,
{
"term"
:
u
"%%%s%%"
%
term
},
)
]
cubicweb_fresh/views/accounting.py
View file @
3345c9ec
...
...
@@ -15,59 +15,64 @@ from cubicweb.view import EntityView
class
ExpenseAccountingXmlView
(
EntityView
):
__regid__
=
'
accexpense
'
__select__
=
is_instance
(
'
Expense
'
)
__regid__
=
"
accexpense
"
__select__
=
is_instance
(
"
Expense
"
)
title
=
_
(
'
accounting entry view
'
)
title
=
_
(
"
accounting entry view
"
)
templatable
=
False
content_type
=
'
text/xml
'
content_type
=
"
text/xml
"
def
call
(
self
):
"""display a list of entities by calling their <item_vid> view
"""
"""display a list of entities by calling their <item_vid> view"""
self
.
w
(
u
'<?xml version="1.0" encoding="%s"?>
\n
'
%
self
.
_cw
.
encoding
)
self
.
w
(
u
'<?xml-stylesheet href="%saccounting-entries.xsl" '
u
'rel="stylesheet" type="text/xsl"?>
\n
'
%
self
.
_cw
.
datadir_url
)
self
.
w
(
u
'<ecritures>
\n
'
)
self
.
w
(
u
'<?xml-stylesheet href="%saccounting-entries.xsl" '
u
'rel="stylesheet" type="text/xsl"?>
\n
'
%
self
.
_cw
.
datadir_url
)
self
.
w
(
u
"<ecritures>
\n
"
)
for
i
in
range
(
self
.
cw_rset
.
rowcount
):
self
.
cell_call
(
i
,
0
)
self
.
w
(
u
'
</ecritures>
\n
'
)
self
.
w
(
u
"
</ecritures>
\n
"
)
def
cell_call
(
self
,
row
,
col
):
entity
=
self
.
cw_rset
.
get_entity
(
row
,
col
)
rset
=
entity
.
related
(
'
has_lines
'
)
rset
=
entity
.
related
(
"
has_lines
"
)
for
i
in
range
(
len
(
rset
)):
self
.
wview
(
'
accentry
'
,
rset
,
row
=
i
,
col
=
0
)
self
.
wview
(
"
accentry
"
,
rset
,
row
=
i
,
col
=
0
)
class
ExpenseLineAccountingEntryXmlView
(
EntityView
):
__regid__
=
'accentry'
__select__
=
is_instance
(
'ExpenseLine'
,)
__regid__
=
"accentry"
__select__
=
is_instance
(
"ExpenseLine"
,
)
title
=
_
(
'
accounting entry view
'
)
title
=
_
(
"
accounting entry view
"
)
templatable
=
False
content_type
=
'
text/xml
'
content_type
=
"
text/xml
"
def
call
(
self
):
"""display a list of entities by calling their <item_vid> view
"""
"""display a list of entities by calling their <item_vid> view"""
self
.
w
(
u
'<?xml version="1.0" encoding="%s"?>
\n
'
%
self
.
_cw
.
encoding
)
self
.
w
(
u
'<?xml-stylesheet href="%saccounting-entries.xsl" '
u
'rel="stylesheet" type="text/xsl"?>
\n
'
%
self
.
_cw
.
datadir_url
)
self
.
w
(
u
'<ecritures>
\n
'
)
self
.
w
(
u
'<?xml-stylesheet href="%saccounting-entries.xsl" '
u
'rel="stylesheet" type="text/xsl"?>
\n
'
%
self
.
_cw
.
datadir_url
)
self
.
w
(
u
"<ecritures>
\n
"
)
for
i
in
range
(
self
.
cw_rset
.
rowcount
):
self
.
cell_call
(
i
,
0
)
self
.
w
(
u
'
</ecritures>
\n
'
)
self
.
w
(
u
"
</ecritures>
\n
"
)
def
cell_call
(
self
,
row
,
col
):
entity
=
self
.
cw_rset
.
complete_entity
(
row
,
col
)
self
.
w
(
u
' <ecriture date="%s">
\n
'
%
entity
.
diem
.
strftime
(
'
%Y-%m-%d
'
))
self
.
w
(
u
'
<libelle>%s</libelle>
\n
'
%
xml_escape
(
entity
.
dc_long_title
()))
self
.
w
(
u
' <ecriture date="%s">
\n
'
%
entity
.
diem
.
strftime
(
"
%Y-%m-%d
"
))
self
.
w
(
u
"
<libelle>%s</libelle>
\n
"
%
xml_escape
(
entity
.
dc_long_title
()))
amount
=
round
(
entity
.
euro_amount
(),
2
)
taxes
=
round
(
entity
.
taxes
,
2
)
account
=
entity
.
paid_by
[
0
].
account
and
xml_escape
(
entity
.
paid_by
[
0
].
account
)
or
u
''
self
.
w
(
u
' <credit compte="%s" montant="%.2f" />
\n
'
%
(
account
,
amount
))
account
=
(
entity
.
paid_by
[
0
].
account
and
xml_escape
(
entity
.
paid_by
[
0
].
account
)
or
u
""
)
self
.
w
(
u
' <credit compte="%s" montant="%.2f" />
\n
'
%
(
account
,
amount
))
if
entity
.
taxes
:
# XXX hardcoded account for VAT
self
.
w
(
u
' <debit compte="44566" montant="%.2f" />
\n
'
%
entity
.
taxes
)
...
...
@@ -81,9 +86,8 @@ class ExpenseLineAccountingEntryXmlView(EntityView):
debit_remainder
-=
1
else
:
debit
=
debit_quotient
/
100.0
account
=
account
.
account
and
xml_escape
(
account
.
account
)
or
u
''
self
.
w
(
u
' <debit compte="%s" montant="%.2f" />
\n
'
%
(
account
,
debit
))
account
=
account
.
account
and
xml_escape
(
account
.
account
)
or
u
""
self
.
w
(
u
' <debit compte="%s" montant="%.2f" />
\n
'
%
(
account
,
debit
))
if
entity
.
workcase
:
self
.
w
(
u
'
<groupe>%s</groupe>
\n
'
%
xml_escape
(
entity
.
workcase
))
self
.
w
(
u
'
</ecriture>
\n
'
)
self
.
w
(
u
"
<groupe>%s</groupe>
\n
"
%
xml_escape
(
entity
.
workcase
))
self
.
w
(
u
"
</ecriture>
\n
"
)
cubicweb_fresh/views/actions.py
View file @
3345c9ec
...
...
@@ -12,10 +12,10 @@ from cubicweb.web.action import Action
class
AccountingAction
(
Action
):
__regid__
=
'
accaction
'
__select__
=
is_instance
(
'
Expense
'
)
title
=
_
(
'
generate accounting entries
'
)
__regid__
=
"
accaction
"
__select__
=
is_instance
(
"
Expense
"
)
title
=
_
(
"
generate accounting entries
"
)
def
url
(
self
):
entity
=
self
.
cw_rset
.
get_entity
(
self
.
cw_row
or
0
,
self
.
cw_col
or
0
)
return
entity
.
absolute_url
(
vid
=
'
accexpense
'
)
return
entity
.
absolute_url
(
vid
=
"
accexpense
"
)
setup.py
View file @
3345c9ec
...
...
@@ -32,34 +32,34 @@ here = dirname(__file__)
# load metadata from the __pkginfo__.py file so there is no risk of conflict
# see https://packaging.python.org/en/latest/single_source_version.html
pkginfo
=
join
(
here
,
'
cubicweb_fresh
'
,
'
__pkginfo__.py
'
)
pkginfo
=
join
(
here
,
"
cubicweb_fresh
"
,
"
__pkginfo__.py
"
)
__pkginfo__
=
{}
with
open
(
pkginfo
)
as
f
:
exec
(
f
.
read
(),
__pkginfo__
)
# get required metadatas
distname
=
__pkginfo__
[
'
distname
'
]
version
=
__pkginfo__
[
'
version
'
]
license
=
__pkginfo__
[
'
license
'
]
description
=
__pkginfo__
[
'
description
'
]
web
=
__pkginfo__
[
'
web
'
]
author
=
__pkginfo__
[
'
author
'
]
author_email
=
__pkginfo__
[
'
author_email
'
]
classifiers
=
__pkginfo__
[
'
classifiers
'
]
distname
=
__pkginfo__
[
"
distname
"
]
version
=
__pkginfo__
[
"
version
"
]
license
=
__pkginfo__
[
"
license
"
]
description
=
__pkginfo__
[
"
description
"
]
web
=
__pkginfo__
[
"
web
"
]
author
=
__pkginfo__
[
"
author
"
]
author_email
=
__pkginfo__
[
"
author_email
"
]
classifiers
=
__pkginfo__
[
"
classifiers
"
]
with
open
(
join
(
here
,
'
README.rst
'
))
as
f
:
with
open
(
join
(
here
,
"
README.rst
"
))
as
f
:
long_description
=
f
.
read
()
# get optional metadatas
data_files
=
__pkginfo__
.
get
(
'
data_files
'
,
None
)
dependency_links
=
__pkginfo__
.
get
(
'
dependency_links
'
,
())
data_files
=
__pkginfo__
.
get
(
"
data_files
"
,
None
)
dependency_links
=
__pkginfo__
.
get
(
"
dependency_links
"
,
())
requires
=
{}
for
entry
in
(
"__depends__"
,):
# "__recommends__"):
requires
.
update
(
__pkginfo__
.
get
(
entry
,
{}))
install_requires
=
[
"{0} {1}"
.
format
(
d
,
v
and
v
or
""
).
strip
()
for
d
,
v
in
requires
.
items
()
]
install_requires
=
[
"{0} {1}"
.
format
(
d
,
v
and
v
or
""
).
strip
()
for
d
,
v
in
requires
.
items
()
]
setup
(
...
...
@@ -72,12 +72,12 @@ setup(
author_email
=
author_email
,
url
=
web
,
classifiers
=
classifiers
,
packages
=
find_packages
(
exclude
=
[
'
test
'
]),
packages
=
find_packages
(
exclude
=
[
"
test
"
]),
install_requires
=
install_requires
,
include_package_data
=
True
,
entry_points
=
{
'
cubicweb.cubes
'
:
[
'
fresh=cubicweb_fresh
'
,
"
cubicweb.cubes
"
:
[
"
fresh=cubicweb_fresh
"
,
],
},
zip_safe
=
False
,
...
...
test/test_fresh.py
View file @
3345c9ec
...
...
@@ -8,11 +8,13 @@ from cubicweb.devtools.testlib import AutomaticWebTest
class
AutomaticWebTest
(
AutomaticWebTest
):
vid_validators
=
AutomaticWebTest
.
vid_validators
.
copy
()
vid_validators
.
update
({