Browse Source

[ADD] Initial Commit

pull/29/head
SHEREEF PT 8 years ago
parent
commit
45e8bb29ae
  1. 40
      payroll_timesheet/README.md
  2. 3
      payroll_timesheet/__init__.py
  3. 30
      payroll_timesheet/__manifest__.py
  4. 13
      payroll_timesheet/data/data.xml
  5. 3
      payroll_timesheet/models/__init__.py
  6. 126
      payroll_timesheet/models/models.py
  7. 2
      payroll_timesheet/security/ir.model.access.csv
  8. BIN
      payroll_timesheet/static/description/banner.jpg
  9. BIN
      payroll_timesheet/static/description/contract.png
  10. BIN
      payroll_timesheet/static/description/cybro_logo.png
  11. BIN
      payroll_timesheet/static/description/icon.png
  12. 171
      payroll_timesheet/static/description/index.html
  13. BIN
      payroll_timesheet/static/description/payslip1.png
  14. BIN
      payroll_timesheet/static/description/payslip2.png
  15. BIN
      payroll_timesheet/static/description/payslip3.png
  16. BIN
      payroll_timesheet/static/description/report1.png
  17. BIN
      payroll_timesheet/static/description/report2.png
  18. BIN
      payroll_timesheet/static/description/rule.png
  19. BIN
      payroll_timesheet/static/description/structure.png
  20. 39
      payroll_timesheet/views/views.xml

40
payroll_timesheet/README.md

