Release v6.0

This commit is contained in:
wilson gomez 2021-06-04 16:04:40 -05:00
parent 3364169673
commit 8b4648f6f3
16 changed files with 219 additions and 130 deletions

View File

@ -1,41 +1,40 @@
#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.pool import Pool
from .period import Period, OpenPeriod
from .wage_type import WageType, WageTypeSalary
from .payroll import Payroll, PayrollLine, PayrollGroupStart, \
PayrollGroup, PayrollReport, Move, PayrollRecompute, PayrollPreliquidation
from .category import CategoryWagesDefault, EmployeeCategory
from .employee import Employee, MandatoryWage, CreateMandatoryWages
from .configuration import StaffConfigurationSequence, StaffConfiguration
from .position import Position, WorkdayDefinition
from . import period
from . import wage_type
from . import payroll
from . import category
from . import employee
from . import configuration
from . import position
def register():
Pool.register(
Position,
WorkdayDefinition,
Period,
WageType,
MandatoryWage,
EmployeeCategory,
Employee,
Payroll,
PayrollLine,
CategoryWagesDefault,
PayrollGroupStart,
StaffConfigurationSequence,
StaffConfiguration,
WageTypeSalary,
Move,
position.Position,
position.WorkdayDefinition,
period.Period,
wage_type.WageType,
employee.MandatoryWage,
category.EmployeeCategory,
employee.Employee,
payroll.Payroll,
payroll.PayrollLine,
category.CategoryWagesDefault,
payroll.PayrollGroupStart,
configuration.StaffConfigurationSequence,
configuration.StaffConfiguration,
wage_type.WageTypeSalary,
payroll.Move,
module='staff_payroll', type_='model')
Pool.register(
PayrollReport,
payroll.PayrollReport,
module='staff_payroll', type_='report')
Pool.register(
OpenPeriod,
PayrollGroup,
CreateMandatoryWages,
PayrollPreliquidation,
PayrollRecompute,
period.OpenPeriod,
payroll.PayrollGroup,
employee.CreateMandatoryWages,
payroll.PayrollPreliquidation,
payroll.PayrollRecompute,
module='staff_payroll', type_='wizard')

View File

@ -2,8 +2,6 @@
# this repository contains the full copyright notices and license terms.
from trytond.model import ModelView, ModelSQL, fields
__all__ = ['EmployeeCategory', 'CategoryWagesDefault']
class EmployeeCategory(ModelSQL, ModelView):
'Employee Category'

View File

@ -3,12 +3,9 @@
from trytond import backend
from trytond.model import fields
from trytond.pool import PoolMeta, Pool
from trytond.pyson import Eval
from trytond.pyson import Eval, Id
from trytond.tools.multivalue import migrate_property
__all__ = ['StaffConfiguration', 'StaffConfigurationSequence']
def default_func(field_name):
@classmethod
@ -19,12 +16,12 @@ def default_func(field_name):
return default
class StaffConfiguration:
__metaclass__ = PoolMeta
class StaffConfiguration(metaclass=PoolMeta):
__name__ = 'staff.configuration'
staff_payroll_sequence = fields.MultiValue(fields.Many2One('ir.sequence',
'Payroll Sequence', required=True, domain=[
('code', '=', 'staff.payroll')])
('sequence_type', '=',
Id('staff_payroll', 'sequence_type_payroll'))])
)
default_hour_workday = fields.Integer('Default Hour Workday',
required=True, help='In hours')
@ -48,22 +45,19 @@ class StaffConfiguration:
return super(StaffConfiguration, cls).multivalue_model(field)
class StaffConfigurationSequence:
__metaclass__ = PoolMeta
class StaffConfigurationSequence(metaclass=PoolMeta):
__name__ = 'staff.configuration.sequence'
staff_payroll_sequence = fields.Many2One(
'ir.sequence', "Staff Payroll Sequence", required=True,
domain=[
('company', 'in', [Eval('company', -1), None]),
('code', '=', 'staff.payroll'),
('sequence_type', '=', Id('staff_payroll', 'sequence_type_payroll')),
],
depends=['company'])
@classmethod
def __register__(cls, module_name):
TableHandler = backend.get('TableHandler')
exist = TableHandler.table_exist(cls._table)
exist = backend.TableHandler.table_exist(cls._table)
super(StaffConfigurationSequence, cls).__register__(module_name)
if not exist:

