diff --git a/__init__.py b/__init__.py index 21d3742..d29e36e 100644 --- a/__init__.py +++ b/__init__.py @@ -10,6 +10,7 @@ from .line import Line, LineContext from .wizard_openline import OpenCashBook, OpenCashBookStart from .configuration import Configuration, UserConfiguration from .category import Category +from .reconciliation import Reconciliation def register(): Pool.register( @@ -20,6 +21,7 @@ def register(): Book, LineContext, Line, + Reconciliation, OpenCashBookStart, module='cashbook', type_='model') Pool.register( diff --git a/book.py b/book.py index a360f7c..da49399 100644 --- a/book.py +++ b/book.py @@ -39,16 +39,22 @@ class Book(Workflow, ModelSQL, ModelView): model_name='cashbook.type', ondelete='RESTRICT', states=STATES, depends=DEPENDS) owner = fields.Many2One(string='Owner', required=True, select=True, - model_name='res.user', ondelete='SET NULL') + model_name='res.user', ondelete='SET NULL', + states=STATES, depends=DEPENDS) reviewer = fields.Many2One(string='Reviewer', select=True, help='Group of users who have write access to the cashbook.', - model_name='res.group', ondelete='SET NULL') + model_name='res.group', ondelete='SET NULL', + states=STATES, depends=DEPENDS) observer = fields.Many2One(string='Observer', select=True, help='Group of users who have read-only access to the cashbook.', - model_name='res.group', ondelete='SET NULL') + model_name='res.group', ondelete='SET NULL', + states=STATES, depends=DEPENDS) lines = fields.One2Many(string='Lines', field='cashbook', model_name='cashbook.line', states=STATES, depends=DEPENDS) + reconciliations = fields.One2Many(string='Reconciliations', + field='cashbook', model_name='cashbook.recon', + states=STATES, depends=DEPENDS) account = fields.Many2One(string='Account', select=True, model_name='account.account', ondelete='RESTRICT', states=STATES, depends=DEPENDS) diff --git a/line.py b/line.py index 0484ab7..b95e4ae 100644 --- a/line.py +++ b/line.py @@ -77,6 +77,8 @@ class Line(Workflow, ModelSQL, ModelView): required=True, readonly=True, depends=['currency_digits']) credit = fields.Numeric(string='Credit', digits=(16, Eval('currency_digits', 2)), required=True, readonly=True, depends=['currency_digits']) + reconciliation = fields.Many2One(string='Reconciliation', readonly=True, + model_name='cashbook.recon', ondelete='SET NULL') balance = fields.Function(fields.Numeric(string='Balance', digits=(16, Eval('currency_digits', 2)), @@ -494,7 +496,6 @@ class LineContext(ModelView): """ get number of accessible cashbooks, depends on user-permissions """ - print('-- on_change_with_num_cashbook:', Transaction().context) LineContext = Pool().get('cashbook.line.context') return LineContext.default_num_cashbook() diff --git a/locale/de.po b/locale/de.po index 6ab03d3..621161a 100644 --- a/locale/de.po +++ b/locale/de.po @@ -110,6 +110,18 @@ msgctxt "model:ir.rule.group,name:rg_book_companies" msgid "User in companies" msgstr "Benutzer im Unternehmen" +msgctxt "model:ir.rule.group,name:rg_recon_companies" +msgid "User in companies" +msgstr "Benutzer im Unternehmen" + +msgctxt "model:ir.rule.group,name:rg_recon_write_adm" +msgid "Administrators: Reconciliation read/write" +msgstr "Administratoren: Abstimmung bearbeiten" + +msgctxt "model:ir.rule.group,name:rg_recon_write" +msgid "Owners and reviewers: Reconciliation write" +msgstr "Eigentümer und Bearbeiter: Abstimmung bearbeiten" + ############## # ir.ui.menu # @@ -126,7 +138,7 @@ msgctxt "model:ir.ui.menu,name:menu_typeconfig" msgid "Cashbook Type" msgstr "Kassenbuchtyp" -msgctxt "model:ir.ui.menu,name:menu_bookconfig" +msgctxt "model:ir.ui.menu,name:menu_booklist" msgid "Cashbook" msgstr "Kassenbuch" @@ -210,6 +222,18 @@ msgctxt "model:ir.model.button,string:book_wfarchive_button" msgid "Archive" msgstr "Archiv" +msgctxt "model:ir.model.button,string:recon_wfedit_button" +msgid "Edit" +msgstr "Bearbeiten" + +msgctxt "model:ir.model.button,string:recon_wfcheck_button" +msgid "Check" +msgstr "Prüfen" + +msgctxt "model:ir.model.button,string:recon_wfdone_button" +msgid "Done" +msgstr "Fertig" + ################# # cashbook.book # @@ -222,6 +246,10 @@ msgctxt "view:cashbook.book:" msgid "Owner and Authorizeds" msgstr "Eigentümer und Autorisierte" +msgctxt "view:cashbook.book:" +msgid "Reconciliations" +msgstr "Abstimmungen" + msgctxt "field:cashbook.book,name:" msgid "Name" msgstr "Name" @@ -282,6 +310,18 @@ msgctxt "field:cashbook.book,start_balance:" msgid "Initial Amount" msgstr "Anfangsbetrag" +msgctxt "field:cashbook.book,balance:" +msgid "Balance" +msgstr "Saldo" + +msgctxt "field:cashbook.book,reconciliations:" +msgid "Reconciliations" +msgstr "Abstimmungen" + +msgctxt "field:cashbook.book,lines:" +msgid "Lines" +msgstr "Zeilen" + ################# # cashbook.line # @@ -406,6 +446,10 @@ msgctxt "help:cashbook.line,balance:" msgid "Balance of the cash book up to the current line, if the default sorting applies." msgstr "Saldo des Kassenbuchs bis zur aktuellen Zeile, sofern die Standardsortierung gilt." +msgctxt "field:cashbook.line,reconciliation:" +msgid "Reconciliation" +msgstr "Abstimmung" + ################# # cashbook.type # @@ -689,3 +733,71 @@ msgstr "Kategorie: Kontonummer zeigen" msgctxt "help:cashbook.configuration_user,cataccno:" msgid "Shows the number of the linked account in the name of a category." msgstr "Zeigt im Namen einer Kategorie die Nummer des verknüpften Kontos." + + +################## +# cashbook.recon # +################## +msgctxt "model:cashbook.recon,name:" +msgid "Cashbook Reconciliation" +msgstr "Kassenbuchabstimmung" + +msgctxt "view:cashbook.recon:" +msgid "Reconciliation period" +msgstr "Abstimmungszeitraum" + +msgctxt "view:cashbook.recon:" +msgid "State" +msgstr "Status" + +msgctxt "field:cashbook.recon,cashbook:" +msgid "Cashbook" +msgstr "Kassenbuch" + +msgctxt "field:cashbook.recon,date:" +msgid "Date" +msgstr "Datum" + +msgctxt "field:cashbook.recon,date_from:" +msgid "Start Date" +msgstr "Anfangsdatum" + +msgctxt "field:cashbook.recon,date_to:" +msgid "End Date" +msgstr "Endedatum" + +msgctxt "field:cashbook.recon,state:" +msgid "State" +msgstr "Status" + +msgctxt "selection:cashbook.recon,state:" +msgid "Edit" +msgstr "Bearbeiten" + +msgctxt "selection:cashbook.recon,state:" +msgid "Check" +msgstr "Prüfen" + +msgctxt "selection:cashbook.recon,state:" +msgid "Done" +msgstr "Fertig" + +msgctxt "field:cashbook.recon,lines:" +msgid "Lines" +msgstr "Zeilen" + +msgctxt "field:cashbook.recon,state_cashbook:" +msgid "State of Cashbook" +msgstr "Kassenbuchstatus" + +msgctxt "selection:cashbook.recon,state_cashbook:" +msgid "Open" +msgstr "Geöffnet" + +msgctxt "selection:cashbook.recon,state_cashbook:" +msgid "Closed" +msgstr "Geschlossen" + +msgctxt "selection:cashbook.recon,state_cashbook:" +msgid "Archive" +msgstr "Archiv" diff --git a/menu.xml b/menu.xml index 4dbd7e3..30094cd 100644 --- a/menu.xml +++ b/menu.xml @@ -30,19 +30,10 @@ full copyright notices and license terms. --> - - - - - - - + parent="menu_config" sequence="10"/> @@ -51,7 +42,7 @@ full copyright notices and license terms. --> + parent="menu_config" sequence="20"/> @@ -59,7 +50,7 @@ full copyright notices and license terms. --> + parent="menu_category" sequence="10"/> @@ -69,6 +60,27 @@ full copyright notices and license terms. --> + + + + + + + + + + + + + + + + + + + diff --git a/reconciliation.py b/reconciliation.py new file mode 100644 index 0000000..6105259 --- /dev/null +++ b/reconciliation.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- +# This file is part of the cashbook-module from m-ds for Tryton. +# The COPYRIGHT file at the top level of this repository contains the +# full copyright notices and license terms. + +from trytond.model import Workflow, ModelView, ModelSQL, fields, Unique +from trytond.transaction import Transaction +from trytond.pyson import Eval, If, Or +from trytond.pool import Pool +from trytond.report import Report +from decimal import Decimal +from .book import sel_state_book + + +sel_reconstate = [ + ('edit', 'Edit'), + ('check', 'Check'), + ('done', 'Done'), + ] + +STATES = { + 'readonly': Or( + Eval('state', '') != 'edit', + Eval('state_cashbook', '') != 'open', + ), + } +DEPENDS=['state', 'state_cashbook'] + + +class Reconciliation(Workflow, ModelSQL, ModelView): + 'Cashbook Reconciliation' + __name__ = 'cashbook.recon' + + cashbook = fields.Many2One(string='Cashbook', required=True, select=True, + model_name='cashbook.book', ondelete='CASCADE', readonly=True) + date = fields.Date(string='Date', required=True, select=True, + states=STATES, depends=DEPENDS) + + date_from = fields.Date(string='Start Date', + required=True, + domain=[ + If(Eval('date_to') & Eval('date_from'), + ('date_from', '<=', Eval('date_to')), + ()), + ], + states=STATES, depends=DEPENDS+['date_to']) + date_to = fields.Date(string='End Date', + required=True, + domain=[ + If(Eval('date_to') & Eval('date_from'), + ('date_from', '<=', Eval('date_to')), + ()), + ], + states=STATES, depends=DEPENDS+['date_from']) + lines = fields.One2Many(string='Lines', field='reconciliation', + model_name='cashbook.line', states=STATES, + depends=DEPENDS+['date_from', 'date_to', 'cashbook'], + add_remove=[ + ('cashbook', '=', Eval('cashbook')), + ('date', '>=', Eval('date_from')), + ('date', '<=', Eval('date_to')), + ], + domain=[ + ('date', '>=', Eval('date_from')), + ('date', '<=', Eval('date_to')), + ]) + + state = fields.Selection(string='State', required=True, readonly=True, + select=True, selection=sel_reconstate) + state_string = state.translated('state') + state_cashbook = fields.Function(fields.Selection(string='State of Cashbook', + readonly=True, states={'invisible': True}, selection=sel_state_book), + 'on_change_with_state_cashbook') + + @classmethod + def __setup__(cls): + super(Reconciliation, cls).__setup__() + cls._order.insert(0, ('date_from', 'ASC')) + cls._transitions |= set(( + ('edit', 'check'), + ('check', 'done'), + ('check', 'edit'), + )) + cls._buttons.update({ + 'wfedit': { + 'invisible': Eval('state', '') != 'check', + 'depends': ['state'], + }, + 'wfcheck': { + 'invisible': Eval('state') != 'edit', + 'depends': ['state'], + }, + 'wfdone': { + 'invisible': Eval('state') != 'check', + 'depends': ['state'], + }, + }) + + @classmethod + @ModelView.button + @Workflow.transition('edit') + def wfedit(cls, lines): + """ edit + """ + pass + + @classmethod + @ModelView.button + @Workflow.transition('check') + def wfcheck(cls, lines): + """ is checked + """ + pass + + @classmethod + @ModelView.button + @Workflow.transition('done') + def wfdone(cls, lines): + """ is done + """ + pass + + def get_rec_name(self, name): + """ short + name + """ + return '%(from)s - %(to)s: %(amount)s %(symbol)s' % { + 'from': Report.format_date(self.date_from, None) if self.date_from is not None else '-', + 'to': Report.format_date(self.date_to, None) if self.date_to is not None else '-', + 'amount': Decimal('0.0'), + 'symbol': getattr(getattr(self.cashbook, 'currency', None), 'symbol', '-'), + } + + @classmethod + def default_state(cls): + return 'edit' + + @classmethod + def default_date(cls): + """ today + """ + IrDate = Pool().get('ir.date') + return IrDate.today() + + @fields.depends('cashbook', '_parent_cashbook.state') + def on_change_with_state_cashbook(self, name=None): + """ get state of cashbook + """ + if self.cashbook: + return self.cashbook.state + +# end Type diff --git a/reconciliation.xml b/reconciliation.xml new file mode 100644 index 0000000..2ee17fb --- /dev/null +++ b/reconciliation.xml @@ -0,0 +1,196 @@ + + + + + + + + cashbook.recon + tree + + recon_list + + + cashbook.recon + form + + recon_form + + + + + Cashbook Reconciliation + cashbook.recon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Administrators: Reconciliation read/write + + + + + + + + + + + + + + + + + + + + Owners and reviewers: Reconciliation write + + + + + + + + + + + + + + + + + + + + Observer: Reconciliation read + + + + + + + + + + + + + + + + + + User in companies + + + + + + + + + + + wfedit + Edit + + + + + + + + + + + + + + wfcheck + Check + + + + + + + + + + + + + + wfdone + Done + + + + + + + + + + + + + diff --git a/tryton.cfg b/tryton.cfg index 065201a..849f0af 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -10,6 +10,7 @@ xml: message.xml types.xml category.xml + reconciliation.xml configuration.xml book.xml line.xml diff --git a/view/book_form.xml b/view/book_form.xml index 863bade..eaf242c 100644 --- a/view/book_form.xml +++ b/view/book_form.xml @@ -2,9 +2,9 @@ -
+