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.
		
		
		
		
		
			
		
			
				
					
					
						
							473 lines
						
					
					
						
							21 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							473 lines
						
					
					
						
							21 KiB
						
					
					
				| # -*- coding: utf-8 -*- | |
| ################################################################################ | |
| # | |
| #    Cybrosys Technologies Pvt. Ltd. | |
| # | |
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | |
| #    Author: Cybrosys Technologies (<https://www.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/>. | |
| # | |
| ################################################################################ | |
| import itertools | |
| from odoo import api, fields, models, _ | |
| from odoo.exceptions import UserError | |
| 
 | |
| 
 | |
| class SaleOrder(models.Model): | |
|     """Inherits Sales""" | |
|     _inherit = "sale.order" | |
| 
 | |
|     is_version = fields.Boolean(string="Is Version", | |
|                                 help="For checking version or not") | |
|     version_count = fields.Integer(string="Sale Version Count", | |
|                                    compute='_compute_version_count', | |
|                                    help="Count of version created") | |
|     current_version_id = fields.Many2one("sale.order", | |
|                                          string="Current Version", | |
|                                          help="For creating versions") | |
|     version_ids = fields.One2many("sale.order", | |
|                                   string="Version", | |
|                                   inverse_name="current_version_id", | |
|                                   help="Versions created") | |
|     quotation_ref = fields.Char(string='Quotation Reference', | |
|                                 copy=False, readonly=True, tracking=True, | |
|                                 help="Quotation Reference") | |
|     state = fields.Selection( | |
|         selection_add=[('waiting_for_approval', 'Waiting For Approval'), | |
|                        ('sale',)]) | |
|     approval_user_id = fields.Many2one('res.users', | |
|                                        string='Discount Approved By', | |
|                                        help="Discount approving person.") | |
|     onhand_check = fields.Boolean(string='Enable OnHand', | |
|                                   help='To check whether it is based on' | |
|                                        ' on hand quantity') | |
|     forecast_check = fields.Boolean(string='Enable Forecast', | |
|                                     help='To check whether it is based on' | |
|                                          ' Forecast quantity') | |
|     automate_print_invoices = fields.Boolean( | |
|         string='Print Invoices', | |
|         help="Print invoices for corresponding sale orders") | |
|     signature = fields.Binary(string='Signature', | |
|                               help="Field for adding " | |
|                                    "the signature of the " | |
|                                    "sales person") | |
|     check_signature = fields.Boolean(compute='_compute_check_signature', | |
|                                      help="To check signature approval is " | |
|                                           "needed") | |
|     settings_approval = fields.Boolean(compute='_compute_settings_approval', | |
|                                      help="To check signature approval is " | |
|                                        "enabled in settings") | |
|     active = fields.Boolean(string='Active', help='Active', default=True) | |
|     user_salesperson = fields.Boolean(string="User Salesperson", | |
|                                       compute="_compute_user_salesperson", | |
|                                       help="Check if user is salesperson") | |
| 
 | |
|     @api.depends('user_salesperson') | |
|     def _compute_user_salesperson(self): | |
|         """Computes the user_salesperson field based on login user""" | |
|         for rec in self: | |
|             if rec.user_id == rec.env.user: | |
|                 rec.user_salesperson = True | |
|             else: | |
|                 rec.user_salesperson = False | |
| 
 | |
|     @api.depends('signature') | |
|     def _compute_check_signature(self): | |
|         """In this function computes the value of | |
|         the boolean field check signature | |
|         which is used to hide/unhide the validate | |
|          button in the current document""" | |
|         if self.env['ir.config_parameter'].sudo().get_param( | |
|                 'all_in_one_sales_kit.sale_document_approve'): | |
|             if self.signature: | |
|                 self.check_signature = True | |
|             else: | |
|                 self.check_signature = False | |
|         else: | |
|             self.check_signature = True | |
| 
 | |
|     def action_create_versions(self): | |
|         """For creating the versions of the sale order""" | |
|         sale_order_copy_id = self.copy() | |
|         sale_order_copy_id.is_version = True | |
|         length = len(self.version_ids) | |
|         sale_order_copy_id.name = "%s-%s" % (self.name, str(length + 1)) | |
| 
 | |
