Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions pos_registrierkasse/i18n/de.po
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-02-06 17:58+0000\n"
"PO-Revision-Date: 2026-02-06 17:58+0000\n"
"Last-Translator: \n"
"POT-Creation-Date: 2026-05-22 05:01+0000\n"
"PO-Revision-Date: 2026-05-22 07:03+0200\n"
"Last-Translator: Manuel Faux <mfaux@conf.at>\n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.9\n"

#. module: pos_registrierkasse
#: model_terms:ir.ui.view,arch_db:pos_registrierkasse.view_pos_config_kanban_extension
Expand Down Expand Up @@ -81,6 +83,12 @@ msgstr "AES Schlüssel für Umsatzzähler"
msgid "Activate FinanzOnline-Integration"
msgstr "FinanzOnline-Integration aktivieren"

#. module: pos_registrierkasse
#. odoo-python
#: code:addons/pos_registrierkasse/models/pos_config.py:0
msgid "Automatic Null Receipt booking from RKSV"
msgstr "Automatische Nullbeleg Buchung der Registrierkasse"

#. module: pos_registrierkasse
#: model:ir.model,name:pos_registrierkasse.model_res_config_settings
msgid "Config Settings"
Expand Down Expand Up @@ -188,6 +196,12 @@ msgstr "Logo"
msgid "Make this POS RKSV compliant"
msgstr "Diesen POS RKSV-konform machen"

#. module: pos_registrierkasse
#. odoo-python
#: code:addons/pos_registrierkasse/models/pos_config.py:0
msgid "Monthly Null Receipt Session"
msgstr "Monatliche Nullbeleg Sitzung"

#. module: pos_registrierkasse
#: model_terms:ir.ui.view,arch_db:pos_registrierkasse.res_config_settings_view_form
msgid "Participant ID"
Expand Down Expand Up @@ -271,6 +285,12 @@ msgstr "Signaturzertifikat"
msgid "Signing failed: %s"
msgstr "Signierung fehlgeschlagen: %s"

#. module: pos_registrierkasse
#. odoo-python
#: code:addons/pos_registrierkasse/models/pos_config.py:0
msgid "Starting Receipt Session"
msgstr "Startbeleg Sitzung"

#. module: pos_registrierkasse
#: model_terms:ir.ui.view,arch_db:pos_registrierkasse.res_config_settings_view_form
msgid "Supplier ID"
Expand Down
16 changes: 9 additions & 7 deletions pos_registrierkasse/models/pos_config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
import logging
from odoo import api, models, fields
from odoo import _, api, models, fields
from odoo.exceptions import UserError
from dateutil.relativedelta import relativedelta
from datetime import timedelta
Expand Down Expand Up @@ -77,7 +77,7 @@ def _onchange_monthly_nullbeleg_time(self):

def _create_sequence(self, pos_config):
sequence = self.env['ir.sequence'].create({
'name': f"POS Order Sequence for {pos_config.id}",
'name': f"POS Order Sequence for {pos_config.name}",
'code': f'pos.order.{pos_config.id}',
'implementation': 'no_gap',
'padding': 5,
Expand Down Expand Up @@ -126,7 +126,7 @@ def _init_pos(self, pos_config_rec):
f"A-Trust setup failed for '{pos_config_rec.name}'. Starting receipt not created. Error: {e}")

# Step 2: Create Session & Order
pos_session = self._rksv_create_pos_session(pos_config_rec, "Starting Receipt Session")
pos_session = self._rksv_create_pos_session(pos_config_rec, _("Starting Receipt Session"))
receipt_num = int(pos_config_rec.receipt_sequence_id.next_by_id())
order_date_obj = fields.Datetime.now()
initial_prev_order_sig_hash = hash_signature(pos_config_rec.name) # Special for first receipt
Expand Down Expand Up @@ -247,7 +247,7 @@ def _cron_create_monthly_receipt(self):
pos_session = None
try:
# Step 1: Create Session & Order
pos_session = self._rksv_create_pos_session(self, "Monthly Null Receipt Session")
pos_session = self._rksv_create_pos_session(self, _("Monthly Null Receipt Session"))
receipt_num = int(self.receipt_sequence_id.next_by_id())
order_date_obj = fields.Datetime.now()

Expand Down Expand Up @@ -297,7 +297,7 @@ def _cron_create_monthly_receipt(self):
_logger.error(f"RKSV CRON: Error processing POS Config '{self.name}': {e}", exc_info=True)
finally:
if (pos_session and pos_session.exists()
and pos_session.name == f'Monthly Null Receipt Session - {self.name}'
and pos_session.opening_notes == _("Monthly Null Receipt Session")
and pos_session.state != 'closed'):
pos_session.write({'state': 'closed', 'stop_at': fields.Datetime.now()})
_logger.info(f"RKSV CRON: Closed POS Session (ID: {pos_session.id})")
Expand Down Expand Up @@ -330,7 +330,7 @@ def action_download_daten_erfassungs_protokoll(self):
'target': 'self',
}

