spitbuchung begonnen

This commit is contained in:
Frederik Jaeckel 2022-08-24 17:12:32 +02:00
parent 9e64c49dc0
commit bdbc9dc27f
10 changed files with 382 additions and 7 deletions

View file

@ -7,6 +7,7 @@ from trytond.pool import Pool
from .book import Book from .book import Book
from .types import Type from .types import Type
from .line import Line, LineContext from .line import Line, LineContext
from .splitline import SplitLine
from .wizard_openline import OpenCashBook, OpenCashBookStart from .wizard_openline import OpenCashBook, OpenCashBookStart
from .wizard_runreport import RunCbReport, RunCbReportStart from .wizard_runreport import RunCbReport, RunCbReportStart
from .configuration import Configuration, UserConfiguration from .configuration import Configuration, UserConfiguration
@ -23,6 +24,7 @@ def register():
Book, Book,
LineContext, LineContext,
Line, Line,
SplitLine,
Reconciliation, Reconciliation,
OpenCashBookStart, OpenCashBookStart,
RunCbReportStart, RunCbReportStart,

23
line.py
View file

@ -31,6 +31,8 @@ sel_linetype = [
sel_bookingtype = [ sel_bookingtype = [
('in', 'Revenue'), ('in', 'Revenue'),
('out', 'Expense'), ('out', 'Expense'),
('spin', 'Revenue Splitbooking'),
('spout', 'Expense Splitbooking'),
('mvin', 'Transfer from'), ('mvin', 'Transfer from'),
('mvout', 'Transfer to'), ('mvout', 'Transfer to'),
] ]
@ -102,7 +104,7 @@ class Line(Workflow, ModelSQL, ModelView):
ondelete='RESTRICT', ondelete='RESTRICT',
states={ states={
'readonly': STATES['readonly'], 'readonly': STATES['readonly'],
'invisible': ~Eval('bookingtype', '').in_(['in', 'out']), 'invisible': ~Eval('bookingtype', '').in_(['in', 'out', 'spin', 'spout']),
}, depends=DEPENDS+['bookingtype']) }, depends=DEPENDS+['bookingtype'])
payee = fields.Function(fields.Reference(string='Payee', readonly=True, payee = fields.Function(fields.Reference(string='Payee', readonly=True,
selection=sel_payee), 'on_change_with_payee', searcher='search_payee') selection=sel_payee), 'on_change_with_payee', searcher='search_payee')
@ -113,11 +115,18 @@ class Line(Workflow, ModelSQL, ModelView):
'invisible': ~Bool(Eval('reference')), 'invisible': ~Bool(Eval('reference')),
}, model_name='cashbook.line', ondelete='CASCADE', }, model_name='cashbook.line', ondelete='CASCADE',
help='The current row was created by and is controlled by the reference row.') help='The current row was created by and is controlled by the reference row.')
references = fields.One2Many(string='References', model_name='cashbook.line', references = fields.One2Many(string='References',
model_name='cashbook.line',
help='The rows are created and managed by the current record.', help='The rows are created and managed by the current record.',
states={ states={
'invisible': ~Bool(Eval('references')), 'invisible': ~Bool(Eval('references')),
}, field='reference', readonly=True) }, field='reference', readonly=True)
splitlines = fields.One2Many(string='Split booking lines',
model_name='cashbook.split',
help='The rows are created and managed by the current record.',
states={
'invisible': ~Bool(Eval('splitlines')),
}, field='line', readonly=True)
reconciliation = fields.Many2One(string='Reconciliation', readonly=True, reconciliation = fields.Many2One(string='Reconciliation', readonly=True,
model_name='cashbook.recon', ondelete='SET NULL', model_name='cashbook.recon', ondelete='SET NULL',
@ -398,7 +407,7 @@ class Line(Workflow, ModelSQL, ModelView):
""" get party or cashbook """ get party or cashbook
""" """
if self.bookingtype: if self.bookingtype:
if self.bookingtype in ['in', 'out']: if self.bookingtype in ['in', 'out', 'spin', 'spout']:
if self.party: if self.party:
return 'party.party,%d' % self.party.id return 'party.party,%d' % self.party.id
elif self.bookingtype in ['mvin', 'mvout']: elif self.bookingtype in ['mvin', 'mvout']:
@ -488,8 +497,8 @@ class Line(Workflow, ModelSQL, ModelView):
""" clear category if not valid type """ clear category if not valid type
""" """
types = { types = {
'in': ['in', 'mvin'], 'in': ['in', 'mvin', 'spin'],
'out': ['out', 'mvout'], 'out': ['out', 'mvout', 'spout'],
} }
if self.bookingtype: if self.bookingtype:
@ -570,12 +579,12 @@ class Line(Workflow, ModelSQL, ModelView):
if type_: if type_:
if amount is not None: if amount is not None:
if type_ in ['in', 'mvin']: if type_ in ['in', 'mvin', 'spin']:
return { return {
'debit': Decimal('0.0'), 'debit': Decimal('0.0'),
'credit': amount, 'credit': amount,
} }
elif type_ in ['out', 'mvout']: elif type_ in ['out', 'mvout', 'spout']:
return { return {
'debit': amount, 'debit': amount,
'credit': Decimal('0.0'), 'credit': Decimal('0.0'),

View file

@ -110,10 +110,18 @@ msgctxt "model:ir.message,text:msg_line_bookingtype_in"
msgid "Rev" msgid "Rev"
msgstr "Einn." msgstr "Einn."
msgctxt "model:ir.message,text:msg_line_bookingtype_spin"
msgid "Rev/Sp"
msgstr "Einn./Spl."
msgctxt "model:ir.message,text:msg_line_bookingtype_out" msgctxt "model:ir.message,text:msg_line_bookingtype_out"
msgid "Exp" msgid "Exp"
msgstr "Ausg." msgstr "Ausg."
msgctxt "model:ir.message,text:msg_line_bookingtype_spout"
msgid "Exp/Sp"
msgstr "Ausg./Spl."
msgctxt "model:ir.message,text:msg_line_bookingtype_mvin" msgctxt "model:ir.message,text:msg_line_bookingtype_mvin"
msgid "from" msgid "from"
msgstr "von" msgstr "von"
@ -166,6 +174,10 @@ msgctxt "model:ir.rule.group,name:rg_book_read_nonowner"
msgid "Observers and Reviewers: Cashbook read" msgid "Observers and Reviewers: Cashbook read"
msgstr "Beobachter und Bearbeiter: Kassenbuch lesen" msgstr "Beobachter und Bearbeiter: Kassenbuch lesen"
msgctxt "model:ir.rule.group,name:rg_split_write_adm"
msgid "Administrators: Splitbooking line read/write"
msgstr "Administratoren: Splitbuchungszeile bearbeiten"
msgctxt "model:ir.rule.group,name:rg_book_write_adm" msgctxt "model:ir.rule.group,name:rg_book_write_adm"
msgid "Administrators: Cashbook read/write" msgid "Administrators: Cashbook read/write"
msgstr "Administratoren: Kassenbuch bearbeiten" msgstr "Administratoren: Kassenbuch bearbeiten"
@ -174,10 +186,18 @@ msgctxt "model:ir.rule.group,name:rg_line_write_adm"
msgid "Administrators: Cashbook line read/write" msgid "Administrators: Cashbook line read/write"
msgstr "Administratoren: Kassenbuchzeile bearbeiten" msgstr "Administratoren: Kassenbuchzeile bearbeiten"
msgctxt "model:ir.rule.group,name:rg_split_write"
msgid "Owners and reviewers: Splitbooking line write"
msgstr "Eigentümer und Bearbeiter: Splitbuchungszeile bearbeiten"
msgctxt "model:ir.rule.group,name:rg_line_write" msgctxt "model:ir.rule.group,name:rg_line_write"
msgid "Owners and reviewers: Cashbook line write" msgid "Owners and reviewers: Cashbook line write"
msgstr "Eigentümer und Bearbeiter: Kassenbuchzeile bearbeiten" msgstr "Eigentümer und Bearbeiter: Kassenbuchzeile bearbeiten"
msgctxt "model:ir.rule.group,name:rg_split_read"
msgid "Observer: Splitbooking line read"
msgstr "Beobachter: Splitbuchungszeile lesen"
msgctxt "model:ir.rule.group,name:rg_line_read" msgctxt "model:ir.rule.group,name:rg_line_read"
msgid "Observer: Cashbook line read" msgid "Observer: Cashbook line read"
msgstr "Beobachter: Kassenbuchzeile lesen" msgstr "Beobachter: Kassenbuchzeile lesen"
@ -186,6 +206,10 @@ msgctxt "model:ir.rule.group,name:rg_line_read"
msgid "User in companies" msgid "User in companies"
msgstr "Benutzer im Unternehmen" msgstr "Benutzer im Unternehmen"
msgctxt "model:ir.rule.group,name:rg_split_companies"
msgid "User in companies"
msgstr "Benutzer im Unternehmen"
msgctxt "model:ir.rule.group,name:rg_type_companies" msgctxt "model:ir.rule.group,name:rg_type_companies"
msgid "User in companies" msgid "User in companies"
msgstr "Benutzer im Unternehmen" msgstr "Benutzer im Unternehmen"
@ -451,6 +475,86 @@ msgid "The numbering of the lines is done in the step Check. If the check mark i
msgstr "Die Nummerierung der Zeilen wird beim Schritt 'Prüfen' erledigt. Bei inaktivem Häkchen passiert dies erst bei 'Fertig'." msgstr "Die Nummerierung der Zeilen wird beim Schritt 'Prüfen' erledigt. Bei inaktivem Häkchen passiert dies erst bei 'Fertig'."
##################
# cashbook.split #
##################
msgctxt "model:cashbook.split,name:"
msgid "Split booking line"
msgstr "Splitbuchungszeile"
msgctxt "field:cashbook.split,line:"
msgid "Line"
msgstr "Zeile"
msgctxt "field:cashbook.split,description:"
msgid "Description"
msgstr "Beschreibung"
msgctxt "field:cashbook.split,category:"
msgid "Category"
msgstr "Kategorie"
msgctxt "field:cashbook.split,amount:"
msgid "Amount"
msgstr "Betrag"
msgctxt "field:cashbook.split,currency:"
msgid "Currency"
msgstr "Währung"
msgctxt "field:cashbook.split,currency_digits:"
msgid "Currency Digits"
msgstr "Nachkommastellen Währung"
msgctxt "field:cashbook.split,bookingtype:"
msgid "Type"
msgstr "Typ"
msgctxt "selection:cashbook.split,bookingtype:"
msgid "Revenue"
msgstr "Einnahme"
msgctxt "selection:cashbook.split,bookingtype:"
msgid "Revenue Splitbooking"
msgstr "Einnahme Splitbuchung"
msgctxt "selection:cashbook.split,bookingtype:"
msgid "Expense"
msgstr "Ausgabe"
msgctxt "selection:cashbook.split,bookingtype:"
msgid "Expense Splitbooking"
msgstr "Ausgabe Splitbuchung"
msgctxt "selection:cashbook.split,bookingtype:"
msgid "Transfer from"
msgstr "Umbuchung von"
msgctxt "selection:cashbook.split,bookingtype:"
msgid "Transfer to"
msgstr "Umbuchung nach"
msgctxt "field:cashbook.split,state:"
msgid "State"
msgstr "Status"
msgctxt "selection:cashbook.split,state:"
msgid "Edit"
msgstr "Bearbeiten"
msgctxt "selection:cashbook.split,state:"
msgid "Checked"
msgstr "Geprüft"
msgctxt "selection:cashbook.split,state:"
msgid "Done"
msgstr "Fertig"
msgctxt "field:cashbook.split,state_cashbook:"
msgid "State of Cashbook"
msgstr "Kassenbuchstatus"
################# #################
# cashbook.line # # cashbook.line #
################# #################
@ -530,10 +634,18 @@ msgctxt "selection:cashbook.line,bookingtype:"
msgid "Revenue" msgid "Revenue"
msgstr "Einnahme" msgstr "Einnahme"
msgctxt "selection:cashbook.line,bookingtype:"
msgid "Revenue Splitbooking"
msgstr "Einnahme Splitbuchung"
msgctxt "selection:cashbook.line,bookingtype:" msgctxt "selection:cashbook.line,bookingtype:"
msgid "Expense" msgid "Expense"
msgstr "Ausgabe" msgstr "Ausgabe"
msgctxt "selection:cashbook.line,bookingtype:"
msgid "Expense Splitbooking"
msgstr "Ausgabe Splitbuchung"
msgctxt "selection:cashbook.line,bookingtype:" msgctxt "selection:cashbook.line,bookingtype:"
msgid "Transfer from" msgid "Transfer from"
msgstr "Umbuchung von" msgstr "Umbuchung von"

View file

@ -80,6 +80,12 @@ full copyright notices and license terms. -->
<record model="ir.message" id="msg_recon_predecessor_not_done"> <record model="ir.message" id="msg_recon_predecessor_not_done">
<field name="text">The predecessor '%(recname_p)s' must be in the 'Done' state before you can check the current reconciliation '%(recname_c)s'.</field> <field name="text">The predecessor '%(recname_p)s' must be in the 'Done' state before you can check the current reconciliation '%(recname_c)s'.</field>
</record> </record>
<record model="ir.message" id="msg_line_bookingtype_spin">
<field name="text">Rev/Sp</field>
</record>
<record model="ir.message" id="msg_line_bookingtype_spout">
<field name="text">Exp/Sp</field>
</record>
<record model="ir.message" id="msg_line_bookingtype_in"> <record model="ir.message" id="msg_line_bookingtype_in">
<field name="text">Rev</field> <field name="text">Rev</field>
</record> </record>

85
splitline.py Normal file
View file

@ -0,0 +1,85 @@
# -*- 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 ModelView, ModelSQL, Workflow, fields, Check
from trytond.pool import Pool
from trytond.pyson import Eval, If
from .line import sel_linetype, sel_bookingtype, STATES, DEPENDS
from .book import sel_state_book
class SplitLine(ModelSQL, ModelView):
'Split booking line'
__name__ = 'cashbook.split'
line = fields.Many2One(string='Line', required=True,
select=True, ondelete='CASCADE', model_name='cashbook.line',
readonly=True)
description = fields.Text(string='Description',
states=STATES, depends=DEPENDS)
category = fields.Many2One(string='Category',
model_name='cashbook.category', ondelete='RESTRICT',
states=STATES, depends=DEPENDS+['bookingtype'],
required=True,
domain=[
If(
Eval('bookingtype', '').in_(['in', 'mvin']),
('cattype', '=', 'in'),
('cattype', '=', 'out'),
)])
amount = fields.Numeric(string='Amount', digits=(16, Eval('currency_digits', 2)),
required=True, states=STATES, depends=DEPENDS+['currency_digits'])
currency = fields.Function(fields.Many2One(model_name='currency.currency',
string="Currency"), 'on_change_with_currency')
currency_digits = fields.Function(fields.Integer(string='Currency Digits'),
'on_change_with_currency_digits')
bookingtype = fields.Function(fields.Selection(string='Type', readonly=True,
selection=sel_bookingtype), 'on_change_with_bookingtype')
state = fields.Function(fields.Selection(string='State', readonly=True,
selection=sel_linetype), 'on_change_with_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', searcher='search_state_cashbook')
@fields.depends('line', '_parent_line.state')
def on_change_with_state(self, name=None):
""" get state
"""
if self.line:
return self.line.state
@fields.depends('line', '_parent_line.cashbook')
def on_change_with_state_cashbook(self, name=None):
""" get state of cashbook
"""
if self.line:
return self.line.cashbook.state
@fields.depends('line', '_parent_line.bookingtype')
def on_change_with_bookingtype(self, name=None):
""" get type
"""
if self.line:
return self.line.bookingtype
@fields.depends('line', '_parent_line.cashbook')
def on_change_with_currency(self, name=None):
""" currency of cashbook
"""
if self.line:
return self.line.cashbook.currency.id
@fields.depends('line', '_parent_line.cashbook')
def on_change_with_currency_digits(self, name=None):
""" currency-digits of cashbook
"""
if self.line:
return self.line.cashbook.currency.digits
else:
return 2
# end SplitLine

129
splitline.xml Normal file
View file

@ -0,0 +1,129 @@
<?xml version="1.0"?>
<!-- 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. -->
<tryton>
<data>
<!-- views -->
<record model="ir.ui.view" id="split_view_list">
<field name="model">cashbook.split</field>
<field name="type">tree</field>
<field name="priority" eval="10"/>
<field name="name">split_list</field>
</record>
<record model="ir.ui.view" id="split_view_form">
<field name="model">cashbook.split</field>
<field name="type">form</field>
<field name="priority" eval="20"/>
<field name="name">split_form</field>
</record>
<!-- permission -->
<!-- anon: deny all -->
<record model="ir.model.access" id="access_split-anon">
<field name="model" search="[('model', '=', 'cashbook.split')]"/>
<field name="perm_read" eval="False"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<!-- group_cashbook_admin: read/write -->
<record model="ir.model.access" id="access_split-group_cashbook_admin">
<field name="model" search="[('model', '=', 'cashbook.split')]"/>
<field name="group" ref="group_cashbook_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<!-- cashbook: read/write -->
<record model="ir.model.access" id="access_split-group_cashbook">
<field name="model" search="[('model', '=', 'cashbook.split')]"/>
<field name="group" ref="group_cashbook"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<!-- permission by rule - admin -->
<record model="ir.rule.group" id="rg_split_write_adm">
<field name="model" search="[('model', '=', 'cashbook.split')]"/>
<field name="name">Administrators: Splitbooking line read/write</field>
<field name="global_p" eval="False"/>
<field name="default_p" eval="False"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.rule" id="rg_split_write_adm-1">
<field name="domain" eval="[]" pyson="1"/>
<field name="rule_group" ref="rg_split_write_adm"/>
</record>
<record model="ir.rule.group-res.group" id="rg_split_write_adm-group_cashbook_admin">
<field name="rule_group" ref="rg_split_write_adm"/>
<field name="group" ref="group_cashbook_admin"/>
</record>
<!-- permission by rule - read/write: owner, reviewer -->
<record model="ir.rule.group" id="rg_split_write">
<field name="model" search="[('model', '=', 'cashbook.split')]"/>
<field name="name">Owners and reviewers: Splitbooking line write</field>
<field name="global_p" eval="False"/>
<field name="default_p" eval="False"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.rule" id="rg_split_write-1">
<field name="domain" eval="['OR',
('line.cashbook.owner.id', '=', Eval('user', {}).get('id', -1)),
('line.cashbook.reviewer.id', 'in', Eval('user', {}).get('groups', [])),
]" pyson="1"/>
<field name="rule_group" ref="rg_split_write"/>
</record>
<record model="ir.rule.group-res.group" id="rg_split_write-group_cashbook">
<field name="rule_group" ref="rg_split_write"/>
<field name="group" ref="group_cashbook"/>
</record>
<!-- permission by rule - read: observer -->
<record model="ir.rule.group" id="rg_split_read">
<field name="model" search="[('model', '=', 'cashbook.split')]"/>
<field name="name">Observer: Splitbooking line read</field>
<field name="global_p" eval="False"/>
<field name="default_p" eval="False"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.rule" id="rg_split_read-1">
<field name="domain" eval="[
('line.cashbook.observer.id', 'in', Eval('user', {}).get('groups', [])),
]" pyson="1"/>
<field name="rule_group" ref="rg_split_read"/>
</record>
<record model="ir.rule.group-res.group" id="rg_split_read-group_cashbook">
<field name="rule_group" ref="rg_split_read"/>
<field name="group" ref="group_cashbook"/>
</record>
<record model="ir.rule.group" id="rg_split_companies">
<field name="name">User in companies</field>
<field name="model"
search="[('model', '=', 'cashbook.split')]"/>
<field name="global_p" eval="True"/>
</record>
<record model="ir.rule" id="r_split_companies">
<field name="domain"
eval="[('line.cashbook.company', 'in', Eval('companies', []))]"
pyson="1"/>
<field name="rule_group" ref="rg_split_companies"/>
</record>
</data>
</tryton>

View file

@ -16,6 +16,7 @@ xml:
configuration.xml configuration.xml
book.xml book.xml
line.xml line.xml
splitline.xml
wizard_openline.xml wizard_openline.xml
wizard_runreport.xml wizard_runreport.xml
menu.xml menu.xml

View file

@ -44,6 +44,8 @@ full copyright notices and license terms. -->
</group> </group>
<newline/> <newline/>
<field name="splitlines" colspan="4" yexpand="1"/>
<newline/>
<field name="references" colspan="4" yexpand="1"/> <field name="references" colspan="4" yexpand="1"/>
<newline/> <newline/>

18
view/split_form.xml Normal file
View file

@ -0,0 +1,18 @@
<?xml version="1.0"?>
<!-- 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. -->
<form col="4">
<label name="line"/>
<field name="line" colspan="3"/>
<label name="amount"/>
<field name="amount" symbol="currency"/>
<label name="category"/>
<field name="category"/>
<group name="description" colspan="4" col="1" string="Description" yexpand="1">
<field name="description" yfill="1"/>
</group>
</form>

11
view/split_list.xml Normal file
View file

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<!-- 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. -->
<tree>
<field name="line" tree_invisible="1"/>
<field name="category_view"/>
<field name="description" expand="1"/>
<field name="amount" sum="Amount"/>
<field name="currency"/>
</tree>