diff --git a/__init__.py b/__init__.py index 511bcb3..2ae8a3d 100644 --- a/__init__.py +++ b/__init__.py @@ -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') diff --git a/category.py b/category.py index 938db7b..31874e8 100644 --- a/category.py +++ b/category.py @@ -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' diff --git a/configuration.py b/configuration.py index 7b7773c..7d65e4d 100644 --- a/configuration.py +++ b/configuration.py @@ -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: diff --git a/configuration.xml b/configuration.xml index 989f352..a64d982 100644 --- a/configuration.xml +++ b/configuration.xml @@ -10,9 +10,23 @@ this repository contains the full copyright notices and license terms. --> configuration_form + + Staff Payroll + - Payroll - staff.payroll + Staff Payroll + + + + + + + + + + diff --git a/employee.py b/employee.py index 15c5ff3..67ab16f 100644 --- a/employee.py +++ b/employee.py @@ -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): diff --git a/exceptions.py b/exceptions.py new file mode 100644 index 0000000..4b2311e --- /dev/null +++ b/exceptions.py @@ -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 diff --git a/message.xml b/message.xml new file mode 100644 index 0000000..ecd7ada --- /dev/null +++ b/message.xml @@ -0,0 +1,55 @@ + + + + + + + + + Error the wage type "%(wage)" does not have party! + + + + The employee does not have salary! + + + The date end can not smaller than date start, for employee "%(employee)" + + + Sequence Payroll is missing! + + + Payroll period is closed! + + + Already exist one payroll in this period with this contract! + + + The date start/end is repetead + or crossed with other date payroll + + + + Payroll "%(payroll)" must be cancelled before deletion. + + + Payroll "%(payroll)" has a move, must be deleted before deletion. + + + Bad configuration of the wage type "%(wage)". + + + The date end can not smaller than date start. + + + The period overlap another period!. + + + Missing default values for workday or restday on configuration! + + + Invalid formula [ %formula ] for unit price! + + + diff --git a/payroll.py b/payroll.py index f758aaf..aa81c27 100644 --- a/payroll.py +++ b/payroll.py @@ -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 diff --git a/payroll.xml b/payroll.xml index 66c937f..5a72930 100644 --- a/payroll.xml +++ b/payroll.xml @@ -4,22 +4,6 @@ this repository contains the full copyright notices and license terms. --> - - Staff Payroll - staff.payroll - - - - - - - - - - - Payroll staff.payroll diff --git a/period.py b/period.py index c6e5442..6461583 100644 --- a/period.py +++ b/period.py @@ -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): diff --git a/position.py b/position.py index 1d77832..be08334 100644 --- a/position.py +++ b/position.py @@ -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], diff --git a/setup.py b/setup.py index 649b9d9..d51de72 100644 --- a/setup.py +++ b/setup.py @@ -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', diff --git a/tryton.cfg b/tryton.cfg index b758101..6e0dbb5 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -1,5 +1,5 @@ [tryton] -version=5.0.3 +version=6.0.0 depends: party currency diff --git a/view/mandatory_wage_tree.xml b/view/mandatory_wage_tree.xml index 5ea3f72..28845b9 100644 --- a/view/mandatory_wage_tree.xml +++ b/view/mandatory_wage_tree.xml @@ -1,7 +1,7 @@ - + diff --git a/view/workday_definition_tree.xml b/view/workday_definition_tree.xml index d85e652..41d4d14 100644 --- a/view/workday_definition_tree.xml +++ b/view/workday_definition_tree.xml @@ -1,7 +1,7 @@ - + diff --git a/wage_type.py b/wage_type.py index 06fcabc..5d451e7 100644 --- a/wage_type.py +++ b/wage_type.py @@ -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):