View File

@ -10,9 +10,23 @@ this repository contains the full copyright notices and license terms. -->
<field name="name">configuration_form</field>
</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">
<field name="name">Payroll</field>
<field name="code">staff.payroll</field>
<field name="name">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>
</data>

View File

@ -6,8 +6,8 @@ from trytond.transaction import Transaction
from trytond.pyson import Not, Bool, Eval, If
from trytond.wizard import Wizard, StateTransition
from datetime import datetime, date
__all__ = ['Employee', 'MandatoryWage', 'CreateMandatoryWages']
from trytond.i18n import gettext
from .exceptions import (MissingPartyWageType)
class Employee(metaclass=PoolMeta):
@ -19,9 +19,6 @@ class Employee(metaclass=PoolMeta):
@classmethod
def __setup__(cls):
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):
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):
super(MandatoryWage, cls).__setup__()
cls._order.insert(0, ('id', 'ASC'))
cls._error_messages.update({
'party_required': ('Error the wage type %s does not have party!'),
})
@classmethod
def validate(cls, mandatoryWages):
@ -70,7 +64,8 @@ class MandatoryWage(ModelSQL, ModelView):
if wages:
for wage in wages:
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):

74
exceptions.py Normal file
View File

@ -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

55
message.xml Normal file
View File

@ -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>

View File

@ -9,11 +9,10 @@ from trytond.pool import Pool, PoolMeta
from trytond.transaction import Transaction
from trytond.modules.company import CompanyReport
from trytond.wizard import Wizard, StateView, StateTransition, Button
__all__ = [
'Payroll', 'PayrollLine', 'PayrollReport', 'Move', 'PayrollGroupStart',
'PayrollGroup', 'PayrollPreliquidation', 'PayrollRecompute'
]
from trytond.i18n import gettext
from .exceptions import (PayrollDeleteError, PayrollPeriodCloseError,
PayrollExistPeriodError, PayrollMissingSequence, WageTypeValidationError,
PayrollValidationError)
STATES = {'readonly': (Eval('state') != 'draft')}
@ -102,20 +101,6 @@ class Payroll(Workflow, ModelSQL, ModelView):
('period', '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((
('draft', 'cancel'),
('cancel', 'draft'),
@ -176,9 +161,11 @@ class Payroll(Workflow, ModelSQL, ModelView):
cls.cancel(records)
for payroll in records:
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:
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)
@classmethod
@ -223,11 +210,9 @@ class Payroll(Workflow, ModelSQL, ModelView):
('kind', '=', 'normal'),
])
if len(payrolls) > 1:
cls.raise_user_error('payroll_exist_period',)
return
raise PayrollExistPeriodError(gettext('staff_payroll.msg_payroll_exist_period'))
if payroll.period.state == 'closed':
cls.raise_user_error('period_closed',)
return
raise PayrollPeriodCloseError(gettext('staff_payroll.msg_period_closed'))
payroll.set_number()
@classmethod
@ -260,13 +245,12 @@ class Payroll(Workflow, ModelSQL, ModelView):
if self.number:
return
pool = Pool()
Sequence = pool.get('ir.sequence')
Configuration = pool.get('staff.configuration')
configuration = Configuration(1)
if not configuration.staff_payroll_sequence:
self.raise_user_error('sequence_missing',)
seq = configuration.staff_payroll_sequence.id
self.write([self], {'number': Sequence.get_id(seq)})
raise PayrollMissingSequence(gettext('msg_sequence_missing'))
seq = configuration.staff_payroll_sequence.get()
self.write([self], {'number': seq})
@fields.depends('start', 'end')
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:
lines_moves[credit_acc.id][party.id]['credit'] += amount_credit
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 = []
for r in lines_moves.values():
@ -549,7 +534,8 @@ class Payroll(Workflow, ModelSQL, ModelView):
if self.start >= self.period.start and \
self.end is None:
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')
def on_change_period(self):
@ -746,8 +732,8 @@ class PayrollReport(CompanyReport):
__name__ = 'staff.payroll'
@classmethod
def get_context(cls, records, data):
report_context = super(PayrollReport, cls).get_context(records, data)
def get_context(cls, records, header, data):
report_context = super().get_context(records, header, data)
return report_context