def _rksv_create_pos_session(self, pos_config_rec, session_name_prefix):
def _rksv_create_pos_session(self, pos_config_rec, opening_notes):
"""
Checks whether there is already an open POS sessions for the given config.
If yes, it returns this session. If no, it creates a new one.
Expand All @@ -346,11 +346,12 @@ def _rksv_create_pos_session(self, pos_config_rec, session_name_prefix):
return open_sessions[-1]

pos_session = self.env['pos.session'].create({
'name': f'{session_name_prefix} - {pos_config_rec.name}',
'config_id': pos_config_rec.id,
'user_id': self.env.user.id,
'start_at': fields.Datetime.now(),
'opening_notes': opening_notes,
})
pos_session.name = self.env['ir.sequence'].with_context(company_id=pos_config_rec.company_id.id).next_by_code('pos.session')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure why this line would be needed. We can just let the default create methode set the name. I did not test it yet, but I believe this would even introduce gaps in the sequence.

@8191 8191 May 26, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That line is actually the essence of this PR... 😄
Odoo overrides the passed name in the create method.

From Odoo 18.0 upstream:

class PosSession(models.Model):
    _name = 'pos.session'
...
    @api.model_create_multi
    def create(self, vals_list):
        for vals in vals_list:
            config_id = vals.get('config_id') or self.env.context.get('default_config_id')
   
            name_counter = 0
            if not vals.get('rescue'):
                config_name = self.env['pos.config'].browse(config_id).name
                vals['name'] = config_name + '/'
                sessions = self.sudo().search_read([('name', 'ilike', vals['name'])], ['name'], order='name desc', limit=1)
                if len(sessions):
                    name_counter = int(sessions[0]['name'].split('/')[-1]) + 1

                vals['name'] += str(name_counter).zfill(5)

So Odoo overrides the name upon session creation, but this addon relies on the session name to be persisted, as otherwise the session is not found anymore when trying to close it.

Additionally, in Odoo 18.0 the session name is changed again, once the user starts the opening control. Because this is not done by this addon, the created session names from pos_registrierkasse differ from all others, which is simply odd... Therefore the new session name needs to be set directly.

This line was actually copied from the upstream:

    def set_opening_control(self, cashbox_value: int, notes: str):
        if self.state != 'opening_control':
            return

        self._set_opening_control_data(cashbox_value, notes)

        if not self.rescue:
            self.name = self.env['ir.sequence'].with_context(company_id=self.config_id.company_id.id).next_by_code('pos.session')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say the switch to using the opening notes to match the correct session to close is the essence of this PR. Since we no longer rely on the name we can just let odoo handle it.

_logger.info(f"RKSV: Created POS Session '{pos_session.name}' (ID: {pos_session.id})")
return pos_session

Expand All @@ -368,6 +369,7 @@ def _rksv_create_null_order(self, pos_config_rec, pos_session, receipt_num, orde
'certificate_serial_number': pos_config_rec.certificate_serial_number,
'prev_order_signature': prev_signature_hash_for_order_field,
'pos_reference': f"{pos_session.id:05d}-{order_sequence_in_session:03d}-{int(receipt_num):04d}",
'general_note': _("Automatic Null Receipt booking from RKSV"),
'state': 'done'
})
_logger.info(f"RKSV: Created POS Order (ID: {order.id}, Name: {order.name}) with number {receipt_num}.")
Expand Down