You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

233 lines
10 KiB

# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from datetime import datetime
from odoo import api, fields, models
from odoo.exceptions import ValidationError
class LabourSupply(models.Model):
""" Class to create contract for labour supply """
_name = "labour.supply"
_description = "Contract creation"
_inherit = ['mail.thread', 'mail.activity.mixin']
_rec_name = 'sequence_number'
sequence_number = fields.Char(string="Sequence Number", readonly=True,
copy=False, default="New",
help="Field to specify sequence number")
customer_id = fields.Many2one('res.partner', string="Customer",
help="Field to choose customer",
required=True)
skill_ids = fields.One2many('labour.on.skill',
'labour_supply_id',
string="Skills Required", required=True,
help="Field to choose skill and number "
"required")
company_id = fields.Many2one('res.company', string='Company',
required=True,
default=lambda self: self.env.company)
from_date = fields.Date(string="From Date", tracking=True,
help="Field to choose from date")
to_date = fields.Date(string="To Date", tracking=True,
help="Field to choose to date")
state = fields.Selection([('draft', 'Draft'), ('ready', 'Ready'),
('confirmed', 'Confirmed'),
('invoiced', 'Invoiced'),
('canceled', 'Canceled'),
('expired', 'Expired')],
string="State", default="draft", tracking=True,
help="Field to specify state")
workers_ids = fields.Many2many('workers.details',
string="Select Workers",
readonly=True,
help="Field to choose workers")
total_amount = fields.Monetary(tracking=True, readonly=True,
string="Total Amount", help="Total amount")
currency_id = fields.Many2one('res.currency',
string='Currency', help="Currency",
related='company_id.currency_id')
period = fields.Integer(string="Period", help="The period of contract")
invoice_id = fields.Many2one('account.move', string="Invoice",
help="The invoice of contract")
is_alert = fields.Boolean(string="Alert",
help="Boolean field to control the visibility "
"of alert visibility")
view_workers_page = fields.Boolean(default=False, string="View Worker Page",
help="Field to control the"
" visibility of workers page ")
@api.model
def create(self, vals):
"""
Summary:
function return sequence number for record
Args:
vals:To store the sequence created
return:
result:return sequence created
"""
vals['sequence_number'] = self.env['ir.sequence'].next_by_code(
'labour.supply') or 'New'
return super(LabourSupply, self).create(vals)
def cron_change_state(self):
"""
Summary: function changes the state of worker when the worker have
ongoing work and also change the state when the contact expire.
"""
labour_supplies = self.env['labour.supply'].search(
[('state', 'not in', ['draft', 'cancel'])])
for labour_supply in labour_supplies:
if labour_supply.to_date < fields.Date.today():
labour_supply.write({'state': 'expired'})
for worker in labour_supply.workers_ids:
worker.write({'state': 'available'})
labours_supplies = self.env['labour.supply'].search(
[('state', '=', 'invoiced')])
for contract in labours_supplies:
if contract.from_date == fields.Date.today():
for labour in contract.workers_ids:
labour.write({'state': 'not_available'})
def action_confirm(self):
"""
Summary: function confirm the record state
"""
self.write({'state': 'confirmed'})
def action_draft(self):
"""
Summary: function change the record state to draft
"""
self.total_amount = 0
self.workers_ids = False
self.view_workers_page = False
self.is_alert = False
self.state = 'draft'
def action_cancel(self):
"""
summary: function change the record state to cancelled
"""
for worker in self.workers_ids:
worker.write({'state': 'available'})
self.write({'state': 'canceled'})
def action_create_invoice(self):
"""
summary: function change the record state to invoice, create invoice on
the basis of total amount and return invoice
"""
if self.from_date == fields.Date.today():
for worker in self.workers_ids:
worker.write({'state': 'not_available'})
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': self.customer_id.id,
'currency_id': self.currency_id.id,
'invoice_date': self.to_date,
'invoice_origin': self.sequence_number,
'invoice_line_ids': [(0, 0, {
'name': "contract cost",
'quantity': 1,
'price_unit': self.total_amount,
})],
})
self.invoice_id = invoice.id
self.write({'state': 'invoiced'})
return {
'name': 'create_invoice',
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_id': invoice.id,
'res_model': 'account.move',
'target': 'current'
}
def action_labour_supply_invoices(self):
"""
Summary: function returns invoice for current record
return: returns invoices created
"""
return {
'name': 'Create Invoice',
'type': 'ir.actions.act_window',
'view_mode': 'tree,form',
'res_model': 'account.move',
'domain': [('invoice_origin', '=', self.sequence_number)]
}
def action_fetch(self):
"""
Summary: function change the record state to Ready, calculate total
amount according workers assigned also calculate the total from date and
to date.
"""
self.workers_ids = False
self.total_amount = 0
if self.skill_ids:
date_list = []
for skill in self.skill_ids:
if skill.from_date < fields.Date.today() or \
skill.to_date < fields.Date.today():
raise ValidationError("Enter valid date ")
if skill.to_date < skill.from_date:
raise ValidationError("Invalid start date and end date ")
labour_not_available = self.env['labour.supply'].search(
[('state', '=', "invoiced"),
('from_date', '<', fields.Date.today())
, ('to_date', '>', fields.Date.today())]).mapped(
'workers_ids.id')
labours_selected = []
for skill in self.skill_ids:
count = 0
date_list.append(skill.from_date)
date_list.append(skill.to_date)
worker_details = self.env['workers.details'].search([])
labour_available = worker_details.search(
[('skill_ids', '=', skill.skill_id.id),
('state', '=', 'available'),
('id', 'not in', labours_selected),
('id', 'not in', labour_not_available)]).mapped('id')
labours_selected = labours_selected + labour_available
if len(labour_available) < skill.number_of_labour_required:
self.is_alert = True
for worker in worker_details:
if worker.id in labour_available:
if count < skill.number_of_labour_required:
count = count + 1
self.write({'workers_ids': [(4, worker.id,)]})
date_start = datetime.strptime(str(skill.from_date),
'%Y-%m-%d')
date_end = datetime.strptime(str(skill.to_date),
'%Y-%m-%d')
period = date_end - date_start
self.period = int(str(period.days))
self.total_amount = self.total_amount + (
worker.rate * (self.period + 1))
date_list = sorted(date_list)
self.from_date = date_list[0]
self.to_date = date_list[-1]
self.view_workers_page = True
self.state = 'ready'
else:
raise ValidationError("Enter Skill Required")