View File

@ -4,22 +4,6 @@ this repository contains the full copyright notices and license terms. -->
<tryton>
<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">
<field name="name">Payroll</field>
<field name="model">staff.payroll</field>

View File

@ -5,8 +5,8 @@ from trytond.pyson import Eval
from trytond.wizard import Wizard, StateTransition
from trytond.pool import Pool
from trytond.transaction import Transaction
__all__ = ['Period', 'OpenPeriod']
from trytond.i18n import gettext
from .exceptions import PeriodValidationError
STATES = {'readonly': Eval('state') != 'draft'}
@ -36,10 +36,6 @@ class Period(Workflow, ModelSQL, ModelView):
def __setup__(cls):
super(Period, cls).__setup__()
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((
('draft', 'open'),
('open', 'draft'),
@ -88,7 +84,7 @@ class Period(Workflow, ModelSQL, ModelView):
def check_start_end(self):
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):
periods = self.search([
@ -105,7 +101,7 @@ class Period(Workflow, ModelSQL, ModelView):
]
]])
if periods:
self.raise_user_error('wrong_period_overlap',)
raise PeriodValidationError(gettext('staff_payroll.msg_wrong_period_overlap'))
class OpenPeriod(Wizard):

View File

@ -3,12 +3,11 @@
from trytond.model import ModelView, ModelSQL, fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, Bool
__all__ = ['Position', 'WorkdayDefinition']
from trytond.i18n import gettext
from .exceptions import MissingConfigPosition
class Position:
__metaclass__ = PoolMeta
class Position(metaclass=PoolMeta):
__name__ = 'staff.position'
workday_definition = fields.One2Many('staff.workday_definition',
'position', 'Workday Definition')
@ -16,9 +15,6 @@ class Position:
@classmethod
def __setup__(cls):
super(Position, cls).__setup__()
cls._error_messages.update({
'missing_config_default': ('Missing default values for '
'workday or restday on configuration!')})
cls._buttons.update({
'create_workdays': {
'invisible': Bool(Eval('workday_definition')),
@ -31,7 +27,7 @@ class Position:
Config = pool.get('staff.configuration')
config = Config(1)
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:
values = {
'position': self.id, 'weekday': day[0],

View File

@ -104,10 +104,10 @@ setup(name=name,
'Natural Language :: Slovenian',
'Natural Language :: Spanish',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Office/Business',

View File

@ -1,5 +1,5 @@
[tryton]
version=5.0.3
version=6.0.0
depends:
party
currency

View File

@ -1,7 +1,7 @@
<?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. -->
<tree editable="top">
<tree editable="1">
<field name="wage_type"/>
<field name="party"/>
<field name="fix_amount"/>

View File

@ -1,7 +1,7 @@
<?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. -->
<tree editable="bottom">
<tree editable="1">
<field name="weekday"/>
<field name="workday"/>
<field name="restday"/>

View File

@ -4,8 +4,8 @@ from decimal import Decimal
from trytond.model import ModelView, ModelSQL, fields
from trytond.pyson import Not, Bool, Eval, If
from trytond.transaction import Transaction
__all__ = ['WageType', 'WageTypeSalary']
from trytond.i18n import gettext
from .exceptions import WageTypeValidationError
STATES = {'readonly': Not(Bool(Eval('active')))}
@ -81,9 +81,6 @@ class WageType(ModelSQL, ModelView):
@classmethod
def __setup__(cls):
super(WageType, cls).__setup__()
cls._error_messages.update({
'invalid_formula': 'Invalid formula [ %s ] for unit price!',
})
cls._order.insert(0, ('sequence', 'ASC'))
@staticmethod
@ -128,7 +125,8 @@ class WageType(ModelSQL, ModelView):
value = Decimal(str(round(eval(formula), 2)))
return value
except Exception:
self.raise_user_error('invalid_formula', formula)
raise WageTypeValidationError(
gettext('staff_payroll.msg_invalid_formula', formula=formula))
class WageTypeSalary(ModelSQL):