Compare commits
8 commits
main
...
ver_6.8.30
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b237981a9b | ||
![]() |
aac6930999 | ||
![]() |
7a4fd94981 | ||
![]() |
6550baa468 | ||
![]() |
e017f20df4 | ||
![]() |
3a0df50d52 | ||
![]() |
eaa502a626 | ||
![]() |
7769f5f14a |
11 changed files with 60 additions and 26 deletions
12
README.rst
12
README.rst
|
@ -9,7 +9,7 @@ pip install mds-cashbook
|
||||||
|
|
||||||
Requires
|
Requires
|
||||||
========
|
========
|
||||||
- Tryton 6.0
|
- Tryton 6.8
|
||||||
|
|
||||||
How to
|
How to
|
||||||
======
|
======
|
||||||
|
@ -153,6 +153,14 @@ currency are converted into the display currency of the parent cash book.
|
||||||
Changes
|
Changes
|
||||||
=======
|
=======
|
||||||
|
|
||||||
*6.0.0 - 05.08.2022*
|
*6.8.30 - 25.07.2023*
|
||||||
|
|
||||||
|
- updt: optimize code, add tests
|
||||||
|
|
||||||
|
*6.8.29 - 24.07.2023*
|
||||||
|
|
||||||
|
- fix: type of indexes
|
||||||
|
|
||||||
|
*6.8.28 - 05.06.2023*
|
||||||
|
|
||||||
- init
|
- init
|
||||||
|
|
2
book.py
2
book.py
|
@ -574,7 +574,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
|
||||||
'defbook', 'book1', 'book2', 'book3',
|
'defbook', 'book1', 'book2', 'book3',
|
||||||
'book4', 'book5']:
|
'book4', 'book5']:
|
||||||
cfg1 = ConfigUser.search([
|
cfg1 = ConfigUser.search([
|
||||||
('iduser.id', '=', book.owner.id),
|
('iduser', '=', book.owner.id),
|
||||||
('%s.id' % x, '=', book.id)])
|
('%s.id' % x, '=', book.id)])
|
||||||
if len(cfg1) > 0:
|
if len(cfg1) > 0:
|
||||||
to_write_config.extend([cfg1, {x: None}])
|
to_write_config.extend([cfg1, {x: None}])
|
||||||
|
|
18
line.py
18
line.py
|
@ -23,7 +23,7 @@ sel_payee = [
|
||||||
('party.party', 'Party')
|
('party.party', 'Party')
|
||||||
]
|
]
|
||||||
|
|
||||||
sel_linetype = [
|
sel_linestate = [
|
||||||
('edit', 'Edit'),
|
('edit', 'Edit'),
|
||||||
('check', 'Checked'),
|
('check', 'Checked'),
|
||||||
('recon', 'Reconciled'),
|
('recon', 'Reconciled'),
|
||||||
|
@ -197,7 +197,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView):
|
||||||
|
|
||||||
state = fields.Selection(
|
state = fields.Selection(
|
||||||
string='State', required=True, readonly=True,
|
string='State', required=True, readonly=True,
|
||||||
selection=sel_linetype)
|
selection=sel_linestate)
|
||||||
state_string = state.translated('state')
|
state_string = state.translated('state')
|
||||||
state_cashbook = fields.Function(fields.Selection(
|
state_cashbook = fields.Function(fields.Selection(
|
||||||
string='State of Cashbook',
|
string='State of Cashbook',
|
||||||
|
@ -245,7 +245,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView):
|
||||||
(t.state, Index.Equality())),
|
(t.state, Index.Equality())),
|
||||||
Index(
|
Index(
|
||||||
t,
|
t,
|
||||||
(t.reference, Index.Range())),
|
(t.reference, Index.Equality())),
|
||||||
})
|
})
|
||||||
cls._sql_constraints.extend([
|
cls._sql_constraints.extend([
|
||||||
('state_val2',
|
('state_val2',
|
||||||
|
@ -375,7 +375,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView):
|
||||||
# allow cashbook-line at range-limits
|
# allow cashbook-line at range-limits
|
||||||
if Recon.search_count([
|
if Recon.search_count([
|
||||||
('state', 'in', ['check', 'done']),
|
('state', 'in', ['check', 'done']),
|
||||||
('cashbook.id', '=', line.cashbook.id),
|
('cashbook', '=', line.cashbook.id),
|
||||||
('date_from', '<', line.date),
|
('date_from', '<', line.date),
|
||||||
('date_to', '>', line.date)]) > 0:
|
('date_to', '>', line.date)]) > 0:
|
||||||
raise UserError(gettext(
|
raise UserError(gettext(
|
||||||
|
@ -386,7 +386,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView):
|
||||||
# reconciliations exist
|
# reconciliations exist
|
||||||
if Recon.search_count([
|
if Recon.search_count([
|
||||||
('state', 'in', ['check', 'done']),
|
('state', 'in', ['check', 'done']),
|
||||||
('cashbook.id', '=', line.cashbook.id),
|
('cashbook', '=', line.cashbook.id),
|
||||||
['OR',
|
['OR',
|
||||||
('date_from', '=', line.date),
|
('date_from', '=', line.date),
|
||||||
('date_to', '=', line.date)]]) > 1:
|
('date_to', '=', line.date)]]) > 1:
|
||||||
|
@ -751,7 +751,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView):
|
||||||
end_value = None
|
end_value = None
|
||||||
|
|
||||||
recons = Reconciliation.search([
|
recons = Reconciliation.search([
|
||||||
('cashbook.id', '=', line.cashbook.id),
|
('cashbook', '=', line.cashbook.id),
|
||||||
('date_to', '<=', line2.date),
|
('date_to', '<=', line2.date),
|
||||||
('state', '=', 'done'),
|
('state', '=', 'done'),
|
||||||
], order=[('date_from', 'DESC')], limit=1)
|
], order=[('date_from', 'DESC')], limit=1)
|
||||||
|
@ -761,14 +761,14 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView):
|
||||||
('date', '<=', line2.date),
|
('date', '<=', line2.date),
|
||||||
['OR',
|
['OR',
|
||||||
('reconciliation', '=', None),
|
('reconciliation', '=', None),
|
||||||
('reconciliation.id', '!=', recons[0])],
|
('reconciliation', '!=', recons[0])],
|
||||||
])
|
])
|
||||||
end_value = getattr(recons[0], 'end_%s' % field_name)
|
end_value = getattr(recons[0], 'end_%s' % field_name)
|
||||||
return (query2, end_value)
|
return (query2, end_value)
|
||||||
|
|
||||||
if line.cashbook:
|
if line.cashbook:
|
||||||
query = [
|
query = [
|
||||||
('cashbook.id', '=', line.cashbook.id),
|
('cashbook', '=', line.cashbook.id),
|
||||||
]
|
]
|
||||||
balance = Decimal('0.0')
|
balance = Decimal('0.0')
|
||||||
|
|
||||||
|
@ -778,7 +778,7 @@ class Line(SecondCurrencyMixin, MemCacheIndexMx, Workflow, ModelSQL, ModelView):
|
||||||
if line.reconciliation:
|
if line.reconciliation:
|
||||||
if line.reconciliation.state == 'done':
|
if line.reconciliation.state == 'done':
|
||||||
query.append(
|
query.append(
|
||||||
('reconciliation.id', '=', line.reconciliation.id),
|
('reconciliation', '=', line.reconciliation.id),
|
||||||
)
|
)
|
||||||
balance = getattr(
|
balance = getattr(
|
||||||
line.reconciliation, 'start_%s' % field_name)
|
line.reconciliation, 'start_%s' % field_name)
|
||||||
|
|
|
@ -183,7 +183,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
||||||
if Line.search_count([
|
if Line.search_count([
|
||||||
('date', '>', reconciliation.date_from),
|
('date', '>', reconciliation.date_from),
|
||||||
('date', '<', reconciliation.date_to),
|
('date', '<', reconciliation.date_to),
|
||||||
('cashbook.id', '=', reconciliation.cashbook.id),
|
('cashbook', '=', reconciliation.cashbook.id),
|
||||||
('state', 'not in', ['check', 'recon']),
|
('state', 'not in', ['check', 'recon']),
|
||||||
]) > 0:
|
]) > 0:
|
||||||
raise UserError(gettext(
|
raise UserError(gettext(
|
||||||
|
@ -224,7 +224,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
||||||
lines = Line.search([
|
lines = Line.search([
|
||||||
('date', '>=', reconciliation.date_from),
|
('date', '>=', reconciliation.date_from),
|
||||||
('date', '<=', reconciliation.date_to),
|
('date', '<=', reconciliation.date_to),
|
||||||
('cashbook.id', '=', reconciliation.cashbook.id),
|
('cashbook', '=', reconciliation.cashbook.id),
|
||||||
('reconciliation', '=', None),
|
('reconciliation', '=', None),
|
||||||
('state', 'in', ['check', 'recon']),
|
('state', 'in', ['check', 'recon']),
|
||||||
])
|
])
|
||||||
|
@ -315,7 +315,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
||||||
|
|
||||||
# deny if there are lines not linked to reconciliation
|
# deny if there are lines not linked to reconciliation
|
||||||
if Line.search_count([
|
if Line.search_count([
|
||||||
('cashbook.id', '=', reconciliation.cashbook.id),
|
('cashbook', '=', reconciliation.cashbook.id),
|
||||||
('reconciliation', '=', None),
|
('reconciliation', '=', None),
|
||||||
['OR',
|
['OR',
|
||||||
[ # lines inside of date-range
|
[ # lines inside of date-range
|
||||||
|
@ -405,7 +405,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
||||||
if self.cashbook:
|
if self.cashbook:
|
||||||
if self.date_from is not None:
|
if self.date_from is not None:
|
||||||
reconciliations = Recon.search([
|
reconciliations = Recon.search([
|
||||||
('cashbook.id', '=', self.cashbook.id),
|
('cashbook', '=', self.cashbook.id),
|
||||||
('date_from', '<', self.date_from),
|
('date_from', '<', self.date_from),
|
||||||
], order=[('date_from', 'DESC')], limit=1)
|
], order=[('date_from', 'DESC')], limit=1)
|
||||||
if len(reconciliations) > 0:
|
if len(reconciliations) > 0:
|
||||||
|
@ -457,7 +457,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
||||||
|
|
||||||
# set date_from to date_to of predecessor
|
# set date_from to date_to of predecessor
|
||||||
recons = Recon.search([
|
recons = Recon.search([
|
||||||
('cashbook.id', '=', id_cashbook),
|
('cashbook', '=', id_cashbook),
|
||||||
], order=[('date_to', 'DESC')], limit=1)
|
], order=[('date_to', 'DESC')], limit=1)
|
||||||
if len(recons) > 0:
|
if len(recons) > 0:
|
||||||
values['date_from'] = recons[0].date_to
|
values['date_from'] = recons[0].date_to
|
||||||
|
@ -466,7 +466,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
||||||
|
|
||||||
# set date_to to day of last 'checked'-booking in selected cashbook
|
# set date_to to day of last 'checked'-booking in selected cashbook
|
||||||
lines = Line.search([
|
lines = Line.search([
|
||||||
('cashbook.id', '=', id_cashbook),
|
('cashbook', '=', id_cashbook),
|
||||||
('state', '=', 'check'),
|
('state', '=', 'check'),
|
||||||
('reconciliation', '=', None),
|
('reconciliation', '=', None),
|
||||||
], order=[('date', 'DESC')], limit=1)
|
], order=[('date', 'DESC')], limit=1)
|
||||||
|
|
3
setup.py
3
setup.py
|
@ -40,7 +40,7 @@ with open(path.join(here, 'versiondep.txt'), encoding='utf-8') as f:
|
||||||
|
|
||||||
# tryton-version
|
# tryton-version
|
||||||
major_version = 6
|
major_version = 6
|
||||||
minor_version = 0
|
minor_version = 8
|
||||||
|
|
||||||
requires = ['python-slugify']
|
requires = ['python-slugify']
|
||||||
for dep in info.get('depends', []):
|
for dep in info.get('depends', []):
|
||||||
|
@ -89,6 +89,7 @@ setup(name='%s_%s' % (PREFIX, MODULE),
|
||||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
'Programming Language :: Python :: 3.8',
|
'Programming Language :: Python :: 3.8',
|
||||||
|
'Programming Language :: Python :: 3.9',
|
||||||
],
|
],
|
||||||
|
|
||||||
keywords='tryton cashbook',
|
keywords='tryton cashbook',
|
||||||
|
|
|
@ -9,7 +9,7 @@ from trytond.pool import Pool
|
||||||
from trytond.pyson import Eval, If
|
from trytond.pyson import Eval, If
|
||||||
from trytond.report import Report
|
from trytond.report import Report
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
from .line import sel_bookingtype, STATES, DEPENDS
|
from .line import sel_bookingtype, sel_linestate, STATES, DEPENDS
|
||||||
from .book import sel_state_book
|
from .book import sel_state_book
|
||||||
from .mixin import SecondCurrencyMixin, MemCacheIndexMx
|
from .mixin import SecondCurrencyMixin, MemCacheIndexMx
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ class SplitLine(SecondCurrencyMixin, MemCacheIndexMx, ModelSQL, ModelView):
|
||||||
selection=sel_bookingtype), 'on_change_with_bookingtype')
|
selection=sel_bookingtype), 'on_change_with_bookingtype')
|
||||||
state = fields.Function(fields.Selection(
|
state = fields.Function(fields.Selection(
|
||||||
string='State', readonly=True,
|
string='State', readonly=True,
|
||||||
selection=sel_linetype), 'on_change_with_state')
|
selection=sel_linestate), 'on_change_with_state')
|
||||||
cashbook = fields.Function(fields.Many2One(
|
cashbook = fields.Function(fields.Many2One(
|
||||||
string='Cashbook',
|
string='Cashbook',
|
||||||
readonly=True, states={'invisible': True}, model_name='cashbook.book'),
|
readonly=True, states={'invisible': True}, model_name='cashbook.book'),
|
||||||
|
|
|
@ -73,6 +73,26 @@ class SplitLineTestCase(object):
|
||||||
book.lines[0].splitlines[1].rec_name,
|
book.lines[0].splitlines[1].rec_name,
|
||||||
'Rev/Sp|6.00 usd|from cashbook [Cat1]')
|
'Rev/Sp|6.00 usd|from cashbook [Cat1]')
|
||||||
|
|
||||||
|
# check function fields
|
||||||
|
self.assertEqual(
|
||||||
|
book.lines[0].splitlines[0].category_view,
|
||||||
|
'Cat1')
|
||||||
|
self.assertEqual(book.lines[0].splitlines[0].date, date(2022, 5, 1))
|
||||||
|
self.assertEqual(book.lines[0].splitlines[0].target.rec_name, 'Cat1')
|
||||||
|
self.assertEqual(book.lines[0].splitlines[0].currency.rec_name, 'usd')
|
||||||
|
self.assertEqual(book.lines[0].splitlines[0].currency_digits, 2)
|
||||||
|
self.assertEqual(book.lines[0].splitlines[0].bookingtype, 'spin')
|
||||||
|
self.assertEqual(book.lines[0].splitlines[0].state, 'edit')
|
||||||
|
self.assertEqual(
|
||||||
|
book.lines[0].splitlines[0].cashbook.rec_name,
|
||||||
|
'Book 1 | 11.00 usd | Open')
|
||||||
|
self.assertEqual(book.lines[0].splitlines[0].feature, 'gen')
|
||||||
|
self.assertEqual(book.lines[0].splitlines[0].booktransf_feature, None)
|
||||||
|
self.assertEqual(book.lines[0].splitlines[0].state_cashbook, 'open')
|
||||||
|
self.assertEqual(
|
||||||
|
book.lines[0].splitlines[0].owner_cashbook.rec_name,
|
||||||
|
'Administrator')
|
||||||
|
|
||||||
@with_transaction()
|
@with_transaction()
|
||||||
def test_splitline_category_and_transfer(self):
|
def test_splitline_category_and_transfer(self):
|
||||||
""" add book, line, two split-lines,
|
""" add book, line, two split-lines,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[tryton]
|
[tryton]
|
||||||
version=6.0.0
|
version=6.8.30
|
||||||
depends:
|
depends:
|
||||||
res
|
res
|
||||||
currency
|
currency
|
||||||
|
|
7
types.py
7
types.py
|
@ -3,7 +3,7 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains the
|
# The COPYRIGHT file at the top level of this repository contains the
|
||||||
# full copyright notices and license terms.
|
# full copyright notices and license terms.
|
||||||
|
|
||||||
from trytond.model import ModelView, ModelSQL, fields, Unique
|
from trytond.model import ModelView, ModelSQL, fields, Unique, Index
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
|
|
||||||
|
@ -30,6 +30,11 @@ class Type(ModelSQL, ModelView):
|
||||||
cls._sql_constraints.extend([
|
cls._sql_constraints.extend([
|
||||||
('code_uniq', Unique(t, t.short), 'cashbook.msg_type_short_unique'),
|
('code_uniq', Unique(t, t.short), 'cashbook.msg_type_short_unique'),
|
||||||
])
|
])
|
||||||
|
cls._sql_indexes.update({
|
||||||
|
Index(
|
||||||
|
t,
|
||||||
|
(t.feature, Index.Equality())),
|
||||||
|
})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_feature(cls):
|
def default_feature(cls):
|
||||||
|
|
|
@ -152,7 +152,7 @@ class EnterBookingWizard(Wizard):
|
||||||
'cashbooks': [x.id for x in Cashbook.search([
|
'cashbooks': [x.id for x in Cashbook.search([
|
||||||
('state', '=', 'open'),
|
('state', '=', 'open'),
|
||||||
('btype', '!=', None),
|
('btype', '!=', None),
|
||||||
('owner.id', '=', Transaction().user),
|
('owner', '=', Transaction().user),
|
||||||
('id', 'in', book_ids),
|
('id', 'in', book_ids),
|
||||||
])],
|
])],
|
||||||
'bookingtype': getattr(self.start, 'bookingtype', 'out'),
|
'bookingtype': getattr(self.start, 'bookingtype', 'out'),
|
||||||
|
|
|
@ -55,7 +55,7 @@ class RunCbReportStart(ModelView):
|
||||||
|
|
||||||
if self.cashbook:
|
if self.cashbook:
|
||||||
recons = Recon2.search([
|
recons = Recon2.search([
|
||||||
('cashbook.id', '=', self.cashbook.id),
|
('cashbook', '=', self.cashbook.id),
|
||||||
], order=[('date_from', 'DESC')])
|
], order=[('date_from', 'DESC')])
|
||||||
return [x.id for x in recons]
|
return [x.id for x in recons]
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ class RunCbReport(Wizard):
|
||||||
result['cashbook'] = result['cashbooks'][0]
|
result['cashbook'] = result['cashbooks'][0]
|
||||||
|
|
||||||
recons = Recon2.search([
|
recons = Recon2.search([
|
||||||
('cashbook.id', '=', result['cashbook']),
|
('cashbook', '=', result['cashbook']),
|
||||||
], order=[('date_from', 'DESC')])
|
], order=[('date_from', 'DESC')])
|
||||||
if len(recons) > 0:
|
if len(recons) > 0:
|
||||||
result['reconciliations'] = [x.id for x in recons]
|
result['reconciliations'] = [x.id for x in recons]
|
||||||
|
|
Loading…
Reference in a new issue