Skip to content

Commit

Permalink
[IMP] hr_expense_advance_clearing: black, isort, prettier
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigonevest committed Nov 9, 2023
1 parent f62b159 commit ded2950
Show file tree
Hide file tree
Showing 10 changed files with 333 additions and 228 deletions.
27 changes: 13 additions & 14 deletions hr_expense_advance_clearing/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
'name': 'Employee Advance and Clearing',
'version': '12.0.1.3.0',
'category': 'Human Resources',
'author': 'Ecosoft, '
'Odoo Community Association (OCA)',
'license': 'AGPL-3',
'website': 'https://github.com/OCA/hr',
'depends': [
'hr_expense',
"name": "Employee Advance and Clearing",
"version": "12.0.1.3.0",
"category": "Human Resources",
"author": "Ecosoft, " "Odoo Community Association (OCA)",
"license": "AGPL-3",
"website": "https://github.com/OCA/hr",
"depends": [
"hr_expense",
],
'data': [
'data/advance_product.xml',
'views/hr_expense_views.xml',
"data": [
"data/advance_product.xml",
"views/hr_expense_views.xml",
],
'installable': True,
'maintainers': ['kittiu'],
"installable": True,
"maintainers": ["kittiu"],
}
8 changes: 4 additions & 4 deletions hr_expense_advance_clearing/data/advance_product.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<odoo noupdate="1">
<record id="product_emp_advance" model="product.product">
<field name="name">Employee Advance</field>
<field name="default_code"></field>
<field name="default_code" />
<field name="type">service</field>
<field name="sale_ok" eval="False"/>
<field name="purchase_ok" eval="False"/>
<field name="can_be_expensed" eval="False"/>
<field name="sale_ok" eval="False" />
<field name="purchase_ok" eval="False" />
<field name="can_be_expensed" eval="False" />
<field name="supplier_taxes_id">False</field>
<field name="taxes_id">False</field>
</record>
Expand Down
9 changes: 4 additions & 5 deletions hr_expense_advance_clearing/models/account_payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@


class AccountPayment(models.Model):
_inherit = 'account.payment'
_inherit = "account.payment"

def _get_counterpart_move_line_vals(self, invoice=False):
emp_advance = self.env.ref('hr_expense_advance_clearing.'
'product_emp_advance')
emp_advance = self.env.ref("hr_expense_advance_clearing." "product_emp_advance")
res = super()._get_counterpart_move_line_vals(invoice=invoice)
if self._context.get('hr_return_advance', False):
res['account_id'] = emp_advance.property_account_expense_id.id
if self._context.get("hr_return_advance", False):
res["account_id"] = emp_advance.property_account_expense_id.id
return res
56 changes: 29 additions & 27 deletions hr_expense_advance_clearing/models/hr_expense.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,83 @@
# Copyright 2019 Kitti Upariphutthiphong <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import api, fields, models, _
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError


class HrExpense(models.Model):
_inherit = 'hr.expense'
_inherit = "hr.expense"

advance = fields.Boolean(
string='Employee Advance',
string="Employee Advance",
default=False,
)

@api.multi
@api.constrains('advance')
@api.constrains("advance")
def _check_advance(self):
for expense in self.filtered('advance'):
emp_advance = self.env.ref('hr_expense_advance_clearing.'
'product_emp_advance')
for expense in self.filtered("advance"):
emp_advance = self.env.ref(
"hr_expense_advance_clearing." "product_emp_advance"
)
if not emp_advance.property_account_expense_id:
raise ValidationError(
_('Employee advance product has no payable account'))
_("Employee advance product has no payable account")
)
if expense.product_id != emp_advance:
raise ValidationError(
_('Employee advance, selected product is not valid'))
_("Employee advance, selected product is not valid")
)
if expense.tax_ids:
raise ValidationError(
_('Employee advance, all taxes must be removed'))
if expense.payment_mode != 'own_account':
raise ValidationError(
_('Employee advance, paid by must be employee'))
raise ValidationError(_("Employee advance, all taxes must be removed"))
if expense.payment_mode != "own_account":
raise ValidationError(_("Employee advance, paid by must be employee"))
return True