|         self.write({'version_ids': [(4, sale_order_copy_id.id)]}) | |
| 
 | |
|     @api.depends('version_ids') | |
|     def _compute_version_count(self): | |
|         """For calculating the number of versions created""" | |
|         for sale in self: | |
|             sale.version_count = len(sale.version_ids) | |
| 
 | |
|     @api.depends('partner_id') | |
|     def _compute_settings_approval(self): | |
|         """Computes the settings_approval field based on settings field.""" | |
|         for rec in self: | |
|             if rec.env['ir.config_parameter'].sudo().get_param( | |
|                     'all_in_one_sales_kit.sale_document_approve'): | |
|                 rec.settings_approval = True | |
|             else: | |
|                 rec.settings_approval = False | |
| 
 | |
|     def action_view_versions(self): | |
|         """Action for viewing versions""" | |
|         action = { | |
|             "type": "ir.actions.act_window", | |
|             "view_mode": "kanban,tree,form", | |
|             "name": _("Sale Order Versions"), | |
|             "res_model": self._name, | |
|             "domain": [('id', 'in', self.version_ids.ids)], | |
|             "target": "current", | |
|         } | |
|         return action | |
| 
 | |
|     def action_confirm(self): | |
|         """Override the confirm button of the sale order for cancelling the | |
|         other versions and making the current version main,also method for | |
|          confirming the sale order discount and sending mail for the approving | |
|          person if approval limit crossed.Super the method create to confirm | |
|           quotation, create and validate invoice""" | |
|         res = super().action_confirm() | |
|         automate_invoice = self.env[ | |
|             'ir.config_parameter'].sudo().get_param( | |
|             'automate_invoice') | |
|         automate_print_invoices = self.env[ | |
|             'ir.config_parameter'].sudo().get_param( | |
|             'automate_print_invoices') | |
|         automate_validate_invoice = self.env[ | |
|             'ir.config_parameter'].sudo().get_param( | |
|             'automate_validate_invoice') | |
|         if automate_print_invoices: | |
|             self.automate_print_invoices = True | |
|         if automate_invoice: | |
|             self._create_invoices() | |
|             if automate_validate_invoice: | |
|                 self.invoice_ids.action_post() | |
|         if not self.version_ids: | |
|             parent_sale = self.current_version_id | |
|             versions = parent_sale.mapped('version_ids').ids | |
|             if versions: | |
|                 versions.append(parent_sale.id) | |
|             for version in parent_sale.version_ids: | |
|                 if version.state == 'sale': | |
|                     # Updating the version name into main version name and | |
|                     # other versions state into cancel | |
|                     version.current_version_id.update({'is_version': True, | |
|                                                        'state': 'cancel'}) | |
|                     version.update({'version_ids': versions, | |
|                                     "name": version.current_version_id.name, | |
|                                     'is_version': False}) | |
|                 if version.state == 'draft': | |
|                     version.update({'state': 'cancel'}) | |
|         else: | |
|             if self.state == 'sale': | |
|                 for sale in self.version_ids: | |
|                     sale.update({'state': 'cancel'}) | |
|         low_qty = ["Can't confirm the sale order due to: \n"] | |
|         for rec in self.order_line: | |
|             product_restriction = self.env[ | |
|                 'ir.config_parameter'].sudo().get_param( | |
|                 'sale_stock_restrict.product_restriction') | |
|             check_stock = self.env[ | |
|                 'ir.config_parameter'].sudo().get_param( | |
|                 'sale_stock_restrict.check_stock') | |
|             if product_restriction: | |
|                 if rec.product_id.detailed_type == 'product': | |
|                     if check_stock == 'on_hand_quantity': | |
|                         if rec.product_uom_qty > rec.qty_available: | |
|                             self.onhand_check = True | |
|                             onhand_qty_list = "You have added %s units of %s" \ | |
|                                               " but you only have %s units" \ | |
|                                               " available.\n" % ( | |
|                                                   rec.product_uom_qty, | |
|                                                   rec.product_id.name, | |
|                                                   rec.qty_available) | |
|                             low_qty.append(onhand_qty_list) | |
| 
 | |
