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
2 changes: 2 additions & 0 deletions connector_sage/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright NuoBiT Solutions - Eric Antones <eantones@nuobit.com>
# Copyright NuoBiT Solutions - Kilian Niubo <kniubo@nuobit.com>
# Copyright 2026 NuoBiT Solutions SL - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

{
Expand Down Expand Up @@ -27,6 +28,7 @@
"views/hr_employee_views.xml",
"views/res_partner_views.xml",
"views/payroll_sage_labour_agreement_views.xml",
"views/payroll_sage_payslip_process_views.xml",
"views/payroll_sage_payslip_line_views.xml",
"views/payroll_sage_payslip_check_views.xml",
"views/payroll_sage_payslip_views.xml",
Expand Down
15 changes: 15 additions & 0 deletions connector_sage/data/ir_cron.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,19 @@
<field name="state">code</field>
<field name="code">model._scheduler_import_labour_agreements()</field>
</record>

<record id="ir_cron_import_payslip_processes" model="ir.cron" forcecreate="True">
<field name="name">Sage - Import payslip processes</field>
<field name="model_id" ref="model_sage_backend" />
<field name="active" eval="False" />
<!-- Mandatory to define a explicit user on record from the frontend,
DON'T USE admin (base.user_root) -->
<!--field name="user_id" ref="< not base.user_root>"/-->
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False" />
<field name="state">code</field>
<field name="code">model._scheduler_import_payslip_processes()</field>
</record>
</odoo>
13 changes: 13 additions & 0 deletions connector_sage/data/queue_job_function_data.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--Copyright NuoBiT Solutions - Eric Antones <eantones@nuobit.com>
Copyright NuoBiT Solutions - Kilian Niubo <kniubo@nuobit.com>
Copyright 2026 NuoBiT Solutions SL - Deniz Gallo <dgallo@nuobit.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)-->
<odoo noupdate="1">
<record
Expand Down Expand Up @@ -58,6 +59,18 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)-->
<field name="channel_id" ref="connector_sage.channel_sage" />
<field name="retry_pattern" eval="{1: 10, 5: 30, 10: 60, 15: 300}" />
</record>
<record
id="sage_binding_import_payslip_processes_since_job_function"
model="queue.job.function"
>
<field
name="model_id"
ref="connector_sage.model_sage_payroll_sage_payslip_process"
/>
<field name="method">import_payslip_processes_since</field>
<field name="channel_id" ref="connector_sage.channel_sage" />
<field name="retry_pattern" eval="{1: 10, 5: 30, 10: 60, 15: 300}" />
</record>
<record
id="sage_binding_import_payslip_lines_job_function"
model="queue.job.function"
Expand Down
1 change: 1 addition & 0 deletions connector_sage/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from . import hr_employee
from . import payroll_sage_labour_agreement
from . import payroll_sage_labour_agreement_wage_type_line
from . import payroll_sage_payslip_process
from . import payroll_sage_payslip_line
from . import payroll_sage_payslip_line_payroll
from . import payroll_sage_payslip_line_transfer
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from . import importer
from . import adapter
from . import mapper
from . import binder
from . import binding
23 changes: 23 additions & 0 deletions connector_sage/models/payroll_sage_payslip_process/adapter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2026 NuoBiT Solutions SL - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)


from odoo.addons.component.core import Component


class PayrollSagePayslipProcessAdapter(Component):
_name = "sage.payroll.sage.payslip.process.adapter"
_inherit = "sage.adapter"
_apply_on = "sage.payroll.sage.payslip.process"

_sql = """
select n.CodigoEmpresa,
n.TipoProceso
from %(schema)s.Historico n
where n.TipoProceso is not null
and n.TipoProceso != ''
group by n.CodigoEmpresa,
n.TipoProceso
"""

_id = ("CodigoEmpresa", "TipoProceso")
25 changes: 25 additions & 0 deletions connector_sage/models/payroll_sage_payslip_process/binder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2026 NuoBiT Solutions SL - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo.addons.component.core import Component


class PayrollSagePayslipProcessBinder(Component):
"""Bind records and give odoo/sage ids correspondence

Binding models are models called ``sage.{normal_model}``,
like ``sage.res.partner`` or ``sage.product.product``.
They are ``_inherits`` of the normal models and contains
the Sage ID, the ID of the Sage Backend and the additional
fields belonging to the Sage instance.
"""

_name = "sage.payroll.sage.payslip.process.binder"
_inherit = "sage.binder"

_apply_on = "sage.payroll.sage.payslip.process"

