mirror of
https://bitbucket.org/presik/trytonpsk-staff_payroll_co.git
synced 2023-12-14 06:42:56 +01:00
279 lines
10 KiB
Python
279 lines
10 KiB
Python
|
from trytond.report import Report
|
||
|
from trytond.wizard import (
|
||
|
Wizard, StateView, Button, StateAction, StateReport, StateTransition
|
||
|
)
|
||
|
from trytond.pool import Pool, PoolMeta
|
||
|
|
||
|
class PayrollAuditory(Wizard):
|
||
|
'Payroll Auditory'
|
||
|
__name__ = 'staff.payroll.auditory'
|
||
|
start = StateView('staff.payroll_paycheck.start',
|
||
|
'staff_payroll_co.payroll_auditory_start_view_form', [
|
||
|
Button('Cancel', 'end', 'tryton-cancel'),
|
||
|
Button('Print', 'print_', 'tryton-ok', default=True),
|
||
|
])
|
||
|
|
||
|
print_ = StateReport('staff.payroll.auditory_report')
|
||
|
|
||
|
def do_print_(self, action):
|
||
|
department_id = None
|
||
|
|
||
|
if self.start.department:
|
||
|
department_id = self.start.department.id
|
||
|
periods = [p.id for p in self.start.periods]
|
||
|
periods_name = [p.name for p in self.start.periods]
|
||
|
data = {
|
||
|
'ids': [],
|
||
|
'company': self.start.company.id,
|
||
|
'periods': periods,
|
||
|
'periods_name': periods_name,
|
||
|
'department': department_id,
|
||
|
}
|
||
|
return action, data
|
||
|
|
||
|
def transition_print_(self):
|
||
|
return 'end'
|
||
|
|
||
|
|
||
|
class PayrollAuditoryReport(Report):
|
||
|
__name__ = 'staff.payroll.auditory_report'
|
||
|
|
||
|
@classmethod
|
||
|
def get_domain_payroll(cls, data):
|
||
|
dom_payroll = [
|
||
|
('period', 'in', data['periods']),
|
||
|
('state', '!=', 'draft'),
|
||
|
]
|
||
|
if data['department']:
|
||
|
dom_payroll.append(
|
||
|
('employee.department', '=', data['department'])
|
||
|
)
|
||
|
return dom_payroll
|
||
|
|
||
|
@classmethod
|
||
|
def get_domain_liquidation(cls, data):
|
||
|
Period = Pool().get('staff.payroll.period')
|
||
|
periods = Period.browse(data['periods'])
|
||
|
date_periods = []
|
||
|
for p in periods:
|
||
|
date_periods.append(p.start)
|
||
|
date_periods.append(p.end)
|
||
|
|
||
|
dom_liquidation = [
|
||
|
('state', '!=', 'draft'),
|
||
|
('liquidation_date', '>=', min(date_periods)),
|
||
|
('liquidation_date', '<=', max(date_periods)),
|
||
|
]
|
||
|
if data['department']:
|
||
|
dom_liquidation.append(
|
||
|
('employee.department', '=', data['department'])
|
||
|
)
|
||
|
return dom_liquidation
|
||
|
|
||
|
@classmethod
|
||
|
def get_context(cls, records, header, data):
|
||
|
report_context = super().get_context(records, header, data)
|
||
|
pool = Pool()
|
||
|
Company = pool.get('company.company')
|
||
|
Payroll = pool.get('staff.payroll')
|
||
|
PayrollLine = pool.get('staff.payroll.line')
|
||
|
Liquidation = pool.get('staff.liquidation')
|
||
|
LiquidationLine = pool.get('staff.liquidation.line')
|
||
|
company = Company(data['company'])
|
||
|
company_id = company.party.id_number
|
||
|
|
||
|
# process payrolls
|
||
|
dom_payroll = cls.get_domain_payroll(data)
|
||
|
fields_payroll = [
|
||
|
'id', 'employee.party.name', 'employee.party.id_number',
|
||
|
'ibc', 'contract.last_salary', 'employee', 'contract.number',
|
||
|
'employee.afc', 'employee.fvp', 'contract',
|
||
|
]
|
||
|
payrolls = Payroll.search_read(
|
||
|
dom_payroll, fields_names=fields_payroll)
|
||
|
res = {}
|
||
|
|
||
|
payroll_ids = []
|
||
|
for p in payrolls:
|
||
|
key = str(p['employee']) + '_' + str(p['contract'])
|
||
|
try:
|
||
|
res[key]['ibc'] += p['ibc']
|
||
|
except:
|
||
|
res[key] = cls.get_default_values_payroll(p)
|
||
|
res[key]['company_id'] = company_id
|
||
|
|
||
|
payroll_ids += [p['id']]
|
||
|
|
||
|
fields_lines = [
|
||
|
'amount', 'quantity', 'party.name', 'wage_type.type_concept',
|
||
|
'payroll', 'payroll.employee', 'wage_type.name', 'wage_type.uom.symbol',
|
||
|
'payroll.contract', 'wage_type.salary_constitute', 'wage_type.definition',
|
||
|
'wage_type.receipt',
|
||
|
]
|
||
|
dom_line = [
|
||
|
('payroll', 'in', payroll_ids),
|
||
|
('wage_type.provision_cancellation', '=', None),
|
||
|
]
|
||
|
order = [('payroll.employee', 'DESC'), ('payroll', 'ASC')]
|
||
|
payroll_lines = PayrollLine.search_read(
|
||
|
dom_line, fields_names=fields_lines, order=order)
|
||
|
|
||
|
for line in payroll_lines:
|
||
|
cls.process_line(res, line, type_line='payroll')
|
||
|
|
||
|
# process liquidations
|
||
|
dom_liquidation = cls.get_domain_liquidation(data)
|
||
|
fields_liquidation = [
|
||
|
'id', 'employee.party.name', 'employee.party.id_number',
|
||
|
'contract.last_salary', 'employee', 'contract.number',
|
||
|
'contract', 'employee.afc', 'employee.fvp'
|
||
|
]
|
||
|
liquidations = Liquidation.search_read(
|
||
|
dom_liquidation, fields_names=fields_liquidation)
|
||
|
|
||
|
liquidation_ids = []
|
||
|
for p in liquidations:
|
||
|
key = str(p['employee']) + '_' + str(p['contract'])
|
||
|
try:
|
||
|
res[key]['ibc'] += p['ibc'] if p.get('ibc') else 0
|
||
|
except:
|
||
|
res[key] = cls.get_default_values_payroll(p)
|
||
|
res[key]['company_id'] = company_id
|
||
|
|
||
|
liquidation_ids += [p['id']]
|
||
|
|
||
|
fields_lines = [
|
||
|
'amount', 'party.name', 'wage.type_concept', 'liquidation.kind',
|
||
|
'liquidation', 'liquidation.employee', 'wage.name', 'wage.uom.symbol',
|
||
|
'liquidation.contract', 'wage.salary_constitute', 'wage.definition',
|
||
|
'wage.receipt'
|
||
|
]
|
||
|
dom_line = [
|
||
|
('liquidation', 'in', liquidation_ids),
|
||
|
# ('wage_type.provision_cancellation', '=', None),
|
||
|
]
|
||
|
order = [('liquidation.employee', 'DESC'), ('liquidation', 'ASC')]
|
||
|
liquidation_lines = LiquidationLine.search_read(
|
||
|
dom_line, fields_names=fields_lines, order=order)
|
||
|
|
||
|
for line in liquidation_lines:
|
||
|
cls.process_line(res, line, type_line='liquidation')
|
||
|
|
||
|
cls.process_records(res)
|
||
|
|
||
|
report_context['records'] = res.values()
|
||
|
report_context['company'] = Company(data['company'])
|
||
|
return report_context
|
||
|
|
||
|
@classmethod
|
||
|
def get_default_values_payroll(cls, p):
|
||
|
value = {
|
||
|
'id_number': p['employee.']['party.']['id_number'],
|
||
|
'contract': p['contract.']['number'],
|
||
|
'salary': p['contract.']['last_salary'],
|
||
|
'ibc': p['ibc'] if p.get('ibc') else 0,
|
||
|
'worked_day': [],
|
||
|
'unpaid_leave': [],
|
||
|
'overtime_hours': [],
|
||
|
'overgead_hours': [],
|
||
|
'basic_benefits': [],
|
||
|
'vacations_base': [],
|
||
|
'certifiable_non_benefits': [],
|
||
|
'paid_salary': [],
|
||
|
'legal_discounts': [],
|
||
|
'other_discounts': [],
|
||
|
'net_payable': [],
|
||
|
'tax_basis': [],
|
||
|
'social_benefits': [],
|
||
|
'bonus_and_interest': [],
|
||
|
'bonus_paid_fund': [],
|
||
|
'other_payments': [],
|
||
|
'commission': [],
|
||
|
'tax': [],
|
||
|
'health': [],
|
||
|
'retirement': [],
|
||
|
'fsp': [],
|
||
|
}
|
||
|
return value
|
||
|
|
||
|
|
||
|
@classmethod
|
||
|
def process_line(cls, res, line, type_line):
|
||
|
if type_line == 'payroll':
|
||
|
wage = line['wage_type.']
|
||
|
key = str(line['payroll.']['employee'])+ '_' + str(line['payroll.']['contract'])
|
||
|
else:
|
||
|
wage = line['wage.']
|
||
|
key = str(line['liquidation.']['employee'])+ '_' + str(line['liquidation.']['contract'])
|
||
|
|
||
|
concept = wage['type_concept']
|
||
|
name_concept = wage['name'].lower()
|
||
|
concepts_amount = ['health', 'retirement', 'commission', 'tax', 'fsp']
|
||
|
salary_constitute = wage['salary_constitute']
|
||
|
definition = wage['definition']
|
||
|
basic_benefit_exc = ['lic', 'sal', 'vac', 'inc']
|
||
|
amount = line['amount']
|
||
|
|
||
|
|
||
|
|
||
|
if concept in concepts_amount:
|
||
|
res[key][concept] += [amount]
|
||
|
|
||
|
if definition == 'deduction':
|
||
|
res[key]['legal_discounts'] += [amount]
|
||
|
if concept != 'tax':
|
||
|
res[key]['tax_basis'] += [-amount]
|
||
|
|
||
|
elif concept not in concepts_amount and definition in ('deduction', 'discounts'):
|
||
|
res[key]['other_discounts'] += [amount]
|
||
|
|
||
|
elif concept == 'extras' and name_concept.startswith('r'):
|
||
|
res[key]['overgead_hours'] += [line['quantity']]
|
||
|
|
||
|
elif concept == 'extras' and ~name_concept.startswith('r'):
|
||
|
res[key]['overtime_hours'] += [line['quantity']]
|
||
|
|
||
|
elif concept == 'transport':
|
||
|
res[key]['certifiable_non_benefits'] += [amount]
|
||
|
|
||
|
elif concept == 'salary':
|
||
|
res[key]['worked_day'] += [line['quantity']/8 if wage['uom.']['symbol'] != 'd' else line['quantity']]
|
||
|
|
||
|
if salary_constitute and name_concept[:3] not in basic_benefit_exc \
|
||
|
and definition == 'payment':
|
||
|
res[key]['basic_benefits'] += [amount]
|
||
|
|
||
|
if concept != 'transport':
|
||
|
res[key]['vacations_base'] += [amount]
|
||
|
|
||
|
if salary_constitute and definition == 'payment' and concept not in ('bonus_service', 'interest', 'unemployment'):
|
||
|
res[key]['tax_basis'] += [amount]
|
||
|
if concept != 'holidays':
|
||
|
res[key]['paid_salary'] += [amount]
|
||
|
|
||
|
|
||
|
if not salary_constitute and wage['receipt'] and definition == 'payment':
|
||
|
res[key]['other_payments'] += [amount]
|
||
|
res[key]['certifiable_non_benefits'] += [amount]
|
||
|
|
||
|
if type_line == 'liquidation':
|
||
|
if concept in ('unemployment', 'interest'):
|
||
|
res[key]['bonus_and_interest'] += [amount]
|
||
|
|
||
|
if line['liquidation.']['kind'] != 'contract':
|
||
|
res[key]['bonus_paid_fund'] += [amount]
|
||
|
|
||
|
if concept in ('bonus_service', 'unemployment', 'interest', 'holidays'):
|
||
|
res[key]['social_benefits'] += [amount]
|
||
|
|
||
|
|
||
|
@classmethod
|
||
|
def process_records(cls, records):
|
||
|
vals = ['id_number', 'contract', 'salary', 'ibc', 'company_id']
|
||
|
for rec in records.values():
|
||
|
for k, v in rec.items():
|
||
|
if k not in vals:
|
||
|
try:
|
||
|
rec[k] = sum(v)
|
||
|
except:
|
||
|
print(v)
|