|                     if check_stock == 'forecast_quantity': | |
|                         if rec.product_uom_qty > rec.forecast_quantity: | |
|                             self.forecast_check = True | |
|                             forecast_qty_list = "You have added %s" \ | |
|                                                 " units of %s but " \ | |
|                                                 "you only have" \ | |
|                                                 " %s units available.\n" % ( | |
|                                                     rec.product_uom_qty, | |
|                                                     rec.product_id.name, | |
|                                                     rec.forecast_quantity) | |
|                             low_qty.append(forecast_qty_list) | |
|         listToStr = ' '.join(map(str, low_qty)) | |
|         if self.onhand_check: | |
|             raise UserError(listToStr) | |
|         if self.forecast_check: | |
|             raise UserError(listToStr) | |
|         to_approve = False | |
|         discount_vals = self.order_line.mapped('discount') | |
|         approval_users = self.env.ref( | |
|             'all_in_one_sales_kit.group_approval_manager').users | |
|         user_discount = self.env.user.allow_discount | |
|         if self.env.user.discount_control == True: | |
|             for rec in discount_vals: | |
|                 if rec > user_discount: | |
|                     to_approve = True | |
|                     break | |
|         if to_approve: | |
|             display_id = self.id | |
|             action_id = self.env.ref( | |
|                 'sale.action_quotations_with_onboarding').id | |
|             base_url = self.env['ir.config_parameter'].sudo().get_param( | |
|                 'web.base.url') | |
|             redirect_link = "/web#id=%s&cids=1&menu_id=178&action=%s" \ | |
|                             "&model" \ | |
|                             "=sale.order&view_type=form" % ( | |
|                                 display_id, action_id) | |
|             url = base_url + redirect_link | |
|             for user in approval_users: | |
|                 mail_body = """ | |
|                         <p>Hello,</p> | |
|                                <p>New sale order '%s'  | |
|                                Created with Discount by '%s'  | |
|                                need your approval on it.</p> | |
|                                <p>To Approve, Cancel Order, | |
|                                 Click on the Following  | |
|                                Link: | |
|                                <a href='%s' style="display: inline-block;  | |
|                                padding: 10px; text-decoration: none;  | |
|                                font-size: 12px; | |
|                                background-color: #875A7B; color: #fff;  | |
|                                border-radius: 5px;"> | |
|                                <strong>Click Me</strong></a> | |
|                                </p> | |
|                                <p>Thank You.</p>""" % (self.name, | |
|                                                        self.env.user.name, | |
|                                                        url) | |
|                 mail_values = { | |
|                     'subject': "'%s' Discount Approval Request" % (self.name), | |
|                     'body_html': mail_body, | |
|                     'email_to': user.partner_id.email, | |
|                     'model': 'sale.order', | |
|                 } | |
|                 mail_id = self.env['mail.mail'].sudo().create(mail_values) | |
|                 mail_id.sudo().send() | |
|             self.state = 'waiting_for_approval' | |
|         for line in self.order_line: | |
|             if line.product_id.is_pack: | |
|                 for record in line.product_id.pack_products_ids: | |
|                     dest_loc = self.env.ref( | |
|                         'stock.stock_location_customers').id | |
|                     self.env['stock.move'].create({ | |
|                         'name': record.product_id.name, | |
|                         'product_id': record.product_id.id, | |
|                         'product_uom_qty': | |
|                             record.quantity * line.product_uom_qty, | |
|                         'product_uom': record.product_id.uom_id.id, | |
|                         'picking_id': self.picking_ids[0].id, | |
|                         'location_id': | |
|                             self.picking_ids.picking_type_id.default_location_src_id.id, | |
|                         'location_dest_id': dest_loc, | |
|                     }) | |
|             return res | |
| 
 | |