_external_field = [
"sage_codigo_empresa",
"sage_tipo_proceso",
]
53 changes: 53 additions & 0 deletions connector_sage/models/payroll_sage_payslip_process/binding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright 2026 NuoBiT Solutions SL - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo import fields, models


class PayrollSagePayslipProcess(models.Model):
_inherit = "payroll.sage.payslip.process"

sage_bind_ids = fields.One2many(
comodel_name="sage.payroll.sage.payslip.process",
inverse_name="odoo_id",
string="Sage Bindings",
)


class PayrollSagePayslipProcessBinding(models.Model):
_name = "sage.payroll.sage.payslip.process"
_inherit = "sage.binding"
_inherits = {"payroll.sage.payslip.process": "odoo_id"}
_description = "Payslip process binding"

odoo_id = fields.Many2one(
comodel_name="payroll.sage.payslip.process",
string="Payslip process",
required=True,
ondelete="cascade",
)

# composed id
sage_codigo_empresa = fields.Integer(string="CodigoEmpresa", required=True)
sage_tipo_proceso = fields.Char(string="TipoProceso", required=True)

_sql_constraints = [
(
"uniq",
"unique(backend_id, sage_codigo_empresa, sage_tipo_proceso)",
"Payslip process with same ID on Sage already exists.",
),
]

def import_payslip_processes_since(self, backend_record=None, since_date=None):
"""Prepare the import of payslip processes modified on Sage"""
filters = {
"CodigoEmpresa": backend_record.sage_company_id,
}
now_fmt = fields.Datetime.now()
self.env["sage.payroll.sage.payslip.process"].import_batch(
backend=backend_record, filters=filters
)
backend_record.import_payslip_processes_since_date = now_fmt

return True
22 changes: 22 additions & 0 deletions connector_sage/models/payroll_sage_payslip_process/importer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2026 NuoBiT Solutions SL - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)


from odoo.addons.component.core import Component


class PayrollSagePayslipProcessBatchImporter(Component):
"""Import the Sage Payslip Processes.

For every payslip process in the list, a delayed job is created.
"""

_name = "sage.payroll.sage.payslip.process.delayed.batch.importer"
_inherit = "sage.delayed.batch.importer"
_apply_on = "sage.payroll.sage.payslip.process"


class PayrollSagePayslipProcessImporter(Component):
_name = "sage.payroll.sage.payslip.process.importer"
_inherit = "sage.importer"
_apply_on = "sage.payroll.sage.payslip.process"
23 changes: 23 additions & 0 deletions connector_sage/models/payroll_sage_payslip_process/mapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2026 NuoBiT Solutions SL - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)


from odoo.addons.component.core import Component
from odoo.addons.connector.components.mapper import mapping, only_create


class PayrollSagePayslipProcessImportMapper(Component):
_name = "sage.payroll.sage.payslip.process.import.mapper"
_inherit = "sage.import.mapper"
_apply_on = "sage.payroll.sage.payslip.process"

direct = [
("TipoProceso", "name"),
("CodigoEmpresa", "sage_codigo_empresa"),
("TipoProceso", "sage_tipo_proceso"),
]

@only_create
@mapping
def backend_id(self, record):
return {"backend_id": self.backend_record.id}
24 changes: 24 additions & 0 deletions connector_sage/models/sage_backend/common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright NuoBiT Solutions - Eric Antones <eantones@nuobit.com>
# Copyright NuoBiT Solutions - Kilian Niubo <kniubo@nuobit.com>
# Copyright 2026 NuoBiT Solutions SL - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

import logging
Expand Down Expand Up @@ -65,6 +66,10 @@ def _select_state(self):
"Import labour agreements since"
)

import_payslip_processes_since_date = fields.Datetime(
"Import payslip processes since"
)

import_payslip_line_id = fields.Many2one(
"payroll.sage.payslip", string="Payslip Line"
)
Expand Down Expand Up @@ -126,6 +131,17 @@ def import_labour_agreements_since(self):

return True

def import_payslip_processes_since(self):
for rec in self:
since_date = rec.import_payslip_processes_since_date
self.env[
"sage.payroll.sage.payslip.process"
].with_delay().import_payslip_processes_since(
backend_record=rec, since_date=since_date
)

return True

def import_payslip_lines(self):
for rec in self:
if not rec.import_payslip_line_id:
Expand Down Expand Up @@ -180,3 +196,11 @@ def _scheduler_import_labour_agreements(self):
domain = [("company_id", "=", company_id.id)]

self.search(domain).import_labour_agreements_since()

@api.model
def _scheduler_import_payslip_processes(self):
company_id = self.get_current_user_company()

domain = [("company_id", "=", company_id.id)]

