diff --git a/__init__.py b/__init__.py index d7417b1..9f96b97 100644 --- a/__init__.py +++ b/__init__.py @@ -7,10 +7,12 @@ from trytond.pool import Pool from .types import Type from .book import Book from .line import Line +from .reconciliation import Reconciliation def register(): Pool.register( Type, Book, Line, + Reconciliation, module='cashbook_investment', type_='model') diff --git a/line.py b/line.py index b724fd2..493acfa 100644 --- a/line.py +++ b/line.py @@ -7,6 +7,8 @@ from decimal import Decimal from trytond.model import fields from trytond.pool import PoolMeta from trytond.pyson import Eval, Or, If +from trytond.exceptions import UserError +from trytond.i18n import gettext from trytond.modules.cashbook.line import STATES, DEPENDS STATESQ = { @@ -34,11 +36,17 @@ class Line(metaclass=PoolMeta): digits=(16, Eval('quantity_digits', 4)), states=STATESQ, depends=DEPENDSQ) quantity_credit = fields.Numeric(string='Quantity Credit', - digits=(16, Eval('quantity_digits', 4)), - states=STATESQ, depends=DEPENDSQ) + digits=(16, Eval('quantity_digits', 4)), readonly=True, + states={ + 'invisible': STATESQ['invisible'], + 'required': STATESQ['required'], + }, depends=DEPENDSQ) quantity_debit = fields.Numeric(string='Quantity Debit', - digits=(16, Eval('quantity_digits', 4)), - states=STATESQ, depends=DEPENDSQ) + digits=(16, Eval('quantity_digits', 4)), readonly=True, + states={ + 'invisible': STATESQ['invisible'], + 'required': STATESQ['required'], + }, depends=DEPENDSQ) quantity_digits = fields.Function(fields.Integer(string='Digits', readonly=True, states={'invisible': True}), @@ -55,6 +63,11 @@ class Line(metaclass=PoolMeta): 'invisible': Eval('feature', '') != 'asset', }, depends=['currency_digits', 'quantity_digits', 'feature']), 'on_change_with_asset_rate') + quantity_balance = fields.Function(fields.Numeric(string='Quantity', + digits=(16, Eval('quantity_digits', 4)), + help='Number of shares in the cashbook up to the current row if the default sort applies.', + readonly=True, depends=['quantity_digits']), + 'on_change_with_quantity_balance') @classmethod def get_debit_credit(cls, values): @@ -123,4 +136,53 @@ class Line(metaclass=PoolMeta): return self.cashbook.quantity_digits return 4 + @classmethod + def validate(cls, lines): + """ deny pos/neg mismatch + """ + super(Line, cls).validate(lines) + + for line in lines: + # ignore non-asset-lines + if line.cashbook.feature != 'asset': + continue + + # quantity must be set + if (line.quantity is None) or \ + (line.quantity_credit is None) or \ + (line.quantity_debit is None): + raise UserError(gettext( + 'cashbook_investment.msg_line_quantity_not_set', + linetxt = line.rec_name, + )) + + # quantity and amount must with same sign + (amount_sign, a_dig, a_exp) = line.amount.as_tuple() + (quantity_sign, q_dig, q_exp) = line.quantity.as_tuple() + if amount_sign != quantity_sign: + raise UserError(gettext( + 'cashbook_investment.msg_line_sign_mismatch', + linetxt = line.rec_name, + )) + + @classmethod + def write(cls, *args): + """ add or update quanity_debit/credit + """ + actions = iter(args) + to_write = [] + for lines, values in zip(actions, actions): + # update debit / credit + if len(set(values.keys()).intersection(set({'quantity', 'bookingtype'}))) > 0: + for line in lines: + values2 = {} + values2.update(values) + values2.update(cls.get_debit_credit({ + x:values.get(x, getattr(line, x)) for x in ['quantity', 'bookingtype'] + })) + to_write.extend([lines, values2]) + else : + to_write.extend([lines, values]) + super(Line, cls).write(*to_write) + # end LineContext diff --git a/locale/de.po b/locale/de.po index 4657712..4c96b2f 100644 --- a/locale/de.po +++ b/locale/de.po @@ -10,6 +10,14 @@ msgctxt "model:ir.message,text:msg_btype_asset" msgid "Asset" msgstr "Vermögenswert" +msgctxt "model:ir.message,text:msg_line_quantity_not_set" +msgid "Quantity must be set for line '%(linetxt)s'." +msgstr "Menge für die Zeile '%(linetxt)s' muß gesetzt werden." + +msgctxt "model:ir.message,text:msg_line_sign_mismatch" +msgid "Quantity and Amount must with same sign for line %(linetxt)s." +msgstr "Menge und Betrag müssen für Zeile %(linetxt)s mit demselben Vorzeichen versehen werden." + ################# # cashbook.book # @@ -124,11 +132,11 @@ msgstr "Anzahl" msgctxt "field:cashbook.line,quantity_credit:" msgid "Quantity Credit" -msgstr "Anzahlgutschrift" +msgstr "Anzahl Haben" msgctxt "field:cashbook.line,quantity_debit:" msgid "Quantity Debit" -msgstr "Anzahllastschrift" +msgstr "Anzahl Soll" msgctxt "field:cashbook.line,quantity_symbol:" msgid "Symbol" @@ -137,3 +145,31 @@ msgstr "Symbol" msgctxt "field:cashbook.line,asset_rate:" msgid "Rate" msgstr "Kurs" + +msgctxt "field:cashbook.line,quantity_balance:" +msgid "Quantity" +msgstr "Anzahl" + +msgctxt "help:cashbook.line,quantity_balance:" +msgid "Number of shares in the cashbook up to the current row if the default sort applies." +msgstr "Anzahl Anteile im Kassenbuch bis zur aktuellen Zeile, wenn die Standardsortierung zutrifft." + + +################## +# cashbook.recon # +################## +msgctxt "field:cashbook.recon,start_quantity:" +msgid "Start Quantity" +msgstr "Anfangsmenge" + +msgctxt "field:cashbook.recon,end_quantity:" +msgid "End Quantity" +msgstr "Endmenge" + +msgctxt "field:cashbook.recon,quantity_digits:" +msgid "Quantity Digits" +msgstr "Anzahl-Dezimalstellen" + +msgctxt "field:cashbook.recon,quantity_uom:" +msgid "Symbol" +msgstr "Symbol" diff --git a/locale/en.po b/locale/en.po index 04c095d..b1f4b77 100644 --- a/locale/en.po +++ b/locale/en.po @@ -1,124 +1,156 @@ -# -msgid "" -msgstr "Content-Type: text/plain; charset=utf-8\n" - -msgctxt "model:ir.message,text:msg_btype_asset" -msgid "Asset" -msgstr "Asset" - -msgctxt "view:cashbook.book:" -msgid "Asset" -msgstr "Asset" - -msgctxt "view:cashbook.book:" -msgid "Quantity" -msgstr "Quantity" - -msgctxt "view:cashbook.book:" -msgid "Current valuation of the investment" -msgstr "Current valuation of the investment" - -msgctxt "field:cashbook.book,asset:" -msgid "Asset" -msgstr "Asset" - -msgctxt "field:cashbook.book,quantity_digits:" -msgid "Digits" -msgstr "Digits" - -msgctxt "help:cashbook.book,quantity_digits:" -msgid "Quantity Digits" -msgstr "Quantity Digits" - -msgctxt "help:cashbook.book,asset_uomcat:" -msgid "UOM Category" -msgstr "UOM Category" - -msgctxt "field:cashbook.book,quantity_uom:" -msgid "UOM" -msgstr "UOM" - -msgctxt "field:cashbook.book,symbol:" -msgid "Symbol" -msgstr "Symbol" - -msgctxt "field:cashbook.book,asset_symbol:" -msgid "Symbol" -msgstr "Symbol" - -msgctxt "field:cashbook.book,quantity:" -msgid "Quantity" -msgstr "Quantity" - -msgctxt "help:cashbook.book,quantity:" -msgid "Quantity of assets until to date" -msgstr "Quantity of assets until to date" - -msgctxt "field:cashbook.book,quantity_all:" -msgid "Total Quantity" -msgstr "Total Quantity" - -msgctxt "help:cashbook.book,quantity_all:" -msgid "Total quantity of all assets" -msgstr "Total quantity of all assets" - -msgctxt "field:cashbook.book,current_value:" -msgid "Value" -msgstr "Value" - -msgctxt "help:cashbook.book,current_value:" -msgid "Valuation of the investment based on the current stock market price." -msgstr "Valuation of the investment based on the current stock market price." - -msgctxt "field:cashbook.book,current_value_ref:" -msgid "Value (Ref.)" -msgstr "Value (Ref.)" - -msgctxt "help:cashbook.book,current_value_ref:" -msgid "Valuation of the investment based on the current stock exchange price, converted into the company currency." -msgstr "Valuation of the investment based on the current stock exchange price, converted into the company currency." - -msgctxt "field:cashbook.book,diff_amount:" -msgid "Difference" -msgstr "Difference" - -msgctxt "help:cashbook.book,diff_amount:" -msgid "Difference between acquisition value and current value" -msgstr "Difference between acquisition value and current value" - -msgctxt "field:cashbook.book,diff_percent:" -msgid "Percent" -msgstr "Percent" - -msgctxt "help:cashbook.book,diff_percent:" -msgid "percentage performance since acquisition" -msgstr "percentage performance since acquisition" - -msgctxt "field:cashbook.book,current_rate:" -msgid "Rate" -msgstr "Rate" - -msgctxt "help:cashbook.book,current_rate:" -msgid "Rate per unit of investment based on current stock exchange price." -msgstr "Rate per unit of investment based on current stock exchange price." - -msgctxt "field:cashbook.line,quantity_digits:" -msgid "Digits" -msgstr "Digits" - -msgctxt "field:cashbook.line,quantity:" -msgid "Quantity" -msgstr "Quantity" - -msgctxt "field:cashbook.line,quantity_credit:" -msgid "Quantity Credit" -msgstr "Quantity Credit" - -msgctxt "field:cashbook.line,quantity_debit:" -msgid "Quantity Debit" -msgstr "Quantity Debit" - -msgctxt "field:cashbook.line,quantity_symbol:" -msgid "Symbol" -msgstr "Symbol" - +# +msgid "" +msgstr "Content-Type: text/plain; charset=utf-8\n" + +msgctxt "model:ir.message,text:msg_btype_asset" +msgid "Asset" +msgstr "Asset" + +msgctxt "model:ir.message,text:msg_line_quantity_not_set" +msgid "Quantity must be set for line '%(linetxt)s'." +msgstr "Quantity must be set for line '%(linetxt)s'." + +msgctxt "model:ir.message,text:msg_line_sign_mismatch" +msgid "Quantity and Amount must with same sign for line %(linetxt)s." +msgstr "Quantity and Amount must with same sign for line %(linetxt)s." + +msgctxt "view:cashbook.book:" +msgid "Asset" +msgstr "Asset" + +msgctxt "view:cashbook.book:" +msgid "Quantity" +msgstr "Quantity" + +msgctxt "view:cashbook.book:" +msgid "Current valuation of the investment" +msgstr "Current valuation of the investment" + +msgctxt "field:cashbook.book,asset:" +msgid "Asset" +msgstr "Asset" + +msgctxt "field:cashbook.book,quantity_digits:" +msgid "Digits" +msgstr "Digits" + +msgctxt "help:cashbook.book,quantity_digits:" +msgid "Quantity Digits" +msgstr "Quantity Digits" + +msgctxt "help:cashbook.book,asset_uomcat:" +msgid "UOM Category" +msgstr "UOM Category" + +msgctxt "field:cashbook.book,quantity_uom:" +msgid "UOM" +msgstr "UOM" + +msgctxt "field:cashbook.book,symbol:" +msgid "Symbol" +msgstr "Symbol" + +msgctxt "field:cashbook.book,asset_symbol:" +msgid "Symbol" +msgstr "Symbol" + +msgctxt "field:cashbook.book,quantity:" +msgid "Quantity" +msgstr "Quantity" + +msgctxt "help:cashbook.book,quantity:" +msgid "Quantity of assets until to date" +msgstr "Quantity of assets until to date" + +msgctxt "field:cashbook.book,quantity_all:" +msgid "Total Quantity" +msgstr "Total Quantity" + +msgctxt "help:cashbook.book,quantity_all:" +msgid "Total quantity of all assets" +msgstr "Total quantity of all assets" + +msgctxt "field:cashbook.book,current_value:" +msgid "Value" +msgstr "Value" + +msgctxt "help:cashbook.book,current_value:" +msgid "Valuation of the investment based on the current stock market price." +msgstr "Valuation of the investment based on the current stock market price." + +msgctxt "field:cashbook.book,current_value_ref:" +msgid "Value (Ref.)" +msgstr "Value (Ref.)" + +msgctxt "help:cashbook.book,current_value_ref:" +msgid "Valuation of the investment based on the current stock exchange price, converted into the company currency." +msgstr "Valuation of the investment based on the current stock exchange price, converted into the company currency." + +msgctxt "field:cashbook.book,diff_amount:" +msgid "Difference" +msgstr "Difference" + +msgctxt "help:cashbook.book,diff_amount:" +msgid "Difference between acquisition value and current value" +msgstr "Difference between acquisition value and current value" + +msgctxt "field:cashbook.book,diff_percent:" +msgid "Percent" +msgstr "Percent" + +msgctxt "help:cashbook.book,diff_percent:" +msgid "percentage performance since acquisition" +msgstr "percentage performance since acquisition" + +msgctxt "field:cashbook.book,current_rate:" +msgid "Rate" +msgstr "Rate" + +msgctxt "help:cashbook.book,current_rate:" +msgid "Rate per unit of investment based on current stock exchange price." +msgstr "Rate per unit of investment based on current stock exchange price." + +msgctxt "field:cashbook.line,quantity_digits:" +msgid "Digits" +msgstr "Digits" + +msgctxt "field:cashbook.line,quantity:" +msgid "Quantity" +msgstr "Quantity" + +msgctxt "field:cashbook.line,quantity_credit:" +msgid "Quantity Credit" +msgstr "Quantity Credit" + +msgctxt "field:cashbook.line,quantity_debit:" +msgid "Quantity Debit" +msgstr "Quantity Debit" + +msgctxt "field:cashbook.line,quantity_symbol:" +msgid "Symbol" +msgstr "Symbol" + +msgctxt "field:cashbook.line,asset_rate:" +msgid "Rate" +msgstr "Rate" + +msgctxt "field:cashbook.line,quantity_balance:" +msgid "Quantity" +msgstr "Quantity" + +msgctxt "help:cashbook.line,quantity_balance:" +msgid "Number of shares in the cashbook up to the current row if the default sort applies." +msgstr "Number of shares in the cashbook up to the current row if the default sort applies." + +msgctxt "field:cashbook.recon,start_quantity:" +msgid "Start Quantity" +msgstr "Start Quantity" + +msgctxt "field:cashbook.recon,end_quantity:" +msgid "End Quantity" +msgstr "End Quantity" + +msgctxt "field:cashbook.recon,quantity_digits:" +msgid "Quantity Digits" +msgstr "Quantity Digits" + diff --git a/message.xml b/message.xml index 96ddc9f..8dea6b1 100644 --- a/message.xml +++ b/message.xml @@ -8,6 +8,12 @@ full copyright notices and license terms. --> Asset + + Quantity must be set for line '%(linetxt)s'. + + + Quantity and Amount must with same sign for line %(linetxt)s. + diff --git a/reconciliation.py b/reconciliation.py new file mode 100644 index 0000000..fd4aefc --- /dev/null +++ b/reconciliation.py @@ -0,0 +1,100 @@ +# -*- 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.pool import PoolMeta +from trytond.model import fields +from trytond.pyson import Eval +from decimal import Decimal + + +class Reconciliation(metaclass=PoolMeta): + __name__ = 'cashbook.recon' + + start_quantity = fields.Numeric(string='Start Quantity', + readonly=True, digits=(16, Eval('quantity_digits', 4)), + states={ + 'required': Eval('feature', '') == 'asset', + 'invisible': Eval('feature', '') != 'asset', + }, depends=['quantity_digits', 'feature']) + end_quantity = fields.Numeric(string='End Quantity', + readonly=True, digits=(16, Eval('quantity_digits', 4)), + states={ + 'required': Eval('feature', '') == 'asset', + 'invisible': Eval('feature', '') != 'asset', + }, depends=['quantity_digits', 'feature']) + quantity_digits = fields.Function(fields.Integer(string='Quantity Digits'), + 'on_change_with_quantity_digits') + quantity_uom = fields.Function(fields.Many2One(string='Symbol', + readonly=True, model_name='product.uom'), + 'on_change_with_quantity_uom') + + @fields.depends('cashbook', '_parent_cashbook.quantity_uom') + def on_change_with_quantity_uom(self, name=None): + """ get quantity-unit of asset + """ + if self.cashbook: + if self.cashbook.quantity_uom: + return self.cashbook.quantity_uom.id + + @fields.depends('cashbook', '_parent_cashbook.quantity_digits') + def on_change_with_quantity_digits(self, name=None): + """ quantity_digits of cashbook + """ + if self.cashbook: + return self.cashbook.currency.digits + else: + return 4 + + @classmethod + def default_start_quantity(cls): + return Decimal('0.0') + + @classmethod + def default_end_quantity(cls): + return Decimal('0.0') + + @classmethod + def get_values_wfedit(cls, reconciliation): + """ get values for 'to_write' in wf-edit + """ + values = super(Reconciliation, cls).get_values_wfedit(reconciliation) + values.update({ + 'start_quantity': Decimal('0.0'), + 'end_quantity': Decimal('0.0'), + }) + return values + + @classmethod + def get_values_wfcheck(cls, reconciliation): + """ get values for 'to_write' in wf-check + """ + values = super(Reconciliation, cls).get_values_wfcheck(reconciliation) + + if reconciliation.predecessor: + values['start_quantity'] = reconciliation.predecessor.end_quantity + else : + values['start_quantity'] = Decimal('0.0') + values['end_quantity'] = values['start_quantity'] + + # add quantities of new lines + if 'lines' in values.keys(): + if len(values['lines']) != 1: + raise ValueError('invalid number of values') + + values['end_quantity'] += sum([ + x.quantity_credit - x.quantity_debit + for x in values['lines'][0][1] + ]) + + # add quantities of already linked lines + values['end_quantity'] += sum([ + x.quantity_credit - x.quantity_debit + for x in reconciliation.lines + ]) + + return values + +# end Reconciliation diff --git a/reconciliation.xml b/reconciliation.xml new file mode 100644 index 0000000..ad8a238 --- /dev/null +++ b/reconciliation.xml @@ -0,0 +1,15 @@ + + + + + + + cashbook.recon + + recon_form + + + + diff --git a/tests/test_book.py b/tests/test_book.py index ad568d0..80377ad 100644 --- a/tests/test_book.py +++ b/tests/test_book.py @@ -531,10 +531,22 @@ class CbInvTestCase(CashbookTestCase, InvestmentTestCase): self.assertEqual(book.rec_name, 'Book 1 | -1.00 usd | Open') self.assertEqual(len(book.lines), 1) self.assertEqual(book.lines[0].quantity, Decimal('1.5')) + self.assertEqual(book.lines[0].quantity_credit, Decimal('0.0')) + self.assertEqual(book.lines[0].quantity_debit, Decimal('1.5')) self.assertEqual(len(book2.lines), 0) self.assertEqual(book.lines[0].rec_name, '05/01/2022|to|-1.00 usd|Transfer Out [Asset-Book | 0.00 usd | Open]') self.assertEqual(len(book.lines[0].references), 0) + # update quantity + Book.write(*[ + [book], + { + 'lines': [('write', [book.lines[0]], {'quantity': Decimal('2.5')})], + }]) + self.assertEqual(book.lines[0].quantity, Decimal('2.5')) + self.assertEqual(book.lines[0].quantity_credit, Decimal('0.0')) + self.assertEqual(book.lines[0].quantity_debit, Decimal('2.5')) + # check counterpart self.assertEqual(book.lines[0].booktransf.rec_name, 'Asset-Book | 0.00 usd | Open') self.assertEqual(book.lines[0].booktransf.btype.feature, 'asset') @@ -547,9 +559,9 @@ class CbInvTestCase(CashbookTestCase, InvestmentTestCase): self.assertEqual(book.lines[0].rec_name, '05/01/2022|to|-1.00 usd|Transfer Out [Asset-Book | 1.00 usd | Open]') self.assertEqual(book.lines[0].state, 'check') self.assertEqual(book.lines[0].bookingtype, 'mvout') - self.assertEqual(book.lines[0].quantity, Decimal('1.5')) + self.assertEqual(book.lines[0].quantity, Decimal('2.5')) self.assertEqual(book.lines[0].quantity_credit, Decimal('0.0')) - self.assertEqual(book.lines[0].quantity_debit, Decimal('1.5')) + self.assertEqual(book.lines[0].quantity_debit, Decimal('2.5')) self.assertEqual(len(book.lines[0].references), 1) self.assertEqual(book.lines[0].reference, None) self.assertEqual(book.lines[0].references[0].id, book2.lines[0].id) @@ -557,12 +569,78 @@ class CbInvTestCase(CashbookTestCase, InvestmentTestCase): self.assertEqual(len(book2.lines), 1) self.assertEqual(book2.lines[0].rec_name, '05/01/2022|from|1.00 usd|Transfer Out [Book 1 | -1.00 usd | Open]') self.assertEqual(book2.lines[0].state, 'check') - self.assertEqual(book2.lines[0].quantity, Decimal('1.5')) - self.assertEqual(book2.lines[0].quantity_credit, Decimal('1.5')) + self.assertEqual(book2.lines[0].quantity, Decimal('2.5')) + self.assertEqual(book2.lines[0].quantity_credit, Decimal('2.5')) self.assertEqual(book2.lines[0].quantity_debit, Decimal('0.0')) self.assertEqual(book2.lines[0].bookingtype, 'mvin') - self.assertEqual(book2.lines[0].asset_rate, Decimal('0.6667')) + self.assertEqual(book2.lines[0].asset_rate, Decimal('0.4')) self.assertEqual(book2.lines[0].reference.rec_name, '05/01/2022|to|-1.00 usd|Transfer Out [Asset-Book | 1.00 usd | Open]') self.assertEqual(len(book2.lines[0].references), 0) + @with_transaction() + def test_assetbook_check_sign_mismatch(self): + """ create cashbook + line, bookingtype 'in', + check detection of sign mismatch between quantity and amount + """ + pool = Pool() + Book = pool.get('cashbook.book') + Line = pool.get('cashbook.line') + Category = pool.get('cashbook.category') + BType = pool.get('cashbook.type') + + type_depot = self.prep_type('Depot', 'D') + BType.write(*[ + [type_depot], + { + 'feature': 'asset', + }]) + + category_in = self.prep_category(cattype='in') + company = self.prep_company() + party = self.prep_party() + + asset = self.prep_asset_item( + company=company, + product = self.prep_asset_product(name='Product 1')) + self.assertEqual(asset.symbol, 'usd/u') + + book, = Book.create([{ + 'name': 'Asset-Book', + 'btype': type_depot.id, + 'asset': asset.id, + 'quantity_uom': asset.uom.id, + 'company': company.id, + 'currency': company.currency.id, + 'number_sequ': self.prep_sequence().id, + 'start_date': date(2022, 5, 1), + 'lines': [('create', [{ + 'date': date(2022, 5, 1), + 'description': 'buy some', + 'category': category_in.id, + 'bookingtype': 'in', + 'amount': Decimal('1.0'), + 'quantity': Decimal('1.5'), + }])], + }]) + + self.assertEqual(book.rec_name, 'Asset-Book | 1.00 usd | Open') + self.assertEqual(len(book.lines), 1) + self.assertEqual(book.lines[0].amount, Decimal('1.0')) + self.assertEqual(book.lines[0].credit, Decimal('1.0')) + self.assertEqual(book.lines[0].debit, Decimal('0.0')) + self.assertEqual(book.lines[0].quantity, Decimal('1.5')) + self.assertEqual(book.lines[0].quantity_credit, Decimal('1.5')) + self.assertEqual(book.lines[0].quantity_debit, Decimal('0.0')) + + self.assertRaisesRegex(UserError, + "Quantity and Amount must with same sign for line 05/01/2022|Rev|1.00 usd|buy some [Cat1].", + Book.write, + *[ + [book], + { + 'lines': [('write', [book.lines[0]], { + 'quantity': Decimal('-1.5'), + })], + }]) + # end CbInvTestCase diff --git a/tryton.cfg b/tryton.cfg index 4ba0023..7e0dd85 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -7,3 +7,4 @@ xml: message.xml book.xml line.xml + reconciliation.xml diff --git a/view/line_form.xml b/view/line_form.xml index 03d0559..51855ad 100644 --- a/view/line_form.xml +++ b/view/line_form.xml @@ -9,11 +9,7 @@ full copyright notices and license terms. -->