@ -0,0 +1,48 @@ | 
				
			|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg | 
				
			|||
    :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html | 
				
			|||
    :alt: License: AGPL-3 | 
				
			|||
 | 
				
			|||
All In One Website Kit | 
				
			|||
====================== | 
				
			|||
All In One Website Kit for odoo15 enables multiple website features. | 
				
			|||
 | 
				
			|||
Configuration | 
				
			|||
============= | 
				
			|||
* No additional configurations needed | 
				
			|||
 | 
				
			|||
Company | 
				
			|||
------- | 
				
			|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | 
				
			|||
 | 
				
			|||
License | 
				
			|||
------- | 
				
			|||
Affero General Public License, Version 3 (AGPL v3). | 
				
			|||
(https://www.gnu.org/licenses/agpl-3.0-standalone.html) | 
				
			|||
 | 
				
			|||
Credits | 
				
			|||
------- | 
				
			|||
* Developers: (V15) Aysha Shalin, | 
				
			|||
              (V16) Yadhukrishnan, | 
				
			|||
  Contact: odoo@cybrosys.com | 
				
			|||
 | 
				
			|||
Contacts | 
				
			|||
-------- | 
				
			|||
* Mail Contact : odoo@cybrosys.com | 
				
			|||
* Website : https://cybrosys.com | 
				
			|||
 | 
				
			|||
Bug Tracker | 
				
			|||
----------- | 
				
			|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. | 
				
			|||
 | 
				
			|||
Maintainer | 
				
			|||
========== | 
				
			|||
.. image:: https://cybrosys.com/images/logo.png | 
				
			|||
   :target: https://cybrosys.com | 
				
			|||
 | 
				
			|||
This module is maintained by Cybrosys Technologies. | 
				
			|||
 | 
				
			|||
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ | 
				
			|||
 | 
				
			|||
Further information | 
				
			|||
=================== | 
				
			|||
HTML Description: `<static/description/index.html>`__ | 
				
			|||
@ -0,0 +1,22 @@ | 
				
			|||
# -*- 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 . import controllers, models | 
				
			|||
@ -0,0 +1,95 @@ | 
				
			|||
# -*- 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/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
{ | 
				
			|||
    'name': 'All In One Website Kit', | 
				
			|||
    'version': '15.0.1.0.0', | 
				
			|||
    'category': 'Website', | 
				
			|||
    'summary': """All In One Website Kit for odoo16 community edition enables | 
				
			|||
    multiple website features.""", | 
				
			|||
    'description': """This module enables the features of the following modules, | 
				
			|||
    Website Call For Price, Customer Order Comment, Ecommerce Barcode Search, | 
				
			|||
    Instagram Feed Snippet, Portal Dashboard, Website Clear Cart, Hide Variants, | 
				
			|||
    Website Custom Contact Us, Product Attachments on the Website, | 
				
			|||
    Website Return Order Management and Whatsapp Floating Icon in Website.""", | 
				
			|||
    'author': 'Cybrosys Techno Solutions', | 
				
			|||
    'company': 'Cybrosys Techno Solutions', | 
				
			|||
    'maintainer': 'Cybrosys Techno Solutions', | 
				
			|||
    'website': "https://www.cybrosys.com", | 
				
			|||
    'depends': [ | 
				
			|||
        'base', 'website_sale_wishlist', 'website_sale_comparison', 'stock', | 
				
			|||
        'sale_management', 'project', 'crm', 'purchase' | 
				
			|||
    ], | 
				
			|||
    'data': [ | 
				
			|||
        'security/ir.model.access.csv', | 
				
			|||
        'data/ir_sequence_data.xml', | 
				
			|||
        'data/insta_profile_sequence_data.xml', | 
				
			|||
        'report/sale_return_reports.xml', | 
				
			|||
        'report/sale_return_templates.xml', | 
				
			|||
        'views/shop_hide_call_price_templates.xml', | 
				
			|||
        'views/wishlist_hide_price_templates.xml', | 
				
			|||
        'views/compare_hide_price_templates.xml', | 
				
			|||
        'views/call_price_views.xml', | 
				
			|||
        'views/sale_order_views.xml', | 
				
			|||
        'views/product_template_views.xml', | 
				
			|||
        'views/res_config_settings_views.xml', | 
				
			|||
        'views/customer_order_comment_templates.xml', | 
				
			|||
        'views/products_barcode_scan_templates.xml', | 
				
			|||
        'views/portal_dashboard_templates.xml', | 
				
			|||
        'views/clear_cart_templates.xml', | 
				
			|||
        'views/website_views.xml', | 
				
			|||
        'views/website_contact_us_template.xml', | 
				
			|||
        'views/product_product_views.xml', | 
				
			|||
        'views/product_attachments_templates.xml', | 
				
			|||
        'views/website_thankyou_templates.xml', | 
				
			|||
        'views/sale_return_views.xml', | 
				
			|||
        'views/sale_return_templates.xml', | 
				
			|||
        'views/stock_picking_views.xml', | 
				
			|||
        'views/insta_post_views.xml', | 
				
			|||
        'views/insta_profile_views.xml', | 
				
			|||
        'views/sale_order_views.xml', | 
				
			|||
        'views/carousal_dashboard_templates.xml', | 
				
			|||
        'views/portal_whatsapp_templates.xml', | 
				
			|||
    ], | 
				
			|||
    'assets': { | 
				
			|||
        'web.assets_frontend': [ | 
				
			|||
            '/all_in_one_website_kit/static/src/js/create_call_price.js', | 
				
			|||
            '/all_in_one_website_kit/static/src/js/review_and_rating.js', | 
				
			|||
            '/all_in_one_website_kit/static/src/css/review_and_rating.css', | 
				
			|||
            '/all_in_one_website_kit/static/src/js/sale_barcode.js', | 
				
			|||
            '/all_in_one_website_kit/static/src/js/portal_dashboard_graph.js', | 
				
			|||
            '/all_in_one_website_kit/static/src/js/variants.js', | 
				
			|||
            '/all_in_one_website_kit/static/src/js/sale_return.js', | 
				
			|||
            '/all_in_one_website_kit/static/src/js/caroursel.js', | 
				
			|||
            'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js', | 
				
			|||
            '/all_in_one_website_kit/static/src/scss/style.scss', | 
				
			|||
            '/all_in_one_website_kit/static/src/js/quagga.js', | 
				
			|||
        ] | 
				
			|||
    }, | 
				
			|||
    'external_dependencies': { | 
				
			|||
        'python': ['pytz', 'geopy'], | 
				
			|||
    }, | 
				
			|||
    'images': ['static/description/banner.png'], | 
				
			|||
    'license': 'AGPL-3', | 
				
			|||
    'installable': True, | 
				
			|||
    'auto_install': False, | 
				
			|||
    'application': False, | 
				
			|||
} | 
				
			|||
@ -0,0 +1,25 @@ | 
				
			|||
# -*- 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 . import all_in_one_website_kit | 
				
			|||
from . import main | 
				
			|||
from . import portal | 
				
			|||
from . import website_sale | 
				
			|||
@ -0,0 +1,68 @@ | 
				
			|||
# -*- 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/>. | 
				
			|||
# | 
				
			|||
############################################################################### | 
				
			|||
import time | 
				
			|||
from odoo import http | 
				
			|||
from odoo.http import request | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class WebsiteClearCart(http.Controller): | 
				
			|||
    """ | 
				
			|||
    The class WebsiteClearCart is used to clear the cart. | 
				
			|||
    Methods: | 
				
			|||
        remove_cart_items(self): | 
				
			|||
    It will remove all items from cart and redirect to shop page | 
				
			|||
    """ | 
				
			|||
    @http.route(['/shop/remove_items'], type="http", auth="public", | 
				
			|||
                website=True) | 
				
			|||
    def remove_cart_items(self): | 
				
			|||
        """ This will remove all items from cart and redirect to shop page """ | 
				
			|||
        current_orders = request.website.sale_get_order() | 
				
			|||
        for line in current_orders.website_order_line: | 
				
			|||
            line.unlink() | 
				
			|||
        return request.redirect('/shop/cart') | 
				
			|||
 | 
				
			|||
    @http.route('/final/customer_rating', type='http', auth="public", | 
				
			|||
                website=True, sitemap=False) | 
				
			|||
    def customer_order_rating(self, **kw): | 
				
			|||
        """ This function helps to fetch the values of comment and rating """ | 
				
			|||
        order_id = request.env['sale.order'].sudo().browse(int(kw['order_id'])) | 
				
			|||
        order_id.comment = kw['comment'] | 
				
			|||
        order_id.rating = kw['rate_value'] | 
				
			|||
        return request.redirect('/shop/confirmation') | 
				
			|||
 | 
				
			|||
    @http.route('/get_dashboard_carousel', auth="public", type='json') | 
				
			|||
    def get_dashboard_carousel(self): | 
				
			|||
        """ Getting data to the carousel """ | 
				
			|||
        events_per_slide = 3 | 
				
			|||
        records = request.env['insta.post'].sudo().search([]) | 
				
			|||
        records_grouped = [records[post:post + events_per_slide] for po3333333333333333333333st in | 
				
			|||
                           range(0, len(records), events_per_slide)] | 
				
			|||
        values = { | 
				
			|||
            "objects": records_grouped, | 
				
			|||
            "events_per_slide": events_per_slide, | 
				
			|||
            "num_slides": len(records_grouped), | 
				
			|||
            "uniqueId": "pc-%d" % int(time.time() * 1000), | 
				
			|||
        } | 
				
			|||
        response = http.Response( | 
				
			|||
            template='all_in_one_website_kit.s_carousel_template_items', | 
				
			|||
            qcontext=values) | 
				
			|||
        return response.render() | 
				
			|||
@ -0,0 +1,64 @@ | 
				
			|||
# -*- 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 http | 
				
			|||
from odoo.http import request | 
				
			|||
from odoo.addons.website.controllers import main | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class Home(main.Home): | 
				
			|||
    """ The CustomerRegistration class is used for creating the sale return | 
				
			|||
        orders and displaying the thankyou page. """ | 
				
			|||
    @http.route('/sale_return', type='http', methods=['POST'], | 
				
			|||
                auth="public", website=True, csrf=False) | 
				
			|||
    def sale_return(self, **kwargs): | 
				
			|||
        """ Controller to create return order. """ | 
				
			|||
        product_id = request.env['product.product'].sudo().browse( | 
				
			|||
            int(kwargs['product'])) | 
				
			|||
        order = request.env['sale.order'].sudo().browse(int(kwargs['order_id'])) | 
				
			|||
        values = { | 
				
			|||
            'partner_id': order.partner_id.id, | 
				
			|||
            'order_id': order.id, | 
				
			|||
            'product_id': product_id.id, | 
				
			|||
            'quantity': kwargs['qty'], | 
				
			|||
            'reason': kwargs['reason'], | 
				
			|||
            'user_id': request.env.uid, | 
				
			|||
            'create_date': datetime.now(), | 
				
			|||
        } | 
				
			|||
        stock_picks = request.env['stock.picking'].search( | 
				
			|||
            [('origin', '=', order.name)]) | 
				
			|||
        moves = stock_picks.mapped('move_ids_without_package').filtered( | 
				
			|||
            lambda p: p.product_id == product_id) | 
				
			|||
        if moves: | 
				
			|||
            moves = moves.sorted('product_uom_qty', reverse=True) | 
				
			|||
            values.update({'state': 'draft'}) | 
				
			|||
            ret_order = request.env['sale.return'].create(values) | 
				
			|||
            moves[0].picking_id.return_order_id = ret_order.id | 
				
			|||
            moves[0].picking_id.return_order_picking = False | 
				
			|||
        return request.redirect('/my/request-thank-you') | 
				
			|||
 | 
				
			|||
    @http.route('/my/request-thank-you', website=True, page=True, | 
				
			|||
                auth='public', csrf=False) | 
				
			|||
    def maintenance_request_thanks(self): | 
				
			|||
        """ Opening thankyou page. """ | 
				
			|||
        return request.render( | 
				
			|||
            'all_in_one_website_kit.customers_request_thank_page') | 
				
			|||
@ -0,0 +1,415 @@ | 
				
			|||
# -*- 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/>. | 
				
			|||
# | 
				
			|||
############################################################################### | 
				
			|||
import base64 | 
				
			|||
from collections import OrderedDict | 
				
			|||
from geopy import Nominatim | 
				
			|||
import json | 
				
			|||
import pytz | 
				
			|||
from odoo import http | 
				
			|||
from odoo.exceptions import AccessError, MissingError | 
				
			|||
from odoo.http import request, route | 
				
			|||
from odoo.tools import image_process | 
				
			|||
from odoo.tools.translate import _ | 
				
			|||
from odoo.addons.portal.controllers.portal import CustomerPortal | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class ReturnCustomerPortal(CustomerPortal): | 
				
			|||
    """ Passing values to the sale return templates. """ | 
				
			|||
    def _prepare_home_portal_values(self, counters): | 
				
			|||
        """getting count of total sale returns""" | 
				
			|||
        values = super()._prepare_home_portal_values(counters) | 
				
			|||
        if 'return_count' in counters: | 
				
			|||
            values['return_count'] = request.env['sale.return'].search_count([ | 
				
			|||
                ('state', 'in', ['draft', 'confirm', 'done', 'cancel'])]) | 
				
			|||
        return values | 
				
			|||
 | 
				
			|||
    @http.route(['/my/return_orders', '/my/return_orders/page/<int:page>'], | 
				
			|||
                type='http', auth="user", website=True) | 
				
			|||
    def portal_my_sale_return(self, page=1, date_begin=None, date_end=None, | 
				
			|||
                              sortby=None, filterby=None): | 
				
			|||
        """ Passing data to the /my/return_orders page. """ | 
				
			|||
        values = self._prepare_portal_layout_values() | 
				
			|||
        sale_return = request.env['sale.return'] | 
				
			|||
        domain = [] | 
				
			|||
        searchbar_sortings = { | 
				
			|||
            'date': {'label': _('Newest'), 'order': 'create_date desc'}, | 
				
			|||
            'name': {'label': _('Name'), 'order': 'name'}, | 
				
			|||
            'sale': {'label': _('Sale Order'), 'order': 'order_id'}, | 
				
			|||
        } | 
				
			|||
        # default sort by value | 
				
			|||
        if not sortby: | 
				
			|||
            sortby = 'date' | 
				
			|||
        order = searchbar_sortings[sortby]['order'] | 
				
			|||
        if date_begin and date_end: | 
				
			|||
            domain += [('create_date', '>', date_begin), | 
				
			|||
                       ('create_date', '<=', date_end)] | 
				
			|||
        searchbar_filters = { | 
				
			|||
            'all': {'label': _('All'), 'domain': [ | 
				
			|||
                ('state', 'in', ['draft', 'confirm', 'done', 'cancel'])]}, | 
				
			|||
            'confirm': {'label': _('Confirmed'), | 
				
			|||
                        'domain': [('state', '=', 'confirm')]}, | 
				
			|||
            'cancel': {'label': _('Cancelled'), | 
				
			|||
                       'domain': [('state', '=', 'cancel')]}, | 
				
			|||
            'done': {'label': _('Done'), 'domain': [('state', '=', 'done')]}, | 
				
			|||
        } | 
				
			|||
        # default filter by value | 
				
			|||
        if not filterby: | 
				
			|||
            filterby = 'all' | 
				
			|||
        domain += searchbar_filters[filterby]['domain'] | 
				
			|||
        # pager | 
				
			|||
        pager = request.website.pager( | 
				
			|||
            url="/my/return_orders", | 
				
			|||
            url_args={'date_begin': date_begin, 'date_end': date_end, | 
				
			|||
                      'sortby': sortby}, | 
				
			|||
            total=sale_return.search_count(domain), | 
				
			|||
            page=page, | 
				
			|||
            step=self._items_per_page | 
				
			|||
        ) | 
				
			|||
        # content according to pager and archive selected | 
				
			|||
        orders = sale_return.search(domain, order=order, | 
				
			|||
                                    limit=self._items_per_page, | 
				
			|||
                                    offset=pager['offset']) | 
				
			|||
        request.session['my_return_history'] = orders.ids[:100] | 
				
			|||
        values.update({ | 
				
			|||
            'date': date_begin, | 
				
			|||
            'orders': orders.sudo(), | 
				
			|||
            'page_name': 'Sale_Return', | 
				
			|||
            'default_url': '/my/return_orders', | 
				
			|||
            'pager': pager, | 
				
			|||
            'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())), | 
				
			|||
            'searchbar_sortings': searchbar_sortings, | 
				
			|||
            'sortby': sortby, | 
				
			|||
        }) | 
				
			|||
        return request.render("all_in_one_website_kit.portal_my_returns", | 
				
			|||
                              values) | 
				
			|||
 | 
				
			|||
    @http.route(['/my/return_orders/<int:order_id>'], type='http', | 
				
			|||
                auth="public", website=True) | 
				
			|||
    def portal_my_return_detail(self, order_id=None, access_token=None, | 
				
			|||
                                report_type=None, download=False, **kw): | 
				
			|||
        """ Passing data to individual return orders. """ | 
				
			|||
        try: | 
				
			|||
            order_sudo = self._document_check_access('sale.return', order_id, | 
				
			|||
                                                     access_token) | 
				
			|||
        except (AccessError, MissingError): | 
				
			|||
            return request.redirect('/my') | 
				
			|||
        if report_type in ('html', 'pdf', 'text'): | 
				
			|||
            return self._show_report( | 
				
			|||
                model=order_sudo, report_type=report_type, | 
				
			|||
                report_ref='all_in_one_website_kit.report_sale_returns', | 
				
			|||
                download=download) | 
				
			|||
        values = self._sale_return_get_page_view_values(order_sudo, | 
				
			|||
                                                        access_token, **kw) | 
				
			|||
        return request.render("all_in_one_website_kit.portal_sale_return_page", | 
				
			|||
                              values) | 
				
			|||
 | 
				
			|||
    def _sale_return_get_page_view_values(self, order, access_token, **kwargs): | 
				
			|||
        """ Getting values to the function portal_my_return_detail. """ | 
				
			|||
        def resize_to_48(b64source): | 
				
			|||
            if not b64source: | 
				
			|||
                b64source = request.env['ir.binary']._placeholder() | 
				
			|||
            else: | 
				
			|||
                b64source = base64.b64decode(b64source) | 
				
			|||
            return base64.b64encode(image_process(b64source, size=(48, 48))) | 
				
			|||
 | 
				
			|||
        values = { | 
				
			|||
            'orders': order, | 
				
			|||
            'resize_to_48': resize_to_48, | 
				
			|||
        } | 
				
			|||
        return self._get_page_view_values(order, access_token, values, | 
				
			|||
                                          'my_return_history', False, **kwargs) | 
				
			|||
 | 
				
			|||
    @route(['/my', '/my/home'], type='http', auth="user", website=True) | 
				
			|||
    def home(self, **kw): | 
				
			|||
        """ Replaces already existing work flow of portal view to redirect to | 
				
			|||
        new template with record values and count. """ | 
				
			|||
        user = request.env.user.id | 
				
			|||
        partners = request.env.user | 
				
			|||
        group_id = request.env.ref('base.group_user') | 
				
			|||
        order_id = request.env['sale.order'].sudo() | 
				
			|||
        purchase_order = request.env['purchase.order'].sudo() | 
				
			|||
        account_move = request.env['account.move'] | 
				
			|||
        project = request.env['project.project'].sudo() | 
				
			|||
        task = request.env['project.task'].sudo() | 
				
			|||
        config_parameters = request.env['ir.config_parameter'].sudo() | 
				
			|||
        number_project = "" | 
				
			|||
        projects_limited = "" | 
				
			|||
        tasks_limited = "" | 
				
			|||
        number_account = "" | 
				
			|||
        invoices_limited = "" | 
				
			|||
        show_project = request.env[ | 
				
			|||
            'ir.config_parameter' | 
				
			|||
        ].sudo().get_param('all_in_one_website_kit.is_show_project') | 
				
			|||
        show_account = request.env['ir.config_parameter'].sudo().get_param( | 
				
			|||
            'all_in_one_website_kit.is_show_recent_invoice_bill') | 
				
			|||
        show_so_q = request.env['ir.config_parameter'].sudo().get_param( | 
				
			|||
            'all_in_one_website_kit.is_show_recent_so_q') | 
				
			|||
        show_po_rfq = request.env[ | 
				
			|||
            'ir.config_parameter' | 
				
			|||
        ].sudo().get_param('all_in_one_website_kit.is_show_recent_po_rfq') | 
				
			|||
        number_order = "" | 
				
			|||
        sale_orders_limited = "" | 
				
			|||
        quotations_limited = "" | 
				
			|||
        number_po = "" | 
				
			|||
        purchase_orders_limited = "" | 
				
			|||
        rfq_limited = "" | 
				
			|||
        if group_id in partners.groups_id: | 
				
			|||
            if show_so_q: | 
				
			|||
                number_order = request.env[ | 
				
			|||
                    'ir.config_parameter' | 
				
			|||
                ].sudo().get_param('all_in_one_website_kit.sale_count', 0) | 
				
			|||
                sale_orders_limited = order_id.search([ | 
				
			|||
                    '|', ('user_id', '=', user), | 
				
			|||
                    ('partner_id', '=', request.env.user.partner_id.id), | 
				
			|||
                    ('state', 'not in', ['draft', 'sent']) | 
				
			|||
                ], limit=int(number_order)) | 
				
			|||
                quotations_limited = order_id.search([ | 
				
			|||
                    '|', ('user_id', '=', user), | 
				
			|||
                    ('partner_id', '=', request.env.user.partner_id.id), | 
				
			|||
                    ('state', 'in', ['sent']) | 
				
			|||
                ], limit=int(number_order)) | 
				
			|||
            if show_po_rfq: | 
				
			|||
                number_po = config_parameters.get_param( | 
				
			|||
                    'all_in_one_website_kit.purchase_count', 0) | 
				
			|||
                purchase_orders_limited = purchase_order.search([ | 
				
			|||
                    '|', ('user_id', '=', user), | 
				
			|||
                    ('partner_id', '=', request.env.user.partner_id.id), | 
				
			|||
                    ('state', 'not in', ['draft', 'sent', 'to approve']) | 
				
			|||
                ], limit=int(number_po)) | 
				
			|||
                rfq_limited = purchase_order.search([ | 
				
			|||
                    '|', ('user_id', '=', user), | 
				
			|||
                    ('partner_id', '=', request.env.user.partner_id.id), | 
				
			|||
                    ('state', 'in', ['draft', 'sent', 'to approve']) | 
				
			|||
                ], limit=int(number_po)) | 
				
			|||
            if show_project: | 
				
			|||
                number_project = config_parameters.get_param( | 
				
			|||
                    'all_in_one_website_kit.project_count', 0) | 
				
			|||
                projects_limited = project.search([], | 
				
			|||
                                                  limit=int(number_project)) | 
				
			|||
                tasks_limited = task.search([], limit=int(number_project)) | 
				
			|||
            if show_account: | 
				
			|||
                number_account = config_parameters.get_param( | 
				
			|||
                    'all_in_one_website_kit.account_count', 0) | 
				
			|||
                invoices_limited = account_move.search([ | 
				
			|||
                    ('partner_id', '=', user.partner_id.id), | 
				
			|||
                    ('state', 'not in', ['draft', 'cancel']) | 
				
			|||
                ], limit=int(number_account)) | 
				
			|||
            sale_orders = order_id.search([ | 
				
			|||
                '|', ('user_id', '=', user), | 
				
			|||
                ('partner_id', '=', request.env.user.partner_id.id), | 
				
			|||
                ('access_token', '!=', False), | 
				
			|||
                ('state', 'not in', ['draft', 'sent']) | 
				
			|||
            ]) | 
				
			|||
            quotations = request.env['sale.order'].sudo().search([ | 
				
			|||
                '|', ('user_id', '=', user), | 
				
			|||
                ('partner_id', '=', request.env.user.partner_id.id), | 
				
			|||
                ('state', '=', 'sent') | 
				
			|||
            ]) | 
				
			|||
            purchase_orders = purchase_order.search([ | 
				
			|||
                '|', ('user_id', '=', user), | 
				
			|||
                ('partner_id', '=', request.env.user.partner_id.id), | 
				
			|||
                ('state', 'not in', ['draft', 'sent', 'to approve']) | 
				
			|||
            ]) | 
				
			|||
            rfq = purchase_order.search([ | 
				
			|||
                '|', ('user_id', '=', user), | 
				
			|||
                ('partner_id', '=', request.env.user.partner_id.id), | 
				
			|||
                ('state', '=', 'sent') | 
				
			|||
            ]) | 
				
			|||
            projects = project.search([]) | 
				
			|||
            tasks = task.search([]) | 
				
			|||
            invoices = account_move.search([('access_token', '!=', False)]) | 
				
			|||
        else: | 
				
			|||
            if show_so_q: | 
				
			|||
                number_order = config_parameters.get_param( | 
				
			|||
                    'all_in_one_website_kit.sale_count', 0) | 
				
			|||
                sale_orders_limited = order_id.search([ | 
				
			|||
                    ('partner_id', '=', partners.partner_id.id), | 
				
			|||
                    ('state', 'not in', ['draft', 'sent']) | 
				
			|||
                ], limit=int(number_order)) | 
				
			|||
                quotations_limited = order_id.search([ | 
				
			|||
                    ('partner_id', '=', partners.partner_id.id), | 
				
			|||
                    ('state', 'in', ['sent']) | 
				
			|||
                ], limit=int(number_order)) | 
				
			|||
            if show_po_rfq: | 
				
			|||
                number_po = config_parameters.get_param( | 
				
			|||
                    'all_in_one_website_kit.purchase_count', 0) | 
				
			|||
                purchase_orders_limited = purchase_order.search([ | 
				
			|||
                    ('partner_id', '=', partners.partner_id.id), | 
				
			|||
                    ('state', 'not in', ['draft', 'sent', 'to approve']) | 
				
			|||
                ], limit=int(number_po)) | 
				
			|||
                rfq_limited = purchase_order.search([ | 
				
			|||
                    ('partner_id', '=', partners.partner_id.id), | 
				
			|||
                    ('state', 'in', ['draft', 'sent', 'to approve']) | 
				
			|||
                ], limit=int(number_po)) | 
				
			|||
            if show_project: | 
				
			|||
                number_project = config_parameters.get_param( | 
				
			|||
                    'all_in_one_website_kit.project_count', 0) | 
				
			|||
                projects_limited = project.search([('user_id', '=', user)], | 
				
			|||
                                                  limit=int(number_project)) | 
				
			|||
                tasks_limited = task.search([('user_id', '=', user)], | 
				
			|||
                                            limit=int(number_project)) | 
				
			|||
            if show_account: | 
				
			|||
                number_account = config_parameters.get_param( | 
				
			|||
                    'all_in_one_website_kit.account_count', 0) | 
				
			|||
                invoices_limited = account_move.search([ | 
				
			|||
                    ('partner_id', '=', partners.partner_id.id), | 
				
			|||
                    ('state', 'not in', ['draft', 'cancel']) | 
				
			|||
                ], limit=int(number_account)) | 
				
			|||
            sale_orders = order_id.search([ | 
				
			|||
                '|', ('user_id', '=', user), | 
				
			|||
                ('partner_id', '=', partners.partner_id.id), | 
				
			|||
                ('state', 'not in', ['draft', 'sent']) | 
				
			|||
            ]) | 
				
			|||
            quotations = order_id.search([ | 
				
			|||
                '|', ('user_id', '=', user), | 
				
			|||
                ('partner_id', '=', partners.partner_id.id), | 
				
			|||
                ('state', 'in', ['sent']) | 
				
			|||
            ]) | 
				
			|||
            purchase_orders = purchase_order.search([ | 
				
			|||
                '|', ('user_id', '=', user), | 
				
			|||
                ('partner_id', '=', partners.partner_id.id), | 
				
			|||
                ('state', 'not in', ['draft', 'sent', 'to approve']) | 
				
			|||
            ]) | 
				
			|||
            rfq = purchase_order.search([ | 
				
			|||
                '|', ('user_id', '=', user), | 
				
			|||
                ('partner_id', '=', partners.partner_id.id), | 
				
			|||
                ('state', 'in', ['sent', 'to approve']) | 
				
			|||
            ]) | 
				
			|||
            projects = project.search([ | 
				
			|||
                ('user_id', '=', user) | 
				
			|||
            ]) | 
				
			|||
            tasks = task.search([('user_id', '=', user)]) | 
				
			|||
            invoices = account_move.search([ | 
				
			|||
                ('access_token', '!=', False) | 
				
			|||
            ]) | 
				
			|||
        values = self._prepare_portal_layout_values() | 
				
			|||
        values['sale_order_portal'] = sale_orders | 
				
			|||
        values['quotation_portal'] = quotations | 
				
			|||
        values['counts_quotation'] = len(quotations) | 
				
			|||
        values['purchase_orders_portal'] = purchase_orders | 
				
			|||
        values['rfq_portal'] = rfq | 
				
			|||
        values['projects_portal'] = projects | 
				
			|||
        values['tasks_portal'] = tasks | 
				
			|||
        values['invoices_portal'] = invoices | 
				
			|||
        values['number_so_portal'] = number_order | 
				
			|||
        values['number_po_portal'] = number_po | 
				
			|||
        values['number_account_portal'] = number_account | 
				
			|||
        values['number_project_portal'] = number_project | 
				
			|||
        values['sale_orders_limited'] = sale_orders_limited | 
				
			|||
        values['quotations_limited'] = quotations_limited | 
				
			|||
        values['purchase_orders_limited'] = purchase_orders_limited | 
				
			|||
        values['rfq_limited'] = rfq_limited | 
				
			|||
        values['invoices_limited'] = invoices_limited | 
				
			|||
        values['projects_limited'] = projects_limited | 
				
			|||
        values['tasks_limited'] = tasks_limited | 
				
			|||
        values['show_so_q'] = show_so_q | 
				
			|||
        values['show_po_rfq'] = show_po_rfq | 
				
			|||
        values['show_project'] = show_project | 
				
			|||
        values['show_account'] = show_account | 
				
			|||
        values['count_return_order'] = request.env['sale.return'].search_count( | 
				
			|||
            [('user_id', '=', request.env.uid)]) | 
				
			|||
        return request.render( | 
				
			|||
            "all_in_one_website_kit.portal_dashboard_data", | 
				
			|||
            values) | 
				
			|||
 | 
				
			|||
    @route() | 
				
			|||
    def account(self, **post): | 
				
			|||
        """ Super CustomerPortal class function and pass the api key value | 
				
			|||
        from settings using params to website view file. """ | 
				
			|||
        res = super(ReturnCustomerPortal, self).account(**post) | 
				
			|||
        params = request.env['ir.config_parameter'].sudo() | 
				
			|||
        values = params.get_param('base_geolocalize.google_map_api_key') | 
				
			|||
        res.qcontext.update({ | 
				
			|||
            'api': values | 
				
			|||
        }) | 
				
			|||
        return res | 
				
			|||
 | 
				
			|||
    @http.route(['/geo/change/<coordinates>'], type='json', auth="none", | 
				
			|||
                website=False, csrf=False) | 
				
			|||
    def geo_changer(self, coordinates): | 
				
			|||
        """ Controller function for get address details  from latitude and | 
				
			|||
        longitude that we pinpointed in map using geopy package from python | 
				
			|||
 | 
				
			|||
        Parameters ---------- coordinates :The stringify value from map that | 
				
			|||
        contains latitude and longitude | 
				
			|||
 | 
				
			|||
        Returns ------- Returning the address details back to view file from | 
				
			|||
        the converted Latitude and longitude | 
				
			|||
        """ | 
				
			|||
        res = json.loads(coordinates) | 
				
			|||
        geolocator = Nominatim(user_agent="geoapiExercises") | 
				
			|||
        location = geolocator.reverse( | 
				
			|||
            str(res.get('lat')) + "," + str(res.get('lng'))) | 
				
			|||
        city = "Undefined" | 
				
			|||
        suburb = "Undefined" | 
				
			|||
        state = "Undefined" | 
				
			|||
        country = "Undefined" | 
				
			|||
        p_code = "Undefined" | 
				
			|||
        if location: | 
				
			|||
            addresses = location.raw['address'] | 
				
			|||
            if addresses.get('village'): | 
				
			|||
                city = addresses.get('village') | 
				
			|||
            if addresses.get('suburb'): | 
				
			|||
                suburb = addresses.get('suburb') | 
				
			|||
            state = addresses.get('state') | 
				
			|||
            country_code = addresses.get('country_code') | 
				
			|||
            country = pytz.country_names[country_code] | 
				
			|||
            if addresses.get('postcode'): | 
				
			|||
                p_code = addresses.get('postcode') | 
				
			|||
        return { | 
				
			|||
            'city': city, | 
				
			|||
            'suburb': suburb, | 
				
			|||
            'state': state, | 
				
			|||
            'country': country, | 
				
			|||
            'p_code': p_code, | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    @http.route(['/geo/location/<address>'], type='json', auth="none", | 
				
			|||
                website=False, csrf=False) | 
				
			|||
    def geo_location(self, address): | 
				
			|||
        """ Get value from city field in 'my_account' page and convert into | 
				
			|||
        lat and long and return back to website and set the map and fields | 
				
			|||
        Parameters ---------- address : The city name that in city field in | 
				
			|||
        website | 
				
			|||
 | 
				
			|||
        Returns | 
				
			|||
        ------- | 
				
			|||
        Pass the value to website view and set required fields and map | 
				
			|||
 | 
				
			|||
        """ | 
				
			|||
        locator = Nominatim(user_agent="myGeocoder") | 
				
			|||
        location = locator.geocode(address) | 
				
			|||
        geolocator = Nominatim(user_agent="geoapiExercises") | 
				
			|||
        location_country = geolocator.reverse( | 
				
			|||
            str(location.latitude) + "," + str(location.longitude)) | 
				
			|||
        addresses = location_country.raw['address'] | 
				
			|||
        country_code = addresses.get('country_code') | 
				
			|||
        country = pytz.country_names[country_code] | 
				
			|||
        p_code = "undefined" | 
				
			|||
        if addresses.get('postcode'): | 
				
			|||
            p_code = addresses.get('postcode') | 
				
			|||
        return { | 
				
			|||
            'lat': location.latitude, | 
				
			|||
            'lng': location.longitude, | 
				
			|||
            'country': country, | 
				
			|||
            'p_code': p_code | 
				
			|||
        } | 
				
			|||
@ -0,0 +1,95 @@ | 
				
			|||
# -*- 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/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
import base64 | 
				
			|||
import io | 
				
			|||
from werkzeug.utils import redirect | 
				
			|||
from odoo import http | 
				
			|||
from odoo.http import request | 
				
			|||
from odoo.addons.http_routing.models.ir_http import slug | 
				
			|||
from odoo.addons.website_sale.controllers.main import WebsiteSale | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class WebsiteSale(WebsiteSale): | 
				
			|||
    """ The class WebsiteProductBarcode is used for getting product with scanned | 
				
			|||
        barcode. """ | 
				
			|||
    @http.route([ | 
				
			|||
        '/shop/barcodeproduct'], type='json', auth="user", website=True, | 
				
			|||
        methods=['GET', 'POST']) | 
				
			|||
    def product_barcode(self, **kwargs): | 
				
			|||
        """ checking the is scanned or not  and passes the corresponding | 
				
			|||
            values""" | 
				
			|||
        barcode_product = request.env['product.product'].search( | 
				
			|||
            [('barcode', '=', kwargs.get('last_code'))]) | 
				
			|||
        if barcode_product: | 
				
			|||
            return { | 
				
			|||
                'type': 'ir.actions.act_url', | 
				
			|||
                'url': '/shop/%s' % slug(barcode_product.product_tmpl_id) | 
				
			|||
            } | 
				
			|||
        else: | 
				
			|||
            return False | 
				
			|||
 | 
				
			|||
    @http.route(['/shop/<model("product.template"):product>'], type='http', | 
				
			|||
                auth="public", website=True) | 
				
			|||
    def product(self, product, category='', search='', **kwargs): | 
				
			|||
        """ Supering the controller to pass the values. """ | 
				
			|||
        res = super(WebsiteSale, self).product(product, category='', search='', | 
				
			|||
                                               **kwargs) | 
				
			|||
        res.qcontext['attachments'] = request.env[ | 
				
			|||
            'ir.attachment'].sudo().search( | 
				
			|||
            [('res_model', '=', 'product.template'), | 
				
			|||
             ('res_id', '=', product.id)], order='id') | 
				
			|||
        return res | 
				
			|||
 | 
				
			|||
    def _get_attribute_exclusion(self, product, reference_product=None): | 
				
			|||
        """ Check the product variant. """ | 
				
			|||
        parent_combination = request.env['product.template.attribute.value'] | 
				
			|||
        if reference_product: | 
				
			|||
            parent_combination |= reference_product.product_template_attribute_value_ids | 
				
			|||
            if reference_product.env.context.get('no_variant_attribute_values'): | 
				
			|||
                # Add "no_variant" attribute values' exclusions | 
				
			|||
                # They are kept in the context since they are not linked to this | 
				
			|||
                # product variant | 
				
			|||
                parent_combination |= reference_product.env.context.get( | 
				
			|||
                    'no_variant_attribute_values') | 
				
			|||
        return product._get_attribute_exclusions(parent_combination) | 
				
			|||
 | 
				
			|||
    @http.route(['/attachment/download', ], type='http', auth='public') | 
				
			|||
    def download_attachment(self, attachment_id): | 
				
			|||
        """ To download the document of the product. """ | 
				
			|||
        # Check if this is a valid attachment id | 
				
			|||
        attachment = request.env['ir.attachment'].sudo().browse( | 
				
			|||
            int(attachment_id)) | 
				
			|||
        if attachment: | 
				
			|||
            attachment = attachment[0] | 
				
			|||
        else: | 
				
			|||
            return redirect('/shop') | 
				
			|||
        if attachment["type"] == "url": | 
				
			|||
            if attachment["url"]: | 
				
			|||
                return redirect(attachment["url"]) | 
				
			|||
            else: | 
				
			|||
                return request.not_found() | 
				
			|||
        elif attachment["datas"]: | 
				
			|||
            data = io.BytesIO(base64.standard_b64decode(attachment["datas"])) | 
				
			|||
            return http.send_file(data, filename=attachment['name'], | 
				
			|||
                                  as_attachment=True) | 
				
			|||
        else: | 
				
			|||
            return request.not_found() | 
				
			|||
@ -0,0 +1,11 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8" ?> | 
				
			|||
<odoo> | 
				
			|||
    <data noupdate="1"> | 
				
			|||
        <record id="insta_profile_id" model="ir.sequence"> | 
				
			|||
            <field name="name">Profile ID</field> | 
				
			|||
            <field name="code">insta.profile</field> | 
				
			|||
            <field name="prefix">INST</field> | 
				
			|||
            <field name="padding">2</field> | 
				
			|||
        </record> | 
				
			|||
    </data> | 
				
			|||
</odoo> | 
				
			|||
@ -0,0 +1,13 @@ | 
				
			|||
<?xml version="1.0" encoding="UTF-8"?> | 
				
			|||
<odoo> | 
				
			|||
    <data noupdate="1"> | 
				
			|||
        <!-- Sequence for sale return --> | 
				
			|||
        <record id="sale_return_ir_sequence" model="ir.sequence"> | 
				
			|||
            <field name="name">Sale Return</field> | 
				
			|||
            <field name="code">sale.return</field> | 
				
			|||
            <field name="prefix">RET</field> | 
				
			|||
            <field name="padding">5</field> | 
				
			|||
            <field name="company_id" eval="False"/> | 
				
			|||
        </record> | 
				
			|||
    </data> | 
				
			|||
</odoo> | 
				
			|||
@ -0,0 +1,6 @@ | 
				
			|||
## Module <all_in_one_website_kit> | 
				
			|||
 | 
				
			|||
#### 03.09.2024 | 
				
			|||
#### Version 15.0.1.0.0 | 
				
			|||
##### ADD | 
				
			|||
- Initial Commit for All In One Website Kit | 
				
			|||
@ -0,0 +1,33 @@ | 
				
			|||
# -*- 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 . import call_price | 
				
			|||
from . import insta_post | 
				
			|||
from . import insta_profile | 
				
			|||
from . import portal_dashboard_data | 
				
			|||
from . import product_product | 
				
			|||
from . import product_template | 
				
			|||
from . import res_config_settings | 
				
			|||
from . import sale_order | 
				
			|||
from . import sale_return | 
				
			|||
from . import stock_picking | 
				
			|||
from . import stock_return_picking | 
				
			|||
from . import website | 
				
			|||
@ -0,0 +1,67 @@ | 
				
			|||
# -*- 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 odoo import api, fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class CallPrice(models.Model): | 
				
			|||
    """ Creating a model to record all the request for price from website. """ | 
				
			|||
    _name = 'call.price' | 
				
			|||
    _description = 'Call for Price' | 
				
			|||
    _rec_name = 'product_id' | 
				
			|||
 | 
				
			|||
    first_name = fields.Char(string="First Name", help="First Name of user") | 
				
			|||
    last_name = fields.Char(string="Last Name", help="Last Name of user") | 
				
			|||
    product_id = fields.Many2one('product.template', string="Product", | 
				
			|||
                                 help="In which product " | 
				
			|||
                                      "they are requesting price") | 
				
			|||
    email = fields.Char(string="Email", help="Users email for contact") | 
				
			|||
    phone = fields.Char(string="Contact No.", | 
				
			|||
                        help="Users contact number for contacting") | 
				
			|||
    quantity = fields.Float(string="Quantity", | 
				
			|||
                              help="How much quantity of product price " | 
				
			|||
                                   "they want know") | 
				
			|||
    message = fields.Char(string="Message", | 
				
			|||
                          help="If any messages for referring") | 
				
			|||
    state = fields.Selection( | 
				
			|||
        [('draft', 'Draft'), ('done', 'Done'), ('cancel', 'Cancel')], | 
				
			|||
        default="draft", help="Call for price requests stage", string="State") | 
				
			|||
 | 
				
			|||
    def action_done(self): | 
				
			|||
        """ Change state of the form to 'done'. """ | 
				
			|||
        self.write({'state': 'done'}) | 
				
			|||
 | 
				
			|||
    def action_cancel(self): | 
				
			|||
        """ Cancel the form and change the state to cancel. """ | 
				
			|||
        self.write({'state': 'cancel'}) | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def create_form(self, first, last, product_id, phone, email, message, qty): | 
				
			|||
        """ Create the request from the users in the backend. """ | 
				
			|||
        self.create({ | 
				
			|||
            'product_id': product_id, | 
				
			|||
            'first_name': first, | 
				
			|||
            'last_name': last, | 
				
			|||
            'phone': phone, | 
				
			|||
            'email': email, | 
				
			|||
            'quantity': qty, | 
				
			|||
            'message': message | 
				
			|||
        }) | 
				
			|||
@ -0,0 +1,57 @@ | 
				
			|||
# -*- 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/>. | 
				
			|||
# | 
				
			|||
############################################################################### | 
				
			|||
import requests | 
				
			|||
from odoo import _, fields, models | 
				
			|||
from odoo.exceptions import UserError | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class InstaPost(models.Model): | 
				
			|||
    """ In the class InstaPost getting the posts of corresponding selected | 
				
			|||
        instagram account. """ | 
				
			|||
    _name = 'insta.post' | 
				
			|||
    _description = 'Insta Post' | 
				
			|||
 | 
				
			|||
    name = fields.Char(string="Media ID", help="The field defines Media ID") | 
				
			|||
    caption = fields.Char(string="Caption", | 
				
			|||
                          help="This field defines the caption") | 
				
			|||
    post_image = fields.Binary(string='Post Image', attachment=True, | 
				
			|||
                               help="The field is defined for attaching the" | 
				
			|||
                                    "post image") | 
				
			|||
    profile_id = fields.Many2one('insta.profile', | 
				
			|||
                                 string="Profile ID", | 
				
			|||
                                 help="The field defines the insta profile id") | 
				
			|||
 | 
				
			|||
    def action_update_post(self, access_token): | 
				
			|||
        """ Action for updating the posts """ | 
				
			|||
        url = ('https://graph.facebook.com/v15.0/%s?fields=id,caption,' + | 
				
			|||
               'comments_count,is_comment_enabled,like_count,' + | 
				
			|||
               'media_product_type,media_type,media_url,owner,permalink,' + | 
				
			|||
               'thumbnail_url,timestamp,username&access_token=%s') % ( | 
				
			|||
                  self.name, access_token) | 
				
			|||
        media_content = requests.get(url, timeout=5).json() | 
				
			|||
        if not media_content.get('error'): | 
				
			|||
            if media_content.get('caption'): | 
				
			|||
                self.write({ | 
				
			|||
                    'caption': media_content['caption'], | 
				
			|||
                }) | 
				
			|||
        else: | 
				
			|||
            raise UserError(_('%s', media_content['error']['message'])) | 
				
			|||
@ -0,0 +1,119 @@ | 
				
			|||
# -*- 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/>. | 
				
			|||
# | 
				
			|||
############################################################################### | 
				
			|||
import base64 | 
				
			|||
import requests | 
				
			|||
from odoo import _, api, fields, models | 
				
			|||
from odoo.exceptions import UserError | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class InstaProfile(models.Model): | 
				
			|||
    """class for adding instagram account""" | 
				
			|||
    _name = 'insta.profile' | 
				
			|||
    _description = 'Insta Profile' | 
				
			|||
 | 
				
			|||
    name = fields.Char(string="Name", readonly=True, | 
				
			|||
                       help="The name for the insta profile.") | 
				
			|||
    access_token = fields.Char(string="Access Token", required=True, | 
				
			|||
                               help="The Access Token for the insta profile.") | 
				
			|||
    username = fields.Char(string='Username', readonly=True, | 
				
			|||
                           help="The field defines the user name") | 
				
			|||
    account_id = fields.Char(string='Account ID', readonly=True, | 
				
			|||
                             help="The field defines the Account id for the" | 
				
			|||
                                  " insta profile") | 
				
			|||
    profile_image_url = fields.Binary(attachment=True, string="Profile Image", | 
				
			|||
                                      help="The profile image can upload here.") | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def create(self, vals): | 
				
			|||
        """" To generate sequence for instagram profiles """ | 
				
			|||
        if vals.get('name', 'New') == 'New': | 
				
			|||
            vals['name'] = self.env['ir.sequence'].next_by_code( | 
				
			|||
                'insta.profile') or 'New' | 
				
			|||
        result = super(InstaProfile, self).create(vals) | 
				
			|||
        return result | 
				
			|||
 | 
				
			|||
    def action_fetch(self): | 
				
			|||
        """ The action is to check the accounts with the given | 
				
			|||
        access token """ | 
				
			|||
        url = ('https://graph.facebook.com/v15.0/me/accounts?access_token=%s' | 
				
			|||
               % self.access_token) | 
				
			|||
        page = requests.get(url) | 
				
			|||
        page_content = page.json() | 
				
			|||
        if not page_content.get('error'): | 
				
			|||
            if page_content['data'][0]['id']: | 
				
			|||
                url = 'https://graph.facebook.com/v14.0/%s?fields=instagram_business_account&access_token=%s' % ( | 
				
			|||
                    page_content['data'][0]['id'], self.access_token) | 
				
			|||
                business_account = requests.get(url) | 
				
			|||
                instagram_business_account = \ | 
				
			|||
                    business_account.json()['instagram_business_account']['id'] | 
				
			|||
                url = ('https://graph.facebook.com/v15.0/%s?fields=name,username,biography,website,followers_count,follows_count,media_count,profile_picture_url&access_token=%s' | 
				
			|||
                       % (instagram_business_account, self.access_token)) | 
				
			|||
                val = requests.get(url) | 
				
			|||
                content = val.json() | 
				
			|||
                if content.get('name'): | 
				
			|||
                    self.name = content['name'] | 
				
			|||
                if content.get('username'): | 
				
			|||
                    self.username = content['username'] | 
				
			|||
                if content.get('id'): | 
				
			|||
                    self.account_id = content['id'] | 
				
			|||
                if content.get('profile_picture_url'): | 
				
			|||
                    img = base64.b64encode( | 
				
			|||
                        requests.get(content['profile_picture_url']).content) | 
				
			|||
                    self.profile_image_url = img | 
				
			|||
        else: | 
				
			|||
            raise UserError(_('%s', page_content['error']['message'])) | 
				
			|||
 | 
				
			|||
    def action_get_post(self): | 
				
			|||
        """ For getting and write posts to insta post model """ | 
				
			|||
        url = 'https://graph.facebook.com/v15.0/%s/media?access_token=%s' % ( | 
				
			|||
            self.account_id, self.access_token) | 
				
			|||
        content = requests.get(url, timeout=5).json() | 
				
			|||
        if not content.get('error'): | 
				
			|||
            post_list = [post.name for post in | 
				
			|||
                         self.env['insta.post'].search([])] | 
				
			|||
            if content.get('data'): | 
				
			|||
                for vals in content['data']: | 
				
			|||
                    if vals['id'] not in post_list: | 
				
			|||
                        url = 'https://graph.facebook.com/v14.0/%s?fields=id,caption,comments_count,is_comment_enabled,like_count,media_product_type,media_type,media_url,owner,permalink,thumbnail_url,timestamp,username&access_token=%s' % ( | 
				
			|||
                            vals['id'], self.access_token) | 
				
			|||
                        media_content = requests.get(url, timeout=5).json() | 
				
			|||
                        if media_content.get('media_type'): | 
				
			|||
                            if media_content['media_type'] == 'IMAGE': | 
				
			|||
                                res = self.env['insta.post'].create({ | 
				
			|||
                                    'name': media_content['id'], | 
				
			|||
                                    'profile_id': self.id, | 
				
			|||
                                }) | 
				
			|||
                                image_data = base64.b64encode(requests.get( | 
				
			|||
                                    media_content['media_url']).content) | 
				
			|||
                                res.write({ | 
				
			|||
                                    'post_image': image_data, | 
				
			|||
                                }) | 
				
			|||
                                if media_content.get('caption'): | 
				
			|||
                                    res.write({ | 
				
			|||
                                        'caption': media_content['caption'], | 
				
			|||
                                    }) | 
				
			|||
                    else: | 
				
			|||
                        record = self.env['insta.post'].search( | 
				
			|||
                            [('name', '=', vals['id'])]) | 
				
			|||
                        record.action_update_post(self.access_token) | 
				
			|||
        else: | 
				
			|||
            raise UserError(_('%s', content['error']['message'])) | 
				
			|||
@ -0,0 +1,61 @@ | 
				
			|||
# -*- 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 odoo import api, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class PortalDashboardData(models.Model): | 
				
			|||
    """ Used to set graphs in portal dashboard template """ | 
				
			|||
    _name = 'portal.dashboard.data' | 
				
			|||
    _description = 'Portal Dashboard Data' | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def datafetch(self): | 
				
			|||
        """ To fetch data of backend documents to display in the portal | 
				
			|||
        dashboard depending on count of records. """ | 
				
			|||
        user = self.env.user | 
				
			|||
        group_id = self.env.ref('base.group_user') | 
				
			|||
        if group_id in user.groups_id: | 
				
			|||
            all_invoice = self.env['account.move'].search_count([ | 
				
			|||
                ('state', 'not in', ['draft', 'cancel']), | 
				
			|||
                ('partner_id', '=', user.partner_id.id)]) | 
				
			|||
            all_accounting = [all_invoice] | 
				
			|||
        else: | 
				
			|||
            all_invoice = self.env['account.move'].search_count([ | 
				
			|||
                ('partner_id', '=', user.partner_id.id), | 
				
			|||
                ('state', 'not in', ['draft', 'cancel'])]) | 
				
			|||
            all_accounting = [all_invoice] | 
				
			|||
        order_id = self.env['sale.order'].search_count([ | 
				
			|||
            ('user_id', '=', user.id), | 
				
			|||
            ('state', 'not in', ['draft', 'sent'])]) | 
				
			|||
        quotations = self.env['sale.order'].search_count([ | 
				
			|||
            ('user_id', '=', user.id), ('state', 'in', ['sent'])]) | 
				
			|||
        purchase_order = self.env['purchase.order'].search_count([ | 
				
			|||
            ('user_id', '=', user.id), | 
				
			|||
            ('state', 'not in', ['draft', 'sent', 'to approve'])]) | 
				
			|||
        purchase_rfq = self.env['purchase.order'].search_count([ | 
				
			|||
            ('user_id', '=', user.id), | 
				
			|||
            ('state', 'in', ['sent', 'to approve'])]) | 
				
			|||
        return { | 
				
			|||
            'target': [order_id, quotations], | 
				
			|||
            'target_po': [purchase_order, purchase_rfq], | 
				
			|||
            'target_accounting': all_accounting | 
				
			|||
        } | 
				
			|||
@ -0,0 +1,32 @@ | 
				
			|||
# -*- 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 odoo import fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class ProductProduct(models.Model): | 
				
			|||
    """ Field to hide the product variants in website """ | 
				
			|||
    _inherit = 'product.product' | 
				
			|||
 | 
				
			|||
    website_hide_variants = fields.Boolean(string="Hide on Website", | 
				
			|||
                                           help="Check right if you want to " | 
				
			|||
                                                "hide the variant in your " | 
				
			|||
                                                "website") | 
				
			|||
@ -0,0 +1,33 @@ | 
				
			|||
# -*- 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 odoo import fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class ProductTemplate(models.Model): | 
				
			|||
    """ Inheriting product template model for adding a field that will hide | 
				
			|||
    price from website. """ | 
				
			|||
    _inherit = 'product.template' | 
				
			|||
 | 
				
			|||
    price_call = fields.Boolean(string="Call for Price", | 
				
			|||
                                help="This will hide the price and cart button" | 
				
			|||
                                     " from shop and customer can request by " | 
				
			|||
                                     "calling for price") | 
				
			|||
@ -0,0 +1,66 @@ | 
				
			|||
# -*- 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 odoo import fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class ResConfigSettings(models.TransientModel): | 
				
			|||
    """ Inherits res.config.settings to add new setting for enabling cusomer | 
				
			|||
    ratings and displaying records in portal. """ | 
				
			|||
    _inherit = 'res.config.settings' | 
				
			|||
 | 
				
			|||
    comment_configuration = fields.Boolean( | 
				
			|||
        config_parameter='all_in_one_website_kit.comment_configuration', | 
				
			|||
        string='Comment Configuration', help='Enable/ Disable the feature.') | 
				
			|||
    is_show_recent_so_q = fields.Boolean( | 
				
			|||
        string='Is show recent quotation and sale order table', | 
				
			|||
        config_parameter='all_in_one_website_kit.is_show_recent_so_q', | 
				
			|||
        help="Enable the field for show the recent quotation and" | 
				
			|||
             "sale order table ") | 
				
			|||
    sale_count = fields.Integer( | 
				
			|||
        string='How many recent records do you want to show?', | 
				
			|||
        config_parameter='all_in_one_website_kit.sale_count', | 
				
			|||
        help="The field shows the number of recent records want to show") | 
				
			|||
    is_show_recent_po_rfq = fields.Boolean( | 
				
			|||
        string='Is show recent RFQ table?', | 
				
			|||
        config_parameter='all_in_one_website_kit.is_show_recent_po_rfq', | 
				
			|||
        help="Enable the field to show the recent RFQ table.") | 
				
			|||
    purchase_count = fields.Integer( | 
				
			|||
        string='How many recent records do you want to show?', | 
				
			|||
        config_parameter='all_in_one_website_kit.purchase_count', | 
				
			|||
        help="The field shows the number of purchase records want to show.") | 
				
			|||
    is_show_project = fields.Boolean( | 
				
			|||
        string='Is show project task table?', | 
				
			|||
        config_parameter='all_in_one_website_kit.is_show_project', | 
				
			|||
        help="Enable the field to show the project task table.") | 
				
			|||
    project_count = fields.Integer( | 
				
			|||
        string='How many recent records do you want to show?', | 
				
			|||
        config_parameter='all_in_one_website_kit.project_count', | 
				
			|||
        help="The field shows the recent project records want to show.") | 
				
			|||
    is_show_recent_invoice_bill = fields.Boolean( | 
				
			|||
        string='Is show recent invoice/bill table?', | 
				
			|||
        config_parameter='all_in_one_website_kit.is_show_recent_invoice_bill', | 
				
			|||
        help="Enable the field to show the recent invoice/bill.") | 
				
			|||
    account_count = fields.Integer( | 
				
			|||
        string='How many recent records do you want to show?', | 
				
			|||
        config_parameter='all_in_one_website_kit.account_count', | 
				
			|||
        help="The field shows the number of recent invoice/bill records" | 
				
			|||
             "want to show.") | 
				
			|||
@ -0,0 +1,60 @@ | 
				
			|||
# -*- 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 LESSER | 
				
			|||
#    GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
				
			|||
#    (LGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
############################################################################### | 
				
			|||
from odoo import fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class SaleOrder(models.Model): | 
				
			|||
    """ Inherits sale order to add the fields comment and rating """ | 
				
			|||
    _inherit = 'sale.order' | 
				
			|||
 | 
				
			|||
    comment = fields.Char(string='Comment', readonly=True, | 
				
			|||
                          help='The comment provided by the customer.') | 
				
			|||
    rating = fields.Selection([ | 
				
			|||
        ('1', 'Poor'), ('2', 'Too Bad'), ('3', 'Average Quality'), | 
				
			|||
        ('4', 'Nice'), ('5', 'Good')], string='Rating', readonly=True, | 
				
			|||
        help='The rating provided by the customer.') | 
				
			|||
    return_order_count = fields.Integer(compute="_compute_return_order_count", | 
				
			|||
                                        string='Return Orders') | 
				
			|||
 | 
				
			|||
    def _compute_return_order_count(self): | 
				
			|||
        """ Method to compute return count """ | 
				
			|||
        sale_return_groups = self.env['sale.return'].sudo().read_group( | 
				
			|||
            domain=[('order_id', '=', self.ids)], | 
				
			|||
            fields=['order_id'], groupby=['order_id']) | 
				
			|||
        orders = self.browse() | 
				
			|||
        for group in sale_return_groups: | 
				
			|||
            order_id = self.browse(group['order_id'][0]) | 
				
			|||
            while order_id: | 
				
			|||
                if order_id in self: | 
				
			|||
                    order_id.return_order_count += group['order_id_count'] | 
				
			|||
                    orders |= order_id | 
				
			|||
                    order_id = False | 
				
			|||
        (self - orders).return_order_count = 0 | 
				
			|||
 | 
				
			|||
    def action_open_returns(self): | 
				
			|||
        """ This function returns an action that displays the return orders | 
				
			|||
        from sale order. """ | 
				
			|||
        action = self.env['ir.actions.act_window']._for_xml_id( | 
				
			|||
            'all_in_one_website_kit.sale_return_action') | 
				
			|||
        action['domain'] = [('order_id', '=', self.id)] | 
				
			|||
        action['context'] = {'search_default_order': 1} | 
				
			|||
        return action | 
				
			|||
@ -0,0 +1,264 @@ | 
				
			|||
# -*- 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 odoo import api, fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class SaleReturn(models.Model): | 
				
			|||
    """ Return of Sale Orders """ | 
				
			|||
    _name = 'sale.return' | 
				
			|||
    _description = "Return Order" | 
				
			|||
    _inherit = ['portal.mixin'] | 
				
			|||
    _rec_name = "name" | 
				
			|||
    _order = "name" | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def _get_default_name(self): | 
				
			|||
        """ Returns the default name to the sale return """ | 
				
			|||
        return self.env['ir.sequence'].get('sale.return') | 
				
			|||
 | 
				
			|||
    active = fields.Boolean(string='Active', default=True, | 
				
			|||
                            help="Enable the field to active the record") | 
				
			|||
    name = fields.Char(string="Name", default=_get_default_name, | 
				
			|||
                       help="The field returns the sequence number of " | 
				
			|||
                            "sales return.") | 
				
			|||
    product_id = fields.Many2one('product.product', string="Product Variant", | 
				
			|||
                                 required=True, | 
				
			|||
                                 help="Defines the product variant that need to" | 
				
			|||
                                      " be returned") | 
				
			|||
    product_tmpl_id = fields.Many2one('product.template', | 
				
			|||
                                      related="product_id.product_tmpl_id", | 
				
			|||
                                      store=True, string="Product", | 
				
			|||
                                      help="Defines the product") | 
				
			|||
    order_id = fields.Many2one('sale.order', string="Sale Order", required=True, | 
				
			|||
                               help="The field refer the sale order ") | 
				
			|||
    partner_id = fields.Many2one('res.partner', string="Customer", | 
				
			|||
                                 help="The field refer the partner") | 
				
			|||
    user_id = fields.Many2one('res.users', string="Responsible", | 
				
			|||
                              default=lambda self: self.env.user, | 
				
			|||
                              help="The field refer the user.") | 
				
			|||
    create_date = fields.Datetime(string="Create Date", | 
				
			|||
                                  help="The field shows the create date.") | 
				
			|||
    quantity = fields.Float(string="Quantity", default=0, | 
				
			|||
                            help='The field refer the quantity') | 
				
			|||
    received_qty = fields.Float(string="Received Quantity", | 
				
			|||
                                help="The field refer the received quantity") | 
				
			|||
    reason = fields.Text(string="Reason", | 
				
			|||
                         help="The field defines reason for the sale return") | 
				
			|||
    stock_picking_ids = fields.One2many('stock.picking', | 
				
			|||
                                        'return_order_pick_id', | 
				
			|||
                                        domain="[('return_order_id','=',False)]", | 
				
			|||
                                        string="Return Picking", | 
				
			|||
                                        help="Shows the return picking of the " | 
				
			|||
                                             "corresponding return order") | 
				
			|||
    picking_count = fields.Integer(compute="_compute_delivery_picking_count", | 
				
			|||
                                   string='Picking Order', copy=False, | 
				
			|||
                                   default=0, store=True, | 
				
			|||
                                   help="Field compute the count of picking") | 
				
			|||
    delivery_count = fields.Integer(compute="_compute_delivery_picking_count", | 
				
			|||
                                    string='Delivery Order', copy=False, | 
				
			|||
                                    default=0, store=True, | 
				
			|||
                                    help="Field compute the count of delivery") | 
				
			|||
    state = fields.Selection( | 
				
			|||
        [('draft', 'Draft'), ('confirm', 'Confirm'), ('done', 'Done'), | 
				
			|||
         ('cancel', 'Canceled')], string='Status', readonly=True, | 
				
			|||
        default='draft', help="Defines the state of sales return") | 
				
			|||
    source_pick_ids = fields.One2many('stock.picking', | 
				
			|||
                                      'return_order_id', | 
				
			|||
                                      string="Source Delivery", | 
				
			|||
                                      domain="[('return_order_pick_id','=',False)]", | 
				
			|||
                                      help="Shows the delivery orders of the " | 
				
			|||
                                           "corresponding return order") | 
				
			|||
    note = fields.Text(string="Note", help="The field can add the note") | 
				
			|||
    to_refund = fields.Boolean(string='Update SO/PO Quantity', | 
				
			|||
                               help='Trigger a decrease of the delivered/' | 
				
			|||
                                    'received quantity in' | 
				
			|||
                                    ' the associated Sale Order/Purchase Order') | 
				
			|||
 | 
				
			|||
    def return_confirm(self): | 
				
			|||
        """ Confirm the sale return """ | 
				
			|||
        if not self.source_pick_ids: | 
				
			|||
            stock_picks = self.env['stock.picking'].search( | 
				
			|||
                [('origin', '=', self.order_id.name)]) | 
				
			|||
            moves = stock_picks.mapped('move_ids_without_package').filtered( | 
				
			|||
                lambda p: p.product_id == self.product_id) | 
				
			|||
        else: | 
				
			|||
            moves = self.source_pick_ids.mapped( | 
				
			|||
                'move_ids_without_package').filtered( | 
				
			|||
                lambda p: p.product_id == self.product_id) | 
				
			|||
        if moves: | 
				
			|||
            moves = moves.sorted('product_uom_qty', reverse=True) | 
				
			|||
            pick = moves[0].picking_id | 
				
			|||
            vals = {'picking_id': pick.id} | 
				
			|||
            return_pick_wizard = self.env['stock.return.picking'].create(vals) | 
				
			|||
            return_pick_wizard._onchange_picking_id() | 
				
			|||
            return_pick_wizard.product_return_moves.unlink() | 
				
			|||
            lines = {'product_id': self.product_id.id, | 
				
			|||
                     "quantity": self.quantity, | 
				
			|||
                     'wizard_id': return_pick_wizard.id, | 
				
			|||
                     'move_id': moves[0].id, 'to_refund': self.to_refund} | 
				
			|||
            self.env['stock.return.picking.line'].create(lines) | 
				
			|||
            return_pick = return_pick_wizard._create_returns() | 
				
			|||
            if return_pick: | 
				
			|||
                return_pick = self.env['stock.picking'].browse(return_pick[0]) | 
				
			|||
                return_pick.write( | 
				
			|||
                    { | 
				
			|||
                        'note': self.reason, | 
				
			|||
                        'return_order_id': False, | 
				
			|||
                        'return_order_pick_id': self.id, | 
				
			|||
                        'return_order_picking': True}) | 
				
			|||
                self.write({'state': 'confirm'}) | 
				
			|||
 | 
				
			|||
    def return_cancel(self): | 
				
			|||
        """ Cancel the return """ | 
				
			|||
        self.write({'state': 'cancel'}) | 
				
			|||
        if self.stock_picking_ids: | 
				
			|||
            for rec in self.stock_picking_ids.filtered( | 
				
			|||
                    lambda s: s.state not in ['done', 'cancel']): | 
				
			|||
                rec.action_cancel() | 
				
			|||
 | 
				
			|||
    def _get_report_base_filename(self): | 
				
			|||
        """ Passing the record name as report name | 
				
			|||
        :return: | 
				
			|||
        """ | 
				
			|||
        self.ensure_one() | 
				
			|||
        return 'Sale Return - %s' % (self.name) | 
				
			|||
 | 
				
			|||
    def _compute_access_url(self): | 
				
			|||
        """ For computing the access url for each sale order """ | 
				
			|||
        super(SaleReturn, self)._compute_access_url() | 
				
			|||
        for order in self: | 
				
			|||
            order.access_url = '/my/return_orders/%s' % order.id | 
				
			|||
 | 
				
			|||
    @api.depends('stock_picking_ids', 'state') | 
				
			|||
    def _compute_delivery_picking_count(self): | 
				
			|||
        """ Function to compute picking and delivery counts """ | 
				
			|||
        for rec in self: | 
				
			|||
            rec.delivery_count = 0 | 
				
			|||
            rec.picking_count = 0 | 
				
			|||
            if rec.source_pick_ids: | 
				
			|||
                rec.delivery_count = len(rec.source_pick_ids) | 
				
			|||
            else: | 
				
			|||
                rec.delivery_count = self.env['stock.picking'].search_count( | 
				
			|||
                    [('return_order_id', 'in', self.ids), | 
				
			|||
                     ('return_order_picking', '=', False)]) | 
				
			|||
            if rec.stock_picking_ids: | 
				
			|||
                rec.picking_count = len(rec.stock_picking_ids) | 
				
			|||
            else: | 
				
			|||
                rec.picking_count = self.env['stock.picking'].search_count( | 
				
			|||
                    [('return_order_pick_id', 'in', self.ids), | 
				
			|||
                     ('return_order_picking', '=', True)]) | 
				
			|||
 | 
				
			|||
    def action_view_picking(self): | 
				
			|||
        """ Function to view the stock picking transfers """ | 
				
			|||
        action = self.env["ir.actions.actions"]._for_xml_id( | 
				
			|||
            "stock.action_picking_tree_all") | 
				
			|||
        pickings = self.mapped('stock_picking_ids') | 
				
			|||
        if not self.stock_picking_ids: | 
				
			|||
            pickings = self.env['stock.picking'].search( | 
				
			|||
                [('return_order_pick_id', '=', self.id), | 
				
			|||
                 ('return_order_picking', '=', True)]) | 
				
			|||
        if len(pickings) > 1: | 
				
			|||
            action['domain'] = [('id', 'in', pickings.ids)] | 
				
			|||
        elif pickings: | 
				
			|||
            form_view = [(self.env.ref('stock.view_picking_form').id, 'form')] | 
				
			|||
            if 'views' in action: | 
				
			|||
                action['views'] = form_view + [(state, view) for state, view in | 
				
			|||
                                               action['views'] if | 
				
			|||
                                               view != 'form'] | 
				
			|||
            else: | 
				
			|||
                action['views'] = form_view | 
				
			|||
            action['res_id'] = pickings.id | 
				
			|||
        # Prepare the context. | 
				
			|||
        picking_id = pickings.filtered( | 
				
			|||
            lambda l: l.picking_type_id.code == 'outgoing') | 
				
			|||
        if picking_id: | 
				
			|||
            picking_id = picking_id[0] | 
				
			|||
        else: | 
				
			|||
            picking_id = pickings[0] | 
				
			|||
        action['context'] = dict( | 
				
			|||
            self._context, | 
				
			|||
            default_partner_id=self.partner_id.id, | 
				
			|||
            default_picking_type_id=picking_id.picking_type_id.id) | 
				
			|||
        return action | 
				
			|||
 | 
				
			|||
    def action_view_delivery(self): | 
				
			|||
        """ Function to view the delivery transfers """ | 
				
			|||
        action = self.env["ir.actions.actions"]._for_xml_id( | 
				
			|||
            "stock.action_picking_tree_all") | 
				
			|||
        pickings = self.mapped('stock_picking_ids') | 
				
			|||
        if not self.stock_picking_ids: | 
				
			|||
            pickings = self.env['stock.picking'].search( | 
				
			|||
                [('return_order_id', '=', self.id), | 
				
			|||
                 ('return_order_picking', '=', False)]) | 
				
			|||
        if len(pickings) > 1: | 
				
			|||
            action['domain'] = [('id', 'in', pickings.ids)] | 
				
			|||
        elif pickings: | 
				
			|||
            form_view = [(self.env.ref('stock.view_picking_form').id, 'form')] | 
				
			|||
            if 'views' in action: | 
				
			|||
                action['views'] = form_view + [(state, view) for state, view in | 
				
			|||
                                               action['views'] if | 
				
			|||
                                               view != 'form'] | 
				
			|||
            else: | 
				
			|||
                action['views'] = form_view | 
				
			|||
            action['res_id'] = pickings.id | 
				
			|||
        # Prepare the context. | 
				
			|||
        picking_id = pickings.filtered( | 
				
			|||
            lambda l: l.picking_type_id.code == 'outgoing') | 
				
			|||
        if picking_id: | 
				
			|||
            picking_id = picking_id[0] | 
				
			|||
        else: | 
				
			|||
            picking_id = pickings[0] | 
				
			|||
        action['context'] = dict( | 
				
			|||
            self._context, | 
				
			|||
            default_partner_id=self.partner_id.id, | 
				
			|||
            default_picking_type_id=picking_id.picking_type_id.id) | 
				
			|||
        return action | 
				
			|||
 | 
				
			|||
    @api.onchange('order_id', 'source_pick_ids') | 
				
			|||
    def _onchange_sale_order(self): | 
				
			|||
        """ All the fields are updated according to the sale order """ | 
				
			|||
        delivery = None | 
				
			|||
        if self.order_id: | 
				
			|||
            self.partner_id = self.order_id.partner_id | 
				
			|||
            delivery = self.env['stock.picking'].search( | 
				
			|||
                [('origin', '=', self.order_id.name)]) | 
				
			|||
        if self.source_pick_ids: | 
				
			|||
            delivery = self.source_pick_ids | 
				
			|||
        if delivery: | 
				
			|||
            product_ids = delivery.move_ids_without_package.mapped( | 
				
			|||
                'product_id').ids | 
				
			|||
            delivery = delivery.ids | 
				
			|||
        else: | 
				
			|||
            product_ids = self.order_id.order_line.mapped('product_id').ids | 
				
			|||
        return {'domain': {'source_pick_ids': [('id', 'in', delivery)], | 
				
			|||
                           'product_id': [('id', 'in', product_ids)]}} | 
				
			|||
 | 
				
			|||
    @api.onchange('product_id') | 
				
			|||
    def _onchange_product_id(self): | 
				
			|||
        """ Update the received quantity based on the selected product and | 
				
			|||
        source pickings. """ | 
				
			|||
        if self.product_id and self.source_pick_ids: | 
				
			|||
            moves = self.source_pick_ids.mapped( | 
				
			|||
                'move_ids_without_package').filtered( | 
				
			|||
                lambda p: p.product_id == self.product_id) | 
				
			|||
            if moves: | 
				
			|||
                self.received_qty = sum(moves.mapped('quantity_done')) | 
				
			|||
@ -0,0 +1,53 @@ | 
				
			|||
# -*- 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 odoo import fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class StockPicking(models.Model): | 
				
			|||
    """ Inheriting the model stock picking and adding custom fields """ | 
				
			|||
    _inherit = 'stock.picking' | 
				
			|||
 | 
				
			|||
    return_order_id = fields.Many2one('sale.return', | 
				
			|||
                                      string='Return order', | 
				
			|||
                                      help="Shows the return order of current" | 
				
			|||
                                           "transfer") | 
				
			|||
    return_order_pick_id = fields.Many2one('sale.return', | 
				
			|||
                                           string='Return order Pick', | 
				
			|||
                                           help="Shows the return order picking" | 
				
			|||
                                                "of current return order") | 
				
			|||
    return_order_picking = fields.Boolean(string='Return order picking', | 
				
			|||
                                          help="Helps to identify delivery and " | 
				
			|||
                                               "return picking, if true the tra" | 
				
			|||
                                               "nsfer is return picking else de" | 
				
			|||
                                               "livery") | 
				
			|||
 | 
				
			|||
    def button_validate(self): | 
				
			|||
        """ Supering the function validating the stock moves """ | 
				
			|||
        res = super(StockPicking, self).button_validate() | 
				
			|||
        for rec in self: | 
				
			|||
            if rec.return_order_pick_id: | 
				
			|||
                if any(line.state != 'done' for line in | 
				
			|||
                       rec.return_order_pick_id.stock_picking_ids): | 
				
			|||
                    return res | 
				
			|||
                else: | 
				
			|||
                    rec.return_order_pick_id.write({'state': 'done'}) | 
				
			|||
        return res | 
				
			|||
@ -0,0 +1,40 @@ | 
				
			|||
# -*- 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 odoo import models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class StockReturnPicking(models.TransientModel): | 
				
			|||
    """ Inherit stock.return.picking to create return orders """ | 
				
			|||
    _inherit = 'stock.return.picking' | 
				
			|||
 | 
				
			|||
    def _create_returns(self): | 
				
			|||
        """ Creating return orders """ | 
				
			|||
        new_picking, pick_type_id = super( | 
				
			|||
            StockReturnPicking,self)._create_returns() | 
				
			|||
        picking = self.env['stock.picking'].browse(new_picking) | 
				
			|||
        if self.picking_id.return_order_id: | 
				
			|||
            picking.write({'return_order_picking': False, | 
				
			|||
                           'return_order_id': False, | 
				
			|||
                           'return_order_pick_id': | 
				
			|||
                               self.picking_id.return_order_id.id}) | 
				
			|||
            self.picking_id.return_order_id.write({'state': 'confirm'}) | 
				
			|||
        return new_picking, pick_type_id | 
				
			|||
@ -0,0 +1,92 @@ | 
				
			|||
# -*- 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 odoo import fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class Website(models.Model): | 
				
			|||
    """ Inheriting Website to add contact fields """ | 
				
			|||
    _inherit = 'website' | 
				
			|||
 | 
				
			|||
    mobile_number = fields.Char(string='Mobile Number', | 
				
			|||
                                help="Defines the mobile number") | 
				
			|||
    company = fields.Boolean(string="Company Name", | 
				
			|||
                             help='If it is true it will show company name on ' | 
				
			|||
                                  'website') | 
				
			|||
    address = fields.Boolean(string="Address", | 
				
			|||
                             help='If it is true it will show address on ' | 
				
			|||
                                  'website') | 
				
			|||
    phone = fields.Boolean(string="Phone", | 
				
			|||
                           help='If it is true it will show phone number on ' | 
				
			|||
                                'website') | 
				
			|||
    mobile = fields.Boolean(string="Mobile", | 
				
			|||
                            help='If it is true it will show mobile ' | 
				
			|||
                                 'number on website') | 
				
			|||
    email = fields.Boolean(string="Email", | 
				
			|||
                           help='If it is true it will show email ' | 
				
			|||
                                'on website') | 
				
			|||
    website = fields.Boolean(string="Website", | 
				
			|||
                             help='If it is true it will show ' | 
				
			|||
                                  'website name on website') | 
				
			|||
    vat = fields.Boolean(string="VAT", help='If it is true it will show tax id ' | 
				
			|||
                                            'on website') | 
				
			|||
    address_in_online = fields.Boolean(string="Address in one line", | 
				
			|||
                                       help='If it is true it will show address' | 
				
			|||
                                            ' in one line on website') | 
				
			|||
    hide_marker_icons = fields.Boolean(string="Hide Marker Icons", | 
				
			|||
                                       help='If it is true it will hide all ico' | 
				
			|||
                                            'ns of address on website') | 
				
			|||
    show_phone_icon = fields.Boolean(string="Show Phone Icons", | 
				
			|||
                                     help='If it is true it will show only phon' | 
				
			|||
                                          'e icons on website') | 
				
			|||
    country_flag = fields.Boolean(string="Country Flag", | 
				
			|||
                                  help='If it is true it will ' | 
				
			|||
                                       'show country flag on website') | 
				
			|||
    facebook = fields.Boolean(string="Facebook", | 
				
			|||
                              help='If it is true it will show ' | 
				
			|||
                                   'company name on website') | 
				
			|||
    social_facebook = fields.Char(string="Facebook Account", | 
				
			|||
                                  related='company_id.social_facebook', | 
				
			|||
                                  readonly=False, | 
				
			|||
                                  help="Company Facebook Account") | 
				
			|||
    twitter = fields.Boolean(string="Twitter", help='If it is true it will' | 
				
			|||
                                                    'show twitter on website') | 
				
			|||
    social_twitter = fields.Char(string="Twitter Account", | 
				
			|||
                                 related='company_id.social_twitter', | 
				
			|||
                                 readonly=False, help='Twitter account') | 
				
			|||
    linked_in = fields.Boolean(string="LinkedIn", | 
				
			|||
                               help='If it is true it will show twitter ' | 
				
			|||
                                    'on website') | 
				
			|||
    social_linked_in = fields.Char(string="Linkedin Account", | 
				
			|||
                                   related='company_id.social_linkedin', | 
				
			|||
                                   readonly=False, help='Linkedin account') | 
				
			|||
    instagram = fields.Boolean(string="Instagram", | 
				
			|||
                               help='If it is true it will show twitter on ' | 
				
			|||
                                    'website') | 
				
			|||
    social_instagram = fields.Char(string="Instagram Account", | 
				
			|||
                                   related='company_id.social_instagram', | 
				
			|||
                                   readonly=False, help='Instagram account') | 
				
			|||
    git_hub = fields.Boolean(string="GitHub", | 
				
			|||
                             help='If it is true it will show twitter on' | 
				
			|||
                                  ' website') | 
				
			|||
    social_git_hub = fields.Char(string="Github Account", | 
				
			|||
                                 related='company_id.social_github', | 
				
			|||
                                 readonly=False, help='Github Account') | 
				
			|||
@ -0,0 +1,14 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<odoo> | 
				
			|||
    <!-- Sales Return Report Record --> | 
				
			|||
    <record id="report_sale_return" model="ir.actions.report"> | 
				
			|||
        <field name="name">Sale Return</field> | 
				
			|||
        <field name="model">sale.return</field> | 
				
			|||
        <field name="report_type">qweb-pdf</field> | 
				
			|||
        <field name="report_name">all_in_one_website_kit.report_salereturn</field> | 
				
			|||
        <field name="report_file">all_in_one_website_kit.report_salereturn</field> | 
				
			|||
        <field name="print_report_name">'Sale Retun - %s' % object.name</field> | 
				
			|||
        <field name="binding_model_id" ref="model_sale_return"/> | 
				
			|||
        <field name="binding_type">report</field> | 
				
			|||
    </record> | 
				
			|||
</odoo> | 
				
			|||
@ -0,0 +1,75 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<odoo> | 
				
			|||
    <!-- Sales Return Report Template --> | 
				
			|||
    <template id="report_salereturn"> | 
				
			|||
        <t t-call="web.html_container"> | 
				
			|||
            <t t-foreach="docs" t-as="doc"> | 
				
			|||
                <t t-call="all_in_one_website_kit.report_sale_return_template" | 
				
			|||
                   t-lang="doc.partner_id.lang"/> | 
				
			|||
            </t> | 
				
			|||
        </t> | 
				
			|||
    </template> | 
				
			|||
    <template id="report_sale_return_template"> | 
				
			|||
        <t t-call="web.external_layout"> | 
				
			|||
            <t t-set="doc" | 
				
			|||
               t-value="doc.with_context(lang=doc.partner_id.lang)"/> | 
				
			|||
            <div class="page"> | 
				
			|||
                <div class="oe_structure"/> | 
				
			|||
                <h2 class="mt16"> | 
				
			|||
                    <span>Return Order #</span> | 
				
			|||
                    <span t-field="doc.name"/> | 
				
			|||
                </h2> | 
				
			|||
                <div class="row mt32 mb32" id="informations"> | 
				
			|||
                    <div t-if="doc.partner_id" | 
				
			|||
                         class="col-auto col-3 mw-100 mb-2"> | 
				
			|||
                        <strong>Customer:</strong> | 
				
			|||
                        <p class="m-0" t-field="doc.partner_id"/> | 
				
			|||
                    </div> | 
				
			|||
                    <div t-if="doc.order_id" class="col-auto col-3 mw-100 mb-2"> | 
				
			|||
                        <strong>Sale Order:</strong> | 
				
			|||
                        <p class="m-0" t-field="doc.order_id"/> | 
				
			|||
                    </div> | 
				
			|||
                    <div t-if="doc.create_date" | 
				
			|||
                         class="col-auto col-3 mw-100 mb-2"> | 
				
			|||
                        <strong>Creation Date:</strong> | 
				
			|||
                        <p class="m-0" t-field="doc.create_date" | 
				
			|||
                           t-options='{"widget": "date"}'/> | 
				
			|||
                    </div> | 
				
			|||
                    <div t-if="doc.user_id" | 
				
			|||
                         class="col-auto col-3 mw-100 mb-2" | 
				
			|||
                         name="expiration_date"> | 
				
			|||
                        <strong>Responsible:</strong> | 
				
			|||
                        <p class="m-0" t-field="doc.user_id"/> | 
				
			|||
                    </div> | 
				
			|||
                </div> | 
				
			|||
                <table class="table table-sm o_main_table"> | 
				
			|||
                    <!-- In case we want to repeat the header, remove "display: table-row-group" --> | 
				
			|||
                    <thead style="display: table-row-group"> | 
				
			|||
                        <tr> | 
				
			|||
                            <th name="th_description" class="text-left"> | 
				
			|||
                                Product | 
				
			|||
                            </th> | 
				
			|||
                            <th name="th_quantity" class="text-right">Quantity | 
				
			|||
                            </th> | 
				
			|||
                        </tr> | 
				
			|||
                    </thead> | 
				
			|||
                    <tbody class="sale_tbody"> | 
				
			|||
                        <tr t-att-class="'bg-200 font-weight-bold'"> | 
				
			|||
                            <td name="td_product"> | 
				
			|||
                                <span t-field="doc.product_id"/> | 
				
			|||
                            </td> | 
				
			|||
                            <td name="td_quantity" class="text-right"> | 
				
			|||
                                <span t-field="doc.quantity"/> | 
				
			|||
                                <span t-field="doc.product_id.uom_id"/> | 
				
			|||
                            </td> | 
				
			|||
                        </tr> | 
				
			|||
                    </tbody> | 
				
			|||
                </table> | 
				
			|||
                <div t-if="doc.partner_id" class="col-auto col-3 mw-100 mb-2"> | 
				
			|||
                    <strong>Reason:</strong> | 
				
			|||
                    <p class="m-0" t-field="doc.reason"/> | 
				
			|||
                </div> | 
				
			|||
            </div> | 
				
			|||
        </t> | 
				
			|||
    </template> | 
				
			|||
</odoo> | 
				
			|||
		
		
			
  | 
| 
		 After Width: | Height: | Size: 3.6 KiB  | 
| 
		 After Width: | Height: | Size: 310 B  | 
| 
		 After Width: | Height: | Size: 1.3 KiB  | 
| 
		 After Width: | Height: | Size: 1.4 KiB  | 
| 
		 After Width: | Height: | Size: 576 B  | 
| 
		 After Width: | Height: | Size: 733 B  | 
| 
		 After Width: | Height: | Size: 911 B  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 673 B  | 
| 
		 After Width: | Height: | Size: 878 B  | 
| 
		 After Width: | Height: | Size: 653 B  | 
| 
		 After Width: | Height: | Size: 905 B  | 
| 
		 After Width: | Height: | Size: 839 B  | 
| 
		 After Width: | Height: | Size: 427 B  | 
| 
		 After Width: | Height: | Size: 627 B  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 988 B  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 1.5 KiB  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 1.9 KiB  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 2.1 KiB  | 
| 
		 After Width: | Height: | Size: 4.4 KiB  | 
| 
		 After Width: | Height: | Size: 589 B  | 
| 
		 After Width: | Height: | Size: 3.4 KiB  | 
| 
		 After Width: | Height: | Size: 1.7 KiB  | 
| 
		 After Width: | Height: | Size: 2.3 KiB  | 
| 
		 After Width: | Height: | Size: 967 B  | 
| 
		 After Width: | Height: | Size: 1.6 KiB  | 
| 
		 After Width: | Height: | Size: 3.8 KiB  | 
| 
		 After Width: | Height: | Size: 5.0 KiB  | 
| 
		 After Width: | Height: | Size: 50 KiB  | 
| 
		 After Width: | Height: | Size: 47 KiB  | 
| 
		 After Width: | Height: | Size: 48 KiB  | 
| 
		 After Width: | Height: | Size: 49 KiB  | 
| 
		 After Width: | Height: | Size: 50 KiB  | 
| 
		 After Width: | Height: | Size: 48 KiB  | 
| 
		 After Width: | Height: | Size: 141 KiB  | 
| 
		 After Width: | Height: | Size: 218 KiB  | 
| 
		 After Width: | Height: | Size: 130 KiB  | 
| 
		 After Width: | Height: | Size: 25 KiB  | 
| 
		 After Width: | Height: | Size: 302 KiB  | 
| 
		 After Width: | Height: | Size: 501 KiB  | 
| 
		 After Width: | Height: | Size: 209 KiB  | 
| 
		 After Width: | Height: | Size: 112 KiB  | 
| 
		 After Width: | Height: | Size: 214 KiB  | 
| 
		 After Width: | Height: | Size: 156 KiB  | 
| 
		 After Width: | Height: | Size: 214 KiB  | 
| 
		 After Width: | Height: | Size: 39 KiB  | 
| 
		 After Width: | Height: | Size: 147 KiB  | 
| 
		 After Width: | Height: | Size: 94 KiB  | 
| 
		 After Width: | Height: | Size: 220 KiB  | 
| 
		 After Width: | Height: | Size: 97 KiB  | 
| 
		 After Width: | Height: | Size: 336 KiB  | 
| 
		 After Width: | Height: | Size: 482 KiB  | 
| 
		 After Width: | Height: | Size: 102 KiB  | 
| 
		 After Width: | Height: | Size: 180 KiB  | 
| 
		 After Width: | Height: | Size: 102 KiB  | 
| 
		 After Width: | Height: | Size: 60 KiB  | 
| 
		 After Width: | Height: | Size: 102 KiB  | 
| 
		 After Width: | Height: | Size: 103 KiB  | 
| 
		 After Width: | Height: | Size: 48 KiB  | 
| 
		 After Width: | Height: | Size: 190 KiB  | 
| 
		 After Width: | Height: | Size: 138 KiB  | 
| 
		 After Width: | Height: | Size: 506 KiB  | 
| 
		 After Width: | Height: | Size: 131 KiB  | 
| 
		 After Width: | Height: | Size: 96 KiB  | 
| 
		 After Width: | Height: | Size: 163 KiB  | 
| 
		 After Width: | Height: | Size: 137 KiB  | 
| 
		 After Width: | Height: | Size: 68 KiB  | 
| 
		 After Width: | Height: | Size: 94 KiB  |