Release v6.0
This commit is contained in:
parent
3364169673
commit
8b4648f6f3
57
__init__.py
57
__init__.py
|
@ -1,41 +1,40 @@
|
||||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
#this repository contains the full copyright notices and license terms.
|
#this repository contains the full copyright notices and license terms.
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from .period import Period, OpenPeriod
|
from . import period
|
||||||
from .wage_type import WageType, WageTypeSalary
|
from . import wage_type
|
||||||
from .payroll import Payroll, PayrollLine, PayrollGroupStart, \
|
from . import payroll
|
||||||
PayrollGroup, PayrollReport, Move, PayrollRecompute, PayrollPreliquidation
|
from . import category
|
||||||
from .category import CategoryWagesDefault, EmployeeCategory
|
from . import employee
|
||||||
from .employee import Employee, MandatoryWage, CreateMandatoryWages
|
from . import configuration
|
||||||
from .configuration import StaffConfigurationSequence, StaffConfiguration
|
from . import position
|
||||||
from .position import Position, WorkdayDefinition
|
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
Pool.register(
|
Pool.register(
|
||||||
Position,
|
position.Position,
|
||||||
WorkdayDefinition,
|
position.WorkdayDefinition,
|
||||||
Period,
|
period.Period,
|
||||||
WageType,
|
wage_type.WageType,
|
||||||
MandatoryWage,
|
employee.MandatoryWage,
|
||||||
EmployeeCategory,
|
category.EmployeeCategory,
|
||||||
Employee,
|
employee.Employee,
|
||||||
Payroll,
|
payroll.Payroll,
|
||||||
PayrollLine,
|
payroll.PayrollLine,
|
||||||
CategoryWagesDefault,
|
category.CategoryWagesDefault,
|
||||||
PayrollGroupStart,
|
payroll.PayrollGroupStart,
|
||||||
StaffConfigurationSequence,
|
configuration.StaffConfigurationSequence,
|
||||||
StaffConfiguration,
|
configuration.StaffConfiguration,
|
||||||
WageTypeSalary,
|
wage_type.WageTypeSalary,
|
||||||
Move,
|
payroll.Move,
|
||||||
module='staff_payroll', type_='model')
|
module='staff_payroll', type_='model')
|
||||||
Pool.register(
|
Pool.register(
|
||||||
PayrollReport,
|
payroll.PayrollReport,
|
||||||
module='staff_payroll', type_='report')
|
module='staff_payroll', type_='report')
|
||||||
Pool.register(
|
Pool.register(
|
||||||
OpenPeriod,
|
period.OpenPeriod,
|
||||||
PayrollGroup,
|
payroll.PayrollGroup,
|
||||||
CreateMandatoryWages,
|
employee.CreateMandatoryWages,
|
||||||
PayrollPreliquidation,
|
payroll.PayrollPreliquidation,
|
||||||
PayrollRecompute,
|
payroll.PayrollRecompute,
|
||||||
module='staff_payroll', type_='wizard')
|
module='staff_payroll', type_='wizard')
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
# this repository contains the full copyright notices and license terms.
|
# this repository contains the full copyright notices and license terms.
|
||||||
from trytond.model import ModelView, ModelSQL, fields
|
from trytond.model import ModelView, ModelSQL, fields
|
||||||
|
|
||||||
__all__ = ['EmployeeCategory', 'CategoryWagesDefault']
|
|
||||||
|
|
||||||
|
|
||||||
class EmployeeCategory(ModelSQL, ModelView):
|
class EmployeeCategory(ModelSQL, ModelView):
|
||||||
'Employee Category'
|
'Employee Category'
|
||||||
|
|
|
@ -3,12 +3,9 @@
|
||||||
from trytond import backend
|
from trytond import backend
|
||||||
from trytond.model import fields
|
from trytond.model import fields
|
||||||
from trytond.pool import PoolMeta, Pool
|
from trytond.pool import PoolMeta, Pool
|
||||||
from trytond.pyson import Eval
|
from trytond.pyson import Eval, Id
|
||||||
from trytond.tools.multivalue import migrate_property
|
from trytond.tools.multivalue import migrate_property
|
||||||
|
|
||||||
__all__ = ['StaffConfiguration', 'StaffConfigurationSequence']
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def default_func(field_name):
|
def default_func(field_name):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -19,12 +16,12 @@ def default_func(field_name):
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
class StaffConfiguration:
|
class StaffConfiguration(metaclass=PoolMeta):
|
||||||
__metaclass__ = PoolMeta
|
|
||||||
__name__ = 'staff.configuration'
|
__name__ = 'staff.configuration'
|
||||||
staff_payroll_sequence = fields.MultiValue(fields.Many2One('ir.sequence',
|
staff_payroll_sequence = fields.MultiValue(fields.Many2One('ir.sequence',
|
||||||
'Payroll Sequence', required=True, domain=[
|
'Payroll Sequence', required=True, domain=[
|
||||||
('code', '=', 'staff.payroll')])
|
('sequence_type', '=',
|
||||||
|
Id('staff_payroll', 'sequence_type_payroll'))])
|
||||||
)
|
)
|
||||||
default_hour_workday = fields.Integer('Default Hour Workday',
|
default_hour_workday = fields.Integer('Default Hour Workday',
|
||||||
required=True, help='In hours')
|
required=True, help='In hours')
|
||||||
|
@ -48,22 +45,19 @@ class StaffConfiguration:
|
||||||
return super(StaffConfiguration, cls).multivalue_model(field)
|
return super(StaffConfiguration, cls).multivalue_model(field)
|
||||||
|
|
||||||
|
|
||||||
class StaffConfigurationSequence:
|
class StaffConfigurationSequence(metaclass=PoolMeta):
|
||||||
__metaclass__ = PoolMeta
|
|
||||||
__name__ = 'staff.configuration.sequence'
|
__name__ = 'staff.configuration.sequence'
|
||||||
staff_payroll_sequence = fields.Many2One(
|
staff_payroll_sequence = fields.Many2One(
|
||||||
'ir.sequence', "Staff Payroll Sequence", required=True,
|
'ir.sequence', "Staff Payroll Sequence", required=True,
|
||||||
domain=[
|
domain=[
|
||||||
('company', 'in', [Eval('company', -1), None]),
|
('company', 'in', [Eval('company', -1), None]),
|
||||||
('code', '=', 'staff.payroll'),
|
('sequence_type', '=', Id('staff_payroll', 'sequence_type_payroll')),
|
||||||
],
|
],
|
||||||
depends=['company'])
|
depends=['company'])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __register__(cls, module_name):
|
def __register__(cls, module_name):
|
||||||
TableHandler = backend.get('TableHandler')
|
exist = backend.TableHandler.table_exist(cls._table)
|
||||||
exist = TableHandler.table_exist(cls._table)
|
|
||||||
|
|
||||||
super(StaffConfigurationSequence, cls).__register__(module_name)
|
super(StaffConfigurationSequence, cls).__register__(module_name)
|
||||||
|
|
||||||
if not exist:
|
if not exist:
|
||||||
|
|
|
@ -10,9 +10,23 @@ this repository contains the full copyright notices and license terms. -->
|
||||||
<field name="name">configuration_form</field>
|
<field name="name">configuration_form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.sequence.type" id="sequence_type_payroll">
|
||||||
|
<field name="name">Staff Payroll</field>
|
||||||
|
</record>
|
||||||
<record model="ir.sequence" id="sequence_staff_payroll">
|
<record model="ir.sequence" id="sequence_staff_payroll">
|
||||||
<field name="name">Payroll</field>
|
<field name="name">Staff Payroll</field>
|
||||||
<field name="code">staff.payroll</field>
|
<field name="sequence_type" ref="sequence_type_payroll"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.sequence.type-res.group"
|
||||||
|
id="sequence_type_payroll_group_admin">
|
||||||
|
<field name="sequence_type" ref="sequence_type_payroll"/>
|
||||||
|
<field name="group" ref="res.group_admin"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.sequence.type-res.group"
|
||||||
|
id="sequence_type_payroll_group_staff_admin">
|
||||||
|
<field name="sequence_type" ref="sequence_type_payroll"/>
|
||||||
|
<field name="group" ref="staff.group_staff_admin"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
|
|
13
employee.py
13
employee.py
|
@ -6,8 +6,8 @@ from trytond.transaction import Transaction
|
||||||
from trytond.pyson import Not, Bool, Eval, If
|
from trytond.pyson import Not, Bool, Eval, If
|
||||||
from trytond.wizard import Wizard, StateTransition
|
from trytond.wizard import Wizard, StateTransition
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
|
from trytond.i18n import gettext
|
||||||
__all__ = ['Employee', 'MandatoryWage', 'CreateMandatoryWages']
|
from .exceptions import (MissingPartyWageType)
|
||||||
|
|
||||||
|
|
||||||
class Employee(metaclass=PoolMeta):
|
class Employee(metaclass=PoolMeta):
|
||||||
|
@ -19,9 +19,6 @@ class Employee(metaclass=PoolMeta):
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(Employee, cls).__setup__()
|
super(Employee, cls).__setup__()
|
||||||
cls._error_messages.update({
|
|
||||||
'no_bank_accounts': ('The employee does not have banks!'),
|
|
||||||
})
|
|
||||||
|
|
||||||
def get_fix_amount_wage_type(self, wage_id):
|
def get_fix_amount_wage_type(self, wage_id):
|
||||||
fix_amount = sum([w.fix_amount or 0 for w in self.mandatory_wages if w.wage_type.id == wage_id])
|
fix_amount = sum([w.fix_amount or 0 for w in self.mandatory_wages if w.wage_type.id == wage_id])
|
||||||
|
@ -51,9 +48,6 @@ class MandatoryWage(ModelSQL, ModelView):
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(MandatoryWage, cls).__setup__()
|
super(MandatoryWage, cls).__setup__()
|
||||||
cls._order.insert(0, ('id', 'ASC'))
|
cls._order.insert(0, ('id', 'ASC'))
|
||||||
cls._error_messages.update({
|
|
||||||
'party_required': ('Error the wage type %s does not have party!'),
|
|
||||||
})
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate(cls, mandatoryWages):
|
def validate(cls, mandatoryWages):
|
||||||
|
@ -70,7 +64,8 @@ class MandatoryWage(ModelSQL, ModelView):
|
||||||
if wages:
|
if wages:
|
||||||
for wage in wages:
|
for wage in wages:
|
||||||
if wage.party_required and not self.party:
|
if wage.party_required and not self.party:
|
||||||
self.raise_user_error('party_required', wage.name)
|
raise MissingPartyWageType(
|
||||||
|
gettext('staff_payroll.msg_party_required', wage=wage.name))
|
||||||
|
|
||||||
|
|
||||||
class CreateMandatoryWages(Wizard):
|
class CreateMandatoryWages(Wizard):
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
from trytond.exceptions import UserError, UserWarning
|
||||||
|
from trytond.model.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
|
class WageTypeValidationError(ValidationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MissingPartyWageType(WageTypeValidationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PayrollDeleteError(ValidationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PayrollExistPeriodError(UserError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PayrollPeriodCloseError(ValidationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PayrollMissingSequence(ValidationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PayrollValidationError(UserError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PeriodValidationError(UserError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MissingConfigPosition(UserError):
|
||||||
|
pass
|
||||||
|
# class DontWriteAccountError(UserError):
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class MissingInvoiceTaxError(UserError):
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class InvoiceDuplicatedError(UserError):
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class NotificationAuthError(UserError):
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class NotificationAuthWarning(UserWarning):
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class AuthExpiredError(UserError):
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class InvalidTypeInvoiceError(UserError):
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class ImportMoveDataError(UserError):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
|
||||||
|
# class AccountMoveCreatedError(UserWarning):
|
||||||
|
# pass
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
this repository contains the full copyright notices and license terms. -->
|
||||||
|
<tryton>
|
||||||
|
<data grouped="1">
|
||||||
|
<record model="ir.message" id="msg_no_bank_accounts">
|
||||||
|
<field name="text"The employee does not have banks!</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_party_required">
|
||||||
|
<field name="text">Error the wage type "%(wage)" does not have party!</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.message" id="msg_employee_without_salary">
|
||||||
|
<field name="text">The employee does not have salary!</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_wrong_start_end">
|
||||||
|
<field name="text">The date end can not smaller than date start, for employee "%(employee)"</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_sequence_missing">
|
||||||
|
<field name="text">Sequence Payroll is missing!</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_period_closed">
|
||||||
|
<field name="text">Payroll period is closed!</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_payroll_exist_period">
|
||||||
|
<field name="text">Already exist one payroll in this period with this contract!</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_wrong_date_consistent">
|
||||||
|
<field name="text">The date start/end is repetead
|
||||||
|
or crossed with other date payroll</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.message" id="msg_delete_cancel">
|
||||||
|
<field name="text">Payroll "%(payroll)" must be cancelled before deletion.</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_existing_move">
|
||||||
|
<field name="text">Payroll "%(payroll)" has a move, must be deleted before deletion.</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_bad_configuration_wage_type">
|
||||||
|
<field name="text">Bad configuration of the wage type "%(wage)".</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_wrong_start_end">
|
||||||
|
<field name="text">The date end can not smaller than date start.</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_wrong_period_overlap">
|
||||||
|
<field name="text">The period overlap another period!.</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_missing_config_default">
|
||||||
|
<field name="text">Missing default values for workday or restday on configuration!</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_invalid_formula">
|
||||||
|
<field name="text">Invalid formula [ %formula ] for unit price!</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</tryton>
|
52
payroll.py
52
payroll.py
|
@ -9,11 +9,10 @@ from trytond.pool import Pool, PoolMeta
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.modules.company import CompanyReport
|
from trytond.modules.company import CompanyReport
|
||||||
from trytond.wizard import Wizard, StateView, StateTransition, Button
|
from trytond.wizard import Wizard, StateView, StateTransition, Button
|
||||||
|
from trytond.i18n import gettext
|
||||||
__all__ = [
|
from .exceptions import (PayrollDeleteError, PayrollPeriodCloseError,
|
||||||
'Payroll', 'PayrollLine', 'PayrollReport', 'Move', 'PayrollGroupStart',
|
PayrollExistPeriodError, PayrollMissingSequence, WageTypeValidationError,
|
||||||
'PayrollGroup', 'PayrollPreliquidation', 'PayrollRecompute'
|
PayrollValidationError)
|
||||||
]
|
|
||||||
|
|
||||||
STATES = {'readonly': (Eval('state') != 'draft')}
|
STATES = {'readonly': (Eval('state') != 'draft')}
|
||||||
|
|
||||||
|
@ -102,20 +101,6 @@ class Payroll(Workflow, ModelSQL, ModelView):
|
||||||
('period', 'DESC'),
|
('period', 'DESC'),
|
||||||
('start', 'DESC'),
|
('start', 'DESC'),
|
||||||
]
|
]
|
||||||
cls._error_messages.update({
|
|
||||||
'employee_without_salary': ('The employee does not have salary!'),
|
|
||||||
'wrong_start_end': ('The date end can not smaller than date start, for employee %s'),
|
|
||||||
'sequence_missing': ('Sequence Payroll is missing!'),
|
|
||||||
'period_closed': ('Payroll period is closed!'),
|
|
||||||
'payroll_exist_period': ('Already exist one payroll in this period with this contract!'),
|
|
||||||
'wrong_date_consistent': ('The date start/end is repetead \
|
|
||||||
or crossed with other date payroll'),
|
|
||||||
'delete_cancel': ('Payroll "%s" must be cancelled before '
|
|
||||||
'deletion.'),
|
|
||||||
'existing_move': ('Payroll "%s" has a move, must be deleted '
|
|
||||||
'before deletion.'),
|
|
||||||
'bad_configuration_wage_type': ('Bad configuration of the wage type "%s".'),
|
|
||||||
})
|
|
||||||
cls._transitions |= set((
|
cls._transitions |= set((
|
||||||
('draft', 'cancel'),
|
('draft', 'cancel'),
|
||||||
('cancel', 'draft'),
|
('cancel', 'draft'),
|
||||||
|
@ -176,9 +161,11 @@ class Payroll(Workflow, ModelSQL, ModelView):
|
||||||
cls.cancel(records)
|
cls.cancel(records)
|
||||||
for payroll in records:
|
for payroll in records:
|
||||||
if payroll.state != 'cancel':
|
if payroll.state != 'cancel':
|
||||||
cls.raise_user_error('delete_cancel', (payroll.rec_name,))
|
raise PayrollDeleteError(
|
||||||
|
gettext('staff_payroll.msg_delete_cancel', payroll=payroll.rec_name))
|
||||||
if payroll.move:
|
if payroll.move:
|
||||||
cls.raise_user_error('existing_move', (payroll.rec_name,))
|
raise PayrollDeleteError(
|
||||||
|
gettext('staff_payroll.msg_existing_move', payroll=payroll.rec_name))
|
||||||
super(Payroll, cls).delete(records)
|
super(Payroll, cls).delete(records)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -223,11 +210,9 @@ class Payroll(Workflow, ModelSQL, ModelView):
|
||||||
('kind', '=', 'normal'),
|
('kind', '=', 'normal'),
|
||||||
])
|
])
|
||||||
if len(payrolls) > 1:
|
if len(payrolls) > 1:
|
||||||
cls.raise_user_error('payroll_exist_period',)
|
raise PayrollExistPeriodError(gettext('staff_payroll.msg_payroll_exist_period'))
|
||||||
return
|
|
||||||
if payroll.period.state == 'closed':
|
if payroll.period.state == 'closed':
|
||||||
cls.raise_user_error('period_closed',)
|
raise PayrollPeriodCloseError(gettext('staff_payroll.msg_period_closed'))
|
||||||
return
|
|
||||||
payroll.set_number()
|
payroll.set_number()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -260,13 +245,12 @@ class Payroll(Workflow, ModelSQL, ModelView):
|
||||||
if self.number:
|
if self.number:
|
||||||
return
|
return
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
Sequence = pool.get('ir.sequence')
|
|
||||||
Configuration = pool.get('staff.configuration')
|
Configuration = pool.get('staff.configuration')
|
||||||
configuration = Configuration(1)
|
configuration = Configuration(1)
|
||||||
if not configuration.staff_payroll_sequence:
|
if not configuration.staff_payroll_sequence:
|
||||||
self.raise_user_error('sequence_missing',)
|
raise PayrollMissingSequence(gettext('msg_sequence_missing'))
|
||||||
seq = configuration.staff_payroll_sequence.id
|
seq = configuration.staff_payroll_sequence.get()
|
||||||
self.write([self], {'number': Sequence.get_id(seq)})
|
self.write([self], {'number': seq})
|
||||||
|
|
||||||
@fields.depends('start', 'end')
|
@fields.depends('start', 'end')
|
||||||
def on_change_with_worked_days(self, name=None):
|
def on_change_with_worked_days(self, name=None):
|
||||||
|
@ -393,7 +377,8 @@ class Payroll(Workflow, ModelSQL, ModelView):
|
||||||
if credit_acc and not line_credit_ready:
|
if credit_acc and not line_credit_ready:
|
||||||
lines_moves[credit_acc.id][party.id]['credit'] += amount_credit
|
lines_moves[credit_acc.id][party.id]['credit'] += amount_credit
|
||||||
except:
|
except:
|
||||||
self.raise_user_error('bad_configuration_wage_type', line.wage_type.name)
|
raise WageTypeValidationError(
|
||||||
|
gettext('staff_payroll.bad_configuration_wage_type', wage=line.wage_type.name))
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for r in lines_moves.values():
|
for r in lines_moves.values():
|
||||||
|
@ -549,7 +534,8 @@ class Payroll(Workflow, ModelSQL, ModelView):
|
||||||
if self.start >= self.period.start and \
|
if self.start >= self.period.start and \
|
||||||
self.end is None:
|
self.end is None:
|
||||||
return
|
return
|
||||||
self.raise_user_error('wrong_start_end', self.employee.party.name)
|
raise PayrollValidationError(
|
||||||
|
gettext('staff_payroll.msg_wrong_start_end', employee=self.employee.party.name))
|
||||||
|
|
||||||
@fields.depends('period', 'start', 'end', 'employee')
|
@fields.depends('period', 'start', 'end', 'employee')
|
||||||
def on_change_period(self):
|
def on_change_period(self):
|
||||||
|
@ -746,8 +732,8 @@ class PayrollReport(CompanyReport):
|
||||||
__name__ = 'staff.payroll'
|
__name__ = 'staff.payroll'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_context(cls, records, data):
|
def get_context(cls, records, header, data):
|
||||||
report_context = super(PayrollReport, cls).get_context(records, data)
|
report_context = super().get_context(records, header, data)
|
||||||
return report_context
|
return report_context
|
||||||
|
|
||||||
|
|
||||||
|
|
16
payroll.xml
16
payroll.xml
|
@ -4,22 +4,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||||
<tryton>
|
<tryton>
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<record model="ir.sequence.type" id="sequence_type_payroll">
|
|
||||||
<field name="name">Staff Payroll</field>
|
|
||||||
<field name="code">staff.payroll</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record model="ir.sequence.type-res.group"
|
|
||||||
id="sequence_type_payroll_group_admin">
|
|
||||||
<field name="sequence_type" ref="sequence_type_payroll"/>
|
|
||||||
<field name="group" ref="res.group_admin"/>
|
|
||||||
</record>
|
|
||||||
<record model="ir.sequence.type-res.group"
|
|
||||||
id="sequence_type_payroll_group_staff_admin">
|
|
||||||
<field name="sequence_type" ref="sequence_type_payroll"/>
|
|
||||||
<field name="group" ref="staff.group_staff_admin"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record model="ir.action.report" id="report_staff_payroll">
|
<record model="ir.action.report" id="report_staff_payroll">
|
||||||
<field name="name">Payroll</field>
|
<field name="name">Payroll</field>
|
||||||
<field name="model">staff.payroll</field>
|
<field name="model">staff.payroll</field>
|
||||||
|
|
12
period.py
12
period.py
|
@ -5,8 +5,8 @@ from trytond.pyson import Eval
|
||||||
from trytond.wizard import Wizard, StateTransition
|
from trytond.wizard import Wizard, StateTransition
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
|
from trytond.i18n import gettext
|
||||||
__all__ = ['Period', 'OpenPeriod']
|
from .exceptions import PeriodValidationError
|
||||||
|
|
||||||
STATES = {'readonly': Eval('state') != 'draft'}
|
STATES = {'readonly': Eval('state') != 'draft'}
|
||||||
|
|
||||||
|
@ -36,10 +36,6 @@ class Period(Workflow, ModelSQL, ModelView):
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(Period, cls).__setup__()
|
super(Period, cls).__setup__()
|
||||||
cls._order.insert(0, ('sequence', 'ASC'))
|
cls._order.insert(0, ('sequence', 'ASC'))
|
||||||
cls._error_messages.update({
|
|
||||||
'wrong_start_end': ('The date end can not smaller than date start'),
|
|
||||||
'wrong_period_overlap': ('The period overlap another period!')
|
|
||||||
})
|
|
||||||
cls._transitions |= set((
|
cls._transitions |= set((
|
||||||
('draft', 'open'),
|
('draft', 'open'),
|
||||||
('open', 'draft'),
|
('open', 'draft'),
|
||||||
|
@ -88,7 +84,7 @@ class Period(Workflow, ModelSQL, ModelView):
|
||||||
|
|
||||||
def check_start_end(self):
|
def check_start_end(self):
|
||||||
if self.start > self.end:
|
if self.start > self.end:
|
||||||
self.raise_user_error('wrong_start_end',)
|
raise PeriodValidationError(gettext('staff_payroll.msg_wrong_start_end'))
|
||||||
|
|
||||||
def check_date_consistent(self):
|
def check_date_consistent(self):
|
||||||
periods = self.search([
|
periods = self.search([
|
||||||
|
@ -105,7 +101,7 @@ class Period(Workflow, ModelSQL, ModelView):
|
||||||
]
|
]
|
||||||
]])
|
]])
|
||||||
if periods:
|
if periods:
|
||||||
self.raise_user_error('wrong_period_overlap',)
|
raise PeriodValidationError(gettext('staff_payroll.msg_wrong_period_overlap'))
|
||||||
|
|
||||||
|
|
||||||
class OpenPeriod(Wizard):
|
class OpenPeriod(Wizard):
|
||||||
|
|
12
position.py
12
position.py
|
@ -3,12 +3,11 @@
|
||||||
from trytond.model import ModelView, ModelSQL, fields
|
from trytond.model import ModelView, ModelSQL, fields
|
||||||
from trytond.pool import Pool, PoolMeta
|
from trytond.pool import Pool, PoolMeta
|
||||||
from trytond.pyson import Eval, Bool
|
from trytond.pyson import Eval, Bool
|
||||||
|
from trytond.i18n import gettext
|
||||||
__all__ = ['Position', 'WorkdayDefinition']
|
from .exceptions import MissingConfigPosition
|
||||||
|
|
||||||
|
|
||||||
class Position:
|
class Position(metaclass=PoolMeta):
|
||||||
__metaclass__ = PoolMeta
|
|
||||||
__name__ = 'staff.position'
|
__name__ = 'staff.position'
|
||||||
workday_definition = fields.One2Many('staff.workday_definition',
|
workday_definition = fields.One2Many('staff.workday_definition',
|
||||||
'position', 'Workday Definition')
|
'position', 'Workday Definition')
|
||||||
|
@ -16,9 +15,6 @@ class Position:
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(Position, cls).__setup__()
|
super(Position, cls).__setup__()
|
||||||
cls._error_messages.update({
|
|
||||||
'missing_config_default': ('Missing default values for '
|
|
||||||
'workday or restday on configuration!')})
|
|
||||||
cls._buttons.update({
|
cls._buttons.update({
|
||||||
'create_workdays': {
|
'create_workdays': {
|
||||||
'invisible': Bool(Eval('workday_definition')),
|
'invisible': Bool(Eval('workday_definition')),
|
||||||
|
@ -31,7 +27,7 @@ class Position:
|
||||||
Config = pool.get('staff.configuration')
|
Config = pool.get('staff.configuration')
|
||||||
config = Config(1)
|
config = Config(1)
|
||||||
if not config.default_hour_workday or not config.default_hour_workday:
|
if not config.default_hour_workday or not config.default_hour_workday:
|
||||||
self.raise_user_error('missing_config_default')
|
raise MissingConfigPosition(gettext('staff_payroll.msg_missing_config_default'))
|
||||||
for day in Workday.weekday.selection:
|
for day in Workday.weekday.selection:
|
||||||
values = {
|
values = {
|
||||||
'position': self.id, 'weekday': day[0],
|
'position': self.id, 'weekday': day[0],
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -104,10 +104,10 @@ setup(name=name,
|
||||||
'Natural Language :: Slovenian',
|
'Natural Language :: Slovenian',
|
||||||
'Natural Language :: Spanish',
|
'Natural Language :: Spanish',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Programming Language :: Python :: 2.7',
|
|
||||||
'Programming Language :: Python :: 3.3',
|
'Programming Language :: Python :: 3.3',
|
||||||
'Programming Language :: Python :: 3.4',
|
'Programming Language :: Python :: 3.4',
|
||||||
'Programming Language :: Python :: 3.5',
|
'Programming Language :: Python :: 3.5',
|
||||||
|
'Programming Language :: Python :: 3.9',
|
||||||
'Programming Language :: Python :: Implementation :: CPython',
|
'Programming Language :: Python :: Implementation :: CPython',
|
||||||
'Programming Language :: Python :: Implementation :: PyPy',
|
'Programming Language :: Python :: Implementation :: PyPy',
|
||||||
'Topic :: Office/Business',
|
'Topic :: Office/Business',
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[tryton]
|
[tryton]
|
||||||
version=5.0.3
|
version=6.0.0
|
||||||
depends:
|
depends:
|
||||||
party
|
party
|
||||||
currency
|
currency
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
this repository contains the full copyright notices and license terms. -->
|
this repository contains the full copyright notices and license terms. -->
|
||||||
<tree editable="top">
|
<tree editable="1">
|
||||||
<field name="wage_type"/>
|
<field name="wage_type"/>
|
||||||
<field name="party"/>
|
<field name="party"/>
|
||||||
<field name="fix_amount"/>
|
<field name="fix_amount"/>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
this repository contains the full copyright notices and license terms. -->
|
this repository contains the full copyright notices and license terms. -->
|
||||||
<tree editable="bottom">
|
<tree editable="1">
|
||||||
<field name="weekday"/>
|
<field name="weekday"/>
|
||||||
<field name="workday"/>
|
<field name="workday"/>
|
||||||
<field name="restday"/>
|
<field name="restday"/>
|
||||||
|
|
10
wage_type.py
10
wage_type.py
|
@ -4,8 +4,8 @@ from decimal import Decimal
|
||||||
from trytond.model import ModelView, ModelSQL, fields
|
from trytond.model import ModelView, ModelSQL, fields
|
||||||
from trytond.pyson import Not, Bool, Eval, If
|
from trytond.pyson import Not, Bool, Eval, If
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
|
from trytond.i18n import gettext
|
||||||
__all__ = ['WageType', 'WageTypeSalary']
|
from .exceptions import WageTypeValidationError
|
||||||
|
|
||||||
STATES = {'readonly': Not(Bool(Eval('active')))}
|
STATES = {'readonly': Not(Bool(Eval('active')))}
|
||||||
|
|
||||||
|
@ -81,9 +81,6 @@ class WageType(ModelSQL, ModelView):
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(WageType, cls).__setup__()
|
super(WageType, cls).__setup__()
|
||||||
cls._error_messages.update({
|
|
||||||
'invalid_formula': 'Invalid formula [ %s ] for unit price!',
|
|
||||||
})
|
|
||||||
cls._order.insert(0, ('sequence', 'ASC'))
|
cls._order.insert(0, ('sequence', 'ASC'))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -128,7 +125,8 @@ class WageType(ModelSQL, ModelView):
|
||||||
value = Decimal(str(round(eval(formula), 2)))
|
value = Decimal(str(round(eval(formula), 2)))
|
||||||
return value
|
return value
|
||||||
except Exception:
|
except Exception:
|
||||||
self.raise_user_error('invalid_formula', formula)
|
raise WageTypeValidationError(
|
||||||
|
gettext('staff_payroll.msg_invalid_formula', formula=formula))
|
||||||
|
|
||||||
|
|
||||||
class WageTypeSalary(ModelSQL):
|
class WageTypeSalary(ModelSQL):
|
||||||
|
|
Loading…
Reference in New Issue