@api.onchange('advance')
@api.onchange("advance")
def onchange_advance(self):
self.tax_ids = False
self.payment_mode = 'own_account'
self.payment_mode = "own_account"
if self.advance:
self.product_id = self.env.ref(
'hr_expense_advance_clearing.product_emp_advance')
"hr_expense_advance_clearing.product_emp_advance"
)
else:
self.product_id = False

@api.multi
def _get_account_move_line_values(self):
move_line_values_by_expense = super()._get_account_move_line_values()
# Only when do the clearing, change cr payable to cr advance
emp_advance = self.env.ref('hr_expense_advance_clearing.'
'product_emp_advance')
sheets = self.mapped('sheet_id').filtered('advance_sheet_id')
emp_advance = self.env.ref("hr_expense_advance_clearing." "product_emp_advance")
sheets = self.mapped("sheet_id").filtered("advance_sheet_id")
sheets_x = sheets.filtered(lambda x: x.advance_sheet_residual <= 0.0)
if sheets_x: # Advance Sheets with no clearing residual left
raise ValidationError(_('Advance: %s has no amount to clear') %
', '.join(sheets_x.mapped('name')))
raise ValidationError(
_("Advance: %s has no amount to clear")
% ", ".join(sheets_x.mapped("name"))
)
for sheet in sheets:
advance_to_clear = sheet.advance_sheet_residual
for expense_id, move_lines in move_line_values_by_expense.items():
payable_move_line = False
for move_line in move_lines:
credit = move_line['credit']
credit = move_line["credit"]
if not credit:
continue
# cr payable -> cr advance
remain_payable = 0.0
if credit > advance_to_clear:
remain_payable = credit - advance_to_clear
move_line['credit'] = advance_to_clear
move_line["credit"] = advance_to_clear
advance_to_clear = 0.0
# extra payable line
payable_move_line = move_line.copy()
payable_move_line['credit'] = remain_payable
payable_move_line["credit"] = remain_payable
else:
advance_to_clear -= credit
# advance line
move_line['account_id'] = \
emp_advance.property_account_expense_id.id
move_line["account_id"] = emp_advance.property_account_expense_id.id
if payable_move_line:
move_lines.append(payable_move_line)
return move_line_values_by_expense
100 changes: 56 additions & 44 deletions hr_expense_advance_clearing/models/hr_expense_sheet.py
Original file line number Diff line number Diff line change
@@ -1,74 +1,81 @@
# Copyright 2019 Kitti Upariphutthiphong <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import api, models, fields, _
from odoo.tools.safe_eval import safe_eval
from odoo.tools import pycompat
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.tools import pycompat
from odoo.tools.safe_eval import safe_eval


class HrExpenseSheet(models.Model):
_inherit = 'hr.expense.sheet'
_inherit = "hr.expense.sheet"

advance = fields.Boolean(
string='Employee Advance',
compute='_compute_advance',
string="Employee Advance",
compute="_compute_advance",
store=True,
)
advance_sheet_id = fields.Many2one(
comodel_name='hr.expense.sheet',
string='Clear Advance',
comodel_name="hr.expense.sheet",
string="Clear Advance",
domain="[('advance', '=', True), ('employee_id', '=', employee_id),"
" ('clearing_residual', '>', 0.0)]",
" ('clearing_residual', '>', 0.0)]",
readonly=True,
states={'draft': [('readonly', False)],
'submit': [('readonly', False)],
'approve': [('readonly', False)]},
states={
"draft": [("readonly", False)],
"submit": [("readonly", False)],
"approve": [("readonly", False)],
},
help="Show remaining advance of this employee",
)
clearing_residual = fields.Monetary(
string='Amount to clear',
compute='_compute_clearing_residual',
string="Amount to clear",
compute="_compute_clearing_residual",
store=True,
help="Amount to clear of this expense sheet in company currency",
)
advance_sheet_residual = fields.Monetary(
string='Advance Remaining',
related='advance_sheet_id.clearing_residual',
string="Advance Remaining",
related="advance_sheet_id.clearing_residual",
store=True,
help="Remaining amount to clear the selected advance sheet",
)
amount_payable = fields.Monetary(
string='Payable Amount',
compute='_compute_amount_payable',
string="Payable Amount",
compute="_compute_amount_payable",
help="Final regiter payment amount even after advance clearing",
)

