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. -->
-
-
-
-
-
+
diff --git a/view/recon_form.xml b/view/recon_form.xml
new file mode 100644
index 0000000..4aadfe5
--- /dev/null
+++ b/view/recon_form.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+