|     @api.model | |
|     def create(self, vals): | |
|         """Method for generating sequence for quotation """ | |
|         res = super(SaleOrder, self).create(vals) | |
|         seq_val = self.env.ref( | |
|             'all_in_one_sales_kit.seq_quotation').id | |
|         res.quotation_ref = self.env['ir.sequence'].browse( | |
|             seq_val).next_by_id() | |
|         return res | |
| 
 | |
|     def action_waiting_approval(self): | |
|         """Method for approving the sale order discount""" | |
|         self.approval_user_id = self.env.user.id | |
|         self.state = 'sale' | |
| 
 | |
|     def action_print_invoice(self): | |
|         """Method to print invoice""" | |
|         data = self.invoice_ids | |
|         return self.env.ref('account.account_invoices').report_action(data) | |
| 
 | |
|     @api.model | |
|     def get_data(self): | |
|         """To get data to the sales dashboard.""" | |
|         domain = [('user_id', '=', self.env.user.id)] | |
|         quotation = self.env['sale.order'].search( | |
|             domain + [('state', '=', 'draft')]) | |
|         my_sale_order_templates = self.env['sale.order'].search( | |
|             domain + [('state', '=', 'sale')]) | |
|         quotation_sent = self.env['sale.order'].search( | |
|             domain + [('state', '=', 'sent')]) | |
|         quotation_cancel = self.env['sale.order'].search( | |
|             domain + [('state', '=', 'cancel')]) | |
|         customers = self.env['res.partner'].search([]) | |
|         to_invoice = self.env['sale.order'].search( | |
|             domain + [('invoice_status', '=', 'to invoice')]) | |
|         products = self.env['product.template'].search([]) | |
|         return { | |
|             'quotation': len(quotation), | |
|             'my_sale_order_templates': len(my_sale_order_templates), | |
|             'quotation_sent': len(quotation_sent), | |
|             'quotation_cancel': len(quotation_cancel), | |
|             'customers': len(customers), | |
|             'products': len(products), | |
|             'to_invoice': len(to_invoice), | |
|         } | |
| 
 | |
|     @api.model | |
|     def get_value(self, start_date, end_date): | |
|         """It is to pass values according to start and end date to the | |
|         dashboard.""" | |
|         if start_date and end_date: | |
|             domain = [('user_id', '=', self.env.user.id), | |
|                       ('date_order', '>=', start_date), | |
|                       ('date_order', '<=', end_date)] | |
|         elif start_date: | |
|             domain = [('user_id', '=', self.env.user.id), | |
|                       ('date_order', '>=', start_date)] | |
|         elif end_date: | |
|             domain = [('user_id', '=', self.env.user.id), | |
|                       ('date_order', '<=', end_date)] | |
| 
 | |
|         quotation = self.env['sale.order'].search( | |
|             domain + [('state', '=', 'draft')]) | |
|         my_sale_order_templates = self.env['sale.order'].search( | |
|             domain + [('state', '=', 'sale')]) | |
|         quotation_sent = self.env['sale.order'].search( | |
|             domain + [('state', '=', 'sent')]) | |
|         quotation_cancel = self.env['sale.order'].search( | |
|             domain + [('state', '=', 'cancel')]) | |
|         customers = self.env['res.partner'].search([]) | |
|         products = self.env['product.template'].search([]) | |
|         to_invoice = self.env['sale.order'].search( | |
|             domain + [('invoice_status', '=', 'to invoice')]) | |
|         return { | |
|             'quotation': len(quotation), | |
|             'my_sale_order_templates': len(my_sale_order_templates), | |
|             'quotation_sent': len(quotation_sent), | |
|             'quotation_cancel': len(quotation_cancel), | |
|             'customers': len(customers), | |
|             'products': len(products), | |
|             'to_invoice': len(to_invoice), | |
|         } | |
| 
 | |