@api.multi
@api.depends('expense_line_ids')
@api.depends("expense_line_ids")
def _compute_advance(self):
for sheet in self:
sheet.advance = bool(sheet.expense_line_ids.filtered('advance') and
len(sheet.expense_line_ids) == 1)
sheet.advance = bool(
sheet.expense_line_ids.filtered("advance")
and len(sheet.expense_line_ids) == 1
)
return

@api.one
@api.constrains('advance_sheet_id', 'expense_line_ids')
@api.constrains("advance_sheet_id", "expense_line_ids")
def _check_advance_expense(self):
advance_lines = self.expense_line_ids.filtered('advance')
advance_lines = self.expense_line_ids.filtered("advance")
if self.advance_sheet_id and advance_lines:
raise ValidationError(_('Advance clearing must not contain any '
'advance expense line'))
raise ValidationError(
_("Advance clearing must not contain any " "advance expense line")
)
if advance_lines and len(self.expense_line_ids) != 1:
raise ValidationError(_('Advance must contain only 1 '
'advance expense line'))
raise ValidationError(
_("Advance must contain only 1 " "advance expense line")
)

@api.one
@api.depends('account_move_id.line_ids.amount_residual')
@api.depends("account_move_id.line_ids.amount_residual")
def _compute_clearing_residual(self):
residual_company = 0.0
emp_advance = self.env.ref('hr_expense_advance_clearing.'
'product_emp_advance', False)
emp_advance = self.env.ref(
"hr_expense_advance_clearing." "product_emp_advance", False
)
if emp_advance:
for line in self.sudo().account_move_id.line_ids:
if line.account_id == emp_advance.property_account_expense_id:
Expand All @@ -79,34 +86,39 @@ def _compute_clearing_residual(self):
def _compute_amount_payable(self):
for sheet in self:
rec_lines = sheet.account_move_id.line_ids.filtered(
lambda x:
x.credit and x.account_id.reconcile and not x.reconciled)
sheet.amount_payable = -sum(rec_lines.mapped('amount_residual'))
lambda x: x.credit and x.account_id.reconcile and not x.reconciled
)
sheet.amount_payable = -sum(rec_lines.mapped("amount_residual"))

@api.multi
def action_sheet_move_create(self):
res = super(HrExpenseSheet, self).action_sheet_move_create()
# Reconcile advance of this sheet with the advance_sheet
emp_advance = self.env.ref('hr_expense_advance_clearing.'
'product_emp_advance')
emp_advance = self.env.ref("hr_expense_advance_clearing." "product_emp_advance")
for sheet in self:
move_lines = sheet.account_move_id.line_ids | \
sheet.advance_sheet_id.account_move_id.line_ids
move_lines = (
sheet.account_move_id.line_ids
| sheet.advance_sheet_id.account_move_id.line_ids
)
account_id = emp_advance.property_account_expense_id.id
adv_move_lines = self.env['account.move.line'].sudo().search([
('id', 'in', move_lines.ids), ('account_id', '=', account_id)])
adv_move_lines = (
self.env["account.move.line"]
.sudo()
.search([("id", "in", move_lines.ids), ("account_id", "=", account_id)])
)
adv_move_lines.reconcile()
return res

@api.multi
def open_clear_advance(self):
self.ensure_one()
action = self.env.ref('hr_expense_advance_clearing.'
'action_hr_expense_sheet_advance_clearing')
action = self.env.ref(
"hr_expense_advance_clearing." "action_hr_expense_sheet_advance_clearing"
)
vals = action.read()[0]
context1 = vals.get('context', {})
context1 = vals.get("context", {})
if isinstance(context1, pycompat.string_types):
context1 = safe_eval(context1)
context1['default_advance_sheet_id'] = self.id
vals['context'] = context1
context1["default_advance_sheet_id"] = self.id
vals["context"] = context1
return vals
Loading

0 comments on commit ded2950

Please sign in to comment.