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.
264 lines
13 KiB
264 lines
13 KiB
# -*- coding: utf-8 -*-
|
|
###############################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
|
# Author: Afra MP (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/>.
|
|
#
|
|
###############################################################################
|
|
import pytz
|
|
from twilio.rest import Client
|
|
from odoo import api, fields, models
|
|
|
|
|
|
class PosOrder(models.Model):
|
|
"""Inherited the pos_order class to add filed and function to calculate pos
|
|
order details in the dashboard menu"""
|
|
_inherit = 'pos.order'
|
|
|
|
exchange = fields.Boolean(string='Exchange',
|
|
help='Enable if the order contain is exchange '
|
|
'product')
|
|
sale_barcode = fields.Char(string='Barcode',
|
|
help='Barcode associated with the pos order.')
|
|
|
|
def get_pos_exchange_order(self):
|
|
"""Mark order a exchanged"""
|
|
self.exchange = True
|
|
return
|
|
|
|
@api.model
|
|
def get_department(self, option):
|
|
"""Function to filter the POs sales report chart"""
|
|
company_id = self.env.company.id
|
|
if option == 'pos_hourly_sales':
|
|
query = '''select EXTRACT(hour FROM date_order at time zone 'utc' at time zone '{}')
|
|
as date_month,sum(amount_total) from pos_order where
|
|
EXTRACT(month FROM date_order::date) = EXTRACT(month FROM CURRENT_DATE)
|
|
AND pos_order.company_id = ''' + str(
|
|
company_id) + ''' group by date_month '''
|
|
query = query.format(
|
|
self.env.user.tz if self.env.user.tz else pytz.UTC)
|
|
label = 'HOURS'
|
|
elif option == 'pos_monthly_sales':
|
|
query = '''select date_order::date as date_month,sum(amount_total) from pos_order where
|
|
EXTRACT(month FROM date_order::date) = EXTRACT(month FROM CURRENT_DATE) AND pos_order.company_id = ''' + str(
|
|
company_id) + ''' group by date_month '''
|
|
label = 'DAYS'
|
|
else:
|
|
query = '''select TO_CHAR(date_order,'MON')date_month,sum(amount_total) from pos_order where
|
|
EXTRACT(year FROM date_order::date) = EXTRACT(year FROM CURRENT_DATE) AND pos_order.company_id = ''' + str(
|
|
company_id) + ''' group by date_month'''
|
|
label = 'MONTHS'
|
|
self._cr.execute(query)
|
|
docs = self._cr.dictfetchall()
|
|
order = []
|
|
today = []
|
|
for record in docs:
|
|
order.append(record.get('sum'))
|
|
today.append(record.get('date_month'))
|
|
return [order, today, label]
|
|
|
|
@api.model
|
|
def get_details(self):
|
|
"""Function to get payment details,session details and sales person
|
|
details"""
|
|
company_id = self.env.company
|
|
self._cr.execute('''select pos_payment_method.name ->>'en_US',sum(amount)
|
|
from pos_payment inner join pos_payment_method on
|
|
pos_payment_method.id=pos_payment.payment_method_id
|
|
where pos_payment.company_id = ''' + str(company_id.id) + " " + '''
|
|
group by pos_payment_method.name ORDER
|
|
BY sum(amount) DESC; ''')
|
|
payment_details = self._cr.fetchall()
|
|
self._cr.execute('''select hr_employee.name,sum(pos_order.amount_paid)
|
|
as total,count(pos_order.amount_paid) as orders from
|
|
pos_order inner join hr_employee on pos_order.user_id =
|
|
hr_employee.user_id where pos_order.company_id =''' + str(
|
|
company_id.id) + " " + '''GROUP BY hr_employee.name order by total DESC;''')
|
|
salesperson = self._cr.fetchall()
|
|
payments = []
|
|
for rec in payment_details:
|
|
rec = list(rec)
|
|
if company_id.currency_id.position == 'after':
|
|
rec[1] = "%s %s" % (rec[1], company_id.currency_id.symbol)
|
|
else:
|
|
rec[1] = "%s %s" % (company_id.currency_id.symbol, rec[1])
|
|
payments.append(tuple(rec))
|
|
total_sales = []
|
|
for rec in salesperson:
|
|
rec = list(rec)
|
|
if company_id.currency_id.position == 'after':
|
|
rec[1] = "%s %s" % (rec[1], company_id.currency_id.symbol)
|
|
else:
|
|
rec[1] = "%s %s" % (company_id.currency_id.symbol, rec[1])
|
|
total_sales.append(tuple(rec))
|
|
sessions_list = []
|
|
session = {'opened': 'Opened', 'opening_control': "Opening Control"}
|
|
for session_id in self.env['pos.config'].search([]):
|
|
if session.get(session_id.pos_session_state) is None:
|
|
sessions_list.append({'session': session_id.name,
|
|
'status': 'Closed'})
|
|
else:
|
|
sessions_list.append({'session': session_id.name,
|
|
'status': session.get(
|
|
session_id.pos_session_state)})
|
|
return {'payment_details': payments, 'salesperson': total_sales,
|
|
'selling_product': sessions_list}
|
|
|
|
@api.model
|
|
def get_refund_details(self):
|
|
"""Function to get total count of orders,session and refund orders"""
|
|
total = sum(self.env['pos.order'].search([]).mapped('amount_total'))
|
|
today_refund_total = 0
|
|
today_sale = 0
|
|
for pos_order_id in self.env['pos.order'].search([]):
|
|
if pos_order_id.date_order.date() == fields.date.today():
|
|
today_sale = today_sale + 1
|
|
if pos_order_id.amount_total < 0.0:
|
|
today_refund_total = today_refund_total + 1
|
|
magnitude = 0
|
|
while abs(total) >= 1000:
|
|
magnitude += 1
|
|
total /= 1000.0
|
|
# add more suffixes if you need them
|
|
val = '%.2f%s' % (total, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])
|
|
return {
|
|
'total_sale': val,
|
|
'total_order_count': self.env['pos.order'].search_count([]),
|
|
'total_refund_count': self.env['pos.order'].search_count(
|
|
[('amount_total', '<', 0.0)]),
|
|
'total_session': self.env['pos.session'].search_count([]),
|
|
'today_refund_total': today_refund_total,
|
|
'today_sale': today_sale,
|
|
}
|
|
|
|
@api.model
|
|
def get_the_top_customer(self):
|
|
"""Function to get top 10 customer in pos"""
|
|
self._cr.execute('''select res_partner.name as customer,pos_order.partner_id,sum(pos_order.amount_paid) as amount_total from pos_order
|
|
inner join res_partner on res_partner.id = pos_order.partner_id where pos_order.company_id = ''' + str(
|
|
self.env.company.id) + ''' GROUP BY pos_order.partner_id,
|
|
res_partner.name ORDER BY amount_total DESC LIMIT 10;''')
|
|
top_customer = self._cr.dictfetchall()
|
|
order = []
|
|
day = []
|
|
for record in top_customer:
|
|
order.append(record.get('amount_total'))
|
|
day.append(record.get('customer'))
|
|
return [order, day]
|
|
|
|
@api.model
|
|
def get_the_top_products(self):
|
|
"""Function to get top 10 product in """
|
|
|
|
self._cr.execute('''select DISTINCT(product_template.name)->>'en_US' as product_name,sum(qty) as total_quantity from
|
|
pos_order_line inner join product_product on product_product.id=pos_order_line.product_id inner join
|
|
product_template on product_product.product_tmpl_id = product_template.id where pos_order_line.company_id = ''' + str(
|
|
self.env.company.id) + ''' group by product_template.id ORDER
|
|
BY total_quantity DESC Limit 10 ''')
|
|
top_product = self._cr.dictfetchall()
|
|
total_quantity = []
|
|
product_name = []
|
|
for record in top_product:
|
|
total_quantity.append(record.get('total_quantity'))
|
|
product_name.append(record.get('product_name'))
|
|
return [total_quantity, product_name]
|
|
|
|
@api.model
|
|
def get_the_top_categories(self):
|
|
"""Function to get top categories in pos"""
|
|
query = '''select DISTINCT(product_category.complete_name) as product_category,sum(qty) as total_quantity
|
|
from pos_order_line inner join product_product on product_product.id=pos_order_line.product_id inner join
|
|
product_template on product_product.product_tmpl_id = product_template.id inner join product_category on
|
|
product_category.id =product_template.categ_id where pos_order_line.company_id = ''' + str(
|
|
self.env.company.id) + ''' group by product_category ORDER BY total_quantity DESC '''
|
|
self._cr.execute(query)
|
|
top_categories = self._cr.dictfetchall()
|
|
total_quantity = []
|
|
product_categ = []
|
|
for record in top_categories:
|
|
total_quantity.append(record.get('total_quantity'))
|
|
product_categ.append(record.get('product_category'))
|
|
return [total_quantity, product_categ]
|
|
|
|
@api.model
|
|
def get_invoice(self, id):
|
|
"""Retrieve invoice information based on a POS reference ID.
|
|
This method searches for a POS record with the specified reference ID. It
|
|
then retrieves the associated invoice based on the name matching the
|
|
reference. The invoice details, including ID, name, base URL, and account
|
|
barcode, are returned as a dictionary.
|
|
:param id: The POS reference ID to search for.
|
|
:return: A dictionary containing the invoice details.
|
|
:rtype: dict"""
|
|
invoice_id = self.env['account.move'].search(
|
|
[('ref', '=', self.search([('pos_reference', '=', id)]).name)])
|
|
return {'invoice_id': invoice_id.id, 'invoice_name': invoice_id.name,
|
|
'base_url': self.env['ir.config_parameter'].get_param(
|
|
'web.base.url'), 'barcode': invoice_id.account_barcode}
|
|
|
|
@api.model
|
|
def create_from_ui(self, orders, draft=False):
|
|
"""Create POS orders from the user interface.
|
|
This method is called to create POS orders based on the provided
|
|
data from the user interface.
|
|
:param orders: A list of dictionaries representing the POS orders.
|
|
:param draft: Set to True if the orders should be created in the
|
|
draft state.
|
|
:returns: A list of dictionaries containing the created order
|
|
details.
|
|
"""
|
|
res = super(PosOrder, self).create_from_ui(orders)
|
|
id = [line['id'] for line in res if line['id']]
|
|
if backend_order := self.search([('id', 'in', id)]):
|
|
for pos_order in backend_order:
|
|
params = self.env['ir.config_parameter'].sudo()
|
|
if params.get_param(
|
|
'pos.customer_msg') and pos_order.partner_id.phone:
|
|
try:
|
|
# Download the helper library from https://www.twilio.com/docs/python/install
|
|
Client(params.get_param('pos.account_sid'),
|
|
params.get_param(
|
|
'pos.auth_token')).messages.create(
|
|
body=params.get_param('pos.sms_body'),
|
|
from_=params.get_param('pos.twilio_number'),
|
|
to=str(pos_order.partner_id.phone))
|
|
self.env['pos.greetings'].create({
|
|
'partner_id': pos_order.partner_id.id,
|
|
'order_id': pos_order.id,
|
|
'auth_token': params.get_param('pos.auth_token'),
|
|
'twilio_number': params.get_param(
|
|
'pos.twilio_number'),
|
|
'to_number': str(pos_order.partner_id.phone),
|
|
'session_id': pos_order.session_id.id,
|
|
'sms_body': params.get_param('pos.sms_body'),
|
|
'send_sms': True,
|
|
})
|
|
except Exception:
|
|
pass
|
|
return res
|
|
|
|
|
|
class PosOrderLine(models.Model):
|
|
"""Inherit the class pos_order_line"""
|
|
_inherit = "pos.order.line"
|
|
|
|
def get_product_details(self, ids):
|
|
"""Function to get the product details"""
|
|
return [{'product_id': rec.product_id.id, 'name': rec.product_id.name,
|
|
'qty': rec.qty}
|
|
for rec in self.env['pos.order.line'].browse(ids)]
|
|
|