|     @api.model | |
|     def get_lead_customer(self): | |
|         """Returns customer data to the graph of dashboard""" | |
|         lead_template = {} | |
|         sale = {} | |
|         partner_id = self.env['res.partner'].sudo().search([]) | |
|         vals = self.env['sale.order'].sudo().search([ | |
|         ]).mapped('partner_id').ids | |
|         for record in partner_id: | |
|             if record.id in vals: | |
|                 record.ref = vals.count(record.id) | |
|                 sale.update({record: vals.count(record.id)}) | |
|         sort = dict( | |
|             sorted(sale.items(), key=lambda item: item[1], reverse=True)) | |
|         out = dict(itertools.islice(sort.items(), 10)) | |
|         for count in out: | |
|             lead_template[count.name] = out[count] | |
|         return { | |
|             'lead_templates': lead_template, | |
|         } | |
| 
 | |
|     @api.model | |
|     def get_lead_product(self): | |
|         """Returns product data to the graph of dashboard""" | |
|         lead_template = {} | |
|         sale = {} | |
|         product_id = self.env['product.template'].search([]) | |
|         for record in product_id: | |
|             sale.update({record: record.sales_count}) | |
|         sort = dict( | |
|             sorted(sale.items(), key=lambda item: item[1], reverse=True)) | |
|         out = dict(itertools.islice(sort.items(), 10)) | |
|         for product in out: | |
|             lead_template[product.name] = out[product] | |
|         return { | |
|             'lead_templates': lead_template, | |
|         } | |
| 
 | |
|     @api.model | |
|     def get_lead_order(self): | |
|         """Returns lead sale order data to the graph of dashboard""" | |
|         lead_template = {} | |
|         sale = {} | |
|         order_id = self.env['sale.order'].search([('state', '=', 'sale')]) | |
|         for record in order_id: | |
|             sale.update({record: record.amount_total}) | |
|         sort = dict( | |
|             sorted(sale.items(), key=lambda item: item[1], reverse=True)) | |
|         out = dict(itertools.islice(sort.items(), 10)) | |
|         for order in out: | |
|             lead_template[order.name] = out[order] | |
|         return { | |
|             'lead_templates': lead_template, | |
|         } | |
| 
 | |
|     @api.model | |
|     def get_my_monthly_comparison(self): | |
|         """Returns my monthly sale count data to the graph of dashboard""" | |
|         lead_template = {} | |
|         sales_order = self.env['sale.order'].search( | |
|             [('user_id', '=', self.env.user.id)]) | |
|         list = [rec.date_order.month for rec in sales_order] | |
|         for i in range(1, 13): | |
|             count = list.count(i) | |
|             lead_template.update({ | |
|                 i: count | |
|             }) | |
|         return { | |
|             'lead_templates': lead_template, | |
|         } | |
| 
 | |
|     @api.model | |
|     def get_sales_team(self): | |
|         """Returns sales team data to the graph of dashboard""" | |
|         lead_template = {} | |
|         sale = {} | |
|         sales_team = self.env['crm.team'].search([]) | |
|         for record in sales_team: | |
|             total = sum(self.env['sale.order'].search( | |
|                 [('state', '=', 'sale'), | |
|                  ('team_id', '=', record.id)]).mapped('amount_total')) | |
|             sale.update({record: total}) | |
|         sort = dict( | |
|             sorted(sale.items(), key=lambda item: item[1], reverse=True)) | |
|         out = dict(itertools.islice(sort.items(), 10)) | |
|         for team in out: | |
|             lead_template[team.name] = out[team] | |
|         return { | |
|             'lead_templates': lead_template, | |
|         } | |
| 
 | |
|     @api.model | |
|     def get_least_sold(self): | |
|         """Returns least sold product data to the graph of dashboard""" | |
|         lead_template = {} | |
|         sale = {} | |
|         product_id = self.env['product.template'].search([]) | |
|         for record in product_id: | |
|             if record.sales_count != 0: | |
|                 sale.update({record: record.sales_count}) | |
|         sort = dict( | |
|             sorted(sale.items(), key=lambda item: item[1], reverse=False)) | |
|         out = dict(itertools.islice(sort.items(), 10)) | |
|         for product in out: | |
|             lead_template[product.name] = out[product] | |
|         return { | |
|             'lead_templates': lead_template, | |
|         }
 | |
| 
 |