@ -0,0 +1,40 @@
# Timesheet Based Payroll
Payroll based on Timesheet hours. While computing payroll the approved total sheet hours submitted by
employees are calculated. This addon creates a rule of category BASIC for hour based calculations. So while creating
salary structure for timesheet based payroll we have to select the rule there.
- Flag which enables the contract as timesheet based.
- Flag which enables the salary structure for timesheet based.
- Timesheet hours and total hours on payslip view.
- Salary Rule for timesheet based calculations.
### Depends
Timesheet Based Payroll depends on hr, hr_timesheet_sheet, hr_timesheet_attendance,hr_payroll
### Tech
* [Python] - Models
* [XML] - Odoo views
### Installation
- www.odoo.com/documentation/10.0/setup/install.html
- Install our custom addon, which also installs its depends [hr, hr_payroll, hr_timesheet_sheet, hr_timesheet_attendance]
### Usage
> Enable Timesheet Based Payroll on contract.
> Enable Timesheet Based structure on salary structure.
> Select Hourly Pay (Timesheet) rule while creating salary structure.
> payslip will display total hours and total timesheet hours,
if the employee contract is enabled Timesheet Based Payroll
License
----
GNU LESSER GENERAL PUBLIC LICENSE, Version 3 (LGPLv3)
(http://www.gnu.org/licenses/agpl.html)

3
payroll_timesheet/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import models

30
payroll_timesheet/__manifest__.py

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
{
'name': "TimeSheet Based Payroll",
'version': "10.0.1.0.0",
'summary': """
Payrolls Are Computed According to the Submitted & Confirmed Timesheets By Employees.""",
'description': """
Payrolls are computed according to the submitted and confirmed Timesheets By employees.
""",
'author': "Cybrosys Techno Solutions",
'company': "Cybrosys Techno Solutions",
'website': "https://cybrosys.com/",
'category': "Generic Modules/Human Resources",
'depends': [
"base",
"hr_payroll",
"hr_timesheet_sheet",
"hr_timesheet_attendance",
],
'data': [
'data/data.xml',
'views/views.xml',
],
'demo': [],
'images': ['static/description/banner.jpg'],
'license': "LGPL-3",
'installable': True,
'application': True
}

13
payroll_timesheet/data/data.xml

@ -0,0 +1,13 @@
<odoo>
<data noupdate="1">
<record id="timesheet_salary_rule" model="hr.salary.rule">
<field name="name">Hourly Pay (Timesheet)</field>
<field name="category_id" ref="hr_payroll.BASIC"/>
<field name="code">HT</field>
<field name="sequence" eval="1"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (contract.wage/payslip.total_hours)*payslip.timesheet_hours if payslip.total_hours else 0.0</field>
</record>
</data>
</odoo>

3
payroll_timesheet/models/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import models

126
payroll_timesheet/models/models.py

@ -0,0 +1,126 @@
# -*- coding: utf-8 -*-
import itertools
from odoo import models, fields, api
class PayrollStructure(models.Model):
_inherit = 'hr.payroll.structure'
timesheet_structure = fields.Boolean(string='Timesheet Based Structure', default=False,
help='Flag Which says the Structure is based on Timesheets submitted by employee')
class HrContract(models.Model):
_inherit = 'hr.contract'
timesheet_payroll = fields.Boolean(string='Timesheet Based Payroll', default=False,
help='Flag Which says the payroll is based on Timesheets submitted by employee')
@api.onchange('timesheet_payroll')
def onchange_timesheet_payroll(self):
if self.timesheet_payroll:
self.struct_id = False
return {
'domain': {
'struct_id': [('timesheet_structure', '=', True)]
},
}
else:
return {
'domain': {'struct_id': []},
}
class HrPayslip(models.Model):
_inherit = 'hr.payslip'
timesheet_hours = fields.Integer(string='Timesheet Hours', states={'done': [('readonly', True)]},
help='Total Timesheet hours approved for employee.')
total_hours = fields.Integer(string='Total Hours', states={'done': [('readonly', True)]},
help='Total Hours By Working schedule')
timesheet_payroll = fields.Boolean(related='contract_id.timesheet_payroll')
def compute_timesheet_hours(self, contract_id, date_from, date_to):
"""
Function which computes total hours, timesheethours, attendances, timehseet difference,
:param employee_id:
:param date_from:
:param date_to:
:return: computed total timesheet hours within duration, total hours by working schedule
"""
if not contract_id:
return {}
env = self.env
employee_id = contract_id.employee_id
timesheet_object = env['hr_timesheet_sheet.sheet']
total_hours = 0.0
timesheet_hours = timesheet_attendance = timesheet_difference = 0.0
for line in self.worked_days_line_ids:
total_hours += line.number_of_hours if line.code == 'WORK100' else 0.0
sheets = timesheet_object.search([
('employee_id', '=', employee_id.id),
('date_from', '>=', date_from),
('date_to', '<=', date_to),
('state', '=', 'done')
])
period_ids = []
period_ids += [sheet.period_ids.ids for sheet in sheets]
period_ids = list(itertools.chain.from_iterable(period_ids))
if len(period_ids):
self.env.cr.execute("""
SELECT
sum(total_attendance) as total_attendance,
sum(total_timesheet) as total_timesheet,
sum(total_difference) as total_difference
FROM hr_timesheet_sheet_sheet_day
WHERE id IN %s
""", (tuple(period_ids),))
data = self.env.cr.dictfetchall()
for x in data:
timesheet_hours = x.pop('total_timesheet')
timesheet_attendance = x.pop('total_attendance')
timesheet_difference = x.pop('total_difference')
return {
'timesheet_hours': timesheet_hours,
'timesheet_attendance': timesheet_attendance,
'timesheet_difference': timesheet_difference,
'total_hours': total_hours,
}
@api.onchange('employee_id', 'date_from')
def onchange_employee(self):
super(HrPayslip, self).onchange_employee()
if self.contract_id.timesheet_payroll:
datas = self.compute_timesheet_hours(self.contract_id, self.date_from, self.date_to)
self.timesheet_hours = datas.get('timesheet_hours') or 0.0
self.total_hours = datas.get('total_hours') or 0.0
return
@api.model
def get_payslip_lines(self, contract_ids, payslip_id):
class BrowsableObject(object):
def __init__(self, employee_id, dict):
self.employee_id = employee_id
self.dict = dict
def __getattr__(self, attr):
return attr in self.dict and self.dict.__getitem__(attr) or 0.0
class Payslips(BrowsableObject):
"""a class that will be used into the python code, mainly for usability purposes"""
def sum(self, code, from_date, to_date=None):
if to_date is None:
to_date = fields.Date.today()
self.env.cr.execute("""SELECT sum(case when hp.credit_note = False then (pl.total) else (-pl.total) end)
FROM hr_payslip as hp, hr_payslip_line as pl
WHERE hp.employee_id = %s AND hp.state = 'done'
AND hp.date_from >= %s AND hp.date_to <= %s AND hp.id = pl.slip_id AND pl.code = %s""",
(self.employee_id, from_date, to_date, code))
res = self.env.cr.fetchone()
return res and res[0] or 0.0
timesheet_hours = self.timesheet_hours
total_hours = self.total_hours
return super(HrPayslip, self).get_payslip_lines(contract_ids, payslip_id)

2
payroll_timesheet/security/ir.model.access.csv

@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_payroll_timesheet_payroll_timesheet,payroll_timesheet.payroll_timesheet,model_payroll_timesheet_payroll_timesheet,,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_payroll_timesheet_payroll_timesheet payroll_timesheet.payroll_timesheet model_payroll_timesheet_payroll_timesheet 1 0 0 0

BIN
payroll_timesheet/static/description/banner.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

BIN
payroll_timesheet/static/description/contract.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
payroll_timesheet/static/description/cybro_logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
payroll_timesheet/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

171
payroll_timesheet/static/description/index.html

@ -0,0 +1,171 @@
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Timesheet Based Payroll</h2>
<h4 class="oe_slogan"><a href="https://www.cybrosys.com">Cybrosys Technologies</a></h4>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan" style="color:#875A7B;">Payroll based on Timesheet hours. </h2>
<h3 class="oe_slogan">
While creating payroll the approved total sheet hours submitted by
employees are calculated.
</h3>
</div>
<div class="oe_container oe_dark">
<div class="row mt32 o_animate o_animate_in_children o_animate_offset_min"
style="animation-name: none; visibility: hidden; animation-play-state: paused;">
<div class="col-md-5 col-md-offset-1" style="transition-delay: 0ms;">
<h2 class=" mt32 mb16"><b>Specifies Timesheet based Contract</b></h2>
</div>
<div class="col-md-6" style="transition-delay: 500ms;">
<div class=" oe_demo oe_picture oe_screenshot">
<img style="max-width: 100%;-moz-transform: scale(1.2);-webkit-transform: scale(1.2); -o-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2);"
src="contract.png">
</div>
</div>
</div>
</div>
<div class="oe_container">
<div class="row mt32 o_animate o_animate_in_children o_animate_offset_min"
style="animation-name: none; visibility: hidden; animation-play-state: paused;">
<div class="col-md-5 col-md-offset-1" style="transition-delay: 0ms;">
<h2 class=" mt32 mb16"><b>Timesheet Based Salary Structure</b></h2>
</div>
<div class="col-md-6" style="transition-delay: 500ms;">
<div class=" oe_demo oe_picture oe_screenshot">
<img style="max-width: 100%;-moz-transform: scale(1.2);-webkit-transform: scale(1.2); -o-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2);"
src="structure.png">
</div>
</div>
</div>
</div>
<div class="oe_container oe_dark">
<div class="row mt32 o_animate o_animate_in_children o_animate_offset_min"
style="animation-name: none; visibility: hidden; animation-play-state: paused;">
<div class="col-md-5 col-md-offset-1" style="transition-delay: 0ms;">
<h2 class=" mt32 mb16"><b>Salary Rule & calculations for Timesheet Based Payroll.</b></h2>
</div>
<div class="col-md-6" style="transition-delay: 500ms;">
<div class=" oe_demo oe_picture oe_screenshot">
<img style="max-width: 100%;-moz-transform: scale(1.2);-webkit-transform: scale(1.2); -o-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2);"
src="rule.png">
</div>
</div>
</div>
</div>
<div class="oe_container">
<div class="row mt32 o_animate o_animate_in_children o_animate_offset_min"
style="animation-name: none; visibility: hidden; animation-play-state: paused;">
<div class="col-md-5 col-md-offset-1" style="transition-delay: 0ms;">
<h2 class=" mt32 mb16"><b>Total Timesheet hours on payslip.</b></h2>
</div>
<div class="col-md-6" style="transition-delay: 500ms;">
<div class=" oe_demo oe_picture oe_screenshot">
<img style="max-width: 100%;-moz-transform: scale(1.2);-webkit-transform: scale(1.2); -o-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2);"
src="payslip1.png">
</div>
</div>
</div>
</div>
<div class="oe_container oe_dark">
<div class="row mt32 o_animate o_animate_in_children o_animate_offset_min"
style="animation-name: none; visibility: hidden; animation-play-state: paused;">
<div class="col-md-5 col-md-offset-1" style="transition-delay: 0ms;">
<h2 class=" mt32 mb16"><b>Computation as per Timesheet Hour based rule.</b></h2>
</div>
<div class="col-md-6" style="transition-delay: 500ms;">
<div class=" oe_demo oe_picture oe_screenshot">
<img style="max-width: 100%;-moz-transform: scale(1.2);-webkit-transform: scale(1.2); -o-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2);"
src="payslip2.png">
</div>
</div>
</div>
</div>
<div class="oe_container">
<div class="row mt32 o_animate o_animate_in_children o_animate_offset_min"
style="animation-name: none; visibility: hidden; animation-play-state: paused;">
<div class="col-md-5 col-md-offset-1" style="transition-delay: 0ms;">
<h2 class=" mt32 mb16"><b>Details as per salary rule category.</b></h2>
</div>
<div class="col-md-6" style="transition-delay: 500ms;">
<div class=" oe_demo oe_picture oe_screenshot">
<img style="max-width: 100%;-moz-transform: scale(1.2);-webkit-transform: scale(1.2); -o-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2);"
src="payslip2.png">
</div>
</div>
</div>
</div>
<div class="oe_container oe_dark">
<div class="row mt32 o_animate o_animate_in_children o_animate_offset_min"
style="animation-name: none; visibility: hidden; animation-play-state: paused;">
<div class="col-md-5 col-md-offset-1" style="transition-delay: 0ms;">
<h2 class=" mt32 mb16"><b>Payslip Report.</b></h2>
</div>
<div class="col-md-6" style="transition-delay: 500ms;">
<div class=" oe_demo oe_picture oe_screenshot">
<img style="max-width: 100%;-moz-transform: scale(1.2);-webkit-transform: scale(1.2); -o-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2);"
src="report1.png">
</div>
</div>
</div>
</div>
<div class="oe_container oe_dark">
<div class="row mt32 o_animate o_animate_in_children o_animate_offset_min"
style="animation-name: none; visibility: hidden; animation-play-state: paused;">
<div class="col-md-5 col-md-offset-1" style="transition-delay: 0ms;">
<h2 class=" mt32 mb16"><b>Payslip Report With Details.</b></h2>
</div>
<div class="col-md-6" style="transition-delay: 500ms;">
<div class=" oe_demo oe_picture oe_screenshot">
<img style="max-width: 100%;-moz-transform: scale(1.2);-webkit-transform: scale(1.2); -o-transform: scale(1.2); -ms-transform: scale(1.2); transform: scale(1.2);"
src="report2.png">
</div>
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<h2 class="oe_slogan" style="margin-top:20px;" >Need Any Help?</h2>
<div class="oe_slogan" style="margin-top:10px !important;">
<div>
<a class="btn btn-primary btn-lg mt8"
style="color: #FFFFFF !important;border-radius: 0;" href="https://www.cybrosys.com"><i
class="fa fa-envelope"></i> Email </a> <a
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;"
href="https://www.cybrosys.com/contact/"><i
class="fa fa-phone"></i> Contact Us </a> <a
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;"
href="https://www.cybrosys.com/odoo-customization-and-installation/"><i
class="fa fa-check-square"></i> Request Customization </a>
</div>
<br>
<img src="cybro_logo.png" style="width: 190px; margin-bottom: 20px;" class="center-block">
<div>
<a href="https://twitter.com/cybrosys" target="_blank"><i class="fa fa-2x fa-twitter" style="color:white;background: #00a0d1;width:35px;"></i></a></td>
<a href="https://www.linkedin.com/company/cybrosys-technologies-pvt-ltd" target="_blank"><i class="fa fa-2x fa-linkedin" style="color:white;background: #31a3d6;width:35px;padding-left: 3px;"></i></a></td>
<a href="https://www.facebook.com/cybrosystechnologies" target="_blank"><i class="fa fa-2x fa-facebook" style="color:white;background: #3b5998;width:35px;padding-left: 8px;"></i></a></td>
<a href="https://plus.google.com/106641282743045431892/about" target="_blank"><i class="fa fa-2x fa-google-plus" style="color:white;background: #c53c2c;width:35px;padding-left: 3px;"></i></a></td>
<a href="https://in.pinterest.com/cybrosys" target="_blank"><i class="fa fa-2x fa-pinterest" style="color:white;background: #ac0f18;width:35px;padding-left: 3px;"></i></a></td>
</div>
</div>
</section>

BIN
payroll_timesheet/static/description/payslip1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
payroll_timesheet/static/description/payslip2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

BIN
payroll_timesheet/static/description/payslip3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
payroll_timesheet/static/description/report1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
payroll_timesheet/static/description/report2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
payroll_timesheet/static/description/rule.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
payroll_timesheet/static/description/structure.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

39
payroll_timesheet/views/views.xml

@ -0,0 +1,39 @@
<openerp>
<data>
<record id="view_hr_employee_grade_form_extend" model="ir.ui.view">
<field name="name">Timesheet Based Structure</field>
<field name="model">hr.payroll.structure</field>
<field name="inherit_id" ref="hr_payroll.view_hr_employee_grade_form"/>
<field name="arch" type="xml">
<field name="code" position="after">
<field name="timesheet_structure"/>
</field>
</field>
</record>
<record id="hr_contract_view_form_extend" model="ir.ui.view">
<field name="name">Timesheet Based Payroll</field>
<field name="model">hr.contract</field>
<field name="inherit_id" ref="hr_contract.hr_contract_view_form"/>
<field name="arch" type="xml">
<field name="struct_id" position="after">
<field name="timesheet_payroll"/>
</field>
</field>
</record>
<record id="view_hr_payslip_form_extend" model="ir.ui.view">
<field name="name">Timesheet View on Payroll</field>
<field name="model">hr.payslip</field>
<field name="inherit_id" ref="hr_payroll.view_hr_payslip_form"/>
<field name="arch" type="xml">
<field name="name" position="after">
<field name="timesheet_payroll" invisible="1"/>
<field name="timesheet_hours"
attrs="{'invisible': [('timesheet_payroll', '=', False)]}"/>
<field name="total_hours"
attrs="{'invisible': [('timesheet_payroll', '=', False)]}"/>
</field>
</field>
</record>
</data>
</openerp>
Loading…
Cancel
Save