self.search(domain).import_payslip_processes_since()
2 changes: 2 additions & 0 deletions connector_sage/security/ir.model.access.csv
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
"access_sage_payroll_sage_labour_agreement_user","sage_payroll_sage_labour_agreement user","model_sage_payroll_sage_labour_agreement","base.group_user",1,0,0,0
"access_sage_payroll_sage_labour_agreement_wage_type_line_manager","sage_payroll_sage_labour_agreement_wage_type_line connector_manager","model_sage_payroll_sage_labour_agreement_wage_type_line","connector.group_connector_manager",1,1,1,1
"access_sage_payroll_sage_labour_agreement_wage_type_line_user","sage_payroll_sage_labour_agreement_wage_type_line user","model_sage_payroll_sage_labour_agreement_wage_type_line","base.group_user",1,0,0,0
"access_sage_payroll_sage_payslip_process_manager","sage_payroll_sage_payslip_process connector_manager","model_sage_payroll_sage_payslip_process","connector.group_connector_manager",1,1,1,1
"access_sage_payroll_sage_payslip_process_user","sage_payroll_sage_payslip_process user","model_sage_payroll_sage_payslip_process","base.group_user",1,0,0,0
"access_sage_payroll_sage_payslip_line_payroll_manager","sage_payroll_sage_payslip_line_payroll connector manager","model_sage_payroll_sage_payslip_line_payroll","connector.group_connector_manager",1,1,1,1
"access_sage_payroll_sage_payslip_line_payrolluser","sage_payroll_sage_payslip_line_payroll connector user","model_sage_payroll_sage_payslip_line_payroll","base.group_user",1,0,0,0
"access_sage_payroll_sage_payslip_line_transfer_manager","sage_payroll_sage_payslip_line_transfer connector manager","model_sage_payroll_sage_payslip_line_transfer","connector.group_connector_manager",1,1,1,1
Expand Down
8 changes: 8 additions & 0 deletions connector_sage/views/connector_sage_menus.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright NuoBiT Solutions - Eric Antones <eantones@nuobit.com>
Copyright 2026 NuoBiT Solutions SL - Deniz Gallo <dgallo@nuobit.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -->
<odoo>
<menuitem
Expand Down Expand Up @@ -41,6 +42,13 @@
action="sage_labour_agreement_action"
/>

<menuitem
id="sage_external_payslip_processes_menu"
name="External Payslip processes"
parent="sage_external_objects_menu"
action="sage_payslip_process_action"
/>

<menuitem
id="sage_external_partners_menu"
name="External Contacts"
Expand Down
67 changes: 67 additions & 0 deletions connector_sage/views/payroll_sage_payslip_process_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2026 NuoBiT Solutions SL - Deniz Gallo <dgallo@nuobit.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -->
<odoo>
<record id="payslip_process_view_form_inherit_connector_sage" model="ir.ui.view">
<field name="name">payslip.process.form.inherit.connector.sage</field>
<field name="model">payroll.sage.payslip.process</field>
<field name="inherit_id" ref="payroll_sage.payslip_process_view_form" />
<field
name="groups_id"
eval="[(4, ref('connector.group_connector_manager'))]"
/>
<field name="arch" type="xml">
<xpath expr="//form/group" position="after">
<notebook>
<page string="Connectors">
<group string="Sage Bindings">
<field name="sage_bind_ids" nolabel="1" />
</group>
</page>
</notebook>
</xpath>
</field>
</record>

<record id="sage_payslip_process_view_form" model="ir.ui.view">
<field name="name">sage.payslip.process.form</field>
<field name="model">sage.payroll.sage.payslip.process</field>
<field name="arch" type="xml">
<form string="Sage Payslip process">
<group>
<field name="backend_id" />
<field name="odoo_id" readonly="True" />
<field name="sage_codigo_empresa" readonly="True" />
<field name="sage_tipo_proceso" readonly="True" />
<field name="sync_date" readonly="True" />
</group>
</form>
</field>
</record>

<record id="sage_payslip_process_view_tree" model="ir.ui.view">
<field name="name">sage.payslip.process.tree</field>
<field name="model">sage.payroll.sage.payslip.process</field>
<field name="arch" type="xml">
<tree>
<field name="backend_id" />
<field name="odoo_id" />
<field name="sage_codigo_empresa" readonly="True" />
<field name="sage_tipo_proceso" readonly="True" />
<field name="sync_date" />
<button
name="resync"
type="object"
string="Resynchronize"
icon="fa-refresh fa-lg"
/>
</tree>
</field>
</record>

<record id="sage_payslip_process_action" model="ir.actions.act_window">
<field name="name">Payslip process</field>
<field name="res_model">sage.payroll.sage.payslip.process</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>
Loading
Loading