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.
243 lines
11 KiB
243 lines
11 KiB
# -*- coding: utf-8 -*-
|
|
################################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
|
|
# Author: Vishnu KP @ Cybrosys, (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 odoo import api, fields, models, _, Command
|
|
from odoo.exceptions import UserError
|
|
from datetime import date
|
|
|
|
|
|
class SaleConsignment(models.Model):
|
|
_name = "sale.consignment"
|
|
_description = "Sale Consignment"
|
|
_inherit = ['mail.activity.mixin', 'mail.thread']
|
|
|
|
"""This is the main model for the sale consignment feature"""
|
|
|
|
@api.model
|
|
def _settings_domain(self):
|
|
"""This function return the customer domain fields
|
|
value from the settings page"""
|
|
customer_domain = self.env['ir.config_parameter'].get_param(
|
|
'sale_consignment.consignment_product_only')
|
|
return customer_domain
|
|
|
|
@api.model
|
|
def _default_destination(self):
|
|
"""This function return the destination location fields
|
|
value from the settings page"""
|
|
location_dest_id = self.env['ir.config_parameter'].get_param(
|
|
'sale_consignment.location_dest_id')
|
|
return int(location_dest_id)
|
|
|
|
name = fields.Char(string='Name', help="Sequence of the consignment Sale",
|
|
default='New')
|
|
company_id = fields.Many2one('res.company',
|
|
string='Company', help='default company',
|
|
default=lambda self: self.env.user.company_id)
|
|
partner_id = fields.Many2one('res.partner', string='Customer',
|
|
help="Partner Name", required=True)
|
|
end_date = fields.Date(string='Expiry Date',
|
|
help="Expiry date of the sale consignment",
|
|
required=True)
|
|
date = fields.Date(string='Date', default=date.today(),
|
|
help="Date of the sale consignment", required=True)
|
|
price_list_id = fields.Many2one('product.pricelist', string='Price List',
|
|
help="Product price list based on the "
|
|
"customer",
|
|
compute='_compute_partner_id')
|
|
state = fields.Selection(
|
|
selection=[('draft', 'Draft'), ('confirm', 'Confirm')],
|
|
help="State of the sale consignment",
|
|
default="draft")
|
|
user_id = fields.Many2one("res.users", string='Sales Person',
|
|
help="Responsible sales person for the sale "
|
|
"consignment",
|
|
default=lambda self: self.env.user,
|
|
required=True)
|
|
consignment_line_ids = fields.One2many('sale.consignment.line',
|
|
'consignment_id',
|
|
string='Order Line')
|
|
location_id = fields.Many2one(
|
|
'stock.location', 'Source Location',
|
|
help="Location where the product you want to pickup from.",
|
|
domain="[('usage','=','internal')]",
|
|
required=True)
|
|
sale_count = fields.Integer(string='Sale Order',
|
|
help="Number of sale order related to "
|
|
"the consignment",
|
|
compute='_compute_sale_count')
|
|
picking_count = fields.Integer(string='Picking Order',
|
|
help="Number of picking order "
|
|
"related to the consignment",
|
|
compute='_compute_picking_count')
|
|
sale_order_id = fields.Many2one('sale.order', help='Related sale order',
|
|
string='Sale Order')
|
|
ware_house_id = fields.Many2one('stock.warehouse',
|
|
string='Warehouse',
|
|
related='location_id.warehouse_id',
|
|
help='Choose the Warehouse')
|
|
condition_check = fields.Char(string='Condition',
|
|
compute='_compute_condition_check',
|
|
help="To check whether the consignment "
|
|
"is enable or not")
|
|
customer_domain = fields.Boolean(
|
|
default=lambda self: self._settings_domain(),
|
|
help='Customer domain',
|
|
string='Customer domain')
|
|
location_dest_id = fields.Many2one(
|
|
'stock.location', 'Destination Location',
|
|
required=True,
|
|
default=lambda self: self._default_destination(),
|
|
help="Location where you want to send the product.")
|
|
|
|
@api.depends('customer_domain')
|
|
def _compute_condition_check(self):
|
|
"""Used to apply the condition into condition_check field if
|
|
customer_domain is true """
|
|
for record in self:
|
|
record.condition_check = [
|
|
('is_consignment', '=', True)] if record.customer_domain else []
|
|
|
|
@api.model
|
|
def create(self, vals):
|
|
"""Used to add the sequence"""
|
|
if vals.get('name', _('New')) == _('New'):
|
|
vals['name'] = self.env['ir.sequence'].next_by_code(
|
|
'sale.consignment') or _('New')
|
|
res = super(SaleConsignment, self).create(vals)
|
|
return res
|
|
|
|
@api.depends('consignment_line_ids')
|
|
def _compute_sale_count(self):
|
|
"""Used to calculate the number of sales count"""
|
|
for rec in self:
|
|
rec.sale_count = self.env['sale.order'].search_count([
|
|
('consignment_id', '=', rec.id)])
|
|
|
|
@api.depends('consignment_line_ids')
|
|
def _compute_picking_count(self):
|
|
"""Used to calculate the number of picking count"""
|
|
for rec in self:
|
|
rec.picking_count = self.env['stock.picking'].search_count([
|
|
('consignment_id', '=', rec.id)])
|
|
|
|
@api.depends('partner_id')
|
|
def _compute_partner_id(self):
|
|
"""Used to find the price-list based on the partner"""
|
|
self.price_list_id = self.partner_id.property_product_pricelist.id
|
|
|
|
def action_order_confirm(self):
|
|
"""Used to confirm the consignment order"""
|
|
picking_type = self.env['stock.picking.type'].search(
|
|
[('code', '=', 'internal'),
|
|
('warehouse_id', '=', self.ware_house_id.id),
|
|
('company_id', '=', self.env.company.id),
|
|
('default_location_src_id.usage', '=', 'internal'),
|
|
('default_location_dest_id.usage', '=', 'transit'),
|
|
], limit=1)
|
|
if not picking_type:
|
|
raise UserError(_(
|
|
"There is no available Operation type like destination "
|
|
"to transit location Please create and try again"))
|
|
else:
|
|
self.env['stock.picking'].create({
|
|
'location_id': self.location_id.id,
|
|
'location_dest_id': self.location_dest_id.id,
|
|
'partner_id': self.partner_id.id,
|
|
'picking_type_id': picking_type.id,
|
|
'consignment_id': self.id,
|
|
'move_ids': [
|
|
Command.create({
|
|
'name': self.name,
|
|
'product_id': line.product_id.id,
|
|
'quantity': line.demand_quantity,
|
|
'picked': True,
|
|
'location_id': self.location_id.id,
|
|
'location_dest_id': self.location_dest_id.id,
|
|
}) for line in self.consignment_line_ids]
|
|
}).action_confirm()
|
|
|
|
self.write({'state': 'confirm'})
|
|
|
|
def create_sale_order(self):
|
|
"""Used to create the related sale order for the consignment"""
|
|
self.sale_order_id = self.env['sale.order'].create({
|
|
'partner_id': self.partner_id.id,
|
|
'consignment_id': self.id,
|
|
'user_id': self.user_id.id,
|
|
'order_line': [
|
|
Command.create({
|
|
'product_id': line.product_id.id,
|
|
'product_uom': line.product_id.uom_id.id,
|
|
'product_uom_qty': 1.0,
|
|
}) for line in self.consignment_line_ids]
|
|
}).id
|
|
return {
|
|
'name': 'Sale Order',
|
|
'view_mode': 'form',
|
|
'res_id': self.sale_order_id.id,
|
|
'res_model': 'sale.order',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'current'
|
|
}
|
|
|
|
def action_view_order(self):
|
|
"""Used to view the sale order of the consignment order"""
|
|
return {
|
|
'name': 'Sale Order',
|
|
'view_mode': 'tree,form',
|
|
'domain': [('consignment_id', 'in', [rec.id for rec in self])],
|
|
'context': {'create': False},
|
|
'res_model': 'sale.order',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'current'
|
|
}
|
|
|
|
def action_view_pickings(self):
|
|
"""Used to view the picking of the consignment order"""
|
|
return {
|
|
'name': 'Picking Order',
|
|
'view_mode': 'tree,form',
|
|
'domain': [('consignment_id', 'in', [rec.id for rec in self])],
|
|
'context': {'create': False},
|
|
'res_model': 'stock.picking',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'current'
|
|
}
|
|
|
|
def mail_update_to_salesman(self):
|
|
"""this function is used to send a mail notification to salesman"""
|
|
orders = self.env['sale.consignment'].search(
|
|
[('end_date', '=', date.today())])
|
|
for rec in orders:
|
|
mail_template_id = 'sale_consignment.sale_consignment_expiry'
|
|
rendered_body = self.env['ir.qweb']._render(mail_template_id,
|
|
{'expiry': rec})
|
|
body = self.env['mail.render.mixin']._replace_local_links(
|
|
rendered_body)
|
|
self.env['mail.mail'].sudo().create({
|
|
'author_id': self.env.user.partner_id.id,
|
|
'auto_delete': True,
|
|
'body_html': body,
|
|
'email_from': self.env.user.partner_id.email,
|
|
'email_to': rec.user_id.partner_id.email,
|
|
'subject': 'Reminder: Sale Consignment Date Expired',
|
|
}).send()
|
|
|