diff --git a/odex25_donation/abs_prodcut_invoices/__init__.py b/odex25_donation/abs_prodcut_invoices/__init__.py new file mode 100644 index 000000000..9853e0707 --- /dev/null +++ b/odex25_donation/abs_prodcut_invoices/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################# +# +# Odoo, Open Source Management Solution +# Copyright (C) 2020-today Ascetic Business Solution +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# 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 for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################# + +from. import models \ No newline at end of file diff --git a/odex25_donation/abs_prodcut_invoices/__manifest__.py b/odex25_donation/abs_prodcut_invoices/__manifest__.py new file mode 100644 index 000000000..e9d3c4d5a --- /dev/null +++ b/odex25_donation/abs_prodcut_invoices/__manifest__.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +################################################################################# +# +# Odoo, Open Source Management Solution +# Copyright (C) 2020-today Ascetic Business Solution +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# 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 for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################# + +{ + 'name': "Total Sales and Purchase of the Product", + 'author': "Ascetic Business Solution", + 'category': 'Sales', + 'summary': """Total Sales and Purchase of the Product""", + 'website': 'http://www.asceticbs.com', + 'license': 'AGPL-3', + 'description': """Total Sales and Purchase of the Product""", + 'version': '14.0.1.0', + 'depends': ['base','sale_management'], + 'data': ['views/product_template_view.xml'], + 'images': ['static/description/banner.png'], + 'installable': True, + 'application': True, + 'auto_install': False, +} diff --git a/odex25_donation/abs_prodcut_invoices/models/__init__.py b/odex25_donation/abs_prodcut_invoices/models/__init__.py new file mode 100644 index 000000000..3ce2d8590 --- /dev/null +++ b/odex25_donation/abs_prodcut_invoices/models/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################# +# +# Odoo, Open Source Management Solution +# Copyright (C) 2020-today Ascetic Business Solution +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# 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 for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################# + +from. import product_template \ No newline at end of file diff --git a/odex25_donation/abs_prodcut_invoices/models/product_template.py b/odex25_donation/abs_prodcut_invoices/models/product_template.py new file mode 100644 index 000000000..427065d37 --- /dev/null +++ b/odex25_donation/abs_prodcut_invoices/models/product_template.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +################################################################################# +# +# Odoo, Open Source Management Solution +# Copyright (C) 2020-today Ascetic Business Solution +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# 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 for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################# + +from odoo import api, fields, models, _ + +#Class is Extended for new features, which are displaying two tables for total customer invoice and total vendor bills on particular product form, also display its button with total amount of that product. +class ProductTemplateInvoiceAmount(models.Model): + _inherit = "product.template" + + cust_invoice_line_ids = fields.One2many('account.move.line','template_id', string='Customer Invoice',compute='_compute_get_customer_invoices_in_product',help='get particular products invoice id from all customers invoices') + + vendor_bill_line_ids = fields.One2many('account.move.line','template_id', string='Vendor Bill Line',compute='_compute_get_vendor_bills_in_product',help='get particular products invoice id from all vendors bills') + + #compute customers invoices on product, which is related to that product. + def _compute_get_customer_invoices_in_product(self): + for record in self: + if record.id: + cust_invoice=self.env['account.move.line'].search([('product_id.product_tmpl_id','=',self.id),('move_id.move_type','=','out_invoice')]) + record.cust_invoice_line_ids = cust_invoice + else: + record.cust_invoice_line_ids = False + + #compute vendor bills invoices on product, which is related to that product. + def _compute_get_vendor_bills_in_product(self): + for record in self: + if record.id: + vendor_bill=self.env['account.move.line'].search([('product_id.product_tmpl_id','=',self.id),('move_id.move_type','=','in_invoice')]) + record.vendor_bill_line_ids = vendor_bill + else: + record.vendor_bill_line_ids = False + +#Class is Extended for new features,take template_id and invoice_state from account.invoice.line to product.template. +class AccountMoveIn(models.Model): + _inherit = "account.move.line" + + template_id = fields.Many2one('product.template',string="template ids",compute='get_template_id',help='This field is in relation with customer invoice and vendor bills') + + invoice_state = fields.Selection([('draft','Draft'),('posted', 'Posted'),('cancel', 'Cancelled'),], string='Status',compute='get_template_id', index=True, readonly=True, default='draft',track_visibility='onchange', copy=False,help=" * The 'Draft' status is used when a user is encoding a new and unconfirmed Invoice.\n"" * The 'Pro-forma' status is used when the invoice does not have an invoice number.\n"" * The 'Open' status is used when user creates invoice, an invoice number is generated. It stays in the open status till the user pays the invoice.\n"" * The 'Paid' status is set automatically when the invoice is paid. Its related journal entries may or may not be reconciled.\n"" * The 'Cancelled' status is used when user cancel invoice.") + + ### Add one field for invoice number and vendor bill number + number = fields.Char(compute='get_template_id') + + #Create template_id(product_id.product_tmpl_id) from product_id and create invoice_state from invoice_id. + def get_template_id(self): + for record in self: + if record.product_id: + record.template_id = record.product_id.product_tmpl_id + else: + record.template_id = False + for record in self: + if record.move_id: + record.invoice_state = record.move_id.state + else: + record.invoice_state = False + for record in self: + if record.move_id: + record.number = record.move_id.name + else: + record.number = False diff --git a/odex25_donation/abs_prodcut_invoices/static/description/banner.png b/odex25_donation/abs_prodcut_invoices/static/description/banner.png new file mode 100644 index 000000000..cc4b10672 Binary files /dev/null and b/odex25_donation/abs_prodcut_invoices/static/description/banner.png differ diff --git a/odex25_donation/abs_prodcut_invoices/static/description/company-logo.png b/odex25_donation/abs_prodcut_invoices/static/description/company-logo.png new file mode 100644 index 000000000..fee9f34ae Binary files /dev/null and b/odex25_donation/abs_prodcut_invoices/static/description/company-logo.png differ diff --git a/odex25_donation/abs_prodcut_invoices/static/description/icon.png b/odex25_donation/abs_prodcut_invoices/static/description/icon.png new file mode 100644 index 000000000..1e6ee1697 Binary files /dev/null and b/odex25_donation/abs_prodcut_invoices/static/description/icon.png differ diff --git a/odex25_donation/abs_prodcut_invoices/static/description/index.html b/odex25_donation/abs_prodcut_invoices/static/description/index.html new file mode 100644 index 000000000..6e88a1152 --- /dev/null +++ b/odex25_donation/abs_prodcut_invoices/static/description/index.html @@ -0,0 +1,97 @@ + + +
+
+
+

Total Sales and Purchase of the Product

+
+ +
+
+ +
+
+
+ +
+
    +
    Do you need any help? +
    +
  • Contact this module maintainer for any question, need support or request for the new feature :
  • +
  • * Riken Bhorania +91 9427425799, riken.bhorania, riken.bhorania@asceticbs.com
  • +
  • * Bhaumin Chorera +91 8530000384, bhaumin.chorera, bhaumin.chorera@asceticbs.com
  • +
+
+
+
+
+
+ + + diff --git a/odex25_donation/abs_prodcut_invoices/views/product_template_view.xml b/odex25_donation/abs_prodcut_invoices/views/product_template_view.xml new file mode 100644 index 000000000..22ed3aef7 --- /dev/null +++ b/odex25_donation/abs_prodcut_invoices/views/product_template_view.xml @@ -0,0 +1,44 @@ + + + + + product.template.product.form + product.template + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/affiliate_management/.gitignore b/odex25_donation/affiliate_management/.gitignore new file mode 100644 index 000000000..cf14435c9 --- /dev/null +++ b/odex25_donation/affiliate_management/.gitignore @@ -0,0 +1,4 @@ +*.pyc +.idea/ +controller/__pycache__ +models/__pycache__ \ No newline at end of file diff --git a/odex25_donation/affiliate_management/LICENSE b/odex25_donation/affiliate_management/LICENSE new file mode 100644 index 000000000..b53403939 --- /dev/null +++ b/odex25_donation/affiliate_management/LICENSE @@ -0,0 +1,398 @@ +SOFTWARE LICENCE AGREEMENT +========================== + +This AGREEMENT is made effective on the date of the purchase of the software +between Webkul Software Pvt. Ltd.,Company incorporated under the Companies +Act, 1956 (hereinafter referred to as “Licensor"), and the purchaser of the +software/ product (hereinafter referred to as "Licensee"). + + +Preamble +-------- + +Licensor is a web and mobile product based organization engaged in the +business of developing and marketing software for enterprise level e-commerce +businesses. It is an ISO and NSR (NASSCOM) certified organization having a +team of more than 150 creative engineers which come from different +backgrounds. It has developed more than 700 web extensions and apps in the +past few years for open source platforms which are used and trusted globally. +Licensee now wishes to obtain license, and Licensor wishes to grant a license, +to allow use of the software so purchased in developing the e-commerce +business website/ mobile app of the Licensee, subject to the terms and +conditions set forth herein. + +THEREFORE, with the intent to be legally bound, the parties hereby agree as +follows: + + +Agreement +--------- + +1.DEFINITIONS. +As used in this Agreement, the following capitalized terms +shall have the definitions set forth below: + +"Derivative Works" are works developed by Licensee, its officers, agents, +contractors or employees, which are based upon, in whole or in part, the +Source Code and/or the Documentation and may also be based upon and/or +incorporate one or more other preexisting works of the Licensor. Derivative +Works may be any improvement, revision, modification, translation (including +compilation or recapitulation by computer), abridgment, condensation, +expansion, or any other form in which such a preexisting work may be recast, +transformed, or adapted. For purposes hereof, a Derivative Work shall also +include any compilation that incorporates such a preexisting work. + +"Documentation" is written, printed or otherwise recorded or stored (digital +or paper) material relating to the Software and/or Source Code, including +technical specifications and instructions for its use including Software/ +Source Code annotations and other descriptions of the principles of its +operation and instructions for its use. + +"Improvements" shall mean, with respect to the Software, all modifications and +changes made, developed, acquired or conceived after the date hereof and +during the entire term of this Agreement. + +"Source Code" is the computer programming source code form of the Software in +the form maintained by the Licensor, and includes all non-third-party +executables, libraries, components, and Documentation created or used in the +creation, development, maintenance, and support of the Software as well as all +updates, error corrections and revisions thereto provided by Licensor, in +whole or in part. + + +2.SOFTWARE LICENSE. + +(a)Grant of License. For the consideration set forth below, Licensor hereby +grants to Licensee, and Licensee hereby accepts the worldwide, non-exclusive, +perpetual, royalty-free rights and licenses set forth below: + +(i)The right and license to use and incorporate the software, in whole or in +part, to develop its website/ mobile app (including the integration of all or +part of the Licensor’s software into Licensee's own software) on one domain ( +Except Joomla modules , listed on store are entitled to be used on unlimited +domain as per the standard guidelines ) only, solely for the own personal or +business use of the Licensee. However, the License does not authorize the +Licensee to compile, copy or distribute the said Software or its Derivative +Works. + +(ii)The right and license does not authorize the Licensee to share any backup +or archival copies of the Software and / or the Source Code and Documentation +on any public internet space including github , stackoverflow etc . The +Licensee must ensure that the backup are not accessible to any other person +and the Licensee must prevent copying / use of source code by any unauthorized +persons. + +(iii)The right and license does not authorize the Licensee to migrate the +domain license to another domain. + +(iv)Our Joomla extensions are published under the GNU/GPL. + + +(b)Scope; Rights and Responsibilities. + +(i)Licensor shall enable the Licensee to download one complete copy of the +Software. + +(ii)The Software is intended for the sole use of the Licensee in development +of its own website/ mobile app. + +(iii)Licensee does not have the right to hand over, sell, distribute, +sub-license, rent, lease or lend any portion of the Software or Documentation, +whether modified or unmodified, to anyone. Licensee should not place the +Software on a server so that it becomes accessible via a public network such +as the Internet for distribution purposes. In case the Licensee is using any +source code management system like github, it can use the code there only when +it has paid subscription from such management system. + +(iv) In case the Licensee purchases the module and allow the third party +development agency to customize as per its need, it is at liberty to do so +subject to the condition that the Licensee as well as the Agency are not +authorized to sell the modified version of the extension. Except for the +required customization purposes, Licensee is not authorized to release the +Source Code, Derivative Work source code and/or Documentation to any third +party, which shall be considered as violation of the Agreement, inter-alia +entailing forthwith termination and legal action. + + +(c)Ownership. + +(i)Software and Source Code. All right, title, copyright, and interest in the +Software, Source Code, Software Modifications and Error corrections will be +and remain the property of Licensor. + +(ii)Derivative Works. As creation of Derivative Works by the Licensee is +prohibited, thus, all right, title, copyright, and interest in any and/or all +Derivative Works and Improvements created by, or on behalf of, Licensee will +also be deemed to the property of Licensor. Licensor shall be entitled to +protect copyright / intellectual property in all such Derivative Works and +Improvements also in any country as it may deem fit including without +limitation seeking copyright and/or patent protection. + + +3.CONSIDERATION. + +(a)Licensee shall pay to Licensor the amount as mentioned on the website from +where the order is placed, as one-time, upfront fees in consideration for the +licenses and rights granted hereunder (hereinafter referred to as the "License +Fee"). The License Fee to be paid by Licensee shall be paid upfront at the +time of placing the order, and no credit will be allowed under any +circumstances. + +(b)Once paid, the License Fees shall be non-refundable. The Licensee has fully +satisfied itself about the Software and has seen the demonstration, and only +thereafter has placed the order. Thus, the License Fees or any part thereof is +non-refundable. No claim for refund of the Licence Fees shall be entertained +under any circumstances. + + +4.REPRESENTATIONS AND WARRANTIES. + +(a)Mutual. Each of the parties represents and warrants to the other as +follows. + +(i)such party is a legal entity duly organized, validly existing and in good +standing; + +(ii)such party has the power and authority to conduct its business as +presently conducted and to enter into, execute, deliver and perform this +Agreement. + +(iii)This Agreement has been duly and validly accepted by such party and +constitutes the legal, valid and binding obligations of such party +respectively, enforceable against such party in accordance with their +respective terms; + +(iv)the acceptance, execution, delivery and performance of this Agreement does +not and will not violate such party's charter or by-laws; nor require any +consent, authorization, approval, exemption or other action by any third party +or governmental entity. + + +(b)Licensor warrants that, at the time of purchase of the Software: + +the Software will function materially as set forth in the website or published +functionality provided by Licensor to customers and potential customers +describing the Software; and + +Software add-ons, if purchased by the Licensee from the Licensor, will not +materially diminish the features or functions of or the specifications of the +Software as they existed as of the execution of this Agreement. + + +(c)Title. Licensor represents and warrants that it is the exclusive owner of +all copyright/ intellectual property in the Software (including the Source +Code) and has good and marketable title to the Software (including the Source +Code) free and clear of all liens, claims and encumbrances of any nature +whatsoever (collectively, "Liens"). Licensor's grant of license and rights to +Licensee hereunder does not, and will not infringe any third party's property, +intellectual property or personal rights. + + +5.TERM. + +(a)Subject to Licensee's payment obligations, this Agreement shall commence as +on the date of making payment of the Software by the Licensee to the Licensor, +and shall continue until terminated by either party. + +(b)The Licensor retains the right to terminate the license at any time, if the +Licensee is not abiding by any of the terms of the Agreement. The Licensee may +terminate the Agreement at any time at its own discretion by uninstalling the +Software and /or by destroying the said Software (or any copies thereof). +However, the Licensee shall not be entitled to seek any refund of the amount +paid by it to the Licensor, under any circumstances. + +(c)Survival. In the event this Agreement is terminated for any reason, the +provisions set forth in Sections 2(a), 2(b), and 2(c) shall survive. + + +6.INDEMNIFICATION. + +The Licensee release the Licensor from, and agree to indemnify, defend and +hold harmless the Licensor (and its officers, directors, employees, agents and +Affiliates) against, any claim, loss, damage, settlement, cost, taxes, expense +or other liability (including, without limitation, attorneys' fees) (each, a +"Claim") arising from or related to: (a) any actual or alleged breach of any +obligations in this Agreement; (b) any refund, adjustment, or return of +Software,(c) any claim for actual or alleged infringement of any Intellectual +Property Rights made by any third party or damages related thereto; or (d) +Taxes. + + +7.LIMITATION OF LIABILITY. + +The Licensor will not be liable for any direct, indirect, incidental, special, +consequential or exemplary damages, including but not limited to, damages for +loss of profits, goodwill, use, data or other intangible losses arising out of +or in connection with the Software, whether in contract, warranty, tort etc. ( +including negligence, software liability, any type of civil responsibility or +other theory or otherwise) to the Licensee or any other person for cost of +software, cover, recovery or recoupment of any investment made by the Licensee +or its affiliates in connection with this Agreement, or for any other loss of +profit, revenue, business, or data or punitive or consequential damages +arising out of or relating to this Agreement. Further, the aggregate liability +of the Licensor, arising out of or in connection with this Agreement or the +transactions contemplated hereby will not exceed at any time, or under any +circumstances, the total amounts received by the Licensor from the Licensee in +connection with the particular software giving rise to the claim. + + +8.FORCE MAJEURE. + +The Licensor will not be liable for any delay or failure to perform any of its +obligations under this Agreement by reasons, events or other matters beyond +its reasonable control. + + +9.RELATIONSHIP OF PARTIES. + +The Licensor and Licensee are independent legal entities, and nothing in this +Agreement will be construed to create a partnership, joint venture, +association of persons, agency, franchise, sales representative, or employment +relationship between the parties. The Licensee will have no authority to make +or accept any offers or representations on behalf of the Licensor. The +relationship between the parties is that of Licensor and Licensee only, and +the rights, duties, liabilities of each party shall be governed by this +Agreement. + + +10.MODIFICATION. + +The Licensor may amend any of the terms and conditions contained in this +Agreement at any time and solely at its discretion. Any changes will be +effective upon the posting of such changes on the Portal/ website, and the +Licensee is responsible for reviewing these changes and informing itself of +all applicable changes or notices. The continued use of a software by the +Licensee after posting of any changes by the Licensor, will constitute the +acceptance of such changes or modifications by the Licensee. + + +11.MISCELLANEOUS. + +(a)General Provisions. This Agreement: (i) may be amended only by a writing +signed by each of the parties; (ii) may be executed in several counterparts, +each of which shall be deemed an original but all of which shall constitute +one and the same instrument; (iii) contains the entire agreement of the +parties with respect to the transactions contemplated hereby and supersedes +all prior written and oral agreements, and all contemporaneous oral +agreements, relating to such transactions; (iv) shall be governed by, and +construed and enforced in accordance with, the laws of India; and (v) shall be +binding upon, and inure to the benefit of, the parties and their respective +successors and permitted assigns. Each of the parties hereby irrevocably +submits to the jurisdiction of the Courts at Delhi, India, for the purposes of +any action or proceeding arising out of or relating to this Agreement or the +subject matter hereof and brought by any other party. + +(b)Assignment. Except for the purpose of customization as mentioned in clause +2(b)(iv) above, Licensee cannot assign, pledge or otherwise transfer, whether +by operation of law or otherwise, this Agreement, or any of its obligations +hereunder, without the prior written consent of Licensor, which consent shall +not be unreasonably withheld. + +(c)Notices. Unless otherwise specifically provided herein, all notices, +consents, requests, demands and other communications required or permitted +hereunder: + +(i)shall be in writing; + +(ii)shall be sent by messenger, certified or registered mail/email, or +reliable express delivery service, to the appropriate address(es) set forth +below; and + +(iii)shall be deemed to have been given on the date of receipt by the +addressee, as evidenced by a receipt executed by the addressee (or a +responsible person in his or her office), the records of the Party delivering +such communication or a notice to the effect that such addressee refused to +claim or accept such communication, if sent by messenger, mail or express +delivery service. + +All such communications shall be sent to the following addresses or numbers, +or to such other addresses or numbers as any party may inform the others by +giving five days' prior notice: + +If to Webkul Software Pvt. Ltd.: + +Webkul Software Pvt. Ltd. +A-67, Sector 63, NOIDA – 201301, +Uttar Pradesh, India + +If to Licensee: +At the address mentioned by the Licensee +(at the time of placing order of generating Invoice) + +(d)Severability. It is the intent of the parties that the provisions of this +Agreement be enforced to the fullest extent permissible under the laws and +public policies of India in which enforcement hereof is sought. In +furtherance of the foregoing, each provision hereof shall be severable from +each other provision, and any provision hereof which is/ becomes unenforceable +shall be subject to the following: (i) if such provision is contrary to or +conflicts with any requirement of any statute, rule or regulation in effect, +then such requirement shall be incorporated into, or substituted for, such +unenforceable provision to the minimum extent necessary to make such provision +enforceable; (ii) the court, agency or arbitrator considering the matter is +hereby authorized to (or, if such court, agency or arbitrator is unwilling or +fails to do so, then the parties shall) amend such provision to the minimum +extent necessary to make such provision enforceable, and the parties hereby +consent to the entry of an order so amending such provision; and (iii) if +any such provision cannot be or is not reformed and made enforceable pursuant +to clause (i) or (ii) above, then such provision shall be ineffective to the +minimum extent necessary to make the remainder of this Agreement enforceable. +Any application of the foregoing provisions to any provision hereof shall not +effect the validity or enforceability of any other provision hereof. + +(e)By purchasing the Software, the Licensee acknowledge that it has read this +Agreement, and that it agrees to the content of the Agreement, its terms and +agree to use the Software in compliance with this Agreement. + +(f)The Licensor holds the sole copyright of the Software. The Software or any +portion thereof is a copyrightable matter and is liable to be protected by the +applicable laws. Copyright infringement in any manner can lead to prosecution +according to the current law. The Licensor reserves the right to revoke the +license of any user who is not holding any license or is holding an invalid +license. + +(g)This Agreement gives the right to use only one copy of the Software on one +domain solely for the own personal or business use of the Licensee, subject to +all the terms and conditions of this Agreement. A separate License has to be +purchased for each new Software installation. Any distribution of the Software +without the written consent of the Licensor (including non-commercial +distribution) is regarded as violation of this Agreement, and will entail +immediate termination of the Agreement and may invite liability, both civil +and criminal, as per applicable laws. + +(h)The Licensor reserves the rights to publish a selected list of users/ +Licensees of its Software, and no permission of any Licensee is needed in this +regard. The Licensee agrees that the Licensor may, in its sole discretion, +disclose or make available any information provided or submitted by the +Licensee or related to it under this Agreement to any judicial, +quasi-judicial, governmental, regulatory or any other authority as may be +required by the Licensor to co-operate and / or comply with any of their +orders, instructions or directions or to fulfill any requirements under +applicable Laws. + +(i)If the Licensee continues to use the Software even after the sending of the +notice by the Licensor for termination, the Licensee agree to accept an +injunction to restrain itself from its further use, and to pay all costs ( +including but not limited to reasonable attorney fees) to enforce injunction +or to revoke the License, and any damages suffered by the Licensor because of +the misuse of the Software by the Licensee. + + +12.ARBITRATION. + +If any dispute arises between the Licensor and the Licensee at any time, in +connection with the validity, interpretation, implementation or alleged breach +of any provision of this Agreement, the same shall be referred to a sole +Arbitrator who shall be an independent and neutral third party appointed +exclusively by the Licensor. The Licensee shall not object to the appointment +of the Arbitrator so appointed by the Licensor. The place of arbitration shall +be Delhi, India. The Arbitration & Conciliation Act, 1996 as amended by The +Arbitration & Conciliation (Amendment) Act, 2015, shall govern the +arbitration proceedings. The arbitration proceedings shall be held in the +English language. + + +This document is an electronic record in terms of Information Technology Act, +2000 and the amended provisions pertaining to electronic records in various +statutes as amended by the Information Technology Act, 2000. This electronic +record is generated by a computer system and does not require any physical or +digital signatures. \ No newline at end of file diff --git a/odex25_donation/affiliate_management/__init__.py b/odex25_donation/affiliate_management/__init__.py new file mode 100644 index 000000000..7aafe1ec1 --- /dev/null +++ b/odex25_donation/affiliate_management/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +from . import models +from . import controllers + + + diff --git a/odex25_donation/affiliate_management/__manifest__.py b/odex25_donation/affiliate_management/__manifest__.py new file mode 100644 index 000000000..236235896 --- /dev/null +++ b/odex25_donation/affiliate_management/__manifest__.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. () +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see +################################################################################# +{ + "name" : "Odoo Affiliate Management", + "summary" : """Affiliate extension for odoo E-commerce store""", + "category" : "Website", + "version" : "1.0.7", + "sequence" : 1, + "author" : "Webkul Software Pvt. Ltd.", + "license" : "Other proprietary", + "maintainer" : "Saurabh Gupta", + "website" : "https://store.webkul.com/Odoo-Affiliate-Management.html", + "description" : """Odoo Affiliate Extension for Affiliate Management""", + "live_test_url" : "http://odoodemo.webkul.com/?module=affiliate_management&lifetime=90&lout=1&custom_url=/", + "depends" : [ + 'sales_team', + 'website_sale', + 'wk_wizard_messages', + 'web', + 'web_tour', + 'auth_signup', + 'account', + 'base' + ], + "data" : [ + 'security/affiliate_security.xml', + 'security/ir.model.access.csv', + 'views/affiliate_pragram_form_view.xml', + 'data/automated_scheduler_action.xml', + 'views/affiliate_manager_view.xml', + 'data/sequence_view.xml', + 'views/account_invoice_inherit.xml', + 'views/affiliate_visit_view.xml', + 'views/affiliate_config_setting_view.xml', + 'views/res_users_inherit_view.xml', + 'views/affiliate_tool_view.xml', + 'views/affiliate_image_view.xml', + 'views/advance_commision_view.xml', + 'views/affiliate_pricelist_view.xml', + 'views/affiliate_banner_view.xml', + 'views/report_template.xml', + 'views/payment_template.xml', + 'views/index_template.xml', + 'views/tool_template.xml', + 'views/header_template.xml', + 'views/footer_template.xml', + 'views/join_email_template.xml', + 'views/signup_template.xml', + 'views/affiliate_request_view.xml', + 'views/welcome_mail_tepmlate.xml', + 'views/reject_mail_template.xml', + 'views/tool_product_link_template.xml', + 'views/about_template.xml', + 'data/default_affiliate_program_data.xml', + ], + "assets" : { + "web.assets_backend" : [], + "web.assets_frontend" : [ + + 'affiliate_management/static/src/css/website_affiliate.css', + 'affiliate_management/static/src/js/validation.js', + + ] + }, + + "demo" : ['data/demo_data_view.xml'], + "images" : ['static/description/banner.gif'], + "application" : True, + "installable" : True, + "price" : 99, + "currency" : "USD", +} diff --git a/odex25_donation/affiliate_management/_q b/odex25_donation/affiliate_management/_q new file mode 100644 index 000000000..20f7cec46 --- /dev/null +++ b/odex25_donation/affiliate_management/_q @@ -0,0 +1,311 @@ +diff --git a/static/description/index.html b/static/description/index.html +index adf3754..4b261ec 100644 +--- a/static/description/index.html ++++ b/static/description/index.html +@@ -20,7 +20,7 @@ +  +
 +
 +-
Affiliate Management in Odoo for marketing on another level!
 ++
Affiliate Management in Odoo for marketing on another level!
 +
 +
 +
 +@@ -58,7 +58,7 @@ +  +
 +
 +-
Hassle-free way for Affiliate Management in Odoo
 ++
Hassle-free way for Affiliate Management in Odoo
 +
 +
 +
 +@@ -425,6 +425,288 @@ +  +  +

 ++
 ++
 ++
 ++

Our Other Apps

 ++
 ++
 ++ Make your eCommerce Experience more better with our other Apps. ++
 ++
 ++
 ++
 ++  ++
 ++
 ++
 ++
 ++
 +  +
 +
 diff --git a/odex25_donation/affiliate_management/changelog.md b/odex25_donation/affiliate_management/changelog.md new file mode 100644 index 000000000..7ca9aa03b --- /dev/null +++ b/odex25_donation/affiliate_management/changelog.md @@ -0,0 +1,11 @@ +=>Affiliate Management technical name 'affiliate_management' +[version:1.0.1] Date : 30-10-2017 + *[IMPROVEMENT] + - improvement in Generate banner (in product search) + *[FIX] + - replace a (select a category) to (all categories) in category dropdown in views/tool_product_link_template.xml + *[ADD] + - + *[change] + -version from 1.0.0 to 1.0.1 in manifest + *[remove] \ No newline at end of file diff --git a/odex25_donation/affiliate_management/controllers/__init__.py b/odex25_donation/affiliate_management/controllers/__init__.py new file mode 100644 index 000000000..cf5409d11 --- /dev/null +++ b/odex25_donation/affiliate_management/controllers/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +from . import main +from . import affiliate_website +from . import home diff --git a/odex25_donation/affiliate_management/controllers/affiliate_website.py b/odex25_donation/affiliate_management/controllers/affiliate_website.py new file mode 100644 index 000000000..be78c79c8 --- /dev/null +++ b/odex25_donation/affiliate_management/controllers/affiliate_website.py @@ -0,0 +1,514 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +from ast import literal_eval +from odoo.addons.auth_signup.models.res_users import SignupError +from odoo import http +from odoo.http import request +from odoo import tools +from odoo.tools.translate import _ +import logging +_logger = logging.getLogger(__name__) +from odoo.fields import Date +import werkzeug.utils +import werkzeug.wrappers +from odoo.addons.website_sale.controllers.main import TableCompute +import requests +# from odoo.addons.web.controllers.main import db_monodb, ensure_db, set_cookie_and_redirect, login_and_redirect +from odoo.addons.web.controllers.utils import ensure_db, _get_login_redirect_url +from odoo.addons.affiliate_management.controllers.home import Home +from odoo.addons.website.controllers.main import Website,QueryURL +# from odoo.addons.website_form.controllers.main import WebsiteForm +from odoo.addons.website_sale.controllers.main import WebsiteSale +from odoo.osv import expression + + + +class website_affiliate(Home): + + + #home page of affiliate website + @http.route('/affiliate/', auth='public',type='http', website=True) + def affiliate(self, **kw): + banner = request.env['affiliate.banner'].sudo().search([]) + banner_title = banner[-1].banner_title if banner else '' + banner_image = banner[-1].banner_image if banner else '' + ConfigValues = request.env['res.config.settings'].sudo().website_constant() + enable_forget_pwd = ConfigValues.get('enable_forget_pwd') + enable_login = ConfigValues.get('enable_login') + enable_signup = ConfigValues.get('enable_signup') + how_it_work_title = ConfigValues.get('work_title') + how_it_work_text = tools.html_sanitize(ConfigValues.get('work_text')) + values = { + 'default_header':False, + 'affiliate_website':True, + 'banner_title':banner_title, + 'banner_image':banner_image, + 'enable_forget_pwd':enable_forget_pwd, + 'enable_login':enable_login, + 'enable_signup':enable_signup, + 'website_name' : request.env['website'].search([])[0].name, + 'how_it_work_title':how_it_work_title, + 'how_it_work_text' :how_it_work_text + } + if request.session.get('error'): + values.update({'error':request.session.get('error')}) + if request.session.get('success'): + values.update({'success':request.session.get('success')}) + request.session.pop('error', None) + request.session.pop('success', None) + return http.request.render('affiliate_management.affiliate', values) + + @http.route('/affiliate/join', auth='public',type='json', website=True,methods=['POST']) + def join(self,email ,**kw): + msg = False + aff = request.env['affiliate.request'].sudo().search([('name','=',email)]) + if aff: + if (not aff.signup_valid) and (not aff.user_id): + aff.regenerate_token() + msg = "Thank you for registering with us, we have sent you the Signup mail at "+email+"." + + else: + if aff.state == 'aproove': + msg = "Your email is already registered with us " + elif aff.state == 'register': + msg = "Your request is pending for approval with us, soon you will receive 'Approval' confirmation e-mail." + else: + if aff.user_id: + msg = "Your request is pending for approval with us, soon you will receive 'Approval' confirmation e-mail." + else: + msg = "We have already sended you a joining e-mail" + + else: + user = request.env['res.users'].sudo().search([('login','=',email)]) + msg = "Thank you for registering with us, we have sent you the Signup mail at "+email + vals = { + 'name':email, + 'state':'draft', + } + if user: + vals.update({ + "partner_id":user.partner_id.id, + "user_id" : user.id, + 'state' : 'register' + }) + msg = "Your request is pending for approval with us, soon you will receive 'Approval' confirmation e-mail." + aff_request = request.env['affiliate.request'].sudo().create(vals) + return msg + + @http.route('/affiliate/about',type='http', auth="user", website=True) + def affiliate_about(self, **kw): + partner = request.env.user.partner_id + base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url') + currency_id = request.env.user.company_id.currency_id + ConfigValues = request.env['res.config.settings'].sudo().website_constant() + db = request.session.get('db') + value={ + 'url': "%s/shop?aff_key=%s&db=%s" %(base_url,partner.res_affiliate_key,db), + 'affiliate_key': partner.res_affiliate_key, + 'pending_amt':partner.pending_amt, + 'approved_amt':partner.approved_amt, + 'currency_id':currency_id, + 'how_it_works_title':ConfigValues.get('work_title'), + 'how_it_works_text':tools.html_sanitize(ConfigValues.get('work_text')), + } + return http.request.render('affiliate_management.about', value) + + @http.route('/affiliate/signup', auth='public',type='http', website=True) + def register(self, **kw): + token = request.httprequest.args.get('token') + user = request.env['affiliate.request'].sudo().search([('signup_token','=',token)]) + term_condition = request.env['res.config.settings'].sudo().website_constant().get('term_condition') + values = {} + if user.signup_valid and user.state == 'draft': + values .update({ + 'name': user.name.split('@')[0], + 'login': user.name, + 'token': token, + 'term_condition':tools.html_sanitize(term_condition), + }) + if request.session.get('error'): + values.update({'error':request.session.get('error')}) + else: + pass + request.session.pop('error', None) + return http.request.render('affiliate_management.register',values) + + + @http.route('/affiliate/register', auth='public',type='http', website=True) + def register_affiliate(self, **kw): + ensure_db() + aff_request = request.env['affiliate.request'].sudo().search([('name','=',kw.get('login'))]) + if aff_request and kw.get('confirm_password') == kw.get('password') and aff_request.signup_token == kw.get('token'): + template_user_id = literal_eval(request.env['ir.config_parameter'].sudo().get_param('base.template_portal_user_id', 'False')) + template_user = request.env['res.users'].sudo().browse(template_user_id) + auto_approve_request = request.env['res.config.settings'].sudo().website_constant().get('auto_approve_request') + if not template_user.exists(): + raise SignupError('Invalid template user.') + data = kw + redirect_url = "/" + values = { key: data.get(key) for key in ('login', 'name') } + values['email'] = data.get('email') or values.get('login') + values['lang'] = request.lang.code + values['active'] = True + no_invitation_mail = True + values['password'] = data.get('password',"") + try: + with request.env.cr.savepoint(): + user = template_user.with_context(no_reset_password = no_invitation_mail).copy(values) + _logger.info('------user.partner--%r-----',user.partner_id) + # update phoen no. and comment in res.partner + user.partner_id.comment = kw.get('comment') + user.partner_id.phone = kw.get('phone') + # update affiliate.request with partner and user id and state + aff_request.partner_id = user.partner_id.id + aff_request.user_id = user.id + aff_request.state = 'register' + request.env.cr.commit() + # check the config for auto approve the request + if auto_approve_request: + aff_request.action_aproove() + db = request.env.cr.dbname + uid = request.session.authenticate(request.session.db, data.get('email') or values.get('login'), data.get('password',"")) + # request.params['login_success'] = True + _logger.info("=================uid====%r",uid) + return request.redirect(_get_login_redirect_url(uid, redirect='/affiliate')) + + # return login_and_redirect(db, data['login'], data['password'],redirect_url='/affiliate') + # return _get_login_redirect_url(user.id,redirect='/affiliate') + except Exception as e: + _logger.error("Error123: %r"%e) + return request.redirect('/') + else: + if kw.get('password')!= kw.get('confirm_password'): + request.session['error']= "Passwords Does't match." + return request.redirect('/affiliate/signup?token='+kw.get('token'), 303) + else: + request.session['error']= "something went wrong.." + return request.redirect('/affiliate/', 303) + + @http.route('/affiliate/register/confirmation', auth='public',type='http', website=True) + def register_affiliate_confirmation(self, **kw): + return http.request.render('affiliate_management.confirmation', { + }) + + + @http.route('/affiliate/home',type='http', auth="user", website=True) + def home(self, **kw): + return http.request.render('affiliate_management.report', { + }) + + + @http.route('/affiliate/report', type='http', auth="user", website=True) + def report(self, **kw): + partner = request.env.user.partner_id + enable_ppc = request.env['res.config.settings'].sudo().website_constant().get('enable_ppc') + currency_id = request.env.user.company_id.currency_id + visits = request.env['affiliate.visit'].sudo() + ppc_visit = visits.search([('affiliate_method','=','ppc'),('affiliate_partner_id','=',partner.id),'|',('state','=','invoice'),('state','=','confirm')]) + pps_visit = visits.search([('affiliate_method','=','pps'),('affiliate_partner_id','=',partner.id),'|',('state','=','invoice'),('state','=','confirm')]) + values = { + 'pending_amt':partner.pending_amt, + 'approved_amt':partner.approved_amt, + 'ppc_count':len(ppc_visit), + 'pps_count':len(pps_visit), + 'enable_ppc':enable_ppc, + "currency_id":currency_id, + } + return http.request.render('affiliate_management.report', values) + + @http.route(['/my/traffic','/my/traffic/page/'], type='http', auth="user", website=True) + def traffic(self, page=1, date_begin=None, date_end=None, **kw): + values={} + partner = request.env.user.partner_id + visits = request.env['affiliate.visit'].sudo() + domain = [('affiliate_partner_id','=',partner.id),('affiliate_method','=','ppc'),'|',('state','=','invoice'),('state','=','confirm')] + if date_begin and date_end: + domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)] + traffic_count = visits.search_count(domain) + pager = request.website.pager( + url='/my/traffic', + url_args={'date_begin': date_begin, 'date_end': date_end}, + total=traffic_count, + page=page, + step=10 + ) + ppc_visit = visits.search(domain, limit=10, offset=pager['offset']) + values.update({ + 'pager': pager, + 'traffic': ppc_visit, + 'default_url': '/my/traffic' + }) + + return http.request.render('affiliate_management.affiliate_traffic', values) + + + @http.route(['/my/traffic/'], type='http', auth="user", website=True) + def aff_traffic_form(self, traffic=None, **kw): + traffic_visit = request.env['affiliate.visit'].sudo().browse([traffic]) + return request.render("affiliate_management.traffic_form", { + 'traffic_detail': traffic_visit, + 'product_detail':request.env['product.product'].browse([traffic_visit.type_id]), + }) + + + + @http.route(['/my/order','/my/order/page/'], type='http', auth="user", website=True) + def aff_order(self, page=1, date_begin=None, date_end=None, **kw): + values={} + partner = request.env.user.partner_id + visits = request.env['affiliate.visit'].sudo() + domain = [('affiliate_partner_id','=',partner.id),('affiliate_method','=','pps'),'|',('state','=','invoice'),('state','=','confirm')] + if date_begin and date_end: + domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)] + traffic_count = visits.search_count(domain) + pager = request.website.pager( + url='/my/order', + url_args={'date_begin': date_begin, 'date_end': date_end}, + total=traffic_count, + page=page, + step=10 + ) + ppc_visit = visits.sudo().search(domain, limit=10, offset=pager['offset']) + values.update({ + 'pager': pager, + 'traffic': ppc_visit, + 'default_url': '/my/order', + }) + return http.request.render('affiliate_management.affiliate_order', values) + + + @http.route(['/my/order/'], type='http', auth="user", website=True) + def aff_order_form(self, order=None, **kw): + order_visit = request.env['affiliate.visit'].sudo().browse([order]) + return request.render("affiliate_management.order_form", { + 'order_visit_detail': order_visit, + 'product_detail' :order_visit.sales_order_line_id.sudo() + }) + + + # Routes for the payment template + @http.route(['/affiliate/payment','/affiliate/payment/page/'], type='http', auth="user", website=True) + def payment(self, page=1, date_begin=None, date_end=None, **kw): + values={} + partner = request.env.user.partner_id + invoices = request.env['account.move'] + domain = [('partner_id','=',partner.id),('payment_state','=','paid'),('ref','=',None)] + if date_begin and date_end: + domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)] + invoice_count = invoices.search_count(domain) + + pager = request.website.pager( + url='/affiliate/payment', + url_args={'date_begin': date_begin, 'date_end': date_end}, + total=invoice_count, + page=page, + step=10 + ) + invoice_list = invoices.search(domain, limit=10, offset=pager['offset']) + + values.update({ + 'pager': pager, + 'invoices': invoice_list, + 'default_url': '/affiliate/payment', + }) + return http.request.render('affiliate_management.payment_tree',values ) + + + @http.route(['/my/invoice/'], type='http', auth="user", website=True) + def aff_invoice_form(self, invoice=None, **kw): + inv = request.env['account.move'].sudo().browse([invoice]) + return request.render("affiliate_management.payment_form", { + 'invoice': inv, + + }) + + @http.route('/affiliate/tool', auth='user',type='http', website=True) + def tool(self, **kw): + """actions for Tool "affiliate/tool""" + return http.request.render('affiliate_management.tool',{}) + + + @http.route('/tool/create_link', auth='user',type='http', website=True) + def create_link(self, **kw): + """generate affiliate link by url""" + partner = request.env.user.partner_id + # link = kw.get("link") + link = kw.get("link") if kw.get("link").find('#') != -1 else str(kw.get("link"))+'#' + index_li = link.find('#') + db = request.session.get('db') + db = "?db=%s" %(db) + link = link[:index_li]+db+link[index_li:] + result = self.check_link_validation(link) + if kw.get('link') and partner.res_affiliate_key and result: + index_li = link.find('#') + request.session['generate_link'] = link[:index_li]+'&aff_key='+partner.res_affiliate_key+link[index_li:] + return request.redirect('/tool/link_generator/', 303) + + @http.route("/tool/link_generator", auth='user',type='http', website=True) + def link_generator(self, **kw): + partner = request.env.user.partner_id + values={} + if request.session.get('generate_link'): + values.update({ + 'generate_link':request.session.get('generate_link'), + 'error':request.session.get('error') + }) + if request.session.get('error'): + values.update({ + 'error':request.session.get('error') + }) + request.session.pop('generate_link', None) + request.session.pop('error', None) + return http.request.render('affiliate_management.link_generator',values) + + def check_link_validation(self,link): + base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url') + try: + r = requests.get(link,verify=False) + + if r.status_code == 200: + langs = [l.code for l in request.website.language_ids] + + link_arr = link.split("/") + # if a language is already in the path, remove it + if link_arr[1] in langs: + link_arr.pop(1) + link_base_url = link_arr[0]+"//"+link_arr[2] + + if base_url == link_base_url : + #changed by vardaan as product are not showing as part of url + if 'shop' in link_arr or 'product' in link_arr: + return True + else: + request.session['error'] = "Url doesn't have shop/product" + return False + else: + request.session['error'] = "Base Url doesn't match" + return False + else: + request.session['error'] = "Please enter a Valid Url. Bad response from "+link + return False + except Exception as e: + request.session['error'] = "Please enter a Valid Url. + %r"%e + return False + + + + + @http.route("/tool/product_link", auth='user',type='http', website=True) + def product_link(self, **kw): + values={} + category = request.env['product.public.category'].sudo().search([]) + values.update({ + 'category': category, + }) + return http.request.render('affiliate_management.product_link',values) + + + # search the product on criteria category and published product + @http.route("/search/product", auth='user',type='http', website=True) + def search_product(self, **kw): + domain = request.website.sale_product_domain() + if kw.get('name'): + + domain += [ + ('website_published','=',True),'|', '|', '|', ('name', 'ilike', kw.get('name')), ('description', 'ilike', kw.get('name')), + ('description_sale', 'ilike', kw.get('name')), ('product_variant_ids.default_code', 'ilike', kw.get('name'))] + + if kw.get('categories'): + category_id = request.env['product.public.category'].sudo().search([('name','=',kw.get('categories'))],limit=1) + if category_id: + domain += [('public_categ_ids', 'child_of', int(category_id.id))] + + partner = request.env.user.partner_id + values={} + category = request.env['product.public.category'].sudo().search([]) + values.update({ + 'category': category, + }) + product_template = request.env['product.template'].sudo() + products = product_template.search(domain) + db = request.session.get('db') + if products: + values.update({ + 'bins': TableCompute().process(products, 10), + 'search_products':products, + 'rows':4, + 'partner_key': partner.res_affiliate_key, + 'base_url': request.env['ir.config_parameter'].sudo().get_param('web.base.url'), + 'db':db + }) + # _logger.info("=======values====%r",values) + return http.request.render('affiliate_management.product_link',values) + + + @http.route('/tool/generate_banner', auth='user',type='http', website=True) + def tool_banner(self, **kw): + partner = request.env.user.partner_id + banner_image_ids = request.env['affiliate.image'].sudo().search([('image_active','=',True)]) + product = request.env['product.template'].sudo().search([('id','=',kw.get('product_id'))]) + db = request.session.get('db') + values={ + 'banner_button':banner_image_ids, + 'product':product, + 'db':db + } + return http.request.render('affiliate_management.generate_banner',values) + + + @http.route("/tool/generate_button_link", auth='user',type='http', website=True) + def generate_button_link(self, **kw): + partner = request.env.user.partner_id + base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url') + db = request.session.get('db') + values ={ + 'partner_key': partner.res_affiliate_key, + 'product_id':kw.get('product_id'), + 'base_url' : base_url, + 'db':db + } + selected_image= kw.get('choose_banner').split("_") + if selected_image[0] == 'button': + _logger.info("-----selected button image id ---%r---",selected_image[1]) + button = request.env['affiliate.image'].sudo().browse([int(selected_image[1])]) + values.update({ + "button":button + }) + else: + if selected_image[0] == 'product': + values.update({ + "is_product":True + }) + _logger.info("-----selected product image id ---%r---",selected_image[1]) + return http.request.render('affiliate_management.generate_button_link',values) + + + + @http.route("/affiliate/request", type='json', auth="public", methods=['POST'], website=True) + def portal_user(self, user_id,**kw): + User = request.env['res.users'].sudo().browse([request.uid]) + AffRqstObj = request.env['affiliate.request'].sudo() + vals ={ + 'name':User.partner_id.email, + 'partner_id': User.partner_id.id, + 'user_id': request.uid, + 'state':'register', + } + aff_request = AffRqstObj.create(vals) + auto_approve_request = request.env['res.config.settings'].sudo().website_constant().get('auto_approve_request') + if auto_approve_request: + aff_request.action_aproove() + return aff_request and True or False diff --git a/odex25_donation/affiliate_management/controllers/home.py b/odex25_donation/affiliate_management/controllers/home.py new file mode 100644 index 000000000..7811da433 --- /dev/null +++ b/odex25_donation/affiliate_management/controllers/home.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import werkzeug.utils +import werkzeug.wrappers + +from odoo import http +from odoo.http import request + +import logging +_logger = logging.getLogger(__name__) +from odoo.addons.web.controllers.home import Home + +import odoo +import odoo.modules.registry +from odoo.tools.translate import _ +from odoo.http import request + +class Home(Home): + + @http.route(website=True, auth="public") + def web_login(self, redirect=None, *args, **kw): + response = super(Home, self).web_login(redirect=redirect, *args, **kw) + # kw.get('affiliate_login_form') is hidden field in login form of affiliate home page + check_affiliate = request.env['res.users'].sudo().search([('login','=',kw.get('login'))]).partner_id.is_affiliate + if kw.get('affiliate_login_form') and response.qcontext.get('error'): + request.session['error']= 'Wrong login/password' + return request.redirect('/affiliate/',303) + else: + if kw.get('affiliate_login_form') and check_affiliate: + return super(Home, self).web_login(redirect='/affiliate/about', *args, **kw) + else: + return response + + @http.route('/web/session/logout', type='http', auth="none") + def logout(self, redirect='/web'): + partner = request.env['res.users'].sudo().browse([request.session.uid]) + if partner.partner_id.is_affiliate: + request.session.logout(keep_db=True) + return werkzeug.utils.redirect('/affiliate', 303) + else: + request.session.logout(keep_db=True) + return werkzeug.utils.redirect(redirect, 303) diff --git a/odex25_donation/affiliate_management/controllers/main.py b/odex25_donation/affiliate_management/controllers/main.py new file mode 100644 index 000000000..e72140178 --- /dev/null +++ b/odex25_donation/affiliate_management/controllers/main.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +from odoo import http +from odoo.http import request +from odoo import fields +import logging +_logger = logging.getLogger(__name__) +from odoo.addons.website_sale.controllers.main import WebsiteSale +import datetime + + +class WebsiteSale(WebsiteSale): + + def create_aff_visit_entry(self,vals): + ppc_exist = self.check_ppc_exist(vals) + if ppc_exist: + visit = ppc_exist + else: + visit = request.env['affiliate.visit'].sudo().create(vals) + return visit + + + def check_ppc_exist(self,vals): + domain = [('type_id','=',vals['type_id']),('affiliate_method','=',vals['affiliate_method']),('affiliate_key','=',vals['affiliate_key']),('ip_address','=',vals['ip_address'])] + visit = request.env['affiliate.visit'].sudo().search(domain) + check_unique_ppc = request.env['res.config.settings'].sudo().website_constant().get('unique_ppc_traffic') + # "check_unique_ppc" it cheacks that in config setting wheather the unique ppc is enable or not + if check_unique_ppc: + if visit: + return visit + else: + return False + else: + return False + +# override shop action in website_sale + @http.route([ + '/shop', + '/shop/page/', + '/shop/category/', + '/shop/category//page/' + ], type='http', auth="public", website=True,sitemap=WebsiteSale.sitemap_shop) + def shop(self, page=0, category=None, search='', ppg=False, **post): + enable_ppc = request.env['res.config.settings'].sudo().website_constant().get('enable_ppc') + expire = False + result = super(WebsiteSale,self).shop(page=page, category=category, search=search, ppg=ppg, **post) + aff_key = request.httprequest.args.get('aff_key') + if category and aff_key: + expire = self.calc_cookie_expire_date() + path = request.httprequest.full_path + partner_id = request.env['res.partner'].sudo().search([('res_affiliate_key','=',aff_key),('is_affiliate','=',True)]) + vals = self.create_affiliate_visit(aff_key,partner_id,category) + vals.update({'affiliate_type':'category'}) + if ( len(partner_id) == 1): + affiliate_visit = self.create_aff_visit_entry(vals) if enable_ppc else False + result.set_cookie(key='affkey_%s'%(aff_key), value='category_%s'%(category.id),expires=expire) + else: + _logger.info("=====affiliate_visit not created by category===========") + else: + if aff_key: + expire = self.calc_cookie_expire_date() + partner_id = request.env['res.partner'].sudo().search([('res_affiliate_key','=',aff_key),('is_affiliate','=',True)]) + if partner_id: + result.set_cookie(key='affkey_%s'%(aff_key), value='shop',expires=expire) + return result + + + @http.route(['/shop/'], type='http', auth="public", website=True) + def product(self, product, category='', search='', **kwargs): + _logger.info("=====product page=========") + _logger.info("=====product page aff_key==%r=========",request.httprequest.args) + enable_ppc = request.env['res.config.settings'].sudo().website_constant().get('enable_ppc') + expire = self.calc_cookie_expire_date() + result = super(WebsiteSale,self).product(product=product, category=category, search=search, **kwargs) + if request.httprequest.args.get('aff_key'): + # path is the complete url with url = xxxx?aff_key=XXXXXXXX + path = request.httprequest.full_path + # aff_key is fetch from url + aff_key = request.httprequest.args.get('aff_key') + partner_id = request.env['res.partner'].sudo().search([('res_affiliate_key','=',aff_key),('is_affiliate','=',True)]) + vals = self.create_affiliate_visit(aff_key,partner_id,product) + vals.update({'affiliate_type':'product'}) + if ( len(partner_id) == 1): + affiliate_visit = self.create_aff_visit_entry(vals) if enable_ppc else False + # "create_aff_visit_entry " this methods check weather the visit is already created or not or if created return the no. of existing record in object + result.set_cookie(key='affkey_%s'%(aff_key),value='product_%s'%(product.id),expires=expire) + _logger.info("============affiliate_visit created by product==%r=======",affiliate_visit) + else: + _logger.info("=====affiliate_visit not created by product===========%s %s"%(aff_key,partner_id)) + return result + + + + @http.route(['/shop/confirmation'], type='http', auth="public", website=True) + def shop_payment_confirmation(self, **post): + result = super(WebsiteSale,self).shop_payment_confirmation(**post) + # here result id http.render argument is http.render{ http.render(template, qcontext=None, lazy=True, **kw) } + sale_order_id = result.qcontext.get('order') + return self.update_affiliate_visit_cookies( sale_order_id,result ) + + + def create_affiliate_visit(self,aff_key,partner_id,type_id): + """ method to delete the cookie after update function on id""" + vals = { + 'affiliate_method':'ppc', + 'affiliate_key':aff_key, + 'affiliate_partner_id':partner_id.id, + 'url':request.httprequest.full_path, + 'ip_address':request.httprequest.environ['REMOTE_ADDR'], + 'type_id':type_id.id, + 'convert_date':fields.datetime.now(), + 'affiliate_program_id': partner_id.affiliate_program_id.id, + } + return vals + + def update_affiliate_visit_cookies(self , sale_order_id ,result): + """update affiliate.visit from cokkies data i.e created in product and shop method""" + cookies = dict(request.httprequest.cookies) + visit = request.env['affiliate.visit'] + arr=[]# contains cookies product_id + for k,v in cookies.items(): + if 'affkey_' in k: + arr.append(k.split('_')[1]) + if arr: + partner_id = request.env['res.partner'].sudo().search([('res_affiliate_key','=',arr[0]),('is_affiliate','=',True)]) + for s in sale_order_id.order_line: + if len(arr)>0 and partner_id: + product_tmpl_id = s.product_id.product_tmpl_id.id + aff_visit = visit.sudo().create({ + 'affiliate_method':'pps', + 'affiliate_key':arr[0], + 'affiliate_partner_id':partner_id.id, + 'url':"", + 'ip_address':request.httprequest.environ['REMOTE_ADDR'], + 'type_id':product_tmpl_id, + 'affiliate_type': 'product', + 'type_name':s.product_id.id, + 'sales_order_line_id':s.id, + 'convert_date':fields.datetime.now(), + 'affiliate_program_id': partner_id.affiliate_program_id.id, + 'product_quantity' : s.product_uom_qty, + 'is_converted':True + }) + # delete cookie after first sale occur + cookie_del_status=False + for k,v in cookies.items(): + if 'affkey_' in k: + cookie_del_status = result.delete_cookie(key=k) + return result + + + def calc_cookie_expire_date(self): + ConfigValues = request.env['res.config.settings'].sudo().website_constant() + cookie_expire = ConfigValues.get('cookie_expire') + cookie_expire_period = ConfigValues.get('cookie_expire_period') + time_dict = { + 'hours':cookie_expire, + 'days':cookie_expire*24, + 'months':cookie_expire*24*30, + } + return datetime.datetime.utcnow() + datetime.timedelta(hours=time_dict[cookie_expire_period]) diff --git a/odex25_donation/affiliate_management/data/automated_scheduler_action.xml b/odex25_donation/affiliate_management/data/automated_scheduler_action.xml new file mode 100644 index 000000000..16e9055b0 --- /dev/null +++ b/odex25_donation/affiliate_management/data/automated_scheduler_action.xml @@ -0,0 +1,81 @@ + + + + + + + + + Automated ppc maturity Scheduler + + 1 + days + -1 + + code + model.process_ppc_maturity_scheduler_queue() + + + + + + + + + + + Automated invoice Scheduler + + 1 + days + -1 + + code + model.process_scheduler_queue() + + + + + + Create Visits Invoice + + + code + + if records: + action = records.create_invoice() + + + + + + + + + + diff --git a/odex25_donation/affiliate_management/data/default_affiliate_program_data.xml b/odex25_donation/affiliate_management/data/default_affiliate_program_data.xml new file mode 100644 index 000000000..2bec4fa3b --- /dev/null +++ b/odex25_donation/affiliate_management/data/default_affiliate_program_data.xml @@ -0,0 +1,51 @@ + + + + + Default Affiliate Program + s + 10 + f + 10 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/affiliate_management/data/demo_data_view.xml b/odex25_donation/affiliate_management/data/demo_data_view.xml new file mode 100644 index 000000000..a12da8212 --- /dev/null +++ b/odex25_donation/affiliate_management/data/demo_data_view.xml @@ -0,0 +1,435 @@ + + + + + + + Banner + image1 + + + + + Banner + image2 + + + + + Banner + image3 + + + + + Button + image4 + + + + + Button + image5 + + + + + Button + image6 + + + + + + Demo1 + + + 1 + DemoCity1 + 106 + + 31 Demo city street + Demo@example.com + (+886) (02) 4162 2023 + http://www.DemoUser.com + + True + 123OxPzL + + + + + Demo2 + + + 1 + DemoCity2 + 106367 + + 313 Demo2 city2 street2 + Demo2@example.com + (+886) (02) 4162 2023 + http://www.DemoUser2.com + + True + 223OxPzL + + + + + Demo3 + + + 1 + DemoCity3 + 106345 + + 313 Demo3 city3 street3 + Demo3@example.com + (+886) (02) 4162 2023 + http://www.DemoUser3.com + + True + 323OxPzL + + + + + Demo1@example.com + webkul + + + + + + + + Demo2@example.com + webkul + + + + + + + + Demo3@example.com + webkul + + + + + + + + + + webkul + Demo1@example.com + + aproove + + + + + webkul + Demo2@example.com + + aproove + + + + + webkul + Demo3@example.com + + aproove + + + + + + Demo4 + + + 1 + DemoCity4 + 106345 + + 313 Demo4 city4 street4 + Demo4@example.com + (+886) (02) 4162 2023 + http://www.DemoUser4.com + + + + + Demo4@example.com + webkul + + + + + + + + webkul + Demo4@example.com + + register + + + + + Demo5 + + + 1 + DemoCity5 + 106345 + + 313 Demo5 city5 street5 + Demo4@example.com + (+886) (02) 4162 2023 + http://www.DemoUser5.com + + + + + + Demo5@example.com + webkul + + + + + + + webkul + Demo5@example.com + + register + + + + + + Demo6@example.com + draft + CJyPAvexmav0Bar8C456 + + + + Demo7@example.com + draft + CJyPAvex1230Bar8C456 + + + + + + + + + + + + + + Zed+ Antivirus + + 1 + + + 2950.00 + + + + Antivirus + + 1 + + + 950.00 + + + + + ppc + product + 15 + iMac + False + 123OxPzL + + /shop/product/e-com09-imac-15?aff_key=123OxPzL + + draft + + + + + ppc + product + 15 + iPad + False + 223OxPzL + + /shop/product/e-com09-ipad-10?aff_key=223OxPzL + + draft + + + + + pps + product + 6 + Zed+ Antivirus + True + + 123OxPzL + + /shop/product/prod-order-zed-antivirus-6?aff_key=123OxPzL + + draft + 1 + + + + pps + product + 6 + Antivirus + True + + 223OxPzL + + /shop/product/prod-antivirus-6?aff_key=223OxPzL + + draft + 1 + + + + + ppc + product + 20 + Bosh Speaker + False + 323OxPzL + + /shop/product/e-com09-ipad-20?aff_key=323OxPzL + + draft + + + + ppc + product + 25 + Xemberg Shoes + False + 323OxPzL + + /shop/product/e-com09-ipad-40?aff_key=323OxPzL + + draft + + + + Advance Commission + True + + + + + product + + 1_product + 10 + fixed + 10 + 1 + + + + product + + 2_product_category + 4 + fixed + 10 + 1 + + + + product + + 3_global + fixed + 10 + 1 + + + + + + + Advance Commission2 + True + + + + + product + + 1_product + 20 + fixed + 100 + 1 + + + + product + + 2_product_category + 9 + fixed + 100 + 1 + + + + product + + 3_global + fixed + 100 + 1 + + + + + + + + + + diff --git a/odex25_donation/affiliate_management/data/sequence_view.xml b/odex25_donation/affiliate_management/data/sequence_view.xml new file mode 100644 index 000000000..ce78a86cf --- /dev/null +++ b/odex25_donation/affiliate_management/data/sequence_view.xml @@ -0,0 +1,12 @@ + + + + Program No + affiliate.visit + VST + 6 + + + + + diff --git a/odex25_donation/affiliate_management/help.txt b/odex25_donation/affiliate_management/help.txt new file mode 100644 index 000000000..213eaad06 --- /dev/null +++ b/odex25_donation/affiliate_management/help.txt @@ -0,0 +1,5 @@ +affiliate_ir_property_manager,manager_access_ir_property,base.model_ir_property,affiliate_security_manager_group,1,1,1,1 +affiliate_res_company_manager,manager_access_res_company,base.model_res_company,affiliate_security_manager_group,1,1,0,0 +affiliate_ir_module_module_manager,manager_access_ir_module_module,base.model_ir_module_module,affiliate_security_manager_group,1,1,0,0 +affiliate_ir_config_parameter_manager,manager_access_ir_config_parameter,base.model_ir_config_parameter,affiliate_security_manager_group,1,1,0,0 +affiliate_ir_rule_manager,manager_access_ir_rule,base.model_ir_rule,affiliate_security_manager_group,1,1,0,0 diff --git a/odex25_donation/affiliate_management/models/__init__.py b/odex25_donation/affiliate_management/models/__init__.py new file mode 100644 index 000000000..b90e2d91e --- /dev/null +++ b/odex25_donation/affiliate_management/models/__init__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +from . import affiliate_program +from . import affiliate_visit +from . import res_partner_inherit +from . import res_user_inherit +from . import affiliate_config_setting +from . import account_invoice_inherit +from . import affiliate_tool +from . import affiliate_banner +from . import affiliate_request +from . import affiliate_image +from . import advance_commision +from . import affiliate_product_pricelist_item +# from . import odoo_http diff --git a/odex25_donation/affiliate_management/models/account_invoice_inherit.py b/odex25_donation/affiliate_management/models/account_invoice_inherit.py new file mode 100644 index 000000000..59beb781c --- /dev/null +++ b/odex25_donation/affiliate_management/models/account_invoice_inherit.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError +from odoo import models, fields,api,_ +import random, string +from odoo.http import request + + +class AccountInvoiceInherit(models.Model): + _inherit = 'account.move' + + + aff_visit_id = fields.One2many('affiliate.visit','act_invoice_id',string="Report") + + +# def write(self, vals): +# result = super(AccountInvoiceInherit,self).write(vals) +# if self.ref: +# move_id = self.env["account.move"].sudo().search([("name","=",self.ref)]) +# if self.payment_state == "paid": + +# if move_id.aff_visit_id: +# move_id.aff_visit_id.write({"state":"paid"}) + +# return result + + + + +class AccountPaymentInherit(models.Model): + _inherit = 'account.payment' + _description = "Account Payment Inherit Model" + + + # def action_validate_invoice_payment(self): + def action_post(self): + result = super(AccountPaymentInherit,self).action_post() + active_id = self._context.get('active_id') + move_id = self.env['account.move'].browse([active_id]) + if move_id: + if move_id.state == "posted" and move_id.aff_visit_id: + for visit in move_id.aff_visit_id: + if visit.state != "paid": + visit.write({"state":"paid"}) + return result diff --git a/odex25_donation/affiliate_management/models/advance_commision.py b/odex25_donation/affiliate_management/models/advance_commision.py new file mode 100644 index 000000000..3db8ae9d5 --- /dev/null +++ b/odex25_donation/affiliate_management/models/advance_commision.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError +from odoo import models, fields,api,_ +class AffiliateCommision(models.Model): + _name = "advance.commision" + _description = "Affiliate Commision Model" + + name = fields.Char(string="Name", required=True) + pricelist_item_ids = fields.One2many("affiliate.product.pricelist.item",'advance_commision_id',string="Item") + active_adv_comsn = fields.Boolean(default=True,string="Active") + + + def toggle_active_button(self): + if self.active_adv_comsn: + self.active_adv_comsn = False + else: + self.active_adv_comsn = True + + # argument of calc_commision_adv(adv_comm_id, product_id on which commision apply , price of product) + def calc_commision_adv(self, adv_comsn_id, product_templ_id , product_price): + _logger.info("-----in adcvace commision model-- method-- calc_commision_adv-----") + product_tmpl_category_ids = self.env['product.template'].browse([product_templ_id]).public_categ_ids + _logger.info("**********-----product_tmpl_category_ids--%r********",product_tmpl_category_ids) + + pricelist_ids = self.env['affiliate.product.pricelist.item'].search([('advance_commision_id','=',adv_comsn_id)]) + for pricelist_id in pricelist_ids: + _logger.info("***====pricelist_id.name=%r======",pricelist_id.name) + + commision_value = False + commision_value_type = False + adv_commision_amount = False + + # on global product + if pricelist_id.applied_on == "3_global": + if pricelist_id.compute_price == "fixed": + commision_value = pricelist_id.fixed_price + commision_value_type = 'fixed' + adv_commision_amount = pricelist_id.fixed_price + else: + if pricelist_id.compute_price == "percentage": + commision_value = product_price * (pricelist_id.percent_price /100) + commision_value_type = 'percentage' + adv_commision_amount = pricelist_id.percent_price + + else: + # on product category + if pricelist_id.applied_on == "2_product_category": + if pricelist_id.categ_id in product_tmpl_category_ids: + if pricelist_id.compute_price == "fixed": + commision_value = pricelist_id.fixed_price + commision_value_type = 'fixed' + adv_commision_amount = pricelist_id.fixed_price + + else: + if pricelist_id.compute_price == "percentage": + commision_value = product_price * (pricelist_id.percent_price /100) + commision_value_type = 'percentage' + adv_commision_amount = pricelist_id.percent_price + + + else: + # on specific product + if pricelist_id.applied_on == "1_product": + if product_templ_id == pricelist_id.product_tmpl_id.id: + if pricelist_id.compute_price == "fixed": + commision_value = pricelist_id.fixed_price + commision_value_type = 'fixed' + adv_commision_amount = pricelist_id.fixed_price + + else: + if pricelist_id.compute_price == "percentage": + commision_value = product_price * (pricelist_id.percent_price /100) + commision_value_type = 'percentage' + adv_commision_amount = pricelist_id.percent_price + + + if commision_value and commision_value_type: + break + # this break is used for if advance commission found in pricelist ids + # then it will break so that further pricelist ids is not executed in for loop + # this is for calculation advance commission base on global, perticular product or category + return adv_commision_amount,commision_value , commision_value_type + + \ No newline at end of file diff --git a/odex25_donation/affiliate_management/models/affiliate_banner.py b/odex25_donation/affiliate_management/models/affiliate_banner.py new file mode 100644 index 000000000..c4c6c0c8e --- /dev/null +++ b/odex25_donation/affiliate_management/models/affiliate_banner.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError +from odoo import models, fields,api,_ +class AffiliateBanner(models.Model): + _name = "affiliate.banner" + _description = "Affiliate Banner Model" + + banner_title = fields.Text(string="Banner Text") + banner_image = fields.Binary(string="Banner Image") + + + @api.model_create_multi + def create(self,vals_list): + res = None + for vals in vals_list: + if vals.get('banner_image') == False: + raise UserError("Image field is mandatory") + res = super(AffiliateBanner,self).create(vals) + return res diff --git a/odex25_donation/affiliate_management/models/affiliate_config_setting.py b/odex25_donation/affiliate_management/models/affiliate_config_setting.py new file mode 100644 index 000000000..f76bc5397 --- /dev/null +++ b/odex25_donation/affiliate_management/models/affiliate_config_setting.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo import api, fields, models, _ +from odoo.exceptions import UserError + +class AffiliateConfiguration(models.TransientModel): + + _inherit = 'res.config.settings' + _description = "Affiliate Configuration Model" + + @api.model + def _get_program(self): + # _logger.info("-----_get_program-----%r-----",self.env['affiliate.program'].search([])) + # self.remove_prgm() + return self.env['affiliate.program'].search([],limit=1).id + + def remove_prgm(self): + # _logger.info("----remove_prgm--env['affiliate.program']------%r-----",self.env['affiliate.program'].search([])) + prgm = self.env['affiliate.program'].search([]) + for p in prgm: + p.unlink() + + + @api.model + def _get_banner(self): + return self.env['affiliate.banner'].search([],limit=1).id + + affiliate_program_id = fields.Many2one('affiliate.program',string=" Affiliate Program") + enable_ppc = fields.Boolean(string= "Enable PPC", default=True ) + auto_approve_request = fields.Boolean(default=False ) + ppc_maturity = fields.Integer(string="PPC Maturity",required=True, default=1) + ppc_maturity_period = fields.Selection([('days','Days'),('months','Months'),('weeks','Weeks')],required=True,default='days') + cookie_expire = fields.Integer(string="Cookie expiration",required=True, default=1) + cookie_expire_period = fields.Selection([('hours','Hours'),('days','Days'),('months','Months')],required=True,default='days') + payment_day = fields.Integer(string="Payment day",required=True, default=7) + minimum_amt = fields.Integer(string="Minimum Payout Balance",required=True, default=0) + currency_id = fields.Many2one('res.currency', 'Currency', required=True, + default=lambda self: self.env.user.company_id.currency_id.id) + aff_product_id = fields.Many2one('product.product', 'Product',help="Product used in Invoicing") + enable_signup = fields.Boolean(string= "Enable Sign Up", default=True ) + enable_login = fields.Boolean(string= "Enable Log In", default=True ) + enable_forget_pwd = fields.Boolean(string= "Enable Forget Password", default=False ) + affiliate_banner_id = fields.Many2one('affiliate.banner',string="Bannner") + welcome_mail_template = fields.Many2one('mail.template',string="Approved Request Mail",readonly=True ) + reject_mail_template = fields.Many2one('mail.template',string="Reject Request Mail ",readonly=True) + Invitation_mail_template = fields.Many2one('mail.template',string="Invitation Request Mail ",readonly=True) + unique_ppc_traffic = fields.Boolean(string= "Unique ppc for product", default=False,help="this field is used to enable unique traffic on product for an Affiliate for a specific browser. " ) + term_condition = fields.Html(string="Term & condition Text", related='affiliate_program_id.term_condition',translate=True) + work_title = fields.Text(string="How Does It Work Title",related='affiliate_program_id.work_title', translate=True) + work_text = fields.Html(string="How Does It Work Text",related='affiliate_program_id.work_text', translate=True) + + + + # @api.multi + def set_values(self): + if self.minimum_amt < 1: + raise UserError(_("Minimum Payout Balance should not be in negative figure.")) + super(AffiliateConfiguration, self).set_values() + IrDefault = self.env['ir.default'].sudo() + IrDefault.set('res.config.settings', 'ppc_maturity', self.ppc_maturity) + IrDefault.set('res.config.settings', 'ppc_maturity_period', self.ppc_maturity_period) + IrDefault.set('res.config.settings', 'enable_ppc', self.enable_ppc) + IrDefault.set('res.config.settings', 'auto_approve_request', self.auto_approve_request ) + IrDefault.set('res.config.settings', 'aff_product_id', self.aff_product_id.id) + IrDefault.set('res.config.settings', 'enable_signup', self.enable_signup ) + IrDefault.set('res.config.settings', 'enable_login', self.enable_login ) + IrDefault.set('res.config.settings', 'enable_forget_pwd', self.enable_forget_pwd ) + IrDefault.set('res.config.settings', 'payment_day', self.payment_day) + IrDefault.set('res.config.settings', 'minimum_amt', self.minimum_amt) + IrDefault.set('res.config.settings', 'cookie_expire', self.cookie_expire) + IrDefault.set('res.config.settings', 'cookie_expire_period', self.cookie_expire_period) + IrDefault.set('res.config.settings', 'unique_ppc_traffic', self.unique_ppc_traffic) + + IrDefault.set('res.config.settings', 'term_condition', self.term_condition) + IrDefault.set('res.config.settings', 'work_title', self.work_title) + IrDefault.set('res.config.settings', 'work_text', self.work_text) + + + # IrDefault.set('res.config.settings', 'affiliate_program_id', self.affiliate_program_id.id) + # IrDefault.set('res.config.settings', 'affiliate_banner_id', self.affiliate_banner_id.id) + IrDefault.set('res.config.settings', 'affiliate_program_id', self._get_program()) + IrDefault.set('res.config.settings', 'affiliate_banner_id', self._get_banner()) + self.scheduler_ppc_maturity_set() + + def scheduler_ppc_maturity_set(self): + ppc_maturity_schedular = self.env.ref("affiliate_management.affiliate_ppc_maturity_scheduler_call") + ppc_maturity_schedular.write({ + 'interval_number' : self.ppc_maturity, + 'interval_type' : self.ppc_maturity_period, + }) + + + @api.model + def get_values(self): + template_1 = self.env['ir.model.data']._xmlid_lookup('affiliate_management.welcome_affiliate_email')[2] + template_2 = self.env['ir.model.data']._xmlid_lookup('affiliate_management.reject_affiliate_email')[2] + template_3 = self.env['ir.model.data']._xmlid_lookup('affiliate_management.join_affiliate_email')[2] + res = super(AffiliateConfiguration, self).get_values() + IrDefault = self.env['ir.default'].sudo() + res.update( + welcome_mail_template=IrDefault.get('res.config.settings', 'welcome_mail_template') or template_1, + reject_mail_template=IrDefault.get('res.config.settings', 'reject_mail_template') or template_2, + Invitation_mail_template=IrDefault.get('res.config.settings', 'Invitation_mail_template') or template_3, + work_title=IrDefault.get('res.config.settings', 'work_title') or _("The process is very simple. Simply, signup/login to your affiliate portal, pick your affiliate link and place them into your website/blogs and watch your account balance grow as your visitors become our customers, as :"), + work_text=IrDefault.get('res.config.settings', 'work_text') or _("
  1. Visitor clicks on affiliate links posted on your website/blogs.

  2. A cookie is placed in their browser for tracking purposes. The visitor browses our site and may decide to order.

  3. The visitor browses our site and may decide to order. If the visitor orders, the order will be registered as a sale for you and you will receive a commission for this sale.

  4. If the visitor orders, the order will be registered as a sale for you and you will receive a commission for this sale.

"), + unique_ppc_traffic=IrDefault.get('res.config.settings', 'unique_ppc_traffic') or False, + term_condition=IrDefault.get('res.config.settings', 'term_condition') or _("Write your own Term and Condition"), + ppc_maturity =IrDefault.get('res.config.settings', 'ppc_maturity') or 1, + ppc_maturity_period=IrDefault.get('res.config.settings', 'ppc_maturity_period')or 'months', + enable_ppc =IrDefault.get('res.config.settings', 'enable_ppc') or False, + auto_approve_request =IrDefault.get('res.config.settings', 'auto_approve_request' ) or False, + aff_product_id=IrDefault.get('res.config.settings', 'aff_product_id') or False, + enable_signup =IrDefault.get('res.config.settings', 'enable_signup') or False, + enable_login =IrDefault.get('res.config.settings', 'enable_login' ) or False, + enable_forget_pwd =IrDefault.get('res.config.settings', 'enable_forget_pwd') or False, + payment_day =IrDefault.get('res.config.settings', 'payment_day') or 7, + minimum_amt =IrDefault.get('res.config.settings', 'minimum_amt') or 1, + cookie_expire=IrDefault.get('res.config.settings', 'cookie_expire') or 1, + cookie_expire_period =IrDefault.get('res.config.settings', 'cookie_expire_period') or 'days', + affiliate_program_id =IrDefault.get('res.config.settings', 'affiliate_program_id') or self._get_program(), + affiliate_banner_id =IrDefault.get('res.config.settings', 'affiliate_banner_id') or self._get_banner(), + ) + return res + + def website_constant(self): + res ={} + IrDefault = self.env['ir.default'].sudo() + aff_prgmObj = self.env['affiliate.program'].search([], limit=1) + res.update( + work_title = aff_prgmObj.work_title or "The process is very simple. Simply, signup/login to your affiliate portal, pick your affiliate link and place them into your website/blogs and watch your account balance grow as your visitors become our customers, as :", + work_text = aff_prgmObj.work_text or "
  1. Visitor clicks on affiliate links posted on your website/blogs.

  2. A cookie is placed in their browser for tracking purposes.

  3. The visitor browses our site and may decide to order.

  4. If the visitor orders, the order will be registered as a sale for you and you will receive a commission for this sale.

", + unique_ppc_traffic = IrDefault.get('res.config.settings', 'unique_ppc_traffic') or False, + term_condition = aff_prgmObj.term_condition or "Write your own Term and Condition", + enable_ppc =IrDefault.get('res.config.settings', 'enable_ppc') or False, + enable_signup =IrDefault.get('res.config.settings', 'enable_signup') or False, + enable_login =IrDefault.get('res.config.settings', 'enable_login' ) or False, + enable_forget_pwd =IrDefault.get('res.config.settings', 'enable_forget_pwd') or False, + auto_approve_request =IrDefault.get('res.config.settings', 'auto_approve_request' ) or False, + cookie_expire=IrDefault.get('res.config.settings', 'cookie_expire') or 1, + cookie_expire_period =IrDefault.get('res.config.settings', 'cookie_expire_period') or 'days', + payment_day =IrDefault.get('res.config.settings', 'payment_day') or 7, + minimum_amt =IrDefault.get('res.config.settings', 'minimum_amt') or 1, + aff_product_id=IrDefault.get('res.config.settings', 'aff_product_id') or False, + ) + return res + + + # @api.multi + def open_program(self): + return { + 'type': 'ir.actions.act_window', + 'name': 'My Affiliate Program', + # 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'affiliate.program', + 'res_id': self.affiliate_program_id.id, + 'target': 'current', + } + + # @api.multi + def open_banner(self): + return { + 'type': 'ir.actions.act_window', + 'name': 'My Affiliate Banner', + # 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'affiliate.banner', + 'res_id': self.affiliate_banner_id.id, + 'target': 'current', + } diff --git a/odex25_donation/affiliate_management/models/affiliate_image.py b/odex25_donation/affiliate_management/models/affiliate_image.py new file mode 100644 index 000000000..b23bd9e76 --- /dev/null +++ b/odex25_donation/affiliate_management/models/affiliate_image.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError +from odoo import models, fields,api,_ +class AffiliateImage(models.Model): + _name = "affiliate.image" + _description = "Affiliate Image Model" + _inherit = ['mail.thread'] + + + name = fields.Char(string = "Name",required=True) + title = fields.Char(string = "Title",required=True) + banner_height = fields.Integer(string = "Height") + bannner_width = fields.Integer(string = "Width") + image = fields.Binary(string="Image",required=True) + user_id = fields.Many2one('res.users', string='current user', index=True, tracking=True, default=lambda self: self.env.user) + image_active = fields.Boolean(string="Active",default=True) + + + def toggle_active_button(self): + if self.image_active: + self.image_active = False + else: + self.image_active = True + + + @api.model_create_multi + def create(self,vals_list): + res = None + for vals in vals_list: + if vals.get('image') == False: + raise UserError("Image field is mandatory") + res = super(AffiliateImage,self).create(vals) + return res diff --git a/odex25_donation/affiliate_management/models/affiliate_product_pricelist_item.py b/odex25_donation/affiliate_management/models/affiliate_product_pricelist_item.py new file mode 100644 index 000000000..8f6605cb8 --- /dev/null +++ b/odex25_donation/affiliate_management/models/affiliate_product_pricelist_item.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError +from odoo import models, fields,api,_ + +class AffiliateProductPricelistItem(models.Model): + _name = "affiliate.product.pricelist.item" + _description = "Affiliate Product Pricelist Item Model" + _order = 'sequence' + + name = fields.Char(string="Name") + advance_commision_id = fields.Many2one('advance.commision') + applied_on = fields.Selection([ + ('3_global', 'Global'), + ('2_product_category', ' Product Category'), + ('1_product', 'Product')], "Apply On", + default='3_global', required=True, + help='Pricelist Item applicable on selected option') + categ_id = fields.Many2one( + 'product.public.category', 'Product Category', ondelete='cascade', + help="Specify a product category if this rule only applies to products belonging to this eccmmerce website category or its children categories. Keep empty otherwise.") + product_tmpl_id = fields.Many2one( + 'product.template', 'Product Template', ondelete='cascade', + help="Specify a template if this rule only applies to one product template. Keep empty otherwise.") + compute_price = fields.Selection([ + ('fixed', 'Fix Price'), + ('percentage', 'Percentage (discount)')], index=True, default='fixed') + fixed_price = fields.Float('Fixed Price') + percent_price = fields.Float('Percentage Price') + + currency_id = fields.Many2one('res.currency', 'Currency', required=True, + default=lambda self: self.env.user.company_id.currency_id.id,readonly='True') + sequence = fields.Integer(required=True, default=1, + help="The sequence field is used to define order in which the pricelist item are applied.") + + # @api.multi + def write(self, vals): + if 'fixed_price' in vals.keys() or 'compute_price' in vals.keys() or 'percent_price' in vals.keys(): + compute_price = vals.get('compute_price') if 'compute_price' in vals.keys() else self[-1].compute_price + change_value = None + if compute_price == 'fixed': + if 'fixed_price' in vals.keys(): + change_value = vals.get('fixed_price') + else: + change_value = self[-1].fixed_price + else: + if 'percent_price' in vals.keys(): + change_value = vals.get('percent_price') + else: + change_value = self[-1].percent_price + + if change_value <= 0: + raise UserError("Price List Item value must be greater than zero.") + + return super(AffiliateProductPricelistItem,self).write(vals) + + @api.model_create_multi + def create(self, vals_list): + res = None + for vals in vals_list: + if (vals.get('compute_price') == 'fixed') and vals.get('fixed_price') <= 0: + raise UserError("Price List Item value must be greater than zero.") + + if (vals.get('compute_price') == 'percentage') and vals.get('percent_price') <= 0: + raise UserError("Price List Item value must be greater than zero.") + + res = super(AffiliateProductPricelistItem,self).create(vals) + + return res + + # @api.model + # def create(self, vals): + # if vals.get('fixed_price') and vals.get('fixed_price') < 0: + # raise UserError(_("Fixed Price should not be in negative figure.")) + # if vals.get('percent_price') and vals.get('percent_price') > -1 or vals.get('percent_price') < 100: + # raise UserError(_("Percentage Price should not be less than zero or greater than 100.")) + # return super(AffiliateProductPricelistItem,self).create(vals) diff --git a/odex25_donation/affiliate_management/models/affiliate_program.py b/odex25_donation/affiliate_management/models/affiliate_program.py new file mode 100644 index 000000000..010063f0b --- /dev/null +++ b/odex25_donation/affiliate_management/models/affiliate_program.py @@ -0,0 +1,64 @@ + +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError +from odoo import models, fields,api,_ +class AffiliateProgram(models.Model): + _name = "affiliate.program" + _description = "Affiliate Model" + + name = fields.Char(string = "Name",required=True) + ppc_type = fields.Selection([("s","Simple"),("a","Advance")], string="Ppc Type",required=True,default="s") + amount_ppc_fixed = fields.Float(string="Amount Fixed",default=0,required=True) + pps_type = fields.Selection([("s","Simple"),("a","Advanced")], string="Pps Type",required=True,default="s") + matrix_type = fields.Selection([("f","Fixed"),("p","Percentage")],required=True,default='f',string="Matrix Type") + amount = fields.Float(string="Amount",default=0, required=True) + currency_id = fields.Many2one('res.currency', 'Currency', + default=lambda self: self.env.user.company_id.currency_id.id) + advance_commision_id = fields.Many2one('advance.commision',string="Pricelist",domain="[('active_adv_comsn', '=', True)]") + + # config field for translation + term_condition = fields.Html(string="Term & condition Text", translate=True) + work_title = fields.Text(string="How Does It Work Title", translate=True) + work_text = fields.Html(string="How Does It Work Text", translate=True) + + + def unlink(self): + raise UserError(_("You can't delete the Affiliate Program.")) + + @api.model + def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False): + cxt = dict(self._context) + cxt['hide_ppc'] = not self.env['ir.default'].get('res.config.settings', 'enable_ppc') + + res = super(AffiliateProgram, self.with_context(cxt)).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu) + return res + + @api.onchange('matrix_type') + def check_amount(self): + m_type = self.matrix_type + amount = self.amount + if m_type == 'p' and amount > 100: + self.amount = 0 + + def write(self, vals): + if vals.get('work_text') and vals.get('work_text')=='


': + vals['work_text'] = None + if vals.get('term_condition') and vals.get('term_condition')=='


': + vals['term_condition'] = None + return super(AffiliateProgram, self).write(vals) diff --git a/odex25_donation/affiliate_management/models/affiliate_request.py b/odex25_donation/affiliate_management/models/affiliate_request.py new file mode 100644 index 000000000..f507cfbaa --- /dev/null +++ b/odex25_donation/affiliate_management/models/affiliate_request.py @@ -0,0 +1,213 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError +from odoo import models, fields,api,_ +from datetime import datetime, timedelta +from odoo.addons.auth_signup.models.res_partner import SignupError, now +import random +from ast import literal_eval +from odoo import SUPERUSER_ID +from odoo.http import request + + +class AffiliateRequest(models.Model): + _name = "affiliate.request" + _description = "Affiliate Request Model" + # _inherit = ['ir.needaction_mixin'] + + def random_token(self): + # the token has an entropy of about 120 bits (6 bits/char * 20 chars) + chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + return ''.join(random.SystemRandom().choice(chars) for i in range(20)) + + + + + password = fields.Char(string='password',invisible=True) + name = fields.Char(string="Email") + partner_id = fields.Many2one('res.partner') + signup_token = fields.Char(string='Token',invisible=True) + signup_expiration = fields.Datetime(copy=False) + signup_valid = fields.Boolean(compute='_compute_signup_valid', string='Signup Token is Valid',default=False) + signup_type = fields.Char(string='Signup Token Type', copy=False) + # user_id = fields.Integer(string='User',help='check wether the request have user id') + user_id = fields.Many2one('res.users') + + parent_aff_key = fields.Char(string='Parent Affiliate Key') + state = fields.Selection([ + ('draft', 'Requested'), + ('register', 'Pending For Approval'), + ('cancel', 'Rejected'), + ('aproove', 'Approved'), + ], string='Status', readonly=True, default='draft' ) + + + @api.model_create_multi + def create(self, vals_list): + aff_request = None + for vals in vals_list: + _logger.info("these are vals we need to create aff req %r",vals) + if vals.get('user_id'): + # for portal user + if len(self.search([('user_id','=',vals.get('user_id'))])) == 0: + aff_request = super(AffiliateRequest,self).create(vals) + else: + aff_request = self.search([('user_id','=',vals.get('user_id'))]) + + else: + # for new user signup with affilaite sign up page + aff_request = super(AffiliateRequest,self).create(vals) + aff_request.signup_token = self.random_token() + aff_request.signup_expiration = fields.Datetime.now() + aff_request.signup_type = 'signup' + self.send_joining_mail(aff_request) + + return aff_request + + # @api.multi + def _compute_signup_valid(self): + + """after one day sign up token is valid false""" + if self.user_id: + self.signup_valid = self.signup_valid + pass + else: + dt = fields.Datetime.from_string(fields.Datetime.now()) + expiration = fields.Datetime.from_string(self.signup_expiration)+timedelta(days=1) + if dt > expiration: + self.signup_valid = False + else: + self.signup_valid = True + + + def action_cancel(self): + user = self.env['res.users'].search([('login','=',self.name),('active','=',True)]) + # find id of security grup user + user_group_id = self.env['ir.model.data'].check_object_reference('affiliate_management', 'affiliate_security_user_group')[1] + if self.user_id: + if self.user_id.id == self.env.ref('base.user_admin').id: + raise UserError("Admin can't be an Affiliate") + # for portal user + # remove grup ids from user groups_id + user.groups_id = [(3, user_group_id)] + user.groups_id = [(3, user_group_id+1)] + + user.partner_id.is_affiliate = False + self.state = 'cancel' + template_id = self.env.ref('affiliate_management.reject_affiliate_email') + user_mail = self.env.user.partner_id.company_id.email or self.env.company.email + email_values = {"email_from":user_mail} + db = request.session.get('db') + res = template_id.with_context({"db":db}).send_mail(self.id,force_send=True,email_values=email_values) + return True + + def action_aproove(self): + if self.user_id: + if self.user_id.id == self.env.ref('base.user_admin').id: + raise UserError("Admin can't be an Affiliate") + affiliate_program = self.env['affiliate.program'].search([]) + if not affiliate_program: + raise UserError("In Configuration settings Program is absent") + with self.env.cr.savepoint(): + self.set_group_user(self.user_id.id) + self.state = 'aproove' + self.user_id.partner_id.is_affiliate = True + self.env.cr.commit() + template_id = self.env.ref('affiliate_management.welcome_affiliate_email') + user_mail = self.env.user.partner_id.company_id.email or self.env.company.email + db = request.session.get('db') + email_values = {"email_from":user_mail} + res = template_id.send_mail(self.id,force_send=True,email_values=email_values) + return True + + + + + @api.model + def _signup_create_user(self, values): + """ create a new user from the template user """ + IrConfigParam = self.env['ir.config_parameter'] + template_user_id = literal_eval(IrConfigParam.get_param('base.template_portal_user_id', 'False')) + template_user = self.browse(template_user_id) + assert template_user.exists(), 'Signup: invalid template user' + + # check that uninvited users may sign up + if 'partner_id' not in values: + if not literal_eval(IrConfigParam.get_param('auth_signup.allow_uninvited', 'False')): + raise SignupError('Signup is not allowed for uninvited users') + + assert values.get('login'), "Signup: no login given for new user" + assert values.get('partner_id') or values.get('name'), "Signup: no name or partner given for new user" + + # create a copy of the template user (attached to a specific partner_id if given) + values['active'] = True + try: + with self.env.cr.savepoint(): + return template_user.with_context(reset_password=False).copy(values) + # return template_user.with_context(no_reset_password=True).copy(values) + except Exception as e: + # copy may failed if asked login is not available. + raise SignupError(ustr(e)) + + def send_joining_mail(self,aff_request): + if aff_request.signup_valid: + db = request.session.get('db') + template_id = self.env.ref('affiliate_management.join_affiliate_email') + user_mail = self.env.user.partner_id.company_id.email or self.env.company.email + email_values = {"email_from":user_mail} + res = template_id.send_mail(aff_request.id,force_send=True,email_values=email_values) + + + def regenerate_token(self): + self.signup_token = self.random_token() + self.signup_expiration = fields.Datetime.now() + self.signup_valid = True + self.send_joining_mail(self) + + +# for counter on request menu + # @api.model + # def _needaction_count(self, domain=None): + # return len(self.env['affiliate.request'].search([('state','=','register')])) + + def set_group_user(self,user_id): + """Assign group to portal user""" + UserObj = self.env['res.users'].sudo() + user_group_id = self.env['ir.model.data']._xmlid_lookup('affiliate_management.affiliate_security_user_group')[2] + groups_obj = self.env["res.groups"].browse(user_group_id) + if groups_obj: + for group_obj in groups_obj: + group_obj.write({"users": [(4, user_id, 0)]}) + user = UserObj.browse([user_id]) + user.active = True + user.partner_id.is_affiliate = True + user.partner_id.res_affiliate_key = ''.join(random.choice('0123456789ABCDEFGHIJ0123456789KLMNOPQRSTUVWXYZ') for i in range(8)) + user.partner_id.affiliate_program_id = self.env['affiliate.program'].search([])[-1].id + + + def checkRequestExists(self,user_id): + exist = self.search([('user_id','=',user_id.id)]) + return len(exist) and True or False + + def checkRequeststate(self,user_id): + exist = self.search([('user_id','=',user_id.id)]) + if len(exist): + if exist.state == 'register': + return 'pending' + elif exist.state == 'cancel': + return 'cancel' diff --git a/odex25_donation/affiliate_management/models/affiliate_tool.py b/odex25_donation/affiliate_management/models/affiliate_tool.py new file mode 100644 index 000000000..2a2ade696 --- /dev/null +++ b/odex25_donation/affiliate_management/models/affiliate_tool.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +from odoo import models,fields,api,_ +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError + +class AffiliateTool(models.TransientModel): + _name = 'affiliate.tool' + _description = "Affiliate Tool Model" + _inherit = ['mail.thread'] + + @api.depends('entity','aff_product_id','aff_category_id') + def _make_link(self): + key = "" + if self.env['res.users'].browse(self.env.uid).res_affiliate_key: + key = self.env['res.users'].browse(self.env.uid).res_affiliate_key + type_url = "" + if self.entity == 'product': + type_url = '/shop/product/'+str(self.aff_product_id.id) + if self.entity == 'category': + type_url = '/shop/category/'+str(self.aff_category_id.id) + base_url = self.env['ir.config_parameter'].get_param('web.base.url') + if self.entity and (self.aff_product_id or self.aff_category_id): + self.link = base_url+type_url+"?aff_key="+key + else: + self.link = "" + + @api.onchange('entity') + def _blank_field(self): + self.aff_product_id = "" + self.aff_category_id = "" + self.link = "" + name = fields.Char(string="Name") + entity = fields.Selection([('product','Product'),('category','Category')],string="Choose Entity",required=True) + aff_product_id = fields.Many2one('product.template', string='Product') + aff_category_id = fields.Many2one('product.public.category',string='Category') + link = fields.Char(string='Link',compute='_make_link') + user_id = fields.Many2one('res.users', string='current user', index=True, tracking=True, default=lambda self: self.env.user) + + @api.model_create_multi + def create(self, vals_list): + new_url = None + for vals in vals_list: + vals['name'] = self.env['ir.sequence'].next_by_code('affiliate.tool') + new_url = super(AffiliateTool,self).create(vals) + return new_url diff --git a/odex25_donation/affiliate_management/models/affiliate_visit.py b/odex25_donation/affiliate_management/models/affiliate_visit.py new file mode 100644 index 000000000..79c766f41 --- /dev/null +++ b/odex25_donation/affiliate_management/models/affiliate_visit.py @@ -0,0 +1,361 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError +from odoo import models, fields,api,_ +from datetime import timedelta +import datetime + +class AffiliateVisit(models.Model): + _name = "affiliate.visit" + _order = "create_date desc" + _description = "Affiliate Visit Model" + + name = fields.Char(string = "Name",readonly='True') + + # @api.multi + @api.depends('affiliate_type','type_id') + def _calc_type_name(self): + for record in self: + if record.affiliate_type == 'product': + record.type_name = record.env['product.template'].browse([record.type_id]).name + if record.affiliate_type == 'category': + record.type_name = record.env['product.public.category'].browse([record.type_id]).name + + + affiliate_method = fields.Selection([("ppc","Pay Per Click"),("pps","Pay Per Sale")],string="Order Report",readonly='True',states={'draft': [('readonly', False)]},help="state of traffic either ppc or pps") + affiliate_type = fields.Selection([("product","Product"),("category","Category")],string="Affiliate Type",readonly='True',states={'draft': [('readonly', False)]},help="whether the ppc or pps is on product or category") + type_id = fields.Integer(string='Type Id',readonly='True',states={'draft': [('readonly', False)]},help="Id of product template on which ppc or pps traffic create") + type_name = fields.Char(string='Type Name',readonly='True',states={'draft': [('readonly', False)]},compute='_calc_type_name',help="Name of the product") + is_converted = fields.Boolean(string="Is Converted",readonly='True',states={'draft': [('readonly', False)]}) + sales_order_line_id = fields.Many2one("sale.order.line",readonly='True',states={'draft': [('readonly', False)]}) + affiliate_key = fields.Char(string="Key",readonly='True',states={'draft': [('readonly', False)]}) + affiliate_partner_id = fields.Many2one("res.partner",string="Affiliate",readonly='True',states={'draft': [('readonly', False)]}) + url = fields.Char(string="Url",readonly='True',states={'draft': [('readonly', False)]}) + ip_address = fields.Char(readonly='True',states={'draft': [('readonly', False)]}) + currency_id = fields.Many2one('res.currency', 'Currency', required=True, + default=lambda self: self.env.user.company_id.currency_id.id,readonly='True',states={'draft': [('readonly', False)]}) + convert_date = fields.Datetime(string='Date',readonly='True',states={'draft': [('readonly', False)]}) + price_total = fields.Monetary(string="Sale value",related='sales_order_line_id.price_total',states={'draft': [('readonly', False)]},help="Total sale value of product" ) + unit_price = fields.Float(string="Product Unit Price", related='sales_order_line_id.price_unit', readonly='True', + states={'draft': [('readonly', False)]},help="price unit of the product") + commission_amt = fields.Float(readonly='True',states={'draft': [('readonly', False)]}) + affiliate_program_id = fields.Many2one('affiliate.program',string='Program',readonly='True',states={'draft': [('readonly', False)]}) + amt_type = fields.Char(string='Commission Matrix',readonly='True',states={'draft': [('readonly', False)]},help="Commission Matrix on which commission value calculated") + act_invoice_id = fields.Many2one("account.move", string='Act Invoice id',readonly='True',states={'draft': [('readonly', False)]}) + state = fields.Selection([ + ('draft', 'Draft'), + ('cancel', 'Cancel'), + ('confirm', 'Confirm'), + ('invoice', 'Invoiced'), + ('paid', 'Paid'), + ], string='Status', readonly=True, default='draft' ) + product_quantity = fields.Integer(readonly='True',states={'draft': [('readonly', False)]}) + + + + @api.model_create_multi + def create(self, vals_list): + new_visit = None + for vals in vals_list: + vals['name'] = self.env['ir.sequence'].next_by_code('affiliate.visit') + new_visit = super(AffiliateVisit,self).create(vals) + return new_visit + +# button on view action + def action_cancel(self): + self.state = 'cancel' + return True + +# button on view action + def action_confirm(self): + check_enable_ppc = self.env['res.config.settings'].sudo().website_constant().get('enable_ppc') + + if self.affiliate_method != 'ppc' and not self.sales_order_line_id: + raise UserError("Order is not present in visit %s."%self.name) + if self.affiliate_method != 'ppc' and not self.price_total: + raise UserError("Sale value must be greater than zero.") + + if self.affiliate_method == 'ppc' and (not check_enable_ppc) : + raise UserError("Pay per click is disable, so you can't confirm it's commission") + self.state = 'confirm' + status = self._get_rate(self.affiliate_method , self.affiliate_type, self.type_id ) + if status.get('is_error'): + raise UserError(status['message']) + return True + + +# button on view action + def action_paid(self): + self.state = 'paid' + return True + + + +# scheduler according to the scheduler define in data automated scheduler + + @api.model + def process_scheduler_queue(self): + users_all = self.env['res.users'].search([('is_affiliate','=',True)]) + ConfigValues = self.env['res.config.settings'].sudo().website_constant() + payment_day = ConfigValues.get('payment_day') + threshold_amt = ConfigValues.get('minimum_amt') + # make the date of current month of setting date + payment_date = datetime.date(datetime.date.today().year, datetime.date.today().month, payment_day) + for u in users_all: + visits = self.search([('state','=','confirm'),('affiliate_partner_id','=',u.partner_id.id)]) + if payment_date and visits: + visits = visits.filtered(lambda r: fields.Date.from_string(r.create_date) <= payment_date) + _logger.info("*****filter- visits=%r******",visits) + + _logger.info("****before******before method***visits**%r*******",visits) + visits = self.check_enable_ppc_visits(visits) + # function to filter the visits if ppc is enable or disable accordingly + _logger.info("*****after*****after method***visits**%r*******",visits) + total_comm_per_user = 0 + if visits: + for v in visits: + total_comm_per_user = total_comm_per_user + v.commission_amt + if total_comm_per_user >= threshold_amt and payment_date: + dic={ + 'name':"Total earn commission on ppc and pps", + 'quantity':1, + 'price_unit':total_comm_per_user, + 'product_id':ConfigValues.get('aff_product_id'), + } + invoice_dict = [ + { + 'invoice_line_ids': [(0, 0, dic)], + 'move_type': 'in_invoice', + 'partner_id':u.partner_id.id, + 'invoice_date':fields.Datetime.now().date() + } + ] + + inv_id = self.env['account.move'].create(invoice_dict) + for v in visits: + v.state = 'invoice' + v.act_invoice_id = inv_id.id + return True + + + def check_enable_ppc_visits(self,visits): + check_enable_ppc = self.env['res.config.settings'].sudo().website_constant().get('enable_ppc') + if check_enable_ppc: + return visits + else: + visits = visits.filtered(lambda v: v.affiliate_method == 'pps') + return visits + + + + # method call from server action + @api.model + def create_invoice(self): + # get the value of enable ppc from settings + ConfigValues = self.env['res.config.settings'].sudo().website_constant() + check_enable_ppc = ConfigValues.get('enable_ppc') + aff_vst = self._context.get('active_ids') + act_invoice = self.env['account.move'] + # check the first visit of context is ppc or pps and enable pps + affiliate_method_type = self.browse([aff_vst[0]]).affiliate_method + if affiliate_method_type == 'ppc' and (not check_enable_ppc) : + raise UserError("Pay per click is disable, so you can't generate it's invoice") + + invoice_ids =[] + for v in aff_vst: + vst = self.browse([v]) + # [[0, 'virtual_754', {'sequence': 10, 'product_id': 36, 'name': '[Deposit] Deposit', 'account_id': 21, 'analytic_account_id': False, 'analytic_tag_ids': [[6, False, []]], + # 'quantity': 1, 'product_uom_id': 1, 'price_unit': 150, 'discount': 0, 'tax_ids': [[6, False, [1]]] + + if vst.state == 'confirm': + # ********** creating invoice line ********************* + if vst.sales_order_line_id: + dic={ + 'name':"Type "+vst.affiliate_type+" on Pay Per Sale ", + 'quantity':1, + 'price_unit':vst.commission_amt, + # 'move_id':inv_id.id, + # 'product_id':ConfigValues.get('aff_product_id'), + } + else: + dic={ + 'name':"Type "+vst.affiliate_type+" on Pay Per Click ", + 'price_unit':vst.commission_amt, + 'quantity':1, + # 'product_id':ConfigValues.get('aff_product_id'), + } + + invoice_dict = [ + { + 'invoice_line_ids': [(0, 0, dic)], + 'move_type': 'in_invoice', + 'partner_id':vst.affiliate_partner_id.id, + 'invoice_date':fields.Datetime.now().date() + }] + line = self.env['account.move'].create(invoice_dict) + vst.state = 'invoice' + vst.act_invoice_id = line.id + invoice_ids.append(line) + msg = str(len(invoice_ids))+' records has been invoiced out of '+str(len(aff_vst)) + + + partial_id = self.env['wk.wizard.message'].create({'text': msg}) + return { + 'name': "Message", + 'view_mode': 'form', + 'view_id': False, + 'res_model': 'wk.wizard.message', + 'res_id': partial_id.id, + 'type': 'ir.actions.act_window', + 'nodestroy': True, + 'target': 'new', + } + + + def _get_rate(self,affiliate_method,affiliate_type,type_id): + #_get_rate() methods arguments (pps,product,product_id) or (ppc,product,product_id) or (ppc,category,category_id) + # check product.id in product.template + # check category.id in product.public.category + product_exists = False + category_exists = False + commission = 0.0 + commission_type = False + adv_commision_amount = False + from_currency = self.sales_order_line_id.currency_id + company = self.env.user.company_id + response = {} + if self.affiliate_program_id: + if affiliate_type == 'product': + product_exists = self.env['product.template'].browse([type_id]) + if affiliate_type == 'category': + category_exists = self.env['product.public.category'].browse([type_id]) + + if affiliate_method == 'ppc' and product_exists or category_exists: # pay per click + commission = from_currency._convert(self.affiliate_program_id.amount_ppc_fixed,self.affiliate_program_id.currency_id, company, fields.Date.today()) + commission_type = 'fixed' + self.commission_amt = commission + else: + # pay per sale + if affiliate_method == 'pps' and product_exists : + #for pps_type simple + if self.affiliate_program_id.pps_type == 's': + if self.affiliate_program_id.matrix_type == 'f': # fixed + amt = from_currency._convert(self.affiliate_program_id.amount,self.affiliate_program_id.currency_id, company, fields.Date.today()) + commission = amt * self.product_quantity + commission_type = 'fixed' + else: + if self.affiliate_program_id.matrix_type == 'p' and (not self.affiliate_program_id.amount >100): # percentage + amt_product = from_currency._convert(self.price_total,self.affiliate_program_id.currency_id, company, fields.Date.today()) + commission = (amt_product * self.affiliate_program_id.amount/100) + commission_type = 'percentage' + else: + response={ + 'is_error':1, + 'message':'Percenatge amount is greater than 100', + } + else: + # for pps type advance (advance depends upon price list) + + if self.affiliate_program_id.pps_type == 'a' and product_exists:#for pps_type advance + adv_commision_amount,commission,commission_type = self.advance_pps_type_calc() + # adv_commision_amount = is a amount if advance commission + # commission = is a amount which is earned by commisiion + commission = commission * self.product_quantity + _logger.info("----commision_value-%r--------commision_value_type-%r------",commission,commission_type) + _logger.info('================advance_pps_type_calc===============') + if commission and commission_type: + _logger.info("---22----adv_commision_amount--%r--commision_value-%r--------commision_value_type-%r------",adv_commision_amount,commission,commission_type) + + else: + response={ + 'is_error':1, + 'message':'No commission Category Found for this product..' + } + + + else: + response={ + 'is_error':1, + 'message':'pps_type is advance', + } + + else: + response={ + 'is_error':1, + 'message':'Affilite method is niether ppc nor pps or affiliate type is absent(product or category)', + } + else: + + response={ + 'is_error':1, + 'message':'Program is absent in visit', + } + + if commission: + self.commission_amt = commission + # self.amt_type = commission_type + if commission_type == 'fixed' and affiliate_method == 'ppc': + self.amt_type = self.affiliate_program_id.currency_id.symbol+ str(commission) + if commission_type == 'percentage' and affiliate_method == 'ppc': + self.amt_type = str(self.affiliate_program_id.amount_ppc_fixed)+ '%' + #for pps + if commission_type == 'percentage' and self.affiliate_program_id.pps_type == 's': + self.amt_type = str(self.affiliate_program_id.amount) +"%" + if commission_type == 'fixed' and affiliate_method == 'pps' and self.affiliate_program_id.pps_type == 's': + self.amt_type = self.affiliate_program_id.currency_id.symbol + str(commission) + if commission_type == 'fixed' and affiliate_method == 'pps' and self.affiliate_program_id.pps_type == 'a': + self.amt_type = self.affiliate_program_id.currency_id.symbol + str(adv_commision_amount)+" advance" + if commission_type == 'percentage' and affiliate_method == 'pps' and self.affiliate_program_id.pps_type == 'a': + self.amt_type = str(adv_commision_amount)+"%"+" advance" + response={ + 'is_error':0, + 'message':'Commission successfully added', + 'comm_type':commission_type, + 'comm_amt' : commission + } + + else: + if response.get('is_error') == 1: + response={ + 'is_error':1, + 'message':response.get('message'), + } + + return response + + + + def advance_pps_type_calc(self): + adv_commision_amount,commision_value,commision_value_type = self.env["advance.commision"].calc_commision_adv(self.affiliate_program_id.advance_commision_id.id, self.type_id , self.unit_price) + # argument of calc_commision_adv(adv_comm_id, product_id on which commision apply , price of product) + # return adv_commision_amount ,commision_value, commision_value_type + _logger.info("---11----adv_commision_amount----commision_value-%r--------commision_value_type-%r------",adv_commision_amount,commision_value,commision_value_type) + # return commision_value,commision_value_type + return adv_commision_amount,commision_value,commision_value_type + + + + + @api.model + def process_ppc_maturity_scheduler_queue(self): + _logger.info("-----Inside----process_ppc_maturity_scheduler_queue-----------") + check_enable_ppc = self.env['res.config.settings'].sudo().website_constant().get('enable_ppc') + all_ppc_visits = self.search([('affiliate_method','=','ppc'),('state','=','draft')]) + if check_enable_ppc: + for visit in all_ppc_visits: + visit.action_confirm() diff --git a/odex25_donation/affiliate_management/models/odoo_http.py b/odex25_donation/affiliate_management/models/odoo_http.py new file mode 100644 index 000000000..94ae72ec1 --- /dev/null +++ b/odex25_donation/affiliate_management/models/odoo_http.py @@ -0,0 +1,70 @@ +from odoo import http +import logging +from odoo.http import request +_logger = logging.getLogger(__name__) +from odoo.tools.func import lazy_property +from odoo.http import root, db_filter, db_list + +DEFAULT_SESSION = { + 'context': { + #'lang': request.default_lang() # must be set at runtime + }, + 'db': None, + 'debug': '', + 'login': None, + 'uid': None, + 'session_token': None, + # profiling + 'profile_session': None, + 'profile_collectors': None, + 'profile_params': None, +} + + + +def _get_session_and_dbname(self): + + sid = (self.httprequest.args.get('session_id') + or self.httprequest.headers.get("X-Openerp-Session-Id")) + db_from_request = self.httprequest.values.get("db") or self.httprequest.headers.get("db") + if sid: + is_explicit = True + else: + sid = self.httprequest.cookies.get('session_id') + is_explicit = False + + if sid is None: + session = root.session_store.new() + else: + session = root.session_store.get(sid) + session.sid = sid # in case the session was not persisted + session.is_explicit = is_explicit + + + + for key, val in DEFAULT_SESSION.items(): + session.setdefault(key, val) + if not session.context.get('lang'): + session.context['lang'] = self.default_lang() + + dbname = None + host = self.httprequest.environ['HTTP_HOST'] + if session.db and db_filter([session.db], host=host): + dbname = session.db + else: + all_dbs = db_list(force=True, host=host) + if len(all_dbs) == 1: + dbname = all_dbs[0] # monodb + + # if db received in request + if db_from_request and db_filter([db_from_request], host=host): + dbname = db_from_request + if session.db != dbname: + if session.db: + _logger.warning("Logged into database %r, but dbfilter rejects it; logging session out.", session.db) + session.logout(keep_db=False) + session.db = dbname + session.is_dirty = False + return session, dbname + +http.Request._get_session_and_dbname = _get_session_and_dbname diff --git a/odex25_donation/affiliate_management/models/res_partner_inherit.py b/odex25_donation/affiliate_management/models/res_partner_inherit.py new file mode 100644 index 000000000..dd536708f --- /dev/null +++ b/odex25_donation/affiliate_management/models/res_partner_inherit.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError +from odoo import models, fields,api,_ +import random, string +import datetime +class ResPartnerInherit(models.Model): + + _inherit = 'res.partner' + _description = "ResPartner Inherit Model" + + + is_affiliate = fields.Boolean(default=False) + res_affiliate_key = fields.Char(string="Affiliate key") + affiliate_program_id = fields.Many2one("affiliate.program",string="Program") + pending_amt = fields.Float(compute='_compute_pending_amt', string='Pending Amount') + approved_amt = fields.Float(compute='_compute_approved_amt', string='Approved Amount') + + + + + def toggle_active(self): + for o in self: + if o.is_affiliate: + o.is_affiliate = False + else: + o.is_affiliate = True + return super(ResPartnerInherit,self).toggle_active() + + def _compute_pending_amt(self): + for s in self: + visits = s.env['affiliate.visit'].search([('state','=','confirm'),('affiliate_partner_id','=',s.id)]) + amt = 0 + for v in visits: + amt = amt + v.commission_amt + s.pending_amt = amt + + def _compute_approved_amt(self): + for s in self: + visits = s.env['affiliate.visit'].search([('state','=','invoice'),('affiliate_partner_id','=',s.id)]) + amt = 0 + for v in visits: + amt = amt + v.commission_amt + s.approved_amt = amt + + def generate_key(self): + ran = ''.join(random.choice('0123456789ABCDEFGHIJ0123456789KLMNOPQRSTUVWXYZ') for i in range(8)) + self.res_affiliate_key = ran + + + @api.model_create_multi + def create(self,vals_list): + aff_prgm = None + new_res_partner = None + for vals in vals_list: + aff_prgm = self.env['affiliate.program'].search([])[-1].id if len(self.env['affiliate.program'].search([]))>0 else '' + if vals.get('is_affiliate'): + vals.update({ + 'affiliate_program_id':aff_prgm + }) + new_res_partner = super(ResPartnerInherit,self).create(vals) + return new_res_partner diff --git a/odex25_donation/affiliate_management/models/res_user_inherit.py b/odex25_donation/affiliate_management/models/res_user_inherit.py new file mode 100644 index 000000000..bf28275d4 --- /dev/null +++ b/odex25_donation/affiliate_management/models/res_user_inherit.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. (:wink: +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see ; +################################################################################# +import logging +_logger = logging.getLogger(__name__) +from odoo.exceptions import UserError +from odoo import models, fields,api,_ +import random, string +from ast import literal_eval + +class ResUserInherit(models.Model): + + _inherit = 'res.users' + _inherits = {'res.partner': 'partner_id'} + _description = "ResUser Inherit Model" + + res_affiliate_key = fields.Char(related='partner_id.res_affiliate_key',string='Partner Affiliate Key', inherited=True) + diff --git a/odex25_donation/affiliate_management/security/affiliate_security.xml b/odex25_donation/affiliate_management/security/affiliate_security.xml new file mode 100644 index 000000000..086b352a0 --- /dev/null +++ b/odex25_donation/affiliate_management/security/affiliate_security.xml @@ -0,0 +1,101 @@ + + + + + + Affiliate Category + + + + User + + + + + Manager + + + + + + + + + + + Affiliate managemnt Records for User + + + [("id", '=',user.partner_id.id)] + + + + + Affiliate managemnt visits for User + + + [("affiliate_partner_id", '=',user.partner_id.id)] + + + + Affiliate managemnt account invoice for User + + + [("partner_id", '=',user.partner_id.id)] + + + + + Affiliate managemnt Image for User + + + [(1, '=',1)] + + + + + + Affiliate managemnt visits for Manager + + + [(1, '=',1)] + + + + + Affiliate managemnt request for Manager + + + [(1, '=',1)] + + + + + Affiliate managemnt account invoice for Manager + + + [(1, '=',1)] + + + + manager managemnt Records for manager + + + [(1, '=',1)] + + + + + manager advance commision for manager + + + [(1, '=',1)] + + + + + + + + + diff --git a/odex25_donation/affiliate_management/security/ir.model.access.csv b/odex25_donation/affiliate_management/security/ir.model.access.csv new file mode 100644 index 000000000..1da3206b6 --- /dev/null +++ b/odex25_donation/affiliate_management/security/ir.model.access.csv @@ -0,0 +1,44 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink + +affiliate_affiliate_visit_global,global_access_affiliate_visit,model_affiliate_visit,,1,0,0,0 + +affiliate_res_partner_user,user_access_res_partner,model_res_partner,affiliate_security_user_group,1,1,0,0 +affiliate_affiliate_visit_user,user_access_affiliate_visit,model_affiliate_visit,affiliate_security_user_group,1,0,0,0 +affiliate_affiliate_program_user,user_affiliate_program_visit,model_affiliate_program,affiliate_security_user_group,1,0,0,0 +affiliate_affiliate_image_user,user_affiliate_image,model_affiliate_image,affiliate_security_user_group,1,0,0,0 +affiliate_account_invoice_user,user_account_invoice,account.model_account_move,affiliate_security_user_group,1,0,0,0 +affiliate_account_invoice_line_user,user_account_invoice_line,account.model_account_move_line,affiliate_security_user_group,1,0,0,0 +affiliate_account_move_line_user,user_account_move_line,account.model_account_move_line,affiliate_security_user_group,1,0,0,0 +affiliate_account_partial_reconcile_user,user_account_partial_reconcile,account.model_account_partial_reconcile,affiliate_security_user_group,1,0,0,0 +affiliate_account_move_user,user_account_move,account.model_account_move,affiliate_security_user_group,1,0,0,0 +affiliate_sale_order_line_user,user_sale_order_line,sale.model_sale_order_line,affiliate_security_user_group,1,0,0,0 +affiliate_product_product_user,user_product_product,product.model_product_product,affiliate_security_user_group,1,0,0,0 +affiliate_sale_order_user,user_sale_order,sale.model_sale_order,affiliate_security_user_group,1,0,0,0 +affiliate_affiliate_product_pricelist_item_user,user_affiliate_product_pricelist_item_view,model_affiliate_product_pricelist_item,affiliate_security_user_group,0,0,0,0 +affiliate_affiliate_affiliate_tool_user,user_affiliate_tool_view,model_affiliate_tool,affiliate_security_user_group,1,0,0,0 + + + + + + +affiliate_res_partner_manager,manager_access_res_partner,model_res_partner,affiliate_security_manager_group,1,1,0,0 +affiliate_res_users_manager,manager_access_res_users,model_res_users,affiliate_security_manager_group,1,1,0,0 +affiliate_affiliate_visit_manager,manager_access_affiliate_visit,model_affiliate_visit,affiliate_security_manager_group,1,1,1,0 +affiliate_affiliate_program_manager,manager_affiliate_program_visit,model_affiliate_program,affiliate_security_manager_group,1,1,1,1 +affiliate_affiliate_image_manager,manager_affiliate_image,model_affiliate_image,affiliate_security_manager_group,1,1,1,1 +affiliate_affiliate_banner_manager,manager_affiliate_banner_visit,model_affiliate_banner,affiliate_security_manager_group,1,1,1,1 +affiliate_account_invoice_manager,manager_account_invoice,account.model_account_move,affiliate_security_manager_group,1,1,1,1 +affiliate_account_invoice_line_manager,manager_account_invoice_line,account.model_account_move_line,affiliate_security_manager_group,1,1,1,1 +affiliate_account_move_line_manager,manager_account_move_line,account.model_account_move_line,affiliate_security_manager_group,1,1,1,1 +affiliate_sale_order_manager,manager_sale_order,sale.model_sale_order,affiliate_security_manager_group,1,0,0,0 +affiliate_sale_order_line_manager,manager_sale_order_line,sale.model_sale_order_line,affiliate_security_manager_group,1,0,0,0 +affiliate_affiliate_request_manager,manager_access_affiliate_request,model_affiliate_request,affiliate_security_manager_group,1,1,1,1 +affiliate_res_groups_manager,manager_access_res_groups,base.model_res_groups,affiliate_security_manager_group,1,1,1,1 +affiliate_ir_module_category_manager,manager_access_ir_module_category,base.model_ir_module_category,affiliate_security_manager_group,1,1,1,1 +affiliate_ir_ui_view_manager,manager_access_ir_ui_view,base.model_ir_ui_view,affiliate_security_manager_group,1,1,1,1 +affiliate_advance_commision_manager,manager_advance_commision_view,model_advance_commision,affiliate_security_manager_group,1,1,1,1 +affiliate_affiliate_product_pricelist_item_manager,manager_affiliate_product_pricelist_item_view,model_affiliate_product_pricelist_item,affiliate_security_manager_group,1,1,1,1 +affiliate_account_journal_manager,manager_account_journal_view,account.model_account_journal,affiliate_security_manager_group,1,1,1,1 + +affiliate_affiliate_affiliate_tool,manager_access_affiliate_tool,model_affiliate_tool,affiliate_security_manager_group,1,1,1,0 diff --git a/odex25_donation/affiliate_management/static/description/1.png b/odex25_donation/affiliate_management/static/description/1.png new file mode 100644 index 000000000..4c0a8dea7 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/1.png differ diff --git a/odex25_donation/affiliate_management/static/description/10.png b/odex25_donation/affiliate_management/static/description/10.png new file mode 100644 index 000000000..404fda4d6 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/10.png differ diff --git a/odex25_donation/affiliate_management/static/description/11.png b/odex25_donation/affiliate_management/static/description/11.png new file mode 100644 index 000000000..b1276b96e Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/11.png differ diff --git a/odex25_donation/affiliate_management/static/description/12.png b/odex25_donation/affiliate_management/static/description/12.png new file mode 100644 index 000000000..722339131 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/12.png differ diff --git a/odex25_donation/affiliate_management/static/description/13.png b/odex25_donation/affiliate_management/static/description/13.png new file mode 100644 index 000000000..00262adb7 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/13.png differ diff --git a/odex25_donation/affiliate_management/static/description/14.png b/odex25_donation/affiliate_management/static/description/14.png new file mode 100644 index 000000000..0bfa7211e Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/14.png differ diff --git a/odex25_donation/affiliate_management/static/description/15.png b/odex25_donation/affiliate_management/static/description/15.png new file mode 100644 index 000000000..9b50bed5b Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/15.png differ diff --git a/odex25_donation/affiliate_management/static/description/16.png b/odex25_donation/affiliate_management/static/description/16.png new file mode 100644 index 000000000..688d95f3d Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/16.png differ diff --git a/odex25_donation/affiliate_management/static/description/17.png b/odex25_donation/affiliate_management/static/description/17.png new file mode 100644 index 000000000..c55e96907 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/17.png differ diff --git a/odex25_donation/affiliate_management/static/description/18.png b/odex25_donation/affiliate_management/static/description/18.png new file mode 100644 index 000000000..385264f8f Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/18.png differ diff --git a/odex25_donation/affiliate_management/static/description/2.png b/odex25_donation/affiliate_management/static/description/2.png new file mode 100644 index 000000000..fa1defa86 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/2.png differ diff --git a/odex25_donation/affiliate_management/static/description/3.png b/odex25_donation/affiliate_management/static/description/3.png new file mode 100644 index 000000000..3db6368d3 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/3.png differ diff --git a/odex25_donation/affiliate_management/static/description/4.png b/odex25_donation/affiliate_management/static/description/4.png new file mode 100644 index 000000000..0b1beac6e Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/4.png differ diff --git a/odex25_donation/affiliate_management/static/description/5.png b/odex25_donation/affiliate_management/static/description/5.png new file mode 100644 index 000000000..40ea095e4 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/5.png differ diff --git a/odex25_donation/affiliate_management/static/description/6.png b/odex25_donation/affiliate_management/static/description/6.png new file mode 100644 index 000000000..27508e76c Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/6.png differ diff --git a/odex25_donation/affiliate_management/static/description/7.png b/odex25_donation/affiliate_management/static/description/7.png new file mode 100644 index 000000000..e935c53b7 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/7.png differ diff --git a/odex25_donation/affiliate_management/static/description/8.png b/odex25_donation/affiliate_management/static/description/8.png new file mode 100644 index 000000000..ab8b4bc66 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/8.png differ diff --git a/odex25_donation/affiliate_management/static/description/9.png b/odex25_donation/affiliate_management/static/description/9.png new file mode 100644 index 000000000..1d86b1f79 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/9.png differ diff --git a/odex25_donation/affiliate_management/static/description/OldBanner.png b/odex25_donation/affiliate_management/static/description/OldBanner.png new file mode 100644 index 000000000..2ca730b79 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/OldBanner.png differ diff --git a/odex25_donation/affiliate_management/static/description/banner.gif b/odex25_donation/affiliate_management/static/description/banner.gif new file mode 100644 index 000000000..8940ce4e7 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/banner.gif differ diff --git a/odex25_donation/affiliate_management/static/description/icon-1.png b/odex25_donation/affiliate_management/static/description/icon-1.png new file mode 100644 index 000000000..1ab000c88 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/icon-1.png differ diff --git a/odex25_donation/affiliate_management/static/description/icon-2.png b/odex25_donation/affiliate_management/static/description/icon-2.png new file mode 100644 index 000000000..97358f82f Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/icon-2.png differ diff --git a/odex25_donation/affiliate_management/static/description/icon-features.png b/odex25_donation/affiliate_management/static/description/icon-features.png new file mode 100644 index 000000000..10e23486e Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/icon-features.png differ diff --git a/odex25_donation/affiliate_management/static/description/icon-help.png b/odex25_donation/affiliate_management/static/description/icon-help.png new file mode 100644 index 000000000..303f9e248 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/icon-help.png differ diff --git a/odex25_donation/affiliate_management/static/description/icon-support.png b/odex25_donation/affiliate_management/static/description/icon-support.png new file mode 100644 index 000000000..5f9759099 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/icon-support.png differ diff --git a/odex25_donation/affiliate_management/static/description/icon-user-guide.png b/odex25_donation/affiliate_management/static/description/icon-user-guide.png new file mode 100644 index 000000000..63ffb7526 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/icon-user-guide.png differ diff --git a/odex25_donation/affiliate_management/static/description/icon.png b/odex25_donation/affiliate_management/static/description/icon.png new file mode 100644 index 000000000..944f1b30c Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/icon.png differ diff --git a/odex25_donation/affiliate_management/static/description/illustration-1.png b/odex25_donation/affiliate_management/static/description/illustration-1.png new file mode 100644 index 000000000..e2a600c22 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/illustration-1.png differ diff --git a/odex25_donation/affiliate_management/static/description/index.html b/odex25_donation/affiliate_management/static/description/index.html new file mode 100644 index 000000000..cf0fe76da --- /dev/null +++ b/odex25_donation/affiliate_management/static/description/index.html @@ -0,0 +1,745 @@ +
+

Odoo Affiliate Management

+
+

Hassle-free way to manage the marketing tags for your Odoo Website! +

+ +
+ + +
+ Odoo Affiliate Management Module facilitates you to create and manage an Affiliate Program in Odoo. The interested candidates can signup from the website and you can manage the process from the back-end. +
+ +
+
Information
+ user-guide + User Guide +

https://webkul.com/blog/odoo-affiliate-management

+
+ +
+
+
Affiliate Management in Odoo for marketing on another level!
+
+
+
+

Marketing is a part for any business that no one can ignore; as it is important for the better of products to the customers. There are various techniques for the marketing of any kind of business but what matters the most is using the apt one at the right time. +

+

Talking about the apt marketing strategy, affiliate management cannot go unnoticed. Coming to the facts, 81% of brands and 84% of publishers leverage the power of affiliate marketing, reported by big-commerce. Affiliate marketing is a type of performance-based marketing in which you can reward one or more affiliates for each visitor or customer brought by the affiliate's own marketing efforts. +

+

Now, you can manage affiliates in Odoo without any hassle. Odoo Affiliate Management facilitates you to create and manage an Affiliate Program in Odoo. The interested candidates can signup from the website and you can manage the process from the back-end. +

+
+
+ + +
+
+
+
+
Affiliate Management for tremendous Business Growth
+
+
+
+

When you associate affiliates with your business then all different minds put their complete efforts to sell your products with their set of creativity. +

+

Moreover, the rewards offered for the sale also motivates the affiliate to bring the maximum customers to you which is a great step for the growth of your business. +

+

Choose and work with the affiliates that relate to the theme of your website. Harness the power of recommendation to your advantage.and focus the efforts on target marketing rather than general paid advertisement.

+ +
+ +
+ +
+
+
+ +
+
+
Hassle-free way for Affiliate Management in Odoo
+
+
+
+

Odoo Affiliate Management allows you to create and manage an Affiliate Program in Odoo. The interested candidates can sign up directly from the website and you can manage the process from the Odoo back-end. +

+

You can easily build your own affiliate marketing team and promote your products on your affiliates' websites. +

+

You can approve/reject affiliate requests and track the activity of your affiliate link for all your affiliates in the backend. Moreover, you can also define threshold balance in affiliate accounts for payout. +

+
+
+
+

Detailed Features List +

+
+

Below is the detailed list of Feature for Affiliate Management +

+
+
+
+
+ Easy way to manage Affiliates in Odoo +
+
+
    +
  • +

    It helps to create an Affiliate Program for your website in Odoo

    +
  • +
    +
  • +

    Manage the entire affiliate Program using Odoo from the back-end +

    +
  • +
+
+
+
+
+
+
Full Admin control for Affiliate Program in Odoo +
+
+
    +
  • +

    As an admin, you can approve/reject the affiliate request from the backend +

    +
  • +
  • +

    You can enable/disable Pay Per Click (PPC) affiliate program using Odoo. +

  • +

    Maturity time for a PPC can be set by the admin. +

    +
  • + +
+
+
+
+ + +
+
+
+ Manage the Reports in Real-time +
+
+
    +
  • +

    The order report is generated for every Pay Per Sale (PPS) event on each affiliate's webpage. +

    +
  • +
    +
  • +

    The event Report is generated for every Pay Per Click (PPC) event on each affiliate's webpage. +

    +
  • +
+
+
+
+
+
+
Manage the Commision as per your Requirement +
+
+
    +
  • +

    Set your threshold amount in commission calculation. +

    +
  • +
  • +

    Commissions can be set on the basis of fixed or percentage paid. +

    + +
  • + +
+
+
+
+ +
+
+
+ Set The Background for Welcome page +
+
+
    +
  • +

    Define/Update welcome page Banner and Title. +

    +
  • +
    +
  • +

    Define/Update Email Text sent to the user for registration, welcome and cancel the request. +

    +
  • +
+
+
+
+
+
+
Send Welcome Notification to the Affiliates +
+
+
    +
  • +

    Set your threshold amount in commission calculation. +

    +
  • +
  • +

    The admin can edit and send emails to new affiliates like welcome mail or request cancellation mail. + +

    + +
  • + +
+
+
+
+ + + +
+ +
+
+ +

+
+ +

Enter your mail id as shown to become an affiliate

+
+ +
+ + + +
+
+
+

View the affiliate requests from the backend

+
+
+ + + +
+
+
+ +

Tick the checkbox to enable the affiliate option

+
+ +
+ + + +
+
+
+ +

Select the affiliate tool to generate the link

+
+ +
+ + + +
+
+
+ +

Affiliate link generator

+
+ +
+ + + +
+
+
+ + +

Generate Product link: Choose Product

+
+ +
+ + + +
+
+
+ +

Generate Product link: Choose Image

+
+ +
+ + + +
+
+
+ + + +

Generate Product link: Copy generated code

+
+ +
+ + + +
+
+
+ + +

View you order earnings from here

+
+ +
+ + + +
+
+
+ + +

View your traffic earnings as shown

+
+ +
+ + + +
+
+
+ + +

View the order reports from the backend

+
+ + +
+ + + +
+ +
+

View the traffic report fromt the backend

+
+
+ + + +
+
+ +
+ +

View the invoices from the backend

+
+ +
+ + + +
+
+
+ + + +

View the affiliate images from the Odoo backend

+
+ +
+ + + +
+
+
+ +

Manage the affiliate configuration from the Odoo backend

+
+ +
+ + + +
+
+
+ + + +

Manage the payment configuration from the Odoo backend

+
+ +
+ + + +
+
+
+ + +

Set the rate for PPC and PPS as shown

+
+ +
+ + + +
+
+
+ + +

Set the advance comission

+
+ +
+ + + +
+
+
+
+ +

+
+ +
+ +
+
+
+

Help and Support

+

Get Immediate support for any of your query

+
+
+

You will get 90 days free support for any doubt, queries, and bug fixing (excluding data recovery) or any type of issue related to this module.

+
+
+
+
+ mail +
+
+

Write a mail to us:

+ support@webkul.com +

Any queries or want any extra features? Just drop a mail to our support.

+
+ +
+
+
+
+
+ support-icon +
+
+

Get in touch with our Expert:

+ https://webkul.uvdesk.com/en/customer/create-ticket/ +

Any technical queries, want extra features, or anything else, our team is ready to answer all your questions, just raise a support ticket.

+
+
+
+
+
diff --git a/odex25_donation/affiliate_management/static/description/signupform.png b/odex25_donation/affiliate_management/static/description/signupform.png new file mode 100644 index 000000000..7afbfaca4 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/signupform.png differ diff --git a/odex25_donation/affiliate_management/static/description/testimonial_banner.png b/odex25_donation/affiliate_management/static/description/testimonial_banner.png new file mode 100644 index 000000000..d616bc3c7 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/testimonial_banner.png differ diff --git a/odex25_donation/affiliate_management/static/description/testimonial_icon.png b/odex25_donation/affiliate_management/static/description/testimonial_icon.png new file mode 100644 index 000000000..da69e7b72 Binary files /dev/null and b/odex25_donation/affiliate_management/static/description/testimonial_icon.png differ diff --git a/odex25_donation/affiliate_management/static/loader/images/ajax-loader.gif b/odex25_donation/affiliate_management/static/loader/images/ajax-loader.gif new file mode 100644 index 000000000..6ac4ca8b2 Binary files /dev/null and b/odex25_donation/affiliate_management/static/loader/images/ajax-loader.gif differ diff --git a/odex25_donation/affiliate_management/static/loader/jquery.loader.css b/odex25_donation/affiliate_management/static/loader/jquery.loader.css new file mode 100644 index 000000000..38aa62912 --- /dev/null +++ b/odex25_donation/affiliate_management/static/loader/jquery.loader.css @@ -0,0 +1,27 @@ +@CHARSET "UTF-8"; +#jquery-loader{ + border:2px black solid; + padding-top:35px; + background-color: white; + text-align: center; +} +#jquery-loader-background{background-color: silver} +#jquery-loader.blue-with-image{ + border:2px #008587 solid; + padding-top:35px; + background-color: white; + text-align: center; + background-image: url(images/ajax-loader.gif); + background-position: center center; + background-repeat: no-repeat; +} +#jquery-loader.blue-with-image-2{ + border:none; + padding-top:35px; + background-color: transparent; + text-align: center; + background-image: url(images/ajax-loader.gif); + background-position: center center; + background-repeat: no-repeat; + +} \ No newline at end of file diff --git a/odex25_donation/affiliate_management/static/loader/jquery.loader.js b/odex25_donation/affiliate_management/static/loader/jquery.loader.js new file mode 100644 index 000000000..3932c6908 --- /dev/null +++ b/odex25_donation/affiliate_management/static/loader/jquery.loader.js @@ -0,0 +1,94 @@ +/* + * jQuery Loader Plugin + * @version: 2.0.0 + * @requires jQuery v1.2.2 or later + * @author : ${author} + * @see : ${demoURL} + * Small loader + * usage : $.loader(); + * $.loader(options) -> options = + * { + * + * } + * + * To close loader : $.loader("close"); + * + */ +var jQueryLoaderOptions = null; +(function($) { + $.loader = function(option){ + switch(option) + { + case 'close': + if(jQueryLoaderOptions){ + if($("#"+jQueryLoaderOptions.id)){ + $("#"+jQueryLoaderOptions.id +", #"+jQueryLoaderOptions.background.id).remove(); + } + } + return; + case 'setContent': + if(jQueryLoaderOptions){ + if($("#"+jQueryLoaderOptions.id)){ + if(arguments.length == 2) + { + $("#"+jQueryLoaderOptions.id).html(arguments[1]); + }else{ + if(console){ + console.error("setContent method must have 2 arguments $.loader('setContent', 'new content');"); + }else{ + alert("setContent method must have 2 arguments $.loader('setContent', 'new content');"); + } + } + } + } + return; + default: + var options = $.extend({ + content:"Loading ...", + className:'loader', + id:'jquery-loader', + height:60, + width:200, + zIndex:30000, + background:{ + opacity:0.4, + id:'jquery-loader-background' + } + }, option); + } + jQueryLoaderOptions = options; + var maskHeight = $(document).height(); + var maskWidth = $(window).width(); + var bgDiv = $('
'); + bgDiv.css({ + zIndex:options.zIndex, + position:'absolute', + top:'0px', + left:'0px', + width:maskWidth, + height:maskHeight, + opacity:options.background.opacity + }); + + bgDiv.appendTo("body"); + if(jQuery.bgiframe){ + bgDiv.bgiframe(); + } + var div = $('
'); + div.css({ + zIndex:options.zIndex+1, + width:options.width, + height:options.height + }); + div.appendTo('body'); + div.center(); + div.html(options.content); + //$(options.content).appendTo(div); + }; + $.fn.center = function () { + this.css("position","absolute"); + this.css("top", ( $(window).height() - this.outerHeight() ) / 2+$(window).scrollTop() + "px"); + this.css("left", ( $(window).width() - this.outerWidth() ) / 2+$(window).scrollLeft() + "px"); + return this; + }; +})(jQuery); \ No newline at end of file diff --git a/odex25_donation/affiliate_management/static/src/css/website_affiliate.css b/odex25_donation/affiliate_management/static/src/css/website_affiliate.css new file mode 100644 index 000000000..ea030c741 --- /dev/null +++ b/odex25_donation/affiliate_management/static/src/css/website_affiliate.css @@ -0,0 +1,153 @@ +.affiliate_loader { + position: fixed; + left: 0px; + top: 0px; + width: 100%; + height: 100%; + z-index: 9999; + background: url(/affiliate_management/static/src/img/affiliateLoder.gif) center no-repeat rgba(255, 255, 255, 0.5); + text-shadow: 0 1px 1px white; +} + +.form_container { + border: solid grey 6px; +} + +.inp_style { + border: 2px solid #3aadaa; + border-radius: 22px; +} + +.cpy_cde { + border-radius: 22px; +} + +.cpy_url { + border-radius: 22px; +} + +.img_banner { + position: absolute; + top: 0px; + height: 100%; + width: 100%; +} + +.banner_text { + text-align: center; + font-style: normal; + font-family: arial; + color: white; + font-size: 50px; +} +/* +.affiliate_banner{ + background-image: url("/affiliate_management/static/src/img/cover-banner.jpg"), +} +.banner_detail { + position: absolute; + top: 100px; + width: 100%; + height: 100%; + +}*/ +.aff_box{ + text-align: center; + /*padding:20px;*/ +} +.img_container { + border: solid; + position: absolute; + top: 50%; + width: 60%; + height: 46%; + left: 25%; +} + +span.step { + background: #cccccc; + border-radius: 0.8em; + -moz-border-radius: 0.8em; + -webkit-border-radius: 0.8em; + color: #ffffff; + display: inline-block; + font-weight: bold; + line-height: 1.6em; + margin-right: 5px; + text-align: center; + width: 1.6em; +} + +span.step1 { + background: green; + border-radius: 0.8em; + -moz-border-radius: 0.8em; + -webkit-border-radius: 0.8em; + color: #ffffff; + display: inline-block; + font-weight: bold; + line-height: 1.6em; + margin-right: 5px; + text-align: center; + width: 1.6em; +} +a { + text-decoration: none !important; +} + +.button_image_generate_url{ + width: 508px; + height: 284px; + display: inline; + position: relative; + top: 3%; + left: 10%; +} + +.alert_msg_banner{ + background: rgba(0, 0, 0, 0.5); + width: 44%; + height: 16%; + padding: 1%; + position: relative; + left: 30%; + display: none; + top:6%; +} +.alert_msg_banner_1{ + background: rgba(0, 0, 0, 0.5); + width: 70%; + height: 20%; + padding: 1%; + position: relative; + left: 15%; + top: 6%; +} +.alert_msg_banner_signup{ + background: rgba(0, 0, 0, 0.5); + width: 70%; + height: 18%; + padding: 1%; + position: relative; + left: 15%; + /*display: none;*/ + top:6%; +} +.card_large_product{ + position:relative !important; + bottom:80px !important; +} +#wrapwrap +{ + border : none !important; + +} + +@media screen and (max-width: 574px) { + .cpy_cde { + margin-top: 36px; + } + .cpy_url { + margin-left: 50px; + } +} \ No newline at end of file diff --git a/odex25_donation/affiliate_management/static/src/img/Icon_tick.png b/odex25_donation/affiliate_management/static/src/img/Icon_tick.png new file mode 100644 index 000000000..3e90e119b Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/Icon_tick.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/affiliateLoder.gif b/odex25_donation/affiliate_management/static/src/img/affiliateLoder.gif new file mode 100644 index 000000000..9f3dd9966 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/affiliateLoder.gif differ diff --git a/odex25_donation/affiliate_management/static/src/img/alert.png b/odex25_donation/affiliate_management/static/src/img/alert.png new file mode 100644 index 000000000..a103ce3b7 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/alert.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/ban1.png b/odex25_donation/affiliate_management/static/src/img/ban1.png new file mode 100644 index 000000000..833e6d155 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/ban1.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/ban2.png b/odex25_donation/affiliate_management/static/src/img/ban2.png new file mode 100644 index 000000000..ac1ef26b2 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/ban2.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/ban3.png b/odex25_donation/affiliate_management/static/src/img/ban3.png new file mode 100644 index 000000000..1bedd06ca Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/ban3.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/but1.png b/odex25_donation/affiliate_management/static/src/img/but1.png new file mode 100644 index 000000000..a31647a57 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/but1.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/but2.png b/odex25_donation/affiliate_management/static/src/img/but2.png new file mode 100644 index 000000000..165c748fe Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/but2.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/but3.png b/odex25_donation/affiliate_management/static/src/img/but3.png new file mode 100644 index 000000000..80b34b3d1 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/but3.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/cover-banner.jpg b/odex25_donation/affiliate_management/static/src/img/cover-banner.jpg new file mode 100644 index 000000000..b39a07249 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/cover-banner.jpg differ diff --git a/odex25_donation/affiliate_management/static/src/img/error.png b/odex25_donation/affiliate_management/static/src/img/error.png new file mode 100644 index 000000000..88e347080 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/error.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/icon-affiliate-tools.svg b/odex25_donation/affiliate_management/static/src/img/icon-affiliate-tools.svg new file mode 100644 index 000000000..d5d6ff1d6 --- /dev/null +++ b/odex25_donation/affiliate_management/static/src/img/icon-affiliate-tools.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/affiliate_management/static/src/img/icon-check.png b/odex25_donation/affiliate_management/static/src/img/icon-check.png new file mode 100644 index 000000000..d559e1137 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/icon-check.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/icon-check.svg b/odex25_donation/affiliate_management/static/src/img/icon-check.svg new file mode 100644 index 000000000..0241d428f --- /dev/null +++ b/odex25_donation/affiliate_management/static/src/img/icon-check.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/affiliate_management/static/src/img/icon-stats-management.svg b/odex25_donation/affiliate_management/static/src/img/icon-stats-management.svg new file mode 100644 index 000000000..a5e7562e6 --- /dev/null +++ b/odex25_donation/affiliate_management/static/src/img/icon-stats-management.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/affiliate_management/static/src/img/res_partner_1-image.png b/odex25_donation/affiliate_management/static/src/img/res_partner_1-image.png new file mode 100644 index 000000000..a7ae12723 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/res_partner_1-image.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/res_partner_2-image.png b/odex25_donation/affiliate_management/static/src/img/res_partner_2-image.png new file mode 100644 index 000000000..4c3f0eb0c Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/res_partner_2-image.png differ diff --git a/odex25_donation/affiliate_management/static/src/img/res_partner_3-image.jpeg b/odex25_donation/affiliate_management/static/src/img/res_partner_3-image.jpeg new file mode 100644 index 000000000..3f5f991e7 Binary files /dev/null and b/odex25_donation/affiliate_management/static/src/img/res_partner_3-image.jpeg differ diff --git a/odex25_donation/affiliate_management/static/src/js/validation.js b/odex25_donation/affiliate_management/static/src/js/validation.js new file mode 100644 index 000000000..469ac3cc1 --- /dev/null +++ b/odex25_donation/affiliate_management/static/src/js/validation.js @@ -0,0 +1,261 @@ +odoo.define('affiliate_management.validation',function(require){ +"use strict"; + +var core = require('web.core'); +var ajax = require('web.ajax'); + +var _t = core._t; + + // js for choose button in step 2 of generate product url + +// term_condition + + + + + + + + + + +$(document).ready(function() { + $('.signup-btn').on('click',function(){ + var c = $('#tc-signup-checkbox').is(':checked'); + console.log(c); + if (c == false) + { + + $('#term_condition_error').show(); + return false; + } + }); + + + + $( ".button_image_generate_url" ).hide(); + $('.o_form_radio').on('click',function(){ + $('[id^=product-text_]').hide(); + console.log(this.getAttribute('id').split("_")[1]) + var radio_id = this.getAttribute('id').split("_")[1]; + $( ".button_image_generate_url" ).hide(); + $('#image_'+radio_id).show(); + + }); + $('.o_form_radio_product').on('click',function(){ + $( ".button_image_generate_url" ).hide(); + var product_text_id =$("#product-text_"+this.id.split("_")[1]); + $(product_text_id).show(); + $( ".product_image" ).show(); + }); + + +// copy the text from clipboard + var copyBtn + var input + + $('[id^=copy-btn_]').on('click',function(){ + console.log("start") + copyBtn = this; + input = $("#copy-me_"+this.id.split("_")[1]); + console.log("input",input) + copyToClipboard(); + $('[id^=copy-btn_]').text('Copy to Clipboard') + $(this).text('copied'); + console.log("copy button clicked") + }); + + function copyToClipboardFF(text) { + window.prompt ("Copy to clipboard: Ctrl C, Enter", text); + } + + function copyToClipboard() { + var success = true, + range = document.createRange(), + selection; + + // For IE. + if (window.clipboardData) { + console.log("clipboard") + window.clipboardData.setData("Text", input.val()); + } else { + // Create a temporary element off screen. + var tmpElem = $('
'); + tmpElem.css({ + position: "absolute", + left: "-1000px", + top: "-1000px", + }); + // Add the input value to the temp element. + tmpElem.text(input.val()); + console.log("tmpElem",tmpElem) + $("body").append(tmpElem); + // Select temp element. + range.selectNodeContents(tmpElem.get(0)); + console.log("range",range) + selection = window.getSelection (); + selection.removeAllRanges (); + console.log("remove range") + selection.addRange (range); + // Lets copy. + try { + success = document.execCommand ("copy", false, null); + } + catch (e) { + copyToClipboardFF(input.val()); + } + if (success) { + // alert ("The text is on the clipboard, try to paste it!"); + // remove temp element. + tmpElem.remove(); + } + } +} + + +// copy link for affiliate link generator +$("#link_copy_button").click(function(){ + + // Code to change the text of copy button to copied and again change it to copy + $(this).text('Copied'); + setTimeout(function() { + $("#link_copy_button").text('Copy'); + }, 2000); + $("#copy_link").show(); + $("#copy_link").select(); + document.execCommand('copy'); + $("#copy_link").hide(); +}); +// copy html code from text area +var clicked = false; +$("#banner_copy_button").click(function(){ + $("#banner_html_code").select(); + document.execCommand('copy'); + $(this).text('Copied'); + setTimeout(function() { + $("#banner_copy_button").text('Copy'); + $("#banner_html_code").blur(); + }, 2000); + if (clicked == false) + { + $('#step3').hide(); + $('#step3').after( + "" + ); + clicked = true; + } +}); + +$("#later_button").click(function(){ + $("#aff_req_btn").hide(); +}); + + + + +$('[id^=yes_btn_uid_]').on('click',function(){ + var uid = this.id.split("_")[3]; + ajax.jsonRpc("/affiliate/request", 'call',{'user_id': uid}).then(function (result){ + console.log(result); + if (result) + { + // $("#aff_req_btn").replaceWith( "

Your Request has been submitted sucessfully. Soon you will be notify by email.

"); + $("#aff_req_btn").hide(); + $(".alert_msg_banner").show(); + + } + else{ + + } + }); + }); + +function isValidEmailAddress(emailAddress) { + // var pattern = /^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i; + var pattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$/i; + return pattern.test(emailAddress); +}; + + $("#join-btn").click(function(){ + var email = $('#register_login').val(); + if (isValidEmailAddress(email)){ + $('.affiliate_loader').show(); + ajax.jsonRpc("/affiliate/join", 'call',{'email': email}).then(function (result){ + if (result){ + console.log(result); + $(".aff_box").replaceWith( + "\ +
\ +
\ +
\ + Continue Shopping\ +
\ +
"); + } + }); + $('.affiliate_loader').hide(); + return false; + }else{ + console.log("wrong email"); + alert("Invalid Email type"); + return false; + } + + }); + + + $("#cpy_cde").click(function() { + $("#usr_aff_code").select(); + $(this).text('copied'); + setTimeout(function() { + $("#cpy_cde").text('copy'); + }, 2000); + document.execCommand('copy'); + return false; + }); + + $("#cpy_url").click(function() { + $("#usr_aff_url").select(); + $(this).text('copied') + setTimeout(function() { + $("#cpy_url").text('copy'); + }, 2000); + document.execCommand('copy'); + return false; + }); + + + $("#url_anchor").click(function(){ + $("#affiliate_url_inp").show(); + $("#affiliate_code_inp").hide(); + return false; + }); + + + $("#code_anchor").click(function(){ + $("#affiliate_url_inp").hide(); + $("#affiliate_code_inp").show(); + return false; + }); + + if ($(window).width() < 570) { + $('#cpy_url').removeClass('ms-2'); + $('.report_amount').removeClass('mt-5'); + $('.report_amount').removeClass('ms-2'); + $('.report_amount').addClass('ms-4'); + } else { + $('#cpy_url').addClass('ms-2'); + $('.report_amount').addClass('mt-5'); + $('.report_amount').removeClass('ms-4'); + $('.report_amount').addClass('ms-2'); + } + +}); + +}); diff --git a/odex25_donation/affiliate_management/views/about_template.xml b/odex25_donation/affiliate_management/views/about_template.xml new file mode 100644 index 000000000..2c809fc12 --- /dev/null +++ b/odex25_donation/affiliate_management/views/about_template.xml @@ -0,0 +1,186 @@ + + + + + + diff --git a/odex25_donation/affiliate_management/views/account_invoice_inherit.xml b/odex25_donation/affiliate_management/views/account_invoice_inherit.xml new file mode 100644 index 000000000..3c3466de2 --- /dev/null +++ b/odex25_donation/affiliate_management/views/account_invoice_inherit.xml @@ -0,0 +1,38 @@ + + + + + + account.move.inherit.supplier.form + account.move + + + + + + + + + + + + + + + Affiliate Invoices + account.move + tree,kanban,form + + + [('move_type', '=', 'in_invoice'), ('aff_visit_id', '!=', False)] + {'default_move_type': 'in_invoice'} + +

+ Create an affiliate invoice +

+ Create invoices, register payments and keep track of the discussions with your affiliates. +

+
+
+
+
diff --git a/odex25_donation/affiliate_management/views/advance_commision_view.xml b/odex25_donation/affiliate_management/views/advance_commision_view.xml new file mode 100644 index 000000000..3672ae63b --- /dev/null +++ b/odex25_donation/affiliate_management/views/advance_commision_view.xml @@ -0,0 +1,77 @@ + + + + advance.commission.form + advance.commision + +
+ + +
+ + +
+ + + +

+ +

+ + + +
+ + + + + + + + + + + + + + + + +
+
+
+
+ + + advance.commission.tree + advance.commision + + + + + + + + + + + + Affiliate Advance Commission + advance.commision + tree,form + + + + +
+
diff --git a/odex25_donation/affiliate_management/views/affiliate_banner_view.xml b/odex25_donation/affiliate_management/views/affiliate_banner_view.xml new file mode 100644 index 000000000..24860dbed --- /dev/null +++ b/odex25_donation/affiliate_management/views/affiliate_banner_view.xml @@ -0,0 +1,34 @@ + + + + affiliate banner form + affiliate.banner + +
+ + + + + + + + + + + + + +
+
+
+ + +
+
diff --git a/odex25_donation/affiliate_management/views/affiliate_config_setting_view.xml b/odex25_donation/affiliate_management/views/affiliate_config_setting_view.xml new file mode 100644 index 000000000..1e24fdc31 --- /dev/null +++ b/odex25_donation/affiliate_management/views/affiliate_config_setting_view.xml @@ -0,0 +1,270 @@ + + + + res.config.view + res.config.settings + + + +
+

Affiliate Management Configuration

+
+
+
+ +
+ Configure your Affiliate Program data +
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+
+ + + + +
+
+ +
+
+
+
+ +
+
+
+
+ + +
+

Payment Configuration

+
+
+
+
+
+
+
+
+
+ +
+

Website Configuration

+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+

Email Configuration

+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+ + + +
+ +
+ +
+
+ + + Settings + ir.actions.act_window + res.config.settings + form + + inline + {'module' : 'affiliate_management'} + + + + +
diff --git a/odex25_donation/affiliate_management/views/affiliate_image_view.xml b/odex25_donation/affiliate_management/views/affiliate_image_view.xml new file mode 100644 index 000000000..ba7965146 --- /dev/null +++ b/odex25_donation/affiliate_management/views/affiliate_image_view.xml @@ -0,0 +1,70 @@ + + + + affiliate.image.form + affiliate.image + +
+ +
+ +
+ + + +

+ +

+
+
+ + + + + + + + + + + + +
+
+
+
+ + + affiliate.image.tree + affiliate.image + + + + + + + + + + + + + Affiliate Image + affiliate.image + tree,form + + + + +
+
diff --git a/odex25_donation/affiliate_management/views/affiliate_manager_view.xml b/odex25_donation/affiliate_management/views/affiliate_manager_view.xml new file mode 100644 index 000000000..b46c2e48e --- /dev/null +++ b/odex25_donation/affiliate_management/views/affiliate_manager_view.xml @@ -0,0 +1,298 @@ + + + + + + + Visits + affiliate.visit + + tree,form + [('affiliate_partner_id','=', active_id)] + +

+ +

+
+
+ + + + + res.partner.form + res.partner + + +
+ +
+
+ +
+ + + +

+ +

+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+ + Refresh token set +
+
+ + No refresh token set +
+
+
+
+ +
+
+ +
+
+
+
+ + Refresh token set +
+
+ + No refresh token set +
+
+
+
+ +
+
+ +
+
+ + + + + + + + + + +
+ + + + +
+
+ + + + + + diff --git a/odex25_donation/dbfilter_from_header/README.rst b/odex25_donation/dbfilter_from_header/README.rst new file mode 100644 index 000000000..0570c42b8 --- /dev/null +++ b/odex25_donation/dbfilter_from_header/README.rst @@ -0,0 +1,124 @@ +==================== +dbfilter_from_header +==================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/16.0/dbfilter_from_header + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-16-0/server-tools-16-0-dbfilter_from_header + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/149/16.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This addon lets you pass a dbfilter as a HTTP header. + +This is interesting for setups where database names can't be mapped to proxied host names. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +To install this module, you only need to add it to your addons, and load it as +a server-wide module. + +This can be done with the ``server_wide_modules`` parameter in ``/etc/odoo.conf`` +or with the ``--load`` command-line parameter + +``server_wide_modules = base,web,dbfilter_from_header`` + +Configuration +============= + +Please keep in mind that the standard odoo dbfilter configuration is still +applied before looking at the regular expression in the header. + +* For nginx, use: + + ``proxy_set_header X-Odoo-dbfilter [your filter regex];`` + +* For caddy, use: + + ``proxy_header X-Odoo-dbfilter [your filter regex]`` + +* For Apache, use: + + ``RequestHeader set X-Odoo-dbfilter [your filter regex]`` + +And make sure that proxy mode is enabled in Odoo's configuration file: + +``proxy_mode = True`` + +Usage +===== + +To use this module, you need to complete installation and configuration +parts. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Therp BV + +Contributors +~~~~~~~~~~~~ + +* Stéphane Bidoul +* Yannick Vaucher +* Alexandre Fayolle +* Holger Brunn +* Laurent Mignon (aka lmi) +* Sandy Carter +* Fabio Vilchez +* Jos De Graeve +* Lai Tim Siu (Quaritle Limited) +* Tharathip Chaweewongphan +* Eric Antones + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/odex25_donation/dbfilter_from_header/__init__.py b/odex25_donation/dbfilter_from_header/__init__.py new file mode 100644 index 000000000..3b8cc81fa --- /dev/null +++ b/odex25_donation/dbfilter_from_header/__init__.py @@ -0,0 +1 @@ +from . import override diff --git a/odex25_donation/dbfilter_from_header/__manifest__.py b/odex25_donation/dbfilter_from_header/__manifest__.py new file mode 100644 index 000000000..72cc9b4c6 --- /dev/null +++ b/odex25_donation/dbfilter_from_header/__manifest__.py @@ -0,0 +1,17 @@ +# © 2013 Therp BV +# © 2014 ACSONE SA/NV +# Copyright 2018 Quartile Limited +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "dbfilter_from_header", + "summary": "Filter databases with HTTP headers", + "version": "16.0.1.0.0", + "website": "https://github.com/OCA/server-tools", + "author": "Therp BV, Odoo Community Association (OCA)", + "license": "AGPL-3", + "category": "Tools", + "depends": ["web"], + "auto_install": False, + "installable": True, +} diff --git a/odex25_donation/dbfilter_from_header/i18n/es_AR.po b/odex25_donation/dbfilter_from_header/i18n/es_AR.po new file mode 100644 index 000000000..e69de29bb diff --git a/odex25_donation/dbfilter_from_header/i18n/zh_CN.po b/odex25_donation/dbfilter_from_header/i18n/zh_CN.po new file mode 100644 index 000000000..e69de29bb diff --git a/odex25_donation/dbfilter_from_header/override.py b/odex25_donation/dbfilter_from_header/override.py new file mode 100644 index 000000000..f759575b1 --- /dev/null +++ b/odex25_donation/dbfilter_from_header/override.py @@ -0,0 +1,29 @@ +# © 2013 Therp BV +# © 2014 ACSONE SA/NV +# Copyright 2018 Quartile Limited +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +import re + +from odoo import http +from odoo.tools import config + +db_filter_org = http.db_filter + + +def db_filter(dbs, host=None): + dbs = db_filter_org(dbs, host) + httprequest = http.request.httprequest + db_filter_hdr = httprequest.environ.get("HTTP_X_ODOO_DBFILTER") + if db_filter_hdr: + dbs = [db for db in dbs if re.match(db_filter_hdr, db)] + return dbs + + +if config.get("proxy_mode") and "dbfilter_from_header" in config.get( + "server_wide_modules" +): + _logger = logging.getLogger(__name__) + _logger.info("monkey patching http.db_filter") + http.db_filter = db_filter diff --git a/odex25_donation/dbfilter_from_header/readme/CONFIGURE.rst b/odex25_donation/dbfilter_from_header/readme/CONFIGURE.rst new file mode 100644 index 000000000..11da21c49 --- /dev/null +++ b/odex25_donation/dbfilter_from_header/readme/CONFIGURE.rst @@ -0,0 +1,18 @@ +Please keep in mind that the standard odoo dbfilter configuration is still +applied before looking at the regular expression in the header. + +* For nginx, use: + + ``proxy_set_header X-Odoo-dbfilter [your filter regex];`` + +* For caddy, use: + + ``proxy_header X-Odoo-dbfilter [your filter regex]`` + +* For Apache, use: + + ``RequestHeader set X-Odoo-dbfilter [your filter regex]`` + +And make sure that proxy mode is enabled in Odoo's configuration file: + +``proxy_mode = True`` diff --git a/odex25_donation/dbfilter_from_header/readme/CONTRIBUTORS.rst b/odex25_donation/dbfilter_from_header/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..8be29af70 --- /dev/null +++ b/odex25_donation/dbfilter_from_header/readme/CONTRIBUTORS.rst @@ -0,0 +1,11 @@ +* Stéphane Bidoul +* Yannick Vaucher +* Alexandre Fayolle +* Holger Brunn +* Laurent Mignon (aka lmi) +* Sandy Carter +* Fabio Vilchez +* Jos De Graeve +* Lai Tim Siu (Quaritle Limited) +* Tharathip Chaweewongphan +* Eric Antones diff --git a/odex25_donation/dbfilter_from_header/readme/DESCRIPTION.rst b/odex25_donation/dbfilter_from_header/readme/DESCRIPTION.rst new file mode 100644 index 000000000..8f058402a --- /dev/null +++ b/odex25_donation/dbfilter_from_header/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +This addon lets you pass a dbfilter as a HTTP header. + +This is interesting for setups where database names can't be mapped to proxied host names. diff --git a/odex25_donation/dbfilter_from_header/readme/INSTALL.rst b/odex25_donation/dbfilter_from_header/readme/INSTALL.rst new file mode 100644 index 000000000..86ee135b7 --- /dev/null +++ b/odex25_donation/dbfilter_from_header/readme/INSTALL.rst @@ -0,0 +1,7 @@ +To install this module, you only need to add it to your addons, and load it as +a server-wide module. + +This can be done with the ``server_wide_modules`` parameter in ``/etc/odoo.conf`` +or with the ``--load`` command-line parameter + +``server_wide_modules = base,web,dbfilter_from_header`` diff --git a/odex25_donation/dbfilter_from_header/readme/USAGE.rst b/odex25_donation/dbfilter_from_header/readme/USAGE.rst new file mode 100644 index 000000000..873c97460 --- /dev/null +++ b/odex25_donation/dbfilter_from_header/readme/USAGE.rst @@ -0,0 +1,2 @@ +To use this module, you need to complete installation and configuration +parts. diff --git a/odex25_donation/dbfilter_from_header/static/description/icon.png b/odex25_donation/dbfilter_from_header/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/odex25_donation/dbfilter_from_header/static/description/icon.png differ diff --git a/odex25_donation/dbfilter_from_header/static/description/index.html b/odex25_donation/dbfilter_from_header/static/description/index.html new file mode 100644 index 000000000..2e6ab924f --- /dev/null +++ b/odex25_donation/dbfilter_from_header/static/description/index.html @@ -0,0 +1,464 @@ + + + + + + +dbfilter_from_header + + + +
+

dbfilter_from_header

+ + +

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runbot

+

This addon lets you pass a dbfilter as a HTTP header.

+

This is interesting for setups where database names can’t be mapped to proxied host names.

+

Table of contents

+ +
+

Installation

+

To install this module, you only need to add it to your addons, and load it as +a server-wide module.

+

This can be done with the server_wide_modules parameter in /etc/odoo.conf +or with the --load command-line parameter

+

server_wide_modules = base,web,dbfilter_from_header

+
+
+

Configuration

+

Please keep in mind that the standard odoo dbfilter configuration is still +applied before looking at the regular expression in the header.

+
    +
  • For nginx, use:

    +

    proxy_set_header X-Odoo-dbfilter [your filter regex];

    +
  • +
  • For caddy, use:

    +

    proxy_header X-Odoo-dbfilter [your filter regex]

    +
  • +
  • For Apache, use:

    +

    RequestHeader set X-Odoo-dbfilter [your filter regex]

    +
  • +
+

And make sure that proxy mode is enabled in Odoo’s configuration file:

+

proxy_mode = True

+
+
+

Usage

+

To use this module, you need to complete installation and configuration +parts.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Therp BV
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/server-tools project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/odex25_donation/droggol_theme_common/COPYRIGHT b/odex25_donation/droggol_theme_common/COPYRIGHT new file mode 100644 index 000000000..e27598c6a --- /dev/null +++ b/odex25_donation/droggol_theme_common/COPYRIGHT @@ -0,0 +1,16 @@ + +Most of the files are + +Copyright (c) 2019 - present Droggol Infotech Private Limited. + +Some javascript files might be from from third +parties libraries. In that case the original +copyright of the contributions can be traced +through the history of the source version +control system. + +When that is not the case, the files contain a prominent +notice stating the original copyright and applicable +license, or come with their own dedicated COPYRIGHT +and/or LICENSE file. + diff --git a/odex25_donation/droggol_theme_common/LICENSE b/odex25_donation/droggol_theme_common/LICENSE new file mode 100644 index 000000000..7a5c68e71 --- /dev/null +++ b/odex25_donation/droggol_theme_common/LICENSE @@ -0,0 +1,27 @@ +Odoo Proprietary License v1.0 + +This software and associated files (the "Software") may only be used (executed, +modified, executed after modifications) if you have purchased a valid license +from the authors, typically via Odoo Apps, or if you have received a written +agreement from the authors of the Software (see the COPYRIGHT file). + +You may develop Odoo modules that use the Software as a library (typically +by depending on it, importing it and using its resources), but without copying +any source code or material from the Software. You may distribute those +modules under the license of your choice, provided that this license is +compatible with the terms of the Odoo Proprietary License (For example: +LGPL, MIT, or proprietary licenses similar to this one). + +It is forbidden to publish, distribute, sublicense, or sell copies of the Software +or modified copies of the Software. + +The above copyright notice and this permission notice must be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/odex25_donation/droggol_theme_common/__init__.py b/odex25_donation/droggol_theme_common/__init__.py new file mode 100644 index 000000000..65496fc9c --- /dev/null +++ b/odex25_donation/droggol_theme_common/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from . import controllers +from . import models +from . import deprecated diff --git a/odex25_donation/droggol_theme_common/__manifest__.py b/odex25_donation/droggol_theme_common/__manifest__.py new file mode 100644 index 000000000..ede21c388 --- /dev/null +++ b/odex25_donation/droggol_theme_common/__manifest__.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +{ + 'name': 'Droggol Theme Common', + 'description': 'Droggol Theme Common', + 'category': 'eCommerce', + 'version': '16.0.0.0.8', + 'depends': [ + 'sale_product_configurator', + 'website_sale_comparison', + 'website_sale_wishlist', + 'website_sale_stock', + 'website_sale_stock_wishlist', + ], + + 'license': 'OPL-1', + 'author': 'Droggol Infotech Private Limited', + 'company': 'Droggol Infotech Private Limited', + 'maintainer': 'Droggol Infotech Private Limited', + 'website': 'https://www.droggol.com/', + + 'price': 10.00, + 'currency': 'USD', + 'live_test_url': '', + + 'data': [ + 'security/ir.model.access.csv', + 'deprecated/ir.model.access.csv', + 'views/templates.xml', + + # Backend + 'views/backend/menu_label.xml', + 'views/backend/website_menu.xml', + 'views/backend/product_label.xml', + 'views/backend/product_template.xml', + 'views/backend/product_attribute.xml', + 'views/backend/product_brand.xml', + 'views/backend/dr_website_content.xml', + 'views/backend/product_pricelist.xml', + 'views/backend/pwa_shortcuts.xml', + 'views/backend/res_config_settings.xml', + 'views/backend/dr_theme_config.xml', + 'views/backend/category_label.xml', + 'views/backend/product_category.xml', + 'views/backend/website.xml', + + # Snippets + 'views/snippets/s_mega_menu.xml', + ], + 'assets': { + 'web.assets_frontend': [ + 'droggol_theme_common/static/src/scss/variants.scss', + ], + 'web.assets_backend': [ + 'droggol_theme_common/static/src/scss/variants.scss', + 'droggol_theme_common/static/src/js/components/*.xml', + 'droggol_theme_common/static/src/js/hooks.js', + ], + 'website.assets_editor': [ + 'droggol_theme_common/static/src/js/components/*.js', + 'droggol_theme_common/static/src/js/components/*.scss', + 'droggol_theme_common/static/src/js/navbar/*.js', + ] + }, +} diff --git a/odex25_donation/droggol_theme_common/controllers/__init__.py b/odex25_donation/droggol_theme_common/controllers/__init__.py new file mode 100644 index 000000000..ef9adf569 --- /dev/null +++ b/odex25_donation/droggol_theme_common/controllers/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from . import main diff --git a/odex25_donation/droggol_theme_common/controllers/main.py b/odex25_donation/droggol_theme_common/controllers/main.py new file mode 100644 index 000000000..689a4d902 --- /dev/null +++ b/odex25_donation/droggol_theme_common/controllers/main.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import http +from odoo.http import request + + +class DroggolThemeCommon(http.Controller): + + @http.route(['/droggol_theme_common/design_content/'], type='http', website=True, auth='user') + def design_content(self, content, **post): + return request.render('droggol_theme_common.design_content', {'content': content, 'no_header': True, 'no_footer': True}) diff --git a/odex25_donation/droggol_theme_common/deprecated/__init__.py b/odex25_donation/droggol_theme_common/deprecated/__init__.py new file mode 100644 index 000000000..34c2e4517 --- /dev/null +++ b/odex25_donation/droggol_theme_common/deprecated/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +# [Files will be removed in a future version] +# Contains deprecated fields and models + +from . import deprecated_v16 +from . import deprecated_v15 diff --git a/odex25_donation/droggol_theme_common/deprecated/deprecated_v15.py b/odex25_donation/droggol_theme_common/deprecated/deprecated_v15.py new file mode 100644 index 000000000..5ccdf226f --- /dev/null +++ b/odex25_donation/droggol_theme_common/deprecated/deprecated_v15.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import fields, models +from odoo.tools.translate import html_translate + + +class DrProductBrand(models.Model): + _name = 'dr.product.brand' + _inherit = ['website.multi.mixin'] + _description = 'Product Brand' + _order = 'sequence,id' + + name = fields.Char(required=True, translate=True) + description = fields.Char(translate=True) + image = fields.Binary() + sequence = fields.Integer(string='Sequence') + active = fields.Boolean(default=True) + + +class DrProductOffer(models.Model): + _name = 'dr.product.offer' + _description = 'Product Offers' + _order = 'sequence,id' + + name = fields.Char(string='Title', required=True, translate=True) + description = fields.Char(string='Description', required=True, translate=True) + icon = fields.Char(default='list') + sequence = fields.Integer(string='Sequence') + dialog_content = fields.Html(sanitize_attributes=False, translate=html_translate, sanitize_form=False) + product_id = fields.Many2one('product.template') + tag_id = fields.Many2one('dr.product.tags') + + +class DrProductTabs(models.Model): + _name = 'dr.product.tabs' + _description = 'Product Tabs' + _order = 'sequence,id' + + name = fields.Char(string='Title', required=True, translate=True) + icon = fields.Char(default='list') + content = fields.Html(sanitize_attributes=False, translate=html_translate, sanitize_form=False) + sequence = fields.Integer(string='Sequence') + product_id = fields.Many2one('product.template') + tag_id = fields.Many2one('dr.product.tags') + + +class DrProductTagsExt(models.Model): + _inherit = 'dr.product.tags' + + dr_tab_ids = fields.One2many('dr.product.tabs', 'tag_id', string='Tabs', help='Display in product detail page on website.') + dr_offer_ids = fields.One2many('dr.product.offer', 'tag_id', string='Offers', help='Display in product detail page on website.') + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + dr_brand_id = fields.Many2one('dr.product.brand') + dr_offer_ids = fields.One2many('dr.product.offer', 'product_id', help='Display in product detail page on website.') + dr_tab_ids = fields.One2many('dr.product.tabs', 'product_id', help='Display in product detail page on website.') + + +class WebsiteMenu(models.Model): + _inherit = 'website.menu' + + dr_is_special_menu = fields.Boolean() diff --git a/odex25_donation/droggol_theme_common/deprecated/deprecated_v16.py b/odex25_donation/droggol_theme_common/deprecated/deprecated_v16.py new file mode 100644 index 000000000..24fa53a1c --- /dev/null +++ b/odex25_donation/droggol_theme_common/deprecated/deprecated_v16.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import fields, models + + +class DrProductTags(models.Model): + _name = 'dr.product.tags' + _inherit = ['website.multi.mixin'] + _description = 'Product Tags' + + name = fields.Char(required=True, translate=True) + product_ids = fields.Many2many('product.template', 'dr_product_tags_rel', 'tag_id', 'product_id', string='Products') + product_count = fields.Integer(compute='_compute_product_count') + active = fields.Boolean(default=True) + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + dr_tag_ids = fields.Many2many('dr.product.tags', 'dr_product_tags_rel', 'product_id', 'tag_id', string='Tags') diff --git a/odex25_donation/droggol_theme_common/deprecated/ir.model.access.csv b/odex25_donation/droggol_theme_common/deprecated/ir.model.access.csv new file mode 100644 index 000000000..e7cbf19ce --- /dev/null +++ b/odex25_donation/droggol_theme_common/deprecated/ir.model.access.csv @@ -0,0 +1,8 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_dr_product_brand_manager,dr.product.brand.manager,model_dr_product_brand,sales_team.group_sale_manager,1,1,1,1 +access_dr_product_tabs_manager,dr.product.tabs.manager,model_dr_product_tabs,sales_team.group_sale_manager,1,1,1,1 +access_dr_product_tabs_public,dr.product.tabs.public,model_dr_product_tabs,,1,0,0,0 +access_dr_product_offer_manager,dr.product.offer.manager,model_dr_product_offer,sales_team.group_sale_manager,1,1,1,1 +access_dr_product_offer_public,dr.product.offer.public,model_dr_product_offer,,1,0,0,0 +access_dr_product_tags_manager,dr.product.tags.manager,model_dr_product_tags,sales_team.group_sale_manager,1,1,1,1 +access_dr_product_tags_public,dr.product.tags.public,model_dr_product_tags,,1,0,0,0 diff --git a/odex25_donation/droggol_theme_common/i18n/ar.po b/odex25_donation/droggol_theme_common/i18n/ar.po new file mode 100644 index 000000000..77bc9fa35 --- /dev/null +++ b/odex25_donation/droggol_theme_common/i18n/ar.po @@ -0,0 +1,2177 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * droggol_theme_common +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-08-24 12:14+0000\n" +"PO-Revision-Date: 2023-08-24 12:14+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "" +"" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_website_content_view_form +msgid "" +"\n" +" Design\n" +" \n" +" \n" +" Content\n" +" " +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_category_mega_menu_snippet +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_category_tabs_snippet +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_tp_mega_menu_category_snippet +msgid "" +"Click Here! " +"to configure snippet." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Starting at $30" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Starting at $40" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "About" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Accessories" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__active +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__active +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__active +msgid "Active" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_brand_values_view_tree +msgid "Add New Brand" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_5 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Aenean" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +msgid "" +"Aenean Sale" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +msgid "" +"Aenean Sale" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "" +"Allows users to follow up product's Add to Cart button until bottom scroll " +"reached." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "" +"Allows users to install your website as an application on mobile and " +"desktop." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "App Shortcuts" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "" +"App shortcuts help users quickly start common or recommended tasks within " +"your web app." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Apply filters with lazy method" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "" +"Apply manual discounts on sales order lines or display discounts computed " +"from pricelists (option to activate in the pricelist configuration)." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_label_view_form +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_label_view_search +msgid "Archived" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Article" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__dr_website_content__content_type__attribute_popup +msgid "Attribute Popup" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_product_attribute_value +msgid "Attribute Value" +msgstr "قيمة الخاصية" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_brand_values_view_search +msgid "Attributes" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__product_attribute__dr_search_suggestion__auto +msgid "Autocomplete" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__product_attribute__dr_search_suggestion__auto_suggestion +msgid "Autocomplete & Suggestion" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "B2B Mode" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "B2b Configuration" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__background_color +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_public_category_label__background_color +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_menu_label__background_color +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Background Color" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__background_color_rgb +msgid "Background Color RGB" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__dr_product_label__style__2 +msgid "Badge" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +msgid "Bags" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Bags & Purses" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Basic" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Basic Grid" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Behavior of load more products" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Blog" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Boots" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Bottom bar allow movement between primary destinations on the website." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Bottombar" +msgstr "" + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/product_attribute.py:0 +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_brand_value_id +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_brand_value_id +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_brand_values_view_form +#, python-format +msgid "Brand" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Brand Page" +msgstr "" + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/product_attribute.py:0 +#, python-format +msgid "Brand attribute must have display type \"Radio Image\"." +msgstr "" + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/website.py:0 +#: model:ir.actions.act_window,name:droggol_theme_common.dr_product_brand_values_action +#: model:ir.ui.menu,name:droggol_theme_common.menu_dr_product_brand_values +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_brand_values_view_search +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_brand_values_view_tree +#, python-format +msgid "Brands" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Buttombar Buttons" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_dr_cache_mixin +msgid "Cache Mixin" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Career" +msgstr "" + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/website.py:0 +#, python-format +msgid "Cart" +msgstr "سله التبرعات" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Cart Flow" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Case Study" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Categories" +msgstr "اقسام التبرع" + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/website.py:0 +#, python-format +msgid "Category" +msgstr "اقسام التبرع" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_dr_product_public_category_label +msgid "Category Label" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.actions.act_window,name:droggol_theme_common.dr_category_label_action +#: model:ir.ui.menu,name:droggol_theme_common.menu_dr_category_label +msgid "Category Labels" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Category Pills" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Category sidebar style" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__dr_product_label__style__3 +msgid "Circle" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +msgid "Client Image #{number}" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Clothing" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Coats & Jackets" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Collapsible attributes" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Collapsible category" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Company" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_res_config_settings +msgid "Config Settings" +msgstr "تهيئة الإعدادات " + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Configure Shortcuts" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Configure action buttons of product card in shop page." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Configure actions and style of product card." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Contact" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__content +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__content +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_website_content_view_form +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_website_content_view_search +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_website_content_view_tree +msgid "Content" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_website_content_view_search +msgid "Content Type" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.actions.act_window,name:droggol_theme_common.dr_website_content_action +#: model:ir.ui.menu,name:droggol_theme_common.menu_dr_website_content +msgid "Contents" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Cover" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_public_category__dr_category_cover_image +msgid "Cover Image" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__create_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__create_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__create_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_public_category_label__create_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__create_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__create_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__create_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_theme_config__create_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__create_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_menu_label__create_uid +msgid "Created by" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__create_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__create_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__create_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_public_category_label__create_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__create_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__create_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__create_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_theme_config__create_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__create_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_menu_label__create_date +msgid "Created on" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "Dapibus" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.xml:0 +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__product_attribute__dr_radio_image_style__default +#, python-format +msgid "Default" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Default view mode" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__description +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__description +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__description +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__description +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_attribute_value__dr_brand_description +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_pwa_shortcuts_view_form +msgid "Description" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.xml:0 +#, python-format +msgid "Dialog" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__dialog_content +msgid "Dialog Content" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Disable grouping of brands" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_website_sale_extra_field__dr_label +msgid "Display Label" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__display_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__display_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__display_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_public_category_label__display_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__display_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__display_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__display_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_theme_config__display_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__display_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_menu_label__display_name +msgid "Display Name" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_attribute__display_type +msgid "Display Type" +msgstr "نوع العرض" + +#. module: droggol_theme_common +#: model:ir.model.fields,help:droggol_theme_common.field_dr_product_tags__dr_offer_ids +#: model:ir.model.fields,help:droggol_theme_common.field_dr_product_tags__dr_tab_ids +#: model:ir.model.fields,help:droggol_theme_common.field_product_product__dr_offer_ids +#: model:ir.model.fields,help:droggol_theme_common.field_product_product__dr_tab_ids +#: model:ir.model.fields,help:droggol_theme_common.field_product_template__dr_offer_ids +#: model:ir.model.fields,help:droggol_theme_common.field_product_template__dr_tab_ids +msgid "Display in product detail page on website." +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_document_ids +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_document_ids +msgid "Documents" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,help:droggol_theme_common.field_product_product__dr_document_ids +#: model:ir.model.fields,help:droggol_theme_common.field_product_template__dr_document_ids +msgid "Documents publicly downloadable from eCommerce product page." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_5 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Donec non" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_5 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Donec ultrices" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_brand_id +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_brand_id +msgid "Dr Brand" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_brand_attribute_ids +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_brand_attribute_ids +msgid "Dr Brand Attribute" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_has_custom_module +msgid "Dr Has Custom Module" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_website_menu__dr_is_special_menu +msgid "Dr Is Special Menu" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_offer_ids +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_offer_ids +msgid "Dr Offer" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_ptav_ids +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_ptav_ids +msgid "Dr Ptav" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_show_out_of_stock +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_show_out_of_stock +msgid "Dr Show Out Of Stock" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_tab_ids +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_tab_ids +msgid "Dr Tab" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Dresses" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.actions.act_window,name:droggol_theme_common.dr_theme_config_action +#: model:ir.model,name:droggol_theme_common.model_dr_theme_config +#: model:ir.ui.menu,name:droggol_theme_common.dr_theme_config_menu +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_theme_config_view_tree +msgid "Droggol Theme Config" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "Duis" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_website_sale_extra_field +msgid "E-Commerce Extra Info Shown on product page" +msgstr "المعلومات الإضافية للتجارة الإلكترونية المعروضة على صفحة المنتج " + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Enable Offline Page" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Enable Progressive Web Apps" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Enable advance search" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Enable category pills" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Enable product offers" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Enable sticky add to cart" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Enable zoom" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_5 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Etiam" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__identifier +msgid "Extra Label" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_website_sale_extra_field__field_id +msgid "Field" +msgstr "حقل" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Filter Position" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Filter Style" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Flats" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_website_content_view_form +msgid "FontAwesome" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_public_category__dr_search_formulate +msgid "Formulated Search" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_free_qty +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_free_qty +msgid "Free To Use Quantity" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Fuzzy search" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "General" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Grant discounts on sales order lines" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Grid Rows" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_brand_values_view_search +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_website_content_view_search +msgid "Group By" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Heels" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Help center" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Hide country flag" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Hide extra attributes" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Hide in desktop device" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_website_menu__dr_highlight_menu +msgid "Highlight Menu" +msgstr "" + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/website.py:0 +#, python-format +msgid "Home" +msgstr "منصه التبرعات" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_public_category_label__id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_theme_config__id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_menu_label__id +msgid "ID" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__icon +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__icon +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__icon +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__icon +msgid "Icon" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Icon (192x192)" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Icon (512x512)" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_public_category__dr_category_icon +msgid "Icon Image" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_pwa_shortcuts_view_form +msgid "Icon size must be 192x192." +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__image +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_attribute_value__dr_image +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template_attribute_value__dr_image +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__product_attribute__dr_radio_image_style__image +msgid "Image" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__product_attribute__dr_radio_image_style__image_text +msgid "Image + Text" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Image Fill" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Image Size" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_attribute__dr_is_brand +msgid "Is Brand?" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,help:droggol_theme_common.field_dr_website_content__identifier +msgid "It is just displayed in backend dropdown and breadcrumb" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Jeans" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Jewelry" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_theme_config__key +msgid "Key" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_label_id +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_public_category__dr_category_label_id +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_label_id +#: model:ir.model.fields,field_description:droggol_theme_common.field_website_menu__dr_menu_label_id +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_label_view_form +msgid "Label" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.actions.act_window,name:droggol_theme_common.dr_product_label_action +#: model:ir.ui.menu,name:droggol_theme_common.menu_dr_product_label +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_category_label_view_tree +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_label_view_search +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_label_view_tree +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_website_menu_label_view_tree +msgid "Labels" +msgstr "" + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/website.py:0 +#, python-format +msgid "Language and Pricelist selector" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Language/Pricelist Selector" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand____last_update +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label____last_update +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer____last_update +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_public_category_label____last_update +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs____last_update +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags____last_update +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts____last_update +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_theme_config____last_update +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content____last_update +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_menu_label____last_update +msgid "Last Modified on" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__write_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__write_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__write_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_public_category_label__write_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__write_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__write_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__write_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_theme_config__write_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__write_uid +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_menu_label__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__write_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__write_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__write_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_public_category_label__write_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__write_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__write_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__write_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_theme_config__write_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__write_date +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_menu_label__write_date +msgid "Last Updated on" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Layout" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +msgid "Limited Collection" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Listing" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Masonry" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_5 +msgid "Mega Menu Image 0#{title}" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Mega Menu Image 01" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.actions.act_window,name:droggol_theme_common.dr_website_menu_label_action +#: model:ir.ui.menu,name:droggol_theme_common.menu_dr_website_menu_label +msgid "Menu Labels" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Mobile" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "Morbi vel" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_public_category_label__name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_menu_label__name +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_brand_values_view_form +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_brand_values_view_tree +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Name" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "New in" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +msgid "Newly Launched" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.xml:0 +#, python-format +msgid "Notification" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "Nulla vehicula" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "Nullam" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +msgid "" +"Nullam Popular" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_5 +msgid "Nullam mattis" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +msgid "" +"Nullam mattis Exclusive" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_5 +msgid "Nullam sed" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_pricelist_item__dr_offer_finish_msg +msgid "Offer Finish Message" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_pricelist_item__dr_offer_msg +msgid "Offer Message" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__dr_website_content__content_type__offer_popup +msgid "Offer Popup" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__dr_offer_products_ids +msgid "Offer Products" +msgstr "" + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/website.py:0 +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__dr_offer_ids +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_product_offer_ids +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_product_offer_ids +#, python-format +msgid "Offers" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.xml:0 +#, python-format +msgid "Open Cart Sidebar" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Opening" +msgstr "" + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/website.py:0 +#, python-format +msgid "Orders" +msgstr "تبرعاتي" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Overview" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_pwa_activated +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_activated +msgid "PWA Activated" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_pwa_background_color +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_background_color +msgid "PWA Background Color" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_pwa_icon_192 +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_icon_192 +msgid "PWA Icon 192x192" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_pwa_icon_512 +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_icon_512 +msgid "PWA Icon 512x512" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_pwa_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_name +msgid "PWA Name" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_pwa_offline_page +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_offline_page +msgid "PWA Offline Page" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_pwa_short_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_short_name +msgid "PWA Short Name" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.actions.act_window,name:droggol_theme_common.dr_pwa_shortcuts_action +#: model:ir.model,name:droggol_theme_common.model_dr_pwa_shortcuts +msgid "PWA Shortcuts" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_pwa_start_url +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_start_url +msgid "PWA Start URL" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_pwa_theme_color +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_theme_color +msgid "PWA Theme Color" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_version +msgid "PWA Version" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Parallax" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_attribute__dr_attribute_popup_id +msgid "Popup" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Portfolio" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "قاعدة قائمة الأسعار " + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Pricelist per customer" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Pricing" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_product_template +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__product_id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__product_id +msgid "Product" +msgstr "المنتج" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_product_attribute +msgid "Product Attribute" +msgstr "خاصية المنتج" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_dr_product_brand +msgid "Product Brand" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Product Card" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Product Card Actions" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__product_count +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__product_count +msgid "Product Count" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Product Detail" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_dr_product_label +msgid "Product Label" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Product Navigation" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#: model:ir.model,name:droggol_theme_common.model_dr_product_offer +#, python-format +msgid "Product Offers" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__dr_website_content__content_type__tab +msgid "Product Tab" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_dr_product_tabs +msgid "Product Tabs" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_dr_product_tags +msgid "Product Tags" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_product_template_attribute_line +msgid "Product Template Attribute Line" +msgstr "بند خاصية قالب المنتج" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_product_template_attribute_value +msgid "Product Template Attribute Value" +msgstr "قيمة خاصية قالب المنتج " + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__product_ids +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_label_view_form +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_website_content_view_form +msgid "Products" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Products limit" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Progressive Web Apps (PWA)" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "Proin" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +msgid "" +"Proin New" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +msgid "" +"Proin New" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "Proin eu" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_5 +msgid "Proin lobortis" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "Quisque" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__product_attribute__display_type__radio_circle +msgid "Radio Circle" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__product_attribute__display_type__radio_image +msgid "Radio Image" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__product_attribute__display_type__radio_square +msgid "Radio Square" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,help:droggol_theme_common.field_dr_product_brand__website_id +#: model:ir.model.fields,help:droggol_theme_common.field_dr_product_tags__website_id +msgid "Restrict publishing to this website." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Result Limit" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Rich" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Rich View" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_sale_special_offer +msgid "Sale Special Offer" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_sale_order +msgid "Sales Order" +msgstr "أمر البيع" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Sandals" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Save" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Scarves & Hats" +msgstr "" + +#. module: droggol_theme_common +#. odoo-python +#. odoo-javascript +#: code:addons/droggol_theme_common/models/website.py:0 +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +#, python-format +msgid "Search" +msgstr "بحث" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_attribute_value__ds_name +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_public_category__ds_name +msgid "Search DS Name" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_attribute__dr_search_suggestion +msgid "Search suggestion type" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "See all the products at once." +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__sequence +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__sequence +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__sequence +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__sequence +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__sequence +msgid "Sequence" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Shoes" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Shop" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Shop Filter" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Shop Now" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +msgid "Shop Offer Image 01" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Shop page main layout." +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__short_name +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Short Name" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_res_config_settings__dr_pwa_shortcuts +#: model:ir.model.fields,field_description:droggol_theme_common.field_website__dr_pwa_shortcuts +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_pwa_shortcuts_view_form +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_pwa_shortcuts_view_tree +msgid "Shortcuts" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Shorts" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show Bottombar" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show Bottombar On Scroll" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_attribute__dr_is_show_shop_search +msgid "Show Searchbar in Shop Filter" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show add to cart" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show attribute count" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show availability filter" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show category count" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show category link in menu sidebar" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show child categories pills of active category" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show compare" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show filters in sidebar" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Show offline page when there is no internet." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show product category pills on top of the shop page." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show product count in category sidebar" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show product preview swatches" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show quick view" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show rating" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show rating filter" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show similar products" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show sort and filter button on shop" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show stock label" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show view switcher" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Show wishlist" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Showcase" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Shows button to see next, previous products based on product sequence." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +#, python-format +msgid "Sidebar" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_public_category__dr_category_sidebar_cover +msgid "Sidebar Cover" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Sidebar: Fluid" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Skirts" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Slippers" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Smart Autocomplete" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Smart Suggestion" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Socks" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__website_menu__dr_highlight_menu__soft +msgid "Soft" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__website_menu__dr_highlight_menu__solid +msgid "Solid" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__dr_product_label__style__4 +msgid "Square" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Start URL" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Sticky Add to Cart" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__style +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_attribute__dr_radio_image_style +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_product_label_view_search +#, python-format +msgid "Style" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template_attribute_value__dr_thumb_image +msgid "Swatch Image" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__dr_tab_products_ids +msgid "Tab Products" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__dr_tab_ids +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_product_tab_ids +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_product_tab_ids +msgid "Tabs" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__tag_id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__tag_id +#: model:ir.model.fields.selection,name:droggol_theme_common.selection__dr_product_label__style__1 +msgid "Tag" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_product__dr_tag_ids +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template__dr_tag_ids +msgid "Tags" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_1 +msgid "Terms" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_label__text_color +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_public_category_label__text_color +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_menu_label__text_color +msgid "Text Color" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,help:droggol_theme_common.field_dr_pwa_shortcuts__url +msgid "The URL opened when a user activates the app shortcut." +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,help:droggol_theme_common.field_product_attribute__display_type +msgid "The display type used in the Product Configurator." +msgstr "نوع العرض المستخدم في أداة تهيئة المنتج. " + +#. module: droggol_theme_common +#: model:ir.model.fields,help:droggol_theme_common.field_dr_pwa_shortcuts__name +msgid "" +"The human-readable label for the app shortcut when displayed to the user." +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,help:droggol_theme_common.field_dr_pwa_shortcuts__short_name +msgid "The human-readable label used where space is limited." +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,help:droggol_theme_common.field_dr_pwa_shortcuts__description +msgid "The human-readable purpose for the app shortcut." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Theme Color" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Theme Configuration" +msgstr "" + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/res_config_settings.py:0 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +#, python-format +msgid "Theme Customizations" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.product_public_category_form_view_inherit_droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.product_template_form_view_inherit_droggol_theme_common +msgid "Theme Prime" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.ui.menu,name:droggol_theme_common.menu_theme_prime_config +msgid "Theme Prime Configuration" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "" +"These icons are used in places like the home screen, app launcher, task " +"switcher, splash screen, etc." +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_offer__name +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tabs__name +msgid "Title" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Tweak filters behavior on shop." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Tweak search behavior for your website." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Tweak your shop behavior." +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_website_content__content_type +msgid "Type" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__url +msgid "URL" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,help:droggol_theme_common.field_product_public_category__dr_search_formulate +msgid "" +"Use to search multi level categories e.g. Men Shirt (Here men and " +"shirt are diffrent category but will be displayed as one in smart search)" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Used in the app install prompt." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Used on the splash screen when the application is first launched." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Used on the user's home screen, launcher, or other places." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Used on toolbar, and may be in the app's preview in task switchers." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.xml:0 +#, python-format +msgid "User Guide" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_theme_config__value +msgid "Value" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "View all products" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_3 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_5 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_6 +msgid "Vivamus" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_2 +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.s_mega_menu_prime_4 +msgid "Want to explore our products?" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_website +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_brand__website_id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_product_tags__website_id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_pwa_shortcuts__website_id +#: model:ir.model.fields,field_description:droggol_theme_common.field_dr_theme_config__website_id +msgid "Website" +msgstr "الموقع الإلكتروني" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_dr_website_content +msgid "Website Content" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_website_menu +msgid "Website Menu" +msgstr "قائمة الموقع الإلكتروني " + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_dr_website_menu_label +msgid "Website Menu Label" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model.fields,field_description:droggol_theme_common.field_product_template_attribute_line__dr_attribute_popup_id +msgid "Website Popup" +msgstr "" + +#. module: droggol_theme_common +#: model:ir.model,name:droggol_theme_common.model_product_public_category +msgid "Website Product Category" +msgstr "فئة منتج الموقع الإلكتروني " + +#. module: droggol_theme_common +#. odoo-python +#: code:addons/droggol_theme_common/models/website.py:0 +#, python-format +msgid "Wishlist" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "You can change behaviour of sidebars." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "You can change how products are being added in cart." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.dr_website_content_view_form +msgid "You can find icon at" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "You will be able to add offers on product and show details in dialog." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.res_config_settings_view_form +msgid "Your application will start from this URL when it is launched." +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Zoom Product Images" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Zoom factor" +msgstr "" + +#. module: droggol_theme_common +#. odoo-javascript +#: code:addons/droggol_theme_common/static/src/js/components/theme_config.js:0 +#, python-format +msgid "Zoom product images in product detail page and quick view." +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.product_attribute_view_form_inherit_droggol_theme_common +msgid "eCommerce" +msgstr "" + +#. module: droggol_theme_common +#: model_terms:ir.ui.view,arch_db:droggol_theme_common.product_attribute_view_form_inherit_droggol_theme_common +msgid "eCommerce Filter Visibility" +msgstr "" diff --git a/odex25_donation/droggol_theme_common/models/__init__.py b/odex25_donation/droggol_theme_common/models/__init__.py new file mode 100644 index 000000000..881e1f2b4 --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from . import dr_cache_mixin +from . import dr_category_label +from . import dr_product_label +from . import dr_pwa_shortcuts +from . import dr_theme_config +from . import dr_website_content +from . import dr_website_menu_label +from . import product_attribute +from . import product_pricelist_item +from . import product_public_category +from . import product_template +from . import res_config_settings +from . import sale_order +from . import website +from . import website_menu diff --git a/odex25_donation/droggol_theme_common/models/dr_cache_mixin.py b/odex25_donation/droggol_theme_common/models/dr_cache_mixin.py new file mode 100644 index 000000000..8df1da004 --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/dr_cache_mixin.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import api, models + + +class DrCacheMixin(models.AbstractModel): + _name = 'dr.cache.mixin' + _description = 'Cache Mixin' + + _fields_to_watch = [] + + @api.model_create_multi + def create(self, vals_list): + self.clear_caches() + return super().create(vals_list) + + def write(self, vals): + self.clear_caches() + return super().write(vals) + + def unlink(self): + self.clear_caches() + return super().unlink() diff --git a/odex25_donation/droggol_theme_common/models/dr_category_label.py b/odex25_donation/droggol_theme_common/models/dr_category_label.py new file mode 100644 index 000000000..5c54b9894 --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/dr_category_label.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import fields, models + + +class DrProductPublicCategoryLabel(models.Model): + _name = 'dr.product.public.category.label' + _description = 'Category Label' + + name = fields.Char(required=True, translate=True) + background_color = fields.Char('Background Color', default='#000000') + text_color = fields.Char('Text Color', default='#FFFFFF') diff --git a/odex25_donation/droggol_theme_common/models/dr_product_label.py b/odex25_donation/droggol_theme_common/models/dr_product_label.py new file mode 100644 index 000000000..4c070d4bd --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/dr_product_label.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from PIL import ImageColor +from odoo import api, fields, models + + +class DrProductLabel(models.Model): + _name = 'dr.product.label' + _description = 'Product Label' + _inherit = 'dr.cache.mixin' + + name = fields.Char(required=True, translate=True) + background_color = fields.Char('Background Color', default='#000000') + background_color_rgb = fields.Char(compute='_compute_background_color_rgb', store=True, string='Background Color RGB') + text_color = fields.Char('Text Color', default='#FFFFFF') + style = fields.Selection([('1', 'Tag'), ('2', 'Badge'), ('3', 'Circle'), ('4', 'Square')], default='1', required=True) + product_count = fields.Integer(compute='_compute_product_count') + active = fields.Boolean(default=True) + + def _compute_product_count(self): + label_data = self.env['product.template'].read_group([('dr_label_id', 'in', self.ids)], ['dr_label_id'], ['dr_label_id']) + mapped_data = dict([(x['dr_label_id'][0], x['dr_label_id_count']) for x in label_data]) + for label in self: + label.product_count = mapped_data.get(label.id, 0) + + @api.depends('background_color') + def _compute_background_color_rgb(self): + for label in self: + colors = ImageColor.getcolor(label.background_color, 'RGB') + label.background_color_rgb = '%s, %s, %s' % (colors[0], colors[1], colors[2]) + + def action_open_products(self): + self.ensure_one() + action = self.env.ref('website_sale.product_template_action_website').read()[0] + action['domain'] = [('dr_label_id', '=', self.id)] + action['context'] = {} + return action diff --git a/odex25_donation/droggol_theme_common/models/dr_pwa_shortcuts.py b/odex25_donation/droggol_theme_common/models/dr_pwa_shortcuts.py new file mode 100644 index 000000000..dd6de8e95 --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/dr_pwa_shortcuts.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import fields, models + + +class PWAShortcuts(models.Model): + _name = 'dr.pwa.shortcuts' + _description = 'PWA Shortcuts' + + website_id = fields.Many2one('website') + sequence = fields.Integer() + name = fields.Char(required=True, translate=True, help='The human-readable label for the app shortcut when displayed to the user.') + short_name = fields.Char('Short Name', translate=True, help='The human-readable label used where space is limited.') + description = fields.Text(help='The human-readable purpose for the app shortcut.') + url = fields.Char('URL', required=True, help='The URL opened when a user activates the app shortcut.') + icon = fields.Binary() diff --git a/odex25_donation/droggol_theme_common/models/dr_theme_config.py b/odex25_donation/droggol_theme_common/models/dr_theme_config.py new file mode 100644 index 000000000..470f80dff --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/dr_theme_config.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +import json +import logging +from odoo import _, api, fields, models, tools + +_logger = logging.getLogger(__name__) + + +class DrThemeConfig(models.Model): + _name = 'dr.theme.config' + _inherit = 'dr.cache.mixin' + _description = 'Droggol Theme Config' + _rec_name = 'key' + + key = fields.Char(required=True) + value = fields.Char() + website_id = fields.Many2one('website') + + @api.model + @tools.ormcache('website_id') + def _get_all_config(self, website_id): + result_configs = self._get_default_theme_config(website_id) + all_config = self.search([('website_id', '=', website_id)]) + for config in all_config: + try: + if config.key.startswith('bool_'): + result_configs[config.key] = config.value == 'True' + elif config.key.startswith('json_'): + config_value = json.loads(config.value) + if isinstance(config_value, dict) and result_configs.get(config.key): + result_configs[config.key].update(config_value) + else: + result_configs[config.key] = config_value + elif config.key.startswith('int_'): + result_configs[config.key] = int(config.value) + elif config.key.startswith('float_'): + result_configs[config.key] = float(config.value) + else: + result_configs[config.key] = config.value + except json.decoder.JSONDecodeError: + _logger.warning("Theme Prime Config: Cannot parse '%s' with value '%s' ", config.key, config.value) + except ValueError: + _logger.warning("Theme Prime Config: Cannot parse '%s' with value '%s' ", config.key, config.value) + return result_configs + + def _get_default_theme_config(self, website_id): + website = self.env['website'].sudo().browse(website_id) + return { + 'json_sidebar_config': {'category_sidebar_style': '2', 'category_sidebar_show_count': True, 'menu_sidebar_show_category': True}, + 'json_shop_layout': {'layout': 'prime', 'show_view_switcher': True, 'default_view_mode': 'grid', 'load_more_products': 'button'}, + 'json_shop_product_item': {'style': '1', 'image_size': 'default', 'image_fill': 'cover', 'show_add_to_cart': True, 'show_wishlist': True, 'show_compare': True, 'show_quick_view': True, 'show_similar_products': True, 'show_product_preview_swatches': True, 'show_rating': True, 'show_stock_label': False}, + 'json_shop_category_pills': {'active': True, 'style': '1', 'show_child_categories': True, 'hide_in_desktop': False}, + 'json_shop_filters': {'lazy_method': True, 'filter_style': '1', 'filter_position': 'left', 'show_in_sidebar': False, 'collapsible_category': True, 'collapsible_attribute': True, 'show_category_count': True, 'show_attribute_count': False, 'hide_extra_attrib_value': False, 'show_rating_filter': True, 'show_availability_filter': False}, + 'json_zoom': {'zoom_enabled': True, 'zoom_factor': 2}, + 'bool_enable_ajax_load': False, + 'json_bottom_bar': {'show_bottom_bar': True, 'show_bottom_bar_on_scroll': False, 'filters': True, 'actions': ['tp_home', 'tp_search', 'tp_wishlist', 'tp_offer', 'tp_brands', 'tp_category', 'tp_orders']}, + 'bool_sticky_add_to_cart': True, + 'json_general_language_pricelist_selector': {'hide_country_flag': False}, + 'json_b2b_shop_config': {'dr_enable_b2b': False, 'dr_only_assigned_pricelist': False}, + 'json_mobile': {}, + 'json_product_search': {'advance_search': True, 'search_category': True, 'search_attribute': True, 'search_suggestion': True, 'search_limit': 10, 'search_max_product': 3, 'search_fuzzy': True}, + 'json_brands_page': {'disable_brands_grouping': False}, + 'cart_flow': 'default', + 'theme_installed': website.theme_id and website.theme_id.name.startswith('theme_prime') or False, + 'pwa_active': website.dr_pwa_activated, + 'bool_product_offers': True, + 'bool_show_products_nav': True, + } + + def save_config(self, website_id, configs): + all_config = self.search([('website_id', '=', website_id)]) + for key, value in configs.items(): + key, value = self._prepare_value_for_write(key, value) + config = all_config.filtered(lambda c: c.key == key) + if config: + config.value = value + else: + self.create({'key': key, 'value': value, 'website_id': website_id}) + return True + + def _prepare_value_for_write(self, key, value): + if key.startswith('json_'): + value = json.dumps(value) + elif key.startswith('int_'): + value = value + return key.strip(), value diff --git a/odex25_donation/droggol_theme_common/models/dr_website_content.py b/odex25_donation/droggol_theme_common/models/dr_website_content.py new file mode 100644 index 000000000..f9bedc4b1 --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/dr_website_content.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import fields, models +from odoo.tools.translate import html_translate + + +class DrWebsiteContent(models.Model): + _name = 'dr.website.content' + _description = 'Website Content' + _inherit = 'dr.cache.mixin' + _order = 'sequence,id' + + sequence = fields.Integer() + name = fields.Char(required=True, translate=True) + identifier = fields.Char('Extra Label', help="It is just displayed in backend dropdown and breadcrumb") + description = fields.Char(translate=True) + icon = fields.Char(default='list') + content = fields.Html(sanitize_attributes=False, translate=html_translate, sanitize_form=False) + content_type = fields.Selection([('tab', 'Product Tab'), ('offer_popup', 'Offer Popup'), ('attribute_popup', 'Attribute Popup')], default='tab', required=True, string='Type') + + dr_tab_products_ids = fields.Many2many('product.template', 'product_template_tab_rel', 'tab_id', 'product_template_id', string='Tab Products') + dr_offer_products_ids = fields.Many2many('product.template', 'product_template_offer_rel', 'offer_id', 'product_template_id', string='Offer Products') + + def name_get(self): + result = [] + for content in self: + name = content.name + if content.identifier: + name = f'[{content.identifier}] {name}' + result.append((content.id, name)) + return result + + def open_design_page(self): + self.ensure_one() + return { + 'type': 'ir.actions.act_url', + 'target': 'new', + 'url': '/droggol_theme_common/design_content/%s?enable_editor=1' % (self.id), + } diff --git a/odex25_donation/droggol_theme_common/models/dr_website_menu_label.py b/odex25_donation/droggol_theme_common/models/dr_website_menu_label.py new file mode 100644 index 000000000..20d6979ea --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/dr_website_menu_label.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import fields, models + + +class DrWebsiteMenuLabel(models.Model): + _name = 'dr.website.menu.label' + _description = 'Website Menu Label' + + name = fields.Char(required=True, translate=True) + background_color = fields.Char('Background Color', default='#000000') + text_color = fields.Char('Text Color', default='#FFFFFF') diff --git a/odex25_donation/droggol_theme_common/models/product_attribute.py b/odex25_donation/droggol_theme_common/models/product_attribute.py new file mode 100644 index 000000000..a2e9e2f8b --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/product_attribute.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError + + +class ProductAttribute(models.Model): + _name = 'product.attribute' + _inherit = ['product.attribute', 'dr.cache.mixin'] + _fields_to_watch = ['name', 'display_type', 'dr_attribute_popup_id', 'dr_radio_image_style', 'dr_is_brand'] + + display_type = fields.Selection( + selection_add=[ + ('radio_circle', 'Radio Circle'), + ('radio_square', 'Radio Square'), + ('radio_image', 'Radio Image'), + ], ondelete={'radio_circle': 'cascade', 'radio_square': 'cascade', 'radio_image': 'cascade'}) + dr_is_show_shop_search = fields.Boolean('Show Searchbar in Shop Filter', default=False) + dr_attribute_popup_id = fields.Many2one('dr.website.content', string='Popup', domain='[("content_type", "=", "attribute_popup")]') + dr_radio_image_style = fields.Selection([ + ('default', 'Default'), + ('image', 'Image'), + ('image_text', 'Image + Text'), + ], default='default', string='Style') + dr_search_suggestion = fields.Selection([('auto', 'Autocomplete'), ('auto_suggestion', 'Autocomplete & Suggestion')], string='Search suggestion type') + dr_is_brand = fields.Boolean('Is Brand?') + + @api.onchange('dr_is_brand') + def _onchange_dr_is_brand(self): + self.display_type = 'radio_image' + + @api.constrains('dr_is_brand', 'display_type') + def _constrains_dr_is_brand(self): + for attribute in self: + if attribute.dr_is_brand and not attribute.display_type == 'radio_image': + raise UserError(_('Brand attribute must have display type "Radio Image".')) + + def open_create_brand_value(self): + return { + 'type': 'ir.actions.act_window', + 'name': _('Brand'), + 'res_model': 'product.attribute.value', + 'view_mode': 'form', + 'target': 'new', + 'views': [[False, 'form']], + 'context': {'default_attribute_id': self.id} + } + + +class ProductAttributeValue(models.Model): + _name = 'product.attribute.value' + _inherit = ['product.attribute.value', 'dr.cache.mixin'] + _fields_to_watch = ['name', 'html_color', 'dr_image', 'dr_brand_description'] + + dr_image = fields.Binary('Image') + dr_brand_description = fields.Text('Description', translate=True) + ds_name = fields.Char('Search DS Name', compute="_compute_ds_name", search="_search_ds_name") + + def _compute_ds_name(self): + for attr in self: + attr.ds_name = attr.name + + @api.model + def _search_ds_name(self, operator, value): + return [('name', operator, value)] + + +class ProductTemplateAttributeValue(models.Model): + _name = 'product.template.attribute.value' + _inherit = ['product.template.attribute.value', 'dr.cache.mixin'] + _fields_to_watch = ['dr_thumb_image'] + + dr_image = fields.Binary('Image', related='product_attribute_value_id.dr_image') + dr_thumb_image = fields.Image('Swatch Image', max_width=128, max_height=128) + + +class ProductTemplateAttributeLine(models.Model): + _inherit = 'product.template.attribute.line' + + dr_attribute_popup_id = fields.Many2one('dr.website.content', string='Website Popup', domain='[("content_type", "=", "attribute_popup")]') diff --git a/odex25_donation/droggol_theme_common/models/product_pricelist_item.py b/odex25_donation/droggol_theme_common/models/product_pricelist_item.py new file mode 100644 index 000000000..7199f57a4 --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/product_pricelist_item.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import fields, models + + +class PricelistItem(models.Model): + _inherit = 'product.pricelist.item' + + dr_offer_msg = fields.Char('Offer Message', default='Hurry Up! Limited time offer.', translate=True) + dr_offer_finish_msg = fields.Char('Offer Finish Message', default='Offer Finished.', translate=True) diff --git a/odex25_donation/droggol_theme_common/models/product_public_category.py b/odex25_donation/droggol_theme_common/models/product_public_category.py new file mode 100644 index 000000000..a0b9bc0a4 --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/product_public_category.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +import re +from odoo import fields, models, api + + +class ProductPublicCategory(models.Model): + _inherit = 'product.public.category' + + dr_category_label_id = fields.Many2one('dr.product.public.category.label', string='Label') + dr_category_cover_image = fields.Binary('Cover Image') + dr_category_icon = fields.Binary('Icon Image') + dr_category_sidebar_cover = fields.Binary('Sidebar Cover') + dr_search_formulate = fields.Boolean('Formulated Search', help="Use to search multi level categories \ + e.g. Men Shirt (Here men and shirt are diffrent category but will be displayed as one in smart search)") + ds_name = fields.Char('Search DS Name', compute="_compute_ds_name", search="_search_ds_name") + + def _compute_ds_name(self): + for category in self: + if self.env.context.get('dr_formulate'): + category.ds_name = ' '.join([categ.name for categ in category.parents_and_self if (category.id == categ.id or categ.dr_search_formulate)]) + else: + category.ds_name = category.name + + @api.model + def _search_ds_name(self, operator, value): + if not self.env.context.get('dr_formulate'): + return [('name', operator, value)] + + # Assumes operator is 'ilike' + domain, website_id = [('dr_search_formulate', '=', False)], self.env.context.get('website_id') + if website_id: + domain += self.env['website'].website_domain(website_id=website_id) + categ_ids = [categ.id for categ in self.search(domain) if re.search(re.escape(value), categ.ds_name, re.IGNORECASE)] + return [('id', 'in', categ_ids)] + + @api.model + def _search_get_detail(self, website, order, options): + "Fix the issue of Odoo's search in html fields" + with_image = options['displayImage'] + options = options.copy() + options['displayDescription'] = False + result = super()._search_get_detail(website, order, options) + if with_image: + result['mapping']['image_url'] = {'name': 'image_url', 'type': 'html'} + + # to fix Odoo's issue Odoo catagory is not multi website compatible + result['base_domain'] = [website.website_domain()] + + return result diff --git a/odex25_donation/droggol_theme_common/models/product_template.py b/odex25_donation/droggol_theme_common/models/product_template.py new file mode 100644 index 000000000..bbb01b7f6 --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/product_template.py @@ -0,0 +1,182 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import api, fields, models, Command +from odoo.addons.website.models import ir_http + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + dr_label_id = fields.Many2one('dr.product.label', string='Label') + + dr_product_tab_ids = fields.Many2many('dr.website.content', 'product_template_tab_rel', 'product_template_id', 'tab_id', string='Tabs') + dr_product_offer_ids = fields.Many2many('dr.website.content', 'product_template_offer_rel', 'product_template_id', 'offer_id', string='Offers') + + dr_document_ids = fields.Many2many('ir.attachment', 'product_template_document_attachment_rel', 'product_template_id', 'attachment_id', string='Documents', help='Documents publicly downloadable from eCommerce product page.') + dr_brand_value_id = fields.Many2one('product.attribute.value', compute='_compute_dr_brand_value_id', inverse='_inverse_dr_brand_value_id', search='_search_dr_brand_value_id', string='Brand') + dr_brand_attribute_ids = fields.Many2many('product.attribute', compute='_compute_dr_brand_attribute_ids') + + dr_free_qty = fields.Float('Free To Use Quantity', compute='_compute_dr_free_qty', search='_search_dr_free_qty', compute_sudo=False, digits='Product Unit of Measure') + dr_show_out_of_stock = fields.Char(compute='_compute_dr_show_out_of_stock', compute_sudo=True) + + dr_ptav_ids = fields.One2many('product.template.attribute.value', 'product_tmpl_id') + + @api.model_create_multi + def create(self, vals): + res = super().create(vals) + res.dr_document_ids.public = True + return res + + def write(self, vals): + res = super().write(vals) + if 'dr_document_ids' in vals: + self.dr_document_ids.public = True + return res + + def _search_dr_brand_value_id(self, operator, value): + if operator in ['in', 'not in']: + return [('attribute_line_ids.value_ids', operator, value)] + elif operator in ['ilike', 'not ilike', '=', '!=']: + brand_attribute_id = self._get_brand_attribute() + values = self.env['product.attribute.value'].search([('name', operator, value), ('attribute_id', 'in', brand_attribute_id.ids)]) + return [('attribute_line_ids.value_ids', 'in', values.ids)] + # Does not support other cases + return [] + + def _compute_dr_brand_value_id(self): + for product in self: + brand_lines = product.attribute_line_ids.filtered(lambda x: x.attribute_id.dr_is_brand) + product.dr_brand_value_id = self.env['product.attribute.value'] + if brand_lines: + product.dr_brand_value_id = brand_lines[0].value_ids[0] + + def _inverse_dr_brand_value_id(self): + brand_value_id = self.dr_brand_value_id + for product in self: + brand_lines = product.attribute_line_ids.filtered(lambda x: x.attribute_id.dr_is_brand) + brand_line = brand_lines and brand_lines[0] + if brand_line and brand_value_id: + brand_line.value_ids = brand_value_id + elif brand_line and not brand_value_id: + brand_line.unlink() + elif brand_value_id: + product.attribute_line_ids = [Command.create({ + 'attribute_id': brand_value_id.attribute_id.id, + 'value_ids': [Command.set(brand_value_id.ids)], + })] + + def _compute_dr_brand_attribute_ids(self): + attributes = self._get_brand_attribute() + for product in self: + product.dr_brand_attribute_ids = attributes + + def _get_brand_attribute(self): + return self.env['product.attribute'].search([('dr_is_brand', '=', True)]) + + @api.depends('product_variant_ids.free_qty') + def _compute_dr_free_qty(self): + res = self._compute_dr_free_qty_quantities_dict() + for template in self: + template.dr_free_qty = res[template.id]['free_qty'] + + def _compute_dr_free_qty_quantities_dict(self): + variants_available = { + p['id']: p for p in self.product_variant_ids.read(['free_qty']) + } + prod_available = {} + for template in self: + free_qty = 0 + for p in template.product_variant_ids: + free_qty += variants_available[p.id]['free_qty'] + prod_available[template.id] = { + 'free_qty': free_qty, + } + return prod_available + + def _search_dr_free_qty(self, operator, value): + domain = [('free_qty', operator, value)] + product_variant_query = self.env['product.product'].sudo()._search(domain) + return [('product_variant_ids', 'in', product_variant_query)] + + def _compute_dr_show_out_of_stock(self): + website = ir_http.get_request_website() + for product in self: + product.dr_show_out_of_stock = '' + if website and website._get_dr_theme_config('json_shop_product_item').get('show_stock_label') and not product.allow_out_of_stock_order and product.detailed_type == 'product': + free_qty = product.dr_free_qty + if product.show_availability and free_qty <= product.available_threshold: + product.dr_show_out_of_stock = int(free_qty) + if free_qty <= 0: + product.dr_show_out_of_stock = 'OUT_OF_STOCK' + + @api.model + def _search_get_detail(self, website, order, options): + res = super()._search_get_detail(website, order, options) + # Hide out of stock + if options.get('hide_out_of_stock'): + res['base_domain'].append(['|', '|', ('detailed_type', '!=', 'product'), ('allow_out_of_stock_order', '=', True), '&', ('dr_free_qty', '>', 0), ('allow_out_of_stock_order', '=', False)]) + # Tag + tag = options.get('tag') + if tag: + res['base_domain'].append([('product_tag_ids', 'in', [int(x) for x in tag])]) + # Rating + ratings = options.get('rating') + if ratings: + result = self.env['rating.rating'].sudo().read_group([('res_model', '=', 'product.template')], ['rating:avg'], groupby=['res_id'], lazy=False) + rating_product_ids = [] + for rating in ratings: + rating_product_ids.extend([item['res_id'] for item in result if item['rating'] >= int(rating)]) + if rating_product_ids: + res['base_domain'].append([('id', 'in', rating_product_ids)]) + else: + res['base_domain'].append([('id', 'in', [])]) + return res + + def _get_image_size_based_grid(self, columns, view_mode): + if view_mode == 'list': + return 'image_1024' + if columns <= 2: + return 'image_1024' + return 'image_512' + + def _get_product_preview_swatches(self, limit=3): + swatches = [] + for ptav in self.dr_ptav_ids: + if ptav.ptav_active and ptav.ptav_product_variant_ids: + vals = {'id': ptav.id, 'name': ptav.name, 'preview_image': '/web/image/product.product/%s' % ptav.ptav_product_variant_ids.ids[0]} + if ptav.dr_thumb_image: + vals.update({'type': 'image', 'value': '/web/image/product.template.attribute.value/%s/dr_thumb_image' % ptav.id}) + swatches.append(vals) + elif ptav.html_color: + vals.update({'type': 'color', 'value': ptav.html_color}) + swatches.append(vals) + return {'swatches': swatches[:limit], 'more': len(swatches) - limit} + + def _get_product_pricelist_offer(self): + website_id = self.env['website'].get_current_website() + if not website_id._dr_has_b2b_access(): + return False + pricelist_id = website_id.get_current_pricelist() + price_rule = pricelist_id._compute_price_rule(self, 1) + price_rule_id = price_rule.get(self.id)[1] + if price_rule_id: + rule = self.env['product.pricelist.item'].browse(price_rule_id) + if rule and rule.date_end: + return {'rule': rule, 'date_end': rule.date_end.strftime('%Y-%m-%d %H:%M:%S')} + return False + + def _get_combination_info(self, combination=False, product_id=False, add_qty=1, pricelist=False, parent_combination=False, only_template=False): + combination_info = super()._get_combination_info(combination=combination, product_id=product_id, add_qty=add_qty, pricelist=pricelist, parent_combination=parent_combination, only_template=only_template) + if combination_info['product_id']: + website = self.env['website'].get_current_website() + theme_id = website.sudo().theme_id + product_variant_id = self.env['product.product'].browse(combination_info['product_id']) + if website and theme_id and theme_id.name.startswith('theme_prime'): + # Render extra fields on product detail page + IrUiView = self.env['ir.ui.view'] + combination_info['tp_extra_fields'] = IrUiView._render_template('theme_prime.product_extra_fields', values={'website': website, 'product_variant': product_variant_id, 'product': product_variant_id.product_tmpl_id}) + # Hide price per UoM feature for B2B mode + if not website._dr_has_b2b_access(): + combination_info['base_unit_price'] = 0 + return combination_info diff --git a/odex25_donation/droggol_theme_common/models/res_config_settings.py b/odex25_donation/droggol_theme_common/models/res_config_settings.py new file mode 100644 index 000000000..80845421a --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/res_config_settings.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import api, fields, models, _ + + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + dr_pwa_activated = fields.Boolean(related='website_id.dr_pwa_activated', readonly=False) + dr_pwa_name = fields.Char(related='website_id.dr_pwa_name', readonly=False) + dr_pwa_short_name = fields.Char(related='website_id.dr_pwa_short_name', readonly=False) + dr_pwa_background_color = fields.Char(related='website_id.dr_pwa_background_color', readonly=False) + dr_pwa_theme_color = fields.Char(related='website_id.dr_pwa_theme_color', readonly=False) + dr_pwa_icon_192 = fields.Binary(related='website_id.dr_pwa_icon_192', readonly=False) + dr_pwa_icon_512 = fields.Binary(related='website_id.dr_pwa_icon_512', readonly=False) + dr_pwa_start_url = fields.Char(related='website_id.dr_pwa_start_url', readonly=False) + dr_pwa_shortcuts = fields.One2many(related='website_id.dr_pwa_shortcuts', readonly=False) + dr_pwa_offline_page = fields.Boolean(related='website_id.dr_pwa_offline_page', readonly=False) + + # This has been done in order to fix Odoo's broken behavior for theme customization. + # If database already have theme installed, it is impossible to have custom module later. + dr_has_custom_module = fields.Boolean(compute='_compute_dr_has_custom_module') + + @api.depends('website_id') + def _compute_dr_has_custom_module(self): + IrModuleModule = self.env['ir.module.module'] + themes = self._get_droggol_theme_list() + for setting in self: + setting.dr_has_custom_module = False + if setting.website_id and setting.website_id.theme_id and setting.website_id.theme_id.name in themes: + search_term = '%s_%%' % setting.website_id.theme_id.name + has_custom_apps = IrModuleModule.sudo().search([('name', '=ilike', search_term)]) + setting.dr_has_custom_module = bool(has_custom_apps) + + def dr_open_pwa_shortcuts(self): + self.website_id._force() + action = self.env.ref('droggol_theme_common.dr_pwa_shortcuts_action').read()[0] + action['domain'] = [('website_id', '=', self.website_id.id)] + action['context'] = {'default_website_id': self.website_id.id} + return action + + def dr_open_theme_custom_modules(self): + self.ensure_one() + themes = self._get_droggol_theme_list() + if self.website_id and self.website_id.theme_id and self.website_id.theme_id.name in themes: + search_term = '%s_%%' % self.website_id.theme_id.name + return { + 'name': _('Theme Customizations'), + 'view_mode': 'kanban,tree,form', + 'res_model': 'ir.module.module', + 'type': 'ir.actions.act_window', + 'domain': [('name', '=ilike', search_term)] + } + return True + + def _get_droggol_theme_list(self): + return ['theme_prime'] diff --git a/odex25_donation/droggol_theme_common/models/sale_order.py b/odex25_donation/droggol_theme_common/models/sale_order.py new file mode 100644 index 000000000..00b0b46cf --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/sale_order.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import models + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + def _cart_update(self, product_id=None, line_id=None, add_qty=0, set_qty=0, **kwargs): + values = super()._cart_update(product_id=product_id, line_id=line_id, add_qty=add_qty, set_qty=set_qty, **kwargs) + if self.website_id and not self.website_id._dr_has_b2b_access(): + for line in self.order_line: + new_val = super()._cart_update(product_id=line.product_id.id, line_id=line.id, add_qty=-1, set_qty=0, **kwargs) + values.update(new_val) + return values diff --git a/odex25_donation/droggol_theme_common/models/website.py b/odex25_donation/droggol_theme_common/models/website.py new file mode 100644 index 000000000..d793dbc97 --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/website.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import _, api, fields, models +from odoo.osv import expression +from odoo.tools.translate import html_translate + + +class Website(models.Model): + _inherit = 'website' + + dr_sale_special_offer = fields.Html('Sale Special Offer', sanitize_attributes=False, translate=html_translate, sanitize_form=False) + + dr_pwa_activated = fields.Boolean('PWA Activated') + dr_pwa_name = fields.Char('PWA Name') + dr_pwa_short_name = fields.Char('PWA Short Name') + dr_pwa_background_color = fields.Char('PWA Background Color', default='#000000') + dr_pwa_theme_color = fields.Char('PWA Theme Color', default='#FFFFFF') + dr_pwa_icon_192 = fields.Binary('PWA Icon 192x192') + dr_pwa_icon_512 = fields.Binary('PWA Icon 512x512') + dr_pwa_start_url = fields.Char('PWA Start URL', default='/shop') + dr_pwa_offline_page = fields.Boolean('PWA Offline Page') + dr_pwa_version = fields.Integer('PWA Version') + dr_pwa_shortcuts = fields.One2many('dr.pwa.shortcuts', 'website_id', string='Shortcuts') + + def _get_brands(self, domain=[], limit=None, order=None): + brand_attributes = self._get_brand_attributes().ids + domain = expression.AND([domain, [('attribute_id', 'in', brand_attributes)]]) + return self.env['product.attribute.value'].search(domain, limit=limit, order=order) + + def _dr_has_b2b_access(self, record=None): + if self._get_dr_theme_config('json_b2b_shop_config')['dr_enable_b2b']: + return not self.env.user.has_group('base.group_public') + return True + + def _get_brand_attributes(self): + """ This will preserver the sequence """ + current_website_products = self.env['product.template'].search(self.sale_product_domain()) + all_brand_attributes = self.env['product.template']._get_brand_attribute() + return self.env['product.template.attribute.line'].search([('product_tmpl_id', 'in', current_website_products.ids), ('attribute_id', 'in', all_brand_attributes.ids)]).mapped('attribute_id') + + def get_dr_theme_config(self): + return self._get_dr_theme_config() + + def _get_dr_theme_config(self, key=False): + """ See dr.theme.config for more info""" + self.ensure_one() + website_config = self.env['dr.theme.config']._get_all_config(self.id) + website_config['is_public_user'] = not self.env.user.has_group('website.group_website_restricted_editor') + website_config['has_sign_up'] = False + if website_config.get('json_b2b_shop_config')['dr_enable_b2b']: + website_config['has_sign_up'] = self.env['res.users']._get_signup_invitation_scope() == 'b2c' + if key: + return website_config.get(key) + return website_config + + def _get_pricelist_available(self, req, show_visible=False): + if self._get_dr_theme_config('json_b2b_shop_config')['dr_only_assigned_pricelist'] and not self.env.user.has_group('base.group_website_designer'): + return self.env.user.partner_id.property_product_pricelist + return super()._get_pricelist_available(req, show_visible=show_visible) + + @api.model + def get_theme_prime_shop_config(self): + Website = self.get_current_website() + return { + 'is_rating_active': Website.sudo().viewref('website_sale.product_comment').active, + 'is_buy_now_active': Website.sudo().viewref('website_sale.product_buy_now').active, + 'is_multiplier_active': Website.sudo().viewref('website_sale.product_quantity').active, + 'is_wishlist_active': Website.sudo().viewref('website_sale_wishlist.product_add_to_wishlist').active, + 'is_comparison_active': Website.sudo().viewref('website_sale_comparison.add_to_compare').active} + + def _get_website_category(self): + return self.env['product.public.category'].search([('website_id', 'in', [False, self.id]), ('parent_id', '=', False)]) + + def _get_theme_prime_rating_template(self, rating_avg, rating_count=False): + return self.env['ir.ui.view']._render_template('theme_prime.d_rating_widget_stars_static', values={ + 'rating_avg': rating_avg, + 'rating_count': rating_count, + }) + + @api.model + def get_theme_prime_bottom_bar_action_buttons(self): + # Add to cart, blog, checkout, pricelist, language, + return {'tp_home': {'name': _("Home"), 'url': '/', 'icon': 'fa fa-home'}, 'tp_search': {'name': _("Search"), 'icon': 'dri dri-search', 'action_class': 'tp-search-sidebar-action'}, 'tp_wishlist': {'name': _("Wishlist"), 'icon': 'dri dri-wishlist', 'url': '/shop/wishlist'}, 'tp_offer': {'name': _("Offers"), 'url': '/offers', 'icon': 'dri dri-bolt'}, 'tp_brands': {'name': _("Brands"), 'icon': 'dri dri-tag-l ', 'url': '/shop/all-brands'}, 'tp_category': {'name': _("Category"), 'icon': 'dri dri-category', 'action_class': 'tp-category-action'}, 'tp_orders': {'name': _("Orders"), 'icon': 'fa fa-file-text-o', 'url': '/my/orders'}, 'tp_cart': {'name': _("Cart"), 'icon': 'dri dri-cart', 'url': '/shop/cart'}, 'tp_lang_selector': {'name': _("Language and Pricelist selector")}} + + def _is_snippet_used(self, snippet_module, snippet_id, asset_version, asset_type, html_fields): + """ There is no versioning for all theme snippets (for the test case)""" + if snippet_module and snippet_module.startswith('theme_prime'): + return True + return super()._is_snippet_used(snippet_module, snippet_id, asset_version, asset_type, html_fields) + + +class WebsiteSaleExtraField(models.Model): + _inherit = 'website.sale.extra.field' + + dr_label = fields.Char('Display Label', translate=True) + field_id = fields.Many2one('ir.model.fields', domain=[('model_id.model', '=', 'product.template'), '|', ('ttype', 'in', ['char', 'binary']), ('name', 'in', ['public_categ_ids'])]) diff --git a/odex25_donation/droggol_theme_common/models/website_menu.py b/odex25_donation/droggol_theme_common/models/website_menu.py new file mode 100644 index 000000000..f3217a28d --- /dev/null +++ b/odex25_donation/droggol_theme_common/models/website_menu.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import api, fields, models + + +class WebsiteMenu(models.Model): + _inherit = 'website.menu' + + dr_menu_label_id = fields.Many2one('dr.website.menu.label', string='Label') + dr_highlight_menu = fields.Selection([('solid', 'Solid'), ('soft', 'Soft')], string='Highlight Menu') + + @api.model + def get_tree(self, website_id, menu_id=None): + result = super().get_tree(website_id, menu_id=menu_id) + for menu in result['children']: + menu['fields']['dr_highlight_menu'] = self.browse(menu['fields']['id']).dr_highlight_menu + return result diff --git a/odex25_donation/droggol_theme_common/security/ir.model.access.csv b/odex25_donation/droggol_theme_common/security/ir.model.access.csv new file mode 100644 index 000000000..995b85a21 --- /dev/null +++ b/odex25_donation/droggol_theme_common/security/ir.model.access.csv @@ -0,0 +1,13 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_dr_product_label_manager,dr.product.label.manager,model_dr_product_label,sales_team.group_sale_manager,1,1,1,1 +access_dr_product_label_public,dr.product.label.public,model_dr_product_label,,1,0,0,0 +access_dr_product_public_category_label_manager,dr.product.public.category.label.manager,model_dr_product_public_category_label,sales_team.group_sale_manager,1,1,1,1 +access_dr_product_public_category_label_public,dr.product.public.category.label.public,model_dr_product_public_category_label,,1,0,0,0 +access_dr_website_content_manager,dr.website.content.manager,model_dr_website_content,sales_team.group_sale_manager,1,1,1,1 +access_dr_website_content_public,dr.website.content.public,model_dr_website_content,,1,0,0,0 +access_dr_website_menu_label_designer,dr.website.menu.label.designer,model_dr_website_menu_label,website.group_website_designer,1,1,1,1 +access_dr_website_menu_label,dr.website.menu.label.public,model_dr_website_menu_label,,1,0,0,0 +access_dr_pwa_shortcuts_designer,dr.pwa.shortcuts.designer,model_dr_pwa_shortcuts,website.group_website_designer,1,1,1,1 +access_dr_pwa_shortcuts,dr.pwa.shortcuts.public,model_dr_pwa_shortcuts,,1,0,0,0 +access_dr_theme_config_designer,dr.theme.config.designer,model_dr_theme_config,website.group_website_designer,1,1,1,1 +access_dr_theme_config,dr.theme.config.public,model_dr_theme_config,,1,0,0,0 diff --git a/odex25_donation/droggol_theme_common/static/description/icon.png b/odex25_donation/droggol_theme_common/static/description/icon.png new file mode 100644 index 000000000..38fa9e9e9 Binary files /dev/null and b/odex25_donation/droggol_theme_common/static/description/icon.png differ diff --git a/odex25_donation/droggol_theme_common/static/description/images/bg.svg b/odex25_donation/droggol_theme_common/static/description/images/bg.svg new file mode 100644 index 000000000..63bb3d0b4 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/odex25_donation/droggol_theme_common/static/description/images/cards/cloud.svg b/odex25_donation/droggol_theme_common/static/description/images/cards/cloud.svg new file mode 100644 index 000000000..0e3e29faf --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/cards/cloud.svg @@ -0,0 +1,62 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/static/description/images/cards/code.svg b/odex25_donation/droggol_theme_common/static/description/images/cards/code.svg new file mode 100644 index 000000000..c297b08b6 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/cards/code.svg @@ -0,0 +1,67 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/static/description/images/cards/coffee.svg b/odex25_donation/droggol_theme_common/static/description/images/cards/coffee.svg new file mode 100644 index 000000000..cdc67ea70 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/cards/coffee.svg @@ -0,0 +1,62 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/static/description/images/cards/hat.svg b/odex25_donation/droggol_theme_common/static/description/images/cards/hat.svg new file mode 100644 index 000000000..587b1178e --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/cards/hat.svg @@ -0,0 +1,57 @@ + + + + + + + + image/svg+xml + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/static/description/images/cards/highlight.svg b/odex25_donation/droggol_theme_common/static/description/images/cards/highlight.svg new file mode 100644 index 000000000..1c212ca7d --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/cards/highlight.svg @@ -0,0 +1,57 @@ + + + + + + + + image/svg+xml + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/static/description/images/cards/layers.svg b/odex25_donation/droggol_theme_common/static/description/images/cards/layers.svg new file mode 100644 index 000000000..245eb10ea --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/cards/layers.svg @@ -0,0 +1,67 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/static/description/images/cards/pulse.svg b/odex25_donation/droggol_theme_common/static/description/images/cards/pulse.svg new file mode 100644 index 000000000..e5709e1dc --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/cards/pulse.svg @@ -0,0 +1,67 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/static/description/images/cards/store.svg b/odex25_donation/droggol_theme_common/static/description/images/cards/store.svg new file mode 100644 index 000000000..cd20ed3f9 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/cards/store.svg @@ -0,0 +1,77 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/static/description/images/cards/tablet.svg b/odex25_donation/droggol_theme_common/static/description/images/cards/tablet.svg new file mode 100644 index 000000000..e0c4d5b22 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/cards/tablet.svg @@ -0,0 +1,67 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/static/description/images/dots_bg.svg b/odex25_donation/droggol_theme_common/static/description/images/dots_bg.svg new file mode 100644 index 000000000..13800ff48 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/dots_bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/odex25_donation/droggol_theme_common/static/description/images/logo.svg b/odex25_donation/droggol_theme_common/static/description/images/logo.svg new file mode 100644 index 000000000..26fa19382 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/logo.svg @@ -0,0 +1,131 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/static/description/images/pages_bg.svg b/odex25_donation/droggol_theme_common/static/description/images/pages_bg.svg new file mode 100644 index 000000000..d92947c90 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/images/pages_bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/odex25_donation/droggol_theme_common/static/description/index.html b/odex25_donation/droggol_theme_common/static/description/index.html new file mode 100644 index 000000000..32801ca72 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/description/index.html @@ -0,0 +1,270 @@ +
+ +
+ +
+ + + +
+
+
+ +
+
+

Warning!

+
+ Droggol Theme common contains the basic setup for Theme Prime. This module does run without Droggol Theme (Theme Prime). The right way to purchase is to purchase Theme Prime.
+ + Explore Theme Prime + + + Still, Have a confusion? + +
+
+
+
+ +
+ +
+
+ + Our Services + +

Checkout Our Odoo Services

+

Great variety of Odoo services that help you to uplift your awesome + business.

+
+ + +
+
+
+
+ +
+

Development

+

+ Customize Odoo modules, integrate with external services, migration from the old version and more. +

+ + Read more + +
+
+
+
+
+
+
+ +
+

+ Implementation +

+

+ We understand your business needs and setup Odoo in the right way to fulfil your business needs. +

+ + Read more + +
+
+
+
+
+
+
+ +
+

+ Mobile Apps +

+

+ Android, iOS or Hybrid mobile applications which are fully integrated with Odoo instances. +

+ + Read more + +
+
+
+
+
+
+
+ +
+

+ Website & Themes +

+

+ Build eye-catching, blazing fast, configurable Odoo website with beautiful custom themes. +

+ + Read more + +
+
+
+
+
+
+
+ +
+

+ Support +

+

+ Odoo functional or technical support, bug-fixes, debugging, performance optimization, and more. +

+ + Read more + +
+
+
+
+
+
+
+ +
+

+ POS & IoT +

+

+ Customize Odoo POS for your retail shops and restaurants. Integrate it with hardware devices to + boost your productivity. +

+ + Read more + +
+
+
+
+
+
+
+ +
+

+ Deployment +

+

+ Deploy or optimize your Odoo instances on the cloud, Odoo.sh or on any other platform with top-notch + security. +

+ + Read more + +
+
+
+
+
+
+
+ +
+

+ Training +

+

+ Learn to develop or customize Odoo backend, website, JavaScript framework, sysadmin, themes and + more. +

+ + Read more + +
+
+
+
+
+
+
+ +
+

+ Hire Developers +

+

+ Hire full-stack Odoo developer to develop, maintain or configure Odoo applications on a regular + basis. +

+ + Read more + +
+
+
+ +
+ +
+ +
+ +
+
+

Let's have a talk.

+

Don't be a stranger. Our team is happy to answer all your questions.

+
+ +
+ + +
diff --git a/odex25_donation/droggol_theme_common/static/src/images/settings.png b/odex25_donation/droggol_theme_common/static/src/images/settings.png new file mode 100644 index 000000000..005aaed3a Binary files /dev/null and b/odex25_donation/droggol_theme_common/static/src/images/settings.png differ diff --git a/odex25_donation/droggol_theme_common/static/src/js/components/theme_config.js b/odex25_donation/droggol_theme_common/static/src/js/components/theme_config.js new file mode 100644 index 000000000..ad86cdb94 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/src/js/components/theme_config.js @@ -0,0 +1,273 @@ +/** @odoo-module **/ + +import { WebsiteDialog } from '@website/components/dialog/dialog'; +import { evaluateExpr } from "@web/core/py_js/py"; + +const { Component, useState, onWillStart, onWillUpdateProps, toRaw } = owl; +import { useService } from '@web/core/utils/hooks'; +import { useCore } from '@droggol_theme_common/js/hooks'; + +import { _t } from 'web.core'; + + +export class AbstractThemeOption extends Component { + setup() { + this.key = this.props.key; + onWillUpdateProps(nextProps => { + this.updateVal(nextProps); + }); + } + updateVal (props) { + if (props.visibilityExpr) { + props['visibility'] = evaluateExpr(props.visibilityExpr, props.source) + } + this.env.updateConfigValue(this.key, props.value) + } + updateSource (value) { + this.env.updateSource(this.key, value) + } +} + +export class ThemeOptionTitle extends AbstractThemeOption {} +ThemeOptionTitle.template = 'theme_config.ThemeOptionTitle'; + +export class ThemeOptionRadio extends AbstractThemeOption {} +ThemeOptionRadio.template = 'theme_config.ThemeOptionRadio'; + +export class ThemeOptionSelection extends AbstractThemeOption {} +ThemeOptionSelection.template = 'theme_config.Selection'; + +export class ThemeOptionCheckbox extends AbstractThemeOption {} +ThemeOptionCheckbox.template = 'theme_config.Checkbox'; + +export class ThemeOptionCardBtnCheckbox extends AbstractThemeOption {} +ThemeOptionCardBtnCheckbox.template = 'theme_config.BtnCheckbox'; + +export class ThemeOptionNumber extends AbstractThemeOption {} +ThemeOptionNumber.template = 'theme_config.Number'; + +export class ThemeOptionChar extends AbstractThemeOption {} +ThemeOptionChar.template = 'theme_config.Char'; + +export class ThemeOptionJson extends AbstractThemeOption { + setup() { + super.setup(); + this.updatedValue = this.props.value; + this._coreProps = { + updateConfigValue: this.updateConfigValue.bind(this), + updateSource: this.updateSource.bind(this), + }; + useCore({subMode: true}); + } + prepareProps (self_props, sub_props) { + var props = sub_props || {}; + props['visibility'] = true; + props['source'] = self_props.source[self_props.key]; + if (props.visibilityExpr) { + props['visibility'] = evaluateExpr(props.visibilityExpr, props['source']) + } + props['value'] = props['source'][sub_props.key] || false; + return props; + } + updateConfigValue (key, value) { + var rawValue = toRaw(this.updatedValue); + rawValue[key] = value; + this.env.updateConfigValue(this.key, rawValue); + } + updateSource (key, value) { + this.props.source[this.key][key] = value; + this.env.updateSource(this.key, this.props.source[this.key]); + } +} +ThemeOptionJson.template = 'theme_config.JSON'; + +export class ThemeOptionBottomBar extends AbstractThemeOption { + setup() { + super.setup(); + this.orm = useService("orm"); + this.state = useState({ + 'actions': this.props.value + }); + onWillStart(async () => { + this.allButtons = await this.orm.call('website', 'get_theme_prime_bottom_bar_action_buttons'); + }); + } + removeAction (action) { + const index = this.state.actions.indexOf(action); + this.state.actions.splice(index, 1); + this.updateSource(this.state.actions); + } + addAction (action) { + this.state.actions.push(action); + this.updateSource(this.state.actions); + } +} +ThemeOptionBottomBar.template = 'theme_config.BottomBar'; + + +export class ThemeConfigDialog extends Component { + setup() { + this.orm = useService('orm'); + this.website = useService('website'); + this.title = this.env._t("Theme Configuration"); + this.primaryTitle = this.env._t("Save"); + this.size = 'md'; + this.updatedValue = {}; + this.source = useState({}); + this._coreProps = { + updateConfigValue: this.updateConfigValue.bind(this), + updateSource: this.updateSource.bind(this) + }; + onWillStart(async () => { + var source = await this.orm.call("website", "get_dr_theme_config", [this.website.currentWebsite.id]); + for (var key in source) { + this.source[key] = source[key]; + } + }); + useCore({}); + } + + async saveConfig() { + await this.orm.call("dr.theme.config", "save_config", [[], this.website.currentWebsite.id, this.updatedValue]); + window.location.reload(); + } + + get _tabInfo() { + return [{ + name: 'general', + icon: 'fa fa-sliders', + label: _t('General'), + components: [ + { props: { title: _t('Search'), subtitle: _t('Tweak search behavior for your website.'), _classes: 'mt-0'}, componentRef: ThemeOptionTitle }, + { props: { key: 'json_product_search', components: [ + { props: { key: 'advance_search', label: _t('Enable advance search')}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'search_category', label: _t('Categories'), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'search_attribute', label: _t('Smart Autocomplete'), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'search_suggestion', label: _t('Smart Suggestion'), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'search_fuzzy', label: _t('Fuzzy search'), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'search_max_product', label: _t('Products limit'), tooltip: _("Max 5"), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionNumber }, + { props: { key: 'search_limit', label: _t('Result Limit'), tooltip: _("Min 5 and Max 10"), visibilityExpr: 'advance_search'}, componentRef: ThemeOptionNumber }, + ]}, componentRef: ThemeOptionJson}, + { props: { key: 'cart_flow_title', title: _t('Cart Flow'), subtitle: _t('You can change how products are being added in cart.')}, key: 'cart_flow_title', componentRef: ThemeOptionTitle}, + { props: { key: 'cart_flow', selection: [['default', 'Default'], ['notification', 'Notification'], ['dialog', 'Dialog'], ['side_cart', 'Open Cart Sidebar']]}, componentRef: ThemeOptionRadio}, + { props: { key: 'brand_title', title: _t('Brand Page')}, componentRef: ThemeOptionTitle}, + { props: { key: 'json_brands_page', components: [ + { props: { key: 'disable_brands_grouping', label: _t('Disable grouping of brands')}, componentRef: ThemeOptionCheckbox } + ]}, componentRef: ThemeOptionJson}, + { props: { key: 'lang_title', title: _t('Language/Pricelist Selector')}, componentRef: ThemeOptionTitle}, + { props: { key: 'json_general_language_pricelist_selector', components: [ + { props: { key: 'hide_country_flag', label: _t('Hide country flag')}, componentRef: ThemeOptionCheckbox } + ]}, componentRef: ThemeOptionJson}, + { props: { title: _t('B2b Configuration'), subtitle: _t('Tweak your shop behavior.')}, componentRef: ThemeOptionTitle }, + { props: { key: 'json_b2b_shop_config', components: [{ props: { key: 'dr_enable_b2b', label: _t('B2B Mode'), tooltip: _("This option will hide product price for public users and don't allow them to place an order") }, componentRef: ThemeOptionCheckbox }, { props: { key: 'dr_only_assigned_pricelist', label: _t('Pricelist per customer'), tooltip: _("After enabling this option user will only see assigned pricelist to their contact record.") }, componentRef: ThemeOptionCheckbox }]}, componentRef: ThemeOptionJson}, + ] + }, { + name: 'shop', + icon: 'fa fa-shopping-cart', + label: _t('Shop'), + components: [ + { props: { title: _t('Shop'), subtitle: _t('Shop page main layout.'), _classes: 'mt-0' }, componentRef: ThemeOptionTitle }, + { props: { key: 'json_shop_layout', components: [ + { props: { key: 'layout', label: _t('Layout'), selection: [['prime', 'Prime'], ['default', 'Default']]}, componentRef: ThemeOptionSelection }, + { props: { key: 'show_view_switcher', label: _t('Show view switcher'), visibilityExpr: "layout == 'prime'"}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'default_view_mode', label: _t('Default view mode'), selection: [['grid', 'Grid'], ['list', 'List']], visibilityExpr: "layout == 'prime'"}, componentRef: ThemeOptionSelection }, + { props: { key: 'load_more_products', label: _t('Behavior of load more products'), selection: [['pager', 'Pager'], ['button', 'Load More Button'], ['scroll', 'Infinite Scroll']], visibilityExpr: "layout == 'prime'"}, componentRef: ThemeOptionSelection }, + ], visibilityKey: 'enable'}, componentRef: ThemeOptionJson}, + { props: { title: _t('Category Pills'), subtitle: _t('Show product category pills on top of the shop page.'), visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionTitle }, + { props: { key: 'json_shop_category_pills', components: [ + { props: { key: 'active', label: _t('Enable category pills')}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'style', label: _t('Style'), selection: [['1', 'Card'], ['2', 'Text'], ['3', 'Image + Text'], ['4', 'Image + Text (Rounded)'], ['5', 'Image Only']], visibilityExpr: 'active'}, componentRef: ThemeOptionSelection }, + { props: { key: 'show_child_categories', label: _t('Show child categories pills of active category'), visibilityExpr: 'active'}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'hide_in_desktop', label: _t('Hide in desktop device'), visibilityExpr: 'active'}, componentRef: ThemeOptionCheckbox }, + ], visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionJson}, + { props: { title: _t('Shop Filter'), subtitle: _t('Tweak filters behavior on shop.'), visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionTitle }, + { props: { key: 'json_shop_filters', components: [ + { props: { key: 'lazy_method', label: _t('Apply filters with lazy method') }, componentRef: ThemeOptionCheckbox }, + { props: { key: 'filter_style', label: _t('Filter Style'), selection: [['1', 'Clean'], ['2', 'Underline'], ['3', 'Card'], ['4', 'Bordered'], ['5', 'Boxed']]}, componentRef: ThemeOptionSelection }, + { props: { key: 'show_in_sidebar', label: _t('Show filters in sidebar')}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'filter_position', label: _t('Filter Position'), selection: [['left', 'Left'], ['right', 'Right']], visibilityExpr: "show_in_sidebar == false"}, componentRef: ThemeOptionSelection }, + { props: { key: 'collapsible_category', label: _t('Collapsible category')}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'collapsible_attribute', label: _t('Collapsible attributes')}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'show_category_count', label: _t('Show category count')}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'show_attribute_count', label: _t('Show attribute count') }, componentRef: ThemeOptionCheckbox }, + { props: { key: 'hide_extra_attrib_value', label: _t('Hide extra attributes'), tooltip: _("Hide attribute value if it is not matched with any product") }, componentRef: ThemeOptionCheckbox }, + { props: { key: 'show_rating_filter', label: _t('Show rating filter'), tooltip: _("To show rating filter, First you have to activate customers 'Rating' option in product detail page.")}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'show_availability_filter', label: _t('Show availability filter'), tooltip: _("If you have large number of products this option may affect performance.")}, componentRef: ThemeOptionCheckbox }, + ], visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionJson}, + { props: { title: _t('Product Card'), subtitle: _t('Configure actions and style of product card.'), visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionTitle }, + { props: { key: 'json_shop_product_item', components: [ + { props: { key: 'style', label: _t('Style'), selection: [['1', 'Square'], ['2', 'Rounded']]}, componentRef: ThemeOptionSelection }, + { props: { key: 'image_size', label: _t('Image Size'), selection: [['default', 'Default (1/1)'], ['landscape', 'Landscape (4/3)'], ['portrait', 'Portrait (4/5)'], ['vertical', 'Vertical (2/3)']]}, componentRef: ThemeOptionSelection }, + { props: { key: 'image_fill', label: _t('Image Fill'), selection: [['contain', 'Contain'], ['cover', 'Cover'], ['fill', 'Fill']]}, componentRef: ThemeOptionSelection }, + { props: { title: _t('Product Card Actions'), subtitle: _t('Configure action buttons of product card in shop page.')}, componentRef: ThemeOptionTitle }, + { props: { key: 'show_add_to_cart', icon: 'fa fa-shopping-cart', label: _t('Show add to cart')}, componentRef: ThemeOptionCardBtnCheckbox }, + { props: { key: 'show_wishlist', icon: 'fa fa-heart', label: _t('Show wishlist')}, componentRef: ThemeOptionCardBtnCheckbox }, + { props: { key: 'show_compare', icon: 'fa fa-retweet', label: _t('Show compare')}, componentRef: ThemeOptionCardBtnCheckbox }, + { props: { key: 'show_quick_view', icon: 'fa fa-eye', label: _t('Show quick view')}, componentRef: ThemeOptionCardBtnCheckbox }, + { props: { key: 'show_similar_products', icon: 'fa fa-clone', label: _t('Show similar products')}, componentRef: ThemeOptionCardBtnCheckbox }, + { props: { key: 'show_product_preview_swatches', icon: 'fa fa-adjust', label: _t('Show product preview swatches')}, componentRef: ThemeOptionCardBtnCheckbox }, + { props: { key: 'show_rating', icon: 'fa fa-star', label: _t('Show rating'), tooltip: _("To show rating, First you have to activate customers 'Rating' option in product detail page.")}, componentRef: ThemeOptionCardBtnCheckbox }, + { props: { key: 'show_stock_label', icon: 'fa fa-tag', label: _t('Show stock label')}, componentRef: ThemeOptionCardBtnCheckbox }, + ], visibilityExpr: "json_shop_layout.layout == 'prime'"}, componentRef: ThemeOptionJson}, + ] + }, { + name: 'product_detail', + icon: 'fa fa-cube', + label: _t('Product Detail'), + components: [ + { props: { title: _t('Zoom Product Images'), subtitle: _t('Zoom product images in product detail page and quick view.'), _classes: 'mt-0' }, componentRef: ThemeOptionTitle }, + { props: { key: 'json_zoom', components: [ + { props: { key: 'zoom_enabled', label: _t('Enable zoom')}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'zoom_factor', label: _t('Zoom factor'), visibilityExpr: 'zoom_enabled'}, componentRef: ThemeOptionNumber }, + ], visibilityKey: 'zoom_enabled'}, componentRef: ThemeOptionJson}, + { props: { title: _t('Sticky Add to Cart'), subtitle: _t("Allows users to follow up product's Add to Cart button until bottom scroll reached."), }, componentRef: ThemeOptionTitle }, + { props: { key: 'bool_sticky_add_to_cart', 'label': _t('Enable sticky add to cart') }, componentRef: ThemeOptionCheckbox}, + { props: { title: _t('Product Offers'), subtitle: _t("You will be able to add offers on product and show details in dialog.")}, componentRef: ThemeOptionTitle }, + { props: { key: 'bool_product_offers', 'label': _t('Enable product offers') }, componentRef: ThemeOptionCheckbox}, + { props: { title: _t('General')}, componentRef: ThemeOptionTitle }, + { props: { key: 'bool_show_products_nav', 'label': _t('Product Navigation'), tooltip: _t("Shows button to see next, previous products based on product sequence.") }, componentRef: ThemeOptionCheckbox}, + ] + }, { + name: 'mobile', + icon: 'fa fa-mobile', + label: _t('Mobile'), + components: [ + { props: { title: _t('Sidebar'), subtitle: _t('You can change behaviour of sidebars.'), _classes: 'mt-0' }, componentRef: ThemeOptionTitle }, + { props: { key: 'json_sidebar_config', components: [ + { props: { key: 'category_sidebar_style', label: _t('Category sidebar style'), selection: [['1', 'Text'], ['2', 'Image + Text'], ['3', 'Cover']]}, componentRef: ThemeOptionSelection }, + { props: { key: 'category_sidebar_show_count', label: _t('Show product count in category sidebar') }, componentRef: ThemeOptionCheckbox }, + { props: { key: 'menu_sidebar_show_category', label: _t('Show category link in menu sidebar') }, componentRef: ThemeOptionCheckbox }, + ]}, componentRef: ThemeOptionJson}, + { props: { title: _t('Bottombar'), subtitle: _t("Bottom bar allow movement between primary destinations on the website.")}, componentRef: ThemeOptionTitle }, + { props: { key: 'json_bottom_bar', components: [ + { props: { key: 'show_bottom_bar', label: _t('Show Bottombar')}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'show_bottom_bar_on_scroll', label: _t('Show Bottombar On Scroll'), visibilityExpr: 'show_bottom_bar'}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'filters', label: _t('Show sort and filter button on shop'), visibilityExpr: 'show_bottom_bar'}, componentRef: ThemeOptionCheckbox }, + { props: { key: 'actions', label: _t('Buttombar Buttons'), visibilityExpr: 'show_bottom_bar'}, componentRef: ThemeOptionBottomBar }, + ], visibilityKey: 'show_bottom_bar'}, componentRef: ThemeOptionJson}, + ] + } + ];} + prepareProps (props) { + props = props || {}; + props['source'] = this.source; + props['visibility'] = true; + if (props.key) { + props['value'] = this.source[props.key] || false; + } + if (props.visibilityExpr) { + props['visibility'] = evaluateExpr(props.visibilityExpr, this.source) + } + return props; + } + + updateConfigValue (key, value) { + this.updatedValue[key] = value; + } + updateSource (key, value) { + this.source[key] = value; + } +} + +ThemeConfigDialog.template = 'droggol_theme_common.ThemeConfigDialog'; +ThemeConfigDialog.components = { WebsiteDialog }; diff --git a/odex25_donation/droggol_theme_common/static/src/js/components/theme_config.scss b/odex25_donation/droggol_theme_common/static/src/js/components/theme_config.scss new file mode 100644 index 000000000..b88bc3f54 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/src/js/components/theme_config.scss @@ -0,0 +1,75 @@ +$tp-setting-color: #0080ff; + +.tp_config_dialog { + border-radius: 16px; + .text-primary { + color: $tp-setting-color !important; + } + .bg-tpc-primary { + background-color: $tp-setting-color; + color: #fff; + } + .bg-tpc-primary-dark { + background-color: darken($tp-setting-color, 10%); + color: #fff; + } + .tp-cp { + cursor: pointer; + } + .pe-24 { + padding-right: 24px !important; + } + header { + h4, .btn-close{ + display: none; + } + } + .tp-setting-tab{ + font-weight: bold; + border-radius: 6px; + letter-spacing: 1px; + color: #000; + &.active { + background-color: rgba($tp-setting-color, 0.15); + color: $tp-setting-color; + } + } + .o_switch { + input + span { + padding-left: 4px; + padding-right: 2px; + width: 37px; + height: 21px; + background: #c1ccdd !important; + &:after { + margin-top: 1px; + display: inline-block; + } + } + input:checked + span { + background: #06bb72 !important; + // background: $tp-setting-color !important; + } + } + + .tp-setting-bg { + background-color: #e7f1ff; + border-radius: 10px; + } + + .form-check-input:checked { + background-color: $tp-setting-color; + border-color: $tp-setting-color; + } + .btn-outline-primary { + border-color: $tp-setting-color; + color: $tp-setting-color; + &:hover { + background-color: #c1ccdd; + } + } + .btn-check:checked + .btn-outline-primary { + background-color: $tp-setting-color; + border-color: $tp-setting-color; + } +} \ No newline at end of file diff --git a/odex25_donation/droggol_theme_common/static/src/js/components/theme_config.xml b/odex25_donation/droggol_theme_common/static/src/js/components/theme_config.xml new file mode 100644 index 000000000..c5d6dfd25 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/src/js/components/theme_config.xml @@ -0,0 +1,181 @@ + + + + + + +
+
+ +
+
+ +
+
+
+ + + User Guide + + +
+
+
+ +
+ + + +
+
+
+
+ +
+ +
+
+ + + +
+ +
+

+ +

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+ + +
+
+ + +
+
+
+ + + + + + + + + +
+ + +
+
+
+ + + +
+ + +
+
+
+ + + + + + + + + + + +
+ + + + + + +
+
+ + + + + +
+
+
+ + + + + + +
\ No newline at end of file diff --git a/odex25_donation/droggol_theme_common/static/src/js/hooks.js b/odex25_donation/droggol_theme_common/static/src/js/hooks.js new file mode 100644 index 000000000..97bb9d587 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/src/js/hooks.js @@ -0,0 +1,21 @@ +/** @odoo-module **/ + +import { useComponent, useChildSubEnv} from "@odoo/owl"; + +// We add here a custom hook +function extendUseCore(cc, newCore, subMode) { + if (!subMode) { + const currentCore = Object.create(cc.env); + const newCoreDescriptors = Object.getOwnPropertyDescriptors(newCore); + cc.env = Object.freeze(Object.defineProperties(currentCore, newCoreDescriptors)); + } + useChildSubEnv(newCore) +} + +export function useCore({core = false, subMode = false}) { + const cc = useComponent(); + core = core || cc._coreProps; + if (core) { + extendUseCore(cc, core, subMode) + } +} \ No newline at end of file diff --git a/odex25_donation/droggol_theme_common/static/src/js/navbar/navbar.js b/odex25_donation/droggol_theme_common/static/src/js/navbar/navbar.js new file mode 100644 index 000000000..17c205937 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/src/js/navbar/navbar.js @@ -0,0 +1,10 @@ +/** @odoo-module **/ + +import { registry } from "@web/core/registry"; +import { ThemeConfigDialog } from '../components/theme_config'; + +registry.category('website_custom_menus').add('droggol_theme_common.menu_theme_prime_config', { + Component: ThemeConfigDialog, + isDisplayed: (env) => !!env.services.website.currentWebsite + && env.services.website.isDesigner +}); diff --git a/odex25_donation/droggol_theme_common/static/src/scss/variants.scss b/odex25_donation/droggol_theme_common/static/src/scss/variants.scss new file mode 100644 index 000000000..74ca788ae --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/src/scss/variants.scss @@ -0,0 +1,59 @@ +//------------------------------------------------------------------------------ +// Variants +//------------------------------------------------------------------------------ +.dr-attribute-info-btn { + display: none; +} +.dr-attribute-item { + .dr-value-item { + &.circle { + padding: 0; + height: 38px; + width: 38px; + line-height: 38px; + text-align: center; + border-radius: 50%; + } + &.square { + padding: 6px 12px; + border-radius: $border-radius; + } + &.circle, &.square { + background-color: o-color('white'); + border: 1px solid o-color('300'); + transition: 0.2s; + font-weight: $font-weight-normal; + cursor: pointer; + &:hover { + border-color: o-color('primary'); + color: o-color('primary'); + } + } + &.image { + margin-right: 0.4rem; + border-width: 0; + transition: 0.2s; + cursor: pointer; + box-shadow: 0px 0px 0px 2px o-color('300'); + &:hover { + box-shadow: 0px 0px 0px 2px o-color('primary'); + } + img { + padding: 2px; + object-fit: contain; + height: 40px; + width: 40px; + } + } + } + input:checked ~ .radio_input_value .dr-value-item { + &.circle, &.square { + background-color: o-color('primary'); + border-color: o-color('primary'); + color: color-contrast(o-color('primary')); + } + &.image { + box-shadow: 0px 0px 0px 2px o-color('primary'); + } + } +} diff --git a/odex25_donation/droggol_theme_common/static/src/snippets/s_mega_menu_prime_3/000.scss b/odex25_donation/droggol_theme_common/static/src/snippets/s_mega_menu_prime_3/000.scss new file mode 100644 index 000000000..940c0b34d --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/src/snippets/s_mega_menu_prime_3/000.scss @@ -0,0 +1,11 @@ +.s_mega_menu_prime_3 .s_badge { + margin: 0; + margin-left: 0.4rem; + padding: 0.4em 0.6em; + font-size: 0.66rem; + border-radius: 3px; + padding-top: 5px; + i { + margin-right: 0.3rem; + } +} diff --git a/odex25_donation/droggol_theme_common/static/src/snippets/s_mega_menu_prime_6/000.scss b/odex25_donation/droggol_theme_common/static/src/snippets/s_mega_menu_prime_6/000.scss new file mode 100644 index 000000000..cbabba9e5 --- /dev/null +++ b/odex25_donation/droggol_theme_common/static/src/snippets/s_mega_menu_prime_6/000.scss @@ -0,0 +1,7 @@ +.s_mega_menu_prime_6 .tp-banner-block { + min-height: 400px; + .tp-banner-text { + @include o-position-absolute($right: 18px, $bottom: 20px, $left: 18px); + padding: 1rem; + } +} diff --git a/odex25_donation/droggol_theme_common/views/backend/category_label.xml b/odex25_donation/droggol_theme_common/views/backend/category_label.xml new file mode 100644 index 000000000..271d9c338 --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/category_label.xml @@ -0,0 +1,25 @@ + + + + + dr.product.public.category.label.view.tree + dr.product.public.category.label + + + + + + + + + + + Category Labels + ir.actions.act_window + dr.product.public.category.label + tree,form + + + + + diff --git a/odex25_donation/droggol_theme_common/views/backend/dr_theme_config.xml b/odex25_donation/droggol_theme_common/views/backend/dr_theme_config.xml new file mode 100644 index 000000000..33c6ad490 --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/dr_theme_config.xml @@ -0,0 +1,31 @@ + + + + + dr.theme.config.view.tree + dr.theme.config + + + + + + + + + + + Droggol Theme Config + dr.theme.config + tree,form + + + + + + + diff --git a/odex25_donation/droggol_theme_common/views/backend/dr_website_content.xml b/odex25_donation/droggol_theme_common/views/backend/dr_website_content.xml new file mode 100644 index 000000000..f80b34bcd --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/dr_website_content.xml @@ -0,0 +1,88 @@ + + + + + dr.website.content.view.form + dr.website.content + +
+ +
+ +
+
+
+ + + + + + + + +

You can find icon at FontAwesome.

+ + + + + + + + +
+
+
+
+ + + dr.website.content.view.tree + dr.website.content + + + + + + + + + + + dr.website.content.view.search + dr.website.content + + + + + + + + + + + + + Contents + ir.actions.act_window + dr.website.content + tree,form + {'search_default_group_by_content_type': True} + + + + +
diff --git a/odex25_donation/droggol_theme_common/views/backend/menu_label.xml b/odex25_donation/droggol_theme_common/views/backend/menu_label.xml new file mode 100644 index 000000000..bf8641c9f --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/menu_label.xml @@ -0,0 +1,30 @@ + + + + + dr.website.menu.label.view.tree + dr.website.menu.label + + + + + + + + + + + Menu Labels + ir.actions.act_window + dr.website.menu.label + tree,form + + + + + diff --git a/odex25_donation/droggol_theme_common/views/backend/product_attribute.xml b/odex25_donation/droggol_theme_common/views/backend/product_attribute.xml new file mode 100644 index 000000000..ba5c7e477 --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/product_attribute.xml @@ -0,0 +1,46 @@ + + + + + product.attribute.view.form.inherit + product.attribute + + + + + + + + + + + + + + + + + + + + + + + + + {'column_invisible': [('parent.dr_is_brand', '=', True)]} + + + + + + product.template.attribute.value.view.form.inherit + product.template.attribute.value + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/views/backend/product_brand.xml b/odex25_donation/droggol_theme_common/views/backend/product_brand.xml new file mode 100644 index 000000000..78a4147f7 --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/product_brand.xml @@ -0,0 +1,68 @@ + + + + + product.attribute.value.view.form + product.attribute.value + +
+ + +
+
+ + + + + +
+
+
+
+ + + product.attribute.value.view.tree + product.attribute.value + + + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + + dr.product.label.view.tree + dr.product.label + + + + + + + + + + + + dr.product.label.view.search + dr.product.label + + + + + + + + + + + + + Labels + ir.actions.act_window + dr.product.label + tree,form + + + + + diff --git a/odex25_donation/droggol_theme_common/views/backend/product_pricelist.xml b/odex25_donation/droggol_theme_common/views/backend/product_pricelist.xml new file mode 100644 index 000000000..659c7d484 --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/product_pricelist.xml @@ -0,0 +1,28 @@ + + + + + product.pricelist.item.form.inherit.droggol.theme.common + product.pricelist.item + + + + + + + + + + + product.pricelist.form.inherit.droggol.theme.common + product.pricelist + + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/views/backend/product_template.xml b/odex25_donation/droggol_theme_common/views/backend/product_template.xml new file mode 100644 index 000000000..a77f9102e --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/product_template.xml @@ -0,0 +1,46 @@ + + + + + product.template.form.inherit.droggol.theme.common + product.template + + + + + + + + + + + + + + + + + + + product.template.only.form.inherit.droggol.theme.common + product.template + + + + + + + + + + product.template.view.tree.inherit.droggol.theme.common + product.template + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/views/backend/pwa_shortcuts.xml b/odex25_donation/droggol_theme_common/views/backend/pwa_shortcuts.xml new file mode 100644 index 000000000..11d89a8b3 --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/pwa_shortcuts.xml @@ -0,0 +1,53 @@ + + + + + dr.pwa.shortcuts.view.form + dr.pwa.shortcuts + +
+ + + +
+
+ + + + + + + + + + + +
+
+
+
+ + + dr.pwa.shortcuts.view.tree + dr.pwa.shortcuts + + + + + + + + + PWA Shortcuts + ir.actions.act_window + dr.pwa.shortcuts + tree,form + + +
diff --git a/odex25_donation/droggol_theme_common/views/backend/res_config_settings.xml b/odex25_donation/droggol_theme_common/views/backend/res_config_settings.xml new file mode 100644 index 000000000..9fe75225e --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/res_config_settings.xml @@ -0,0 +1,130 @@ + + + + + res.config.settings.view.form.inherit.droggol.theme.common + res.config.settings + + + +
+
+
+
+ +
+
+
+
+ + + + + + diff --git a/odex25_donation/droggol_theme_common/views/backend/website.xml b/odex25_donation/droggol_theme_common/views/backend/website.xml new file mode 100644 index 000000000..51275c777 --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/website.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + website_sale.website.form + website + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/views/backend/website_menu.xml b/odex25_donation/droggol_theme_common/views/backend/website_menu.xml new file mode 100644 index 000000000..65c1cdb4e --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/backend/website_menu.xml @@ -0,0 +1,28 @@ + + + + + website.menu.view.form.inherit + website.menu + + + + + + + + + + + website.menu.tree.inherit.droggol.theme.common + website.menu + + + + + + + + + + diff --git a/odex25_donation/droggol_theme_common/views/snippets/s_mega_menu.xml b/odex25_donation/droggol_theme_common/views/snippets/s_mega_menu.xml new file mode 100644 index 000000000..05c3a29d8 --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/snippets/s_mega_menu.xml @@ -0,0 +1,513 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Mega Menu Prime 3 000 SCSS + web.assets_frontend + droggol_theme_common/static/src/snippets/s_mega_menu_prime_3/000.scss + + + + Mega Menu Prime 6 000 SCSS + web.assets_frontend + droggol_theme_common/static/src/snippets/s_mega_menu_prime_6/000.scss + + + diff --git a/odex25_donation/droggol_theme_common/views/templates.xml b/odex25_donation/droggol_theme_common/views/templates.xml new file mode 100644 index 000000000..dd6d664c3 --- /dev/null +++ b/odex25_donation/droggol_theme_common/views/templates.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + diff --git a/odex25_donation/ensan_campaign/__init__.py b/odex25_donation/ensan_campaign/__init__.py new file mode 100644 index 000000000..aa439e710 --- /dev/null +++ b/odex25_donation/ensan_campaign/__init__.py @@ -0,0 +1,3 @@ +from . import models +from . import controller +from . import wizard \ No newline at end of file diff --git a/odex25_donation/ensan_campaign/__manifest__.py b/odex25_donation/ensan_campaign/__manifest__.py new file mode 100644 index 000000000..487e03ec4 --- /dev/null +++ b/odex25_donation/ensan_campaign/__manifest__.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +{ + 'name': 'ensan campaign', + 'version': '1.0', + 'summary': 'ensan campaign', + + 'description': """ +ensan campaign +==================== +create new campaign """, + 'depends': ['website','website_sale'], + 'assets': { + 'web.assets_frontend': ['ensan_campaign/static/src/css/stylesheet.css'] + + }, + 'data': [ + 'security/ir.model.access.csv', + 'data/campaign_sms.xml', + #'wizard/campaign_report.xml', + 'views/campaign_menu.xml', + 'views/campaign_campaign_views.xml', + #'report/campaign_report.xml', + + ], + "images": ['kafala.png','111.png', +'footer.png', +'header.png', +'header2.png'], + +} diff --git a/odex25_donation/ensan_campaign/controller/__init__.py b/odex25_donation/ensan_campaign/controller/__init__.py new file mode 100644 index 000000000..72f4562d7 --- /dev/null +++ b/odex25_donation/ensan_campaign/controller/__init__.py @@ -0,0 +1 @@ +from . import controller \ No newline at end of file diff --git a/odex25_donation/ensan_campaign/controller/controller.py b/odex25_donation/ensan_campaign/controller/controller.py new file mode 100644 index 000000000..5f02764d8 --- /dev/null +++ b/odex25_donation/ensan_campaign/controller/controller.py @@ -0,0 +1,72 @@ + + +# -*- coding: utf-8 -*- +from odoo import http +from odoo.http import request + + +class PartnerForm(http.Controller): + # mention class name + @http.route(['/campaign/view'], type='http', auth="user", website=True) + + # mention a url for redirection. + # define the type of controllers which in this case is ‘http’. + # mention the authentication to be either public or user. + def campaign_view(self, **post): + # create method + # this will load the form webpage + name = 'ss gamal eh' + name =' '.join(name.split()).replace(' ','%20') + # name = name.replace(' ', '%20') + # name = name.replace(' ', '%20') + print(name) + campaigns = request.env['campaign.campaign'].search([('state','=','بإنتظار الإعتماد'),('create_uid','=',request.session.uid)]) + return request.render("ensan_campaign.campaigns", {'campaigns':campaigns}) + + @http.route(['/campaign/view2'], type='http', auth="user", website=True) + # mention a url for redirection. + # define the type of controllers which in this case is ‘http’. + # mention the authentication to be either public or user. + def campaign_view2(self, **post): + # create method + # this will load the form webpage + campaigns = request.env['campaign.campaign'].search([('state', '=', 'نشطة'),('create_uid','=',request.session.uid)]) + return request.render("ensan_campaign.campaigns2", {'campaigns': campaigns}) + + @http.route(['/campaign/view3'], type='http', auth="user", website=True) + # mention a url for redirection. + # define the type of controllers which in this case is ‘http’. + # mention the authentication to be either public or user. + def campaign_view3(self, **post): + # create method + # this will load the form webpage + campaigns = request.env['campaign.campaign'].search([('state', '=', 'غير نشطة'),('create_uid','=',request.session.uid)]) + return request.render("ensan_campaign.campaigns3", {'campaigns': campaigns}) + + @http.route(['/campaign/form'], type='http', auth="user", website=True) + # mention a url for redirection. + # define the type of controllers which in this case is ‘http’. + # mention the authentication to be either public or user. + def partner_form(self, **post): + # create method + # this will load the form webpage + product_categories = request.env['product.public.category'].sudo().search([]) + return request.render("ensan_campaign.tmp_campaign_form", {'selection_options':['رعاية الأيتام'],'categories':product_categories}) + + @http.route(['/campaign/form/submit'], type='http', auth="user", website=True) + # next controllers with url for submitting data from the form# + def customer_form_submit(self, **post): + campaign = request.env['campaign.campaign'].sudo().create({ + 'campaign_name': post.get('اسم الحمله'), + 'donation_amount': post.get('المبلغ المستهدف'), + 'remaining_amount': post.get('المبلغ المستهدف'), + 'category_id': post.get('مجال التبرع'), + 'user_id':request.session.uid, + # 'phone': post.get('phone') + }) + vals = { + 'campaign': campaign, + } + # inherited the model to pass the values to the model from the form# + return request.render("ensan_campaign.tmp_campaign_form_success", vals) + # finally send a request to render the thank you page# \ No newline at end of file diff --git a/odex25_donation/ensan_campaign/data/campaign_sms.xml b/odex25_donation/ensan_campaign/data/campaign_sms.xml new file mode 100644 index 000000000..48e435397 --- /dev/null +++ b/odex25_donation/ensan_campaign/data/campaign_sms.xml @@ -0,0 +1,10 @@ + + + + Campaign Activated + + ar + تم تنشيط الحملة بنجاح + + + \ No newline at end of file diff --git a/odex25_donation/ensan_campaign/models/__init__.py b/odex25_donation/ensan_campaign/models/__init__.py new file mode 100644 index 000000000..983a24e31 --- /dev/null +++ b/odex25_donation/ensan_campaign/models/__init__.py @@ -0,0 +1,2 @@ +from . import campaign_campaign +from . import product_template \ No newline at end of file diff --git a/odex25_donation/ensan_campaign/models/campaign_campaign.py b/odex25_donation/ensan_campaign/models/campaign_campaign.py new file mode 100644 index 000000000..ffc2fa5e8 --- /dev/null +++ b/odex25_donation/ensan_campaign/models/campaign_campaign.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, models,fields + + + +class CampaignCampaign(models.Model): + _name = 'campaign.campaign' + _inherit = 'mail.thread' + _rec_name = 'campaign_name' + seq = fields.Char(readonly=True,string='الرقم التسلسلي') + image = fields.Binary(default='') + description =fields.Text(String="Description",default="عند ضغط على زر 'Activate' سيتم تنشيط الحملة وإنشاء تبرع جديد يعرض في الصفحة الرئيسية",readonly=True) + #donation_field = fields.Selection([('كفاله يتيم','كفاله يتيم')],default='كفاله يتيم',string='مجال التبرع') + category_id = fields.Many2one('product.public.category',string="مجال الحمله") + campaign_name = fields.Char(string='اسم الحمله') + donation_amount = fields.Float(string='المبلغ المستهدف') + state = fields.Selection([('بإنتظار الإعتماد','بإنتظار الإعتماد'), + ('نشطة','نشطة'), + ('غير نشطة','غير نشطة')],string='الحالة',default='بإنتظار الإعتماد') + + confirm_flag = fields.Boolean() + user_id = fields.Many2one('res.users',string='مقدم الطلب') + email = fields.Char(related='user_id.login',string='الايميل') + remaining_amount = fields.Float() + # def _get_remaining_amount(self): + # for rec in self: + # template = rec.env['product.template'].search([('campaign_id','=',rec.id)]) + # if template: + # rec.remaining_amount = template.remaining_amount + # else: + # rec.remaining_amount = 0 + + + + def action_activate(self): + for rec in self: + rec .state = 'نشطة' + campaigns = rec.env['product.template'].search([('campaign_id','=',rec.id)]) + if not campaigns : + rec.env['product.template'].create({'name':rec.campaign_name, + 'target_amount':rec.donation_amount, + 'remaining_amount':rec.donation_amount, + 'sale_ok':True, + 'website_published':True, + 'image_1920':rec.image, + 'campaign_id':rec.id, + "public_categ_ids": [rec.category_id.id]}) + if rec.user_id.partner_id.phone: + sms_template_id = self.env.ref('ensan_campaign.sms_campaign') + # print(sms_template_id.body) + sms_template_id.body = 'تم تنشيط الحملة ({seq}) بنجاح'.format(seq=rec.seq) + # print(sms_template_id.body) + rec._message_sms_with_template( + template=sms_template_id, + put_in_queue=False, + sms_numbers=[rec.user_id.partner_id.phone] + ) + + def action_deactivate(self): + for rec in self: + rec.state = 'غير نشطة' + rec.env['product.template'].search([('campaign_id','=',rec.id)]).unlink() + + @api.model + def create(self, vals): + vals['seq'] = self.env['ir.sequence'].next_by_code('campaign.campaign') + campaign = super(CampaignCampaign, self).create(vals) + + # Send notifications here (use Odoo's messaging system or other notification mechanisms) + campaign.notification_create_campaign(campaign) + + return campaign + + def notification_create_campaign(self, campaign): + for rec in self: + + users = rec.env.ref('website.group_website_designer').users + notification_ids = [] + for user in users: + notification_ids.append((0, 0, { + 'res_partner_id': user.partner_id.id, + 'notification_type': 'inbox' + })) + + base_url = self.env['ir.config_parameter'].get_param('web.base.url') + base_url += '/web#id=%d&model=%s&view_type=form' % (self.id, self._name) + body = "Campaign " + campaign.campaign_name + " Added " + base_url + rec.message_post(record_name='campaign', body=body + , message_type="notification", + subtype_xmlid="mail.mt_comment", + author_id=rec.create_uid.partner_id.id, + notification_ids=notification_ids) + + # @api.model_create_multi + # def create(self, vals_list): + # # Call the original create method to create the record + # campaign = super(CampaignCampaign, self).create(vals_list) + # + # # Send notifications here (use Odoo's messaging system or other notification mechanisms) + # campaign.notification_create_campaign(campaign) + # + # return campaign \ No newline at end of file diff --git a/odex25_donation/ensan_campaign/models/product_template.py b/odex25_donation/ensan_campaign/models/product_template.py new file mode 100644 index 000000000..d0817b72f --- /dev/null +++ b/odex25_donation/ensan_campaign/models/product_template.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, models,fields + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + campaign_id = fields.Many2one('campaign.campaign') + + diff --git a/odex25_donation/ensan_campaign/report/campaign_report.xml b/odex25_donation/ensan_campaign/report/campaign_report.xml new file mode 100644 index 000000000..6417bf14c --- /dev/null +++ b/odex25_donation/ensan_campaign/report/campaign_report.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + Ensan Campaigns + campaign.campaign + qweb-pdf + ensan_campaign.report_campaign + ensan_campaign.report_campaign + + 'Campaign -%s' %(object.state) + + + report + + + diff --git a/odex25_donation/ensan_campaign/security/ir.model.access.csv b/odex25_donation/ensan_campaign/security/ir.model.access.csv new file mode 100644 index 000000000..5b5847fe0 --- /dev/null +++ b/odex25_donation/ensan_campaign/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +campaign_campaign,campaign_campaign,model_campaign_campaign,,1,1,1,1 +campaign_report,campaign_report,model_campaign_report,,1,1,1,1 + diff --git a/odex25_donation/ensan_campaign/security/res_groups.xml b/odex25_donation/ensan_campaign/security/res_groups.xml new file mode 100644 index 000000000..173bf8a79 --- /dev/null +++ b/odex25_donation/ensan_campaign/security/res_groups.xml @@ -0,0 +1,14 @@ + + + campaign rule + + + [('create_uid', '=', user.id)] + + + admin campaign rule + + [(1, '=', 1)] + + + \ No newline at end of file diff --git a/odex25_donation/ensan_campaign/static/src/css/stylesheet.css b/odex25_donation/ensan_campaign/static/src/css/stylesheet.css new file mode 100644 index 000000000..d14355e7c --- /dev/null +++ b/odex25_donation/ensan_campaign/static/src/css/stylesheet.css @@ -0,0 +1,61 @@ + +.shopping-cart { + + + box-shadow: 1px 2px 3px 0px ; + border-radius: 6px; + + display: flex; + flex-direction: column; +} +.title-custom { + height: 60px; + border-bottom: 1px solid #E1E8EE; + padding: 20px 30px; + color: #5E6977; + font-size: 18px; + font-weight: 400; +} + +.item-custom { + padding: 20px 30px; + height: 120px; + display: flex; +} + +.item-custom:nth-child(3) { + border-top: 1px solid #E1E8EE; + border-bottom: 1px solid #E1E8EE; +} + + + + + +Let’s add some basic style to product name and description. +.description-custom { + padding-top: 10px; + margin-right: 60px; + width: 115px; +} + +.description-custom span { + display: block; + font-size: 14px; + color: #43484D; + font-weight: 400; +} + +.description-custom span:first-child { + margin-bottom: 5px; +} +.description-custom span:last-child { + font-weight: 300; + margin-top: 8px; + color: #86939E; +} + + + + + diff --git a/odex25_donation/ensan_campaign/static/src/img/111.png b/odex25_donation/ensan_campaign/static/src/img/111.png new file mode 100644 index 000000000..77772bc38 Binary files /dev/null and b/odex25_donation/ensan_campaign/static/src/img/111.png differ diff --git a/odex25_donation/ensan_campaign/static/src/img/footer.png b/odex25_donation/ensan_campaign/static/src/img/footer.png new file mode 100644 index 000000000..e890aa554 Binary files /dev/null and b/odex25_donation/ensan_campaign/static/src/img/footer.png differ diff --git a/odex25_donation/ensan_campaign/static/src/img/header.png b/odex25_donation/ensan_campaign/static/src/img/header.png new file mode 100644 index 000000000..29cfdd6f9 Binary files /dev/null and b/odex25_donation/ensan_campaign/static/src/img/header.png differ diff --git a/odex25_donation/ensan_campaign/static/src/img/header2.png b/odex25_donation/ensan_campaign/static/src/img/header2.png new file mode 100644 index 000000000..fc6cb14d7 Binary files /dev/null and b/odex25_donation/ensan_campaign/static/src/img/header2.png differ diff --git a/odex25_donation/ensan_campaign/static/src/img/kafala.png b/odex25_donation/ensan_campaign/static/src/img/kafala.png new file mode 100644 index 000000000..e2c19bff9 Binary files /dev/null and b/odex25_donation/ensan_campaign/static/src/img/kafala.png differ diff --git a/odex25_donation/ensan_campaign/views/campaign_campaign_views.xml b/odex25_donation/ensan_campaign/views/campaign_campaign_views.xml new file mode 100644 index 000000000..a259937a8 --- /dev/null +++ b/odex25_donation/ensan_campaign/views/campaign_campaign_views.xml @@ -0,0 +1,95 @@ + + + + campaign_campaign_view_tree + campaign.campaign + + + + + + + + + + + + + + \ No newline at end of file diff --git a/odex25_donation/ensan_in_numbers/.idea/.gitignore b/odex25_donation/ensan_in_numbers/.idea/.gitignore new file mode 100644 index 000000000..26d33521a --- /dev/null +++ b/odex25_donation/ensan_in_numbers/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/odex25_donation/ensan_in_numbers/.idea/ensan_in_numbers.iml b/odex25_donation/ensan_in_numbers/.idea/ensan_in_numbers.iml new file mode 100644 index 000000000..d0876a78d --- /dev/null +++ b/odex25_donation/ensan_in_numbers/.idea/ensan_in_numbers.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/odex25_donation/ensan_in_numbers/.idea/inspectionProfiles/profiles_settings.xml b/odex25_donation/ensan_in_numbers/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 000000000..105ce2da2 --- /dev/null +++ b/odex25_donation/ensan_in_numbers/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/odex25_donation/ensan_in_numbers/.idea/misc.xml b/odex25_donation/ensan_in_numbers/.idea/misc.xml new file mode 100644 index 000000000..36532959d --- /dev/null +++ b/odex25_donation/ensan_in_numbers/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/odex25_donation/ensan_in_numbers/.idea/modules.xml b/odex25_donation/ensan_in_numbers/.idea/modules.xml new file mode 100644 index 000000000..e34ef723d --- /dev/null +++ b/odex25_donation/ensan_in_numbers/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/odex25_donation/ensan_in_numbers/__init__.py b/odex25_donation/ensan_in_numbers/__init__.py new file mode 100644 index 000000000..fb4e92aee --- /dev/null +++ b/odex25_donation/ensan_in_numbers/__init__.py @@ -0,0 +1,3 @@ +from . import models +from . import controller +from . import images \ No newline at end of file diff --git a/odex25_donation/ensan_in_numbers/__manifest__.py b/odex25_donation/ensan_in_numbers/__manifest__.py new file mode 100644 index 000000000..b095b8b6e --- /dev/null +++ b/odex25_donation/ensan_in_numbers/__manifest__.py @@ -0,0 +1,24 @@ + +{ + 'name': 'ensan_in_numbers', + 'version': '16.0', + 'author': 'Raqmeyat.', + + 'depends': ['website','website_sale'], + + "images": ['images/bg-single-news.png',], + + 'data': [ + + 'security/ir.model.access.csv', + 'data/ensan_in_numbers_record.xml', + 'views/ensan_in_numbers.xml', + 'views/ensan_in_number_menu_view.xml', + + ], +'installable': True, + 'application': True, + 'auto_install': False, + 'license': 'AGPL-3', + +} \ No newline at end of file diff --git a/odex25_donation/ensan_in_numbers/controller/__init__.py b/odex25_donation/ensan_in_numbers/controller/__init__.py new file mode 100644 index 000000000..72f4562d7 --- /dev/null +++ b/odex25_donation/ensan_in_numbers/controller/__init__.py @@ -0,0 +1 @@ +from . import controller \ No newline at end of file diff --git a/odex25_donation/ensan_in_numbers/controller/controller.py b/odex25_donation/ensan_in_numbers/controller/controller.py new file mode 100644 index 000000000..0339dcdcb --- /dev/null +++ b/odex25_donation/ensan_in_numbers/controller/controller.py @@ -0,0 +1,55 @@ +from odoo import http +from odoo.http import request + + +class EnsanInNumbers(http.Controller): + @http.route(['/EnsanInNumbers/view'], type='http', auth="public", website=True) + + + def ensan_in_numbers_view(self, **post): + numbers = request.env.ref('ensan_in_numbers.ensan_in_number_record') + # numbers = request.env['ensan.in.numbers'].search([]) + establishment_years = numbers.establishment_years + orphan_count = numbers.orphan_count + services_count = numbers.services_count + donation_operations_count = numbers.donation_operations_count + relief_cases_count = numbers.relief_cases_count + donation_projects_count = numbers.donation_projects_count + partners_count = numbers.partners_count + sponsors_count = numbers.sponsors_count + return request.render('ensan_in_numbers.ensan_in_numbers_template', { + 'establishment_years': establishment_years, + 'orphan_count': orphan_count, + 'services_count': services_count, + 'donation_operations_count': donation_operations_count, + 'relief_cases_count': relief_cases_count, + 'donation_projects_count': donation_projects_count, + 'partners_count': partners_count, + 'sponsors_count': sponsors_count, + }) + + + + + + + + + + + + + + + + + + + # # return request.render("ensan_in_numbers.numbers", {'numbers':numbers}) + # print(numbers) + # # return request.render('ensan_dynamic_dedicationcard.gift_template_id', + # # {'establishment_years': [establishment_years], + # # 'from_persons': [from_person], + # # 'to_persons': [to_person]}) + # # + diff --git a/odex25_donation/ensan_in_numbers/data/ensan_in_numbers_record.xml b/odex25_donation/ensan_in_numbers/data/ensan_in_numbers_record.xml new file mode 100644 index 000000000..d8a40f8d4 --- /dev/null +++ b/odex25_donation/ensan_in_numbers/data/ensan_in_numbers_record.xml @@ -0,0 +1,14 @@ + + + + 25 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + + + diff --git a/odex25_donation/ensan_in_numbers/images/bg-single-news.png b/odex25_donation/ensan_in_numbers/images/bg-single-news.png new file mode 100644 index 000000000..5189a339c Binary files /dev/null and b/odex25_donation/ensan_in_numbers/images/bg-single-news.png differ diff --git a/odex25_donation/ensan_in_numbers/models/__init__.py b/odex25_donation/ensan_in_numbers/models/__init__.py new file mode 100644 index 000000000..1c25b4ac3 --- /dev/null +++ b/odex25_donation/ensan_in_numbers/models/__init__.py @@ -0,0 +1 @@ +from . import ensan_in_numbers \ No newline at end of file diff --git a/odex25_donation/ensan_in_numbers/models/ensan_in_numbers.py b/odex25_donation/ensan_in_numbers/models/ensan_in_numbers.py new file mode 100644 index 000000000..c4a596544 --- /dev/null +++ b/odex25_donation/ensan_in_numbers/models/ensan_in_numbers.py @@ -0,0 +1,21 @@ +from odoo import models, fields, api + +class EnsanInNumbers(models.Model): + _name = 'ensan.in.numbers' + _rec_name = 'report_name' + report_name = fields.Char(String='Configuration Ensan In Numbers') + establishment_years = fields.Integer(string='تأسيس الجمعية ربع قرن', default=25) + + orphan_count = fields.Float(string='عدد الأيتام') + + services_count = fields.Float(string='عدد الخدمات المقدمة لليتيم') + + donation_operations_count = fields.Float(string='عدد عمليات التبرع في المنصة') + + + + relief_cases_count = fields.Float(string='عدد حالات تفريج كربة للأسر الأشد حاجة') + + donation_projects_count = fields.Float(string='عدد مشاريع التبرع') + partners_count = fields.Float(string='عدد الشركاء') + sponsors_count = fields.Float(string='عدد الكافلين') \ No newline at end of file diff --git a/odex25_donation/ensan_in_numbers/security/ir.model.access.csv b/odex25_donation/ensan_in_numbers/security/ir.model.access.csv new file mode 100644 index 000000000..8ea1424d9 --- /dev/null +++ b/odex25_donation/ensan_in_numbers/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +ensan_in_numbers,ensan_in_numbers,model_ensan_in_numbers,,1,1,1,1 + + + diff --git a/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy 2.png b/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy 2.png new file mode 100644 index 000000000..882d10eb2 Binary files /dev/null and b/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy 2.png differ diff --git a/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy 3.png b/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy 3.png new file mode 100644 index 000000000..48eb97fb2 Binary files /dev/null and b/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy 3.png differ diff --git a/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy 4.png b/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy 4.png new file mode 100644 index 000000000..3ddc03b5c Binary files /dev/null and b/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy 4.png differ diff --git a/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy.png b/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy.png new file mode 100644 index 000000000..9e2ac7451 Binary files /dev/null and b/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1 copy.png differ diff --git a/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1.png b/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1.png new file mode 100644 index 000000000..219539041 Binary files /dev/null and b/odex25_donation/ensan_in_numbers/static/src/img/Artboard 1.png differ diff --git a/odex25_donation/ensan_in_numbers/views/ensan_in_number_menu_view.xml b/odex25_donation/ensan_in_numbers/views/ensan_in_number_menu_view.xml new file mode 100644 index 000000000..027eac263 --- /dev/null +++ b/odex25_donation/ensan_in_numbers/views/ensan_in_number_menu_view.xml @@ -0,0 +1,182 @@ + + + + + + + Ensan In Numbers + /EnsanInNumbers/view + + 24 + + + diff --git a/odex25_donation/ensan_in_numbers/views/ensan_in_numbers.xml b/odex25_donation/ensan_in_numbers/views/ensan_in_numbers.xml new file mode 100644 index 000000000..8d17eb343 --- /dev/null +++ b/odex25_donation/ensan_in_numbers/views/ensan_in_numbers.xml @@ -0,0 +1,35 @@ + + + + ensan.in.number + ensan.in.numbers + +
+ + + + + + + + + + + + + + +
+
+
+ + Ensan In Number + ensan.in.numbers + form + + + + + +
+
diff --git a/odex25_donation/ensan_performance_enhancement/__init__.py b/odex25_donation/ensan_performance_enhancement/__init__.py new file mode 100644 index 000000000..9a7e03ede --- /dev/null +++ b/odex25_donation/ensan_performance_enhancement/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/odex25_donation/ensan_performance_enhancement/__manifest__.py b/odex25_donation/ensan_performance_enhancement/__manifest__.py new file mode 100644 index 000000000..40b651f38 --- /dev/null +++ b/odex25_donation/ensan_performance_enhancement/__manifest__.py @@ -0,0 +1,13 @@ + +{ + "name": "ensan_performance_enhancement", + "author": "Ritsol Allied", + "version": "16.0", + "depends": ['sale','sale_management'], + "data": + { + #'data/product_cron.xml', + + }, + 'images': ['static/description/completed-01.jpg'], +} diff --git a/odex25_donation/ensan_performance_enhancement/data/product_cron.xml b/odex25_donation/ensan_performance_enhancement/data/product_cron.xml new file mode 100644 index 000000000..b39aea038 --- /dev/null +++ b/odex25_donation/ensan_performance_enhancement/data/product_cron.xml @@ -0,0 +1,17 @@ + + + + + ir_cron_compute_donations + 1 + hours + -1 + + + + model.cron_compute_donations() + code + + + + \ No newline at end of file diff --git a/odex25_donation/ensan_performance_enhancement/models/__init__.py b/odex25_donation/ensan_performance_enhancement/models/__init__.py new file mode 100644 index 000000000..ea04bab6d --- /dev/null +++ b/odex25_donation/ensan_performance_enhancement/models/__init__.py @@ -0,0 +1,2 @@ +#from . import product_template +from . import account_move_line \ No newline at end of file diff --git a/odex25_donation/ensan_performance_enhancement/models/account_move_line.py b/odex25_donation/ensan_performance_enhancement/models/account_move_line.py new file mode 100644 index 000000000..87d21e2c5 --- /dev/null +++ b/odex25_donation/ensan_performance_enhancement/models/account_move_line.py @@ -0,0 +1,48 @@ +from odoo import api, fields, models +from odoo.exceptions import UserError, ValidationError +from odoo.tools import file_open +import base64 +class AccountMoveLine(models.Model): + _inherit = 'account.move' + + @api.constrains('payment_state') + def update_donate_percentage_and_remaining_amount(self): + for rec in self: + if rec.move_type == 'out_invoice': + for line in rec.invoice_line_ids: + product = rec.env['product.template'].search([('id', '=', line.product_id.product_tmpl_id.id)]) + all_invoices_paid = self.env['account.move.line'].search( + [ + + ('product_id.product_tmpl_id', '=', product.id),('move_id.payment_state', '=', 'paid'), ('move_id.move_type', '=', 'out_invoice') + ]) + + if all_invoices_paid: + + total_sum = sum(all_invoices_paid.mapped('price_total')) + donated_amount = total_sum + else: + donated_amount = 0 + product.remaining_amount = product.target_amount - donated_amount + if hasattr(product,'campaign_id'): + if product.campaign_id: + product.campaign_id.remaining_amount = product.target_amount - donated_amount + if product.remaining_amount <= 0 and product.target_amount !=0: + product.sale_ok = False + # image_path = 'ensan_performance_enhancement/static/description/completed-01.jpg' + # with file_open(image_path, 'rb', ) as image_file: + # image_data = image_file.read() + # encoded_image_data = base64.b64encode(image_data) + # product.image_1920 = encoded_image_data + else: + product.sale_ok = True + # product.image_1920 = False + + if product.target_amount !=0 : + product.done_percentage = (donated_amount / product.target_amount) * 100 + else: + product.done_percentage = 0 + + + + diff --git a/odex25_donation/ensan_performance_enhancement/models/product_template.py b/odex25_donation/ensan_performance_enhancement/models/product_template.py new file mode 100644 index 000000000..0ab95d1f4 --- /dev/null +++ b/odex25_donation/ensan_performance_enhancement/models/product_template.py @@ -0,0 +1,30 @@ +from odoo import api, fields, models +from odoo.exceptions import UserError, ValidationError + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + def cron_compute_donations(self): + + products = self.env['product.template'].search([]) + for product in products: + all_invoices_paid = self.env['account.move.line'].search( + [ + ('move_id.move_type', '=', 'out_invoice'), ('move_id.payment_state', '=', 'paid'), + ('product_id.product_tmpl_id', '=', product.id) + ]) + total_sum = 0 + if all_invoices_paid: + # for invoice_order_line in all_invoices_paid: + # total_sum += invoice_order_line.price_total + total_sum = sum(all_invoices_paid.mapped('price_total')) + product['donated_amount'] = total_sum + else: + product['donated_amount'] = 0 + + product.remaining_amount = product.target_amount - product.donated_amount + + if product.target_amount: + product.done_percentage = (product.donated_amount / product.target_amount) * 100 + else: + product.done_percentage = 0 diff --git a/odex25_donation/ensan_performance_enhancement/static/description/completed-01.jpg b/odex25_donation/ensan_performance_enhancement/static/description/completed-01.jpg new file mode 100644 index 000000000..9616785dd Binary files /dev/null and b/odex25_donation/ensan_performance_enhancement/static/description/completed-01.jpg differ diff --git a/odex25_donation/ensan_product_filtration/__init__.py b/odex25_donation/ensan_product_filtration/__init__.py new file mode 100644 index 000000000..19240f4ea --- /dev/null +++ b/odex25_donation/ensan_product_filtration/__init__.py @@ -0,0 +1,2 @@ +from . import controllers +from . import models \ No newline at end of file diff --git a/odex25_donation/ensan_product_filtration/__manifest__.py b/odex25_donation/ensan_product_filtration/__manifest__.py new file mode 100644 index 000000000..239e42611 --- /dev/null +++ b/odex25_donation/ensan_product_filtration/__manifest__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +{ + 'name' : 'ensan_product_filtration', + 'version' : '1.0', + 'depends' : ['product','sale','sale_management','p_donation_theme'], + 'assets': { + 'web.assets_backend': [ + ], + + }, + 'data': [ + + 'views/edit_gift.xml', + + ], + +} diff --git a/odex25_donation/ensan_product_filtration/controllers/__init__.py b/odex25_donation/ensan_product_filtration/controllers/__init__.py new file mode 100644 index 000000000..82763c9ec --- /dev/null +++ b/odex25_donation/ensan_product_filtration/controllers/__init__.py @@ -0,0 +1 @@ +from . import websitesale \ No newline at end of file diff --git a/odex25_donation/ensan_product_filtration/controllers/websitesale.py b/odex25_donation/ensan_product_filtration/controllers/websitesale.py new file mode 100644 index 000000000..27d51330a --- /dev/null +++ b/odex25_donation/ensan_product_filtration/controllers/websitesale.py @@ -0,0 +1,93 @@ +from odoo import http +from odoo.addons.website_sale.controllers.main import WebsiteSale + + + +from collections import defaultdict +from itertools import product as cartesian_product +import json +import logging +from datetime import datetime +from werkzeug.exceptions import Forbidden, NotFound +from werkzeug.urls import url_decode, url_encode, url_parse + +from odoo import fields, http, SUPERUSER_ID, tools, _ +from odoo.fields import Command +from odoo.http import request +from odoo.addons.base.models.ir_qweb_fields import nl2br +from odoo.addons.http_routing.models.ir_http import slug +from odoo.addons.payment import utils as payment_utils +from odoo.addons.payment.controllers import portal as payment_portal +from odoo.addons.payment.controllers.post_processing import PaymentPostProcessing +from odoo.addons.website.controllers.main import QueryURL +from odoo.addons.website.models.ir_http import sitemap_qs2dom +from odoo.exceptions import AccessError, MissingError, ValidationError +from odoo.addons.portal.controllers.portal import _build_url_w_params +from odoo.addons.website.controllers import main +from odoo.addons.website.controllers.form import WebsiteForm +from odoo.addons.sale.controllers import portal +from odoo.osv import expression +from odoo.tools import lazy +from odoo.tools.json import scriptsafe as json_scriptsafe + +class CustomWebsiteSale(WebsiteSale): + + def _shop_lookup_products(self, attrib_set, options, post, search, website): + # No limit because attributes are obtained from complete product list + product_count, details, fuzzy_search_term = website._search_with_fuzzy("products_only", search, + limit=None, + order=self._get_search_order(post), + options=options) + search_result = details[0].get('results', request.env['product.template']).with_context(bin_size=True) + # search_result = search_result.filtered(lambda product:product.is_quick_donation == False and product.show_on_website == True) + search_result = search_result.filtered(lambda product:product.quick_donation_only == False) + print(len(search_result)) + product_count = len(search_result) + if attrib_set: + # Attributes value per attribute + attribute_values = request.env['product.attribute.value'].browse(attrib_set) + values_per_attribute = defaultdict(lambda: request.env['product.attribute.value']) + # In case we have only one value per attribute we can check for a combination using those attributes directly + multi_value_attribute = False + for value in attribute_values: + values_per_attribute[value.attribute_id] |= value + if len(values_per_attribute[value.attribute_id]) > 1: + multi_value_attribute = True + + def filter_template(template, attribute_values_list): + # Transform product.attribute.value to product.template.attribute.value + attribute_value_to_ptav = dict() + for ptav in template.attribute_line_ids.product_template_value_ids: + attribute_value_to_ptav[ptav.product_attribute_value_id] = ptav.id + possible_combinations = False + for attribute_values in attribute_values_list: + ptavs = request.env['product.template.attribute.value'].browse( + [attribute_value_to_ptav[val] for val in attribute_values if val in attribute_value_to_ptav] + ) + if len(ptavs) < len(attribute_values): + # In this case the template is not compatible with this specific combination + continue + if len(ptavs) == len(template.attribute_line_ids): + if template._is_combination_possible(ptavs): + return True + elif len(ptavs) < len(template.attribute_line_ids): + if len(attribute_values_list) == 1: + if any(template._get_possible_combinations(necessary_values=ptavs)): + return True + if not possible_combinations: + possible_combinations = template._get_possible_combinations() + if any(len(ptavs & combination) == len(ptavs) for combination in possible_combinations): + return True + return False + + # If multi_value_attribute is False we know that we have our final combination (or at least a subset of it) + if not multi_value_attribute: + possible_attrib_values_list = [attribute_values] + else: + # Cartesian product from dict keys and values + possible_attrib_values_list = [request.env['product.attribute.value'].browse([v.id for v in values]) for + values in cartesian_product(*values_per_attribute.values())] + + search_result = search_result.filtered(lambda tmpl: filter_template(tmpl, possible_attrib_values_list)) + return fuzzy_search_term, product_count, search_result + diff --git a/odex25_donation/ensan_product_filtration/models/__init__.py b/odex25_donation/ensan_product_filtration/models/__init__.py new file mode 100644 index 000000000..510f3bdc6 --- /dev/null +++ b/odex25_donation/ensan_product_filtration/models/__init__.py @@ -0,0 +1 @@ +from . import product_template \ No newline at end of file diff --git a/odex25_donation/ensan_product_filtration/models/product_template.py b/odex25_donation/ensan_product_filtration/models/product_template.py new file mode 100644 index 000000000..daad059ea --- /dev/null +++ b/odex25_donation/ensan_product_filtration/models/product_template.py @@ -0,0 +1,12 @@ +from odoo.exceptions import ValidationError + +from odoo import fields, models,api + +class ProductTemplate(models.Model): + + _inherit = 'product.template' + available_for_dedication=fields.Boolean(default=True) + quick_donation_only = fields.Boolean(default=False) + # is_recurring_product = fields.Boolean() + # show_on_website=fields.Boolean(default=True) + diff --git a/odex25_donation/ensan_product_filtration/views/edit_gift.xml b/odex25_donation/ensan_product_filtration/views/edit_gift.xml new file mode 100644 index 000000000..aac6bb152 --- /dev/null +++ b/odex25_donation/ensan_product_filtration/views/edit_gift.xml @@ -0,0 +1,31 @@ + + + + + edit_gift + product.template + + + +
+ +
+
+ +
+ + + + + + + + + +
+
+
+
+
\ No newline at end of file diff --git a/odex25_donation/friendly_website_errors/__init__.py b/odex25_donation/friendly_website_errors/__init__.py new file mode 100644 index 000000000..cef7209c1 --- /dev/null +++ b/odex25_donation/friendly_website_errors/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import controller \ No newline at end of file diff --git a/odex25_donation/friendly_website_errors/__manifest__.py b/odex25_donation/friendly_website_errors/__manifest__.py new file mode 100644 index 000000000..dfc39c2e8 --- /dev/null +++ b/odex25_donation/friendly_website_errors/__manifest__.py @@ -0,0 +1,16 @@ +{ + 'name': 'Friendly Website Error', + 'category': 'Website', + 'author': 'TheOdooGuy', + 'website': 'https://www.theodooguy.com', + 'summary': 'Style Odoo website errors and make the message more user friendly', + 'depends': ['website', 'base'], + 'images': ['images/main.png', 'images/main_screenshot.png'], + 'data': [ + 'views/exceptions_view.xml', + ], + 'installable': True, + 'application': True, + 'auto_install': False, + 'license': 'AGPL-3', +} diff --git a/odex25_donation/friendly_website_errors/controller/__init__.py b/odex25_donation/friendly_website_errors/controller/__init__.py new file mode 100644 index 000000000..deec4a8b8 --- /dev/null +++ b/odex25_donation/friendly_website_errors/controller/__init__.py @@ -0,0 +1 @@ +from . import main \ No newline at end of file diff --git a/odex25_donation/friendly_website_errors/controller/main.py b/odex25_donation/friendly_website_errors/controller/main.py new file mode 100644 index 000000000..c48f16d6e --- /dev/null +++ b/odex25_donation/friendly_website_errors/controller/main.py @@ -0,0 +1,10 @@ +from odoo import http +from odoo.http import request + + +class Website(http.Controller): + + @http.route('/web/403', type='http', auth="public") + def redirect_403(self, **kwargs): + # Redirect 403 errors to the home page + return request.redirect('/') \ No newline at end of file diff --git a/odex25_donation/friendly_website_errors/images/main.png b/odex25_donation/friendly_website_errors/images/main.png new file mode 100644 index 000000000..5c2092910 Binary files /dev/null and b/odex25_donation/friendly_website_errors/images/main.png differ diff --git a/odex25_donation/friendly_website_errors/images/main_screenshot.png b/odex25_donation/friendly_website_errors/images/main_screenshot.png new file mode 100644 index 000000000..cfc3b8dfb Binary files /dev/null and b/odex25_donation/friendly_website_errors/images/main_screenshot.png differ diff --git a/odex25_donation/friendly_website_errors/models/__init__.py b/odex25_donation/friendly_website_errors/models/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/odex25_donation/friendly_website_errors/security/ir.model.access.csv b/odex25_donation/friendly_website_errors/security/ir.model.access.csv new file mode 100644 index 000000000..08145a00f --- /dev/null +++ b/odex25_donation/friendly_website_errors/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink + diff --git a/odex25_donation/friendly_website_errors/static/description/icon.png b/odex25_donation/friendly_website_errors/static/description/icon.png new file mode 100644 index 000000000..2676e6ad7 Binary files /dev/null and b/odex25_donation/friendly_website_errors/static/description/icon.png differ diff --git a/odex25_donation/friendly_website_errors/static/description/index.html b/odex25_donation/friendly_website_errors/static/description/index.html new file mode 100644 index 000000000..40791a99a --- /dev/null +++ b/odex25_donation/friendly_website_errors/static/description/index.html @@ -0,0 +1,52 @@ +
+
+

404 & 403 Error Message

+

+ Styles and make 404 Error Message more Friendly and presentable +

+
+ +
+
+
+ +
+
+

500 Internal Server Error

+

+ Styles and make 500 Error Message more Friendly and presentable +

+
+ +
+
+
+
+
+

500 Internal Server Error

+

+ Styles and make 500 Error Message more Friendly and presentable +

+
+ +
+
+
+ +
+
+
+
+

Contact us for support, query, customization

+
+ + Website | + Write us + +
+
+
+ + +
+
diff --git a/odex25_donation/friendly_website_errors/static/description/main.png b/odex25_donation/friendly_website_errors/static/description/main.png new file mode 100644 index 000000000..5c2092910 Binary files /dev/null and b/odex25_donation/friendly_website_errors/static/description/main.png differ diff --git a/odex25_donation/friendly_website_errors/static/description/main_screenshot.png b/odex25_donation/friendly_website_errors/static/description/main_screenshot.png new file mode 100644 index 000000000..cfc3b8dfb Binary files /dev/null and b/odex25_donation/friendly_website_errors/static/description/main_screenshot.png differ diff --git a/odex25_donation/friendly_website_errors/static/images/404-error.png b/odex25_donation/friendly_website_errors/static/images/404-error.png new file mode 100644 index 000000000..ea867ec82 Binary files /dev/null and b/odex25_donation/friendly_website_errors/static/images/404-error.png differ diff --git a/odex25_donation/friendly_website_errors/static/images/completed-01.png b/odex25_donation/friendly_website_errors/static/images/completed-01.png new file mode 100644 index 000000000..aa235b8e7 Binary files /dev/null and b/odex25_donation/friendly_website_errors/static/images/completed-01.png differ diff --git a/odex25_donation/friendly_website_errors/static/images/internal_server_error.png b/odex25_donation/friendly_website_errors/static/images/internal_server_error.png new file mode 100644 index 000000000..4f3b01ce3 Binary files /dev/null and b/odex25_donation/friendly_website_errors/static/images/internal_server_error.png differ diff --git a/odex25_donation/friendly_website_errors/static/src/handle_exceptions.css b/odex25_donation/friendly_website_errors/static/src/handle_exceptions.css new file mode 100644 index 000000000..9e6a291b0 --- /dev/null +++ b/odex25_donation/friendly_website_errors/static/src/handle_exceptions.css @@ -0,0 +1,30 @@ +.my_container { + margin-top: 70px; + color: red; + +} + +.message_error { + text-align: right; + vertical-align: middle; + color: red; +} + +.message_error h1{ + font-family: "Lato",sans-serif; + font-size: 58px; + color: red; +} + +.message_error p{ + font-family: "Lato",sans-serif; + font-size: 23px; + color: red; +} + +.message_error ol{ + font-family: "Lato",sans-serif; + font-size: 23px; + padding: 15px 0; + color: red; +} diff --git a/odex25_donation/friendly_website_errors/views/exceptions_view.xml b/odex25_donation/friendly_website_errors/views/exceptions_view.xml new file mode 100644 index 000000000..16b48b7f4 --- /dev/null +++ b/odex25_donation/friendly_website_errors/views/exceptions_view.xml @@ -0,0 +1,101 @@ + + + + + + + + + diff --git a/odex25_donation/p_donation_gift/.idea/.gitignore b/odex25_donation/p_donation_gift/.idea/.gitignore new file mode 100644 index 000000000..26d33521a --- /dev/null +++ b/odex25_donation/p_donation_gift/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/odex25_donation/p_donation_gift/.idea/inspectionProfiles/profiles_settings.xml b/odex25_donation/p_donation_gift/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 000000000..105ce2da2 --- /dev/null +++ b/odex25_donation/p_donation_gift/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/.idea/misc.xml b/odex25_donation/p_donation_gift/.idea/misc.xml new file mode 100644 index 000000000..db8786c06 --- /dev/null +++ b/odex25_donation/p_donation_gift/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/.idea/modules.xml b/odex25_donation/p_donation_gift/.idea/modules.xml new file mode 100644 index 000000000..9b91892b1 --- /dev/null +++ b/odex25_donation/p_donation_gift/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/.idea/p_donation_gift.iml b/odex25_donation/p_donation_gift/.idea/p_donation_gift.iml new file mode 100644 index 000000000..d0876a78d --- /dev/null +++ b/odex25_donation/p_donation_gift/.idea/p_donation_gift.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/LICENSE b/odex25_donation/p_donation_gift/LICENSE new file mode 100644 index 000000000..7a5c68e71 --- /dev/null +++ b/odex25_donation/p_donation_gift/LICENSE @@ -0,0 +1,27 @@ +Odoo Proprietary License v1.0 + +This software and associated files (the "Software") may only be used (executed, +modified, executed after modifications) if you have purchased a valid license +from the authors, typically via Odoo Apps, or if you have received a written +agreement from the authors of the Software (see the COPYRIGHT file). + +You may develop Odoo modules that use the Software as a library (typically +by depending on it, importing it and using its resources), but without copying +any source code or material from the Software. You may distribute those +modules under the license of your choice, provided that this license is +compatible with the terms of the Odoo Proprietary License (For example: +LGPL, MIT, or proprietary licenses similar to this one). + +It is forbidden to publish, distribute, sublicense, or sell copies of the Software +or modified copies of the Software. + +The above copyright notice and this permission notice must be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/__init__.py b/odex25_donation/p_donation_gift/__init__.py new file mode 100644 index 000000000..511a0ca3a --- /dev/null +++ b/odex25_donation/p_donation_gift/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import controllers +from . import models \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/__manifest__.py b/odex25_donation/p_donation_gift/__manifest__.py new file mode 100644 index 000000000..44abab7e7 --- /dev/null +++ b/odex25_donation/p_donation_gift/__manifest__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +{ + 'name': "GIFT Feature on donation platform", + 'summary': 'GIFT Feature on donation platform', + 'description': 'this module adds GIFT Feature in Ensan.sa interface', + 'author': 'Shah Enterprise', + 'maintainer': 'Shah Enterprise', + 'company': 'Shah Enterprise', + 'website': 'https://shahenterprise.co', + 'price': 600, + 'currency': 'USD', + 'license': 'LGPL-3', + 'category': 'Uncategorized', + 'version': '16.0.1', + 'depends': [ + 'base', 'website_sale', 'theme_prime', 'p_donation_theme' + ], + 'data': [ + 'views/website_template.xml', + 'views/sale_view.xml' + ], + 'assets': { + 'web.assets_frontend': [ + 'p_donation_gift/static/src/js/*.js', + 'p_donation_gift/static/src/scss/*.scss', + # 'p_donation_gift/static/src/xml/gift.xml', + ], + } +} diff --git a/odex25_donation/p_donation_gift/controllers/__init__.py b/odex25_donation/p_donation_gift/controllers/__init__.py new file mode 100644 index 000000000..deec4a8b8 --- /dev/null +++ b/odex25_donation/p_donation_gift/controllers/__init__.py @@ -0,0 +1 @@ +from . import main \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/controllers/main.py b/odex25_donation/p_donation_gift/controllers/main.py new file mode 100644 index 000000000..9fcd2eeaa --- /dev/null +++ b/odex25_donation/p_donation_gift/controllers/main.py @@ -0,0 +1,16 @@ +from odoo import http, _ +from odoo.addons.website_sale.controllers.main import WebsiteSale +from odoo.http import request + +class WebsiteSale_Cart(WebsiteSale): + + @http.route(['/shop/cart/update'], type='http', auth="public", methods=['POST'], website=True) + def cart_update( + self, product_id, add_qty=1, set_qty=0, + product_custom_attribute_values=None, no_variant_attribute_values=None, + express=False, **kwargs): + gift_redirect = 'gift_redirect' in kwargs and kwargs.pop('gift_redirect') or False + call_super = super(WebsiteSale_Cart, self).cart_update(product_id, add_qty, set_qty, product_custom_attribute_values, no_variant_attribute_values, express, **kwargs) + if gift_redirect: + return request.redirect("/shop/payment") + return call_super \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/description/icon.png b/odex25_donation/p_donation_gift/description/icon.png new file mode 100644 index 000000000..392838e0c Binary files /dev/null and b/odex25_donation/p_donation_gift/description/icon.png differ diff --git a/odex25_donation/p_donation_gift/i18n/ar_001.po b/odex25_donation/p_donation_gift/i18n/ar_001.po new file mode 100644 index 000000000..f8133424f --- /dev/null +++ b/odex25_donation/p_donation_gift/i18n/ar_001.po @@ -0,0 +1,162 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * p_donation_gift +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-05-28 18:33+0000\n" +"PO-Revision-Date: 2024-05-28 18:33+0000\n" +"Last-Translator: Harshil Shah, 2024\n" +"Language-Team: Arabic\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +msgid "05xxxxxxxx" +msgstr "" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +msgid "Close" +msgstr "" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +msgid "Dedicate Now" +msgstr "تبرع الان" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +msgid "Donate on behalf of your family or friends" +msgstr "اهدٍ من احببت اجرًا" + +#. module: p_donation_gift +#: model:ir.model.fields,field_description:p_donation_gift.field_sale_report__order_name +msgid "Donor Name" +msgstr "اسم المهدي" + +#. module: p_donation_gift +#: model:ir.model.fields,field_description:p_donation_gift.field_sale_report__order_mobile_number +msgid "Donor Number" +msgstr "رقم جوال المهدي" + +#. module: p_donation_gift +#: model:ir.model,name:p_donation_gift.model_ir_http +msgid "HTTP Routing" +msgstr "مسار HTTP" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +msgid "Invalid Name!" +msgstr "الاسم خطأ" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +msgid "Invalid Number! It Should start with 05 and minimum length 10" +msgstr "رقم الجوال خطأ، الصيغة الصحيحة" + +#. module: p_donation_gift +#: model:ir.model.fields,field_description:p_donation_gift.field_product_product__is_gift +#: model:ir.model.fields,field_description:p_donation_gift.field_product_template__is_gift +#: model:ir.model.fields,field_description:p_donation_gift.field_sale_order__is_gift +#: model:ir.model.fields,field_description:p_donation_gift.field_sale_order_line__is_gift +msgid "Is Gift Product?" +msgstr "" + +#. module: p_donation_gift +#: model:ir.model.fields,field_description:p_donation_gift.field_sale_report__is_gift +msgid "Order Contains Gift" +msgstr "" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.sale_report_view_search_website +#: model_terms:ir.ui.view,arch_db:p_donation_gift.view_order_form +#: model_terms:ir.ui.view,arch_db:p_donation_gift.view_sales_order_filter +msgid "Order Contains Gift?" +msgstr "" + +#. module: p_donation_gift +#: model:ir.model,name:p_donation_gift.model_product_template +msgid "Product" +msgstr "المنتج" + +#. module: p_donation_gift +#: model:ir.model,name:p_donation_gift.model_product_product +msgid "Product Variant" +msgstr "متغير المنتج " + +#. module: p_donation_gift +#: model:ir.model.fields,field_description:p_donation_gift.field_sale_order__first_receiver_name +#: model:ir.model.fields,field_description:p_donation_gift.field_sale_report__first_receiver_name +#: model_terms:ir.ui.view,arch_db:p_donation_gift.sale_report_view_search_website +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +#: model_terms:ir.ui.view,arch_db:p_donation_gift.view_sales_order_filter +msgid "Receiver Name" +msgstr "اسم المهدى له" + +#. module: p_donation_gift +#: model:ir.model.fields,field_description:p_donation_gift.field_sale_order__first_receiver_number +#: model:ir.model.fields,field_description:p_donation_gift.field_sale_report__first_receiver_number +#: model_terms:ir.ui.view,arch_db:p_donation_gift.sale_report_view_search_website +#: model_terms:ir.ui.view,arch_db:p_donation_gift.view_sales_order_filter +msgid "Receiver Number" +msgstr "رقم جوال المهدى له" + +#. module: p_donation_gift +#: model:ir.model,name:p_donation_gift.model_sale_report +msgid "Sales Analysis Report" +msgstr "تقرير المبيعات التحليلي" + +#. module: p_donation_gift +#: model:ir.model,name:p_donation_gift.model_sale_order +msgid "Sales Order" +msgstr "أمر البيع" + +#. module: p_donation_gift +#: model:ir.model,name:p_donation_gift.model_sale_order_line +msgid "Sales Order Line" +msgstr "بند أمر المبيعات" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.sale_report_view_search_website +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +#: model_terms:ir.ui.view,arch_db:p_donation_gift.view_sales_order_filter +msgid "Sender Name" +msgstr "اسم المهدي" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.sale_report_view_search_website +#: model_terms:ir.ui.view,arch_db:p_donation_gift.view_sales_order_filter +msgid "Sender Number" +msgstr "رقم جوال المهدي" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +msgid "Valid Name!" +msgstr "الاسم صحيح " + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout + +#. module: p_donation_gift +#. odoo-javascript +#: code:addons/p_donation_gift/static/src/js/gift.js:0 +#, python-format +msgid "Please Fill out this field." +msgstr "يرجى ملئ مبلغ التبرع" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +msgid "Sender Mobile" +msgstr "رقم جوال المهدي" + +#. module: p_donation_gift +#: model_terms:ir.ui.view,arch_db:p_donation_gift.shop_layout +msgid "Receiver Mobile" +msgstr "رقم جوال المهدى له" \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/models/__init__.py b/odex25_donation/p_donation_gift/models/__init__.py new file mode 100644 index 000000000..d879249ac --- /dev/null +++ b/odex25_donation/p_donation_gift/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import sale, product, sale_report, ir_http \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/models/ir_http.py b/odex25_donation/p_donation_gift/models/ir_http.py new file mode 100644 index 000000000..df2834677 --- /dev/null +++ b/odex25_donation/p_donation_gift/models/ir_http.py @@ -0,0 +1,10 @@ +from odoo import models + + +class IrHttp(models.AbstractModel): + _inherit = 'ir.http' + + @classmethod + def _get_translation_frontend_modules_name(cls): + mods = super(IrHttp, cls)._get_translation_frontend_modules_name() + return mods + ['p_donation_gift'] \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/models/product.py b/odex25_donation/p_donation_gift/models/product.py new file mode 100644 index 000000000..b1ff4e2fe --- /dev/null +++ b/odex25_donation/p_donation_gift/models/product.py @@ -0,0 +1,13 @@ +from odoo import models, fields + + +class ProductTemplate_Inherit(models.Model): + _inherit = 'product.template' + + is_gift = fields.Boolean("Is Gift Product?", default=False) + + +class ProductProduct_Inherit(models.Model): + _inherit = 'product.product' + + is_gift = fields.Boolean("Is Gift Product?", related="product_tmpl_id.is_donation") diff --git a/odex25_donation/p_donation_gift/models/sale.py b/odex25_donation/p_donation_gift/models/sale.py new file mode 100644 index 000000000..55f2425b0 --- /dev/null +++ b/odex25_donation/p_donation_gift/models/sale.py @@ -0,0 +1,66 @@ +from odoo import models, fields, api +from odoo.tools.json import scriptsafe as json_scriptsafe + + +class SaleOrder_Inherit(models.Model): + _inherit = 'sale.order' + + is_gift = fields.Boolean("Is Gift Product?", store=True, compute="compute_gift_order") + first_receiver_number = fields.Char("Receiver Number", compute="_compute_receiver_details", store=True) + first_receiver_name = fields.Char("Receiver Name", compute="_compute_receiver_details", store=True) + + @api.depends('donators_ids') + def _compute_receiver_details(self): + for rec in self: + first_receiver_number = '' + first_receiver_name = '' + if rec.donators_ids: + gift_donators_id = rec.donators_ids.filtered(lambda l:l.product_id.product_tmpl_id.is_gift) + if not gift_donators_id: + gift_donators_id = rec.donators_ids + gift_donators_id = gift_donators_id[0] + first_receiver_number = gift_donators_id.donator_mobile_number + first_receiver_name = gift_donators_id.donator_name + rec.first_receiver_number = first_receiver_number + rec.first_receiver_name = first_receiver_name + + @api.depends('order_line.is_gift') + def compute_gift_order(self): + for rec in self: + if rec.order_line.filtered(lambda l: l.is_gift): + rec.is_gift = True + else: + rec.is_gift = False + + def _cart_update(self, *args, **kwargs): + donate_list = kwargs.get('donate_list', []) + if donate_list: + donate_list = json_scriptsafe.loads(donate_list) + donate_dict = donate_list[0] + gift_sender_name = donate_dict.get("gift_sender_name") + gift_sender_mobile = donate_dict.get("gift_sender_mobile") + kwargs.pop('donate_list') + kwargs.update({ + 'donators_ids': json_scriptsafe.dumps([donate_dict]) + }) + self.write({ + 'order_mobile_number': gift_sender_mobile, + 'order_name': gift_sender_name + }) + + call_super = super(SaleOrder_Inherit, self)._cart_update(*args, **kwargs) + return call_super + + +class SaleOrderLineInherit(models.Model): + _inherit = 'sale.order.line' + + is_gift = fields.Boolean("Is Gift Product?", store=True) + + @api.model_create_multi + def create(self, vals_list): + call_super = super(SaleOrderLineInherit, self).create(vals_list) + for line in call_super: + if line.product_id: + line.is_gift = line.product_id.is_gift + return call_super diff --git a/odex25_donation/p_donation_gift/models/sale_report.py b/odex25_donation/p_donation_gift/models/sale_report.py new file mode 100644 index 000000000..021da3f70 --- /dev/null +++ b/odex25_donation/p_donation_gift/models/sale_report.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +from odoo import fields, models + + +class SaleReport(models.Model): + _inherit = "sale.report" + + is_gift = fields.Boolean("Order Contains Gift", readonly=True) + first_receiver_number = fields.Char("Receiver Number", readonly=True) + first_receiver_name = fields.Char("Receiver Name", readonly=True) + order_mobile_number = fields.Char("Donor Number", readonly=True) + order_name = fields.Char("Donor Name", readonly=True) + + def _select_additional_fields(self): + res = super()._select_additional_fields() + res['is_gift'] = "s.is_gift" + res['first_receiver_number'] = "s.first_receiver_number" + res['first_receiver_name'] = "s.first_receiver_name" + res['order_mobile_number'] = "s.order_mobile_number" + res['order_name'] = "s.order_name" + return res + + def _group_by_sale(self): + res = super()._group_by_sale() + res += """, + s.is_gift, s.first_receiver_number,s.first_receiver_name,s.order_mobile_number,s.order_name""" + return res diff --git a/odex25_donation/p_donation_gift/static/src/js/gift.js b/odex25_donation/p_donation_gift/static/src/js/gift.js new file mode 100644 index 000000000..f652f5d95 --- /dev/null +++ b/odex25_donation/p_donation_gift/static/src/js/gift.js @@ -0,0 +1,133 @@ +odoo.define('p_donation_gift.gift', function (require) { + + "use strict"; + require('web.dom_ready'); + require('p_donation_theme.product-gift-card'); + var publicWidget = require('web.public.widget'); + const {qweb, _t} = require('web.core'); + + function ArabictoEnglishNumber(strNum) { + var ar = '٠١٢٣٤٥٦٧٨٩'.split(''); + var en = '0123456789'.split(''); + strNum = strNum.replace(/[٠١٢٣٤٥٦٧٨٩]/g, x => en[ar.indexOf(x)]); + strNum = strNum.replace(/[^\d]/g, ''); + return strNum; + } + + function RemoveNumber(strNum) { + strNum = strNum.replace(/[٠١٢٣٤٥٦٧٨٩]/g, ''); + strNum = strNum.replace(/[0123456789]/g, ''); + return strNum; + } + + $('.oe_website_sale form input[name=add_qty]').each(function (index, ev) { + ev.addEventListener("invalid", (e) => { + const validityState = e.target.validity; + if (!validityState.valid) { + ev.setCustomValidity(_t('Please Fill out this field.')); + } else { + ev.target.setCustomValidity(_t('')); + } + }); + }); + + publicWidget.registry.WebsiteSale.include({ + events: _.extend({}, publicWidget.registry.WebsiteSale.prototype.events || {}, { + 'click .gift-product-button': '_open_gift_popup', + }), + + _convert_arabic_to_english(ev) { + ev.currentTarget.value = ArabictoEnglishNumber(ev.currentTarget.value) + if (ev.target.tagName == "INPUT") { + ev.currentTarget.setCustomValidity(_t('')) + } + }, + + _open_gift_popup(ev) { + ev.preventDefault() + ev.stopPropagation() + var gift_form = $(ev.currentTarget).closest('form'); + gift_form[0].reportValidity() + var qty_input = gift_form.find('input[name=add_qty]') + var price = qty_input[0].dataset.price || 1 + var amount = qty_input.val() * price + if (amount <= 0) { + return + } + var product_id = ev.currentTarget.dataset.product_id; + var gift_box_list = [] + $('#action_gift_product_popup input').removeClass("is-valid").removeClass("is-invalid").val(''); + $('#action_gift_product_popup').show(); + $('#action_gift_product_popup').on('show.bs.modal', function (event) { + var modal = $(this) + modal.find('#gift-popup-close').on("click", function() { + modal.find('input').removeClass("is-valid").removeClass("is-invalid").val(''); + modal.hide(); + }) + modal.find('input[inputmode=numeric]').on("change", function( ) { + $(this).val(ArabictoEnglishNumber($(this).val())) + }) + modal.find('input[inputmode!=numeric]').on("change", function( ) { + $(this).val(RemoveNumber($(this).val())) + }) + + modal.find('#gift-popup-buttons a').on("click", function() { + var is_valid = true; + modal.find('input').each(function() { + var current_input = $(this) + if(!current_input.val()){ + current_input.addClass("is-invalid"); + current_input.removeClass("is-valid"); + is_valid = false + } else if(current_input.hasClass('number-input')) { + if (!current_input.val().startsWith('05')) { + current_input.addClass("is-invalid"); + current_input.removeClass("is-valid"); + is_valid = false + } else if (current_input.val().length < 10) { + current_input.addClass("is-invalid"); + current_input.removeClass("is-valid"); + is_valid = false + } else { + current_input.removeClass("is-invalid"); + current_input.addClass("is-valid"); + } + } else { + current_input.removeClass("is-invalid"); + current_input.addClass("is-valid"); + } + }); + if (!is_valid) { + return false + } + + var gift_sender_name = modal.find('input[name=gift_sender_name]').val() + var gift_sender_number = modal.find('input[name=gift_sender_number]').val() + var gift_receiver_name = modal.find('input[name=gift_receiver_name]').val() + var gift_receiver_mobile = modal.find('input[name=gift_receiver_mobile]').val() + + gift_box_list.push({ + product_id: product_id, + donator_name: gift_receiver_name, + donator_mobile_number: gift_receiver_mobile, + donated_amount: amount, + gift_sender_name: gift_sender_name, + gift_sender_mobile: gift_sender_number + }) + gift_form.find('input[name=donate_list]').val(JSON.stringify(gift_box_list)) + gift_form.find('input[name=gift_redirect]').val('/shop/payment') + gift_form.find('button[type=submit]').click() + }) + }) + $("#action_gift_product_popup").modal({backdrop: true}); + $("#action_gift_product_popup").modal('show'); + }, + }); +}) + + + + + + + diff --git a/odex25_donation/p_donation_gift/static/src/scss/gift_popup.scss b/odex25_donation/p_donation_gift/static/src/scss/gift_popup.scss new file mode 100644 index 000000000..ed05ac87d --- /dev/null +++ b/odex25_donation/p_donation_gift/static/src/scss/gift_popup.scss @@ -0,0 +1,29 @@ +#action_gift_product_popup { + z-index:9990; + a,div,input,label,h5 { + font-family: Greta-AR-LT-Bold + } + a { + background-color: #08654e !important; + color: white + } + input { + border-radius: 20px; + color: #929393 !important; + } + label { + color: #08654e !important; + } + h5 { + font-family: Greta-AR-LT-Semibold; + color: #08654e !important; + } + i { + color:#31ae9c !important; + } + #gift-header { + display: flex; + align-items: center; + justify-content: center; + } +} \ No newline at end of file diff --git a/odex25_donation/p_donation_gift/views/sale_view.xml b/odex25_donation/p_donation_gift/views/sale_view.xml new file mode 100644 index 000000000..8dbea2a8f --- /dev/null +++ b/odex25_donation/p_donation_gift/views/sale_view.xml @@ -0,0 +1,149 @@ + + + + + product.template.form.inherit + product.template + + + + + + + + + + extrafield.sale.order.form.view + sale.order + + + + + + +
+ + + + + + +
+
+
+
+ + + sale.report.form.view + sale.report + + + + + + + + + + + + + + + + + + + + + + sale.order.list.select + sale.order + + + + + + + + + + + + + + + + + + + + + + + + + + Group By Gift Sender Number + sale.order + [('is_gift', '=', True)] + + {'group_by': ['order_mobile_number']} + + + Group By Gift Sender Name + sale.order + [('is_gift', '=', True)] + + {'group_by': ['order_name']} + + + Group By Gift Receiver Number + sale.order + [('is_gift', '=', True)] + + {'group_by': ['first_receiver_number']} + + + Group By Gift Receiver Name + sale.order + [('is_gift', '=', True)] + + {'group_by': ['first_receiver_name']} + + + + + Group By Gift Sender Number + sale.report + [('is_gift', '=', True)] + + {'group_by': ['order_mobile_number']} + + + Group By Gift Sender Name + sale.report + [('is_gift', '=', True)] + + {'group_by': ['order_name']} + + + Group By Gift Receiver Number + sale.report + [('is_gift', '=', True)] + + {'group_by': ['first_receiver_number']} + + + Group By Gift Receiver Name + sale.report + [('is_gift', '=', True)] + + {'group_by': ['first_receiver_name']} + +
+
\ No newline at end of file diff --git a/odex25_donation/p_donation_gift/views/website_template.xml b/odex25_donation/p_donation_gift/views/website_template.xml new file mode 100644 index 000000000..b13f8ed75 --- /dev/null +++ b/odex25_donation/p_donation_gift/views/website_template.xml @@ -0,0 +1,136 @@ + + + + + Product Item Grid: Donation Style + qweb + + + + + + + + + + + + + + + margin:5px 0px; #{'width: 100%;' if product.is_gift else ''} + + + + text-align: center !important; + #{'width: 90px;' if not product.is_gift else ''} + + + + + + + + + shop_layout: Donation Style + qweb + p_donation_gift.shop_layout + + + + + + + + + + diff --git a/odex25_donation/p_donation_theme/.idea/.gitignore b/odex25_donation/p_donation_theme/.idea/.gitignore new file mode 100644 index 000000000..26d33521a --- /dev/null +++ b/odex25_donation/p_donation_theme/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/odex25_donation/p_donation_theme/.idea/.name b/odex25_donation/p_donation_theme/.idea/.name new file mode 100644 index 000000000..58e806f80 --- /dev/null +++ b/odex25_donation/p_donation_theme/.idea/.name @@ -0,0 +1 @@ +templates.xml \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/.idea/inspectionProfiles/profiles_settings.xml b/odex25_donation/p_donation_theme/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 000000000..105ce2da2 --- /dev/null +++ b/odex25_donation/p_donation_theme/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/.idea/misc.xml b/odex25_donation/p_donation_theme/.idea/misc.xml new file mode 100644 index 000000000..d1e22ecb8 --- /dev/null +++ b/odex25_donation/p_donation_theme/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/.idea/modules.xml b/odex25_donation/p_donation_theme/.idea/modules.xml new file mode 100644 index 000000000..1e546e9f7 --- /dev/null +++ b/odex25_donation/p_donation_theme/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/.idea/p_donation_theme.iml b/odex25_donation/p_donation_theme/.idea/p_donation_theme.iml new file mode 100644 index 000000000..d0876a78d --- /dev/null +++ b/odex25_donation/p_donation_theme/.idea/p_donation_theme.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/LICENSE b/odex25_donation/p_donation_theme/LICENSE new file mode 100644 index 000000000..7a5c68e71 --- /dev/null +++ b/odex25_donation/p_donation_theme/LICENSE @@ -0,0 +1,27 @@ +Odoo Proprietary License v1.0 + +This software and associated files (the "Software") may only be used (executed, +modified, executed after modifications) if you have purchased a valid license +from the authors, typically via Odoo Apps, or if you have received a written +agreement from the authors of the Software (see the COPYRIGHT file). + +You may develop Odoo modules that use the Software as a library (typically +by depending on it, importing it and using its resources), but without copying +any source code or material from the Software. You may distribute those +modules under the license of your choice, provided that this license is +compatible with the terms of the Odoo Proprietary License (For example: +LGPL, MIT, or proprietary licenses similar to this one). + +It is forbidden to publish, distribute, sublicense, or sell copies of the Software +or modified copies of the Software. + +The above copyright notice and this permission notice must be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/__init__.py b/odex25_donation/p_donation_theme/__init__.py new file mode 100644 index 000000000..511a0ca3a --- /dev/null +++ b/odex25_donation/p_donation_theme/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import controllers +from . import models \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/__manifest__.py b/odex25_donation/p_donation_theme/__manifest__.py new file mode 100644 index 000000000..f5583dbde --- /dev/null +++ b/odex25_donation/p_donation_theme/__manifest__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +{ + 'name': "Ensan.sa new donation platform", + 'summary': 'Ensan.sa new donation platform', + 'description': 'this module changes odoo e-commerce interface to Ensan.sa interface', + 'author': 'VarietyIT', + 'maintainer': 'VarietyIT', + 'company': 'VarietyIT', + 'website': 'https://varietyit.com', + 'price': 5000, + 'currency': 'USD', + 'license': 'LGPL-3', + 'category': 'Uncategorized', + 'version': '16.0.4', + 'depends': ['base', 'website_sale', 'theme_prime', 'droggol_theme_common', 'payment_hyperpay', 'payment_applepay'], + + 'data': [ + 'security/ir.model.access.csv', + 'views/templates.xml', + 'views/views.xml', + 'data/sms_data.xml' + ], + 'assets': { + 'web.assets_frontend': [ + 'p_donation_theme/static/src/scss/hyperpay_quick_donation.scss', + 'p_donation_theme/static/src/scss/theme.scss', + 'p_donation_theme/static/src/js/*.js', + 'p_donation_theme/static/src/xml/donation.xml', + ], + 'web._assets_primary_variables': [ + "p_donation_theme/static/src/scss/primary_variables.scss", + ], + 'website.assets_editor': [ + 'p_donation_theme/static/src/js/components/*.js' + ] + }, + 'images': ['static/description/banner.png'], +} diff --git a/odex25_donation/p_donation_theme/controllers/__init__.py b/odex25_donation/p_donation_theme/controllers/__init__.py new file mode 100644 index 000000000..deec4a8b8 --- /dev/null +++ b/odex25_donation/p_donation_theme/controllers/__init__.py @@ -0,0 +1 @@ +from . import main \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/controllers/main.py b/odex25_donation/p_donation_theme/controllers/main.py new file mode 100644 index 000000000..42d4f43bf --- /dev/null +++ b/odex25_donation/p_donation_theme/controllers/main.py @@ -0,0 +1,229 @@ +from odoo import http, _ +from odoo.addons.website_sale.controllers.main import PaymentPortal +from odoo.exceptions import ValidationError +from odoo.http import request +import requests, logging +import phonenumbers +from phonenumbers.phonenumberutil import NumberParseException + +_logger = logging.getLogger(__name__) + + + +class PaymentPortalExtraFields(PaymentPortal): + + def check_mobile_number_validation(self, phone): + if phone[0] == '+' and phone[1] != '0': + if phone[1:4] == '966': + if len(phone[4:]) >= 8: + return phone + else: + phone = phone[0] + '966' + phone[1:] + elif phone[0] == '+' and phone[1] == '0': + phone = phone[0] + '966' + phone[2:] + elif phone[0] == '0' and phone[1] == '5': + phone = '+966' + phone[1:] + elif phone[0:2] == '00': # 00966555555555 + if phone[2:5] == '966': + phone = '+' + '966' + phone[5:] + elif phone[0] == '0': # 0966555555555 + if phone[1:4] == '966': + phone = '+' + '966' + phone[4:] + else: + if phone[0:3] == '966': + phone = '+' + phone + else: + phone = '+' + '966' + phone + return phone + + @http.route() + def shop_payment_transaction(self, *args, **kwargs): + order = request.website.sale_get_order() + if order: + try: + string_phone_number = kwargs.get('extra_mobile', '') + string_name = kwargs.get('extra_name', '') + if string_phone_number: + string_phone_number = kwargs.get('extra_mobile', '') + # string_phone_number = '+' + str(string_phone_number) + string_phone_number = self.check_mobile_number_validation(string_phone_number) + phone_number = phonenumbers.parse(string_phone_number) + is_valid = phonenumbers.is_possible_number(phone_number) + if not is_valid: + raise ValidationError(_('Mobile Number is invalid!')) + order.sudo().write({ + 'order_mobile_number': string_phone_number, + }) + if string_name: + order.sudo().write({ + 'order_name': string_name + }) + except NumberParseException: + raise ValidationError(_('Mobile Number is invalid!')) + except Exception as e: + raise ValidationError(_(e)) + return super().shop_payment_transaction(*args, **kwargs) + + @http.route( + '/quickpay/hyperpay/payment', type='json', auth='public', website=True + ) + def quick_hyperpay_payment(self, **kw): + success = False + order = request.website.sale_get_order(force_create=True) + test_domain = "https://test.oppwa.com/v1/payments" + live_domain = "https://oppwa.com/v1/payments" + product_id = kw.pop('product_id') + if order: + if product_id: + product_id = request.env['product.product'].sudo().browse(int(product_id)) + if product_id: + order.order_line.sudo().unlink() + order.write({ + 'order_line': + [(0, 0, { + 'product_id': product_id.id, + 'product_uom_qty': 1, + 'price_unit': float(kw.get('amount')), + 'product_uom': product_id.uom_id.id + })] + }) + try: + payment_acquire_id = request.env['payment.provider'].search([('code', '=','hyperpay'), ('company_id', 'in', (False, order.company_id.id))], limit=1) + temp_vals = { + 'access_token': order._portal_ensure_token(), + 'order_id': order.id, + 'payment_option_id': payment_acquire_id.id, + 'flow': 'direct', + 'tokenization_requested': False, + 'landing_route': '/', + 'currency_id': order.currency_id.id, + } + vals = self.shop_payment_transaction(**(temp_vals)) + payment_sudo = request.env['payment.transaction'].sudo() + tx = payment_sudo.search([('reference', '=', vals.get('reference', False))], limit=1) + if tx: + acq = tx.provider_id + payment_vals = { + "entityId": acq.hyperpay_merchant_id, + "amount": '%.2f' % tx.amount, + "currency": tx.currency_id and tx.sudo().currency_id.name or '', + "paymentType": "DB", + "customParameters[SHOPPER_tx_id]": tx.id, + "merchantTransactionId": tx.id, + 'paymentBrand': kw.get('paymentBrand'), + 'card.number': int(kw.get('card.number')), + 'card.holder': kw.get('card.holder'), + 'card.expiryMonth': '%02d' % int(kw.get('card.expiryMonth')), + 'card.expiryYear': kw.get('card.expiryYear'), + 'card.cvv': '%03d' % int(kw.get('card.cvv')), + } + try: + headers = { + "Authorization": "Bearer " + acq.hyperpay_authorization, + } + if acq.state == 'enabled': + p_url = live_domain + else: + p_url = test_domain + hyper_response = requests.post(url=p_url, data=payment_vals, headers=headers) + hyper_response = hyper_response.json() + tx.hyperpay_checkout_id = hyper_response.get('id') + hyper_response.update({ + 'tx_id': hyper_response.get('customParameters', {}).get('SHOPPER_tx_id') or tx and tx.id or '' + }) + tx._handle_notification_data('hyperpay', hyper_response) + confirmed_orders = tx._check_amount_and_confirm_order() + confirmed_orders._send_order_confirmation_mail() + if tx and tx.state == 'done': + success = True + except Exception as e: + _logger.info("Error in Quick Donation Payment: %s" % (e)) + except Exception as e: + _logger.info("Error in Quick Donation Payment: %s" % (e)) + return { + 'success': success, + } + + @http.route( + '/quickpay/hyperpay/payment/create', type='json', auth='public', website=True + ) + def quick_hyperpay_payment_trans_create(self, **kw): + success = False + order = request.website.sale_get_order(force_create=True) + product_id = kw.pop('product_id') + acquire_id = kw.pop('acquire_id') + mobile = kw.pop('mobile') + if order: + if product_id: + product_id = request.env['product.product'].sudo().browse(int(product_id)) + if product_id: + order.order_line.sudo().unlink() + order.write({ + 'order_line': + [(0, 0, { + 'product_id': product_id.id, + 'product_uom_qty': 1, + 'price_unit': float(kw.get('amount')), + 'product_uom': product_id.uom_id.id + })], + 'order_mobile_number': mobile + }) + try: + if acquire_id: + payment_acquire_id = request.env['payment.provider'].sudo().search( + [('code', 'in', ['hyperpay', 'applepay']), ('company_id', 'in', (False, order.company_id.id)), ('id', '=', int(acquire_id))], limit=1) + else: + payment_acquire_id = request.env['payment.provider'].sudo().search( + [('code', '=', 'hyperpay'), ('company_id', 'in', (False, order.company_id.id))], limit=1) + temp_vals = { + 'access_token': order._portal_ensure_token(), + 'order_id': order.id, + 'payment_option_id': payment_acquire_id.id, + 'flow': 'direct', + 'tokenization_requested': False, + 'landing_route': '/', + 'currency_id': order.currency_id.id, + } + vals = self.shop_payment_transaction(**(temp_vals)) + payment_sudo = request.env['payment.transaction'].sudo() + tx = payment_sudo.search([('reference', '=', vals.get('reference', False))], limit=1) + for sale in tx.sale_order_ids: + sale.done_with_quick_donation = True + final_vals = { + 'success': True, + 'tx_id': tx.id + } + if payment_acquire_id and payment_acquire_id.code == 'applepay' and tx: + redirect_url = '/quick/applepay/payment?tx=%s' % (tx.id) + final_vals.update({ + 'redirect_url': redirect_url + }) + return final_vals + except Exception as e: + _logger.info("Error in Quick Donation Payment: %s" % (e)) + return { + 'success': success, + } + + @http.route('/quick/applepay/payment', type='http', auth='public', website=True, csrf=False) + def apple_pay_payment_method(self, **kwargs): + tx = kwargs.get('tx') + payment_sudo = request.env['payment.transaction'].sudo() + tx = payment_sudo.search([('id', '=', int(tx))], limit=1) + if tx: + kw = tx._get_processing_values() + kw = tx._get_specific_rendering_values(kw) + + acquirer = request.env['payment.provider'].sudo().search([('code', '=', 'applepay')], limit=1) + + kw['currency'] = 'SAR' + _logger.info("Post Values From Apple Payment = %s" % (kw)) + + if acquirer.state == 'test': + return request.render("payment_applepay.payment_applepay_card", + {'check_out_id': kw.get('check_out_id'), 'return_url': kw.get('applepay_return')}) + else: + return request.render("payment_applepay.payment_applepay_card_live", + {'check_out_id': kw.get('check_out_id'), 'return_url': kw.get('applepay_return')}) + else: + return request.redirect('/') diff --git a/odex25_donation/p_donation_theme/data/sms_data.xml b/odex25_donation/p_donation_theme/data/sms_data.xml new file mode 100644 index 000000000..b176d1849 --- /dev/null +++ b/odex25_donation/p_donation_theme/data/sms_data.xml @@ -0,0 +1,18 @@ + + + + Donation Confirmed + + ar + عطاؤكم أثرٌ يبقى .. بلّغكم الله مرافقة النبي صلى الله عليه وسلم في الجنة.سند التبرع:{{object.sale_order_portal_url}} + + + + Donation on Behalf Confirmed + + ar + بكل الود أهديك تبرع عبر منصة إنسان لمشروع: {{object.product_id.name}} من : {{object.sale_id.order_name}} + + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/i18n/ar.po b/odex25_donation/p_donation_theme/i18n/ar.po new file mode 100644 index 000000000..f159ec585 --- /dev/null +++ b/odex25_donation/p_donation_theme/i18n/ar.po @@ -0,0 +1,954 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * p_donation_theme +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-08-24 09:03+0000\n" +"PO-Revision-Date: 2023-08-24 09:03+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: p_donation_theme +#. odoo-python +#: code:addons/p_donation_theme/models/product.py:0 +#, python-format +msgid " Days" +msgstr "ايام" + +#. module: p_donation_theme +#. odoo-python +#: code:addons/p_donation_theme/models/product.py:0 +#, python-format +msgid " Month " +msgstr " شهر " + +#. module: p_donation_theme +#. odoo-python +#: code:addons/p_donation_theme/models/product.py:0 +#, python-format +msgid " Year" +msgstr " سنه" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.payment_sale_extra_field +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "05XXXXXXXX" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "10" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "" +"10\n" +" SAR" +msgstr "" +"10\n" +" رس" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "10 Saudi riyals" +msgstr "10 ريال سعودي" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "100" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "" +"100\n" +" SAR" +msgstr "" +"100\n" +" رس" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "100 Saudi riyals" +msgstr "100 ريال سعودي" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "50" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "" +"50\n" +" SAR" +msgstr "" +"50\n" +" رس" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "50 Saudi riyals" +msgstr "50 ريال سعودى" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "5xxxxxxxx" +msgstr "5xxxxxxxx" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tShare\n" +"\t\t\t\t\t\t\t\t\t\t\t\t\t\t" +msgstr "" +"\n" +"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tسهم\n" +"\t\t\t\t\t\t\t\t\t\t\t\t\t\t" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"Donate For " +"Someone Else" +msgstr "تبرع عن شخص اخر" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Loading..." +msgstr "جاري التحميل ..." + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "100" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "10" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "50" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "+" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "" +"\n" +"\t\t\t\t\t\t\t\t\t\t\tCase Number:\n" +"\t\t\t\t\t\t\t\t\t\t" +msgstr "" +"\n" +"\t\t\t\t\t\t\t\t\t\t\tرقم الحالة:\n" +"\t\t\t\t\t\t\t\t\t\t" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" Last donation\n" +" " +msgstr "" +"\n" +" اخر تبرع منذ\n" +" " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" The number of beneficiaries\n" +" " +msgstr "" +"\n" +" عدد المستفيدين\n" +" " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" The number of donations is\n" +" " +msgstr "" +"\n" +" عدد التبرعات هو\n" +" " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" Visits\n" +" " +msgstr "" +"\n" +" &nbsp;الزيارات" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" sharing\n" +" \n" +" " +msgstr "" +"\n" +" مشاركه\n" +" \n" +" " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" Case number\n" +" " +msgstr "" +"\n" +" رقم الحاله\n" +" " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" The unit price is\n" +" " +msgstr "" +"\n" +" قيمة التبرع\n" +" " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "SAR" +msgstr "" +"ر " +"س" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Remaining amount" +msgstr "المتبقي" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Residual" +msgstr "المتبقي" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Target" +msgstr "المستهدف" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "has been supported" +msgstr "تم دعم" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" so far\n" +" " +msgstr "" +"\n" +" حتى الان\n" +" " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" visits\n" +" " +msgstr "" +"\n" +" زيارة\n" +" " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "" +"\n" +" \n" +" " +msgstr "" +"\n" +" \n" +" " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "" +"Click to open the Quick Donate box in a pop-up window\n" +" Click to close the Quick Donate box." +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" The target number is\n" +" " +msgstr "" +"\n" +" العدد المستهدف\n" +" " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"\n" +" beneficiaries\n" +" " +msgstr "" +"\n" +" مستفيد\n" +" " + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_needaction +msgid "Action Needed" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.cart_lines +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "Add one" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "Add to Cart" +msgstr "اضف الي السله" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "All Products" +msgstr "كل فرص التبرع" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__donated_amount +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "Amount" +msgstr "قيمه التبرع" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__done_percentage +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__done_percentage +msgid "Amount Percentage " +msgstr "النسبه المئويه" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Another Amount" +msgstr "قيمه اخرى" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Another donation amount" +msgstr "مبلغ تبرع اخر" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_attachment_count +msgid "Attachment Count" +msgstr "اضف العدد" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__beneficiaries +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__beneficiaries +msgid "Beneficiaries" +msgstr "المستفيدين" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__beneficiaries_been_supported +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__beneficiaries_been_supported +msgid "Beneficiaries Been Supported" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__done_beneficiaries_percentage +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__done_beneficiaries_percentage +msgid "Beneficiaries Percentage " +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__beneficiaries_residual +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__beneficiaries_residual +msgid "Beneficiaries Residual" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "Case Details" +msgstr "تفاصيل المشروع" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Choose the donation amount" +msgstr "اختار مبلغ التبرع" + +#. module: p_donation_theme +#. odoo-javascript +#: code:addons/p_donation_theme/static/src/xml/donation.xml:0 +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +#, python-format +msgid "Close" +msgstr "اغلق" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__donated_amount +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__donated_amount +msgid "Collected Amount" +msgstr "تم جمع" + +#. module: p_donation_theme +#. odoo-javascript +#: code:addons/p_donation_theme/static/src/xml/donation.xml:0 +#, python-format +msgid "Copy link" +msgstr "انسخ الرابط" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__create_uid +msgid "Created by" +msgstr "انشئ بواسطه" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__create_date +msgid "Created on" +msgstr "انشئ في" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Default select example" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__display_name +msgid "Display Name" +msgstr "الاسم" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "Donate Now" +msgstr "تبرع الان" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Donate On Behalf" +msgstr "تبرع عن" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Donate now" +msgstr "تبرع الأن" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Donate now to facilitate" +msgstr "تبرع الان لتسهيل" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"Donate on behalf\n" +" of your family or friends and share the reward with\n" +" them" +msgstr "تبرع عن أهلك أو أصدقائك وشاركهم الأجر" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "" +"Donate on behalf of your family or friends and share the reward with them" +msgstr "تبرع عن أهلك أو أصدقائك وشاركهم الأجر" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_template_inherit_form +msgid "Donation" +msgstr "تبرع" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "Donation Amount" +msgstr "قيمه التبرع" + +#. module: p_donation_theme +#: model:sms.template,name:p_donation_theme.sms_template_data_donation +msgid "Donation Confirmed" +msgstr "تم تاكيد التبرع" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__donation_type +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__donation_type +msgid "Donation Type" +msgstr "نوع التبرع" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Donation amount" +msgstr "قيمه التبرع" + +#. module: p_donation_theme +#: model:sms.template,name:p_donation_theme.sms_template_donors_data_donation +msgid "Donation on Behalf Confirmed" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order__donators_ids +#: model_terms:ir.ui.view,arch_db:p_donation_theme.view_order_form +msgid "Donators" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order__order_name +msgid "Donor Name" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order__order_mobile_number +msgid "Donor Number" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Enter the amount" +msgstr "ادخل القيمه" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.payment_sale_extra_field +msgid "Enter your name" +msgstr "الاسم" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_line__extra_donators_ids +msgid "Extra Donators" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields.selection,name:p_donation_theme.selection__product_template__donation_type__fixed_amount +msgid "Fixed Amount" +msgstr "مبلغ ثابت" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_follower_ids +msgid "Followers" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_partner_ids +msgid "Followers (Partners)" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields.selection,name:p_donation_theme.selection__product_template__donation_type__free_amount +msgid "Free Amount" +msgstr "اي قيمه" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Full Name" +msgstr "الاسم بالكامل" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__has_message +msgid "Has Message" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__id +msgid "ID" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,help:p_donation_theme.field_sale_order_extra_donators__message_needaction +msgid "If checked, new messages require your attention." +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,help:p_donation_theme.field_sale_order_extra_donators__message_has_error +#: model:ir.model.fields,help:p_donation_theme.field_sale_order_extra_donators__message_has_sms_error +msgid "If checked, some messages have a delivery error." +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Interactive box." +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Invalid Amount!" +msgstr "قيمة غير صحيحة" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Invalid Mobile Number!" +msgstr ":رقم الجوال خطأ، الصيغة الصحيحة 05XXXXXXXXX" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Invalid Name!" +msgstr "اسم خاطئ" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__is_donation +msgid "Is Donation Product?" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__is_donation +msgid "Is Donation Variant?" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_is_follower +msgid "Is Follower" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__is_quick_donation +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__is_quick_donation +msgid "Is Quick Donation?" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators____last_update +msgid "Last Modified on" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__write_date +msgid "Last Updated on" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__line_id +msgid "Line" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_main_attachment_id +msgid "Main Attachment" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_has_error +msgid "Message Delivery error" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_ids +msgid "Messages" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__donator_mobile_number +#: model_terms:ir.ui.view,arch_db:p_donation_theme.payment_sale_extra_field +msgid "Mobile" +msgstr "الجوال" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Mobile Number" +msgstr "رقم الجوال" + +#. module: p_donation_theme +#. odoo-python +#: code:addons/p_donation_theme/controllers/main.py:0 +#: code:addons/p_donation_theme/controllers/main.py:0 +#, python-format +msgid "Mobile Number is invalid!" +msgstr "رقم الجوال خاطئ. برجاء ادخال الرقم 05xxxxxxxx" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__donator_name +msgid "Name" +msgstr "الاسم" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__number_of_donations +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__number_of_donations +msgid "Number Of Donation" +msgstr "عدد التبرعات" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_needaction_counter +msgid "Number of Actions" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_has_error_counter +msgid "Number of errors" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,help:p_donation_theme.field_sale_order_extra_donators__message_needaction_counter +msgid "Number of messages which requires an action" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,help:p_donation_theme.field_sale_order_extra_donators__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Other amount (SAR)" +msgstr "مبلغ اخر" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Payment Failed!" +msgstr "خطا في الدفع" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Payment Received!" +msgstr "تم استلام التبرع" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Please Try again after Sometime." +msgstr "" + +#. module: p_donation_theme +#: model:ir.model,name:p_donation_theme.model_product_template +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__product_id +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__product_ids +msgid "Product" +msgstr "المنتج" + +#. module: p_donation_theme +#: model:ir.model,name:p_donation_theme.model_product_product +msgid "Product Variant" +msgstr "متغير المنتج " + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Quick donation" +msgstr "التبرع السريع" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Quick donation options" +msgstr "خيارات التبرع السريع" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "Remaining" +msgstr "المتبقي" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__remaining_amount +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__remaining_amount +msgid "Remaining Amount" +msgstr "المتبقي" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Remove GiftCard" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.cart_lines +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "Remove one" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__message_has_sms_error +msgid "SMS Delivery error" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__sale_id +msgid "Sale Order" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order__sale_order_portal_url +msgid "Sale Order Url" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model,name:p_donation_theme.model_sale_order +msgid "Sales Order" +msgstr "أمر البيع" + +#. module: p_donation_theme +#: model:ir.model,name:p_donation_theme.model_sale_order_line +msgid "Sales Order Line" +msgstr "بند أمر المبيعات" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "Share" +msgstr "مشاركه" + +#. module: p_donation_theme +#. odoo-javascript +#: code:addons/p_donation_theme/static/src/xml/donation.xml:0 +#, python-format +msgid "Share link" +msgstr "رابط المشاركة" + +#. module: p_donation_theme +#. odoo-javascript +#: code:addons/p_donation_theme/static/src/xml/donation.xml:0 +#, python-format +msgid "Share via Facebook" +msgstr "" + +#. module: p_donation_theme +#. odoo-javascript +#: code:addons/p_donation_theme/static/src/xml/donation.xml:0 +#, python-format +msgid "Share via Twitter" +msgstr "" + +#. module: p_donation_theme +#. odoo-javascript +#: code:addons/p_donation_theme/static/src/xml/donation.xml:0 +#, python-format +msgid "Share via WhatsApp" +msgstr "" + +#. module: p_donation_theme +#. odoo-javascript +#: code:addons/p_donation_theme/static/src/xml/donation.xml:0 +#, python-format +msgid "Share via social media" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Share your donation on social media" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.product_item_grid_3 +msgid "Target" +msgstr "المستهدف" + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_product_product__target_amount +#: model:ir.model.fields,field_description:p_donation_theme.field_product_template__target_amount +msgid "Target Amount" +msgstr "المستهدف" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Thanks for the Donation!" +msgstr "شكرا لتبرعك" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Valid Amount!" +msgstr "قيمه صحيحه" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +msgid "Valid Name!" +msgstr "اسم صحيح" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "Valid Number!" +msgstr "رقم صحيح" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "" +"We are Processing your Payment!\n" +"
\n" +" Please do not refresh/close this window or click the Back button on your browser." +msgstr "" +"نقوم بمعالجه تبرعك!\n" +"
\n" +" من فضلك لا تغلق او تحدث المتصفح." + +#. module: p_donation_theme +#: model:ir.model.fields,field_description:p_donation_theme.field_sale_order_extra_donators__website_message_ids +msgid "Website Messages" +msgstr "" + +#. module: p_donation_theme +#: model:ir.model.fields,help:p_donation_theme.field_sale_order_extra_donators__website_message_ids +msgid "Website communication history" +msgstr "" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.payment_sale_extra_field +msgid "Your Name" +msgstr "الاسم(اختياري)" + +#. module: p_donation_theme +#: model_terms:ir.ui.view,arch_db:p_donation_theme.donation_product_detail_layout +#: model_terms:ir.ui.view,arch_db:p_donation_theme.quick_donation_layout +msgid "amount value" +msgstr "قيمة التبرع" + +#. module: p_donation_theme +#: model:ir.model,name:p_donation_theme.model_sale_order_extra_donators +msgid "sale.order.extra_donators" +msgstr "" + +#. module: p_donation_theme +#. odoo-javascript +#: code:addons/p_donation_theme/static/src/xml/donation.xml:0 +#, python-format +msgid "twitter-icon" +msgstr "" + +#. module: p_donation_theme +#: model:sms.template,body:p_donation_theme.sms_template_data_donation +msgid "" +"عطاؤكم أثرٌ يبقى .. بلّغكم الله مرافقة النبي صلى الله عليه وسلم في " +"الجنة.سند التبرع:{{object.sale_order_portal_url}}" +msgstr "" + +#. module: p_donation_theme +#: model:sms.template,body:p_donation_theme.sms_template_donors_data_donation +msgid "" +"محبةً لك، أهديك تبرع عبر منصة إنسان لمشروع ( {{object.product_id.with_context({'lang':'ar_001'}).name}} ) بلّغكم الله مرافقة النبي ﷺ في الجنّة. إهداء من : {{object.sale_id.order_name}} \n" +"https://ensan.sa/dedicationcard/{{object.product_id.with_context({'lang':'ar_001'}).name.replace(' ','%20')}}{{'&from='}}{{str(object.sale_id.order_name).replace(' ','%20')}}{{'&to='}}{{object.donator_name.replace(' ','%20')}} " +msgstr "" +"محبةً لك، أهديك تبرع عبر منصة إنسان لمشروع ( " +"{{object.product_id.with_context({'lang':'ar_001'}).name}} ) بلّغكم الله " +"مرافقة النبي ﷺ في الجنّة. إهداء من : {{object.sale_id.order_name}} " +"https://ensan.sa/dedicationcard/{{object.product_id.with_context({'lang':'ar_001'}).name.replace('" +" ','%20')}}{{'&from='}}{{str(object.sale_id.order_name).replace(' " +"','%20')}}{{'&to='}}{{object.donator_name.replace(' ','%20')}} " diff --git a/odex25_donation/p_donation_theme/models/__init__.py b/odex25_donation/p_donation_theme/models/__init__.py new file mode 100644 index 000000000..114b41426 --- /dev/null +++ b/odex25_donation/p_donation_theme/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import sale, product \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/models/product.py b/odex25_donation/p_donation_theme/models/product.py new file mode 100644 index 000000000..409009af4 --- /dev/null +++ b/odex25_donation/p_donation_theme/models/product.py @@ -0,0 +1,206 @@ +from odoo import models, fields, api, _ +from dateutil.relativedelta import relativedelta +from datetime import datetime +import calendar +import time +import logging +logger = logging.getLogger(__name__) + + +class ProductTemplate_Inherit(models.Model): + _inherit = 'product.template' + + is_donation = fields.Boolean("Is Donation Product?", default=True) + donation_type = fields.Selection( + [ + ('Free Amount', 'Free Amount'), + ('Fixed Amount', 'Fixed Amount') + ], + default="Free Amount" + ) + is_quick_donation = fields.Boolean("Is Quick Donation?") + target_amount = fields.Integer('Target Amount', tracking=True, default=1) + donated_amount = fields.Integer(string="Collected Amount", tracking=True, compute="_compute_total_sold_amount", store=False) + remaining_amount = fields.Integer('Remaining Amount') + done_percentage = fields.Integer('Amount Percentage ',store=True) + number_of_donations = fields.Integer(string="Number Of Donation", tracking=True, + compute="_compute_number_of_donations", store=False) + beneficiaries = fields.Integer('Beneficiaries', default=1) + beneficiaries_been_supported = fields.Integer(string="Beneficiaries Been Supported", tracking=True, + compute="_compute_beneficiaries_been_supported", store=False) + beneficiaries_residual = fields.Integer('Beneficiaries Residual', compute='_get_beneficiaries_residual') + done_beneficiaries_percentage = fields.Integer('Beneficiaries Percentage ', compute='get_done_beneficiaries_percentage') + + def get_product_visitors_info(self, domain=''): + sale_ids = self.env['sale.order.line'].sudo().search( + [('product_id.product_tmpl_id', '=', self.id), ('order_id', '!=', False), ('state', 'not in', ['draft', 'sent', 'cancel'])]) + visit_id = self.env['website.track'].sudo().search([('url', '=', domain + self.website_url)]) + tot_sec = 0 + last_order_duration=False + if sale_ids: + t_start = sale_ids[0].order_id.date_order + t_end = datetime.now() + duration = t_end - t_start + tot_sec = round(duration.total_seconds()) + if 1 < tot_sec < 60: + last_order_duration = str(int(tot_sec)) + " ثانيه" + elif 60 < tot_sec < 3600: + last_order_duration = str(int(tot_sec/60)) + " دقيقه" + elif 3600 < tot_sec < 86400: + last_order_duration = str(int(tot_sec/3600)) + " ساعه" + elif 86400 < tot_sec < 2592000: + last_order_duration = str(int(tot_sec/86400)) + " يوم" + elif 2592000 < tot_sec < 31104000: + last_order_duration = str(int(tot_sec/2592000)) + " شهر" + elif tot_sec > 31104000: + last_order_duration = str(int(tot_sec/31104000)) + " سنه" + + return { + 'visits': len(visit_id), + 'last_order': last_order_duration, + 'total_order': len(sale_ids) + } + + # When the product is 100% complete the product is deleted + # @api.onchange('done_percentage') + # def onchange_done_percentage(self): + # logger.info("Done Percentage Change %s",self.done_percentage) + # if self.done_percentage and self.done_percentage == 100: + # self.sale_ok = False + + @api.depends('end_donation_date') + def _get_date_remaining(self): + for rec in self: + date_remaining = '' + if rec.end_donation_date: + end_data = fields.Datetime.now() + delta = relativedelta(end_data, rec.end_donation_date) + if delta.years <= 2: + date_remaining = str(delta.months) + _(" Month ") + str(delta.days) + _(" Days") + else: + date_remaining = str(delta.years) + _(" Year") + rec.date_remaining = date_remaining + + + @api.depends('beneficiaries', 'beneficiaries_been_supported') + def _get_beneficiaries_residual(self): + for rec in self: + rec.beneficiaries_residual = rec.beneficiaries - rec.beneficiaries_been_supported + + @api.depends('target_amount', 'donated_amount') + def _get_remaining_amount(self): + for rec in self: + rec.remaining_amount = rec.target_amount - rec.donated_amount + + @api.depends('target_amount', 'donated_amount') + def get_done_percentage(self): + for rec in self: + if rec.target_amount: + rec.done_percentage = (rec.donated_amount / rec.target_amount) * 100 + # When the product is 100% complete the product is deleted + if rec.done_percentage >= 100 and rec.target_amount != 1: + rec.sale_ok = False + else: + rec.done_percentage = 0 + return str(rec.done_percentage) + '%' + + @api.depends('beneficiaries', 'beneficiaries_been_supported') + def get_done_beneficiaries_percentage(self): + for rec in self: + if rec.beneficiaries: + rec.done_beneficiaries_percentage = (rec.beneficiaries_been_supported / rec.beneficiaries) * 100 + else: + rec.done_beneficiaries_percentage = 0 + return str(rec.done_beneficiaries_percentage) + '%' + + def _compute_number_of_donations(self): + for rec in self: + # all_invoices_paid = self.env['account.move'].search([('move_type', '=', 'out_invoice'), ('payment_state', '=', 'paid')]) + all_invoices_paid = self.env['account.move.line'].search( + [ + ('move_id.move_type', '=', 'out_invoice'), ('move_id.payment_state', '=', 'paid'), + ('product_id.product_tmpl_id', '=', rec.id) + ]) + invoices_counter = 0 + if all_invoices_paid: + + # for invoice_line in all_invoices_paid.invoice_line_ids: + # if invoice_line.product_id.product_tmpl_id.id == rec.id: + # #Exists + # invoices_counter +=1 + # continue + invoices_counter = len(all_invoices_paid) + + rec['number_of_donations'] = invoices_counter + + + else: + rec['number_of_donations'] = 0 + + """ + all_invoices_paid = self.env['account.move.line'].search( + [ + ('move_id.move_type', '=', 'out_invoice'), ('move_id.payment_state', '=', 'paid'), + ('product_id.product_tmpl_id', '=', rec.id) + ]) + total_sum = 0 + if all_invoices_paid: + for invoice_order_line in all_invoices_paid: + if rec.donation_type == "Free Amount": + total_sum += invoice_order_line.price_total + else: + total_sum += invoice_order_line.quantity + rec['number_of_donations'] = total_sum + else: + rec['number_of_donations'] = 0 + """ + + def _compute_beneficiaries_been_supported(self): + for rec in self: + + all_invoices_paid = self.env['account.move.line'].search( + [ + ('move_id.move_type', '=', 'out_invoice'), ('move_id.payment_state', '=', 'paid'), + ('product_id.product_tmpl_id', '=', rec.id) + ]) + total_sum = 0 + if all_invoices_paid: + # for invoice_order_line in all_invoices_paid: + # total_sum += invoice_order_line.price_total + total_sum = sum(all_invoices_paid.mapped('price_total')) + rec['beneficiaries_been_supported'] = total_sum / rec.list_price if rec.list_price != 0 else total_sum + else: + rec['beneficiaries_been_supported'] = 0 + + def _compute_total_sold_amount(self): + for rec in self: + + # all_invoices_paid = self.env['account.move.line'].search( + # [ + # ('move_id.move_type', '=', 'out_invoice'), ('move_id.payment_state', '=', 'paid'), + # ('product_id.product_tmpl_id', '=', rec.id) + # ]) + all_invoices_paid = self.env['account.move.line'].search( + [ + ('move_id.move_type', '=', 'out_invoice'), ('move_id.payment_state', '=', 'paid'), + ('product_id.product_tmpl_id', '=', rec.id) + ]) + + total_sum = 0 + if all_invoices_paid: + # for invoice_order_line in all_invoices_paid: + # total_sum += invoice_order_line.price_total + total_sum = sum(all_invoices_paid.mapped('price_total')) + rec['donated_amount'] = total_sum + + else: + rec['donated_amount'] = 0 + + + + + +class ProductProduct_Inherit(models.Model): + _inherit = 'product.product' + + is_donation = fields.Boolean('Is Donation Variant?', related="product_tmpl_id.is_donation") diff --git a/odex25_donation/p_donation_theme/models/sale.py b/odex25_donation/p_donation_theme/models/sale.py new file mode 100644 index 000000000..2b6961ab0 --- /dev/null +++ b/odex25_donation/p_donation_theme/models/sale.py @@ -0,0 +1,120 @@ +from odoo import models, fields, api +from odoo.tools.json import scriptsafe as json_scriptsafe + + +class SaleOrder_Inherit(models.Model): + _inherit = 'sale.order' + done_with_quick_donation = fields.Boolean(default=False) + order_mobile_number = fields.Char("Donor Number") + order_name = fields.Char("Donor Name") + sale_order_portal_url = fields.Char("Sale Order Url", compute="get_sale_order_portal_url") + donators_ids = fields.One2many('sale.order.extra_donators', 'sale_id', string="Donators", store=True, readonly=True) + + def get_sale_order_portal_url(self): + for sale in self: + sale.sale_order_portal_url = self.env['ir.config_parameter'].sudo().get_param( + 'web.base.url') + sale.get_portal_url() + + def _cart_update(self, *args, **kwargs): + res = super(SaleOrder_Inherit, self)._cart_update(*args, **kwargs) + order_line = self.env['sale.order.line'].browse(res.get('line_id')) + qty = kwargs.get('add_qty', False) or kwargs.get('set_qty', False) + if qty and order_line: + self.convert_donation_qty_to_price(order_line, qty) + return res + + def convert_donation_qty_to_price(self, order_line, qty): + if order_line.product_uom_qty >= 1 and order_line.product_id.is_donation and order_line.product_id.donation_type == 'Free Amount': + order_line.write({ + 'product_uom_qty': 1, + 'price_unit': qty + }) + + def action_confirm(self): + call_super = super(SaleOrder_Inherit, self).action_confirm() + if call_super == True: + for rec in self: + if rec.order_mobile_number: + sms_template_id = self.env.ref('p_donation_theme.sms_template_data_donation') + rec._message_sms_with_template( + template=sms_template_id, + put_in_queue=False, + sms_numbers=[rec.order_mobile_number] + ) + donar_sms_template_id = self.env.ref('p_donation_theme.sms_template_donors_data_donation') + for donator in rec.donators_ids: + donator._message_sms_with_template( + template=donar_sms_template_id, + put_in_queue=False, + sms_numbers=[donator.donator_mobile_number] + ) + return call_super + + def _prepare_order_line_values( + self, product_id, quantity, linked_line_id=False, + no_variant_attribute_values=None, product_custom_attribute_values=None, + **kwargs + ): + call_super = super(SaleOrder_Inherit, self)._prepare_order_line_values(product_id, quantity, linked_line_id, + no_variant_attribute_values, + product_custom_attribute_values, **kwargs) + + order_id = call_super.get('order_id') + if order_id and 'donators_ids' in kwargs: + extra_donators_ids = [] + for i in json_scriptsafe.loads(kwargs.get('donators_ids')): + extra_donators_ids.append((0, 0, { + 'sale_id': order_id, + 'product_id': int(i.get('product_id')), + 'donated_amount': float(i.get('donated_amount')), + 'donator_name': i.get('donator_name'), + 'donator_mobile_number': i.get('donator_mobile_number') + })) + call_super.update({'extra_donators_ids' : extra_donators_ids}) + return call_super + + def _prepare_order_line_update_values( + self, order_line, quantity, linked_line_id=False, **kwargs + ): + call_super = super(SaleOrder_Inherit, self)._prepare_order_line_update_values(order_line, quantity, linked_line_id, **kwargs) + + if order_line and 'donators_ids' in kwargs: + order_line.extra_donators_ids.sudo().unlink() + extra_donators_ids = [] + for i in json_scriptsafe.loads(kwargs.get('donators_ids')): + extra_donators_ids.append((0, 0, { + 'sale_id': order_line.order_id.id, + 'product_id': int(i.get('product_id')), + 'donated_amount': float(i.get('donated_amount')), + 'donator_name': i.get('donator_name'), + 'donator_mobile_number': i.get('donator_mobile_number') + })) + order_line.extra_donators_ids = extra_donators_ids + return call_super + + +class ExtraDonators(models.Model): + _name = "sale.order.extra_donators" + _inherit = ['mail.thread'] + + product_ids = fields.Many2many('product.template') + donator_name = fields.Char(string="Name") + donated_amount = fields.Float(string="Amount") + donator_mobile_number = fields.Char(string="Mobile") + line_id = fields.Many2one('sale.order.line', ondelete='cascade') + sale_id = fields.Many2one("sale.order", string="Sale Order", ondelete='cascade') + product_id = fields.Many2one('product.product', string="Product", ondelete='cascade') + + + +class SaleOrderLineInherit(models.Model): + _inherit = 'sale.order.line' + + extra_donators_ids = fields.One2many('sale.order.extra_donators', 'line_id') + + @api.depends('product_id', 'product_uom', 'product_uom_qty') + def _compute_price_unit(self): + for line in self: + if line.product_id and line.product_id.is_donation and line.product_id.donation_type == 'Free Amount': + continue + super(SaleOrderLineInherit, line)._compute_price_unit() diff --git a/odex25_donation/p_donation_theme/security/ir.model.access.csv b/odex25_donation/p_donation_theme/security/ir.model.access.csv new file mode 100644 index 000000000..f382e04fe --- /dev/null +++ b/odex25_donation/p_donation_theme/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_sale_order_extra_donators,access.sale.order.extra_donators,model_sale_order_extra_donators,,1,1,1,1 \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/description/1.png b/odex25_donation/p_donation_theme/static/description/1.png new file mode 100644 index 000000000..9effb2387 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/1.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/Varietyit.gif b/odex25_donation/p_donation_theme/static/description/assets/Varietyit.gif new file mode 100644 index 000000000..2d1d0629d Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/Varietyit.gif differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/cogs.png b/odex25_donation/p_donation_theme/static/description/assets/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/cogs.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/consultation.png b/odex25_donation/p_donation_theme/static/description/assets/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/consultation.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/corporate.png b/odex25_donation/p_donation_theme/static/description/assets/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/corporate.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/customer-support.png b/odex25_donation/p_donation_theme/static/description/assets/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/customer-support.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/ecom-black.png b/odex25_donation/p_donation_theme/static/description/assets/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/ecom-black.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/education-black.png b/odex25_donation/p_donation_theme/static/description/assets/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/education-black.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/heading.png b/odex25_donation/p_donation_theme/static/description/assets/heading.png new file mode 100644 index 000000000..347482183 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/heading.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/hotel-black.png b/odex25_donation/p_donation_theme/static/description/assets/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/hotel-black.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/license.png b/odex25_donation/p_donation_theme/static/description/assets/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/license.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/lifebuoy.png b/odex25_donation/p_donation_theme/static/description/assets/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/lifebuoy.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/manufacturing-black.png b/odex25_donation/p_donation_theme/static/description/assets/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/manufacturing-black.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/pos-black.png b/odex25_donation/p_donation_theme/static/description/assets/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/pos-black.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/puzzle.png b/odex25_donation/p_donation_theme/static/description/assets/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/puzzle.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/restaurant-black.png b/odex25_donation/p_donation_theme/static/description/assets/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/restaurant-black.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/service-black.png b/odex25_donation/p_donation_theme/static/description/assets/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/service-black.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/trading-black.png b/odex25_donation/p_donation_theme/static/description/assets/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/trading-black.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/training.png b/odex25_donation/p_donation_theme/static/description/assets/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/training.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/update.png b/odex25_donation/p_donation_theme/static/description/assets/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/update.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/user.png b/odex25_donation/p_donation_theme/static/description/assets/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/user.png differ diff --git a/odex25_donation/p_donation_theme/static/description/assets/wrench.png b/odex25_donation/p_donation_theme/static/description/assets/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/assets/wrench.png differ diff --git a/odex25_donation/p_donation_theme/static/description/banner.png b/odex25_donation/p_donation_theme/static/description/banner.png new file mode 100644 index 000000000..9effb2387 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/banner.png differ diff --git a/odex25_donation/p_donation_theme/static/description/icon.png b/odex25_donation/p_donation_theme/static/description/icon.png new file mode 100644 index 000000000..392838e0c Binary files /dev/null and b/odex25_donation/p_donation_theme/static/description/icon.png differ diff --git a/odex25_donation/p_donation_theme/static/description/index.html b/odex25_donation/p_donation_theme/static/description/index.html new file mode 100644 index 000000000..fe8daffa6 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/description/index.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + +
+
+
+
+
+ logo +
+
+ Community + Enterprise + Odoo.sh +
+
+
+
+
+ +
+
+
+

Ensan.sa new donation platform

+ + heading +

this module changes odoo e-commerce interface to Ensan.sa interface

+
+
+
+
+
+ +
+ + +
+
+
+
+

Ensan.sa new donation platform +

+ +
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+ Odoo + Customization
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Support
+
+ + +
+
+ +
+
+ Hire + Odoo + Developer
+
+ +
+
+ +
+
+ Odoo + Integration
+
+ +
+
+ +
+
+ Odoo + Migration
+
+ + +
+
+ +
+
+ Odoo + Consultancy
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Licensing Consultancy
+
+
+ +
+
+
+
+
+
+
+ +
+ Trading +
+

+ Easily procure + and + sell your products

+
+
+ +
+
+ +
+ POS +
+

+ Easy + configuration + and convivial experience

+
+
+ +
+
+ +
+ Education +
+

+ A platform for + educational management

+
+
+ +
+
+ +
+ Manufacturing +
+

+ Plan, track and + schedule your operations

+
+
+ +
+
+ +
+ E-commerce & Website +
+

+ Mobile + friendly, + awe-inspiring product pages

+
+
+ +
+
+ +
+ Service Management +
+

+ Keep track of + services and invoice

+
+
+ +
+
+ +
+ Restaurant +
+

+ Run your bar or + restaurant methodically

+
+
+ +
+
+ +
+ Hotel Management +
+

+ An + all-inclusive + hotel management application

+
+
+
+
+
+
+
+
+
+ +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+ +
+ + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Bold.ttf b/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Bold.ttf new file mode 100644 index 000000000..a8c10987c Binary files /dev/null and b/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Bold.ttf differ diff --git a/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Light.ttf b/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Light.ttf new file mode 100644 index 000000000..c5505490b Binary files /dev/null and b/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Light.ttf differ diff --git a/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Regular.ttf b/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Regular.ttf new file mode 100644 index 000000000..825a4cf44 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Regular.ttf differ diff --git a/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Semibold.ttf b/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Semibold.ttf new file mode 100644 index 000000000..f8e20ae72 Binary files /dev/null and b/odex25_donation/p_donation_theme/static/src/fonts/Greta-AR-LT-Semibold.ttf differ diff --git a/odex25_donation/p_donation_theme/static/src/fonts/Greta-Arabic-Bold.ttf b/odex25_donation/p_donation_theme/static/src/fonts/Greta-Arabic-Bold.ttf new file mode 100644 index 000000000..1baa0419d Binary files /dev/null and b/odex25_donation/p_donation_theme/static/src/fonts/Greta-Arabic-Bold.ttf differ diff --git a/odex25_donation/p_donation_theme/static/src/img/facebook.svg b/odex25_donation/p_donation_theme/static/src/img/facebook.svg new file mode 100644 index 000000000..cbb13c4b1 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/facebook.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/img/icon-eye.svg b/odex25_donation/p_donation_theme/static/src/img/icon-eye.svg new file mode 100644 index 000000000..e51eaa62c --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/icon-eye.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/p_donation_theme/static/src/img/icon-hand.svg b/odex25_donation/p_donation_theme/static/src/img/icon-hand.svg new file mode 100644 index 000000000..ba448078e --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/icon-hand.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/p_donation_theme/static/src/img/icon-info.svg b/odex25_donation/p_donation_theme/static/src/img/icon-info.svg new file mode 100644 index 000000000..f86f00223 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/icon-info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/img/icon-last-donation.svg b/odex25_donation/p_donation_theme/static/src/img/icon-last-donation.svg new file mode 100644 index 000000000..b920cc1ad --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/icon-last-donation.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/p_donation_theme/static/src/img/icon-users.svg b/odex25_donation/p_donation_theme/static/src/img/icon-users.svg new file mode 100644 index 000000000..c088b89cc --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/icon-users.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/p_donation_theme/static/src/img/icons-gift-green.svg b/odex25_donation/p_donation_theme/static/src/img/icons-gift-green.svg new file mode 100644 index 000000000..b2a079b69 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/icons-gift-green.svg @@ -0,0 +1,3 @@ + + + diff --git a/odex25_donation/p_donation_theme/static/src/img/rounded-applepay.svg b/odex25_donation/p_donation_theme/static/src/img/rounded-applepay.svg new file mode 100644 index 000000000..dd469503e --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/rounded-applepay.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/odex25_donation/p_donation_theme/static/src/img/rounded-mada.svg b/odex25_donation/p_donation_theme/static/src/img/rounded-mada.svg new file mode 100644 index 000000000..6e1b211eb --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/rounded-mada.svg @@ -0,0 +1,20 @@ + + + + + + + diff --git a/odex25_donation/p_donation_theme/static/src/img/rounded-mastercard.svg b/odex25_donation/p_donation_theme/static/src/img/rounded-mastercard.svg new file mode 100644 index 000000000..3ff39ce8c --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/rounded-mastercard.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/p_donation_theme/static/src/img/rounded-visa.svg b/odex25_donation/p_donation_theme/static/src/img/rounded-visa.svg new file mode 100644 index 000000000..17fc4ec46 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/rounded-visa.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/odex25_donation/p_donation_theme/static/src/img/share-img.svg b/odex25_donation/p_donation_theme/static/src/img/share-img.svg new file mode 100644 index 000000000..e3925b96a --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/share-img.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/img/twitter.svg b/odex25_donation/p_donation_theme/static/src/img/twitter.svg new file mode 100644 index 000000000..50f3b0e57 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/twitter.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/img/visa_dimmed.svg b/odex25_donation/p_donation_theme/static/src/img/visa_dimmed.svg new file mode 100644 index 000000000..22e25635d --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/visa_dimmed.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/p_donation_theme/static/src/img/whatsapp.svg b/odex25_donation/p_donation_theme/static/src/img/whatsapp.svg new file mode 100644 index 000000000..f206bbd5e --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/img/whatsapp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/js/checkout.js b/odex25_donation/p_donation_theme/static/src/js/checkout.js new file mode 100644 index 000000000..a3b76c3f3 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/js/checkout.js @@ -0,0 +1,103 @@ +odoo.define('p_donation_theme.payment', require => { + 'use strict'; + + const checkoutForm = require('payment.checkout_form'); + const publicWidget = require('web.public.widget'); + const manageForm = require('payment.manage_form'); + function ArabictoEnglishNumber(strNum) { + var ar = '٠١٢٣٤٥٦٧٨٩'.split(''); + var en = '0123456789'.split(''); + strNum = strNum.replace(/[٠١٢٣٤٥٦٧٨٩]/g, x => en[ar.indexOf(x)]); + strNum = strNum.replace(/[^\d]/g, ''); + return strNum; + } + const websiteSaleextraMixin = { + + init: function() { + this._onCheck_extra_validation = _.debounce(this._onCheck_extra_validation, 100, true); + this._super(...arguments); + }, + + start: function() { + this.$submitButton = this.$('button[name="o_payment_submit_button"]'); + this._adaptConfirmButton(); + return this._super(...arguments); + }, + + _adaptConfirmButton: function() { + if (this.$('#order_mobile_number').length > 0) { + const disabledReasons = this.$submitButton.data('disabled_reasons') || {}; + disabledReasons.omn = !this.$('#order_mobile_number').val(); + this.$submitButton.data('disabled_reasons', disabledReasons); + } + }, + + }; + + checkoutForm.include(Object.assign({}, websiteSaleextraMixin, { + events: Object.assign({}, checkoutForm.prototype.events, { + 'input #order_mobile_number':'_convert_arabic_to_english' + }), + _convert_arabic_to_english(ev) { + ev.currentTarget.value = ArabictoEnglishNumber(ev.currentTarget.value) + this._onCheck_extra_validation(); + }, + _isButtonReady: function() { + const disabledReasonFound = _.contains( + this.$submitButton.data('disabled_reasons'), true + ); + return !disabledReasonFound && this._super(); + }, + _onCheck_extra_validation: function() { + this._adaptConfirmButton(); + + if (!this._enableButton()) { + this._disableButton(false); + } + }, + + })); + + publicWidget.registry.WebsiteSaleExtraField = publicWidget.Widget.extend( + Object.assign({}, websiteSaleextraMixin, { + selector: 'div[name="o_website_sale_free_cart"]', + events: { + 'change #order_mobile_number': '_onCheck_extra_validation', + }, + + start: function() { + this.$submitButton = this.$('button[name="o_payment_submit_button"]'); + this._onCheck_extra_validation(); + return this._super(...arguments); + }, + + _onCheck_extra_validation: function() { + this._adaptConfirmButton(); + + const disabledReasonFound = _.contains( + this.$submitButton.data('disabled_reasons'), true + ); + this.$submitButton.prop('disabled', disabledReasonFound); + }, + }) + ); + + + + const ExtraFieldMixin = { + _prepareTransactionRouteParams: function(code, paymentOptionId, flow) { + const transactionRouteParams = this._super(...arguments); + var extra_name = this.$('#order_name'); + var extra_mobile = this.$('#order_mobile_number'); + return { + ...transactionRouteParams, + 'extra_name': extra_name.length > 0 ? extra_name.val() : null, + 'extra_mobile': extra_mobile.length > 0 ? extra_mobile.val() : null, + }; + }, + + }; + + checkoutForm.include(ExtraFieldMixin); + manageForm.include(ExtraFieldMixin); +}); \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/js/components/theme_config.js b/odex25_donation/p_donation_theme/static/src/js/components/theme_config.js new file mode 100644 index 000000000..59bfef805 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/js/components/theme_config.js @@ -0,0 +1,26 @@ +/** @odoo-module **/ + +import { ThemeConfigDialog } from '@droggol_theme_common/js/components/theme_config'; +import { patch } from "@web/core/utils/patch"; + +patch(ThemeConfigDialog.prototype, 'p_donation_theme/static/src/js/components/theme_config.js', { + get _tabInfo() { + var call_super = this._super(...arguments) + if (call_super.length > 0) { + call_super.forEach(function (state) { + if (state.name == 'shop') { + state.components.forEach(function (comp) { + if (comp.props.key == "json_shop_product_item") { + comp.props.components.forEach(function (shop_item) { + if (shop_item.props.key == "style") { + shop_item.props.selection.push(['3', 'Donation Style']) + } + }) + } + }) + } + }); + } + return call_super + } +}); diff --git a/odex25_donation/p_donation_theme/static/src/js/hyperpay_quick_donation.js b/odex25_donation/p_donation_theme/static/src/js/hyperpay_quick_donation.js new file mode 100644 index 000000000..89ade7a72 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/js/hyperpay_quick_donation.js @@ -0,0 +1,255 @@ +odoo.define('p_donation_theme.quick_donation_hyperpay', function(require) { + "use strict"; + + var core = require('web.core'); + var Dialog = require('web.Dialog'); + var publicWidget = require('web.public.widget'); + var ajax = require('web.ajax'); + const { + assets + } = require('@web/core/assets'); + + var qweb = core.qweb; + var _t = core._t; + + function ArabictoEnglishNumber(strNum) { + var ar = '٠١٢٣٤٥٦٧٨٩'.split(''); + var en = '0123456789'.split(''); + strNum = strNum.replace(/[٠١٢٣٤٥٦٧٨٩]/g, x => en[ar.indexOf(x)]); + strNum = strNum.replace(/[^\d]/g, ''); + return strNum; + } + + // Reference + // https://dev.to/pulljosh/how-to-load-html-css-and-js-code-into-an-iframe-2blc + const getGeneratedPageURL = ({ + html, + css, + js + }) => { + const getBlobURL = (code, type) => { + const blob = new Blob([code], { + type + }) + return URL.createObjectURL(blob) + } + + const source = ` + + + ${css} + ${js} + + + + + ${html || ''} + + + ` + + return getBlobURL(source, 'text/html') + } + + var QuickDonation_HyperpayPaymentForm = publicWidget.Widget.extend({ + init: function() { + this.quick_donation = $('#quick-donation-widget'); + this.tx_id = this.quick_donation.find('#hyperpay_tx').val(); + this._initBlockUI(); + this.start(); + }, + start: function() { + var self = this; + self._createHyperpayCheckoutId(); + }, + _createHyperpayCheckoutId: function() { + var self = this; + ajax.jsonRpc('/payment/hyperpay/checkout/create', 'call', { + 'txId': self.tx_id + }) + .then(function(result) { + if (result) { + self._renderHyperpayModal(result.checkoutId, result.domain, result.base_url, result.data_brands, result.acq); + } else { + console.log('Error Occured'); + } + }); + }, + _renderHyperpayModal: function(checkoutId, domain, base_url, data_brands, acq) { + var self = this; + try { + var $quick_donation_tag = this.quick_donation.find("#quick-donation-3") + var style_css = '' + var script = '' + var js_script = '' + var shopperResultUrlTag = '
' + var theIframe = document.createElement("iframe"); + theIframe.id = "quick_donation_hyperpay_iframe"; + theIframe.style = "display:none"; + var html = script + shopperResultUrlTag; + + const url = getGeneratedPageURL({ + html: html, + css: style_css, + js: js_script + }) + theIframe.src = url; + $quick_donation_tag[0].appendChild(theIframe); + $quick_donation_tag.addClass("show"); + } catch (err) { + console.log('component error:', err); + } + + }, + _initBlockUI: function() { + if (this.quick_donation.length > 0) { + this.quick_donation.find("#qn-spinner").removeClass('o_hidden') + this.quick_donation.find("#qd-options").addClass("blur_disabled"); + } + }, + + }); + + $(document).ready(function() { + $("#quick-donation-widget #quick-donation-button").on("click", function(ev){ + $("#quick-donation-widget").toggleClass("has-focus"); + }); + + $("#quick-donation-widget #qd-options li").on("click", function(ev){ + $("#quick-donation-widget #qd-options li").removeClass('active') + $(this).addClass('active') + }); + + $("#quick-donation-widget .pre-amount").on("click", function(ev){ + $('#quick-donation-widget #qd_amount').val(ev.currentTarget.dataset.amount); + }); + + $("#quick-donation-widget #editAmountBtn").on("click", function(ev){ + $('#quick-donation-widget .payment-info-box .amount-display').toggleClass('toggle-hide') + $('#quick-donation-widget .payment-info-box input').toggleClass('toggle-hide') + }); + + $("#vit-product-grid input.allow-ar-number").on("input", function(ev) { + $(this).val(ArabictoEnglishNumber($(this).val())) + }); + + $("#quick-donation-widget input.allow-ar-number").on("input", function(ev) { + $(this).val(ArabictoEnglishNumber($(this).val())) + }); + + $("#quick-donation-widget .payment-methods img").on("click", function(ev){ + $("#quick-donation-widget .payment-methods img").removeClass('active'); + $(this).addClass('active'); + }); + + $("#quick-donation-widget #qd-checkout-buuton").on("click", function(ev){ + var amount = $('#quick-donation-widget #qd_amount'); + var acquire_id = $("#quick-donation-widget .payment-methods img.active") + var product_id = $("#quick-donation-widget #qd-options li.active") + var mobile = $("#quick-donation-widget #qd_mobile_number") + var is_valid = false; + if (!amount.val() || amount.val() <= 0) { + amount.addClass("is-invalid"); + amount.removeClass("is-valid"); + $('#quick-donation-widget .field-validation-error').text("Invalid Amount!"); + } else if(!mobile.val() || mobile.val() <= 0) { + mobile.addClass("is-invalid"); + mobile.removeClass("is-valid"); + } else if(product_id.length == 0) { + $('#quick-donation-widget #donate_error_msg').removeClass('o_hidden').text("Missing Product.") + } else if(acquire_id.length == 0) { + $('#quick-donation-widget #donate_error_msg').removeClass('o_hidden').text("Click on Payment Icon to Proceed.") + } else { + amount.addClass("is-valid"); + amount.removeClass("is-invalid"); + $('#quick-donation-widget .field-validation-error').text(""); + $('#quick-donation-widget #donate_error_msg').addClass('o_hidden').text("") + is_valid = true; + } + if (is_valid) { + var quick_pay_detail = {}; + quick_pay_detail['amount'] = amount.val() + $('#quick-donation-widget #quick-donation-1').toggleClass('show'); + if (product_id.length > 0) { + product_id = product_id[0].dataset.product_id + } + else { + $('#quick-donation-widget #qn-failure').removeClass('o_hidden'); + } + quick_pay_detail['product_id'] = product_id; + quick_pay_detail['acquire_id'] = acquire_id[0].dataset.acquireId; + quick_pay_detail['mobile'] = mobile.val(); + ajax.jsonRpc('/quickpay/hyperpay/payment/create', 'call', quick_pay_detail) + .then(function (result) { + if (result['success'] && result['redirect_url']) { + + window.location.href = result['redirect_url'] + } + else if (result['success']) { + $('#quick-donation-widget #hyperpay_tx').val(result['tx_id']); + new QuickDonation_HyperpayPaymentForm(); + } + else { + $('#quick-donation-widget #qn-failure').removeClass('o_hidden'); + } + }); + } + }); + + }); + +}); \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/js/product-gift-card.js b/odex25_donation/p_donation_theme/static/src/js/product-gift-card.js new file mode 100644 index 000000000..1c725f6b9 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/js/product-gift-card.js @@ -0,0 +1,234 @@ +odoo.define('p_donation_theme.product-gift-card', function (require) { + "use strict"; + require('web.dom_ready'); + var ajax = require('web.ajax'); + var publicWidget = require('web.public.widget'); + const {qweb, _t} = require('web.core'); + + function ArabictoEnglishNumber(strNum) { + var ar = '٠١٢٣٤٥٦٧٨٩'.split(''); + var en = '0123456789'.split(''); + strNum = strNum.replace(/[٠١٢٣٤٥٦٧٨٩]/g, x => en[ar.indexOf(x)]); + strNum = strNum.replace(/[^\d]/g, ''); + return strNum; + } + + publicWidget.registry.WebsiteSale.include({ + events: _.extend({}, publicWidget.registry.WebsiteSale.prototype.events || {}, { + 'change .update_amount': '_onchange_quantity_price', + 'click .donation-product-detail-layout .temp-donate-now': 'async _temp_donate_now', + 'click .donation-product-detail-layout .temp-add-cart': 'async _temp_add_cart', + 'click .donation-product-detail-layout .gift-input-amount': '_donation_gift_input_amt', + 'click .donation-product-detail-layout .removeGiftee': '_donation_remove_gift_container', + 'click .donation-product-detail-layout #addGiftee': '_donation_add_gift_container', + 'change .donation-product-detail-layout #sendAsGiftCheckbox': '_donation_toggle_gift_container', + 'click .donation-product-detail-layout .single-amount': '_update_default_amt', + 'click .donation_share_btn': '_open_share_popup', + 'input form input[name="add_qty"]': '_convert_arabic_to_english', + 'input .donation-product-detail-layout input.only-number, .donation-product-detail-layout input.input-gifteeNumber, .donation-product-detail-layout input.number-input, .donation-product-detail-layout input.update_amount': '_convert_arabic_to_english' + }), + + _convert_arabic_to_english(ev) { + ev.currentTarget.value = ArabictoEnglishNumber(ev.currentTarget.value) + + }, + + _submitForm() { + const params = this.rootProduct; + const $product = $('#product_detail'); + const product_id = $product.find('input[name=product_id]').val() + const gift_box_list = []; + if ($product.find('#sendAsGiftCheckbox:checked').length > 0) { + $product.find('#gift-details #gifteeContainer .gifteeBoxDetails').each(function(){ + gift_box_list.push({ + product_id: product_id, + donator_name: $(this).find('input.input-gifteeName').val(), + donator_mobile_number: $(this).find('select.country-code').val() + $(this).find('input.input-gifteeNumber').val(), + donated_amount: ArabictoEnglishNumber($(this).find('input.donation-input-amt').val()) + }) + }); + } + this.rootProduct.donators_ids = JSON.stringify(gift_box_list); + return this._super(...arguments); + }, + + _handleAdd: function ($form) { + if ($form.length == 0) { + $form = $("#add_to_cart, .o_we_buy_now, #products_grid .o_wsale_product_btn .a-submit").closest('form') + } + return this._super($form); + }, + + _onchange_quantity_price(ev) { + var price = ev.currentTarget.dataset.price + var qty = ArabictoEnglishNumber(ev.target.value) + $(ev.target).parent().parent().parent().find("input[inputmode=numeric]").val(price*qty) + }, + + _open_share_popup(ev) { + ev.preventDefault() + ev.stopPropagation() + var share_model = document.createElement("div"); + share_model.classList.add("donation-product-detail-layout") + $(qweb.render("product_share_modal",{website_url :ev.currentTarget.dataset.website_url,url: encodeURIComponent(ev.currentTarget.dataset.website_url),msg: encodeURIComponent("Thanks For your Donation")})).appendTo($(share_model)); + $(share_model).appendTo($(ev.currentTarget).parent()); + $('#action_product_share_modal').on('show.bs.modal', function (event) { + var button = $(event.relatedTarget) // Button that triggered the modal + var modal = $(this) + var input_url = modal.find('.share-link input') + modal.find('.share-link #copy_clip').on("click", function(ev){ + ev.preventDefault() + ev.stopPropagation() + input_url.select(); + navigator.clipboard.writeText(input_url.val()); + }); + modal.find('#toggle-share-modal').on("click", function() { + modal.parent().remove(); + }) + }) + $("#action_product_share_modal").modal({backdrop: true}); + $("#action_product_share_modal").modal('show'); + $('#action_product_share_modal').on('hidden.bs.modal', function () { + $('#action_product_share_modal').parent().remove(); + }); + }, + + async _temp_add_cart() { + if (await this._is_all_input_valid()) { + await this._donation_total_amount(); + await $('.donation-product-detail-layout .donate_product_add_cart')[0].click() + } + }, + + async _temp_donate_now() { + if (await this._is_all_input_valid()) { + await this._donation_total_amount(); + await $('.donation-product-detail-layout .o_we_buy_now')[0].click(); + } + }, + + _donation_gift_input_amt(ev) { + $(ev.target).parent().parent().parent().find("input.AnotherAmountAdd").val(ev.target.value) + }, + + _donation_remove_gift_container(ev) { + $(ev.target).closest(".gifteeBoxDetails").remove(); + }, + + _donation_add_gift_container() { + var new_box = $(".donation-product-detail-layout .gifteeBoxDetails:last").clone(true, true) + new_box.find('.removeGiftee').removeClass("o_hidden"); + new_box.find('input').each(function(){ + var temp_id = $(this).prop("id") + var temp_id_list = temp_id.split('-') + if (temp_id_list[0] == "amount") { + $(this).prop('id', temp_id_list[0].concat('-' + (parseInt(temp_id_list[1]) + 3)) ); + $(this).prop('checked', false) + } + else { + $(this).prop('id', temp_id_list[0].concat('-' + (parseInt(temp_id_list[1]) + 1)) ); + $(this).prop('value', ''); + } + var temp_name = $(this).prop("name") + var temp_name_list = temp_name.split('-') + $(this).prop('name', temp_name_list[0].concat('-' + (parseInt(temp_name_list[1]) + 1)) ); + }) + new_box.find('label').each(function(){ + var temp_label = $(this).prop("for") + var temp_label_list = temp_label.split('-') + if (temp_label_list[0] == "amount") { + $(this).prop('for', temp_label_list[0].concat('-' + (parseInt(temp_label_list[1]) + 3)) ); + } + else { + $(this).prop('for', temp_label_list[0].concat('-' + (parseInt(temp_label_list[1]) + 1)) ); + } + }); + var temp_id = new_box.prop("id") + var temp_id_list = temp_id.split('-') + new_box.prop('id', temp_id_list[0].concat('-' + (parseInt(temp_id_list[1]) + 1)) ); + new_box.appendTo(".donation-product-detail-layout #gifteeContainer"); + }, + + _donation_toggle_gift_container(ev) { + if (ev.target.checked) { + $(".donation-product-detail-layout #gift-details" ).show(); + $(".donation-product-detail-layout #remove_gift_card:first" ).addClass("o_hidden"); + $(".donation-product-detail-layout .ProhectDetailsSubBox").addClass("is-disabled"); + $(".donation-product-detail-layout .ProhectDetailsSubBox").find("input[inputmode=numeric]").val('') + } + else { + $(".donation-product-detail-layout #gift-details" ).hide(); + $(".donation-product-detail-layout .ProhectDetailsSubBox").removeClass("is-disabled"); + } + }, + + async _donation_total_amount() { + let total_amt = 0 + var fixed_qty = $(".donation-product-detail-layout input.update_amount") + if (fixed_qty.length > 0) { + fixed_qty.each(function() { + if ($(this).val()) { + total_amt = total_amt + parseFloat(ArabictoEnglishNumber($(this).val())) + } + }); + } else { + $(".donation-product-detail-layout input.donation-input-amt").each(function() { + if ($(this).val()) { + total_amt = total_amt + parseFloat(ArabictoEnglishNumber($(this).val())) + } + }); + } + $(".donation-product-detail-layout form input[name=add_qty]").val(total_amt) + $(".donation-product-detail-layout form input[name=add_qty]").trigger("change") + }, + + _update_default_amt(ev) { + $("input.input-another-amount").val(ev.currentTarget.dataset.amount) + }, + + _is_all_input_valid() { + if($("#sendAsGiftCheckbox:checked").length > 0) { + var is_valid = true; + $("#gift-details input").each(function() { + if(!$(this).val()){ + $(this).addClass("is-invalid"); + $(this).removeClass("is-valid"); + is_valid = false + } else{ + $(this).removeClass("is-invalid"); + $(this).addClass("is-valid"); + } + + }); + if (!is_valid) { + return false + } + } + else { + var is_valid = true; + $(".ProhectDetailsSubBox input").each(function() { + if(!$(this).val() || $(this).val() == 0){ + $(this).addClass("is-invalid"); + $(this).removeClass("is-valid"); + is_valid = false + } else{ + $(this).removeClass("is-invalid"); + $(this).addClass("is-valid"); + } + }); + if (!is_valid) { + return false + } + } + return true + } + }); + +}) + + + + + + + diff --git a/odex25_donation/p_donation_theme/static/src/scss/hyperpay_quick_donation.scss b/odex25_donation/p_donation_theme/static/src/scss/hyperpay_quick_donation.scss new file mode 100644 index 000000000..6d7c0e470 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/scss/hyperpay_quick_donation.scss @@ -0,0 +1,46 @@ +@-moz-document url-prefix() { + .wpwl-container{ + display: block !important; + } +} + +@supports (-moz-appearance:none) { + .wpwl-container{ + display: block !important; + } +} + +@media (min-width: 480px) { + /* this rule applies only to devices with a minimum screen width of 480px */ + .wpwl-button { + width: 50%; + } +} + +.input { + height: 44px; + width: 100%; +} +.wpwl-button { + height: 44px; + width: 100%; +} +.wpwl-form { + background-color:#196956; + margin:0px; +} + +.wpwl-button-pay { + background: #196956; + color: #fff +} + +.wpwl-button-pay:focus,.wpwl-button-pay:hover { + background: #196956!important; + color: #fff!important; + outline: none!important +} + +.wpwl-label { + color:white; +} \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/scss/primary_variables.scss b/odex25_donation/p_donation_theme/static/src/scss/primary_variables.scss new file mode 100644 index 000000000..7220bcfca --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/scss/primary_variables.scss @@ -0,0 +1,17 @@ +$o-theme-font-configs: map-merge($o-theme-font-configs, ( + 'Greta-Arabic-Bold': ( + 'family': ('Greta-Arabic-Bold'), + ), + 'Greta-AR-LT-Bold': ( + 'family': ('Greta-AR-LT-Bold'), + ), + 'Greta-AR-LT-Semibold': ( + 'family': ('Greta-AR-LT-Semibold'), + ), + 'Greta-AR-LT-Regular': ( + 'family': ('Greta-AR-LT-Regular'), + ), + 'Greta-AR-LT-Light': ( + 'family': ('Greta-AR-LT-Light'), + ), +)); \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/scss/theme.scss b/odex25_donation/p_donation_theme/static/src/scss/theme.scss new file mode 100644 index 000000000..ea8a334c7 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/scss/theme.scss @@ -0,0 +1,13392 @@ +.tp-product-item.tp-product-item-grid-3{ + padding:10px; +} +.tp-product-item { + &.tp-product-item-grid-3 { + .tp-rounded-border-radius { + border-radius: 25px !important; + box-shadow: 0 1px 5px 0 #4e4e08; + margin: 10, 10, 10, 10; + } + + .tp-rounded-border-radius:hover { + -webkit-transform: scale(1.1, 1.1); + -moz-transform: scale(1.1, 1.1); + -o-transform: scale(1.1, 1.1); + transform: scale(1.1, 1.1); + -webkit-transition: all .5s ease-in-out; + -moz-transition: all .5s ease-in-out; + -o-transition: all .5s ease-in-out; + transition: all .5s ease-in-out; + box-shadow: 0 2px 15px 0 #000; + } + + .tp-input-amount { + width: 50%; + border-radius: 10px; + } + + .row-cols-lg-3>* { + + padding-bottom: 10px; + } + + + // top title + .tp-product-title a { + font-size: 18px; + font-weight: bold; + font-family: Greta-Arabic-Bold; + } + + i.fa.fa-minus { + color: #fff; + } + + .bg-white { + background-color: #FFF !important; + color: #22B3A0; + } + + div, + a, + p, + h1, + h2, + h3, + h4, + h5, + h6, + .h1, + .h2, + .h3, + .h4, + .h5, + .h6 { + font-family: Greta-Arabic-Bold; + } + + a { + font-weight: bold; + } + + .progress-bar { + font-weight: bold; + font-size: unset; + } + + figcaption { + position: absolute; + right: 137; + bottom: 114px; + background-color: #196956; + color: white; + padding: 2px; + font-size: 15px; + line-height: 18px; + border-radius: 50px; + } + + .text-primary-green { + font-size: 15px; + font-weight: bold; + } + + .btn { + font-family: "Poppins", "Odoo Unicode Support Noto", sans-serif; + font-size: 13px; + font-weight: bold; + } + + // --- + + .tp-product-image { + border-top-left-radius: 15px; + border-top-right-radius: 15px; + border-bottom: 0.1rem solid var(--o-color-1); + } + + .progress-bar { + background-color: var(--o-color-1) !important; + } + + .css_quantity .quantity { + max-width: 150ch; + } + + .rangeslider3 { + position: relative; + user-select: none + } + + .rangeslider3 .rangeslider-fill-lower { + border-radius: 7px; + height: 25px; + transform: translateY(-50%); + width: 100% !important + } + + .rangeslider3 .rangeslider-thumb { + background-color: var(--o-color-1) !important; + border-radius: 7px; + box-sizing: border-box; + color: #fff; + height: 31.5px; + inset-block-start: 50%; + inset-inline-start: 0; + line-height: 20px; + min-width: 35px; + padding: 7px 0 7px 3px; + position: absolute; + text-align: end; + touch-action: pan-x; + transform: translateY(-50%) + } + + .rangeslider3 .range-output .output { + display: block; + font-family: Greta-AR-LT-Semibold; + font-size: 16px + } + + @media(max-width: 767px) { + .rangeslider3 .rangeslider-thumb { + min-width: 35px + } + + .rangeslider3 .range-output .output { + font-size: 14px + } + } + + } +} + + +.donation-product-detail-layout { + .blur_disabled { + pointer-events: none; + filter: blur(1px); + -webkit-filter: blur(1px); + } + + .payment-methods img.active { + border: 2px solid #196956 + } + + @font-face { + font-family: 'Greta-Arabic-Bold'; + src: url('/p_donation_theme/static/src/fonts/Greta-Arabic-Bold.ttf') format('truetype'); + } + + @font-face { + font-family: 'Greta-AR-LT-Bold'; + src: url('/p_donation_theme/static/src/fonts/Greta-AR-LT-Bold.ttf') format('truetype'); + } + + @font-face { + font-family: 'Greta-AR-LT-Semibold'; + src: url('/p_donation_theme/static/src/fonts/Greta-AR-LT-Semibold.ttf') format('truetype'); + } + + @font-face { + font-family: 'Greta-AR-LT-Regular'; + src: url('/p_donation_theme/static/src/fonts/Greta-AR-LT.ttf') format('truetype'); + } + + @font-face { + font-family: 'Greta-AR-LT-Light'; + src: url('/p_donation_theme/static/src/fonts/Greta-AR-LT-Light.ttf') format('truetype'); + } + + .font-head-bold { + font-family: Greta-Arabic-Bold + } + + .font-bold { + font-family: Greta-AR-LT-Bold + } + + .font-semibold { + font-family: Greta-AR-LT-Semibold + } + + .font-regular { + font-family: Greta-AR-LT-Regular + } + + .font-light { + font-family: Greta-AR-LT-Light + } + + + .is-disabled { + pointer-events: none; + opacity: 0.4; + } + + .is-invalid { + border-color: #dc3545 !important; + } + + .css_quantity .quantity { + max-width: 200ch + } + + .gifteeBoxDetails { + border: 2px solid var(--o-color-1); + } + + .bg-grey-1 { + background-color: #eee + } + + .bg-f8f8f8, + .bg-light-grey-2, + .bg-smoke-white-2 { + background-color: #f7f7f7 + } + + .bg-grey-2 { + background-color: #d9d9d9 + } + + .bg-grey-3 { + background-color: #999 + } + + .bg-grey-4 { + background-color: #666 + } + + .bg-grey-5 { + background-color: #333 + } + + .bg-transparent { + background-color: transparent + } + + .bg-dugong { + background-color: #707070 + } + + .bg-dugong[disabled] { + background-color: hsla(0, 0%, 44%, .8) + } + + .hr-darkgrey { + border-block-start-color: #aaa + } + + .bg-grey-5 { + color: #333 !important + } + + .bg-none { + background-image: none !important + } + + .bg-middle-grey { + background-color: #d9d9d9 !important + } + + .bg-blue-vivid-cerulean { + background-color: #00aced !important + } + + .bg-blue-opacity-15 { + background-color: rgba(33, 69, 112, .15) !important + } + + .bg-primary-green { + background-color: #196956 !important + } + + .bg-green-opacity-5 { + background-color: rgba(13, 143, 117, .05) !important + } + + .bg-primary-green-transparent { + background-color: rgba(13, 143, 117, .1) !important + } + + .bg-primary-blue { + background-color: #214570 !important + } + + .bg-primary-lightgreen { + background-color: #01b477 !important + } + + .bg-primary-darkgreen { + background-color: #00726f !important + } + + .bg-lightyellow { + background-color: #fffee7 !important + } + + .bg-light-green { + background-color: #0cf5c9 !important + } + + .bg-light-grey { + background-color: #f2f2f2 !important + } + + .bg-blue-transparent { + background-color: #389296 !important + } + + .bg-smoke-white { + background-color: #f2f2f2 !important + } + + .bg-smoke-white-3 { + background-color: #ededed !important + } + + .bg-transparent-darksky { + background-color: rgba(64, 157, 160, .05) !important + } + + .bg-gradient-green { + background: #196956; + background: linear-gradient(90deg, #196956, #01b477) + } + + .bg-gradient-green span { + opacity: .8 + } + + .bg-primary-gradient { + background: #196956; + background: linear-gradient(270deg, #196956 30%, #214570 110%); + color: #fff + } + + .bg-primary-gradient-2 { + background: #196956; + background: linear-gradient(90deg, #196956 30%, #214570 90%); + color: #fff + } + + .bg-primary-gradient-3 { + background: #196956; + background: linear-gradient(226deg, #214570, #196956); + color: #fff + } + + .bg-blue-gradient { + background: #21446f; + background: linear-gradient(226deg, #204870, #0f6d68); + color: #fff + } + + .bg-green-transparent { + background-color: rgba(1, 180, 119, .58) + } + + .bg-transparency-30 { + background-color: hsla(0, 0%, 100%, .3) + } + + .bg-transparency-50 { + background-color: hsla(0, 0%, 100%, .5) + } + + .bg-transparency-70 { + background-color: hsla(0, 0%, 100%, .7) + } + + .bg-green-light { + background-color: #ecf4f2 !important + } + + .bg-my-sin-approx-17 { + background-color: rgba(254, 179, 40, .17) !important + } + + .bg-primary-darksky { + background: #409da0 + } + + .bg-image-none { + background-image: none !important + } + + .bg_shape-1 { + position: relative + } + + .bg_shape-1:after { + background: url(../images/shape-1.svg) no-repeat 0 100%; + content: ""; + inset: 0; + position: absolute + } + + .bg_shape-color-1, + .current-tag .data { + position: relative + } + + .bg_shape-color-1:after, + .current-tag .data:after { + background: url(../images/shape-color.svg) no-repeat 2% 15%; + background-size: 14%; + content: ""; + inset: 0; + position: absolute + } + + .text-grey-1 { + color: #eee !important + } + + .text-grey-2 { + color: #d9d9d9 !important + } + + .text-grey-3 { + color: #999 !important + } + + .text-grey-4 { + color: #666 !important + } + + .alert { + border: none; + border-radius: 16px + } + + .alert-danger { + background-color: rgba(224, 102, 65, .1); + color: #e04141 + } + + .alert-light { + background-color: #eee; + border-color: transparent !important; + color: #383d41 + } + + .badge-primary-green { + background-color: #0f6d68; + color: #fff + } + + .badge-primary-blue { + background-color: #214570; + color: #fff + } + + .dir-ltr { + direction: ltr; + text-align: start + } + + .rounded-input-group-start { + border-bottom-right-radius: rem(10) !important; + border-top-right-radius: rem(10) !important + } + + .rounded-input-group-end { + border-bottom-left-radius: rem(10) !important; + border-top-left-radius: rem(10) !important + } + + .ul-style-dashed ::marker { + content: " - "; + font-family: Greta-AR-LT-Semibold + } + + .ul-style-dashed li { + padding-inline-start: 10px + } + + .aspect-ratio-1x1 { + aspect-ratio: 1/1 + } + + .Rectangle-277 { + background-image: linear-gradient(90deg, #196956, #3ba9c9); + height: 6px; + width: 410px + } + + .display-5 { + font-size: 2.5rem + } + + .display-5, + .display-6 { + font-weight: 300; + line-height: 1.2 + } + + .display-6 { + font-size: 1.5rem + } + + .text-underline { + text-decoration: underline !important + } + + .text-color-inherit { + color: inherit !important + } + + .text-primary-green { + color: #196956 !important + } + + .text-primary-lightgreen { + color: #01b477 !important + } + + .text-primary-blue { + color: #214570 !important + } + + .text-primary-turquoise { + color: #0cf5c9 !important + } + + .text-primary-sky { + color: #1bbdd4 !important + } + + .text-primary-darksky { + color: #409da0 !important + } + + .text-white-70 { + color: hsla(0, 0%, 100%, .7) !important + } + + .text-warning { + color: #ffab00 !important + } + + .text-pink { + color: #e699bf + } + + .text-blue { + color: #629bd9 + } + + .text-yellow { + color: #ff0 + } + + .text-green { + color: #196956 + } + + .text-light-grey { + color: #aaa + } + + .text-secondary-light { + color: #6c757d + } + + .gradient-borders { + background-image: linear-gradient(90deg, #196956, #3ba9c9); + height: 4px; + width: 100% + } + + .border-grey { + border-color: #bbb !important + } + + .border-width-7 { + border-width: 7px !important + } + + .border-primary-green { + border-color: #196956 !important + } + + .border-primary-blue { + border-color: #214570 !important + } + + .border-rounded-2 { + border-radius: 5px + } + + .border-rounded { + border-radius: 20px + } + + .border-width-2 { + border-width: 2px !important + } + + .rounded-top-right-8 { + border-top-right-radius: 8px !important + } + + .rounded-top-left-8 { + border-top-left-radius: 8px !important + } + + .rounded-bottom-right-8 { + border-bottom-right-radius: 8px !important + } + + .rounded-bottom-left-8 { + border-bottom-left-radius: 8px !important + } + + .rounded-top-right-15 { + border-top-right-radius: 15px !important + } + + .rounded-top-left-15 { + border-top-left-radius: 15px !important + } + + .rounded-bottom-right-15 { + border-bottom-right-radius: 15px !important + } + + .rounded-bottom-left-15 { + border-end-end-radius: 15px !important + } + + .rounded-bottom-20 { + border-end-end-radius: 20px !important; + border-end-start-radius: 20px !important + } + + .rounded-top-35 { + border-start-end-radius: 35px !important; + border-start-start-radius: 35px !important + } + + .rounded-bottom-35 { + border-end-end-radius: 35px !important; + border-end-start-radius: 35px !important + } + + .rounded-bottom-0 { + border-bottom-left-radius: 0 !important; + border-bottom-right-radius: 0 !important + } + + .max-width-350 { + max-width: 350px + } + + .alert-grey { + background-color: #f2f2f2; + color: #949494 + } + + .bg-size-25 { + background-size: 25% + } + + .w-33 { + width: 33.33% !important + } + + .fixed-top { + z-index: 9990 + } + + .fs-10 { + font-size: 10px !important + } + + .rounded-15 { + border-radius: 15px !important + } + + .rounded-20 { + border-radius: 20px !important + } + + .rounded-10 { + border-radius: 10px !important + } + + .opacity-40 { + opacity: .4 !important + } + + .z-index-2 { + z-index: 2 !important + } + + .z-index-99999 { + z-index: 99999 !important + } + + .z-index-9999 { + z-index: 9999 !important + } + + .z-index-1070 { + z-index: 1070 !important + } + + .modal { + z-index: 9999 + } + + .modal-backdrop { + z-index: 9998 + } + + .txt-green { + color: #196956 + } + + .color-dark-green { + color: #214570 + } + + .text-dark-danger { + color: #460808 + } + + ::-webkit-scrollbar { + height: 8px; + width: 8px + } + + ::-webkit-scrollbar-track { + background: #f2f2f2 + } + + ::-webkit-scrollbar-thumb { + background: #196956; + border-radius: 5px + } + + ::-webkit-scrollbar-thumb:hover { + background: #12a875 + } + + .custom_question_icon { + color: #b6b6b6; + font-size: 22px !important; + inset-inline-end: 0; + transform: rotate(0) + } + + .text-black-555 { + color: #333 + } + + .text-color-dugong { + color: #707070 !important + } + + .column-1 { + flex: 82% + } + + .column-2 { + flex: 10%; + margin-inline-start: 13px + } + + .border-right-rounded-15 { + border-radius: 0 15px 15px 0 + } + + .border-left-rounded-15 { + border-radius: 15px 0 0 15px + } + + .border-rounded-8 { + border-radius: 8px !important + } + + .border-rounded-10 { + border-radius: 10px !important + } + + .border-rounded-15 { + border-radius: 15px !important + } + + .border-top-rounded-10 { + border-radius: 10px 10px 0 0 !important + } + + .border-right-rounded-10 { + border-radius: 0 10px 10px 0 + } + + .border-inline-end-rounded-15 { + border-radius: 15px 0 0 15px + } + + .line-height-0 { + line-height: 0 !important + } + + .shadow-md { + box-shadow: 0 .25rem .95rem rgba(1, 1, 1, .15) !important + } + + .copy--wrapper { + background: #ededed + } + + .copy--wrapper button { + inset-block-end: 0; + inset-block-start: 0 + } + + .copy--wrapper input { + border: 1px solid #f7f7f7; + padding-inline-end: .75rem; + padding-inline-start: .75rem + } + + .shared-links .img-shadow { + box-shadow: -5px 10px 20px 0 rgba(0, 106, 70, .15) + } + + .border-rounded-top-13 { + border-top-left-radius: 13px !important; + border-top-right-radius: 13px !important + } + + .img-holder { + margin-block-end: 26px + } + + .cart-placeholder-image { + margin-inline-end: auto; + margin-inline-start: 21px + } + + .verification-inputs input { + margin-inline-end: 5px + } + + .verification-inputs input.valid { + border: 2px solid #196956 !important; + color: #196956; + font-size: 18px; + font-weight: 700 + } + + .already-donate .removeFromCart, + .already-donate-subsidy .removeFromCart { + font-family: Greta-AR-LT-Semibold + } + + .img-to-white { + filter: brightness(0) invert(1) + } + + .custom-alert_warning { + background-color: #d6d6d621; + color: #feb328 + } + + #amountRadioBtns .btn { + border: 1px solid #dee2e6; + box-shadow: none !important + } + + #amountRadioBtns .btn.active { + border: 2px solid #196956 + } + + .filters .btn-primary-green { + padding: 8px 30px + } + + .sponsers-items img { + width: 145px + } + + label.error { + color: #dc3545 !important + } + + .text-truncate-60 { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 60% + } + + .border-top-primary-2px { + border-block-start: 2px solid #0f6d68 + } + + .cursor-pointer { + cursor: pointer + } + + .border-style-dashed { + border-style: dashed !important + } + + .filter-gray { + filter: grayscale(1) + } + + .hover-primary:hover { + background-color: #196956 !important; + color: #fff !important + } + + .hover-primary:hover img { + filter: brightness(0) invert(1) + } + + .hover-primary:hover i { + color: #fff !important + } + + .border-semi-light { + border-color: #d9d9d9 !important + } + + .btn-gray-3 { + background-color: #999 !important; + color: #fff !important + } + + .btn-gray-3:hover { + background-color: #666 !important; + color: #fff !important; + transition: all .5s + } + + .border-right-green-4 { + border-inline-start: 4px solid #196956 + } + + .border-right-green-7 { + border-inline-start: 7px solid #196956 + } + + .w-70 { + width: 70% !important + } + + .w-65 { + width: 65% !important + } + + .text-primary-color-lighter { + color: #10a789 !important + } + + .border-light-danger { + border-color: rgba(195, 67, 56, .18) !important + } + + .bject-fit_contain { + object-fit: contain + } + + .bject-fit_cover { + object-fit: cover + } + + .no-wrap { + white-space: nowrap + } + + .translate-x-100 { + transform: translateX(100%) + } + + .divid-children-end>:not(:last-child) { + position: relative + } + + .divid-children-end>:not(:last-child):after { + background-color: hsla(0, 0%, 44%, .1); + content: ""; + position: absolute + } + + @media(min-width: 768px) { + .divid-children-end>:not(:last-child):after { + inset-block: 20%; + inset-inline-end: -31%; + width: 1px + } + } + + .w-7px { + width: 7px !important + } + + .h-7px { + height: 7px !important + } + + .lh-7px { + line-height: 7px + } + + .min-h-7px { + min-height: 7px !important + } + + .min-w-7px { + min-width: 7px !important + } + + .px-7px { + padding-inline: 7px !important + } + + .mt-7px { + margin-block-start: 7px + } + + .mb-7px { + margin-block-end: 7px + } + + .ms-7px { + margin-inline-start: 7px + } + + .me-7px { + margin-inline-end: 7px + } + + .pt-7px { + padding-block-start: 7px + } + + .pb-7px { + padding-block-end: 7px + } + + .ps-7px { + padding-inline-start: 7px + } + + .pe-7px { + padding-inline-end: 7px + } + + .w-10px { + width: 10px !important + } + + .h-10px { + height: 10px !important + } + + .lh-10px { + line-height: 10px + } + + .min-h-10px { + min-height: 10px !important + } + + .min-w-10px { + min-width: 10px !important + } + + .px-10px { + padding-inline: 10px !important + } + + .mt-10px { + margin-block-start: 10px + } + + .mb-10px { + margin-block-end: 10px + } + + .ms-10px { + margin-inline-start: 10px + } + + .me-10px { + margin-inline-end: 10px + } + + .pt-10px { + padding-block-start: 10px + } + + .pb-10px { + padding-block-end: 10px + } + + .ps-10px { + padding-inline-start: 10px + } + + .pe-10px { + padding-inline-end: 10px + } + + .w-12px { + width: 12px !important + } + + .h-12px { + height: 12px !important + } + + .lh-12px { + line-height: 12px + } + + .min-h-12px { + min-height: 12px !important + } + + .min-w-12px { + min-width: 12px !important + } + + .px-12px { + padding-inline: 12px !important + } + + .mt-12px { + margin-block-start: 12px + } + + .mb-12px { + margin-block-end: 12px + } + + .ms-12px { + margin-inline-start: 12px + } + + .me-12px { + margin-inline-end: 12px + } + + .pt-12px { + padding-block-start: 12px + } + + .pb-12px { + padding-block-end: 12px + } + + .ps-12px { + padding-inline-start: 12px + } + + .pe-12px { + padding-inline-end: 12px + } + + .w-14px { + width: 14px !important + } + + .h-14px { + height: 14px !important + } + + .lh-14px { + line-height: 14px + } + + .min-h-14px { + min-height: 14px !important + } + + .min-w-14px { + min-width: 14px !important + } + + .px-14px { + padding-inline: 14px !important + } + + .mt-14px { + margin-block-start: 14px + } + + .mb-14px { + margin-block-end: 14px + } + + .ms-14px { + margin-inline-start: 14px + } + + .me-14px { + margin-inline-end: 14px + } + + .pt-14px { + padding-block-start: 14px + } + + .pb-14px { + padding-block-end: 14px + } + + .ps-14px { + padding-inline-start: 14px + } + + .pe-14px { + padding-inline-end: 14px + } + + .w-16px { + width: 16px !important + } + + .h-16px { + height: 16px !important + } + + .lh-16px { + line-height: 16px + } + + .min-h-16px { + min-height: 16px !important + } + + .min-w-16px { + min-width: 16px !important + } + + .px-16px { + padding-inline: 16px !important + } + + .mt-16px { + margin-block-start: 16px + } + + .mb-16px { + margin-block-end: 16px + } + + .ms-16px { + margin-inline-start: 16px + } + + .me-16px { + margin-inline-end: 16px + } + + .pt-16px { + padding-block-start: 16px + } + + .pb-16px { + padding-block-end: 16px + } + + .ps-16px { + padding-inline-start: 16px + } + + .pe-16px { + padding-inline-end: 16px + } + + .w-18px { + width: 18px !important + } + + .h-18px { + height: 18px !important + } + + .lh-18px { + line-height: 18px + } + + .min-h-18px { + min-height: 18px !important + } + + .min-w-18px { + min-width: 18px !important + } + + .px-18px { + padding-inline: 18px !important + } + + .mt-18px { + margin-block-start: 18px + } + + .mb-18px { + margin-block-end: 18px + } + + .ms-18px { + margin-inline-start: 18px + } + + .me-18px { + margin-inline-end: 18px + } + + .pt-18px { + padding-block-start: 18px + } + + .pb-18px { + padding-block-end: 18px + } + + .ps-18px { + padding-inline-start: 18px + } + + .pe-18px { + padding-inline-end: 18px + } + + .w-20px { + width: 20px !important + } + + .h-20px { + height: 20px !important + } + + .lh-20px { + line-height: 20px + } + + .min-h-20px { + min-height: 20px !important + } + + .min-w-20px { + min-width: 20px !important + } + + .px-20px { + padding-inline: 20px !important + } + + .mt-20px { + margin-block-start: 20px + } + + .mb-20px { + margin-block-end: 20px + } + + .ms-20px { + margin-inline-start: 20px + } + + .me-20px { + margin-inline-end: 20px + } + + .pt-20px { + padding-block-start: 20px + } + + .pb-20px { + padding-block-end: 20px + } + + .ps-20px { + padding-inline-start: 20px + } + + .pe-20px { + padding-inline-end: 20px + } + + .w-22px { + width: 22px !important + } + + .h-22px { + height: 22px !important + } + + .lh-22px { + line-height: 22px + } + + .min-h-22px { + min-height: 22px !important + } + + .min-w-22px { + min-width: 22px !important + } + + .px-22px { + padding-inline: 22px !important + } + + .mt-22px { + margin-block-start: 22px + } + + .mb-22px { + margin-block-end: 22px + } + + .ms-22px { + margin-inline-start: 22px + } + + .me-22px { + margin-inline-end: 22px + } + + .pt-22px { + padding-block-start: 22px + } + + .pb-22px { + padding-block-end: 22px + } + + .ps-22px { + padding-inline-start: 22px + } + + .pe-22px { + padding-inline-end: 22px + } + + .w-24px { + width: 24px !important + } + + .h-24px { + height: 24px !important + } + + .lh-24px { + line-height: 24px + } + + .min-h-24px { + min-height: 24px !important + } + + .min-w-24px { + min-width: 24px !important + } + + .px-24px { + padding-inline: 24px !important + } + + .mt-24px { + margin-block-start: 24px + } + + .mb-24px { + margin-block-end: 24px + } + + .ms-24px { + margin-inline-start: 24px + } + + .me-24px { + margin-inline-end: 24px + } + + .pt-24px { + padding-block-start: 24px + } + + .pb-24px { + padding-block-end: 24px + } + + .ps-24px { + padding-inline-start: 24px + } + + .pe-24px { + padding-inline-end: 24px + } + + .w-26px { + width: 26px !important + } + + .h-26px { + height: 26px !important + } + + .lh-26px { + line-height: 26px + } + + .min-h-26px { + min-height: 26px !important + } + + .min-w-26px { + min-width: 26px !important + } + + .px-26px { + padding-inline: 26px !important + } + + .mt-26px { + margin-block-start: 26px + } + + .mb-26px { + margin-block-end: 26px + } + + .ms-26px { + margin-inline-start: 26px + } + + .me-26px { + margin-inline-end: 26px + } + + .pt-26px { + padding-block-start: 26px + } + + .pb-26px { + padding-block-end: 26px + } + + .ps-26px { + padding-inline-start: 26px + } + + .pe-26px { + padding-inline-end: 26px + } + + .w-28px { + width: 28px !important + } + + .h-28px { + height: 28px !important + } + + .lh-28px { + line-height: 28px + } + + .min-h-28px { + min-height: 28px !important + } + + .min-w-28px { + min-width: 28px !important + } + + .px-28px { + padding-inline: 28px !important + } + + .mt-28px { + margin-block-start: 28px + } + + .mb-28px { + margin-block-end: 28px + } + + .ms-28px { + margin-inline-start: 28px + } + + .me-28px { + margin-inline-end: 28px + } + + .pt-28px { + padding-block-start: 28px + } + + .pb-28px { + padding-block-end: 28px + } + + .ps-28px { + padding-inline-start: 28px + } + + .pe-28px { + padding-inline-end: 28px + } + + .w-30px { + width: 30px !important + } + + .h-30px { + height: 30px !important + } + + .lh-30px { + line-height: 30px + } + + .min-h-30px { + min-height: 30px !important + } + + .min-w-30px { + min-width: 30px !important + } + + .px-30px { + padding-inline: 30px !important + } + + .mt-30px { + margin-block-start: 30px + } + + .mb-30px { + margin-block-end: 30px + } + + .ms-30px { + margin-inline-start: 30px + } + + .me-30px { + margin-inline-end: 30px + } + + .pt-30px { + padding-block-start: 30px + } + + .pb-30px { + padding-block-end: 30px + } + + .ps-30px { + padding-inline-start: 30px + } + + .pe-30px { + padding-inline-end: 30px + } + + .w-32px { + width: 32px !important + } + + .h-32px { + height: 32px !important + } + + .lh-32px { + line-height: 32px + } + + .min-h-32px { + min-height: 32px !important + } + + .min-w-32px { + min-width: 32px !important + } + + .px-32px { + padding-inline: 32px !important + } + + .mt-32px { + margin-block-start: 32px + } + + .mb-32px { + margin-block-end: 32px + } + + .ms-32px { + margin-inline-start: 32px + } + + .me-32px { + margin-inline-end: 32px + } + + .pt-32px { + padding-block-start: 32px + } + + .pb-32px { + padding-block-end: 32px + } + + .ps-32px { + padding-inline-start: 32px + } + + .pe-32px { + padding-inline-end: 32px + } + + .w-34px { + width: 34px !important + } + + .h-34px { + height: 34px !important + } + + .lh-34px { + line-height: 34px + } + + .min-h-34px { + min-height: 34px !important + } + + .min-w-34px { + min-width: 34px !important + } + + .px-34px { + padding-inline: 34px !important + } + + .mt-34px { + margin-block-start: 34px + } + + .mb-34px { + margin-block-end: 34px + } + + .ms-34px { + margin-inline-start: 34px + } + + .me-34px { + margin-inline-end: 34px + } + + .pt-34px { + padding-block-start: 34px + } + + .pb-34px { + padding-block-end: 34px + } + + .ps-34px { + padding-inline-start: 34px + } + + .pe-34px { + padding-inline-end: 34px + } + + .w-36px { + width: 36px !important + } + + .h-36px { + height: 36px !important + } + + .lh-36px { + line-height: 36px + } + + .min-h-36px { + min-height: 36px !important + } + + .min-w-36px { + min-width: 36px !important + } + + .px-36px { + padding-inline: 36px !important + } + + .mt-36px { + margin-block-start: 36px + } + + .mb-36px { + margin-block-end: 36px + } + + .ms-36px { + margin-inline-start: 36px + } + + .me-36px { + margin-inline-end: 36px + } + + .pt-36px { + padding-block-start: 36px + } + + .pb-36px { + padding-block-end: 36px + } + + .ps-36px { + padding-inline-start: 36px + } + + .pe-36px { + padding-inline-end: 36px + } + + .w-40px { + width: 40px !important + } + + .h-40px { + height: 40px !important + } + + .lh-40px { + line-height: 40px + } + + .min-h-40px { + min-height: 40px !important + } + + .min-w-40px { + min-width: 40px !important + } + + .px-40px { + padding-inline: 40px !important + } + + .mt-40px { + margin-block-start: 40px + } + + .mb-40px { + margin-block-end: 40px + } + + .ms-40px { + margin-inline-start: 40px + } + + .me-40px { + margin-inline-end: 40px + } + + .pt-40px { + padding-block-start: 40px + } + + .pb-40px { + padding-block-end: 40px + } + + .ps-40px { + padding-inline-start: 40px + } + + .pe-40px { + padding-inline-end: 40px + } + + .w-42px { + width: 42px !important + } + + .h-42px { + height: 42px !important + } + + .lh-42px { + line-height: 42px + } + + .min-h-42px { + min-height: 42px !important + } + + .min-w-42px { + min-width: 42px !important + } + + .px-42px { + padding-inline: 42px !important + } + + .mt-42px { + margin-block-start: 42px + } + + .mb-42px { + margin-block-end: 42px + } + + .ms-42px { + margin-inline-start: 42px + } + + .me-42px { + margin-inline-end: 42px + } + + .pt-42px { + padding-block-start: 42px + } + + .pb-42px { + padding-block-end: 42px + } + + .ps-42px { + padding-inline-start: 42px + } + + .pe-42px { + padding-inline-end: 42px + } + + .w-45px { + width: 45px !important + } + + .h-45px { + height: 45px !important + } + + .lh-45px { + line-height: 45px + } + + .min-h-45px { + min-height: 45px !important + } + + .min-w-45px { + min-width: 45px !important + } + + .px-45px { + padding-inline: 45px !important + } + + .mt-45px { + margin-block-start: 45px + } + + .mb-45px { + margin-block-end: 45px + } + + .ms-45px { + margin-inline-start: 45px + } + + .me-45px { + margin-inline-end: 45px + } + + .pt-45px { + padding-block-start: 45px + } + + .pb-45px { + padding-block-end: 45px + } + + .ps-45px { + padding-inline-start: 45px + } + + .pe-45px { + padding-inline-end: 45px + } + + .w-50px { + width: 50px !important + } + + .h-50px { + height: 50px !important + } + + .lh-50px { + line-height: 50px + } + + .min-h-50px { + min-height: 50px !important + } + + .min-w-50px { + min-width: 50px !important + } + + .px-50px { + padding-inline: 50px !important + } + + .mt-50px { + margin-block-start: 50px + } + + .mb-50px { + margin-block-end: 50px + } + + .ms-50px { + margin-inline-start: 50px + } + + .me-50px { + margin-inline-end: 50px + } + + .pt-50px { + padding-block-start: 50px + } + + .pb-50px { + padding-block-end: 50px + } + + .ps-50px { + padding-inline-start: 50px + } + + .pe-50px { + padding-inline-end: 50px + } + + .w-52px { + width: 52px !important + } + + .h-52px { + height: 52px !important + } + + .lh-52px { + line-height: 52px + } + + .min-h-52px { + min-height: 52px !important + } + + .min-w-52px { + min-width: 52px !important + } + + .px-52px { + padding-inline: 52px !important + } + + .mt-52px { + margin-block-start: 52px + } + + .mb-52px { + margin-block-end: 52px + } + + .ms-52px { + margin-inline-start: 52px + } + + .me-52px { + margin-inline-end: 52px + } + + .pt-52px { + padding-block-start: 52px + } + + .pb-52px { + padding-block-end: 52px + } + + .ps-52px { + padding-inline-start: 52px + } + + .pe-52px { + padding-inline-end: 52px + } + + .w-54px { + width: 54px !important + } + + .h-54px { + height: 54px !important + } + + .lh-54px { + line-height: 54px + } + + .min-h-54px { + min-height: 54px !important + } + + .min-w-54px { + min-width: 54px !important + } + + .px-54px { + padding-inline: 54px !important + } + + .mt-54px { + margin-block-start: 54px + } + + .mb-54px { + margin-block-end: 54px + } + + .ms-54px { + margin-inline-start: 54px + } + + .me-54px { + margin-inline-end: 54px + } + + .pt-54px { + padding-block-start: 54px + } + + .pb-54px { + padding-block-end: 54px + } + + .ps-54px { + padding-inline-start: 54px + } + + .pe-54px { + padding-inline-end: 54px + } + + .w-56px { + width: 56px !important + } + + .h-56px { + height: 56px !important + } + + .lh-56px { + line-height: 56px + } + + .min-h-56px { + min-height: 56px !important + } + + .min-w-56px { + min-width: 56px !important + } + + .px-56px { + padding-inline: 56px !important + } + + .mt-56px { + margin-block-start: 56px + } + + .mb-56px { + margin-block-end: 56px + } + + .ms-56px { + margin-inline-start: 56px + } + + .me-56px { + margin-inline-end: 56px + } + + .pt-56px { + padding-block-start: 56px + } + + .pb-56px { + padding-block-end: 56px + } + + .ps-56px { + padding-inline-start: 56px + } + + .pe-56px { + padding-inline-end: 56px + } + + .w-58px { + width: 58px !important + } + + .h-58px { + height: 58px !important + } + + .lh-58px { + line-height: 58px + } + + .min-h-58px { + min-height: 58px !important + } + + .min-w-58px { + min-width: 58px !important + } + + .px-58px { + padding-inline: 58px !important + } + + .mt-58px { + margin-block-start: 58px + } + + .mb-58px { + margin-block-end: 58px + } + + .ms-58px { + margin-inline-start: 58px + } + + .me-58px { + margin-inline-end: 58px + } + + .pt-58px { + padding-block-start: 58px + } + + .pb-58px { + padding-block-end: 58px + } + + .ps-58px { + padding-inline-start: 58px + } + + .pe-58px { + padding-inline-end: 58px + } + + .w-60px { + width: 60px !important + } + + .h-60px { + height: 60px !important + } + + .lh-60px { + line-height: 60px + } + + .min-h-60px { + min-height: 60px !important + } + + .min-w-60px { + min-width: 60px !important + } + + .px-60px { + padding-inline: 60px !important + } + + .mt-60px { + margin-block-start: 60px + } + + .mb-60px { + margin-block-end: 60px + } + + .ms-60px { + margin-inline-start: 60px + } + + .me-60px { + margin-inline-end: 60px + } + + .pt-60px { + padding-block-start: 60px + } + + .pb-60px { + padding-block-end: 60px + } + + .ps-60px { + padding-inline-start: 60px + } + + .pe-60px { + padding-inline-end: 60px + } + + .w-65px { + width: 65px !important + } + + .h-65px { + height: 65px !important + } + + .lh-65px { + line-height: 65px + } + + .min-h-65px { + min-height: 65px !important + } + + .min-w-65px { + min-width: 65px !important + } + + .px-65px { + padding-inline: 65px !important + } + + .mt-65px { + margin-block-start: 65px + } + + .mb-65px { + margin-block-end: 65px + } + + .ms-65px { + margin-inline-start: 65px + } + + .me-65px { + margin-inline-end: 65px + } + + .pt-65px { + padding-block-start: 65px + } + + .pb-65px { + padding-block-end: 65px + } + + .ps-65px { + padding-inline-start: 65px + } + + .pe-65px { + padding-inline-end: 65px + } + + .w-70px { + width: 70px !important + } + + .h-70px { + height: 70px !important + } + + .lh-70px { + line-height: 70px + } + + .min-h-70px { + min-height: 70px !important + } + + .min-w-70px { + min-width: 70px !important + } + + .px-70px { + padding-inline: 70px !important + } + + .mt-70px { + margin-block-start: 70px + } + + .mb-70px { + margin-block-end: 70px + } + + .ms-70px { + margin-inline-start: 70px + } + + .me-70px { + margin-inline-end: 70px + } + + .pt-70px { + padding-block-start: 70px + } + + .pb-70px { + padding-block-end: 70px + } + + .ps-70px { + padding-inline-start: 70px + } + + .pe-70px { + padding-inline-end: 70px + } + + .w-80px { + width: 80px !important + } + + .h-80px { + height: 80px !important + } + + .lh-80px { + line-height: 80px + } + + .min-h-80px { + min-height: 80px !important + } + + .min-w-80px { + min-width: 80px !important + } + + .px-80px { + padding-inline: 80px !important + } + + .mt-80px { + margin-block-start: 80px + } + + .mb-80px { + margin-block-end: 80px + } + + .ms-80px { + margin-inline-start: 80px + } + + .me-80px { + margin-inline-end: 80px + } + + .pt-80px { + padding-block-start: 80px + } + + .pb-80px { + padding-block-end: 80px + } + + .ps-80px { + padding-inline-start: 80px + } + + .pe-80px { + padding-inline-end: 80px + } + + .w-90px { + width: 90px !important + } + + .h-90px { + height: 90px !important + } + + .lh-90px { + line-height: 90px + } + + .min-h-90px { + min-height: 90px !important + } + + .min-w-90px { + min-width: 90px !important + } + + .px-90px { + padding-inline: 90px !important + } + + .mt-90px { + margin-block-start: 90px + } + + .mb-90px { + margin-block-end: 90px + } + + .ms-90px { + margin-inline-start: 90px + } + + .me-90px { + margin-inline-end: 90px + } + + .pt-90px { + padding-block-start: 90px + } + + .pb-90px { + padding-block-end: 90px + } + + .ps-90px { + padding-inline-start: 90px + } + + .pe-90px { + padding-inline-end: 90px + } + + .w-100px { + width: 100px !important + } + + .h-100px { + height: 100px !important + } + + .lh-100px { + line-height: 100px + } + + .min-h-100px { + min-height: 100px !important + } + + .min-w-100px { + min-width: 100px !important + } + + .px-100px { + padding-inline: 100px !important + } + + .mb-100px { + margin-block-end: 100px + } + + .ms-100px { + margin-inline-start: 100px + } + + .me-100px { + margin-inline-end: 100px + } + + .pt-100px { + padding-block-start: 100px + } + + .pb-100px { + padding-block-end: 100px + } + + .ps-100px { + padding-inline-start: 100px + } + + .pe-100px { + padding-inline-end: 100px + } + + .w-110px { + width: 110px !important + } + + .h-110px { + height: 110px !important + } + + .lh-110px { + line-height: 110px + } + + .min-h-110px { + min-height: 110px !important + } + + .min-w-110px { + min-width: 110px !important + } + + .px-110px { + padding-inline: 110px !important + } + + .mt-110px { + margin-block-start: 110px + } + + .mb-110px { + margin-block-end: 110px + } + + .ms-110px { + margin-inline-start: 110px + } + + .me-110px { + margin-inline-end: 110px + } + + .pt-110px { + padding-block-start: 110px + } + + .pb-110px { + padding-block-end: 110px + } + + .ps-110px { + padding-inline-start: 110px + } + + .pe-110px { + padding-inline-end: 110px + } + + .w-115px { + width: 115px !important + } + + .h-115px { + height: 115px !important + } + + .lh-115px { + line-height: 115px + } + + .min-h-115px { + min-height: 115px !important + } + + .min-w-115px { + min-width: 115px !important + } + + .px-115px { + padding-inline: 115px !important + } + + .mt-115px { + margin-block-start: 115px + } + + .mb-115px { + margin-block-end: 115px + } + + .ms-115px { + margin-inline-start: 115px + } + + .me-115px { + margin-inline-end: 115px + } + + .pt-115px { + padding-block-start: 115px + } + + .pb-115px { + padding-block-end: 115px + } + + .ps-115px { + padding-inline-start: 115px + } + + .pe-115px { + padding-inline-end: 115px + } + + .w-130px { + width: 130px !important + } + + .h-130px { + height: 130px !important + } + + .lh-130px { + line-height: 130px + } + + .min-h-130px { + min-height: 130px !important + } + + .min-w-130px { + min-width: 130px !important + } + + .px-130px { + padding-inline: 130px !important + } + + .mt-130px { + margin-block-start: 130px + } + + .mb-130px { + margin-block-end: 130px + } + + .ms-130px { + margin-inline-start: 130px + } + + .me-130px { + margin-inline-end: 130px + } + + .pt-130px { + padding-block-start: 130px + } + + .pb-130px { + padding-block-end: 130px + } + + .ps-130px { + padding-inline-start: 130px + } + + .pe-130px { + padding-inline-end: 130px + } + + .w-140px { + width: 140px !important + } + + .h-140px { + height: 140px !important + } + + .lh-140px { + line-height: 140px + } + + .min-h-140px { + min-height: 140px !important + } + + .min-w-140px { + min-width: 140px !important + } + + .px-140px { + padding-inline: 140px !important + } + + .mt-140px { + margin-block-start: 140px + } + + .mb-140px { + margin-block-end: 140px + } + + .ms-140px { + margin-inline-start: 140px + } + + .me-140px { + margin-inline-end: 140px + } + + .pt-140px { + padding-block-start: 140px + } + + .pb-140px { + padding-block-end: 140px + } + + .ps-140px { + padding-inline-start: 140px + } + + .pe-140px { + padding-inline-end: 140px + } + + .w-150px { + width: 150px !important + } + + .h-150px { + height: 150px !important + } + + .lh-150px { + line-height: 150px + } + + .min-h-150px { + min-height: 150px !important + } + + .min-w-150px { + min-width: 150px !important + } + + .px-150px { + padding-inline: 150px !important + } + + .mt-150px { + margin-block-start: 150px + } + + .mb-150px { + margin-block-end: 150px + } + + .ms-150px { + margin-inline-start: 150px + } + + .me-150px { + margin-inline-end: 150px + } + + .pt-150px { + padding-block-start: 150px + } + + .pb-150px { + padding-block-end: 150px + } + + .ps-150px { + padding-inline-start: 150px + } + + .pe-150px { + padding-inline-end: 150px + } + + .w-200px { + width: 200px !important + } + + .h-200px { + height: 200px !important + } + + .lh-200px { + line-height: 200px + } + + .min-h-200px { + min-height: 200px !important + } + + .min-w-200px { + min-width: 200px !important + } + + .px-200px { + padding-inline: 200px !important + } + + .mt-200px { + margin-block-start: 200px + } + + .mb-200px { + margin-block-end: 200px + } + + .ms-200px { + margin-inline-start: 200px + } + + .me-200px { + margin-inline-end: 200px + } + + .pt-200px { + padding-block-start: 200px + } + + .pb-200px { + padding-block-end: 200px + } + + .ps-200px { + padding-inline-start: 200px + } + + .pe-200px { + padding-inline-end: 200px + } + + .w-300px { + width: 300px !important + } + + .h-300px { + height: 300px !important + } + + .lh-300px { + line-height: 300px + } + + .min-h-300px { + min-height: 300px !important + } + + .min-w-300px { + min-width: 300px !important + } + + .px-300px { + padding-inline: 300px !important + } + + .mt-300px { + margin-block-start: 300px + } + + .mb-300px { + margin-block-end: 300px + } + + .ms-300px { + margin-inline-start: 300px + } + + .me-300px { + margin-inline-end: 300px + } + + .pt-300px { + padding-block-start: 300px + } + + .pb-300px { + padding-block-end: 300px + } + + .ps-300px { + padding-inline-start: 300px + } + + .pe-300px { + padding-inline-end: 300px + } + + .w--10px { + width: -10px !important + } + + .h--10px { + height: -10px !important + } + + .lh--10px { + line-height: -10px + } + + .min-h--10px { + min-height: -10px !important + } + + .min-w--10px { + min-width: -10px !important + } + + .px--10px { + padding-inline: -10px !important + } + + .mt--10px { + margin-block-start: -10px + } + + .mb--10px { + margin-block-end: -10px + } + + .ms--10px { + margin-inline-start: -10px + } + + .me--10px { + margin-inline-end: -10px + } + + .pt--10px { + padding-block-start: -10px + } + + .pb--10px { + padding-block-end: -10px + } + + .ps--10px { + padding-inline-start: -10px + } + + .pe--10px { + padding-inline-end: -10px + } + + .w--5px { + width: -5px !important + } + + .h--5px { + height: -5px !important + } + + .lh--5px { + line-height: -5px + } + + .min-h--5px { + min-height: -5px !important + } + + .min-w--5px { + min-width: -5px !important + } + + .px--5px { + padding-inline: -5px !important + } + + .mt--5px { + margin-block-start: -5px + } + + .mb--5px { + margin-block-end: -5px + } + + .ms--5px { + margin-inline-start: -5px + } + + .me--5px { + margin-inline-end: -5px + } + + .pt--5px { + padding-block-start: -5px + } + + .pb--5px { + padding-block-end: -5px + } + + .ps--5px { + padding-inline-start: -5px + } + + .pe--5px { + padding-inline-end: -5px + } + + .w--25px { + width: -25px !important + } + + .h--25px { + height: -25px !important + } + + .lh--25px { + line-height: -25px + } + + .min-h--25px { + min-height: -25px !important + } + + .min-w--25px { + min-width: -25px !important + } + + .px--25px { + padding-inline: -25px !important + } + + .mt--25px { + margin-block-start: -25px + } + + .mb--25px { + margin-block-end: -25px + } + + .ms--25px { + margin-inline-start: -25px + } + + .me--25px { + margin-inline-end: -25px + } + + .pt--25px { + padding-block-start: -25px + } + + .pb--25px { + padding-block-end: -25px + } + + .ps--25px { + padding-inline-start: -25px + } + + .pe--25px { + padding-inline-end: -25px + } + + .fs-8px { + font-size: 8px + } + + .fs-10px { + font-size: 10px + } + + .fs-12px { + font-size: 12px + } + + .fs-14px { + font-size: 14px + } + + .fs-16px { + font-size: 16px + } + + .fs-18px { + font-size: 18px + } + + .fs-20px { + font-size: 20px + } + + .fs-22px { + font-size: 22px + } + + .fs-24px { + font-size: 24px + } + + .fs-26px { + font-size: 26px + } + + @media(max-width: 767.98px) { + .fs-26px { + font-size: 21.66667px + } + } + + .fs-28px { + font-size: 28px + } + + @media(max-width: 767.98px) { + .fs-28px { + font-size: 23.33333px + } + } + + .fs-30px { + font-size: 30px + } + + @media(max-width: 767.98px) { + .fs-30px { + font-size: 25px + } + } + + .fs-36px { + font-size: 36px + } + + .fs-42px { + font-size: 42px + } + + .fs-48px { + font-size: 48px + } + + .fs-52px { + font-size: 52px + } + + .fs-56px { + font-size: 56px + } + + .rounded-5px { + border-radius: 5px !important + } + + .rounded-end-start-5px { + border-end-start-radius: 5px !important + } + + .rounded-start-end-5px { + border-start-end-radius: 5px !important + } + + .rounded-end-end-5px { + border-end-end-radius: 5px !important + } + + .rounded-start-start-5px { + border-start-start-radius: 5px !important + } + + .rounded-top-right-5px { + border-start-end-radius: 5px !important + } + + .rounded-8px { + border-radius: 8px !important + } + + .rounded-end-start-8px { + border-end-start-radius: 8px !important + } + + .rounded-start-end-8px { + border-start-end-radius: 8px !important + } + + .rounded-end-end-8px { + border-end-end-radius: 8px !important + } + + .rounded-start-start-8px { + border-start-start-radius: 8px !important + } + + .rounded-top-right-8px { + border-start-end-radius: 8px !important + } + + .rounded-10px { + border-radius: 10px !important + } + + .rounded-end-start-10px { + border-end-start-radius: 10px !important + } + + .rounded-start-end-10px { + border-start-end-radius: 10px !important + } + + .rounded-end-end-10px { + border-end-end-radius: 10px !important + } + + .rounded-start-start-10px { + border-start-start-radius: 10px !important + } + + .rounded-top-right-10px { + border-start-end-radius: 10px !important + } + + .rounded-12px { + border-radius: 12px !important + } + + .rounded-end-start-12px { + border-end-start-radius: 12px !important + } + + .rounded-start-end-12px { + border-start-end-radius: 12px !important + } + + .rounded-end-end-12px { + border-end-end-radius: 12px !important + } + + .rounded-start-start-12px { + border-start-start-radius: 12px !important + } + + .rounded-top-right-12px { + border-start-end-radius: 12px !important + } + + .rounded-14px { + border-radius: 14px !important + } + + .rounded-end-start-14px { + border-end-start-radius: 14px !important + } + + .rounded-start-end-14px { + border-start-end-radius: 14px !important + } + + .rounded-end-end-14px { + border-end-end-radius: 14px !important + } + + .rounded-start-start-14px { + border-start-start-radius: 14px !important + } + + .rounded-top-right-14px { + border-start-end-radius: 14px !important + } + + .rounded-16px { + border-radius: 16px !important + } + + .rounded-end-start-16px { + border-end-start-radius: 16px !important + } + + .rounded-start-end-16px { + border-start-end-radius: 16px !important + } + + .rounded-end-end-16px { + border-end-end-radius: 16px !important + } + + .rounded-start-start-16px { + border-start-start-radius: 16px !important + } + + .rounded-top-right-16px { + border-start-end-radius: 16px !important + } + + .rounded-18px { + border-radius: 18px !important + } + + .rounded-end-start-18px { + border-end-start-radius: 18px !important + } + + .rounded-start-end-18px { + border-start-end-radius: 18px !important + } + + .rounded-end-end-18px { + border-end-end-radius: 18px !important + } + + .rounded-start-start-18px { + border-start-start-radius: 18px !important + } + + .rounded-top-right-18px { + border-start-end-radius: 18px !important + } + + .rounded-20px { + border-radius: 20px !important + } + + .rounded-end-start-20px { + border-end-start-radius: 20px !important + } + + .rounded-start-end-20px { + border-start-end-radius: 20px !important + } + + .rounded-end-end-20px { + border-end-end-radius: 20px !important + } + + .rounded-start-start-20px { + border-start-start-radius: 20px !important + } + + .rounded-top-right-20px { + border-start-end-radius: 20px !important + } + + .rounded-22px { + border-radius: 22px !important + } + + .rounded-end-start-22px { + border-end-start-radius: 22px !important + } + + .rounded-start-end-22px { + border-start-end-radius: 22px !important + } + + .rounded-end-end-22px { + border-end-end-radius: 22px !important + } + + .rounded-start-start-22px { + border-start-start-radius: 22px !important + } + + .rounded-top-right-22px { + border-start-end-radius: 22px !important + } + + .rounded-24px { + border-radius: 24px !important + } + + .rounded-end-start-24px { + border-end-start-radius: 24px !important + } + + .rounded-start-end-24px { + border-start-end-radius: 24px !important + } + + .rounded-end-end-24px { + border-end-end-radius: 24px !important + } + + .rounded-start-start-24px { + border-start-start-radius: 24px !important + } + + .rounded-top-right-24px { + border-start-end-radius: 24px !important + } + + .rounded-26px { + border-radius: 26px !important + } + + .rounded-end-start-26px { + border-end-start-radius: 26px !important + } + + .rounded-start-end-26px { + border-start-end-radius: 26px !important + } + + .rounded-end-end-26px { + border-end-end-radius: 26px !important + } + + .rounded-start-start-26px { + border-start-start-radius: 26px !important + } + + .rounded-top-right-26px { + border-start-end-radius: 26px !important + } + + .rounded-28px { + border-radius: 28px !important + } + + .rounded-end-start-28px { + border-end-start-radius: 28px !important + } + + .rounded-start-end-28px { + border-start-end-radius: 28px !important + } + + .rounded-end-end-28px { + border-end-end-radius: 28px !important + } + + .rounded-start-start-28px { + border-start-start-radius: 28px !important + } + + .rounded-top-right-28px { + border-start-end-radius: 28px !important + } + + .rounded-35px { + border-radius: 35px !important + } + + .rounded-end-start-35px { + border-end-start-radius: 35px !important + } + + .rounded-start-end-35px { + border-start-end-radius: 35px !important + } + + .rounded-end-end-35px { + border-end-end-radius: 35px !important + } + + .rounded-start-start-35px { + border-start-start-radius: 35px !important + } + + .rounded-top-right-35px { + border-start-end-radius: 35px !important + } + + .rounded-40px { + border-radius: 40px !important + } + + .rounded-end-start-40px { + border-end-start-radius: 40px !important + } + + .rounded-start-end-40px { + border-start-end-radius: 40px !important + } + + .rounded-end-end-40px { + border-end-end-radius: 40px !important + } + + .rounded-start-start-40px { + border-start-start-radius: 40px !important + } + + .rounded-top-right-40px { + border-start-end-radius: 40px !important + } + + .rounded-45px { + border-radius: 45px !important + } + + .rounded-end-start-45px { + border-end-start-radius: 45px !important + } + + .rounded-start-end-45px { + border-start-end-radius: 45px !important + } + + .rounded-end-end-45px { + border-end-end-radius: 45px !important + } + + .rounded-start-start-45px { + border-start-start-radius: 45px !important + } + + .rounded-top-right-45px { + border-start-end-radius: 45px !important + } + + .rounded-30px { + border-radius: 30px !important + } + + .rounded-end-start-30px { + border-end-start-radius: 30px !important + } + + .rounded-start-end-30px { + border-start-end-radius: 30px !important + } + + .rounded-end-end-30px { + border-end-end-radius: 30px !important + } + + .rounded-start-start-30px { + border-start-start-radius: 30px !important + } + + .rounded-top-right-30px { + border-start-end-radius: 30px !important + } + + .rotate-45deg { + transform: rotate(45deg) !important + } + + .rotate-90deg { + transform: rotate(90deg) !important + } + + .rotate--90deg { + transform: rotate(-90deg) !important + } + + .rotate-0 { + transform: rotate(0) !important + } + + .rotate-180deg { + transform: rotate(180deg) !important + } + + .rotate--180deg { + transform: rotate(-180deg) !important + } + + .w--webkit-fill-available { + width: -webkit-fill-available !important + } + + .w-fit-content { + width: fit-content !important + } + + .w-max-content { + width: max-content !important + } + + .w-min-content { + width: min-content !important + } + + .w-unset { + width: unset !important + } + + .start-5px { + inset-inline-start: 5px + } + + .end-5px, + .inset-end-5px, + .left-5px { + inset-inline-end: 5px + } + + .right-5px { + inset-inline-start: 5px + } + + .top-5px { + inset-block-start: 5px + } + + .bottom-5px { + inset-block-end: 5px + } + + .start-8px { + inset-inline-start: 8px + } + + .end-8px, + .inset-end-8px, + .left-8px { + inset-inline-end: 8px + } + + .right-8px { + inset-inline-start: 8px + } + + .top-8px { + inset-block-start: 8px + } + + .bottom-8px { + inset-block-end: 8px + } + + .start-10px { + inset-inline-start: 10px + } + + .end-10px, + .inset-end-10px, + .left-10px { + inset-inline-end: 10px + } + + .right-10px { + inset-inline-start: 10px + } + + .top-10px { + inset-block-start: 10px + } + + .bottom-10px { + inset-block-end: 10px + } + + .start-12px { + inset-inline-start: 12px + } + + .end-12px, + .inset-end-12px, + .left-12px { + inset-inline-end: 12px + } + + .right-12px { + inset-inline-start: 12px + } + + .top-12px { + inset-block-start: 12px + } + + .bottom-12px { + inset-block-end: 12px + } + + .start-14px { + inset-inline-start: 14px + } + + .end-14px, + .inset-end-14px, + .left-14px { + inset-inline-end: 14px + } + + .right-14px { + inset-inline-start: 14px + } + + .top-14px { + inset-block-start: 14px + } + + .bottom-14px { + inset-block-end: 14px + } + + .start-16px { + inset-inline-start: 16px + } + + .end-16px, + .inset-end-16px, + .left-16px { + inset-inline-end: 16px + } + + .right-16px { + inset-inline-start: 16px + } + + .top-16px { + inset-block-start: 16px + } + + .bottom-16px { + inset-block-end: 16px + } + + .start-18px { + inset-inline-start: 18px + } + + .end-18px, + .inset-end-18px, + .left-18px { + inset-inline-end: 18px + } + + .right-18px { + inset-inline-start: 18px + } + + .top-18px { + inset-block-start: 18px + } + + .bottom-18px { + inset-block-end: 18px + } + + .start-20px { + inset-inline-start: 20px + } + + .end-20px, + .inset-end-20px, + .left-20px { + inset-inline-end: 20px + } + + .right-20px { + inset-inline-start: 20px + } + + .top-20px { + inset-block-start: 20px + } + + .bottom-20px { + inset-block-end: 20px + } + + .start-22px { + inset-inline-start: 22px + } + + .end-22px, + .inset-end-22px, + .left-22px { + inset-inline-end: 22px + } + + .right-22px { + inset-inline-start: 22px + } + + .top-22px { + inset-block-start: 22px + } + + .bottom-22px { + inset-block-end: 22px + } + + .start-24px { + inset-inline-start: 24px + } + + .end-24px, + .inset-end-24px, + .left-24px { + inset-inline-end: 24px + } + + .right-24px { + inset-inline-start: 24px + } + + .top-24px { + inset-block-start: 24px + } + + .bottom-24px { + inset-block-end: 24px + } + + .start-26px { + inset-inline-start: 26px + } + + .end-26px, + .inset-end-26px, + .left-26px { + inset-inline-end: 26px + } + + .right-26px { + inset-inline-start: 26px + } + + .top-26px { + inset-block-start: 26px + } + + .bottom-26px { + inset-block-end: 26px + } + + .start-28px { + inset-inline-start: 28px + } + + .end-28px, + .inset-end-28px, + .left-28px { + inset-inline-end: 28px + } + + .right-28px { + inset-inline-start: 28px + } + + .top-28px { + inset-block-start: 28px + } + + .bottom-28px { + inset-block-end: 28px + } + + .start-30px { + inset-inline-start: 30px + } + + .end-30px, + .inset-end-30px, + .left-30px { + inset-inline-end: 30px + } + + .right-30px { + inset-inline-start: 30px + } + + .top-30px { + inset-block-start: 30px + } + + .bottom-30px { + inset-block-end: 30px + } + + .start-35px { + inset-inline-start: 35px + } + + .end-35px, + .inset-end-35px, + .left-35px { + inset-inline-end: 35px + } + + .right-35px { + inset-inline-start: 35px + } + + .top-35px { + inset-block-start: 35px + } + + .bottom-35px { + inset-block-end: 35px + } + + .start-40px { + inset-inline-start: 40px + } + + .end-40px, + .inset-end-40px, + .left-40px { + inset-inline-end: 40px + } + + .right-40px { + inset-inline-start: 40px + } + + .top-40px { + inset-block-start: 40px + } + + .bottom-40px { + inset-block-end: 40px + } + + .start-45px { + inset-inline-start: 45px + } + + .end-45px, + .inset-end-45px, + .left-45px { + inset-inline-end: 45px + } + + .right-45px { + inset-inline-start: 45px + } + + .top-45px { + inset-block-start: 45px + } + + .bottom-45px { + inset-block-end: 45px + } + + .start-50px { + inset-inline-start: 50px + } + + .end-50px, + .inset-end-50px, + .left-50px { + inset-inline-end: 50px + } + + .right-50px { + inset-inline-start: 50px + } + + .top-50px { + inset-block-start: 50px + } + + .bottom-50px { + inset-block-end: 50px + } + + .start-55px { + inset-inline-start: 55px + } + + .end-55px, + .inset-end-55px, + .left-55px { + inset-inline-end: 55px + } + + .right-55px { + inset-inline-start: 55px + } + + .top-55px { + inset-block-start: 55px + } + + .bottom-55px { + inset-block-end: 55px + } + + .start-60px { + inset-inline-start: 60px + } + + .end-60px, + .inset-end-60px, + .left-60px { + inset-inline-end: 60px + } + + .right-60px { + inset-inline-start: 60px + } + + .top-60px { + inset-block-start: 60px + } + + .bottom-60px { + inset-block-end: 60px + } + + .start-70px { + inset-inline-start: 70px + } + + .end-70px, + .inset-end-70px, + .left-70px { + inset-inline-end: 70px + } + + .right-70px { + inset-inline-start: 70px + } + + .top-70px { + inset-block-start: 70px + } + + .bottom-70px { + inset-block-end: 70px + } + + .start-100px { + inset-inline-start: 100px + } + + .end-100px, + .inset-end-100px, + .left-100px { + inset-inline-end: 100px + } + + .right-100px { + inset-inline-start: 100px + } + + .top-100px { + inset-block-start: 100px + } + + .bottom-100px { + inset-block-end: 100px + } + + .start-170px { + inset-inline-start: 170px + } + + .end-170px, + .inset-end-170px, + .left-170px { + inset-inline-end: 170px + } + + .right-170px { + inset-inline-start: 170px + } + + .top-170px { + inset-block-start: 170px + } + + .bottom-170px { + inset-block-end: 170px + } + + .start--3px { + inset-inline-start: -3px + } + + .end--3px, + .inset-end--3px, + .left--3px { + inset-inline-end: -3px + } + + .right--3px { + inset-inline-start: -3px + } + + .top--3px { + inset-block-start: -3px + } + + .bottom--3px { + inset-block-end: -3px + } + + .start--10px { + inset-inline-start: -10px + } + + .end--10px, + .inset-end--10px, + .left--10px { + inset-inline-end: -10px + } + + .right--10px { + inset-inline-start: -10px + } + + .top--10px { + inset-block-start: -10px + } + + .bottom--10px { + inset-block-end: -10px + } + + .start--15px { + inset-inline-start: -15px + } + + .end--15px, + .inset-end--15px, + .left--15px { + inset-inline-end: -15px + } + + .right--15px { + inset-inline-start: -15px + } + + .top--15px { + inset-block-start: -15px + } + + .bottom--15px { + inset-block-end: -15px + } + + .start--20px { + inset-inline-start: -20px + } + + .end--20px, + .inset-end--20px, + .left--20px { + inset-inline-end: -20px + } + + .right--20px { + inset-inline-start: -20px + } + + .top--20px { + inset-block-start: -20px + } + + .bottom--20px { + inset-block-end: -20px + } + + .start--30px { + inset-inline-start: -30px + } + + .end--30px, + .inset-end--30px, + .left--30px { + inset-inline-end: -30px + } + + .right--30px { + inset-inline-start: -30px + } + + .top--30px { + inset-block-start: -30px + } + + .bottom--30px { + inset-block-end: -30px + } + + .start--40px { + inset-inline-start: -40px + } + + .end--40px, + .inset-end--40px, + .left--40px { + inset-inline-end: -40px + } + + .right--40px { + inset-inline-start: -40px + } + + .top--40px { + inset-block-start: -40px + } + + .bottom--40px { + inset-block-end: -40px + } + + .start--50px { + inset-inline-start: -50px + } + + .end--50px, + .inset-end--50px, + .left--50px { + inset-inline-end: -50px + } + + .right--50px { + inset-inline-start: -50px + } + + .top--50px { + inset-block-start: -50px + } + + .bottom--50px { + inset-block-end: -50px + } + + @media(min-width: 768px)and (max-width:1199.98px) { + .w-md-7px { + width: 7px !important + } + + .h-md-7px { + height: 7px !important + } + + .lh-md-7px { + line-height: 7px !important + } + + .w-md-10px { + width: 10px !important + } + + .h-md-10px { + height: 10px !important + } + + .lh-md-10px { + line-height: 10px !important + } + + .w-md-12px { + width: 12px !important + } + + .h-md-12px { + height: 12px !important + } + + .lh-md-12px { + line-height: 12px !important + } + + .w-md-14px { + width: 14px !important + } + + .h-md-14px { + height: 14px !important + } + + .lh-md-14px { + line-height: 14px !important + } + + .w-md-16px { + width: 16px !important + } + + .h-md-16px { + height: 16px !important + } + + .lh-md-16px { + line-height: 16px !important + } + + .w-md-18px { + width: 18px !important + } + + .h-md-18px { + height: 18px !important + } + + .lh-md-18px { + line-height: 18px !important + } + + .w-md-20px { + width: 20px !important + } + + .h-md-20px { + height: 20px !important + } + + .lh-md-20px { + line-height: 20px !important + } + + .w-md-22px { + width: 22px !important + } + + .h-md-22px { + height: 22px !important + } + + .lh-md-22px { + line-height: 22px !important + } + + .w-md-24px { + width: 24px !important + } + + .h-md-24px { + height: 24px !important + } + + .lh-md-24px { + line-height: 24px !important + } + + .w-md-26px { + width: 26px !important + } + + .h-md-26px { + height: 26px !important + } + + .lh-md-26px { + line-height: 26px !important + } + + .w-md-28px { + width: 28px !important + } + + .h-md-28px { + height: 28px !important + } + + .lh-md-28px { + line-height: 28px !important + } + + .w-md-30px { + width: 30px !important + } + + .h-md-30px { + height: 30px !important + } + + .lh-md-30px { + line-height: 30px !important + } + + .w-md-32px { + width: 32px !important + } + + .h-md-32px { + height: 32px !important + } + + .lh-md-32px { + line-height: 32px !important + } + + .w-md-34px { + width: 34px !important + } + + .h-md-34px { + height: 34px !important + } + + .lh-md-34px { + line-height: 34px !important + } + + .w-md-36px { + width: 36px !important + } + + .h-md-36px { + height: 36px !important + } + + .lh-md-36px { + line-height: 36px !important + } + + .w-md-40px { + width: 40px !important + } + + .h-md-40px { + height: 40px !important + } + + .lh-md-40px { + line-height: 40px !important + } + + .w-md-42px { + width: 42px !important + } + + .h-md-42px { + height: 42px !important + } + + .lh-md-42px { + line-height: 42px !important + } + + .w-md-45px { + width: 45px !important + } + + .h-md-45px { + height: 45px !important + } + + .lh-md-45px { + line-height: 45px !important + } + + .w-md-50px { + width: 50px !important + } + + .h-md-50px { + height: 50px !important + } + + .lh-md-50px { + line-height: 50px !important + } + + .w-md-52px { + width: 52px !important + } + + .h-md-52px { + height: 52px !important + } + + .lh-md-52px { + line-height: 52px !important + } + + .w-md-54px { + width: 54px !important + } + + .h-md-54px { + height: 54px !important + } + + .lh-md-54px { + line-height: 54px !important + } + + .w-md-56px { + width: 56px !important + } + + .h-md-56px { + height: 56px !important + } + + .lh-md-56px { + line-height: 56px !important + } + + .w-md-58px { + width: 58px !important + } + + .h-md-58px { + height: 58px !important + } + + .lh-md-58px { + line-height: 58px !important + } + + .w-md-60px { + width: 60px !important + } + + .h-md-60px { + height: 60px !important + } + + .lh-md-60px { + line-height: 60px !important + } + + .w-md-65px { + width: 65px !important + } + + .h-md-65px { + height: 65px !important + } + + .lh-md-65px { + line-height: 65px !important + } + + .w-md-70px { + width: 70px !important + } + + .h-md-70px { + height: 70px !important + } + + .lh-md-70px { + line-height: 70px !important + } + + .w-md-80px { + width: 80px !important + } + + .h-md-80px { + height: 80px !important + } + + .lh-md-80px { + line-height: 80px !important + } + + .w-md-90px { + width: 90px !important + } + + .h-md-90px { + height: 90px !important + } + + .lh-md-90px { + line-height: 90px !important + } + + .w-md-100px { + width: 100px !important + } + + .h-md-100px { + height: 100px !important + } + + .lh-md-100px { + line-height: 100px !important + } + + .w-md-110px { + width: 110px !important + } + + .h-md-110px { + height: 110px !important + } + + .lh-md-110px { + line-height: 110px !important + } + + .w-md-115px { + width: 115px !important + } + + .h-md-115px { + height: 115px !important + } + + .lh-md-115px { + line-height: 115px !important + } + + .w-md-130px { + width: 130px !important + } + + .h-md-130px { + height: 130px !important + } + + .lh-md-130px { + line-height: 130px !important + } + + .w-md-140px { + width: 140px !important + } + + .h-md-140px { + height: 140px !important + } + + .lh-md-140px { + line-height: 140px !important + } + + .w-md-150px { + width: 150px !important + } + + .h-md-150px { + height: 150px !important + } + + .lh-md-150px { + line-height: 150px !important + } + + .w-md-200px { + width: 200px !important + } + + .h-md-200px { + height: 200px !important + } + + .lh-md-200px { + line-height: 200px !important + } + + .w-md-300px { + width: 300px !important + } + + .h-md-300px { + height: 300px !important + } + + .lh-md-300px { + line-height: 300px !important + } + + .w-md--10px { + width: -10px !important + } + + .h-md--10px { + height: -10px !important + } + + .lh-md--10px { + line-height: -10px !important + } + + .w-md--5px { + width: -5px !important + } + + .h-md--5px { + height: -5px !important + } + + .lh-md--5px { + line-height: -5px !important + } + + .w-md--25px { + width: -25px !important + } + + .h-md--25px { + height: -25px !important + } + + .lh-md--25px { + line-height: -25px !important + } + + .fs-md-8px { + font-size: 8px + } + + .fs-md-10px { + font-size: 10px + } + + .fs-md-12px { + font-size: 12px + } + + .fs-md-14px { + font-size: 14px + } + + .fs-md-16px { + font-size: 16px + } + + .fs-md-18px { + font-size: 18px + } + + .fs-md-20px { + font-size: 20px + } + + .fs-md-22px { + font-size: 22px + } + + .fs-md-24px { + font-size: 24px + } + + .fs-md-26px { + font-size: 26px + } + + .fs-md-28px { + font-size: 28px + } + + .fs-md-30px { + font-size: 30px + } + + .fs-md-36px { + font-size: 36px + } + + .fs-md-42px { + font-size: 42px + } + + .fs-md-48px { + font-size: 48px + } + + .fs-md-52px { + font-size: 52px + } + + .fs-md-56px { + font-size: 56px + } + + .w-md--webkit-fill-available { + width: -webkit-fill-available !important + } + + .w-md-fit-content { + width: fit-content !important + } + + .w-md-max-content { + width: max-content !important + } + + .w-md-min-content { + width: min-content !important + } + + .w-md-unset { + width: unset !important + } + } + + @media(max-width: 575.98px) { + .w-sm--webkit-fill-available { + width: -webkit-fill-available !important + } + + .w-sm-fit-content { + width: fit-content !important + } + + .w-sm-max-content { + width: max-content !important + } + + .w-sm-min-content { + width: min-content !important + } + + .w-sm-unset { + width: unset !important + } + + .w-sm-7px { + width: 7px !important + } + + .h-sm-7px { + height: 7px !important + } + + .lh-sm-7px { + line-height: 7px !important + } + + .w-sm-10px { + width: 10px !important + } + + .h-sm-10px { + height: 10px !important + } + + .lh-sm-10px { + line-height: 10px !important + } + + .w-sm-12px { + width: 12px !important + } + + .h-sm-12px { + height: 12px !important + } + + .lh-sm-12px { + line-height: 12px !important + } + + .w-sm-14px { + width: 14px !important + } + + .h-sm-14px { + height: 14px !important + } + + .lh-sm-14px { + line-height: 14px !important + } + + .w-sm-16px { + width: 16px !important + } + + .h-sm-16px { + height: 16px !important + } + + .lh-sm-16px { + line-height: 16px !important + } + + .w-sm-18px { + width: 18px !important + } + + .h-sm-18px { + height: 18px !important + } + + .lh-sm-18px { + line-height: 18px !important + } + + .w-sm-20px { + width: 20px !important + } + + .h-sm-20px { + height: 20px !important + } + + .lh-sm-20px { + line-height: 20px !important + } + + .w-sm-22px { + width: 22px !important + } + + .h-sm-22px { + height: 22px !important + } + + .lh-sm-22px { + line-height: 22px !important + } + + .w-sm-24px { + width: 24px !important + } + + .h-sm-24px { + height: 24px !important + } + + .lh-sm-24px { + line-height: 24px !important + } + + .w-sm-26px { + width: 26px !important + } + + .h-sm-26px { + height: 26px !important + } + + .lh-sm-26px { + line-height: 26px !important + } + + .w-sm-28px { + width: 28px !important + } + + .h-sm-28px { + height: 28px !important + } + + .lh-sm-28px { + line-height: 28px !important + } + + .w-sm-30px { + width: 30px !important + } + + .h-sm-30px { + height: 30px !important + } + + .lh-sm-30px { + line-height: 30px !important + } + + .w-sm-32px { + width: 32px !important + } + + .h-sm-32px { + height: 32px !important + } + + .lh-sm-32px { + line-height: 32px !important + } + + .w-sm-34px { + width: 34px !important + } + + .h-sm-34px { + height: 34px !important + } + + .lh-sm-34px { + line-height: 34px !important + } + + .w-sm-36px { + width: 36px !important + } + + .h-sm-36px { + height: 36px !important + } + + .lh-sm-36px { + line-height: 36px !important + } + + .w-sm-40px { + width: 40px !important + } + + .h-sm-40px { + height: 40px !important + } + + .lh-sm-40px { + line-height: 40px !important + } + + .w-sm-42px { + width: 42px !important + } + + .h-sm-42px { + height: 42px !important + } + + .lh-sm-42px { + line-height: 42px !important + } + + .w-sm-45px { + width: 45px !important + } + + .h-sm-45px { + height: 45px !important + } + + .lh-sm-45px { + line-height: 45px !important + } + + .w-sm-50px { + width: 50px !important + } + + .h-sm-50px { + height: 50px !important + } + + .lh-sm-50px { + line-height: 50px !important + } + + .w-sm-52px { + width: 52px !important + } + + .h-sm-52px { + height: 52px !important + } + + .lh-sm-52px { + line-height: 52px !important + } + + .w-sm-54px { + width: 54px !important + } + + .h-sm-54px { + height: 54px !important + } + + .lh-sm-54px { + line-height: 54px !important + } + + .w-sm-56px { + width: 56px !important + } + + .h-sm-56px { + height: 56px !important + } + + .lh-sm-56px { + line-height: 56px !important + } + + .w-sm-58px { + width: 58px !important + } + + .h-sm-58px { + height: 58px !important + } + + .lh-sm-58px { + line-height: 58px !important + } + + .w-sm-60px { + width: 60px !important + } + + .h-sm-60px { + height: 60px !important + } + + .lh-sm-60px { + line-height: 60px !important + } + + .w-sm-65px { + width: 65px !important + } + + .h-sm-65px { + height: 65px !important + } + + .lh-sm-65px { + line-height: 65px !important + } + + .w-sm-70px { + width: 70px !important + } + + .h-sm-70px { + height: 70px !important + } + + .lh-sm-70px { + line-height: 70px !important + } + + .w-sm-80px { + width: 80px !important + } + + .h-sm-80px { + height: 80px !important + } + + .lh-sm-80px { + line-height: 80px !important + } + + .w-sm-90px { + width: 90px !important + } + + .h-sm-90px { + height: 90px !important + } + + .lh-sm-90px { + line-height: 90px !important + } + + .w-sm-100px { + width: 100px !important + } + + .h-sm-100px { + height: 100px !important + } + + .lh-sm-100px { + line-height: 100px !important + } + + .w-sm-110px { + width: 110px !important + } + + .h-sm-110px { + height: 110px !important + } + + .lh-sm-110px { + line-height: 110px !important + } + + .w-sm-115px { + width: 115px !important + } + + .h-sm-115px { + height: 115px !important + } + + .lh-sm-115px { + line-height: 115px !important + } + + .w-sm-130px { + width: 130px !important + } + + .h-sm-130px { + height: 130px !important + } + + .lh-sm-130px { + line-height: 130px !important + } + + .w-sm-140px { + width: 140px !important + } + + .h-sm-140px { + height: 140px !important + } + + .lh-sm-140px { + line-height: 140px !important + } + + .w-sm-150px { + width: 150px !important + } + + .h-sm-150px { + height: 150px !important + } + + .lh-sm-150px { + line-height: 150px !important + } + + .w-sm-200px { + width: 200px !important + } + + .h-sm-200px { + height: 200px !important + } + + .lh-sm-200px { + line-height: 200px !important + } + + .w-sm-300px { + width: 300px !important + } + + .h-sm-300px { + height: 300px !important + } + + .lh-sm-300px { + line-height: 300px !important + } + + .w-sm--10px { + width: -10px !important + } + + .h-sm--10px { + height: -10px !important + } + + .lh-sm--10px { + line-height: -10px !important + } + + .w-sm--5px { + width: -5px !important + } + + .h-sm--5px { + height: -5px !important + } + + .lh-sm--5px { + line-height: -5px !important + } + + .w-sm--25px { + width: -25px !important + } + + .h-sm--25px { + height: -25px !important + } + + .lh-sm--25px { + line-height: -25px !important + } + + .left-sm-5px { + inset-inline-start: 5px + } + + .right-sm-5px { + inset-inline-end: 5px + } + + .top-sm-5px { + inset-block-start: 5px + } + + .bottom-sm-5px { + inset-block-end: 5px + } + + .left-sm-8px { + inset-inline-start: 8px + } + + .right-sm-8px { + inset-inline-end: 8px + } + + .top-sm-8px { + inset-block-start: 8px + } + + .bottom-sm-8px { + inset-block-end: 8px + } + + .left-sm-10px { + inset-inline-start: 10px + } + + .right-sm-10px { + inset-inline-end: 10px + } + + .top-sm-10px { + inset-block-start: 10px + } + + .bottom-sm-10px { + inset-block-end: 10px + } + + .left-sm-12px { + inset-inline-start: 12px + } + + .right-sm-12px { + inset-inline-end: 12px + } + + .top-sm-12px { + inset-block-start: 12px + } + + .bottom-sm-12px { + inset-block-end: 12px + } + + .left-sm-14px { + inset-inline-start: 14px + } + + .right-sm-14px { + inset-inline-end: 14px + } + + .top-sm-14px { + inset-block-start: 14px + } + + .bottom-sm-14px { + inset-block-end: 14px + } + + .left-sm-16px { + inset-inline-start: 16px + } + + .right-sm-16px { + inset-inline-end: 16px + } + + .top-sm-16px { + inset-block-start: 16px + } + + .bottom-sm-16px { + inset-block-end: 16px + } + + .left-sm-18px { + inset-inline-start: 18px + } + + .right-sm-18px { + inset-inline-end: 18px + } + + .top-sm-18px { + inset-block-start: 18px + } + + .bottom-sm-18px { + inset-block-end: 18px + } + + .left-sm-20px { + inset-inline-start: 20px + } + + .right-sm-20px { + inset-inline-end: 20px + } + + .top-sm-20px { + inset-block-start: 20px + } + + .bottom-sm-20px { + inset-block-end: 20px + } + + .left-sm-22px { + inset-inline-start: 22px + } + + .right-sm-22px { + inset-inline-end: 22px + } + + .top-sm-22px { + inset-block-start: 22px + } + + .bottom-sm-22px { + inset-block-end: 22px + } + + .left-sm-24px { + inset-inline-start: 24px + } + + .right-sm-24px { + inset-inline-end: 24px + } + + .top-sm-24px { + inset-block-start: 24px + } + + .bottom-sm-24px { + inset-block-end: 24px + } + + .left-sm-26px { + inset-inline-start: 26px + } + + .right-sm-26px { + inset-inline-end: 26px + } + + .top-sm-26px { + inset-block-start: 26px + } + + .bottom-sm-26px { + inset-block-end: 26px + } + + .left-sm-28px { + inset-inline-start: 28px + } + + .right-sm-28px { + inset-inline-end: 28px + } + + .top-sm-28px { + inset-block-start: 28px + } + + .bottom-sm-28px { + inset-block-end: 28px + } + + .left-sm-30px { + inset-inline-start: 30px + } + + .right-sm-30px { + inset-inline-end: 30px + } + + .top-sm-30px { + inset-block-start: 30px + } + + .bottom-sm-30px { + inset-block-end: 30px + } + + .left-sm-35px { + inset-inline-start: 35px + } + + .right-sm-35px { + inset-inline-end: 35px + } + + .top-sm-35px { + inset-block-start: 35px + } + + .bottom-sm-35px { + inset-block-end: 35px + } + + .left-sm-40px { + inset-inline-start: 40px + } + + .right-sm-40px { + inset-inline-end: 40px + } + + .top-sm-40px { + inset-block-start: 40px + } + + .bottom-sm-40px { + inset-block-end: 40px + } + + .left-sm-45px { + inset-inline-start: 45px + } + + .right-sm-45px { + inset-inline-end: 45px + } + + .top-sm-45px { + inset-block-start: 45px + } + + .bottom-sm-45px { + inset-block-end: 45px + } + + .left-sm-50px { + inset-inline-start: 50px + } + + .right-sm-50px { + inset-inline-end: 50px + } + + .top-sm-50px { + inset-block-start: 50px + } + + .bottom-sm-50px { + inset-block-end: 50px + } + + .left-sm-55px { + inset-inline-start: 55px + } + + .right-sm-55px { + inset-inline-end: 55px + } + + .top-sm-55px { + inset-block-start: 55px + } + + .bottom-sm-55px { + inset-block-end: 55px + } + + .left-sm-60px { + inset-inline-start: 60px + } + + .right-sm-60px { + inset-inline-end: 60px + } + + .top-sm-60px { + inset-block-start: 60px + } + + .bottom-sm-60px { + inset-block-end: 60px + } + + .left-sm-70px { + inset-inline-start: 70px + } + + .right-sm-70px { + inset-inline-end: 70px + } + + .top-sm-70px { + inset-block-start: 70px + } + + .bottom-sm-70px { + inset-block-end: 70px + } + + .left-sm-100px { + inset-inline-start: 100px + } + + .right-sm-100px { + inset-inline-end: 100px + } + + .top-sm-100px { + inset-block-start: 100px + } + + .bottom-sm-100px { + inset-block-end: 100px + } + + .left-sm-170px { + inset-inline-start: 170px + } + + .right-sm-170px { + inset-inline-end: 170px + } + + .top-sm-170px { + inset-block-start: 170px + } + + .bottom-sm-170px { + inset-block-end: 170px + } + + .left-sm--3px { + inset-inline-start: -3px + } + + .right-sm--3px { + inset-inline-end: -3px + } + + .top-sm--3px { + inset-block-start: -3px + } + + .bottom-sm--3px { + inset-block-end: -3px + } + + .left-sm--10px { + inset-inline-start: -10px + } + + .right-sm--10px { + inset-inline-end: -10px + } + + .top-sm--10px { + inset-block-start: -10px + } + + .bottom-sm--10px { + inset-block-end: -10px + } + + .left-sm--15px { + inset-inline-start: -15px + } + + .right-sm--15px { + inset-inline-end: -15px + } + + .top-sm--15px { + inset-block-start: -15px + } + + .bottom-sm--15px { + inset-block-end: -15px + } + + .left-sm--20px { + inset-inline-start: -20px + } + + .right-sm--20px { + inset-inline-end: -20px + } + + .top-sm--20px { + inset-block-start: -20px + } + + .bottom-sm--20px { + inset-block-end: -20px + } + + .left-sm--30px { + inset-inline-start: -30px + } + + .right-sm--30px { + inset-inline-end: -30px + } + + .top-sm--30px { + inset-block-start: -30px + } + + .bottom-sm--30px { + inset-block-end: -30px + } + + .left-sm--40px { + inset-inline-start: -40px + } + + .right-sm--40px { + inset-inline-end: -40px + } + + .top-sm--40px { + inset-block-start: -40px + } + + .bottom-sm--40px { + inset-block-end: -40px + } + + .left-sm--50px { + inset-inline-start: -50px + } + + .right-sm--50px { + inset-inline-end: -50px + } + + .top-sm--50px { + inset-block-start: -50px + } + + .bottom-sm--50px { + inset-block-end: -50px + } + + .fs-sm-8px { + font-size: 8px + } + + .fs-sm-10px { + font-size: 10px + } + + .fs-sm-12px { + font-size: 12px + } + + .fs-sm-14px { + font-size: 14px + } + + .fs-sm-16px { + font-size: 16px + } + + .fs-sm-18px { + font-size: 18px + } + + .fs-sm-20px { + font-size: 20px + } + + .fs-sm-22px { + font-size: 22px + } + + .fs-sm-24px { + font-size: 24px + } + + .fs-sm-26px { + font-size: 26px + } + + .fs-sm-28px { + font-size: 28px + } + + .fs-sm-30px { + font-size: 30px + } + + .fs-sm-36px { + font-size: 36px + } + + .fs-sm-42px { + font-size: 42px + } + + .fs-sm-48px { + font-size: 48px + } + + .fs-sm-52px { + font-size: 52px + } + + .fs-sm-56px { + font-size: 56px + } + + .rounded-sm-5px { + border-radius: 5px !important + } + + .rounded-end-start-sm-5px { + border-end-start-radius: 5px !important + } + + .rounded-end-end-sm-5px { + border-end-end-radius: 5px !important + } + + .rounded-start-start-sm-5px { + border-start-start-radius: 5px !important + } + + .rounded-start-end-sm-5px { + border-start-end-radius: 5px !important + } + + .rounded-sm-8px { + border-radius: 8px !important + } + + .rounded-end-start-sm-8px { + border-end-start-radius: 8px !important + } + + .rounded-end-end-sm-8px { + border-end-end-radius: 8px !important + } + + .rounded-start-start-sm-8px { + border-start-start-radius: 8px !important + } + + .rounded-start-end-sm-8px { + border-start-end-radius: 8px !important + } + + .rounded-sm-10px { + border-radius: 10px !important + } + + .rounded-end-start-sm-10px { + border-end-start-radius: 10px !important + } + + .rounded-end-end-sm-10px { + border-end-end-radius: 10px !important + } + + .rounded-start-start-sm-10px { + border-start-start-radius: 10px !important + } + + .rounded-start-end-sm-10px { + border-start-end-radius: 10px !important + } + + .rounded-sm-12px { + border-radius: 12px !important + } + + .rounded-end-start-sm-12px { + border-end-start-radius: 12px !important + } + + .rounded-end-end-sm-12px { + border-end-end-radius: 12px !important + } + + .rounded-start-start-sm-12px { + border-start-start-radius: 12px !important + } + + .rounded-start-end-sm-12px { + border-start-end-radius: 12px !important + } + + .rounded-sm-14px { + border-radius: 14px !important + } + + .rounded-end-start-sm-14px { + border-end-start-radius: 14px !important + } + + .rounded-end-end-sm-14px { + border-end-end-radius: 14px !important + } + + .rounded-start-start-sm-14px { + border-start-start-radius: 14px !important + } + + .rounded-start-end-sm-14px { + border-start-end-radius: 14px !important + } + + .rounded-sm-16px { + border-radius: 16px !important + } + + .rounded-end-start-sm-16px { + border-end-start-radius: 16px !important + } + + .rounded-end-end-sm-16px { + border-end-end-radius: 16px !important + } + + .rounded-start-start-sm-16px { + border-start-start-radius: 16px !important + } + + .rounded-start-end-sm-16px { + border-start-end-radius: 16px !important + } + + .rounded-sm-18px { + border-radius: 18px !important + } + + .rounded-end-start-sm-18px { + border-end-start-radius: 18px !important + } + + .rounded-end-end-sm-18px { + border-end-end-radius: 18px !important + } + + .rounded-start-start-sm-18px { + border-start-start-radius: 18px !important + } + + .rounded-start-end-sm-18px { + border-start-end-radius: 18px !important + } + + .rounded-sm-20px { + border-radius: 20px !important + } + + .rounded-end-start-sm-20px { + border-end-start-radius: 20px !important + } + + .rounded-end-end-sm-20px { + border-end-end-radius: 20px !important + } + + .rounded-start-start-sm-20px { + border-start-start-radius: 20px !important + } + + .rounded-start-end-sm-20px { + border-start-end-radius: 20px !important + } + + .rounded-sm-22px { + border-radius: 22px !important + } + + .rounded-end-start-sm-22px { + border-end-start-radius: 22px !important + } + + .rounded-end-end-sm-22px { + border-end-end-radius: 22px !important + } + + .rounded-start-start-sm-22px { + border-start-start-radius: 22px !important + } + + .rounded-start-end-sm-22px { + border-start-end-radius: 22px !important + } + + .rounded-sm-24px { + border-radius: 24px !important + } + + .rounded-end-start-sm-24px { + border-end-start-radius: 24px !important + } + + .rounded-end-end-sm-24px { + border-end-end-radius: 24px !important + } + + .rounded-start-start-sm-24px { + border-start-start-radius: 24px !important + } + + .rounded-start-end-sm-24px { + border-start-end-radius: 24px !important + } + + .rounded-sm-26px { + border-radius: 26px !important + } + + .rounded-end-start-sm-26px { + border-end-start-radius: 26px !important + } + + .rounded-end-end-sm-26px { + border-end-end-radius: 26px !important + } + + .rounded-start-start-sm-26px { + border-start-start-radius: 26px !important + } + + .rounded-start-end-sm-26px { + border-start-end-radius: 26px !important + } + + .rounded-sm-28px { + border-radius: 28px !important + } + + .rounded-end-start-sm-28px { + border-end-start-radius: 28px !important + } + + .rounded-end-end-sm-28px { + border-end-end-radius: 28px !important + } + + .rounded-start-start-sm-28px { + border-start-start-radius: 28px !important + } + + .rounded-start-end-sm-28px { + border-start-end-radius: 28px !important + } + + .rounded-sm-35px { + border-radius: 35px !important + } + + .rounded-end-start-sm-35px { + border-end-start-radius: 35px !important + } + + .rounded-end-end-sm-35px { + border-end-end-radius: 35px !important + } + + .rounded-start-start-sm-35px { + border-start-start-radius: 35px !important + } + + .rounded-start-end-sm-35px { + border-start-end-radius: 35px !important + } + + .rounded-sm-40px { + border-radius: 40px !important + } + + .rounded-end-start-sm-40px { + border-end-start-radius: 40px !important + } + + .rounded-end-end-sm-40px { + border-end-end-radius: 40px !important + } + + .rounded-start-start-sm-40px { + border-start-start-radius: 40px !important + } + + .rounded-start-end-sm-40px { + border-start-end-radius: 40px !important + } + + .rounded-sm-45px { + border-radius: 45px !important + } + + .rounded-end-start-sm-45px { + border-end-start-radius: 45px !important + } + + .rounded-end-end-sm-45px { + border-end-end-radius: 45px !important + } + + .rounded-start-start-sm-45px { + border-start-start-radius: 45px !important + } + + .rounded-start-end-sm-45px { + border-start-end-radius: 45px !important + } + + .rounded-sm-30px { + border-radius: 30px !important + } + + .rounded-end-start-sm-30px { + border-end-start-radius: 30px !important + } + + .rounded-end-end-sm-30px { + border-end-end-radius: 30px !important + } + + .rounded-start-start-sm-30px { + border-start-start-radius: 30px !important + } + + .rounded-start-end-sm-30px { + border-start-end-radius: 30px !important + } + } + + footer { + flex-shrink: 0; + position: relative + } + + footer .faq-link { + margin-inline-end: 64px + } + + footer .nav-link { + padding: 0 + } + + footer.footer-large .content-3 .nav a.nav-link i { + font-size: 22px + } + + .footer-large .content-1 { + background-color: #214570; + height: 8px; + width: 100% + } + + .footer-large .content-3 { + background-color: #082c36; + color: #fff; + padding: 30px 0; + text-align: center + } + + .footer-large .content-3 a { + color: #fff + } + + .footer-large .content-3 a:hover { + color: #d9d9d9 + } + + .footer-large .content-3 .nav a.nav-link i { + font-size: 22px + } + + .footer-large .content-4 { + background-color: #196956; + color: #fff; + font-size: 11px; + padding: 15px 0; + text-align: center + } + + + .dropdown-item { + text-align: start + } + + .nav { + padding-inline-start: 0 + } + + .dropdown-toggle:after { + color: #196956; + margin-inline-start: 10px; + vertical-align: middle + } + + .navbar-toggler:focus, + .navbar-toggler:hover { + outline: none; + text-decoration: none + } + + .navbar-mobile { + display: flex; + width: 100% + } + + .navbar-mobile .nav-link { + padding: .5rem 1rem + } + + .navbar-mobile .dropdown-item { + color: #196956 + } + + @media(max-width: 767px) { + .has-menu { + display: contents !important + } + + .navbar-mobile { + background: #fff; + display: block; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + width: 75% + } + + .offcanvas-backdrop.show { + inset-inline-end: 0; + inset-inline-start: auto; + width: 25% + } + + .offcanvas-collapse { + background-color: rgba(0, 0, 0, .4); + inset-block: 0; + inset-inline-start: -100%; + overflow-y: auto; + position: fixed; + transition-duration: .3s; + transition-property: inset-inline-start, visibility; + transition-timing-function: ease-in-out; + visibility: hidden; + width: 100% + } + + .offcanvas-collapse.open, + .offcanvas-collapse.show { + inset-inline-start: 0; + visibility: visible + } + + .offcanvas.show { + transform: none + } + + .offcanvas.offcanvas-start { + border-inline-end: 1px solid rgba(0, 0, 0, .2); + inset-inline-end: auto !important; + inset-inline-start: 0; + transform: translateX(100%) + } + } + + .custom-tabs.nav-pills .nav-link { + background-color: #f8f9fa + } + + .custom-tabs.nav-pills .nav-link.active.bg-white { + background-color: #196956 + } + + .sub-tabs.nav-tabs .nav-link.active.bg-white { + background-color: #196956 !important; + border-color: #196956 !important; + color: #fff !important + } + + @media(max-width: 767.98px) { + .custom-tabs.nav-pills { + gap: 20px + } + + .custom-tabs.nav-pills .nav-link { + background: #fff; + border-radius: 50px; + border-width: 0; + box-shadow: 0 2px 15px 0 rgba(78, 78, 78, .1); + color: #21446f + } + + .custom-tabs.nav-pills .nav-link.active { + background: #196956 !important; + color: #fff + } + + .custom-tabs.nav-pills .nav-link.active:before { + display: none + } + } + + @media(max-width: 767px) { + .user-sidebar--menu { + display: -ms-flexbox !important; + display: flex; + flex-wrap: wrap; + justify-content: space-between + } + + .user-sidebar--menu li:first-child { + flex-grow: 1; + width: 100% + } + + .user-sidebar--menu li { + background-color: #fff !important; + border-radius: 10px; + box-shadow: 0 1px 4px 0 rgba(78, 78, 78, .1) !important; + margin-block-end: 10px; + text-align: center; + width: 49% + } + + .user-sidebar--menu li a { + border-radius: 10px + } + + .user-sidebar--menu__option { + color: #214570; + justify-content: center + } + + .user-sidebar--menu__option:hover { + background-color: #fff; + box-shadow: none; + color: #707070 + } + + .user-sidebar--menu__option.menu-option-active { + background-color: #196956; + color: #fff + } + + .user-sidebar--menu__option.menu-option-active img { + filter: brightness(0) invert(1) + } + + .user-sidebar--menu__option .icon { + margin-inline-end: 10px + } + + .user-sidebar--menu__option:not(.active):hover { + background-color: #f2f2f2; + border-color: #196956 + } + } + + .breadcrumb { + background: none; + font-weight: 400; + padding: 10px 0 + } + + .breadcrumb a { + text-decoration: none + } + + .breadcrumb.breadcrumb-onslider { + inset-inline-start: 15px; + position: absolute; + top: 28px; + z-index: 7 + } + + .breadcrumb.breadcrumb-onslider.text-white .breadcrumb-item+.breadcrumb-item:before { + color: #fff !important + } + + .breadcrumb.breadcrumb-onslider.text-primary-green .breadcrumb-item+.breadcrumb-item:before { + color: #196956 !important + } + + .breadcrumb.breadcrumb-onslider.text-primary-blue .breadcrumb-item+.breadcrumb-item:before { + color: #214570 !important + } + + .breadcrumb .breadcrumb-item:not(.active) a { + color: #196956; + transition: all .3s linear + } + + .breadcrumb .breadcrumb-item:not(.active) a:hover { + color: #196956 + } + + .breadcrumb-item+.breadcrumb-item { + padding-inline-end: 0; + padding-inline-start: .3rem + } + + .breadcrumb-item+.breadcrumb-item:before { + padding-inline-end: .3rem; + padding-inline-start: 0 + } + + [dir=rtl] .breadcrumb-item+.breadcrumb-item:before { + float: right + } + + .btn { + touch-action: manipulation + } + + .btn:disabled { + background: #ccc !important; + border-color: #ccc !important; + cursor: not-allowed + } + + .btn:focus { + box-shadow: none !important + } + + .btn:active { + border-color: transparent !important + } + + .btn-link { + color: #196956; + text-decoration: none + } + + .btn-link:hover { + color: #196956 !important; + text-decoration: underline !important + } + + .btn-round-icon { + border-radius: 50%; + font-size: 20px; + height: 37px; + padding: 4px 0; + width: 38px + } + + .btn-primary-green { + background: #196956; + color: #fff + } + + .btn-primary-green:disabled { + color: #fff + } + + .btn-primary-green:focus, + .btn-primary-green:hover { + background: rgba(13, 143, 117, .8) !important; + color: #fff !important; + outline: none !important + } + + .btn-dugong { + background-color: #707070; + color: #fff + } + + .btn-dugong.disabled, + .btn-dugong:focus, + .btn-dugong:hover, + .btn-dugong[disabled] { + background-color: hsla(0, 0%, 44%, .8) !important; + color: #fff !important + } + + .btn-primary, + .btn-primary-blue { + background: #214570; + color: #fff + } + + .btn-primary-blue:focus, + .btn-primary-blue:hover, + .btn-primary:focus, + .btn-primary:hover { + background: rgba(33, 69, 112, .8) !important; + color: #fff !important; + outline: none !important + } + + .btn-gradient { + background: linear-gradient(270deg, #196956 20%, #214570 105%); + border-radius: 44px; + color: #fff + } + + .btn-gradient:hover { + background: linear-gradient(270deg, #196956 20%, #214570 105%) !important; + color: #fff !important + } + + .btn-light-grey { + background: #f7f7f7; + color: #545353 + } + + .btn-light-grey:hover { + background: #ececed !important; + color: #545353 !important; + outline: none + } + + .btn-dark-grey { + background: #d9d9d9; + color: #214570 + } + + .btn-dark-grey:hover { + background: #cac9c9 !important; + color: #214570 !important; + outline: none !important + } + + .btn-white { + background-color: #fff; + border-color: #fff; + color: #000 + } + + .btn-white:focus, + .btn-white:hover { + background: #fff !important; + outline: none + } + + .btn-outline-primary-blue { + border-color: #214570; + color: #214570 + } + + .btn-outline-primary-blue:hover { + background-color: #214570 !important; + border-color: #214570 !important; + color: #fff !important + } + + .btn-outline-primary-green { + border-color: #196956; + color: #196956 + } + + .btn-outline-primary-green:hover { + background-color: #196956 !important; + border-color: #196956 !important; + color: #fff !important + } + + .btn-primary-grey { + color: #128b75; + } + + .btn-primary-grey:hover { + color: #128b75 !important + } + + .btn-hover-green:hover { + background-color: #196956 !important; + color: #fff !important + } + + .btn-hover-green:hover i { + color: #fff !important + } + + .bg-mint-cream { + background-color: #f7f7f7 !important + } + + .btn-shadow { + box-shadow: 0 4px 8px 0 rgba(0, 106, 70, .3) + } + + .btn-outline-primary-lightgreen { + border-color: #01b477; + color: #01b477 + } + + .btn-outline-primary-lightgreen:hover { + background-color: #01b477 !important; + border-color: #01b477 !important; + color: #fff !important + } + + .btn-whitesmoke { + background-color: #f7f7f7; + border-color: #e9e9e9; + color: #767676 + } + + .btn-whitesmoke:hover { + background-color: #f2f2f2 !important; + border-color: #e9e9e9 !important; + color: #767676 !important + } + + .pagination { + align-items: center; + background: #f2f2f2; + border-radius: 50px; + justify-content: center; + padding: 2px 5px; + width: max-content + } + + .pagination.bg-light { + background-color: #fff + } + + .pagination .page-item { + align-self: baseline; + margin: 0 3px + } + + .pagination .page-item .named { + align-items: center; + background-color: #196956; + border: none; + border-radius: 50%; + box-shadow: 0 4px 8px 0 rgba(0, 106, 70, .3); + color: #fff; + display: flex; + height: 35px; + justify-content: center; + margin-block-start: 2px; + padding: 0; + transition: all .3s ease; + width: 35px + } + + .pagination .page-item .named:hover { + background-color: #018155 + } + + .pagination .page-item .named i { + font-size: 13px + } + + .pagination .page-item .page-link:not(.named) { + background-color: transparent; + border: none; + border-block-end: 3px solid transparent; + color: #003b4c; + font-size: 13px; + font-weight: 400 + } + + .pagination .page-item.active .page-link:not(.named) { + background-color: transparent; + border-color: transparent; + border-block-end: 3px solid #196956 + } + + .pagination .page-item.disabled .page-link { + background-color: #ccc; + box-shadow: 0 4px 8px 0 #ccc + } + + @media(max-width: 767px) { + .pagination { + flex-wrap: wrap; + justify-content: space-between + } + } + + .custom-tooltip+.custom-tooltip__text { + height: fit-content; + inset-block-end: 30px; + inset-inline-end: 0 + } + + .custom-tooltip:active+.custom-tooltip__text, + .custom-tooltip:focus+.custom-tooltip__text, + .custom-tooltip:hover+.custom-tooltip__text { + opacity: 1; + visibility: visible; + z-index: 9999 + } + + .card.white-card { + border: 0; + border-radius: .625rem; + box-shadow: 0 1px 10px 0 rgba(78, 78, 78, .18); + overflow: hidden + } + + .share-modal.popup-modal { + background: transparent + } + + .share-modal .modal-head { + align-items: center; + display: flex; + margin-block-end: 44px + } + + .share-modal .modal-head h6 { + color: #06b085; + font-size: 24px + } + + .share-modal .modal-head .modal-close { + color: #8d8d8d; + font-size: 20px; + margin-inline-end: 15px; + opacity: 1 + } + + .share-modal .seperator { + background: #d9d9d9; + height: 2px; + margin-block-end: 30px; + width: 100% + } + + .share-modal .link-label { + align-items: center; + display: flex; + margin-block-end: 15px + } + + .share-modal .link-label .text { + color: #1b4f5f; + font-size: 18px + } + + .share-modal .share-link { + align-items: center; + border: 2px solid #d9d9d9; + border-radius: 30px; + display: flex; + margin-block-end: 30px + } + + .share-modal .share-link input { + border: none; + color: #8d8d8d; + flex: 1; + font-size: 16px; + height: 28px; + margin: 0 5px; + outline: none + } + + .share-modal .share-link .btn-primary-green { + font-size: 20px; + padding: 7px 30px + } + + .share-modal .social-icons { + display: flex; + justify-content: center; + margin-block-end: 33px + } + + .share-modal .social-icons .btn { + border: 2px solid transparent; + border-radius: 50%; + padding: 5px; + transition: all .3s ease-in + } + + .share-modal .social-icons .btn>div { + align-items: center; + border-radius: 50%; + display: flex; + height: 64px; + justify-content: center; + transition: all .3s ease-in; + width: 64px + } + + .share-modal .social-icons .btn>div img { + max-height: 50%; + max-width: 100% + } + + .share-modal .social-icons .watsapp { + margin-inline-end: 17px + } + + .share-modal .social-icons .watsapp:hover { + border: 2px solid #0ec244 + } + + .share-modal .social-icons .watsapp:hover>div { + box-shadow: 0 0 3px #0ec244 + } + + .share-modal .social-icons .watsapp>div { + background: #0ec244 + } + + .share-modal .social-icons .twitter:hover { + border: 2px solid #2aa3ef + } + + .share-modal .social-icons .twitter:hover>div { + box-shadow: 0 0 3px #2aa3ef + } + + .share-modal .social-icons .twitter>div { + background: #2aa3ef + } + + .share-modal .social-icons .facebook:hover { + border: 2px solid #3d5a96 + } + + .share-modal .social-icons .facebook:hover>div { + box-shadow: 0 0 3px #3d5a96 + } + + .share-modal .social-icons .facebook>div { + background: #3d5a96 + } + + .card-filter--btn_show img { + inset-inline-start: 10px + } + + ::-webkit-input-placeholder { + color: #ccc + } + + :-ms-input-placeholder { + color: #ccc + } + + ::placeholder { + color: #ccc; + line-height: 2.5 + } + + * { + outline: none !important + } + + body, + html { + height: 100% + } + + body { + -webkit-animation: fadeIn .5s ease-in; + animation: fadeIn .5s ease-in; + display: flex; + flex-direction: column + } + + .h1, + .h2, + .h3, + .h4, + .h5, + .h6, + h1, + h2, + h3, + h4, + h5, + h6 { + font-family: Greta-AR-LT-Semibold + } + + strong { + font-family: Greta-AR-LT-Bold + } + + .list-inline { + padding-inline-start: 0 + } + + .text-primary { + --bs-text-opacity: 1; + color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important + } + + abbr[data-original-title], + abbr[title] { + text-decoration: none + } + + @media(max-width: 767px) { + .w-sm-100 { + width: 100% !important + } + + .size-sm-100 { + width: 100px + } + + :-ms-input-placeholder, + ::-webkit-input-placeholder, + ::placeholder { + color: #fff + } + } + + main { + background-image: url(../images/header-img.svg); + background-position: 0 0; + background-repeat: no-repeat; + background-size: 800px; + flex: 1 1 auto + } + + @media(min-width: 768px) { + main { + background-size: contain + } + } + + .form-select { + padding-block: .375rem; + padding-inline-end: 2.25rem; + padding-inline-start: .75rem + } + + [dir=rtl] .form-select { + background-position: left .75rem center + } + + .form-select[multiple], + .form-select[size]:not([size="1"]) { + padding-inline-end: .75rem + } + + .form-select-sm { + padding-inline-start: .5rem + } + + .form-select-lg { + padding-inline-start: 1rem + } + + .form-check { + padding-inline: 1.5em 0 + } + + .form-check .form-check-input { + float: left; + margin-inline-start: -1.5em + } + + [dir=rtl] .form-check .form-check-input { + float: right + } + + .form-check-reverse { + padding-inline-end: 1.5em; + padding-inline-start: 0; + text-align: end + } + + .form-check-reverse .form-check-input { + float: right; + margin-inline-end: -1.5em; + margin-inline-start: 0 + } + + [dir=rtl] .form-check-reverse .form-check-input { + float: left + } + + .form-switch { + padding-inline-start: 2.5em + } + + .form-switch .form-check-input { + background-position: 0; + margin-inline-start: -2.5em + } + + [dir=rtl] .form-switch .form-check-input { + background-position: 100% + } + + .form-switch.form-check-reverse { + padding-inline-end: 2.5em; + padding-inline-start: 0 + } + + .form-switch.form-check-reverse .form-check-input { + margin-inline-end: -2.5em; + margin-inline-start: 0 + } + + .form-check-inline { + margin-inline-end: 1rem + } + + .form-floating>label { + inset-inline-start: 0 + } + + .input-group-lg>.form-select, + .input-group-sm>.form-select { + padding-inline-end: 3rem + } + + .input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3), + .input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control, + .input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select, + .input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating) { + border-end-end-radius: 0; + border-start-end-radius: 0 + } + + .input-group>:not(:first-child):not(.dropdown-menu) { + margin-inline-start: -1px + } + + .input-group>.input-group-prepend>.btn, + .input-group>.input-group-prepend>.input-group-text { + border-end-end-radius: 0; + border-end-start-radius: 50rem; + border-start-end-radius: 0; + border-start-start-radius: 50rem + } + + .input-group>.input-group-append>.btn, + .input-group>.input-group-append>.input-group-text, + .input-group>.input-group-prepend:first-child>.btn:not(:first-child), + .input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child), + .input-group>.input-group-prepend:not(:first-child)>.btn, + .input-group>.input-group-prepend:not(:first-child)>.input-group-text { + border-end-end-radius: 50rem; + border-end-start-radius: 0; + border-start-end-radius: 50rem; + border-start-start-radius: 0 + } + + .input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle), + .input-group>.input-group-append:last-child>.input-group-text:not(:last-child) { + border-end-end-radius: 0; + border-end-start-radius: 50rem; + border-start-end-radius: 0; + border-start-start-radius: 50rem + } + + .input-group>.custom-select:not(:first-child), + .input-group>.form-control:not(:first-child) { + border-end-end-radius: .65rem; + border-end-start-radius: 0; + border-start-end-radius: .65rem; + border-start-start-radius: 0 + } + + .input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn, + .input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text { + border-end-end-radius: 0; + border-end-start-radius: 50rem; + border-start-end-radius: 0; + border-start-start-radius: 50rem + } + + .input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label:after, + .input-group:not(.has-validation)>.custom-select:not(:last-child), + .input-group:not(.has-validation)>.form-control:not(:last-child), + .input-group:not(.has-validation)>.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3), + .input-group:not(.has-validation)>.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control, + .input-group:not(.has-validation)>.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select, + .input-group:not(.has-validation)>.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating) { + border-end-end-radius: 0; + border-end-start-radius: var(--mp-result-border-radius) !important; + border-start-end-radius: 0; + border-start-start-radius: var(--mp-result-border-radius) !important + } + + .input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { + border-end-end-radius: var(--mp-result-border-radius) !important; + border-end-start-radius: 0; + border-start-end-radius: var(--mp-result-border-radius) !important; + border-start-start-radius: 0; + margin-inline-start: -1px + } + + .input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn, + .input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text { + border-end-end-radius: 0; + border-end-start-radius: 50rem; + border-start-end-radius: 0; + border-start-start-radius: 50rem + } + + .btn-gradient, + .btn-gradient.btn { + background: #196956; + background: linear-gradient(270deg, #196956 20%, #214570 105%); + color: #fff !important + } + + .btn-gradient.btn:focus, + .btn-gradient.btn:hover, + .btn-gradient:focus, + .btn-gradient:hover { + background: #196956; + background: linear-gradient(270deg, #196956 20%, #214570 105%); + color: #fff + } + + .input-group-prepend { + margin-inline: 0 -1px + } + + .input-group-append { + margin-inline: -1px 0 + } + + .custom-uploader { + align-items: center; + background-color: #f2f2f2; + border-radius: 7px; + color: #aaa; + display: flex; + height: 70px; + justify-content: center; + padding: 10px 0; + width: 100% + } + + .custom-uploader--icon { + font-size: 25px; + margin-inline-start: 10px + } + + [type=button], + [type=reset], + [type=submit], + button { + -webkit-appearance: auto + } + + input::-webkit-inner-spin-button, + input::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0 + } + + input[type=number] { + -moz-appearance: textfield + } + + [dir=rtl] select { + direction: rtl + } + + .hide-input { + clip: rect(0, 0, 0, 0); + pointer-events: none; + position: absolute + } + + a, + a:hover { + color: #196956; + text-decoration: none + } + + a:hover { + outline: none + } + + a:active, + a:focus { + outline: none; + text-decoration: none + } + + a.disabled { + cursor: default; + pointer-events: none + } + + .h1, + .h2, + .h3, + .h4, + .h5, + .h6, + h1, + h2, + h3, + h4, + h5, + h6 { + font-weight: 600 + } + + .wrapper { + flex: 1 0 auto + } + + .bg-with-small-snabel { + background: #214570; + background-image: url(../images/snabel-small.svg), linear-gradient(90deg, #196956 -50%, #214570); + background-repeat: no-repeat + } + + .gifts { + color: #003b4c + } + + .gifts .background-fixed { + background-attachment: fixed; + background-image: url(../images/banner.png); + background-repeat: no-repeat; + background-size: cover + } + + .gifts .background-fixed img { + visibility: hidden + } + + .gifts .bg-grey { + background-color: #f2f2f2 + } + + .gifts .title { + font-size: 16px + } + + .gifts .title.label { + font-size: 22px + } + + .gifts .card { + border: none; + border-radius: 10px; + padding: 40px 0 + } + + .gifts .card .number { + background: #003b4c; + border-radius: 50%; + box-shadow: 0 3px 20px 0 rgba(0, 0, 0, .16); + color: #fff; + font-size: 24px; + height: 70px; + padding: 16px 0; + text-align: center; + width: 70px + } + + .gifts .card img { + max-width: 100%; + width: 345px + } + + .gifts .card .description { + font-size: 16px; + max-width: 230px + } + + .gifts .card .title { + font-size: 28px; + margin-block-end: 32px + } + + .gifts .gift-action { + background: linear-gradient(90deg, #118b77, #01b276); + background-size: 400% 400%; + border-radius: 50px; + color: #fff; + font-size: 22px; + font-weight: 600; + margin: 23px auto 100px; + padding: 16px 80px + } + + .gifts h6.title { + font-size: 14px + } + + .animate-out { + opacity: 0; + -webkit-transition: opacity .5s; + transition: opacity .5s + } + + @keyframes fadeIn { + 0% { + opacity: 0 + } + + to { + opacity: 1 + } + } + + .project-details { + font-size: 20px + } + + .donation-status .card .title { + color: #214570 + } + + .donation-status .card h6 { + font-size: 24px; + font-weight: 600; + line-height: 30px + } + + .donation-status .round-checkbox .round-check { + inset-block-start: 0 + } + + .donation-status .round-checkbox .round-check:after { + inset-block-start: 6px; + inset-inline-end: 4px + } + + .donation-status .center { + align-items: center; + display: flex; + justify-content: space-between + } + + .donation-status input[type=number] { + border: 0; + outline: none + } + + .big-icon { + font-size: 70px; + inset-block-start: 24px; + inset-inline-end: 20px; + position: absolute + } + + .login-icon { + background-image: linear-gradient(45deg, #068571, #196956); + border-radius: 50%; + color: #fff; + font-size: 58px; + height: 109px; + line-height: 106px; + margin: auto; + width: 109px + } + + .login .card { + border: none; + border-radius: 15px + } + + .login .register-link { + font-size: 14px; + margin-block-start: 14px + } + + .login .elipse-bg { + background: url(../images/Ellipse51.svg); + background-position: 50%; + background-repeat: no-repeat; + background-size: contain + } + + .login .elipse-bg img { + padding: 17px + } + + .login a { + color: #214570; + margin-inline-start: 8px; + text-decoration: underline + } + + .login .resend, + .login h6 { + font-size: 12px + } + + .login .resend i { + font-size: 10px + } + + .login h3 { + font-size: 26px + } + + .login .field-validation-error { + width: 90% + } + + .login .input-validation-error { + background: #fff; + border: 1px solid #e58494 !important + } + + .login :not(.verification-inputs) input:focus { + border: 1.5px solid #06b085; + box-shadow: none; + outline: none + } + + .login input.valid { + background: #fff; + border: 1px solid #a4d171 !important + } + + .header_bread { + margin-block-start: 9rem + } + + .txt-dark-green { + color: #214570 + } + + .verification-inputs { + direction: ltr + } + + .verification-inputs input { + border: 1px solid #d9d9d9; + border-radius: 9px; + color: #868d96; + height: 38px; + margin-inline-start: 5px; + outline: none; + text-align: center; + transition: .3s; + width: 40px + } + + .verification-inputs input:focus { + box-shadow: 0 0 0 .2rem rgba(33, 69, 112, .25) + } + + .verification-inputs input::-webkit-inner-spin-button, + .verification-inputs input::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0 + } + + .verification-inputs input[type=number] { + -moz-appearance: textfield + } + + .card-gray { + background-color: #f7f7f7; + border: 0 + } + + .verification-page .resend, + .verification-page h6 { + font-size: 14px + } + + .verification-page .resend i { + font-size: 11px + } + + .verification-page h3 { + font-size: 26px + } + + .verification-page .btn { + font-weight: 400 + } + + .verification-page .input-validation-error { + background: #fff; + border: 1px solid #e58494 !important + } + + .verification-page input.valid { + background: #fff; + border: 1px solid #a4d171 !important + } + + .already-donate .removeFromCart { + background-color: #fff; + border: none; + color: #ccc; + cursor: pointer; + font-family: Greta-AR-LT-Regular; + font-size: 12px; + font-stretch: normal; + font-style: normal; + font-weight: 500; + height: 30px; + letter-spacing: normal; + line-height: 36px; + outline: none; + text-align: center; + width: 80px + } + + .already-donate .removeFromCart:focus, + .already-donate .removeFromCart:hover { + color: #214570; + outline: none + } + + .already-donate .addedToCart { + background-color: #ccc; + border-radius: 28px; + color: #fff; + height: 37px; + width: 100% + } + + .already-donate-subsidy .removeFromCart { + background-color: #fff; + border: none; + color: #ccc; + cursor: pointer; + font-family: Greta-AR-LT-Regular; + font-size: 12px; + font-stretch: normal; + font-style: normal; + font-weight: 500; + height: 30px; + letter-spacing: normal; + line-height: 36px; + outline: none; + text-align: center; + width: 80px + } + + .already-donate-subsidy .removeFromCart:focus, + .already-donate-subsidy .removeFromCart:hover { + color: #214570; + outline: none + } + + .already-donate-subsidy .addedToCart { + background-color: #ccc; + border-radius: 28px; + color: #fff; + height: 37px; + width: 100% + } + + .card h6 { + font-size: 17px; + font-weight: 600; + line-height: 30px + } + + .card .tilte { + max-width: 100% + } + + .card .price-details.error { + align-items: center; + border: 1px solid #dc3545; + border-radius: 20px; + color: #dc3545; + display: flex; + flex: 1; + font-size: 13px; + justify-content: space-between; + padding: 0 10px + } + + .card .share-icon-btn i { + background-color: #f2f2f2; + border-radius: 50%; + font-size: 18px; + height: 35px; + padding: 10px; + width: 35px + } + + .loader { + align-items: center; + display: flex; + justify-content: center + } + + .loader.card-1 { + height: 350px + } + + .loader.card-2 { + height: 300px + } + + .loader.card-3 { + height: 250px + } + + .field-validation-error { + color: #dc3545; + font-size: 12px + } + + .field-validation-error span { + display: inline-block; + margin-block-start: 5px + } + + .cart .price-details { + font-size: 15px !important; + position: relative + } + + .cart .price-details .field-validation-error { + inset-block-start: 95%; + position: absolute + } + + .cart.donations .card { + font-size: 15px + } + + .cart .card.total-amount { + border-radius: 23px + } + + .cart .card.total-amount h6 { + font-size: 20px; + font-weight: 700 + } + + .cart .card.total-amount .amount-unit { + font-size: 24px + } + + .cart .card.total-amount .amount-unit #cart_total { + font-size: 28px + } + + .cart .card.total-amount .separator-vertical { + background-color: #f2f2f2; + height: 1px; + margin: 30px 0; + width: 100% + } + + .cart .card.total-amount .btn-primary-blue { + font-size: 18px; + font-weight: 600; + margin-inline-start: auto; + padding: 8px 80px; + width: max-content + } + + .donut-chart { + height: 60px; + position: relative; + width: 60px + } + + .donut-chart svg { + background: #fff; + border-radius: 50%; + height: 100%; + transform: rotate(-90deg); + width: 100% + } + + .donut-chart circle { + fill: #fff; + stroke: #196956; + stroke-width: 32; + stroke-dasharray: 70 100; + transition: stroke-dasharray .5s ease + } + + .donut-chart .donut-center { + background: #fff; + border-radius: 50%; + color: #214570; + height: 80%; + inset-block-start: 50%; + inset-inline-end: 50%; + padding: 25% 0; + position: absolute; + text-align: center; + transform: translate(-50%, -50%); + width: 80% + } + + .all-projects { + color: #003b4c; + min-height: calc(100vh - 65px); + overflow-x: hidden + } + + .all-projects .card .donut-chart { + height: 60px; + position: relative; + width: 60px + } + + .all-projects .card .donut-chart svg { + background: #fff; + border-radius: 50%; + height: 100%; + transform: rotate(-90deg); + width: 100% + } + + .all-projects .card .donut-chart circle { + fill: #fff; + stroke: #196956; + stroke-width: 32; + stroke-dasharray: 70 100; + transition: stroke-dasharray .5s ease + } + + .all-projects .card .donut-chart .donut-center { + background: #fff; + border-radius: 50%; + color: #214570; + height: 80%; + inset-block-start: 50%; + inset-inline-end: 50%; + padding: 25% 0; + position: absolute; + text-align: center; + transform: translate(-50%, -50%); + width: 80% + } + + .all-projects .card .price-details { + align-items: center; + border: 1px solid #ccc; + border-radius: 20px; + color: #ccc; + display: flex; + flex: 1; + font-size: 13px; + justify-content: space-between; + padding: 0 10px + } + + .all-projects .card .price-details input { + border: none; + color: #003b4c; + font-size: 14px; + height: 30px; + outline: none; + width: 70% + } + + .all-projects .card .btn { + font-weight: inherit + } + + .all-projects .card h6 { + font-size: 20px; + font-weight: 600; + line-height: 30px + } + + .all-projects .filters { + background-color: #f7f7f7; + border-radius: 30px + } + + .all-projects .filters .has-menu>.btn, + .all-projects .filters>.btn { + font-family: Greta-AR-LT-Semibold; + font-size: 18px; + height: 44px; + margin-block: 8px; + padding: 8px 30px + } + + .all-projects .share-btn { + inset-block-start: 56px; + inset-inline-end: 5px; + position: absolute + } + + .all-projects .separator { + background-color: #ccc; + height: 1px; + width: 100% + } + + .all-projects .MaxValueBox { + background: rgba(13, 143, 117, .929); + border-radius: 8px; + inset-block-end: 59px; + width: 91% + } + + .all-projects .actions { + display: flex + } + + .all-projects .actions .btn-primary-blue { + flex: 1 + } + + .all-projects h6 { + font-size: 20px; + max-width: 100% !important; + width: 100% !important + } + + .all-projects .section-bg { + background: #f7f7f7; + border-radius: 52px; + height: 110%; + inset-block-start: -20px; + position: absolute; + width: 200%; + z-index: -1 + } + + .all-projects .section-bg.right-bg { + inset-inline-end: -100px + } + + .all-projects .section-bg.left-bg { + inset-inline-start: -100px + } + + .forijat-donut-chart { + height: 60px; + position: relative; + width: 60px + } + + .forijat-donut-chart svg { + background: #fff; + border-radius: 50%; + height: 100%; + transform: rotate(-90deg); + width: 100% + } + + .forijat-donut-chart circle { + fill: #fff; + stroke: #196956; + stroke-width: 32; + stroke-dasharray: 70 100; + transition: stroke-dasharray .5s ease + } + + .forijat-donut-chart .donut-center { + background: #fff; + border-radius: 50%; + color: #214570; + height: 80%; + inset-block-start: 50%; + inset-inline-end: 50%; + padding: 25% 0; + position: absolute; + text-align: center; + transform: translate(-50%, -50%); + width: 80% + } + + .card-filter .card-header { + background-color: #00726f; + background-image: url(../images/card-header-bg_repeat.svg); + background-position-x: left; + background-repeat: no-repeat; + background-size: contain; + border-radius: 16px 16px 0 0; + color: #fff; + font-family: Greta-AR-LT-Semibold; + font-size: 20px; + line-height: 55px; + position: relative + } + + .card-filter .card-header.bg-shorter { + background-position: left -165px center + } + + .card-filter .card-header label { + margin: 0; + padding-inline-start: 130px + } + + .card-filter .card-header-no-title { + background: #068571; + background: linear-gradient(270deg, #196956 30%, #214570 110%); + border-radius: 16px 16px 0 0; + color: #fff; + font-family: Greta-AR-LT-Semibold; + font-size: 20px; + min-height: 85px; + position: relative + } + + .card-filter .card-filter__filter-options { + background: #fff; + border-radius: 16px; + box-shadow: 0 8px 35px rgba(0, 0, 0, .16); + inset-block-start: 0; + inset-inline-start: 0; + position: absolute; + width: 100%; + z-index: 8 + } + + .card-header--logo, + .card-header--logo+img { + inset-block-start: 0; + position: absolute + } + + .card-header--logo+img { + inset-inline-end: -10px; + width: 280px + } + + .forijat-card { + border-radius: 20px + } + + .forijat-card .card-body .card-inner-top { + background: #196956; + background: linear-gradient(90deg, #196956, #214570); + border-radius: 20px 20px 0 0; + height: 202px + } + + .forijat-card .card-body .card-inner-top>img { + clip: rect(0, 500px, 500px, 125px); + inset-block-start: 0; + inset-inline-end: 0; + position: absolute; + transform: rotate(90deg) translate(12px, 144px) + } + + .forijat-card .card-body .card-inner-bottom { + background: #fff; + border-radius: 0 0 20px 20px; + position: relative + } + + .forijat-card .card-body .card-inner-bottom .forijat-case { + background: #fff; + border-radius: 8px 8px 0 0; + box-shadow: 0 2px 15px rgba(78, 78, 78, .1); + inset-block-start: -5px; + inset-inline-end: 50%; + padding: 25px; + position: absolute; + transform: translate(-50%, -50%); + width: 90%; + z-index: 5 + } + + .forijat-bill-number { + align-items: baseline; + background: #196956; + border-radius: 0 12px 0 28px; + color: #fff; + display: inline-flex; + justify-content: space-between; + min-width: 213px + } + + .forijat-bill-number label { + font-family: Greta-AR-LT-Semibold; + font-size: 13px; + padding: 10px 15px + } + + .forijat-bill-number div { + background: #00726f; + border-radius: 50%; + float: left; + margin-block-start: 5px; + margin-inline-end: 10px; + padding: 5px 9px + } + + [dir=ltr] .forijat-bill-number div { + float: right + } + + .forijat-bill-number img { + vertical-align: sub + } + + .card-filter--body { + background: #fff; + border-radius: 0 0 16px 16px; + box-shadow: 0 8px 35px rgba(0, 0, 0, .16); + inset-block-start: 0; + inset-inline-start: 0; + position: absolute; + width: 100%; + z-index: 1070 + } + + .card-filter--body .select2-container { + flex: 1; + margin-block-end: 20px; + margin-inline-end: 20px + } + + .furijat-label { + font-family: Greta-AR-LT-Semibold; + font-size: 28px + } + + .tanfeeth-bill { + inset-block-end: -15px; + inset-inline-end: -15px; + position: absolute + } + + .card-inner-top_patteren-left { + inset-block-start: 0; + inset-inline-end: 0; + position: absolute; + width: 100px + } + + .card-inner-top_patteren-right { + inset-block-start: 0; + inset-inline-start: 0; + position: absolute; + width: 150px + } + + .card-tanfeeth-details_header { + min-height: 85px + } + + .card-tanfeeth-details_patteren { + inset-block-start: 0; + inset-inline-start: 0; + position: absolute; + width: 170px + } + + .custom_theme_hr { + inset-block-start: 12px; + position: relative + } + + .custom_theme_title { + background: #fff; + margin: 0 auto; + position: relative; + text-align: center; + width: 165px + } + + .custom-payment-a { + height: 30px; + width: 55px + } + + .custom-payment-a-img { + width: 55px !important + } + + .custom_answer_span { + color: #214570; + font-size: 15px; + font-weight: 600 + } + + .custom_question { + font-weight: 600 + } + + .custom_question.accordion-button:not(.collapsed) { + padding-block-end: 5px !important + } + + .qa-wrapper { + border-block-end: 1px solid #e9ecef + } + + .qa-wrapper:last-child { + border-block-end: 0 + } + + .accordion-button:after { + display: none + } + + button.close { + outline: none !important + } + + button.collapsed .custom_question_icon { + transform: rotate(180deg) + } + + .custom_otp_radius { + border-radius: 15px + } + + .text-black-555 { + color: #545353 + } + + .project-img { + height: 155px + } + + .project-item-details { + border-radius: 12px; + position: relative + } + + .project-item-details .details-content { + background-color: #003b4c; + border-radius: 4px; + color: #fff; + font-size: 12px; + transition: all .3s ease + } + + .project-item-details .details-content h6 { + font-size: 12px + } + + .project-item-details .details-content .section-1 { + display: flex + } + + .project-item-details .details-content .section-1 .item { + align-items: center; + display: flex; + flex: .5; + flex-direction: column + } + + .project-item-details .details-content .section-1 .separator-vertical { + align-self: normal; + background-color: #fff; + width: 2px + } + + .project-item-details .details-content .section-2 { + background-color: hsla(0, 0%, 100%, .18); + border-end-end-radius: 12px; + border-end-start-radius: 12px; + color: #fff; + margin-block-start: -9px + } + + .project-item-details .project-img img { + border-radius: 12px 12px 0 0; + object-fit: cover + } + + .samiBold { + font-weight: 600 + } + + .price-details { + font-size: 11px !important + } + + .price-details span { + font-weight: 600 + } + + .price-details span.error { + color: #dc3545; + font-size: 13px; + font-weight: 400; + inset-block-end: -21px; + inset-inline-start: 0; + position: absolute + } + + .price-details .btn { + color: #196956 + } + + .price-details .btn small { + color: #214570 + } + + .price-details .btn:active, + .price-details .btn:focus { + border-color: #196956 !important; + border-width: 2px !important + } + + .MobileBtn { + font-size: 20px; + width: 100% + } + + .MaxValueBox { + background: rgba(13, 143, 117, .85); + color: #fff; + display: none; + font-size: 13px; + inset-block-end: 0; + padding: 8px; + position: absolute; + text-align: center; + width: 100% + } + + .donation-projects .share-btn { + inset-block-start: 56px; + inset-inline-end: 5px; + position: absolute + } + + .donation-projects .card { + border: none; + border-radius: 1rem; + font-weight: 100 + } + + .donation-projects .card .price-details { + align-items: center; + border: 1px solid #ccc; + border-radius: 20px; + color: #ccc; + display: flex; + flex: 50%; + font-size: 13px; + justify-content: space-between; + margin-inline-end: 5px; + padding: 0 10px + } + + .donation-projects .card .price-details input { + border: none; + color: #003b4c; + height: 20px; + outline: none; + width: 70% + } + + .donation-projects .card .btn { + font-weight: inherit + } + + .donation-projects .card .header { + align-items: center; + display: flex + } + + .donation-projects .card .header .title { + flex: 1; + margin: 0 + } + + .donation-projects .card .header .item-text { + font-size: 12px; + font-weight: 400; + margin-inline-end: 5px + } + + .donation-projects .card .header .item-order { + background-color: #ccc; + border-radius: 15px; + color: #fff; + font-size: 12px; + max-width: 70px; + min-height: 24px; + min-width: 40px; + padding: 3px 10px; + text-align: center + } + + .donation-projects .card .share-slider { + align-items: center; + display: flex; + margin-block-end: 10px + } + + .donation-projects .card .share-icon-btn { + color: #06b085; + font-size: 22px; + line-height: 0; + padding: 0 + } + + .donation-projects .card .rangeslider2 { + margin-block-start: 1px; + margin-inline-end: 17px + } + + .donation-projects .MaxValueBox { + background: rgba(13, 143, 117, .92); + border-radius: 8px; + inset-block-end: 59px; + width: 91% + } + + .card-Electricity circle { + stroke: #409da0 !important + } + + .card-Electricity .card-body .card-inner-top { + background: #214570; + background: linear-gradient(57deg, #409da0, #214570); + border-radius: 20px 20px 0 0; + height: 202px; + overflow: hidden; + padding: 40px; + position: relative + } + + .card-Electricity .card-body .card-inner-top .card-inner-top_patteren-right { + inset-block-start: -170px; + inset-inline-end: -64px; + inset-inline-start: auto; + position: absolute; + width: 230px + } + + .card-Electricity .card-body .card-inner-top .card-inner-top_patteren-left { + inset-block-start: -168px; + inset-inline-end: auto; + inset-inline-start: -54px; + position: absolute; + width: 250px + } + + .electracity-card-header-img { + inset-block-start: -150px; + inset-inline-start: -130px; + position: absolute + } + + .electracity-card-bg { + background: #214570 !important; + background: linear-gradient(-90deg, #409da0, #214570) !important + } + + .electracity-btn, + .electricity-bill { + background-color: #409da0 + } + + .electricity-bill { + color: #fff; + inset-block-end: -15px; + inset-inline-end: -20px + } + + .border-end-style-dashes { + border-inline-end-style: dashed !important + } + + .form-check-input { + border: 2px solid rgba(0, 0, 0, .38) + } + + .form-check-input:checked { + background-color: #196956; + border-color: #196956 + } + + .form-check-input:checked:focus { + border: none + } + + .form-check-input:focus { + border: 2px solid rgba(0, 0, 0, .58) + } + + .fix-dir { + direction: ltr; + display: inline-table + } + + .horizontal-menu.show { + min-width: 8rem; + padding: 7px 5px + } + + .horizontal-menu .dropdown-item { + background-color: hsla(0, 0%, 100%, .07); + margin: 2px 0; + padding: 7px + } + + .horizontal-menu .dropdown-item:focus, + .horizontal-menu .dropdown-item:hover { + background-color: #fff !important; + color: #196956 !important; + transition: all .8s + } + + .has-menu .dropdown-toggle.show:after { + transform: rotate(180deg) + } + + .has-menu .dropdown-item:focus { + background-color: #d9d9d9; + color: #214570 !important; + margin: 0 !important + } + + .tysaratTypeTitle:before { + background-color: #196956; + border-radius: 50%; + content: ""; + height: 10px; + inset-block-start: 7px; + inset-inline-start: -18px; + position: absolute; + width: 10px + } + + .ShowMaxValueBox { + display: block + } + + .withScroll { + direction: ltr + } + + .withScrollContent { + direction: rtl + } + + .ProhectDetailsSubBox { + position: relative + } + + .ProhectDetailsSubBox .MaxValueBox { + border-radius: 20px; + inset-block-end: -38px; + inset-inline-end: 10px; + width: 95% + } + + .showInMobile { + display: none + } + + .sliderContent { + margin-block-start: 30%; + transform: scale(1) + } + + .home-banner--top { + background-color: #01b477; + height: 20px + } + + .home-banner--bottom { + background: #214570; + background: linear-gradient(90deg, #196956 -50%, #214570) + } + + .no-projects-found { + align-items: center; + display: flex; + flex-direction: column; + justify-content: center + } + + .no-projects-found div { + font-weight: 600 + } + + .no-projects-found .btn { + font-size: 16px + } + + .without-icon .form-check-label:before { + border: 1px solid #bbb; + border-radius: 50% !important; + content: ""; + cursor: pointer; + display: block; + height: 17px; + inset-inline-end: -21px; + position: absolute; + width: 17px + } + + .without-icon .form-check-label:after { + background-position: 50%; + background-repeat: no-repeat; + background-size: 50% 50%; + border-radius: 50% !important; + content: ""; + cursor: pointer; + display: block; + height: 1rem; + inset-block-start: 0; + inset-inline: auto -21px; + position: absolute; + width: 1rem + } + + .without-icon .form-check-input:checked.form-check-label:before { + border: 0 !important + } + + .without-icon .form-check-input:checked.form-check-label:after { + background-color: #196956; + color: #fff; + content: "" !important; + font-family: Font Awesome\ 5 Free; + font-size: 11px; + font-weight: 700; + height: 17px; + inset-inline: auto -21px; + line-height: 21px; + position: absolute; + text-align: center; + transition: all .3s; + width: 17px + } + + .with-icon .form-check-label { + inset-inline-end: 1px; + position: absolute + } + + .with-icon .form-check-input:checked { + display: none + } + + .with-icon .form-check-input:checked~.form-check-label:after { + background-color: #196956; + border-radius: 50%; + color: #fff; + content: ""; + display: block; + font-family: Font Awesome\ 5 Free; + font-size: 11px; + font-weight: 700; + height: 17px; + line-height: 18px; + text-align: center; + width: 17px + } + + .account-thankyou { + font-size: 14px + } + + .account-thankyou h6 { + font-size: 15px; + font-weight: 600; + text-align: center + } + + .account-thankyou .btn-primary-blue { + font-size: 15px + } + + .img-holder { + display: flex; + justify-content: center; + width: 130px + } + + .img-holder.placeholder { + background: #214570; + height: 100% + } + + .cart-placeholder-image { + height: 60px; + inset-inline: -21px auto; + margin-block-start: 9px + } + + @keyframes gradient { + 0% { + background-position: 0 50% + } + + 50% { + background-position: 100% 50% + } + + to { + background-position: 0 50% + } + } + + .close-modal { + display: none !important + } + + img { + max-width: 100%; + outline: none + } + + .server-error-page .type { + font-size: 50px + } + + .server-error-page .message { + font-size: 13px; + font-weight: 600 + } + + .ghiras-page-bg { + inset-block-start: -200px; + inset-inline-end: -80px; + position: absolute; + width: 380px; + z-index: -1 + } + + .card-header-ghiras-bg { + inset-block-end: 0; + inset-inline-end: 60px; + position: absolute; + width: 200px + } + + .collapsed .rotate-on-collapse { + transform: rotate(180deg) + } + + .collapsed .ritual-description { + display: none + } + + .rotate-on-collapse { + transition: .3s + } + + .table-rounded td:first-child { + border-radius: 0 15px 15px 0 + } + + .table-rounded td:last-child { + border-radius: 15px 0 0 15px + } + + .table-rounded th:first-child { + border-radius: 0 15px 15px 0 + } + + .table-rounded th:last-child { + border-radius: 15px 0 0 15px + } + + .table-rounded tr { + border-block-end: 3px solid #f7f7f7 + } + + .table-rounded.table-rounded-10 td:last-child { + border-radius: 10px 0 0 10px + } + + .table-rounded.table-rounded-10 td:first-child { + border-radius: 0 10px 10px 0 + } + + .table-rounded.table-rounded-10 th:last-child { + border-radius: 10px 0 0 10px + } + + .table-rounded thead tr { + background-color: #0f6d68; + background-image: url(../images/adahi-patteren.svg); + background-position: bottom -15px left; + background-repeat: no-repeat + } + + .table-rounded.table-head-white thead tr { + background: #fff; + border-block-end: 7px solid #f7f7f7 + } + + .table-rounded.table-head-white thead th:nth-child(2) { + background-image: url(../images/Gheras-table-header-bg.svg); + background-position: bottom -5px left; + background-repeat: no-repeat + } + + .table-rounded.table-head-light-grey thead tr { + background: #e9ecef; + border-block-end: 7px solid #f7f7f7 + } + + .table-rounded.table-head-light-grey thead th:nth-child(2) { + background-image: url(../images/Gheras-table-header-bg.svg); + background-position: bottom -5px left; + background-repeat: no-repeat + } + + .table-rounded.table-head-light-green thead tr { + background: #ecf4f2 !important; + border-block-end: 7px solid #fff + } + + .table-rounded.table-light-rows tr { + border-block-end: 3px solid #fff + } + + .table-rounded table th { + background-color: #331763; + color: #fff + } + + .table-rounded tbody th { + font-weight: 400 + } + + .custom-tooltip { + cursor: pointer + } + + .custom-tooltip+.custom-tooltip__text { + background-color: #fff; + border: 1px solid rgba(0, 0, 0, .14); + border-radius: 10px; + font-size: 12px; + inset-block: 30px 0; + opacity: 0; + padding: 8px; + position: absolute; + text-align: start; + transition: .3s; + visibility: hidden; + width: fit-content; + z-index: -1 + } + + .custom-tooltip:active+.custom-tooltip__text, + .custom-tooltip:focus+.custom-tooltip__text, + .custom-tooltip:hover+.custom-tooltip__text { + opacity: 1; + visibility: visible; + z-index: 9999 + } + + .adahi-page .accordion .card { + border-radius: 10px !important + } + + .adahi-page .accordion .card:first-of-type { + border-block-end: 1px solid rgba(0, 0, 0, .12) + } + + .adahi-page .accordion .card-header { + background-color: #0c746a; + background-image: url(../images/adahi-patteren.svg); + background-position: bottom -8px left 40px; + background-repeat: no-repeat + } + + .adahi-page .list-group-item { + padding: .55rem 1rem + } + + .adahi-increase-decrease { + width: 140px + } + + .adahi-increase-decrease .btn { + align-items: center !important; + aspect-ratio: 1; + background-color: #196956; + border: none !important; + border-radius: 50% !important; + display: -ms-flexbox !important; + display: flex !important; + height: 20px; + justify-content: center !important; + padding: 0 !important + } + + .adahi-increase-decrease input { + border: none !important; + height: 20px + } + + .adahi-total-on-mobile { + inset-block-end: 0; + position: fixed; + width: 100%; + z-index: 999 + } + + .adahi-total-on-mobile .card { + border-radius: 15px 15px 0 0 + } + + .adahi-status-number { + background-color: #fff; + border-radius: 50%; + color: red; + font-weight: 700; + height: 15px; + margin-inline-start: 5px; + padding-block-start: 2px; + width: 15px + } + + .badge-primary-blue .adahi-status-number { + color: #214570 + } + + .badge-primary-green .adahi-status-number { + color: #0f6d68 + } + + .ritual-description { + font-size: 11px + } + + .nav-zakat-icons { + inset-inline-start: 12px; + position: absolute + } + + .zakah-summary-on-mobile { + inset-block-end: 0; + inset-inline-start: 0; + position: fixed; + width: 100%; + z-index: 999 + } + + .zakah-summary-on-mobile>div { + border-radius: 10px 10px 0 0; + box-shadow: 0 -4px 10px hsla(0, 0%, 55%, .45) + } + + .toast-container { + inset-block-start: 9rem; + position: fixed; + z-index: 999 + } + + .toast-container.toast-container-left { + inset-inline-end: 1rem + } + + .toast-container.toast-container-right { + inset-inline-start: 1rem + } + + .toast { + border: 1px solid #d9d9d9; + border-radius: 15px + } + + .toast.toast-success { + background-color: #d4edda; + border-color: #c3e6cb; + color: #155724 + } + + .toast.toast-success .toast-header { + background-color: #b7dbc0; + color: #155724 + } + + .toast.toast-danger { + background-color: #f8d7da; + border-color: #f5c6cb; + color: #721c24 + } + + .toast.toast-danger .toast-header { + background-color: #e6b7bb; + color: #721c24 + } + + .toast.toast-info { + background-color: #d1ecf1; + border: 1px solid #bee5eb; + color: #0c5460 + } + + .toast.toast-info .toast-header { + background-color: #abdbe4; + color: #0c5460 + } + + .toast.toast-warning { + background-color: #fff3cd; + border-color: #ffeeba; + color: #856404 + } + + .toast.toast-warning .toast-header { + background-color: #f8e8b5; + color: #856404 + } + + .card-shadow { + border: none; + box-shadow: 0 2px 15px 0 rgb(78, 78, 78 / 10%); + } + + .tiptop { + animation: main .3s forwards; + background: rgba(27, 79, 95, .8); + border-radius: 5px; + color: #fff; + font-size: 12px; + max-width: 300px; + padding: 5px 20px; + position: absolute; + transform: scaleX(.5); + z-index: 1 + } + + @keyframes main { + 0% { + transform: scaleX(.5) + } + + to { + transform: scaleX(1) + } + } + + .card-details-link { + color: unset; + max-width: 80% + } + + .card-details-link:focus, + .card-details-link:hover { + color: unset + } + + .clickable-wrapper { + align-items: center; + cursor: pointer; + display: flex; + height: 100%; + justify-content: center; + width: 100% + } + + .center-img-fluid { + height: 100%; + inset-inline-end: 50%; + position: absolute; + transform: translateX(-50%); + width: 100% + } + + .custom-checkbox-square .custom-control-input { + height: 1.25rem; + inset-inline-end: 0; + opacity: 0; + position: absolute; + width: 1rem; + z-index: -1 + } + + .custom-checkbox-square .custom-control-input:checked.custom-control-label:before { + background-color: #06b085; + border-color: #06b085 !important; + color: #fff + } + + .custom-checkbox-square .custom-control-input:checked.custom-control-label:after { + border: solid #fff; + border-width: 0 2px 2px 0; + height: 10px; + inset-inline-start: -20.3px; + transform: rotate(45deg); + width: 6px + } + + .custom-checkbox-square .custom-control-label { + color: #6c757d; + cursor: pointer; + display: inline-block; + font-family: Greta-AR-LT-Semibold; + margin-block-end: 0; + position: relative; + vertical-align: top + } + + .custom-checkbox-square .custom-control-label:before { + border: 2px solid #929292 !important; + border-radius: 2px; + height: 14px; + inset-block-start: 4px; + width: 14px + } + + .custom-checkbox-square .custom-control-label:before, + .custom-checkbox-square .custom-file-label { + transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out + } + + .custom-checkbox-square .custom-control-label:after { + inset-block-start: 4px + } + + .custom-select { + transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out + } + + .gift-checkbox-wrapper { + display: flex; + justify-content: space-between; + width: 100% + } + + .gift-checkbox-wrapper.checked .gift-icon g path { + fill: #6ea2dc + } + + .gift-icon { + margin-block-start: -9px + } + + .Payment-details-page .payment-info .gift-box { + background-color: rgba(64, 157, 160, .1) + } + + .Payment-details-page .payment-info .gift-box>label { + color: #409da0 + } + + .Payment-details-page .payment-info .gift-box>img { + vertical-align: text-top; + width: 15px + } + + .Payment-details-page .payment-info .card-header { + border-radius: 20px 20px 0 0; + height: 110px + } + + .Payment-details-page .payment-info .card-header img { + clip: rect(55px, 500px, 165px, 0); + inset-block-start: -55px; + inset-inline-end: -5px; + position: absolute + } + + .Payment-details-page .payment-info .cart-items { + list-style: none; + padding: 15px 0 0 + } + + .Payment-details-page .payment-info .cart-items li { + display: flex; + font-size: 18px; + justify-content: space-between + } + + .Payment-details-page .payment-info .cart-items li .item-amount { + font-size: 22px + } + + .Payment-details-page .payment-info .cart-items li:not(:last-of-type) { + margin-block-end: 15px + } + + .Payment-details-page .amount-details .title { + font-size: 24px; + margin-block-end: 42px + } + + .Payment-details-page .amount-details .amount { + font-size: 32px; + margin: 40px 0 30px + } + + .Payment-details-page .amount-details .user-details { + font-size: 22px; + margin: 30px 0 43px + } + + .Payment-details-page .amount-details .user-details>div:first-of-type { + margin-block-end: 40px + } + + .Payment-details-page .amount-details .sep-4 { + margin-block-end: 22px + } + + .Payment-details-page .apple-pay { + border-radius: 4px; + padding: 22px 30px; + width: 100% + } + + .Payment-details-page .card-icon { + align-items: center; + background: #e9ecef; + border-end-end-radius: 4px; + border-inline-start: 2px solid #d1d1d1; + border-radius: .65rem 0 0 .65rem !important; + border-start-end-radius: 4px; + display: flex; + height: 35px; + inset-block-start: .9px; + inset-inline-end: 0; + justify-content: center; + position: absolute + } + + .Payment-details-page .card-icon-image { + margin: 9% 8px; + max-height: 70%; + max-width: 30px + } + + .Payment-details-page .line-with-words { + margin-block-end: 25px; + margin-block-start: 15px + } + + .Payment-details-page .line-with-words .title { + font-family: Greta-AR-LT-Semibold; + font-size: 16px; + font-weight: 600 + } + + .Payment-details-page .line-with-words.page-title .title { + font-size: 20px; + font-weight: 600 + } + + .Payment-details-page .user-details .name { + margin-inline-start: 30px + } + + .Payment-details-page .payment .card-holder-name { + text-transform: uppercase + } + + .view-all-link { + position: relative + } + + .gheras .sub-title { + color: #214570; + font-size: 16px; + letter-spacing: 0; + line-height: normal; + margin: 0 auto; + margin-block-end: 125px; + max-width: 745px; + text-align: center + } + + .gheras .steps { + display: flex; + margin: 0 -15px; + margin-block-end: 160px + } + + .gheras .steps .count { + background: #214570; + border-radius: 50%; + color: #fff; + font-size: 40px; + height: 70px; + line-height: 70px; + margin-block-end: 48px; + overflow: hidden; + text-align: center; + width: 70px + } + + .gheras .steps h4 { + color: #196956; + line-height: normal; + margin-block-end: 14px + } + + .gheras .steps p { + color: #214570; + font-size: 18px; + line-height: normal + } + + .gheras .steps:last-of-type { + margin-block-end: 70px + } + + .gheras .line-with-words .title { + max-width: 100%; + min-width: auto; + padding: 0 + } + + .with--share .share-help { + inset-block-start: 29px; + inset-inline-end: 13px; + position: absolute + } + + .with--share .text-dark-green span.title { + max-width: 80% + } + + .copy--wrapper { + background: #eee; + border-radius: 7px; + height: 44px; + margin: 0 0 30px; + padding: 0 15px; + position: relative; + width: 100% + } + + .copy--wrapper button { + background: none; + border: none; + color: #196956; + cursor: pointer; + font-size: 20px; + inset-block: 0; + inset-inline-end: 15px; + margin: auto; + position: absolute + } + + .copy--wrapper button:focus { + outline: none + } + + .copy--wrapper input { + background: transparent; + border: 1px solid #dfe1e5; + border-radius: 8px; + color: #214570; + font-size: 14px; + line-height: 40px; + outline: 0; + padding-inline: .75rem; + width: 90% + } + + .user-control-options-wrapper { + align-items: center; + display: flex + } + + .replaced-link { + cursor: pointer; + outline: none !important + } + + .arabic-list-style { + list-style: none; + position: relative + } + + .arabic-list-style>li:before { + direction: ltr; + display: inline-block; + inset-inline-start: 0; + position: absolute; + text-align: start; + width: 25px + } + + .arabic-list-style>li:first-child:before { + content: ".Ø£" + } + + .arabic-list-style>li:nth-child(2):before { + content: ".ب" + } + + .arabic-list-style>li:nth-child(3):before { + content: ".ج" + } + + .arabic-list-style>li:nth-child(4):before { + content: ".د" + } + + .arabic-list-style>li:nth-child(5):before { + content: ".Ù‡" + } + + .arabic-list-style>li:nth-child(6):before { + content: ".Ùˆ" + } + + .arabic-list-style>li:nth-child(7):before { + content: ".ز" + } + + .arabic-list-style>li:nth-child(8):before { + content: ".Ø­" + } + + .arabic-list-style>li:nth-child(9):before { + content: ".Ø·" + } + + .arabic-list-style>li:nth-child(10):before { + content: ".Ù‰" + } + + .payment-details .creditCardForm .heading { + margin-block-end: 7px + } + + .payment-details .creditCardForm .heading h4 { + color: #31616e; + font-size: 22px; + margin: 0 + } + + .payment-details .creditCardForm .sep-1 { + margin-block-end: 47px + } + + .payment-details .creditCardForm label { + color: #214570; + font-size: 16px; + font-weight: 600; + margin-block-start: 12px + } + + .payment-details .creditCardForm .cvv { + width: 120px + } + + .payment-details .creditCardForm .already-member { + color: #b8b8b8; + font-size: 13px; + margin-block-end: 20px + } + + .payment-details .creditCardForm .expiry-dates { + max-width: 40%; + width: 170px + } + + .payment-details .creditCardForm .expiry-dates .card-dates { + display: flex + } + + .payment-details .creditCardForm .expiry-dates .card-dates #expYear { + border-end-start-radius: 0; + border-start-start-radius: 0; + margin-inline-start: -2px; + width: 50% + } + + .payment-details .creditCardForm .expiry-dates .card-dates #expMonth { + border-end-end-radius: 0; + border-start-end-radius: 0; + width: 50% + } + + .payment-details .creditCardForm .custom-checkbox-round .custom-control-label { + margin-block-end: 15px + } + + .payment-details .payment { + margin-block-end: 25px + } + + .payment-details .form-group { + margin-block-end: 22px; + position: relative + } + + .payment-details .form-group .error { + color: #e0394a; + font-size: 14px + } + + .payment-details .form-group input.error, + .payment-details .form-group select.error { + color: #495057 + } + + .creditCardForm label { + color: #214570; + font-size: 14px; + font-weight: 600; + margin-block-start: 12px + } + + .creditCardForm .cvv { + width: 120px + } + + .creditCardForm .already-member { + color: #b8b8b8; + font-size: 13px; + margin-block-end: 20px + } + + .creditCardForm .expiry-dates { + max-width: 50%; + width: 200px + } + + .creditCardForm .expiry-dates .card-dates { + display: flex + } + + .creditCardForm .expiry-dates .card-dates #expYear { + border-end-start-radius: 0; + border-start-start-radius: 0; + margin-inline-start: -2px; + width: 50% + } + + .creditCardForm .expiry-dates .card-dates #expMonth { + border-end-end-radius: 0; + border-start-end-radius: 0; + width: 50% + } + + .creditCardForm .sign-in-options { + color: #aaa; + font-size: 11px; + font-weight: 700; + margin: 0 0 10px + } + + .creditCardForm .sign-in-options a { + text-decoration: underline + } + + .creditCardForm .custom-checkbox-round .custom-control-label { + margin-block-end: 15px + } + + .creditCardForm .payment-info-box input.error~span~span .amount-display { + inset-block-start: -300px; + position: fixed; + z-index: -1 + } + + &.fixed-side-menu { + inset-block-start: 250px; + inset-inline-start: 0; + line-height: 16px; + max-width: 310px; + position: fixed; + z-index: 9989 + } + + &.fixed-side-menu.has-focus .title { + width: 270px + } + + &.fixed-side-menu.has-focus .icon { + border-end-end-radius: 0 + } + + &.fixed-side-menu.has-focus .options { + display: block + } + + &.fixed-side-menu.has-focus .hide-hovered { + display: none + } + + &.fixed-side-menu.has-focus .hovered { + border-radius: 20px; + display: unset; + font-size: 12px + } + + &.fixed-side-menu.varient-2.has-focus .icon { + border-end-end-radius: 0; + text-align: end; + width: 310px + } + + &.fixed-side-menu.varient-2.has-focus .hovered { + color: #fff !important; + margin-inline-start: auto; + padding: 0 20px + } + + &.fixed-side-menu.varient-2.has-focus .hovered span { + color: #fff !important; + display: inline-block; + margin-block-start: 5px + } + + &.fixed-side-menu.varient-2 .title { + display: none + } + + &.fixed-side-menu.varient-2 .icon { + background: #21446f; + border-end-end-radius: 20px; + border-start-end-radius: 20px; + height: 36px; + transition: all .1s linear + } + + &.fixed-side-menu .card-icon { + align-items: center; + background: #e9ecef; + border-inline-start: 2px solid #d1d1d1; + border-radius: .65rem 0 0 .65rem; + display: flex; + height: 36.6px; + inset-block-start: .9px; + inset-inline-end: 1px; + justify-content: center; + position: absolute + } + + &.fixed-side-menu .card-icon-image { + margin: 9% 8px; + max-height: 70%; + max-width: 30px + } + + &.fixed-side-menu form input.error { + border: 1px solid #f25e09 + } + + &.fixed-side-menu form span.error { + display: none !important + } + + &.fixed-side-menu .error-box { + position: relative + } + + &.fixed-side-menu .error-box input.amount.error~.error-border { + visibility: visible + } + + &.fixed-side-menu .error-border { + border: 1px solid #f25e09; + border-radius: 20px; + content: ""; + inset: -1px; + position: absolute; + visibility: hidden + } + + &.fixed-side-menu .amount { + z-index: 1 + } + + &.fixed-side-menu .apple-pay { + margin-block-end: 10px + } + + &.fixed-side-menu .price-box { + border-block-end: 1px dotted #ccc; + margin-block-end: 8px; + padding-block-end: 12px + } + + &.fixed-side-menu .payment-info-box { + background: #068571; + background: linear-gradient(270deg, #196956 0, #214570 110%); + border-radius: 9px; + color: #fff; + font-size: 12px; + padding: 10px 15px + } + + &.fixed-side-menu .payment-info-box .edit-amount-btn { + color: inherit; + font-size: inherit; + padding: 0 + } + + &.fixed-side-menu .payment-info-box .amount-display { + font-size: 24px + } + + &.fixed-side-menu .clickable { + cursor: pointer + } + + &.fixed-side-menu .title { + background-color: #fff; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, .29); + color: #214570; + font-size: 14px; + font-weight: 500; + padding: 10px 15px; + text-align: start; + transition: all .3s ease; + width: 110px + } + + &.fixed-side-menu .icon { + background: #196956; + border-end-end-radius: 50%; + border-end-start-radius: 0; + border-start-end-radius: 50%; + border-start-start-radius: 0; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, .29); + padding: 0; + text-align: center; + width: 40px + } + + &.fixed-side-menu .icon, + &.fixed-side-menu .icon .round { + align-items: center; + display: flex; + justify-content: center + } + + &.fixed-side-menu .icon .round { + background: #fff; + border-radius: 25px; + color: #196956; + font-size: 30px; + height: 16px; + line-height: 1.4; + margin: auto; + padding: 11px; + width: 16px + } + + &.fixed-side-menu .icon .close-icon { + color: #fff; + font-size: 14px + } + + &.fixed-side-menu .options { + background-color: #fff; + border-end-end-radius: 10px; + border-end-start-radius: 10px; + box-shadow: 0 5px 6px 0 rgba(0, 0, 0, .15); + display: none; + inset-block-start: 36px; + inset-inline-start: 0; + position: absolute; + transition: all .2s ease-in-out .3s; + width: 100% + } + + &.fixed-side-menu .options .tab-content .price-details { + align-items: center; + border: 1px solid #dfe1e5; + border-radius: 6px; + color: #ccc; + display: flex; + flex: 1; + font-size: 13px; + justify-content: space-between; + padding: 6px 10px + } + + &.fixed-side-menu .options .tab-content .price-details input { + border: none; + color: #214570; + height: 20px; + outline: none; + width: 70% + } + + &.fixed-side-menu .options .tab-content>.active { + max-height: 55vh; + opacity: 1; + overflow: auto + } + + &.fixed-side-menu .options .nav-tabs li { + border-inline-end: 1px solid #ccc; + color: #196956; + cursor: pointer; + flex: 1; + font-size: 13px; + font-weight: 700; + margin-block-end: 4px; + padding: 9px; + text-align: center + } + + &.fixed-side-menu .options .nav-tabs li:last-child { + border-inline-end-width: 0 + } + + &.fixed-side-menu .options .nav-tabs li.active { + background-color: #196956; + color: #fff; + margin-block-end: 0 + } + + &.fixed-side-menu .options .nav-tabs li:focus { + outline: none + } + + &.fixed-side-menu .hovered { + display: none + } + + &.fixed-side-menu .text-desc { + color: #063f50; + display: inline-block; + font-size: 12px; + font-weight: 500; + margin-block-end: 16px; + margin-block-start: 10px + } + + &.fixed-side-menu .payment .card-holder-name { + text-transform: uppercase + } + + &.fixed-side-menu .field-validation-error span { + color: #e0394a; + font-weight: 500; + margin-block-end: 10px + } + + .card-type { + position: relative + } + + .donations .card { + border: none; + color: #003b4c; + font-size: 13px + } + + .donations .card .price-details { + align-items: center; + border: 1px solid #ccc; + border-radius: 7px; + color: #196956; + display: flex; + font-size: 13px; + padding: 2px 10px + } + + .donations .card .price-details input { + border: none; + height: 25px; + outline: none; + padding-block-start: 0; + width: 150px + } + + .donations .card .bg-gradient-green { + background: #068571; + background: linear-gradient(90deg, #068571, #196956) + } + + .donations .card .border-rounded-2 { + border-radius: 5px + } + + .donations .gift .title { + font-size: 14px + } + + .donations .gift .amount { + font-size: 18px + } + + .donations .gift i { + color: #cecece; + font-size: 40px + } + + .donations .gift .center { + align-items: center; + display: flex; + justify-content: space-between + } + + .donations .gift input { + border: 0; + color: #196956; + line-height: 30px; + outline: 0; + width: 100% + } + + .donations .gift input:focus { + border-color: #196956 !important + } + + .donations .separator { + background-color: #ccc; + height: 1px; + opacity: .5; + width: 100% + } + + .donations .items .card .title { + background: #196956; + color: #fff; + font-size: 12px; + font-weight: 100; + height: 26px; + inset-block-end: 0; + inset-inline-end: 0; + inset-inline-start: 0; + padding: 0 10px; + position: absolute; + text-align: center + } + + .donations .items .card i { + color: #cecece + } + + .donations .Payment-details-page .apple-pay { + margin: 10px auto 0; + padding: 18px 0; + width: 190px + } + + .nav-tabs { + border-block-end: 1.5px solid #dee2e6 + } + + .donation-links .title { + color: #214570; + font-size: 24px; + margin-block-end: 1rem; + margin-inline-start: .8rem + } + + .donation-links .card { + border-radius: 16px + } + + .donation-links .card .label { + font-size: 20px; + text-align: center + } + + .donation-links .card .value { + font-size: 28px + } + + .donation-links .img-shadow { + box-shadow: -5px 10px 20px 0 rgba(0, 0, 0, .15) + } + + .donation-links .message-box { + font-size: 14px + } + + .donation-links .avatar-wrapper .avatar-icon { + background: #fff; + height: 50px; + width: 50px + } + + .donation-links .avatar-wrapper .avatar-icon img { + margin: auto; + width: 60% + } + + .shared-links .title { + color: #214570; + font-size: 24px; + margin-block-end: 1rem; + margin-inline-start: .8rem + } + + .shared-links .card .value { + font-size: 22px; + width: 100px + } + + .shared-links .card .label { + font-size: 16px + } + + .shared-links .avatar-icon { + background: #fff; + height: 50px; + width: 50px + } + + .shared-links .avatar-icon img { + margin: auto; + width: 60% + } + + .shared-links .img-shadow { + box-shadow: -5px 10px 20px 0 rgba(0, 0, 0, .15) + } + + .shared-links .message-box { + font-size: 14px + } + + .payment { + color: #003b4c + } + + .payment .separator { + background-color: #ccc; + height: 1px; + width: 100% + } + + .payment .user-details { + font-size: 14px + } + + .payment .amount { + font-size: 20px + } + + .payment .card-details { + font-size: 13px + } + + .payment .card-details .card-images .img-container { + border: 2px solid transparent; + border-radius: 5px + } + + .payment .card-details .card-images .active { + border: 2px solid #196956 + } + + .payment .card-details .card-info input { + border: 0; + color: #196956; + font-weight: 100; + line-height: 30px; + outline: 0; + width: 100% + } + + .payment .card-details .card-info input:focus { + border-color: #196956 !important + } + + .payment h6.title { + font-size: 14px + } + + .center-items-vertically { + align-items: center; + display: flex + } + + #cart { + border-inline-start: 1px solid rgba(0, 0, 0, .12); + position: relative; + text-align: center + } + + #cart .badge { + background: #ffab00; + border: 2px solid #fff; + border-radius: 50%; + color: #fff; + font-family: Greta-AR-LT-Semibold; + font-size: 12px; + height: 18px; + inset-block-start: -5px; + inset-inline-start: 10px; + min-width: 18px; + padding: 2px; + position: absolute + } + + #cart_total { + font-size: 22px + } + + .cursor-pointer { + cursor: pointer !important + } + + .toggle-hide { + inset-block-start: -300px; + position: fixed; + z-index: -1 + } + + .line-with-words { + align-items: center; + display: flex + } + + .line-with-words .line { + background: #ccc; + height: 1px; + width: 100% + } + + .line-with-words .title { + min-width: max-content; + padding: 0 10px + } + + .text-copied-msg { + background-color: #f7f7f7; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 10px; + font-size: 12px; + inset-block-end: 110%; + inset-inline-end: -20px; + padding: 10px; + position: absolute + } + + .about-page { + overflow: hidden + } + + .about-page>section { + padding: 100px 0 40px; + position: relative + } + + .about-page>section:first-child { + padding: 80px 20px + } + + .about-page>section.bg-grey, + .about-page>section.bg-grey .section-title span { + background-color: #f7f7f7 + } + + .about-page>section .section-title { + font-size: 24px; + margin-block-end: 30px; + position: relative; + text-align: center; + z-index: 1 + } + + .about-page>section .section-title span { + background-color: #fff; + color: #214570; + display: inline-block; + padding: 0 10px + } + + .about-page>section .section-title:before { + background-color: #b6b6b6; + content: ""; + height: 1px; + inset-block-start: 15px; + inset-inline-start: 0; + position: absolute; + width: 100%; + z-index: -1 + } + + .about-main { + background-image: url(../images/white-plant-vector-xs.svg), url(../images/green-overlay.svg), url(../images/plant-bg.jpg); + background-position: -165px 0, 0 0, -475px 0; + background-repeat: no-repeat; + background-size: contain, cover, cover + } + + .about-main h1 { + font-size: 2rem + } + + .about-main p { + font-size: 16px + } + + .about-main .about-main-logos img { + height: 55px + } + + .about-vision { + background-image: url(../images/bg.svg); + background-position: right -120px bottom; + background-repeat: no-repeat + } + + .about-vision .about-vision-icon { + display: inline-block; + position: relative + } + + .about-vision .about-vision-icon .dashed-circle { + inset-block-start: -4px; + inset-inline-start: -4px; + max-width: none; + position: absolute; + width: 83px + } + + .about-vision .about-vision-icon .vector-icon { + width: 75px + } + + .about-vision .about-vision-icon+p { + margin: 25px 0; + position: relative; + z-index: 1 + } + + .about-vision .row .col-12 .about-vision-icon .dashed-line, + .about-vision .row .col-12 .about-vision-icon .dashed-line-2 { + inset-inline-end: 50%; + position: absolute; + transform: translate(-50%, -50%); + width: 1.5px + } + + .about-vision .row .col-12:first-child .about-vision-icon .dashed-line { + inset-block-end: -37px + } + + .about-vision .row .col-12:nth-child(2) .about-vision-icon .dashed-line-2 { + inset-block-end: -50px + } + + .about-vision .row .col-12:nth-child(2) .about-vision-icon .dashed-line { + inset-block-start: -10px + } + + .about-vision .row .col-12:nth-child(3) .about-vision-icon .dashed-line { + inset-block-start: -9px + } + + .about-vision .row .col-12:nth-child(3) .about-vision-icon+p { + margin-block-start: 0 + } + + .about-goals { + z-index: 1 + } + + .about-goals:after { + background-image: url(../images/bg.svg); + background-repeat: no-repeat; + content: ""; + height: 495px; + inset-block-start: 150px; + inset-inline-end: -60px; + position: absolute; + width: 200px; + z-index: -1 + } + + .about-goals-box { + background-image: url(../images/icon-about-goals.svg); + background-position: right -5px; + background-repeat: no-repeat; + padding-inline-start: 23px + } + + .about-goals-box h5 { + color: #123d64; + font-size: 18px + } + + .about-goals-box p { + font-size: 14px + } + + .about-features:after { + background-image: url(../images/bg.svg); + background-position: right -300px bottom 0; + background-repeat: no-repeat; + content: ""; + height: 100%; + inset-block-end: -60px; + inset-inline-start: 0; + position: absolute; + width: 100%; + z-index: 1 + } + + .about-features .card { + box-shadow: 0 2px 15px hsla(0, 0%, 70%, .2); + z-index: 2 + } + + .about-features .card .feature-title { + background-image: url(../images/icon-about-feature.svg); + background-position: 45px -5px; + background-repeat: no-repeat; + color: #068571; + font-size: 16px; + font-weight: 700; + margin-block-start: 30px; + min-width: 85px; + padding-block-end: 20px; + position: relative; + text-align: center + } + + .about-features .card .feature-title:before { + background-color: hsla(0, 0%, 94%, .54); + border-radius: 50%; + content: ""; + height: 60px; + inset-block-start: -22px; + inset-inline-start: 11px; + position: absolute; + width: 60px; + z-index: -1 + } + + .about-features .card .feature-text { + align-self: center; + color: #707070; + font-size: 14px; + margin-block-end: 0 + } + + .about-donation-key { + margin-block-end: 50px; + text-align: center + } + + .about-donation-key label { + color: #4e4e4e; + font-size: 14px + } + + .donation-key-circle { + background-color: #fff; + border-radius: 50%; + box-shadow: 0 3px 6px hsla(0, 0%, 72%, .16); + display: -ms-flexbox; + display: flex; + height: 60px; + margin: 0 auto 8px; + padding: 10px; + width: 60px + } + + .donation-key-circle img { + width: 40px + } + + .user-sidebar { + display: flex; + flex-direction: column; + width: 100% + } + + .user-sidebar .card+.card { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important + } + + .user-sidebar--menu { + list-style: none; + margin: 0; + padding: 0 + } + + .user-sidebar--menu__option { + align-items: center; + color: #707070; + display: flex; + padding: .8rem 1.25rem; + transition: .3s + } + + .user-sidebar--menu__option.menu-option-active, + .user-sidebar--menu__option:hover { + background-color: #f2f2f2; + box-shadow: inset -5px 0 0 0 #196956 + } + + .user-sidebar--menu__option img { + margin-inline-end: 10px; + transition: .3s + } + + .circle-with-shadow-100 { + background: #fff; + box-shadow: -5px 10px 20px 0 rgba(0, 106, 70, .15); + height: 100px; + width: 100px + } + + .circle-with-shadow-100 img { + width: 65% + } + + .user-sidebar_mobile { + border-block-end: 1px dashed #f0f0f0; + border-block-start: 1px dashed #f0f0f0 + } + + .user-mobile-icon { + margin-inline: 2px 10px + } + + .user-email-icon { + margin-inline: 0 9px + } + + .form-control { + border: 1px solid #dfe1e5; + border-radius: .65rem + } + + .form-control:disabled~.input-group-text { + background-color: #e9ecef !important + } + + .form-control:disabled+.input-group-append span { + background-color: #e9ecef !important; + opacity: 1 + } + + .form-control:focus { + border-color: #dfe1e5; + box-shadow: none + } + + .input-group-text { + border: 1px solid #dfe1e5; + border-radius: .65rem; + padding: .375rem .35rem + } + + .field-validation-valid, + .field-validation-valid.input-group-append .input-group-text, + .field-validation-valid.input-group-text { + border-color: #dc3545 !important + } + + .border-right-input { + border-end-start-radius: .65rem !important; + border-start-start-radius: .65rem !important + } + + .border-inline-end-input { + border-end-end-radius: .65rem !important; + border-start-end-radius: .65rem !important + } + + .input-group>.custom-select:not(:last-child), + .input-group>.form-control:not(:last-child) { + padding-inline-end: 0 + } + + .input-group.no-bg .input-group-text { + background: transparent; + border-inline-start: 0 + } + + .input-group.no-bg input.form-control { + border-inline-end: 0 + } + + .rounded-pill-right { + border-radius: 0 50rem 50em 0 !important + } + + .rounded-pill-left { + border-radius: 50rem 0 0 50em !important + } + + .rangeslider1 { + height: 22px; + margin-block-start: -12px; + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none + } + + .rangeslider1:before { + background: hsla(0, 0%, 100%, .5); + box-sizing: border-box; + content: ""; + width: 100% + } + + .rangeslider1 .rangeslider-fill-lower, + .rangeslider1:before { + border-radius: 100px; + height: 4px; + inset-block-start: 50%; + position: absolute; + -webkit-transform: translateY(-50%); + transform: translateY(-50%) + } + + .rangeslider1 .rangeslider-fill-lower { + background: linear-gradient(90deg, #196956, #3ba9c9); + min-width: 38px; + width: 100% !important + } + + .rangeslider1 .rangeslider-thumb { + background: #196956; + box-sizing: border-box; + color: #fff; + height: 18px; + inset-block-start: 50%; + inset-inline-start: 0; + line-height: 20px; + min-width: 12%; + padding-inline-end: 10px; + position: absolute; + text-align: end; + touch-action: pan-x; + -webkit-transform: translateY(-50%); + transform: translateY(-50%) + } + + .rangeslider1.varient-2 .rangeslider-thumb { + background: #fff; + color: #003b4c; + height: 20px; + line-height: 21px + } + + .details-page .rangeslider-circles_completed.can-complete:after { + background-size: 30% !important + } + + @media(min-width: 1024px) { + .details-page .rangeslider-thumb_container .rangeslider-thumb { + font-size: .8rem; + height: 21px + } + + .details-page .rangeslider-circles_2 { + width: 45px + } + } + + .rangeslider-thumb_container { + margin-inline: -2px; + white-space: nowrap + } + + .rangeslider-thumb_container .rangeslider-thumb { + border-end-start-radius: 0 !important; + border-start-start-radius: 0 !important; + height: 13px + } + + .slider-with-image { + margin-block-start: -4px !important + } + + .slider-with-image .tiny-snabel { + inset-block-start: 3px; + inset-inline-end: 2px; + position: absolute + } + + .slider-with-image .rangeslider-fill-lower { + background: #bbb !important; + border-radius: 0 !important; + height: 23px !important + } + + .slider-with-image .rangeslider-thumb { + height: 22px !important + } + + .rangeslider-circles_completed .rangeslider-circles_2:first-child, + .rangeslider-circles_init .rangeslider-circles_2:first-child { + background: #214570 + } + + .rangeslider-circles_completed .rangeslider-circles_2:first-child img, + .rangeslider-circles_init .rangeslider-circles_2:first-child img { + filter: brightness(0) invert(1) + } + + .rangeslider-circles_completed { + overflow: hidden + } + + .rangeslider-circles_completed.can-complete:after { + background: rgba(223, 225, 229, .39) url(../images/orphanwish_completed.svg) no-repeat 50%/50%; + content: ""; + inset: 0; + position: absolute; + z-index: 9 + } + + .rangeslider-circles_completed .rangeslider-thumb { + border-radius: 0 !important + } + + .rangeslider-circles_completed .rangeslider-circles_2 { + background: #196956 + } + + .rangeslider-circles_completed .rangeslider-circles_2 img { + filter: brightness(0) invert(1) + } + + .rangeslider2 { + height: 22px; + position: relative + } + + .rangeslider2:before { + background: linear-gradient(90deg, #ffe63d 50%, #f25e09 0); + height: 7px; + inset-inline-end: 0 + } + + .rangeslider2 .rangeslider-fill-lower { + background: transparent + } + + .rangeslider2 .rangeslider-thumb { + background: #fff; + border-radius: 1px; + box-shadow: 0 0 4px 0 #000; + height: 11px; + width: 5px + } + + .rangeslider3 { + position: relative; + user-select: none + } + + .rangeslider3 .rangeslider-fill-lower { + background: #f2f2f2; + border-radius: 7px; + height: 32px; + transform: translateY(-50%); + width: 100% !important + } + + .rangeslider3 .rangeslider-thumb { + background: #196956; + border-radius: 7px; + box-sizing: border-box; + color: #fff; + height: 31.5px; + inset-block-start: 50%; + inset-inline-start: 0; + line-height: 20px; + min-width: 35px; + padding: 7px 0 7px 3px; + position: absolute; + text-align: end; + touch-action: pan-x; + transform: translateY(-50%) + } + + .rangeslider3 .range-output .output { + display: block; + font-family: Greta-AR-LT-Semibold; + font-size: 16px + } + + .rangeslider-circles { + height: 50px; + position: absolute; + width: 50px + } + + .rangeslider-circles, + .rangeslider-circles_2 { + background: #dfe0e0; + border-radius: 50%; + z-index: 2 + } + + .rangeslider-circles_2 { + aspect-ratio: 1; + width: 30px + } + + .rangeslider-circle-1 { + inset-block-end: 50%; + inset-inline-start: 0; + transform: translateY(50%) + } + + .rangeslider-circle-2 { + inset-block-end: 50%; + inset-inline-start: 50%; + transform: translate(50%, 50%) + } + + .rangeslider-circle-3, + .rangeslider-circle-4 { + inset-block-end: 50%; + inset-inline-end: 0; + transform: translateY(50%) + } + + .rangeslider-circle-4 { + background-color: #196956; + height: 70px; + width: 70px + } + + .rangeslider-circle-4 .range-label { + inset-block-start: -50px; + inset-inline-end: 18px + } + + .rangeslider-exceededline-4 { + background-color: #196956; + height: 11px; + inset-block-start: 0; + inset-inline-start: 2px; + position: absolute; + width: 99%; + z-index: 1 + } + + .rangeslider4 { + height: 11px; + position: relative; + user-select: none + } + + .rangeslider4 .rangeslider-fill-lower { + background: #dfe0e0; + border-radius: 100px; + height: 11px + } + + .rangeslider4 .rangeslider-thumb { + background: #196956; + background: linear-gradient(90deg, #196956 20%, #214570); + border-radius: 100px; + color: #fff; + height: 11px; + inset-block-start: 0; + inset-inline-start: 0; + max-width: 100% !important; + min-width: 2%; + position: absolute; + text-align: end; + touch-action: pan-x + } + + .rangeslider4 .range-output .output { + display: block; + font-size: 9px; + margin-inline-end: 10px + } + + .rangeslider5 { + height: 11px; + margin: 60px 0; + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none + } + + .rangeslider5 .rangeslider-fill-lower { + background: #dfe0e0; + border-radius: 100px; + height: 11px; + position: relative; + z-index: 2 + } + + .rangeslider5 .rangeslider-fill-lower.exceed_100 { + max-width: 85% + } + + .rangeslider5 .rangeslider-fill-lower.exceed_100 .rangeslider-thumb { + max-width: 100% + } + + .rangeslider5 .rangeslider-thumb { + background: #196956; + background: linear-gradient(90deg, #214570 20%, #196956); + border-radius: 100px; + color: #fff; + height: 11px; + inset-block-start: 0; + inset-inline-start: 0; + position: absolute; + text-align: end; + touch-action: pan-x + } + + .rangeslider5 .range-output .output:after { + background-color: #214570; + border-radius: 50%; + content: ""; + height: 15px; + inset-block-start: -2px; + inset-inline-end: -5px; + position: absolute; + width: 15px + } + + .rangeslider5 .range-output .output.less-than10:after { + inset-inline-end: auto; + inset-inline-start: 0 + } + + .rangeslider5 .range-output .output.more-than100:after { + background-color: transparent; + opacity: 0; + visibility: hidden + } + + .range-label { + align-items: center; + color: #fff !important; + display: flex; + font-size: 12px; + height: 35px; + inset-block-start: -64px; + inset-inline-end: -15px; + justify-content: center; + position: absolute; + width: 35px; + z-index: 1 + } + + .range-label span { + background-color: #01b477; + border-radius: 0 50% 50% 50%; + height: 100%; + inset-block-start: 0; + inset-inline-end: 0; + position: absolute; + transform: rotate(225deg); + width: 100%; + z-index: -1 + } + + .rangeslider5_mobile_container { + inset-block-end: 0; + position: fixed; + width: 100%; + z-index: 99 + } + + .rangeslider5_mobile_container .rangeslider-circles, + .rangeslider5_mobile_container .rangeslider-circles_2 { + height: 35px; + width: 35px + } + + .rangeslider5_mobile_container .rangeslider5 { + margin: 10px 0 + } + + .rangeslider5_mobile_container .range-output .output.more-than97:after { + inset-inline-end: 0 + } + + .card-campaign { + background: #fff url(../images/campaign-card-bg.svg) no-repeat 0 0 + } + + .card-campaign-empty { + background: rgba(18, 61, 100, .05) url(../images/icon-campaign-empty.svg) no-repeat left -10px top; + border: 1px dashed #214570; + border-radius: 5px; + display: block; + height: 140px; + transition: .3s; + width: 210px + } + + .card-campaign-empty:hover { + background: rgba(18, 61, 100, .05) url(../images/icon-campaign-empty-onhover.svg) no-repeat left -10px top; + border-style: solid; + box-shadow: 0 1px 7px rgba(18, 61, 100, .5); + transition: .3s + } + + .campaign-details-inactive { + align-items: center; + background-color: hsla(0, 0%, 94%, .5); + border-radius: 15px; + display: flex; + height: 100%; + inset-block-start: 0; + inset-inline-start: 0; + justify-content: center; + position: absolute; + width: 100% + } + + .img-subsidy { + border: 1px solid #196956; + border-radius: 13px 13px 0 0; + cursor: pointer; + margin-block-end: 5px; + position: relative + } + + .img-subsidy .img-subsidy-price { + background: #196956; + border-radius: 0 12px 0 16px; + color: #fff; + font-family: Greta-AR-LT-Semibold; + font-size: 14px; + inset-block-start: -1px; + inset-inline-start: -1px; + padding: 5px 12px; + position: absolute + } + + .img-subsidy .img-subsidy-price span { + margin: 0 7px + } + + .img-subsidy img { + border-radius: 13px 13px 0 0; + height: 195px; + width: 100% + } + + .img-subsidy .rangeslider1 { + margin-block-start: -16px + } + + .img-subsidy .rangeslider1 .rangeslider-thumb { + inset-inline-start: -1px; + -webkit-transform: translateY(-10%); + transform: translateY(-10%) + } + + .img-subsidy .rangeslider1 .rangeslider-fill-lower, + .img-subsidy .rangeslider1:before { + height: 0 + } + + .img-subsidy:before { + background: #196956; + background: linear-gradient(90deg, #196956, #214570); + content: ""; + height: 8px; + inset-block-end: -1px; + inset-inline-start: -1px; + position: absolute; + width: 100.6% + } + + .line-crossed { + display: inline-block; + position: relative + } + + .line-crossed:before { + inset-inline-start: -30px; + transform: translate(100%, -50%) + } + + .line-crossed:after, + .line-crossed:before { + background-color: red; + content: ""; + height: 1px; + inset-block-start: 50%; + position: absolute; + width: 100% + } + + .line-crossed:after { + inset-inline-end: -30px; + transform: translate(-100%, -50%) + } + + .line-crossed.line-w-90:after, + .line-crossed.line-w-90:before { + width: 90px + } + + .line-crossed.line-platinum:after, + .line-crossed.line-platinum:before { + background-color: #8b8b8b + } + + .line-crossed.line-diamond:after, + .line-crossed.line-diamond:before { + background-color: #96baca + } + + .line-crossed.line-gold:after, + .line-crossed.line-gold:before { + background-color: #dbc47b + } + + .line-crossed.line-silver:after, + .line-crossed.line-silver:before { + background-color: #d9d9d9 + } + + .line-crossed.line-bronze:after, + .line-crossed.line-bronze:before { + background-color: #d8a97d + } + + .banner-ghiras-ambassadors { + background-image: url(../images/ghiras-ambassadors-mobile.jpg) + } + + .banner-ghiras-ambassadors, + .banner-major-doners { + background-repeat: no-repeat; + background-size: 100% 100%; + height: 260px + } + + .banner-major-doners { + background-image: url(../images/major-donors-mobile.jpg) + } + + .banner-sms-donation { + background-image: url(../images/sms-donation-mobile.jpg); + background-repeat: no-repeat; + background-size: 100% 100%; + height: 170px + } + + .border-rounded-top-13 { + border-start-end-radius: 13px !important; + border-start-start-radius: 13px !important + } + + #amountRadioBtns .btn, + .amountRadioBtns .btn { + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: .65rem; + box-shadow: none !important + } + + #amountRadioBtns .btn span, + .amountRadioBtns .btn span { + color: #196956 + } + + #amountRadioBtns .btn small, + .amountRadioBtns .btn small { + color: #21446f + } + + #amountRadioBtns .btn:nth-child(4), + .amountRadioBtns .btn:nth-child(4) { + margin-inline-end: .25rem; + margin-inline-start: .25rem + } + + #amountRadioBtns .btn-check:checked+label, + .amountRadioBtns .btn-check:checked+label { + background-color: #196956; + color: #fff !important + } + + #amountRadioBtns .btn-check:checked+label small, + #amountRadioBtns .btn-check:checked+label span, + .amountRadioBtns .btn-check:checked+label small, + .amountRadioBtns .btn-check:checked+label span { + color: #fff + } + + .title-with-amounts.disabled .btn, + .title-with-amounts.disabled .title, + .title-with-amounts.disabled input { + background: #fff !important; + pointer-events: none; + user-select: none + } + + .title-with-amounts.disabled .btn, + .title-with-amounts.disabled .title, + .title-with-amounts.disabled input, + .title-with-amounts.disabled input::placeholder, + .title-with-amounts.disabled small { + color: #aaa !important + } + + .border-bottom-dashed { + border-block-end: 2px dotted #d9d9d9 + } + + .border-rounded-bottom-13 { + border-end-end-radius: 13px !important; + border-end-start-radius: 13px !important + } + + .text-second { + color: #003b4c + } + + .sms-donation-bg { + background-image: url(../images/bg.jpg); + background-repeat: no-repeat; + background-size: cover; + height: 100vh; + overflow: hidden; + padding-block-start: 135px + } + + .sms-donation-bg__hand { + inset-block-end: -75px; + inset-inline-end: 0; + position: absolute; + width: 550px + } + + .sms-donation__title { + max-width: 310px + } + + .telecom-container { + inset-block-end: 10px; + inset-inline-start: 0; + z-index: 1 + } + + .text-shadow-white { + text-shadow: 3px 1px #fff + } + + .text-shadow-green { + text-shadow: 3px 1px #196956 + } + + .sms-donation-pricing-container-1 { + background-image: url(../images/card-patteren-container-1.svg); + background-position: 30px bottom; + background-repeat: no-repeat + } + + .sms-donation-pricing-container-2 { + background-image: url(../images/card-patteren-container-2.svg); + background-position: 80px bottom; + background-repeat: no-repeat + } + + .sms-donation-pricing-1 { + background-image: url(../images/card-patteren-1.svg); + background-position: 100%; + background-repeat: no-repeat + } + + .sms-donation-pricing-1 .card-body { + background: linear-gradient(159deg, rgba(13, 143, 117, .25), rgba(33, 69, 112, .25)) + } + + .sms-donation-pricing-2 { + background-image: url(../images/card-patteren-2.svg); + background-position: 100%; + background-repeat: no-repeat + } + + .sms-donation-pricing-2 .card-body { + background: linear-gradient(159deg, rgba(13, 143, 117, .4), rgba(33, 69, 112, .4)) + } + + .sms-donation-pricing-3 { + background-image: url(../images/card-patteren-3.svg); + background-position: 100%; + background-repeat: no-repeat + } + + .sms-donation-pricing-3 .card-body { + background: linear-gradient(159deg, rgba(13, 143, 117, .6), rgba(33, 69, 112, .6)) + } + + .sms-donation-pricing-4 { + background-image: url(../images/card-patteren-3.svg); + background-position: 100%; + background-repeat: no-repeat + } + + .sms-donation-pricing-4 .card-body { + background: linear-gradient(159deg, rgba(13, 143, 117, .75), rgba(33, 69, 112, .75)) + } + + .sms-donation-pricing-5 { + background-image: url(../images/card-patteren-3.svg); + background-position: 100%; + background-repeat: no-repeat + } + + .sms-donation-pricing-5 .card-body { + background: linear-gradient(159deg, rgba(13, 143, 117, .9), rgba(33, 69, 112, .9)) + } + + .icon-shadow { + border-radius: 50%; + box-shadow: -5px 10px 20px rgba(0, 106, 70, .15) + } + + .user-verify { + inset-block-start: 0; + inset-inline-end: 10px; + position: absolute + } + + .user-verify__item { + border: 1px solid #aaa; + border-block-start: none; + border-radius: 0 0 6px 6px; + color: #aaa; + height: 30px; + margin: 0 2px; + opacity: .6; + padding-block-start: 2px; + text-align: center; + width: 25px + } + + .user-verify__item.user-verify__item-verified { + background-color: #196956; + border-color: #196956; + color: #fff; + opacity: 1 + } + + .user-verify__item-phone { + font-size: 18px + } + + .creditcardContainer { + overflow-x: auto; + overflow-y: hidden; + padding-block-end: 10px + } + + .creditcard, + .creditcardContainer { + display: -ms-flexbox; + display: flex; + margin-block-end: 10px + } + + .creditcard { + -ms-flex-pack: justify; + -ms-flex-negative: 0; + background-color: hsla(0, 0%, 95%, .31); + border: 1.5px solid #d9d9d9; + border-radius: 9px; + box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .08); + -ms-flex-direction: column; + flex-direction: column; + flex-shrink: 0; + height: 136px; + justify-content: space-between; + margin-inline-end: 10px; + padding: 6px 10px 2px; + position: relative; + width: 250px + } + + .creditcard.creditcard-active { + background: #068571; + background: linear-gradient(270deg, #196956 30%, #214570 110%); + color: #fff + } + + .creditcard--footer, + .creditcard--header { + -ms-flex-pack: justify; + display: -ms-flexbox; + display: flex; + justify-content: space-between + } + + .creditcard--footer { + font-size: 12px + } + + .creditcard--header__check { + font-size: 11px + } + + .creditcard--header__check .custom-control-label:after, + .creditcard--header__check .custom-control-label:before { + inset-block-start: 0; + inset-inline-end: -1.5rem; + inset-inline-start: auto + } + + .creditcard--header__check .custom-control { + padding-inline-end: 1.5rem; + padding-inline-start: 0 + } + + .creditcard--footer__delete { + color: #e04141 + } + + .creditcard--footer__delete i { + margin-inline-end: 5px + } + + .creditcard--footer__delete:hover { + color: #bc2e2e + } + + .creditcard--footer__expired { + background-color: #e04141; + border-radius: 0 9px 0 9px; + color: #fff; + inset-block-end: -1px; + inset-inline-end: -1px; + padding: 1px 15px; + position: absolute + } + + .creditcard--body .form-control.error, + .creditcard--body .input-group-text.error { + border: 2px solid #dc3545 !important + } + + .rc-anchor-normal { + margin: 0 auto; + width: 270px + } + + .rc-anchor-normal .rc-anchor-content { + width: 175px + } + + .rc-anchor-normal .rc-anchor-pt { + margin: 2px 0 0 45px + } + + .rc-anchor-logo-portrait { + margin: 10px 14px 0 0 + } + + .btnSkipToMainContent { + border-radius: 0 0 15px 15px; + font-size: 12px; + inset-block-start: -40px; + inset-inline-start: 50%; + position: absolute; + transform: translate(50%); + transition: .3s; + z-index: 99999999 + } + + .btnSkipToMainContent:focus { + inset-block-start: 0; + transition: .3s + } + + @media(prefers-reduced-motion:reduce) { + .btnSkipToMainContent { + transition-duration: .001ms !important + } + } + + .wizard { + display: flex; + flex-wrap: wrap; + list-style: none; + margin: 0; + padding: 15px + } + + .wizard--item { + align-items: center; + display: flex; + margin-block-end: 5px; + margin-block-start: 5px; + margin-inline-end: 10px; + position: relative + } + + .wizard--item .wizard-item--count { + background-color: #dfe1e5; + border-radius: 50%; + color: #6c757d; + font-family: Greta-AR-LT-Semibold; + font-size: 16px; + height: 28px; + margin-inline-end: 5px; + padding-block-start: 2px; + text-align: center; + width: 28px + } + + .wizard--item.active .wizard-item--count { + background-color: #196956; + color: #fff + } + + .wizard--item.active .wizard-item--title { + color: #196956 + } + + .wizard--item .wizard-item--title { + color: #dfe1e5; + font-family: Greta-AR-LT-Semibold; + font-size: 14px + } + + .wizard--item .wizard-item--line { + display: none + } + + .hr-dashed-custom { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' stroke='%23DDDDDDFF' stroke-width='4' stroke-dasharray='2, 8'/%3E%3C/svg%3E"); + height: 1px; + width: 100% + } + + .hr-dashed-custom-2 { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' stroke='%23DDDDDDFF' stroke-width='2' stroke-dasharray='20' stroke-dashoffset='8'/%3E%3C/svg%3E"); + height: 1px; + width: 100% + } + + .padding-header { + background: transparent url(../images/header-img.svg) left top 130px no-repeat; + height: 100%; + min-height: calc(100vh - 70px); + padding-block-start: 130px; + width: 100% + } + + .pwa { + filter: opacity(0) !important; + height: 0 !important; + opacity: 0 !important; + pointer-events: none !important; + user-select: none !important; + visibility: hidden !important + } + + #emailLength { + direction: ltr + } + + .slide-in { + animation: slideIn 1s forwards + } + + .slide-out { + animation: slideOut 1s forwards + } + + .fade-item { + opacity: 0 + } + + .fade-item.in { + animation: fadeIn 1s forwards + } + + @keyframes slideIn { + 0% { + transform: translateX(-100%) + } + } + + @keyframes slideOut { + 0% { + transform: translateX(0) + } + + to { + transform: translateX(-100%) + } + } + + @keyframes HideList { + 0% { + transform: scaleY(1) + } + + to { + transform: scaleY(0) + } + } + + .text_decoration { + text-decoration: underline + } + + .mobile-shadow { + box-shadow: none + } + + .org-logo-wrapper { + max-width: 190px; + text-align: center; + width: 190px + } + + .org-logo-wrapper .snabel { + inset-block-end: 0; + inset-inline-start: -70px + } + + #majorDonorsTabs .nav-link { + background-color: #ededed + } + + #majorDonorsTabs .nav-link.active { + background-color: #f7f7f7 + } + + #majorDonorsTabs :not(.nav-item:last-child) .nav-link { + margin-inline-end: .5rem + } + + .searchWrapper { + transition: width .2s ease; + width: 50% + } + + .searchWrapper.show { + background-color: #fff; + border: 1px solid #e0e0e0; + border-radius: 8px; + box-shadow: 0 3px 6px #00000029; + width: 100% + } + + .searchWrapper.show .form-control { + background-color: transparent; + border-width: 0 + } + + .msg-warning { + color: #aaa; + gap: 20px + } + + .color-blue-light { + color: #00d0c0 + } + + .form-select[disabled=disabled] { + background-image: none + } + + i.fa.fa-phone.text-primary.mr-2 { + transform: rotateY(-180deg); + -ms-transform: rotateY(-180deg); + -webkit-transform: rotateY(-180deg) + } + + .forijat-details .card .donut-chart { + height: 60px; + position: relative; + width: 60px + } + + .forijat-details .card .donut-chart svg { + background: #fff; + border-radius: 50%; + height: 100%; + transform: rotate(-90deg); + width: 100% + } + + .forijat-details .card .donut-chart circle { + fill: #fff; + stroke: #196956; + stroke-width: 32; + stroke-dasharray: 70 100; + transition: stroke-dasharray .5s ease + } + + .forijat-details .card .donut-chart .donut-center { + background: #fff; + border-radius: 50%; + color: #214570; + height: 80%; + inset-block-start: 50%; + inset-inline-end: 50%; + padding: 25% 0; + position: absolute; + text-align: center; + transform: translate(-50%, -50%); + width: 80% + } + + .forijat-details .card h6 { + color: #214570; + font-size: 24px; + font-weight: 600; + line-height: 30px + } + + .card-filter--btn_show img { + inset-block-start: 11px; + inset-inline-start: 20px; + position: absolute + } + + .card-filter--btn_hide img { + inset-block-start: 13px; + inset-inline-start: 10px; + position: absolute + } + + .mob-for-gift .select2-container { + width: 45% !important + } + + .card-tanfeeth .card-body .card-inner-top { + background: #196956; + background: linear-gradient(220deg, #196956, #214570); + border-radius: 20px 20px 0 0; + height: 202px; + overflow: hidden; + padding: 40px; + position: relative + } + + .dotes-grey li:before { + color: #d9d9d9; + content: "•"; + display: inline-block; + font-weight: 700; + margin-inline-start: -1em; + width: 1em + } + + .dropdown-toggle.btn-primary-green:after { + color: #fff + } + + .filters .btn-primary-green { + box-shadow: 0 4px 8px 0 rgba(0, 106, 70, .3) + } + + .form-switch .form-check-input { + height: 25px; + width: 50px + } + + .dropdown-item:active { + background-color: #d9d9d9; + color: #214570 !important; + margin: 0 !important + } + + .sponsers-items img { + max-height: 65px; + max-width: 145px + } + + .slider>.container { + height: 100vh + } + + .slider>.swiper-container img { + inset-block-end: 0; + inset-inline-end: 0; + position: absolute + } + + .swiper-container-horizontal>.swiper-pagination-bullets { + inset-block-end: 80px + } + + .home-banner span { + background: #e06641; + border-radius: 0 0 10px 10px; + color: #fff; + inset-block-start: 0; + inset-inline-start: 15px; + line-height: 1.2; + padding: 0 20px 4px; + position: absolute + } + + .round-checkbox .round-check:after { + inset-block-start: 6px; + inset-inline-end: 4px + } + + .form-check.without-icon { + inset-inline-end: 20px + } + + .custom-control-primary-green .custom-control-input:focus:not(:checked)~.custom-control-label:before { + border-color: rgba(13, 143, 117, .5) + } + + .custom-control-primary-green .custom-control-input:focus~.custom-control-label:before { + box-shadow: 0 0 0 .2rem rgba(13, 143, 117, .2) + } + + .custom-control-primary-green .custom-control-input:not(:disabled):active~.custom-control-label:before { + background-color: rgba(13, 143, 117, .5); + border-color: rgba(13, 143, 117, .5); + color: #fff + } + + .custom-control-primary-blue .custom-control-input:focus:not(:checked)~.custom-control-label:before { + border-color: rgba(33, 69, 112, .5) + } + + .custom-control-primary-blue .custom-control-input:focus~.custom-control-label:before { + box-shadow: 0 0 0 .2rem rgba(33, 69, 112, .2) + } + + .custom-control-primary-blue .custom-control-input:checked~.custom-control-label:before { + background-color: #214570; + border-color: #214570; + color: #fff + } + + .custom-control-primary-blue .custom-control-input:not(:disabled):active~.custom-control-label:before { + background-color: rgba(33, 69, 112, .5); + border-color: rgba(33, 69, 112, .5); + color: #fff + } + + .custom-control-danger .custom-control-input:focus:not(:checked)~.custom-control-label:before { + border-color: rgba(220, 53, 69, .5) + } + + .custom-control-danger .custom-control-input:focus~.custom-control-label:before { + box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .2) + } + + .custom-control-danger .custom-control-input:checked~.custom-control-label:before { + background-color: #dc3545; + border-color: #dc3545; + color: #fff + } + + .custom-control-danger .custom-control-input:not(:disabled):active~.custom-control-label:before { + background-color: rgba(220, 53, 69, .5); + border-color: rgba(220, 53, 69, .5); + color: #fff + } + + .table-bg-on-first-col tbody th:first-child { + position: relative; + text-align: center + } + + .table-bg-on-first-col tbody th:first-child:after { + background: rgba(78, 78, 78, .1); + content: ""; + height: 30px; + inset-block-start: 10px; + inset-inline-end: 7px; + position: absolute; + width: 1px + } + + .table-border-left-on-first-col tbody th:first-child { + min-width: 50px; + position: relative; + text-align: center + } + + .table-border-left-on-first-col tbody th:first-child:after { + background-color: #707070; + content: ""; + height: 30px; + inset-block-start: 10px; + inset-inline-end: 7px; + position: absolute; + width: 1px + } + + .table-white-rows tbody tr { + background-color: #fff + } + + .table-light-rows tbody tr { + background-color: #f7f7f7 + } + + .badge-danger .adahi-status-number { + color: #dc3545 + } + + .badge-warning .adahi-status-number { + color: #ffc107 + } + + .table-roundedtable-rounded-10 th:first-child { + border-radius: 0 10px 10px 0 + } + + .zakkah-details .card { + padding: 20px 20px 30px + } + + .zakkah-details .card .title { + color: #1b4f5f; + font-size: 14px; + margin: 0 + } + + .zakkah-details .card .amount-wrapper { + display: flex; + font-size: 18px; + justify-content: space-between + } + + .zakat-details label { + color: #545353; + font-size: 14px + } + + .social-icons .twitter { + margin-inline-end: 17px + } + + .form-group.required .col-form-label:after { + color: #06b085; + content: "*" + } + + .form-check-input-square .form-check-label { + color: #6c757d; + cursor: pointer; + display: inline-block; + font-family: Greta-AR-LT-Semibold; + margin-block-end: 0; + position: relative; + vertical-align: top + } + + .custom-checkbox.custom-checkbox-circle .custom-control-label:before { + border-radius: 50% !important + } + + .title-only-modal .modal-title { + max-width: 300px + } + + .payment-methods img { + margin-inline-end: 5px; + max-width: 65px + } + + .hr-after-word:after { + background-color: #c3c3c3; + content: ""; + height: 2px; + inset-block-start: 12px; + inset-inline-end: -210px; + position: absolute; + width: 200px + } + + .form-control[readonly]~.input-group-text { + background-color: #e9ecef !important + } + + .range-output .output { + display: block; + font-size: 14px + } + + #donorModal .modal-body { + background-position: top -190px left -26px; + background-repeat: no-repeat + } + + div[class*=card-donors-] img { + width: 65px + } + + .card-donors-platinum .table-border-left-on-first-col tbody th:first-child { + color: #8b8b8b + } + + .card-donors-platinum .table-border-left-on-first-col tbody th:first-child:after { + background-color: #8b8b8b + } + + .card-donors-diamond .table-border-left-on-first-col tbody th:first-child { + color: #96baca + } + + .card-donors-diamond .table-border-left-on-first-col tbody th:first-child:after { + background-color: #96baca + } + + .card-donors-gold .table-border-left-on-first-col tbody th:first-child { + color: #dbc47b + } + + .card-donors-gold .table-border-left-on-first-col tbody th:first-child:after { + background-color: #dbc47b + } + + .card-donors-silver .table-border-left-on-first-col tbody th:first-child { + color: #8b8b8b + } + + .card-donors-silver .table-border-left-on-first-col tbody th:first-child:after { + background-color: #8b8b8b + } + + .card-donors-bronze .table-border-left-on-first-col tbody th:first-child { + color: #d8a97d + } + + .card-donors-bronze .table-border-left-on-first-col tbody th:first-child:after { + background-color: #d8a97d + } + + .custom-card-header>.header, + .custom-card-header>.replaced-link { + display: block !important; + flex: 1; + outline: none !important; + width: 80% + } + + .rb-primary-green.custom-control-input:checked~.custom-control-label:before { + background-color: #196956; + border-color: #196956 + } + + .switch-primary-green .custom-control-input:checked~.custom-control-label:before { + background-color: #196956; + border-color: #196956; + color: #fff + } + + .telecom-logos img { + margin-inline-end: 20px; + width: 20px + } + + .telecom-logos img:nth-child(2) { + width: 16px + } + + .sms-donation-page .card .card .card-body { + height: 250px + } + + .gheras-mobile>div { + align-items: center; + border-block-start: 1px solid #e3e9ed; + color: #214570; + display: flex; + font-family: Greta-AR-LT-Semibold; + font-size: 20px; + padding: 15px 30px + } + + .hover-shadow:hover { + box-shadow: 0 1.3px 11px rgba(0, 0, 0, .27) !important; + transition: all .6s + } + + #unique-donation-tabs.nav-pills .nav-link { + background-color: #f7f7f7; + border-radius: 16px 16px 0 0; + color: #9aa0a5; + font-family: Greta-AR-LT-Semibold; + height: 100%; + padding: .5rem 3rem; + position: relative + } + + #unique-donation-tabs.nav-pills .nav-link.active { + background-color: #ededed; + color: #214570; + overflow-x: hidden + } + + #unique-donation-tabs.nav-pills .nav-link.active img { + display: inline-block + } + + #unique-donation-tabs.nav-pills .nav-link.active:before { + background: #214570; + content: ""; + height: 5px; + inset-block-start: 0; + inset-inline-start: 0; + position: absolute; + width: 100% + } + + #unique-donation-tabs.nav-pills .nav-link img { + display: none; + width: 25px + } + + #unique-donation-tabs.nav-pills .show>.nav-link { + background-color: #ededed; + color: #214570; + overflow-x: hidden + } + + .custom-tabs.nav-pills .nav-link { + background-color: #f7f7f7; + border-radius: 16px 16px 0 0; + color: #9aa0a5; + font-family: Greta-AR-LT-Semibold; + height: 100%; + padding: .5rem 3rem; + position: relative + } + + .custom-tabs.nav-pills .nav-link.active { + background-color: #ededed; + color: #214570; + overflow-x: hidden + } + + .custom-tabs.nav-pills .nav-link.active:before { + background: #214570; + content: ""; + height: 5px; + inset-block-start: 0; + inset-inline-start: 0; + position: absolute; + width: 100% + } + + .custom-tabs.nav-pills .show>.nav-link { + background-color: #ededed; + color: #214570; + overflow-x: hidden + } + + .card-radio .form-check-input[type=radio] { + height: 18px; + margin: 0; + width: 18px + } + + .creditcard-active .creditcard--footer__delete { + color: #fff + } + + .creditcard--header__brand img { + width: 44px + } + + .savedCard-cvv+.error { + display: none !important + } + + .rc-inline-block+.rc-inline-block { + width: 120px + } + + .g-recaptcha>div { + margin: 0 auto + } + + #qd-pre-amounts .btn { + color: #196956 + } + + #qd-pre-amounts .btn small { + color: #214570 + } + + #qd-pre-amounts .btn:active, + #qd-pre-amounts .btn:focus { + border-color: #196956 !important; + border-width: 2px !important + } + + #PaymentTabs.nav-tabs .nav-link { + background: #f7f7f7; + border: none; + border-block-start: 4px solid #dfe1e5; + border-radius: 0; + border-start-end-radius: 3px; + border-start-start-radius: 3px; + box-shadow: inset -2px -2px 8px rgba(0, 0, 0, .1); + color: #6c757d; + font-family: Greta-AR-LT-Semibold; + text-align: center + } + + #PaymentTabs.nav-tabs .nav-link.active { + background: #fff; + border-color: #196956; + box-shadow: none; + color: #196956 + } + + .tysarat-btns { + border-start-end-radius: 70px; + border-start-start-radius: 70px; + margin-block-start: -100px !important; + padding-block-end: 30px; + padding-block-start: 24px; + width: fit-content + } + + @media(max-width: 768px) { + .tysarat-btns { + border-start-end-radius: 20px; + border-start-start-radius: 20px; + padding-block-start: 10px + } + } + + .tysarat-btns .elec-btn, + .tysarat-btns .tan-btn { + background: url(../images/btn-bg.png); + background-position: -22px 10px; + background-repeat: no-repeat; + background-size: 55px; + border: 1px solid #b0b5be; + line-height: 26px; + min-width: 90px; + padding-block-start: 10px + } + + .tysarat-btns .btn.active, + .tysarat-btns .btn:hover, + .tysarat-btns .elec-btn:hover, + .tysarat-btns.electracity .elec-btn { + background-color: #355883 !important; + color: #fff + } + + .tysarat-btns .tan-btn:hover, + .tysarat-btns.tanfeeth .tan-btn { + background-color: #196956 !important; + color: #fff + } + + @media(max-width: 767px) { + .badge-new:after { + font-size: 10px !important; + line-height: 7px !important; + padding: 0 5px 1px !important + } + + .tysarat-btns .elec-btn, + .tysarat-btns .tan-btn { + line-height: 22px !important + } + } + + .top-55 { + inset-block-start: 55px; + z-index: 1 + } + + .mt-100px { + margin-block-start: 100px + } + + .circle-after:after { + background-color: red; + content: ""; + height: 60px; + width: 60px + } + + .medals-list { + position: relative + } + + .medals-list__item { + align-items: center; + display: flex; + margin-block-end: 20px; + position: relative; + z-index: 2 + } + + .medals-list__vertical-line { + background-color: #efefef; + height: 94%; + inset-block-start: 30px; + inset-inline-start: 20px; + position: absolute; + width: 10px; + z-index: 1 + } + + .medals-list__item__desc__badge { + display: none + } + + .medals-list__item--active .medals-list__item__desc { + background: #21446f; + background: linear-gradient(90deg, rgba(56, 94, 141, .2), #fff); + border-end-end-radius: 15px; + border-start-end-radius: 15px + } + + .medals-list__item--active .medals-list__item__desc__badge { + display: inline + } + + .medals-list__item__desc { + color: #214570; + flex: 1 1 auto; + padding: 1.5rem + } + + .medals-list__item__img { + width: 50px + } + + @media(min-width: 576px) { + .card-campaign-empty { + height: 175px; + width: 270px + } + + .modal-md { + max-width: 400px + } + + .about-page>section:first-child { + padding: 120px 0 + } + + .about-features:after { + background-position: right -240px bottom 0 + } + } + + @media(min-width: 768px) { + .bg-md-light { + background-color: #f7f7f7 !important + } + + .banner-ghiras-ambassadors { + background-image: url(../images/ghiras-ambassadors.jpg); + height: 160px + } + + .banner-major-doners { + background-image: url(../images/major-donors.jpg); + height: 160px + } + + .banner-sms-donation { + background-image: url(../images/sms-donation.jpg); + height: 337px + } + + .campaign-card-header { + background: url(../images/flowers.svg) no-repeat left 150px bottom -60px, url(../images/flowers.svg) no-repeat right -40px top -30px + } + + .creditcardContainer { + flex-wrap: wrap + } + + .card-filter { + box-shadow: 0 1px 11px rgba(0, 0, 0, .16) + } + + .gheras .steps img { + max-width: 500px + } + + .gheras .steps p { + max-width: 380px + } + + .gheras .steps h4 { + max-width: 400px + } + + .gheras .line-with-words .title { + max-width: 300px; + min-width: auto; + padding: 0 + } + + .DonationCasesLabel { + display: none + } + + .login input::-webkit-input-placeholder { + color: #214570; + opacity: 1 + } + + .login input:-moz-placeholder { + color: #214570; + opacity: 1 + } + + .login input:-ms-input-placeholder { + color: #214570; + opacity: 1 + } + + .about-main { + background-image: url(../images/white-plant-vector-lg.svg), url(../images/green-overlay.svg), url(../images/plant-bg.jpg); + background-position: -110px 0, 0 0, 0 0 + } + + .about-main h1 { + font-size: 3rem + } + + .about-main p { + font-size: 20px + } + + .about-page.padding-header { + padding-block-start: 130px + } + + .about-page>section .section-title:before { + inset-inline-start: 50%; + transform: translate(50%, 50%); + width: 30% + } + + .about-vision { + background-image: url(../images/bg-lg.svg); + background-position: right -350px bottom -250px + } + + .about-vision .about-vision-icon .dashed-circle, + .about-vision .about-vision-icon .dashed-line, + .about-vision .about-vision-icon .dashed-line-2 { + display: none + } + + .about-vision .about-vision-icon .vector-icon { + width: 140px + } + + .about-vision .row .col-12:nth-child(3) .about-vision-icon+p { + margin-block-start: 25px + } + + .about-goals-box { + margin-block-end: 35px + } + + .about-goals-box h5 { + font-size: 22px + } + + .about-goals-box p { + font-size: 16px; + max-width: 200px + } + + .about-features .card { + height: 100% + } + + .about-features .card .feature-title:before { + inset-block-start: -50px; + inset-inline-start: 50%; + transform: translate(50%, 50%) + } + + .about-features .card .feature-title { + background-position: 88px -5px + } + + .about-features:after { + background-image: url(../images/bg-lg-green.svg); + background-position: right -200px bottom 0; + background-size: 500px; + height: 700px; + inset-block-end: -55px; + inset-inline-start: 0 + } + + .about-vision-icon.arrow-lg-1:after { + background-image: url(../images/left-arrow-up.svg); + inset-block-start: 40px + } + + .about-vision-icon.arrow-lg-1:after, + .about-vision-icon.arrow-lg-2:after { + background-repeat: no-repeat; + background-size: 100px; + content: ""; + height: 50px; + inset-inline-end: -100px; + position: absolute; + width: 200px + } + + .about-vision-icon.arrow-lg-2:after { + background-image: url(../images/left-arrow-down.svg); + inset-block-start: 70px + } + + .donation-key-circle { + height: 80px; + justify-content: center; + width: 80px + } + + .donation-key-circle img { + width: 50px + } + + .table-bg-on-first-col tbody th:first-child { + background-image: url(../images/ghiras-table-badge-new.svg); + background-position: center right 5px; + background-repeat: no-repeat; + background-size: 24px; + position: relative; + width: 100px + } + + .telecom-logos img { + margin-inline-end: 20px; + width: 30px + } + + .telecom-logos img:nth-child(2) { + width: 22px + } + + .sms-donation-page .card { + border: 0 !important + } + + .sms-donation-page .card .card .card-body { + height: 350px + } + + .opaque .navbar-brand { + height: 115px; + padding-block-end: 20px; + width: 121px + } + + .opaque .navbar-brand img { + height: 90px + } + + .gifts-left-bg:after { + background-image: url(../images/gift-left-bg.svg); + background-repeat: no-repeat; + content: ""; + height: 495px; + inset-block-end: 8px; + inset-inline-end: -113px; + position: absolute; + -ms-transform: rotate(180deg); + transform: rotate(180deg); + width: 200px; + z-index: -1 + } + + .card-filter--body .select2-container:nth-of-type(3n+0) { + margin-inline-end: 0 !important + } + + footer.footer-large .content-4 { + font-size: 14px + } + + .line-with-words .title { + font-size: 28px; + font-weight: 600; + min-width: max-content + } + + .about-goals:after { + background-image: url(../images/bg-lg.svg); + background-size: 200px; + height: 1112px; + inset-block-start: -200px + } + + .navbar .container { + padding-inline-start: 160px + } + } + + @media(min-width: 768px)and (max-width:991px) { + .sms-donation__title { + margin-block-start: -120px + } + + .container-md { + max-width: 100%; + padding-inline-end: 25px; + padding-inline-start: 25px; + width: 100% + } + } + + @media(min-width: 768px)and (max-width:1199px) { + .share-modal .modal-content { + transform: scale(.7) + } + } + + @media(min-width: 992px) { + .border-lg-left { + border-inline-end: 2px dotted #d9d9d9 + } + + .wizard--item { + margin-block-end: 0; + width: 33% + } + + .wizard--item .wizard-item--line { + display: block + } + + .about-main { + min-height: 880px + } + + .about-main .about-main-logos img { + height: 80px + } + + .about-features:before { + background-image: url(../images/bg-lg-white.svg); + background-position: left -740px bottom 0; + background-repeat: no-repeat; + background-size: 1300px; + content: ""; + height: 1505px; + inset-block-end: -1000px; + inset-inline-end: 0; + position: absolute; + width: 200px; + z-index: 1 + } + + .about-features .card .feature-title { + background-position: 63% -5px + } + + .about-vision-icon.arrow-lg-1:after, + .about-vision-icon.arrow-lg-2:after { + background-size: 160px; + inset-inline-end: -175px + } + + .custom-tooltip+.custom-tooltip__text { + inset-block-end: 30px; + inset-inline-start: 100px; + width: 280px + } + + .campaign-stats .card { + padding-inline-start: 7rem + } + + .ghiras-banner .home-banner--bottom:before { + background-image: url(../images/ghiras-banner.svg); + background-position: left 0 bottom -15px; + content: ""; + height: 100%; + inset-inline-start: 0; + position: absolute; + width: 100% + } + + .about-page>section { + padding: 80px 20px + } + + .opaque li.seperator { + height: 34px; + margin-block-end: 6px + } + + .swiper-slide>.container { + transform: translateY(-50%) + } + + .nav-link.nav-link-txt { + padding-inline-end: 30px + } + } + + @media(min-width: 1200px) { + .about-features:after { + background-position: right -300px bottom 0; + background-size: 650px; + height: 700px; + inset-block-end: -55px; + inset-inline-start: 0 + } + + .about-features .card .feature-title { + background-position: 60% -5px + } + + .about-vision-icon.arrow-lg-1:after, + .about-vision-icon.arrow-lg-2:after { + background-size: auto; + inset-inline-end: -210px + } + + .wizard--item .wizard-item--line { + width: 190px + } + + .campaign-stats .card { + padding-inline-start: 10rem + } + + #amountRadioBtns:nth-child(4), + .amountRadioBtns:nth-child(4) { + margin-inline-end: 1rem; + margin-inline-start: 1rem + } + } + + @media(max-width: 1199px) { + + .footer-large .content-3, + .footer-large .content-4 { + padding: 8px 0 + } + + .payment-details .creditCardForm .heading { + margin-block-end: 15px + } + + .payment-details .creditCardForm .already-member { + font-size: 12px; + margin-block-end: 15px + } + + .payment-details .creditCardForm input { + font-size: 13px; + padding: 5px + } + + .payment-details .creditCardForm .expiry-dates { + max-width: 50% + } + + .payment-details .creditCardForm .cvv { + width: 130px + } + + .payment-details .creditCardForm .custom-checkbox-round .custom-control-label { + margin-block-end: 10px + } + + .payment-details .bg-gradient { + font-size: 16px + } + + .creditCardForm .heading { + margin-block-end: 15px + } + + .creditCardForm .already-member { + font-size: 12px; + margin-block-end: 15px + } + + .creditCardForm input { + font-size: 13px; + padding: 5px + } + + .creditCardForm .expiry-dates { + max-width: 50% + } + + .creditCardForm .cvv { + width: 130px + } + + .creditCardForm .custom-checkbox-round .custom-control-label { + margin-block-end: 10px + } + + .Payment-details-page .card-icon { + height: 30px; + inset-block-start: 0; + inset-inline-end: 0 + } + + .Payment-details-page .amount-details .title { + font-size: 20px; + margin-block-end: 28px + } + + .Payment-details-page .amount-details .amount { + font-size: 20px; + margin: 25px 0 + } + + .Payment-details-page .amount-details .user-details { + font-size: 16px; + margin: 25px 0 32px + } + + .Payment-details-page .amount-details .user-details>div:first-of-type { + margin-block-end: 25px + } + + &.fixed-side-menu .card-icon { + height: 28.6px + } + + &.fixed-side-menu .payment-info-box { + padding: 5px 15px; + width: auto + } + + .all-projects .section-bg { + height: 105% + } + + .rangeslider1.varient-2 .rangeslider-thumb { + font-size: 10px; + height: 15px; + line-height: 17px; + width: 29px + } + } + + @media(max-width: 991px) { + .sms-donation-bg__hand { + inset-block-end: -50px; + width: 500px + } + + .ghiras-page-bg { + inset-block-start: -160px + } + + .cards-wrapper { + justify-content: center + } + + .all-projects .filters a { + margin: 5px 0; + margin-inline-end: 5px + } + + .campaign-stats .card { + padding-inline-start: 5rem + } + + .sponsers-items img { + margin-block-end: 25px; + margin-inline-end: 15px; + max-height: 70px; + width: 115px + } + + footer.footer-large .links { + width: 100% + } + + .donation-links .avatar-wrapper { + flex-direction: column + } + + .donation-links .avatar-wrapper .avatar-icon { + height: 100px; + width: 100px + } + + .donation-links .avatar-wrapper h3 { + font-size: 38px; + font-weight: 600 + } + + .shared-links .avatar-wrapper { + flex-direction: column + } + + .shared-links .avatar-wrapper .avatar-icon { + height: 100px; + width: 100px + } + + .shared-links .avatar-wrapper h3 { + font-size: 38px; + font-weight: 600; + text-align: center + } + } + + @media(max-width: 767px) { + .medals-list__item__desc { + padding: 1.5rem 1.1rem + } + + .all-projects .tysarat-title-wrapper { + border-inline-start: 8px solid #196956 + } + + .all-projects .filters .has-menu>.btn, + .all-projects .filters>.btn { + font-size: 14px; + height: 38px; + line-height: 21px; + margin: 5px 0; + margin-inline-end: 5px; + min-width: 114px + } + + .all-projects .section-bg { + height: 103% + } + + .electracity-filter-btn { + border-radius: 10px !important + } + + .org-logo-wrapper { + max-width: 160px; + text-align: center; + width: 160px + } + + .org-logo-wrapper .snabel { + inset-inline-start: -30px + } + + .user-avatar { + inset-block-start: -20px; + inset-inline-start: 50%; + position: absolute; + transform: translate(60%) + } + + .ghiras-page-bg { + inset-block-start: -110px; + inset-inline-end: -20px; + width: 220px + } + + .shadow-none-sm { + box-shadow: none !important + } + + .page-link { + padding: .5rem .2rem + } + + .card-header-ghiras-bg { + inset-inline-end: -100px + } + + .btnSkipToMainContent { + inset-block-start: -100px; + z-index: -999 + } + + .user-sidebar--menu { + display: -ms-flexbox !important; + display: flex; + flex-wrap: wrap; + justify-content: space-between + } + + .user-sidebar--menu li { + background-color: #fff !important; + border-radius: 10px; + box-shadow: 0 1px 4px 0 rgba(77, 77, 77, .1) !important; + margin-block-end: 10px; + text-align: center; + width: 49% + } + + .user-sidebar--menu li a { + border-radius: 10px + } + + .user-sidebar--menu__option { + color: #214570; + justify-content: center + } + + .user-sidebar--menu__option:hover { + background-color: #fff; + box-shadow: none; + color: #707070 + } + + .user-sidebar--menu__option.menu-option-active { + background-color: #196956; + color: #fff + } + + .user-sidebar--menu__option.menu-option-active img { + filter: brightness(0) invert(1) + } + + .rangeslider3 .rangeslider-thumb { + min-width: 35px + } + + .rangeslider3 .range-output .output { + font-size: 14px + } + + #referenceId { + color: #000 + } + + .table-rounded.table-head-light-grey thead th:nth-child(2), + .table-rounded.table-head-white thead th:nth-child(2) { + background-position: 0 100%; + background-size: 80px + } + + .sms-donation__title { + max-width: 100% + } + + .close { + font-size: 30px + } + + &.fixed-side-menu { + inset-block-start: 130px; + max-width: 250px + } + + .subBtns form { + width: 50% + } + + .subBtns button { + width: 95% + } + + .login i { + background: #fff; + margin-block-end: 0 !important + } + + .login .txt-dark-green { + color: #ffe082 + } + + .withScrollContent { + margin-block-start: 20px + } + + .withScrollContent .d-flex { + display: block !important + } + + .withScrollContent .card .d-flex>div:not(.HideMobile) { + align-items: center; + display: flex; + margin-block-end: 9px; + width: 100% !important + } + + .HideMobile { + display: none + } + + .showInMobile { + display: block + } + + .HomeCards h6 { + background: #196956; + color: #fff; + padding: 10px; + text-align: center + } + + .HomeCards form { + margin: 5px 20px 0 + } + + .share-modal .modal-head { + margin-block-end: 30px + } + + .share-modal .modal-head h6 { + font-size: 18px + } + + .share-modal .link-label .text { + font-size: 15px + } + + .share-modal .share-link .btn-primary-green { + font-size: 15px; + padding: 7px 13px + } + + .share-modal .social-icons .btn>div { + height: 44px; + width: 44px + } + + .gifts .card { + padding: 30px 0 + } + + .gifts .card img { + width: 200px + } + + .gifts .card .title { + font-size: 20px; + margin-block-end: 20px + } + + .gifts .card .description { + font-size: 14px + } + + .gifts .card .number { + font-size: 20px; + height: 50px; + padding: 10px 0; + width: 50px + } + + .gifts .gift-action { + font-size: 17px; + font-weight: 600; + margin: -7px auto 60px; + padding: 10px 50px + } + + .gifts .title.label { + font-size: 18px + } + + .padding-header { + background: transparent url(../images/header-img.svg) left top 55px no-repeat; + background-size: 700px; + min-height: calc(100vh - 91px); + padding-block-start: 50px + } + + #showFilter { + width: 100% + } + + #showFilter img { + inset-inline-start: 6px + } + + .user-control-options-wrapper { + display: block + } + + .btn-sm-block { + display: block; + width: 100% + } + + .table.table-compact-on-mobile td, + .table.table-compact-on-mobile th { + padding: .75rem .35rem + } + + .table-bg-on-first-col tbody th:first-child:after { + inset-inline-end: 1px + } + + .hr-after-word:after { + inset-inline-end: -110px; + width: 100px + } + + .adahi-page .accordion .card-header { + background-position: bottom; + background-size: 130px + } + + #unique-donation-tabs.nav-pills .nav-link { + font-size: 14px; + padding: .5rem .9rem + } + + #unique-donation-tabs.nav-pills .nav-link img { + width: 18px + } + + .verification-inputs input { + height: 33px; + width: 33px + } + + .card-filter--body .select2-container { + flex: none; + margin-inline-end: 0; + width: 49% !important + } + + span.DonationCasesLabel { + color: #06b085; + font-weight: 600; + margin-inline-end: 11px + } + + .MobileBtn a { + font-size: 18px; + padding: 10px; + width: 100% + } + + .swiper-container .btn-white { + font-size: 16px + } + + .payment-methods img { + max-width: 63px + } + + #cart .badge { + inset-block-start: -7px; + inset-inline-start: -5px + } + } + + @media(max-width: 575px) { + .org-logo-wrapper { + min-width: 130px; + width: 130px + } + + .width-sm-100 { + width: 88px + } + + .case-name { + min-height: 40px !important + } + + .case-name .item-name { + font-size: 17px + } + + .mobile-shadow { + border: 0 !important; + box-shadow: 0 4px 10px rgba(0, 0, 0, .122) !important + } + + .mobile-profile-actions { + display: block + } + + .payment-details .cards-logo { + align-items: center; + display: flex; + flex-direction: column; + justify-content: center + } + + .payment-details .cards-logo img { + margin-block-start: 10px + } + + .payment-details form input.error { + border: 1px solid #f25e09 + } + + .footer-large .content-3 { + padding: 14px 0 + } + + .footer-large .content-3 .d-flex { + flex-direction: column + } + + .footer-large .content-3 .nav { + margin-block-end: 10px + } + + .footer-large .content-4 { + padding: 12px 0 + } + + footer .faq-link { + margin-block-end: 8px; + margin-inline-end: 0 + } + + footer.footer-large .links { + align-items: center; + display: flex; + flex-direction: column; + justify-content: space-around + } + + .breadcrumb.breadcrumb-onslider { + inset-inline-start: 45px + } + + .card-filter--body .select2-container { + margin-inline-end: 0; + width: 100% !important + } + + .donation-links .avatar-wrapper .avatar-icon, + .shared-links .avatar-wrapper .avatar-icon { + height: 120px; + width: 120px + } + + .avatar-icon svg { + margin: 0 auto + } + + .cart .card.total-amount .btn-primary-blue { + margin: auto + } + + .Payment-details-page .payment-info .payment-sum { + margin-block-end: 20px + } + + .Payment-details-page .payment-info .payment-sum .amount { + font-size: 26px; + margin: 0 5px + } + + .Payment-details-page .payment-info .payment-sum .unit { + font-size: 22px + } + + .Payment-details-page .payment-info .payment-sum .title { + font-size: 18px + } + + .Payment-details-page .payment-info .cart-items { + padding: 15px 0 10px + } + } + + @media(max-width: 320px) { + .sms-donation-bg__hand { + inset-block-end: 0; + width: 190px + } + + #unique-donation-tabs.nav-pills .nav-link { + padding: .5rem + } + + .campaign-stats .card { + padding-inline-start: 3rem + } + } + + .housing-cards .btn.addToCart { + aspect-ratio: 1; + border-radius: 50%; + display: grid; + height: 35px; + place-content: center + } + + .already-donate { + display: none + } + + .added-to-cart .already-donate { + display: flex !important + } + + .added-to-cart .addToCart, + .added-to-cart .donate-now, + .added-to-cart .price-details:not(.d-flex) { + display: none !important + } + + .font-weight-semibold { + font-family: Greta-AR-LT-Semibold + } + + .skeleton-box { + background-color: #efefef; + display: inline-block; + height: 1em; + overflow: hidden; + position: relative + } + + .skeleton-box:after { + animation: shimmer 1s infinite; + background-image: linear-gradient(90deg, hsla(0, 0%, 100%, 0), hsla(0, 0%, 100%, .2) 20%, hsla(0, 0%, 100%, .5) 60%, hsla(0, 0%, 100%, 0)); + content: ""; + inset: 0; + position: absolute; + transform: translateX(-100%) + } + + @keyframes shimmer { + to { + transform: translateX(100%) + } + } + + :root { + --mp-result-border-radius: 10px + } + + .bs-popover-start>.popover-arrow { + block-size: 1rem; + inline-size: .5rem; + inset-inline-start: 100% + } + + .bs-popover-start>.popover-arrow:after { + border-inline-start-color: #fff; + border-width: .5rem .5rem .5rem 0; + inset-inline-start: -1px + } + + .bs-popover-start>.popover-arrow:before { + border-inline-start-color: #d9d9d9; + border-width: .5rem .5rem .5rem 0; + inset-inline-end: 0 + } + + @media screen and (orientation: landscape) { + .offcanvas.offcanvas-start.w-75 { + width: 50% !important + } + } + + .subsidy-card-cotrols .d-flex { + display: flex !important + } + + .apple-pay-button { + -apple-pay-button-type: donate; + -webkit-appearance: -apple-pay-button; + display: inline-block; + width: 100% + } + + .apple-pay-button-black { + -apple-pay-button-style: #000 + } + + .apple-pay-button-white { + -apple-pay-button-style: #fff + } + + .apple-pay-button-white-with-line { + -apple-pay-button-style: white-outline + } +} \ No newline at end of file diff --git a/odex25_donation/p_donation_theme/static/src/xml/donation.xml b/odex25_donation/p_donation_theme/static/src/xml/donation.xml new file mode 100644 index 000000000..0e4aca105 --- /dev/null +++ b/odex25_donation/p_donation_theme/static/src/xml/donation.xml @@ -0,0 +1,48 @@ + + + + + + + + diff --git a/odex25_donation/p_donation_theme/views/templates.xml b/odex25_donation/p_donation_theme/views/templates.xml new file mode 100644 index 000000000..fd595c10b --- /dev/null +++ b/odex25_donation/p_donation_theme/views/templates.xml @@ -0,0 +1,1404 @@ + + + + + Product Item Grid: Donation Style + qweb + theme_prime.product_item_grid_3 + + +
+ + +
+ + +
+
+
+
+
+
+
+ +
+
Target
+
+ + +
+
+
+
+
+
+
Amount
+
+ + + +
+
+
+ +
+
+
  
+
  
+
+
+
+
+
+ +
+
Remaining
+
+ + +
+
+
+
+
+
+
+
+ + + + + + + +
+
+
+ + + + +
+
Valid Amount!
+
Invalid Amount!
+
+
+
+
+ +
+ + + + + + + +
+ + + + +

+ +
+
+ +
+
+ + + shop_layout: Donation Style + qweb + p_donation_theme.shop_layout + + + + + row row-cols-#{1 if _config_product_item.get('style') == '3' else 2} + row-cols-md-#{ppr >= 3 and 3 or ppr} row-cols-lg-#{ppr} g-2 g-lg-3 mt-0 + + + + + + + + + + + + + + +
diff --git a/odex25_donation/p_donation_theme/views/templates.zip b/odex25_donation/p_donation_theme/views/templates.zip new file mode 100644 index 000000000..e1e8cb2d9 Binary files /dev/null and b/odex25_donation/p_donation_theme/views/templates.zip differ diff --git a/odex25_donation/p_donation_theme/views/views.xml b/odex25_donation/p_donation_theme/views/views.xml new file mode 100644 index 000000000..55a81499d --- /dev/null +++ b/odex25_donation/p_donation_theme/views/views.xml @@ -0,0 +1,68 @@ + + + + + product.template.form.inherit + product.template + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + extrafield.sale.order.form.view + sale.order + + + + + + + + + + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/odex25_donation/payment_applepay/COPYRIGHT b/odex25_donation/payment_applepay/COPYRIGHT new file mode 100644 index 000000000..56f3bddc4 --- /dev/null +++ b/odex25_donation/payment_applepay/COPYRIGHT @@ -0,0 +1,3 @@ +This module and its content is copyright of Technaureus Info Solutions Pvt. Ltd. - © Technaureus Info Solutions Pvt. Ltd 2020. All rights reserved. +Any redistribution or reproduction of part or all of the contents in any form is prohibited other than your personal use. +You may not, except with our express written permission, distribute or commercially exploit the content. diff --git a/odex25_donation/payment_applepay/LICENSE b/odex25_donation/payment_applepay/LICENSE new file mode 100644 index 000000000..7a5c68e71 --- /dev/null +++ b/odex25_donation/payment_applepay/LICENSE @@ -0,0 +1,27 @@ +Odoo Proprietary License v1.0 + +This software and associated files (the "Software") may only be used (executed, +modified, executed after modifications) if you have purchased a valid license +from the authors, typically via Odoo Apps, or if you have received a written +agreement from the authors of the Software (see the COPYRIGHT file). + +You may develop Odoo modules that use the Software as a library (typically +by depending on it, importing it and using its resources), but without copying +any source code or material from the Software. You may distribute those +modules under the license of your choice, provided that this license is +compatible with the terms of the Odoo Proprietary License (For example: +LGPL, MIT, or proprietary licenses similar to this one). + +It is forbidden to publish, distribute, sublicense, or sell copies of the Software +or modified copies of the Software. + +The above copyright notice and this permission notice must be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/odex25_donation/payment_applepay/__init__.py b/odex25_donation/payment_applepay/__init__.py new file mode 100644 index 000000000..10f2feb85 --- /dev/null +++ b/odex25_donation/payment_applepay/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# This module and its content is copyright of Technaureus Info Solutions Pvt. Ltd. +# - © Technaureus Info Solutions Pvt. Ltd 2020. All rights reserved. + +from . import models +from . import controllers + diff --git a/odex25_donation/payment_applepay/__manifest__.py b/odex25_donation/payment_applepay/__manifest__.py new file mode 100644 index 000000000..3c8de5c3f --- /dev/null +++ b/odex25_donation/payment_applepay/__manifest__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# This module and its content is copyright of Technaureus Info Solutions Pvt. Ltd. +# - © Technaureus Info Solutions Pvt. Ltd 2020. All rights reserved. + +{ + 'name': 'Hyperpay Payment Acquirer - Applepay', + 'category': 'Accounting', + 'version': '15.0.0.1', + 'summary': 'Payment Acquirer: Applepay', + 'author': 'Technaureus Info Solutions Pvt. Ltd.', + 'sequence': 1, + 'website': 'http://www.technaureus.com/', + 'description': """Applepay Payment Acquirer""", + 'price': 79.99, + 'currency': 'EUR', + 'license': 'Other proprietary', + 'depends': ['payment'], + 'data': [ + 'views/payment_views.xml', + 'views/payment_popup_template.xml', + 'views/payment_applepay_templates.xml', + 'data/payment_acquirer_data.xml', + ], + 'images': ['images/main_screenshot.gif'], + 'installable': True, +} diff --git a/odex25_donation/payment_applepay/controllers/__init__.py b/odex25_donation/payment_applepay/controllers/__init__.py new file mode 100644 index 000000000..ba2379bf6 --- /dev/null +++ b/odex25_donation/payment_applepay/controllers/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# This module and its content is copyright of Technaureus Info Solutions Pvt. Ltd. +# - © Technaureus Info Solutions Pvt. Ltd 2020. All rights reserved. + +from . import main diff --git a/odex25_donation/payment_applepay/controllers/main.py b/odex25_donation/payment_applepay/controllers/main.py new file mode 100644 index 000000000..251eca97f --- /dev/null +++ b/odex25_donation/payment_applepay/controllers/main.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# This module and its content is copyright of Technaureus Info Solutions Pvt. Ltd. +# - © Technaureus Info Solutions Pvt. Ltd 2020. All rights reserved. + +import json +import logging +import pprint + +import requests +import werkzeug +from werkzeug import urls + +from odoo import http, _ +from odoo.addons.payment.models.payment_provider import ValidationError +from odoo.http import request +from odoo.exceptions import UserError, Warning + +_logger = logging.getLogger(__name__) + + +class ApplepayController(http.Controller): + + @http.route('/payment/applepay/return', type='http', auth='public', csrf=False) + def applepay_return(self, **post): + """ applepay.""" + acquirer = request.env['payment.provider'].sudo().search([('code', '=', 'applepay')], limit=1) + _logger.info("acquirer......applepay%s" % (acquirer.state)) + _logger.info("Post Return = %s" % (post)) + if post.get('resourcePath'): + if acquirer.state == 'test': + url = "https://eu-test.oppwa.com" + else: + url = "https://eu-prod.oppwa.com" + url += post.get('resourcePath') + url += '?entityId=' + acquirer.applepay_entity_id + authorization_bearer = "Bearer " + acquirer.applepay_authorization_bearer + _logger.info("Url = %s",url) + _logger.info("Headers = %s",authorization_bearer) + try: + headers = {'Authorization': authorization_bearer} + + response = requests.get( + url, + headers=headers, + ) + response = json.loads(response.text) + except Exception as e: + raise UserError(_(e)) + _logger.info( + 'applepay: entering form_feedback with post data %s', pprint.pformat(post)) + _logger.info("Response = %s",response) + payment = request.env['payment.transaction'].sudo() + tx_id = payment.search([('applepay_checkout_id', '=', post.get('id',''))]) + #tx_sudo = request.env['payment.transaction'].sudo(). + #response.update({'tx_id': tx}) + _logger.info("Tx Sudo = %s",tx_id) + tx = response.get('customParameters',{}).get('SHOPPER_tx_id') or tx_id or '' + response.update({'tx_id': tx}) + #tx = response.get('customParameters',{}).get('SHOPPER_tx_id') or tx_sudo and tx_sudo.id or '' + #response.update({'tx_id': tx}) + + tx._handle_notification_data('applepay', response) + return werkzeug.utils.redirect(f'/payment/status') + + @http.route('/shop/applepay/payment/', type='http', auth="none", methods=['POST'], csrf=False) + def _payment_applepay_card(self, **kw): + acquirer = request.env['payment.provider'].sudo().search([('code', '=', 'applepay')], limit=1) + + kw['currency'] = 'SAR' + _logger.info("Post Values From Apple Payment = %s",kw) + + if acquirer.state == 'test': + return request.render("payment_applepay.payment_applepay_card", + {'check_out_id': kw.get('check_out_id'), 'return_url': kw.get('applepay_return')}) + else: + return request.render("payment_applepay.payment_applepay_card_live", + {'check_out_id': kw.get('check_out_id'), 'return_url': kw.get('applepay_return')}) diff --git a/odex25_donation/payment_applepay/data/payment_acquirer_data.xml b/odex25_donation/payment_applepay/data/payment_acquirer_data.xml new file mode 100644 index 000000000..eee41e03f --- /dev/null +++ b/odex25_donation/payment_applepay/data/payment_acquirer_data.xml @@ -0,0 +1,22 @@ + + + + + + Applepay + + applepay + + + You will be redirected to the applepay payment form after clicking on the payment button.

]]>
+ dummy + dummy +
+ + Applepay + applepay + inbound + +
+
diff --git a/odex25_donation/payment_applepay/images/main_screenshot.gif b/odex25_donation/payment_applepay/images/main_screenshot.gif new file mode 100644 index 000000000..0eaf1a23e Binary files /dev/null and b/odex25_donation/payment_applepay/images/main_screenshot.gif differ diff --git a/odex25_donation/payment_applepay/models/__init__.py b/odex25_donation/payment_applepay/models/__init__.py new file mode 100644 index 000000000..817d0e5d4 --- /dev/null +++ b/odex25_donation/payment_applepay/models/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# This module and its content is copyright of Technaureus Info Solutions Pvt. Ltd. +# - © Technaureus Info Solutions Pvt. Ltd 2020. All rights reserved. + +from . import payment +from . import payment_transaction +from . import account_payment_method diff --git a/odex25_donation/payment_applepay/models/account_payment_method.py b/odex25_donation/payment_applepay/models/account_payment_method.py new file mode 100644 index 000000000..4843301aa --- /dev/null +++ b/odex25_donation/payment_applepay/models/account_payment_method.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, models + + +class AccountPaymentMethod(models.Model): + _inherit = 'account.payment.method' + + @api.model + def _get_payment_method_information(self): + res = super()._get_payment_method_information() + res['applepay'] = {'mode': 'unique', 'domain': [('type', '=', 'bank')]} + return res diff --git a/odex25_donation/payment_applepay/models/payment copy.py b/odex25_donation/payment_applepay/models/payment copy.py new file mode 100644 index 000000000..c3262b66a --- /dev/null +++ b/odex25_donation/payment_applepay/models/payment copy.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +# This module and its content is copyright of Technaureus Info Solutions Pvt. Ltd. +# - © Technaureus Info Solutions Pvt. Ltd 2020. All rights reserved. + +import json +import re +import logging +from odoo.exceptions import UserError + +from urllib.parse import urljoin +from odoo import api, fields, models, _ +from odoo.addons.payment.models.payment_provider import ValidationError +import requests + +from odoo.http import request + +_logger = logging.getLogger(__name__) + + +class AcquirerApplepay(models.Model): + _inherit = 'payment.provider' + + code = fields.Selection(selection_add=[('applepay', 'applepay')], ondelete={'applepay': 'set default'}) + + applepay_entity_id = fields.Char(string='Merchant ID/Entity Id', required_if_provider='applepay', + groups='base.group_user') + applepay_authorization_bearer = fields.Char( + string='Authorization Bearer', required_if_provider='applepay', groups='base.group_user') + + @api.model + def _get_authorize_urls(self): + base_url = self.get_base_url() + """ ApplePay URLS """ + return base_url + 'shop/applepay/payment/' + + def _partner_split_name(self, partner_name): + return [' '.join(partner_name.split()[:-1]), ' '.join(partner_name.split()[-1:])] + + def _get_authenticate_apple_pay(self, values): + url = "https://eu-test.oppwa.com/v1/checkouts" if self.state == 'test' else "https://eu-prod.oppwa.com/v1/checkouts" + authorization_bearer = "Bearer " + self.applepay_authorization_bearer + currency = self.env['res.currency'].browse(values['currency_id']) + partner = self.env['res.partner'].browse(values['partner_id']) + last_name = self._partner_split_name(partner.name)[1] + _logger.info(">>%s" % (authorization_bearer)) + data = { + 'entityId': self.applepay_entity_id, + 'amount': str(format(values['amount'], '.2f')), + 'currency': 'SAR', + 'paymentType': 'DB', + 'merchantTransactionId': values.get('reference'), + 'customer.email': partner.email, + 'customer.givenName': partner.name, + 'customer.companyName': partner.company_id.name, + 'customer.phone': partner.phone, + 'billing.street1': partner.street, + 'billing.state': partner.state_id.name, + 'billing.country': partner.country_id.code, + 'billing.postcode': partner.zip, + 'customer.surname': last_name + + } + try: + headers = {'Authorization': authorization_bearer} + response = requests.post( + url, + headers=headers, + data=data + ) + response = json.loads(response.text) + _logger.info("Info From Authorization = %s " % (response)) + return response.get('id') + except Exception as e: + raise UserError(_(e)) + + def applepay_form_generate_values(self, values): + currency = self.env['res.currency'].browse(values['currency_id']) + base_url = self.get_base_url() + check_out_id = self._get_authenticate_apple_pay(values) + _logger.info(">>%s" % (self.applepay_authorization_bearer)) + authorization_bearer = "Bearer " + self.applepay_authorization_bearer + applepay_tx_values = dict(values) + applepay_tx_values.update({ + 'entityId': self.applepay_entity_id, + 'check_out_id': check_out_id, + 'Authorization': authorization_bearer, + 'amount': str(format(values['amount'], '.2f')), + 'currency': currency.id and currency.name or '', + 'paymentBrand': 'APPLEPAY', + 'paymentType': 'DB', + 'merchantTransactionId': values.get('reference'), + 'shopperResultUrl': '%s' % urljoin(base_url, '/shop/applepay/payment/'), + 'applepay_return': '%s' % urljoin(base_url, '/payment/applepay/return'), + 'custom': json.dumps({'return_url': '%s' % applepay_tx_values.pop('return_url')}) if applepay_tx_values.get( + 'return_url') else False, + }) + return applepay_tx_values + #New method added to core + def _get_default_payment_method_id(self,code): + provider_method_id = self._get_provider_payment_method(code) + if provider_method_id: + return provider_method_id.id + return self.env.ref('payment_applepay.payment_method_applepay').id + + #def _get_default_payment_method_id(self): + # self.ensure_one() + # if self.provider != 'applepay': + # return super()._get_default_payment_method_id() + # return self.env.ref('payment_applepay.payment_method_applepay').id + + def applepay_get_form_action_url(self): + self.ensure_one() + environment = 'prod' if self.state == 'enabled' else 'test' + return self._get_authorize_urls_apple_pay(environment)['url'] + + @api.model + def _get_compatible_providers(self, *args, currency_id=None, **kwargs): + """ Override of payment to unlist PayPal providers when the currency is not supported. """ + providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs) + + currency = self.env['res.currency'].browse(currency_id).exists() + #if currency and currency.name: + + # providers = providers.filtered(lambda p: p.code != 'applepay') + + return providers \ No newline at end of file diff --git a/odex25_donation/payment_applepay/models/payment.py b/odex25_donation/payment_applepay/models/payment.py new file mode 100644 index 000000000..add388870 --- /dev/null +++ b/odex25_donation/payment_applepay/models/payment.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +# This module and its content is copyright of Technaureus Info Solutions Pvt. Ltd. +# - © Technaureus Info Solutions Pvt. Ltd 2020. All rights reserved. + +import json +import re +import logging +import random +from odoo.exceptions import UserError + +from urllib.parse import urljoin +from odoo import api, fields, models, _ +from odoo.addons.payment.models.payment_provider import ValidationError +import requests + +from odoo.http import request + +_logger = logging.getLogger(__name__) + + +class AcquirerApplepay(models.Model): + _inherit = 'payment.provider' + + code = fields.Selection(selection_add=[('applepay', 'applepay')], ondelete={'applepay': 'set default'}) + + applepay_entity_id = fields.Char(string='Merchant ID/Entity Id', required_if_provider='applepay', + groups='base.group_user') + applepay_authorization_bearer = fields.Char( + string='Authorization Bearer', required_if_provider='applepay', groups='base.group_user') + + @api.model + def _get_authorize_urls(self): + base_url = self.get_base_url() + """ ApplePay URLS """ + return base_url + 'shop/applepay/payment/' + + def _partner_split_name(self, partner_name): + if partner_name: + return [' '.join(partner_name.split()[:-1]), ' '.join(partner_name.split()[-1:])] + else: + return ['', ''] + + def _get_authenticate_apple_pay(self, values): + url = "https://eu-test.oppwa.com/v1/checkouts" if self.state == 'test' else "https://eu-prod.oppwa.com/v1/checkouts" + authorization_bearer = "Bearer " + self.applepay_authorization_bearer + # currency = self.env['res.currency'].browse(values['currency_id']) + partner = self.env['res.partner'].sudo().browse(values['partner_id']).sudo() + order_no = values.get('reference', '').split('-', 1) + partner_name = partner.name or '' + partner_mobile = partner.mobile or '' + if order_no: + order_id = request.env['sale.order'].sudo().search([('name', '=', order_no[0])], limit=1).sudo() + if order_id: + partner_mobile = order_id.order_mobile_number + partner_name = order_id.order_name + last_name = self._partner_split_name(partner_name)[-1] if partner_name else '' + _logger.info(">>%s" % (authorization_bearer)) + + data = { + 'entityId': self.applepay_entity_id, + 'amount': str(format(values['amount'], '.2f')), + 'currency': 'SAR', + 'paymentType': 'DB', + 'merchantTransactionId': values.get('reference'), + 'customer.email': '{seq}@ensan.sa'.format(seq=random.randint(0,10000)), + 'customer.givenName': partner_name or 'guest', + 'customer.companyName': partner.company_id.name, + 'customer.phone': partner_mobile, + 'billing.street1': partner.street or 'Riyadh', + 'billing.state': partner.state_id.name or 'Riyadh', + 'billing.country': partner.country_id.code or 'SA', + 'billing.postcode': partner.zip, + 'customer.surname': last_name or 'guest' + + } + try: + headers = {'Authorization': authorization_bearer} + response = requests.post( + url, + headers=headers, + data=data + ) + response = json.loads(response.text) + _logger.info("Info From Authorization = %s ",response) + return response.get('id') + except Exception as e: + raise UserError(_(e)) + + def applepay_form_generate_values(self, values): + currency = self.env['res.currency'].browse(values['currency_id']) + base_url = self.get_base_url() + check_out_id = self._get_authenticate_apple_pay(values) + _logger.info(">>%s" % (self.applepay_authorization_bearer)) + authorization_bearer = "Bearer " + self.applepay_authorization_bearer + applepay_tx_values = dict(values) + applepay_tx_values.update({ + 'entityId': self.applepay_entity_id, + 'check_out_id': check_out_id, + 'Authorization': authorization_bearer, + 'amount': str(format(values['amount'], '.2f')), + 'currency': currency.id and currency.name or '', + 'paymentBrand': 'APPLEPAY', + 'paymentType': 'DB', + 'merchantTransactionId': values.get('reference'), + 'shopperResultUrl': '%s' % urljoin(base_url, '/shop/applepay/payment/'), + 'applepay_return': '%s' % urljoin(base_url, '/payment/applepay/return'), + 'custom': json.dumps({'return_url': '%s' % applepay_tx_values.pop('return_url')}) if applepay_tx_values.get( + 'return_url') else False, + }) + return applepay_tx_values + #New method added to core + def _get_default_payment_method_id(self,code): + provider_method_id = self._get_provider_payment_method(code) + if provider_method_id: + return provider_method_id.id + return self.env.ref('payment_applepay.payment_method_applepay').id + + #def _get_default_payment_method_id(self): + # self.ensure_one() + # if self.provider != 'applepay': + # return super()._get_default_payment_method_id() + # return self.env.ref('payment_applepay.payment_method_applepay').id + + def applepay_get_form_action_url(self): + self.ensure_one() + environment = 'prod' if self.state == 'enabled' else 'test' + return self._get_authorize_urls_apple_pay(environment)['url'] + + @api.model + def _get_compatible_providers(self, *args, currency_id=None, **kwargs): + """ Override of payment to unlist PayPal providers when the currency is not supported. """ + providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs) + + currency = self.env['res.currency'].browse(currency_id).exists() + #if currency and currency.name: + + # providers = providers.filtered(lambda p: p.code != 'applepay') + + return providers diff --git a/odex25_donation/payment_applepay/models/payment_before_email_patch.py b/odex25_donation/payment_applepay/models/payment_before_email_patch.py new file mode 100644 index 000000000..fbc5efbe4 --- /dev/null +++ b/odex25_donation/payment_applepay/models/payment_before_email_patch.py @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- +# This module and its content is copyright of Technaureus Info Solutions Pvt. Ltd. +# - © Technaureus Info Solutions Pvt. Ltd 2020. All rights reserved. + +import json +import re +import logging +from odoo.exceptions import UserError + +from urllib.parse import urljoin +from odoo import api, fields, models, _ +from odoo.addons.payment.models.payment_provider import ValidationError +import requests + +from odoo.http import request + +_logger = logging.getLogger(__name__) + + +class AcquirerApplepay(models.Model): + _inherit = 'payment.provider' + + code = fields.Selection(selection_add=[('applepay', 'applepay')], ondelete={'applepay': 'set default'}) + + applepay_entity_id = fields.Char(string='Merchant ID/Entity Id', required_if_provider='applepay', + groups='base.group_user') + applepay_authorization_bearer = fields.Char( + string='Authorization Bearer', required_if_provider='applepay', groups='base.group_user') + + @api.model + def _get_authorize_urls(self): + base_url = self.get_base_url() + """ ApplePay URLS """ + return base_url + 'shop/applepay/payment/' + + def _partner_split_name(self, partner_name): + if partner_name: + return [' '.join(partner_name.split()[:-1]), ' '.join(partner_name.split()[-1:])] + else: + return ['', ''] + + def _get_authenticate_apple_pay(self, values): + url = "https://eu-test.oppwa.com/v1/checkouts" if self.state == 'test' else "https://eu-prod.oppwa.com/v1/checkouts" + authorization_bearer = "Bearer " + self.applepay_authorization_bearer + # currency = self.env['res.currency'].browse(values['currency_id']) + partner = self.env['res.partner'].sudo().browse(values['partner_id']).sudo() + order_no = values.get('reference', '').split('-', 1) + partner_name = partner.name or '' + partner_mobile = partner.mobile or '' + if order_no: + order_id = request.env['sale.order'].sudo().search([('name', '=', order_no[0])], limit=1).sudo() + if order_id: + partner_mobile = order_id.order_mobile_number + partner_name = order_id.order_name + last_name = self._partner_split_name(partner_name)[-1] if partner_name else '' + _logger.info(">>%s" % (authorization_bearer)) + + data = { + 'entityId': self.applepay_entity_id, + 'amount': str(format(values['amount'], '.2f')), + 'currency': 'SAR', + 'paymentType': 'DB', + 'merchantTransactionId': values.get('reference'), + 'customer.email': partner.email, + 'customer.givenName': partner_name or 'guest', + 'customer.companyName': partner.company_id.name, + 'customer.phone': partner_mobile, + 'billing.street1': partner.street or 'Riyadh', + 'billing.state': partner.state_id.name or 'Riyadh', + 'billing.country': partner.country_id.code or 'SA', + 'billing.postcode': partner.zip, + 'customer.surname': last_name or 'guest' + + } + try: + headers = {'Authorization': authorization_bearer} + response = requests.post( + url, + headers=headers, + data=data + ) + response = json.loads(response.text) + _logger.info("Info From Authorization = %s ",response) + return response.get('id') + except Exception as e: + raise UserError(_(e)) + + def applepay_form_generate_values(self, values): + currency = self.env['res.currency'].browse(values['currency_id']) + base_url = self.get_base_url() + check_out_id = self._get_authenticate_apple_pay(values) + _logger.info(">>%s" % (self.applepay_authorization_bearer)) + authorization_bearer = "Bearer " + self.applepay_authorization_bearer + applepay_tx_values = dict(values) + applepay_tx_values.update({ + 'entityId': self.applepay_entity_id, + 'check_out_id': check_out_id, + 'Authorization': authorization_bearer, + 'amount': str(format(values['amount'], '.2f')), + 'currency': currency.id and currency.name or '', + 'paymentBrand': 'APPLEPAY', + 'paymentType': 'DB', + 'merchantTransactionId': values.get('reference'), + 'shopperResultUrl': '%s' % urljoin(base_url, '/shop/applepay/payment/'), + 'applepay_return': '%s' % urljoin(base_url, '/payment/applepay/return'), + 'custom': json.dumps({'return_url': '%s' % applepay_tx_values.pop('return_url')}) if applepay_tx_values.get( + 'return_url') else False, + }) + return applepay_tx_values + #New method added to core + def _get_default_payment_method_id(self,code): + provider_method_id = self._get_provider_payment_method(code) + if provider_method_id: + return provider_method_id.id + return self.env.ref('payment_applepay.payment_method_applepay').id + + #def _get_default_payment_method_id(self): + # self.ensure_one() + # if self.provider != 'applepay': + # return super()._get_default_payment_method_id() + # return self.env.ref('payment_applepay.payment_method_applepay').id + + def applepay_get_form_action_url(self): + self.ensure_one() + environment = 'prod' if self.state == 'enabled' else 'test' + return self._get_authorize_urls_apple_pay(environment)['url'] + + @api.model + def _get_compatible_providers(self, *args, currency_id=None, **kwargs): + """ Override of payment to unlist PayPal providers when the currency is not supported. """ + providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs) + + currency = self.env['res.currency'].browse(currency_id).exists() + #if currency and currency.name: + + # providers = providers.filtered(lambda p: p.code != 'applepay') + + return providers \ No newline at end of file diff --git a/odex25_donation/payment_applepay/models/payment_transaction.py b/odex25_donation/payment_applepay/models/payment_transaction.py new file mode 100644 index 000000000..2b4b6164d --- /dev/null +++ b/odex25_donation/payment_applepay/models/payment_transaction.py @@ -0,0 +1,95 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import logging + +from werkzeug import urls +import re +from odoo import _, api, models,fields +from odoo.exceptions import ValidationError +from odoo.tools.float_utils import float_compare + +from odoo.addons.payment_applepay.controllers.main import ApplepayController + +_logger = logging.getLogger(__name__) + + +class PaymentTransaction(models.Model): + _inherit = 'payment.transaction' + + applepay_checkout_id = fields.Char('Checkout Id', groups='base.group_user', help='Unique checkout id for every applepay transasction') + + def _get_specific_rendering_values(self, processing_values): + res = super()._get_specific_rendering_values(processing_values) + if self.provider_code != 'applepay': + return res + + base_url = self.provider_id.get_base_url() + rendering_values = self.provider_id.applepay_form_generate_values(processing_values) + tx = self.env['payment.transaction'].sudo().search([('reference', '=', self.reference)]) + tx.applepay_checkout_id = rendering_values.get('check_out_id') + rendering_values.update({ + 'api_url': self.provider_id._get_authorize_urls(), + "txId": tx.id, + 'reference':self.reference + }) + return rendering_values + + + def _get_tx_from_notification_data(self, provider_code, notification_data): + if provider_code != 'applepay': + return tx + _logger.info("Notification Data = %s",notification_data) + reference = notification_data.get('ndc') + tx_id = notification_data.get('tx_id') + tx = tx_id and self.sudo().browse(int(tx_id)) + if not tx or len(tx) > 1: + error_msg = _('received data for reference %s') % (pprint.pformat(reference)) + if not tx: + error_msg += _('; no order found') + else: + error_msg += _('; multiple order found') + _logger.info(error_msg) + raise ValidationError(error_msg) + return tx + + def _process_notification_data(self, data): + super()._process_notification_data(data) + if self.provider_code != 'applepay': + return + + status_code = data.get('result').get('code') + success_regex_1 = re.compile(r'000\.000\.|000\.100\.1|000\.[36]').search(status_code) + success_regex_2 = re.compile(r'000\.400\.0[^3]|000\.400\.100').search(status_code) + pending_regex_1 = re.compile(r'000\.200').search(status_code) + pending_regex_2 = re.compile(r'800\.400\.5|100\.400\.500').search(status_code) + error_regex_1 = re.compile(r'000\.100\.2').search(status_code) + if success_regex_1 or success_regex_2: + success_message = data.get('result').get('description') or 'success' + logger_msg = _('applepay:' + success_message) + _logger.info(logger_msg) + self.write({ + 'provider_reference': data.get('id'), + }) + self._set_done() + return True + elif pending_regex_1 or pending_regex_2: + pending_message = data.get('result').get('description') or 'pending' + logger_msg = _('applepay:' + pending_message) + _logger.info(logger_msg) + self.write({'provider_reference': data.get('id')}) + self._set_pending() + return True + elif error_regex_1: + error_message = data.get('result').get('description') or 'error' + error = _('applepay:' + error_message) + _logger.info(error) + self.write({'state_message': error}) + self._set_canceled() + return False + else: + cancel_message = data.get('result').get('description') or 'cancel' + logger_msg = _('applepay:' + cancel_message) + _logger.info(logger_msg) + self.write({'provider_reference': data.get('id')}) + self._set_canceled() + return True diff --git a/odex25_donation/payment_applepay/static/description/1.png b/odex25_donation/payment_applepay/static/description/1.png new file mode 100644 index 000000000..b49e0cfaf Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/1.png differ diff --git a/odex25_donation/payment_applepay/static/description/applepay_sc_02.png b/odex25_donation/payment_applepay/static/description/applepay_sc_02.png new file mode 100644 index 000000000..b03593690 Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/applepay_sc_02.png differ diff --git a/odex25_donation/payment_applepay/static/description/applepay_sc_03.png b/odex25_donation/payment_applepay/static/description/applepay_sc_03.png new file mode 100644 index 000000000..54db459b5 Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/applepay_sc_03.png differ diff --git a/odex25_donation/payment_applepay/static/description/applepay_sc_05.png b/odex25_donation/payment_applepay/static/description/applepay_sc_05.png new file mode 100644 index 000000000..cc3f9a3ba Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/applepay_sc_05.png differ diff --git a/odex25_donation/payment_applepay/static/description/hyperpay_sc_01.png b/odex25_donation/payment_applepay/static/description/hyperpay_sc_01.png new file mode 100644 index 000000000..213c53779 Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/hyperpay_sc_01.png differ diff --git a/odex25_donation/payment_applepay/static/description/hyperpay_sc_02.png b/odex25_donation/payment_applepay/static/description/hyperpay_sc_02.png new file mode 100644 index 000000000..61c7f86ce Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/hyperpay_sc_02.png differ diff --git a/odex25_donation/payment_applepay/static/description/hyperpay_sc_03.png b/odex25_donation/payment_applepay/static/description/hyperpay_sc_03.png new file mode 100644 index 000000000..c14a63edd Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/hyperpay_sc_03.png differ diff --git a/odex25_donation/payment_applepay/static/description/hyperpay_sc_04.png b/odex25_donation/payment_applepay/static/description/hyperpay_sc_04.png new file mode 100644 index 000000000..4e24e1ae2 Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/hyperpay_sc_04.png differ diff --git a/odex25_donation/payment_applepay/static/description/hyperpay_sc_05.png b/odex25_donation/payment_applepay/static/description/hyperpay_sc_05.png new file mode 100644 index 000000000..d90eab541 Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/hyperpay_sc_05.png differ diff --git a/odex25_donation/payment_applepay/static/description/icon.png b/odex25_donation/payment_applepay/static/description/icon.png new file mode 100644 index 000000000..98ecdcb9e Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/icon.png differ diff --git a/odex25_donation/payment_applepay/static/description/index.html b/odex25_donation/payment_applepay/static/description/index.html new file mode 100644 index 000000000..d0b0297b5 --- /dev/null +++ b/odex25_donation/payment_applepay/static/description/index.html @@ -0,0 +1,89 @@ +
+

Applepay Payment Acquirer

+
+ +
+
+

This module integrates Odoo to Applepay Payment Gateway

+

Adding Credentials

+
Enter the Merchant Id/ Entity Id
+
Enter the Authorization Bearer.
+
+

+
+ +
+
+
Add journal
+
+

+
+ +
+
+



+

Applepay payment button in the website

+
Select Applepay for payment.
+
+

+
+ +
+
+
+

+
+ +
+
+

Payment Confirmation.

+
+

+
+ +
+
+ +
+
+ +
+
+

Help and Support

+

For support, new features and customizations.

+
+ +
+ +
+
+ +
+
\ No newline at end of file diff --git a/odex25_donation/payment_applepay/static/description/logo.png b/odex25_donation/payment_applepay/static/description/logo.png new file mode 100644 index 000000000..199b115af Binary files /dev/null and b/odex25_donation/payment_applepay/static/description/logo.png differ diff --git a/odex25_donation/payment_applepay/static/src/img/applepay_icon.png b/odex25_donation/payment_applepay/static/src/img/applepay_icon.png new file mode 100644 index 000000000..952dcf2bd Binary files /dev/null and b/odex25_donation/payment_applepay/static/src/img/applepay_icon.png differ diff --git a/odex25_donation/payment_applepay/views/payment_applepay_templates.xml b/odex25_donation/payment_applepay/views/payment_applepay_templates.xml new file mode 100644 index 000000000..4c07c8605 --- /dev/null +++ b/odex25_donation/payment_applepay/views/payment_applepay_templates.xml @@ -0,0 +1,78 @@ + + + + + + diff --git a/odex25_donation/payment_applepay/views/payment_popup_template.xml b/odex25_donation/payment_applepay/views/payment_popup_template.xml new file mode 100644 index 000000000..ce29a318b --- /dev/null +++ b/odex25_donation/payment_applepay/views/payment_popup_template.xml @@ -0,0 +1,80 @@ + + + + + + + \ No newline at end of file diff --git a/odex25_donation/payment_applepay/views/payment_views.xml b/odex25_donation/payment_applepay/views/payment_views.xml new file mode 100644 index 000000000..0f0567447 --- /dev/null +++ b/odex25_donation/payment_applepay/views/payment_views.xml @@ -0,0 +1,19 @@ + + + + + + acquirer.form.applepay + payment.provider + + + + + + + + + + + + diff --git a/odex25_donation/payment_hyperpay/.gitignore b/odex25_donation/payment_hyperpay/.gitignore new file mode 100644 index 000000000..f53e4af05 --- /dev/null +++ b/odex25_donation/payment_hyperpay/.gitignore @@ -0,0 +1,2 @@ +**/__pycache__ +*.pyc diff --git a/odex25_donation/payment_hyperpay/.idea/.gitignore b/odex25_donation/payment_hyperpay/.idea/.gitignore new file mode 100644 index 000000000..26d33521a --- /dev/null +++ b/odex25_donation/payment_hyperpay/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/odex25_donation/payment_hyperpay/.idea/inspectionProfiles/profiles_settings.xml b/odex25_donation/payment_hyperpay/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 000000000..105ce2da2 --- /dev/null +++ b/odex25_donation/payment_hyperpay/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/odex25_donation/payment_hyperpay/.idea/misc.xml b/odex25_donation/payment_hyperpay/.idea/misc.xml new file mode 100644 index 000000000..f662c2b3e --- /dev/null +++ b/odex25_donation/payment_hyperpay/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/odex25_donation/payment_hyperpay/.idea/modules.xml b/odex25_donation/payment_hyperpay/.idea/modules.xml new file mode 100644 index 000000000..bae327838 --- /dev/null +++ b/odex25_donation/payment_hyperpay/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/odex25_donation/payment_hyperpay/.idea/payment_hyperpay.iml b/odex25_donation/payment_hyperpay/.idea/payment_hyperpay.iml new file mode 100644 index 000000000..d0876a78d --- /dev/null +++ b/odex25_donation/payment_hyperpay/.idea/payment_hyperpay.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/odex25_donation/payment_hyperpay/LICENSE b/odex25_donation/payment_hyperpay/LICENSE new file mode 100644 index 000000000..b53403939 --- /dev/null +++ b/odex25_donation/payment_hyperpay/LICENSE @@ -0,0 +1,398 @@ +SOFTWARE LICENCE AGREEMENT +========================== + +This AGREEMENT is made effective on the date of the purchase of the software +between Webkul Software Pvt. Ltd.,Company incorporated under the Companies +Act, 1956 (hereinafter referred to as “Licensor"), and the purchaser of the +software/ product (hereinafter referred to as "Licensee"). + + +Preamble +-------- + +Licensor is a web and mobile product based organization engaged in the +business of developing and marketing software for enterprise level e-commerce +businesses. It is an ISO and NSR (NASSCOM) certified organization having a +team of more than 150 creative engineers which come from different +backgrounds. It has developed more than 700 web extensions and apps in the +past few years for open source platforms which are used and trusted globally. +Licensee now wishes to obtain license, and Licensor wishes to grant a license, +to allow use of the software so purchased in developing the e-commerce +business website/ mobile app of the Licensee, subject to the terms and +conditions set forth herein. + +THEREFORE, with the intent to be legally bound, the parties hereby agree as +follows: + + +Agreement +--------- + +1.DEFINITIONS. +As used in this Agreement, the following capitalized terms +shall have the definitions set forth below: + +"Derivative Works" are works developed by Licensee, its officers, agents, +contractors or employees, which are based upon, in whole or in part, the +Source Code and/or the Documentation and may also be based upon and/or +incorporate one or more other preexisting works of the Licensor. Derivative +Works may be any improvement, revision, modification, translation (including +compilation or recapitulation by computer), abridgment, condensation, +expansion, or any other form in which such a preexisting work may be recast, +transformed, or adapted. For purposes hereof, a Derivative Work shall also +include any compilation that incorporates such a preexisting work. + +"Documentation" is written, printed or otherwise recorded or stored (digital +or paper) material relating to the Software and/or Source Code, including +technical specifications and instructions for its use including Software/ +Source Code annotations and other descriptions of the principles of its +operation and instructions for its use. + +"Improvements" shall mean, with respect to the Software, all modifications and +changes made, developed, acquired or conceived after the date hereof and +during the entire term of this Agreement. + +"Source Code" is the computer programming source code form of the Software in +the form maintained by the Licensor, and includes all non-third-party +executables, libraries, components, and Documentation created or used in the +creation, development, maintenance, and support of the Software as well as all +updates, error corrections and revisions thereto provided by Licensor, in +whole or in part. + + +2.SOFTWARE LICENSE. + +(a)Grant of License. For the consideration set forth below, Licensor hereby +grants to Licensee, and Licensee hereby accepts the worldwide, non-exclusive, +perpetual, royalty-free rights and licenses set forth below: + +(i)The right and license to use and incorporate the software, in whole or in +part, to develop its website/ mobile app (including the integration of all or +part of the Licensor’s software into Licensee's own software) on one domain ( +Except Joomla modules , listed on store are entitled to be used on unlimited +domain as per the standard guidelines ) only, solely for the own personal or +business use of the Licensee. However, the License does not authorize the +Licensee to compile, copy or distribute the said Software or its Derivative +Works. + +(ii)The right and license does not authorize the Licensee to share any backup +or archival copies of the Software and / or the Source Code and Documentation +on any public internet space including github , stackoverflow etc . The +Licensee must ensure that the backup are not accessible to any other person +and the Licensee must prevent copying / use of source code by any unauthorized +persons. + +(iii)The right and license does not authorize the Licensee to migrate the +domain license to another domain. + +(iv)Our Joomla extensions are published under the GNU/GPL. + + +(b)Scope; Rights and Responsibilities. + +(i)Licensor shall enable the Licensee to download one complete copy of the +Software. + +(ii)The Software is intended for the sole use of the Licensee in development +of its own website/ mobile app. + +(iii)Licensee does not have the right to hand over, sell, distribute, +sub-license, rent, lease or lend any portion of the Software or Documentation, +whether modified or unmodified, to anyone. Licensee should not place the +Software on a server so that it becomes accessible via a public network such +as the Internet for distribution purposes. In case the Licensee is using any +source code management system like github, it can use the code there only when +it has paid subscription from such management system. + +(iv) In case the Licensee purchases the module and allow the third party +development agency to customize as per its need, it is at liberty to do so +subject to the condition that the Licensee as well as the Agency are not +authorized to sell the modified version of the extension. Except for the +required customization purposes, Licensee is not authorized to release the +Source Code, Derivative Work source code and/or Documentation to any third +party, which shall be considered as violation of the Agreement, inter-alia +entailing forthwith termination and legal action. + + +(c)Ownership. + +(i)Software and Source Code. All right, title, copyright, and interest in the +Software, Source Code, Software Modifications and Error corrections will be +and remain the property of Licensor. + +(ii)Derivative Works. As creation of Derivative Works by the Licensee is +prohibited, thus, all right, title, copyright, and interest in any and/or all +Derivative Works and Improvements created by, or on behalf of, Licensee will +also be deemed to the property of Licensor. Licensor shall be entitled to +protect copyright / intellectual property in all such Derivative Works and +Improvements also in any country as it may deem fit including without +limitation seeking copyright and/or patent protection. + + +3.CONSIDERATION. + +(a)Licensee shall pay to Licensor the amount as mentioned on the website from +where the order is placed, as one-time, upfront fees in consideration for the +licenses and rights granted hereunder (hereinafter referred to as the "License +Fee"). The License Fee to be paid by Licensee shall be paid upfront at the +time of placing the order, and no credit will be allowed under any +circumstances. + +(b)Once paid, the License Fees shall be non-refundable. The Licensee has fully +satisfied itself about the Software and has seen the demonstration, and only +thereafter has placed the order. Thus, the License Fees or any part thereof is +non-refundable. No claim for refund of the Licence Fees shall be entertained +under any circumstances. + + +4.REPRESENTATIONS AND WARRANTIES. + +(a)Mutual. Each of the parties represents and warrants to the other as +follows. + +(i)such party is a legal entity duly organized, validly existing and in good +standing; + +(ii)such party has the power and authority to conduct its business as +presently conducted and to enter into, execute, deliver and perform this +Agreement. + +(iii)This Agreement has been duly and validly accepted by such party and +constitutes the legal, valid and binding obligations of such party +respectively, enforceable against such party in accordance with their +respective terms; + +(iv)the acceptance, execution, delivery and performance of this Agreement does +not and will not violate such party's charter or by-laws; nor require any +consent, authorization, approval, exemption or other action by any third party +or governmental entity. + + +(b)Licensor warrants that, at the time of purchase of the Software: + +the Software will function materially as set forth in the website or published +functionality provided by Licensor to customers and potential customers +describing the Software; and + +Software add-ons, if purchased by the Licensee from the Licensor, will not +materially diminish the features or functions of or the specifications of the +Software as they existed as of the execution of this Agreement. + + +(c)Title. Licensor represents and warrants that it is the exclusive owner of +all copyright/ intellectual property in the Software (including the Source +Code) and has good and marketable title to the Software (including the Source +Code) free and clear of all liens, claims and encumbrances of any nature +whatsoever (collectively, "Liens"). Licensor's grant of license and rights to +Licensee hereunder does not, and will not infringe any third party's property, +intellectual property or personal rights. + + +5.TERM. + +(a)Subject to Licensee's payment obligations, this Agreement shall commence as +on the date of making payment of the Software by the Licensee to the Licensor, +and shall continue until terminated by either party. + +(b)The Licensor retains the right to terminate the license at any time, if the +Licensee is not abiding by any of the terms of the Agreement. The Licensee may +terminate the Agreement at any time at its own discretion by uninstalling the +Software and /or by destroying the said Software (or any copies thereof). +However, the Licensee shall not be entitled to seek any refund of the amount +paid by it to the Licensor, under any circumstances. + +(c)Survival. In the event this Agreement is terminated for any reason, the +provisions set forth in Sections 2(a), 2(b), and 2(c) shall survive. + + +6.INDEMNIFICATION. + +The Licensee release the Licensor from, and agree to indemnify, defend and +hold harmless the Licensor (and its officers, directors, employees, agents and +Affiliates) against, any claim, loss, damage, settlement, cost, taxes, expense +or other liability (including, without limitation, attorneys' fees) (each, a +"Claim") arising from or related to: (a) any actual or alleged breach of any +obligations in this Agreement; (b) any refund, adjustment, or return of +Software,(c) any claim for actual or alleged infringement of any Intellectual +Property Rights made by any third party or damages related thereto; or (d) +Taxes. + + +7.LIMITATION OF LIABILITY. + +The Licensor will not be liable for any direct, indirect, incidental, special, +consequential or exemplary damages, including but not limited to, damages for +loss of profits, goodwill, use, data or other intangible losses arising out of +or in connection with the Software, whether in contract, warranty, tort etc. ( +including negligence, software liability, any type of civil responsibility or +other theory or otherwise) to the Licensee or any other person for cost of +software, cover, recovery or recoupment of any investment made by the Licensee +or its affiliates in connection with this Agreement, or for any other loss of +profit, revenue, business, or data or punitive or consequential damages +arising out of or relating to this Agreement. Further, the aggregate liability +of the Licensor, arising out of or in connection with this Agreement or the +transactions contemplated hereby will not exceed at any time, or under any +circumstances, the total amounts received by the Licensor from the Licensee in +connection with the particular software giving rise to the claim. + + +8.FORCE MAJEURE. + +The Licensor will not be liable for any delay or failure to perform any of its +obligations under this Agreement by reasons, events or other matters beyond +its reasonable control. + + +9.RELATIONSHIP OF PARTIES. + +The Licensor and Licensee are independent legal entities, and nothing in this +Agreement will be construed to create a partnership, joint venture, +association of persons, agency, franchise, sales representative, or employment +relationship between the parties. The Licensee will have no authority to make +or accept any offers or representations on behalf of the Licensor. The +relationship between the parties is that of Licensor and Licensee only, and +the rights, duties, liabilities of each party shall be governed by this +Agreement. + + +10.MODIFICATION. + +The Licensor may amend any of the terms and conditions contained in this +Agreement at any time and solely at its discretion. Any changes will be +effective upon the posting of such changes on the Portal/ website, and the +Licensee is responsible for reviewing these changes and informing itself of +all applicable changes or notices. The continued use of a software by the +Licensee after posting of any changes by the Licensor, will constitute the +acceptance of such changes or modifications by the Licensee. + + +11.MISCELLANEOUS. + +(a)General Provisions. This Agreement: (i) may be amended only by a writing +signed by each of the parties; (ii) may be executed in several counterparts, +each of which shall be deemed an original but all of which shall constitute +one and the same instrument; (iii) contains the entire agreement of the +parties with respect to the transactions contemplated hereby and supersedes +all prior written and oral agreements, and all contemporaneous oral +agreements, relating to such transactions; (iv) shall be governed by, and +construed and enforced in accordance with, the laws of India; and (v) shall be +binding upon, and inure to the benefit of, the parties and their respective +successors and permitted assigns. Each of the parties hereby irrevocably +submits to the jurisdiction of the Courts at Delhi, India, for the purposes of +any action or proceeding arising out of or relating to this Agreement or the +subject matter hereof and brought by any other party. + +(b)Assignment. Except for the purpose of customization as mentioned in clause +2(b)(iv) above, Licensee cannot assign, pledge or otherwise transfer, whether +by operation of law or otherwise, this Agreement, or any of its obligations +hereunder, without the prior written consent of Licensor, which consent shall +not be unreasonably withheld. + +(c)Notices. Unless otherwise specifically provided herein, all notices, +consents, requests, demands and other communications required or permitted +hereunder: + +(i)shall be in writing; + +(ii)shall be sent by messenger, certified or registered mail/email, or +reliable express delivery service, to the appropriate address(es) set forth +below; and + +(iii)shall be deemed to have been given on the date of receipt by the +addressee, as evidenced by a receipt executed by the addressee (or a +responsible person in his or her office), the records of the Party delivering +such communication or a notice to the effect that such addressee refused to +claim or accept such communication, if sent by messenger, mail or express +delivery service. + +All such communications shall be sent to the following addresses or numbers, +or to such other addresses or numbers as any party may inform the others by +giving five days' prior notice: + +If to Webkul Software Pvt. Ltd.: + +Webkul Software Pvt. Ltd. +A-67, Sector 63, NOIDA – 201301, +Uttar Pradesh, India + +If to Licensee: +At the address mentioned by the Licensee +(at the time of placing order of generating Invoice) + +(d)Severability. It is the intent of the parties that the provisions of this +Agreement be enforced to the fullest extent permissible under the laws and +public policies of India in which enforcement hereof is sought. In +furtherance of the foregoing, each provision hereof shall be severable from +each other provision, and any provision hereof which is/ becomes unenforceable +shall be subject to the following: (i) if such provision is contrary to or +conflicts with any requirement of any statute, rule or regulation in effect, +then such requirement shall be incorporated into, or substituted for, such +unenforceable provision to the minimum extent necessary to make such provision +enforceable; (ii) the court, agency or arbitrator considering the matter is +hereby authorized to (or, if such court, agency or arbitrator is unwilling or +fails to do so, then the parties shall) amend such provision to the minimum +extent necessary to make such provision enforceable, and the parties hereby +consent to the entry of an order so amending such provision; and (iii) if +any such provision cannot be or is not reformed and made enforceable pursuant +to clause (i) or (ii) above, then such provision shall be ineffective to the +minimum extent necessary to make the remainder of this Agreement enforceable. +Any application of the foregoing provisions to any provision hereof shall not +effect the validity or enforceability of any other provision hereof. + +(e)By purchasing the Software, the Licensee acknowledge that it has read this +Agreement, and that it agrees to the content of the Agreement, its terms and +agree to use the Software in compliance with this Agreement. + +(f)The Licensor holds the sole copyright of the Software. The Software or any +portion thereof is a copyrightable matter and is liable to be protected by the +applicable laws. Copyright infringement in any manner can lead to prosecution +according to the current law. The Licensor reserves the right to revoke the +license of any user who is not holding any license or is holding an invalid +license. + +(g)This Agreement gives the right to use only one copy of the Software on one +domain solely for the own personal or business use of the Licensee, subject to +all the terms and conditions of this Agreement. A separate License has to be +purchased for each new Software installation. Any distribution of the Software +without the written consent of the Licensor (including non-commercial +distribution) is regarded as violation of this Agreement, and will entail +immediate termination of the Agreement and may invite liability, both civil +and criminal, as per applicable laws. + +(h)The Licensor reserves the rights to publish a selected list of users/ +Licensees of its Software, and no permission of any Licensee is needed in this +regard. The Licensee agrees that the Licensor may, in its sole discretion, +disclose or make available any information provided or submitted by the +Licensee or related to it under this Agreement to any judicial, +quasi-judicial, governmental, regulatory or any other authority as may be +required by the Licensor to co-operate and / or comply with any of their +orders, instructions or directions or to fulfill any requirements under +applicable Laws. + +(i)If the Licensee continues to use the Software even after the sending of the +notice by the Licensor for termination, the Licensee agree to accept an +injunction to restrain itself from its further use, and to pay all costs ( +including but not limited to reasonable attorney fees) to enforce injunction +or to revoke the License, and any damages suffered by the Licensor because of +the misuse of the Software by the Licensee. + + +12.ARBITRATION. + +If any dispute arises between the Licensor and the Licensee at any time, in +connection with the validity, interpretation, implementation or alleged breach +of any provision of this Agreement, the same shall be referred to a sole +Arbitrator who shall be an independent and neutral third party appointed +exclusively by the Licensor. The Licensee shall not object to the appointment +of the Arbitrator so appointed by the Licensor. The place of arbitration shall +be Delhi, India. The Arbitration & Conciliation Act, 1996 as amended by The +Arbitration & Conciliation (Amendment) Act, 2015, shall govern the +arbitration proceedings. The arbitration proceedings shall be held in the +English language. + + +This document is an electronic record in terms of Information Technology Act, +2000 and the amended provisions pertaining to electronic records in various +statutes as amended by the Information Technology Act, 2000. This electronic +record is generated by a computer system and does not require any physical or +digital signatures. \ No newline at end of file diff --git a/odex25_donation/payment_hyperpay/__init__.py b/odex25_donation/payment_hyperpay/__init__.py new file mode 100644 index 000000000..2da555886 --- /dev/null +++ b/odex25_donation/payment_hyperpay/__init__.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +################################################################################# +# +# Copyright (c) 2015-Present Webkul Software Pvt. Ltd. () +# +################################################################################# +from . import models +from . import controllers +from . import data diff --git a/odex25_donation/payment_hyperpay/__manifest__.py b/odex25_donation/payment_hyperpay/__manifest__.py new file mode 100644 index 000000000..5a585364d --- /dev/null +++ b/odex25_donation/payment_hyperpay/__manifest__.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +################################################################################# +# Author : Webkul Software Pvt. Ltd. () +# Copyright(c): 2015-Present Webkul Software Pvt. Ltd. +# All Rights Reserved. +# +# +# +# This program is copyright property of the author mentioned above. +# You can`t redistribute it and/or modify it. +# +# +# You should have received a copy of the License along with this program. +# If not, see +################################################################################# +{ + "name" : "Hyperpay Payment Acquirer", + "summary" : """Website Hyper Pay Payment Acquirer""", + "category" : "Website", + "version" : "1.0.0", + "sequence" : 1, + "author" : "Webkul Software Pvt. Ltd.", + "license" : "Other proprietary", + "maintainer" : "Anuj Kumar Chhetri", + "website" : "https://store.webkul.com/odoo-hyperpay-payment-acquirer.html", + "description" : """Odoo Hyperpay Payment Gateway + Payment Gateway + Hyperpay + hyper pay + payment methods + website payment method + Hyperpay integration + Payment acquirer + Payment processing + Payment processor + Website payments + Sale orders payment + Customer payment + Integrate hyperpay payment acquirer in Odoo + Integrate hyperpay payment gateway in Odoo""", + "live_test_url" : "http://odoodemo.webkul.com/?module=payment_hyperpay", + "depends" : ['account', + 'payment', + 'website_sale', + ], + "data" : [ + 'views/payment_views.xml', + 'views/payment_hyperpay_templates.xml', + 'data/payment_acquirer_data.xml', + ], + 'assets' : { + 'web.assets_frontend': ['payment_hyperpay/static/src/css/loader.css'] + }, + "demo" : [], + "images" : ['static/description/banner.gif'], + "application" : True, + "installable" : True, + "price" : 99.0, + "currency" : "USD", +} diff --git a/odex25_donation/payment_hyperpay/controllers/__init__.py b/odex25_donation/payment_hyperpay/controllers/__init__.py new file mode 100644 index 000000000..b32d929ce --- /dev/null +++ b/odex25_donation/payment_hyperpay/controllers/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +################################################################################# +# +# Copyright (c) 2015-Present Webkul Software Pvt. Ltd. () +# +################################################################################# +from . import main diff --git a/odex25_donation/payment_hyperpay/controllers/main.py b/odex25_donation/payment_hyperpay/controllers/main.py new file mode 100644 index 000000000..ea0d56e90 --- /dev/null +++ b/odex25_donation/payment_hyperpay/controllers/main.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +################################################################################# +# +# Copyright (c) 2015-Present Webkul Software Pvt. Ltd. () +# +################################################################################# + +import requests +import werkzeug +from werkzeug import urls +import json +from odoo import http +import urllib +import random +# from odoo.addons.portal.controllers.portal import _build_url_w_params + +#from odoo.addons.payment.controllers.portal import PaymentProcessing +from odoo.addons.website_sale.controllers.main import WebsiteSale +from odoo.http import request +from odoo.addons.payment_hyperpay.data.payment_icon import payment_icon + +import logging +_logger = logging.getLogger(__name__) + +# test_domain = "https://test.oppwa.com" +# live_domain = "https://oppwa.com" +test_domain = "https://eu-test.oppwa.com" +live_domain = "https://eu-prod.oppwa.com" + +def _get_checkout_id(**params): + auth = params.pop('auth', '') + env = params.pop('env') + if env == 'enabled': + domain = live_domain + else: + domain = test_domain + # params['testMode'] = 'EXTERNAL' + url_string = domain + "/v1/checkouts" + + # url = _build_url_w_params(url_string, params) + headers = { + "Authorization" : auth, + } + try: + r = requests.post(url=url_string, data=params, headers=headers) + r = r.json() + if 'parameterErrors' in r.get('result'): + raise Exception + return r + except Exception as e: + return {} + +class HyperPayController(http.Controller): + + @http.route('/payment/hyperpay/checkout/create', type='json', auth='public', csrf=False, website=True) + def create_hyperpay_checkout(self, **post): + _logger.info('--post---%r', post) + tx = request.env['payment.transaction'].sudo().search([('id','=',int(post.get('txId', 0)))]) + final_response = {} + if tx: + base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url') + acq = tx.provider_id + partner_id = tx.partner_id + order_no = tx.reference.split('-', 1) + partner_name = partner_id.name or 'Guest' + partner_mobile = partner_id.mobile or '' + if order_no: + order_id = request.env['sale.order'].sudo().search([('name', '=', order_no[0])], limit=1) + if order_id: + partner_mobile = order_id.order_mobile_number + partner_name = order_id.order_name + kwargs = { + "auth": "Bearer " + acq.hyperpay_authorization, + "entityId": acq.hyperpay_merchant_id, + "amount": '%.2f'%tx.amount, + "currency": tx.currency_id and tx.sudo().currency_id.name or '', + "paymentType": "DB", + "env": acq.state, + "customParameters[SHOPPER_tx_id]": tx.id, + "merchantTransactionId": tx.reference, + "billing.street1": partner_id.street or 'Riyadh', + "billing.street2": partner_id.street2 or '', + "billing.city": partner_id.city or 'Riyadh', + "billing.state": partner_id.state_id.name or 'Riyadh', + "billing.postcode": partner_id.zip or '', + "billing.country": partner_id.country_id.code or 'SA', + "customer.givenName": partner_name, + "customer.surname": '', + "customer.email": '{seq}@ensan.sa'.format(seq=random.randint(0,10000)), + "customer.mobile": partner_mobile, + "customer.phone": partner_id and partner_id.phone or partner_id.mobile or '', + } + resp = _get_checkout_id(**kwargs) + tx.hyperpay_checkout_id = resp.get('id') + domain = live_domain if acq.state == 'enabled' else test_domain + #payment_acq = request.env['payment.acquirer'].sudo() + #hyperpay =payment_acq.search([('name','=','HyperPay')]) + payment_icons = acq.payment_icon_ids.mapped('name') + data_brands = "VISA" + if(len(payment_icon)>1): + brands = [payment_icon[i.upper()] for i in payment_icons if i.upper() in payment_icon.keys()] + data_brands = brands and " ".join(brands) or data_brands + + final_response = { + "checkoutId": resp.get('id',''), + 'domain': domain, + 'base_url': base_url, + 'data_brands':data_brands, + 'acq':acq.id + } + return final_response + + + @http.route('/payment/hyperpay/result', type='http', auth='public', csrf=False,website=True ,save_session=True) + def hyperpay_shopper_result(self, **post): + acq = request.env['payment.provider'].sudo().search([('id', '=', post.get('acq'))]) + if acq.state == 'enabled': + url = live_domain + else: + url = test_domain + url += '/' + post.get('resourcePath')+"?entityId=%s"%(acq.hyperpay_merchant_id) + headers = { + "Authorization" : "Bearer " + acq.hyperpay_authorization, + } + resp = requests.get(url=url, headers=headers).json() + + _logger.info("-----/payment/hyperpay/result-----response------------%r----", resp) + + payment = request.env['payment.transaction'].sudo() + tx_id = payment.search([('hyperpay_checkout_id', '=', post.get('id',''))]) + tx = resp.get('customParameters',{}).get('SHOPPER_tx_id') or tx_id and tx_id.id or '' + resp.update({'tx_id': tx}) + #if tx: + # PaymentProcessing.add_payment_transaction(payment.browse(int(tx))) + + res = tx_id._handle_notification_data('hyperpay',resp) + return werkzeug.utils.redirect(f'/payment/status') diff --git a/odex25_donation/payment_hyperpay/controllers/main_before_email_patch.py b/odex25_donation/payment_hyperpay/controllers/main_before_email_patch.py new file mode 100644 index 000000000..f10c7272b --- /dev/null +++ b/odex25_donation/payment_hyperpay/controllers/main_before_email_patch.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +################################################################################# +# +# Copyright (c) 2015-Present Webkul Software Pvt. Ltd. () +# +################################################################################# + +import requests +import werkzeug +from werkzeug import urls +import json +from odoo import http +import urllib +# from odoo.addons.portal.controllers.portal import _build_url_w_params + +#from odoo.addons.payment.controllers.portal import PaymentProcessing +from odoo.addons.website_sale.controllers.main import WebsiteSale +from odoo.http import request +from odoo.addons.payment_hyperpay.data.payment_icon import payment_icon + +import logging +_logger = logging.getLogger(__name__) + +# test_domain = "https://test.oppwa.com" +# live_domain = "https://oppwa.com" +test_domain = "https://eu-test.oppwa.com" +live_domain = "https://eu-prod.oppwa.com" + +def _get_checkout_id(**params): + auth = params.pop('auth', '') + env = params.pop('env') + if env == 'enabled': + domain = live_domain + else: + domain = test_domain + # params['testMode'] = 'EXTERNAL' + url_string = domain + "/v1/checkouts" + + # url = _build_url_w_params(url_string, params) + headers = { + "Authorization" : auth, + } + try: + r = requests.post(url=url_string, data=params, headers=headers) + r = r.json() + if 'parameterErrors' in r.get('result'): + raise Exception + return r + except Exception as e: + return {} + +class HyperPayController(http.Controller): + + @http.route('/payment/hyperpay/checkout/create', type='json', auth='public', csrf=False, website=True) + def create_hyperpay_checkout(self, **post): + _logger.info('--post---%r', post) + tx = request.env['payment.transaction'].sudo().search([('id','=',int(post.get('txId', 0)))]) + final_response = {} + if tx: + base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url') + acq = tx.provider_id + partner_id = tx.partner_id + order_no = tx.reference.split('-', 1) + partner_name = partner_id.name or 'Guest' + partner_mobile = partner_id.mobile or '' + if order_no: + order_id = request.env['sale.order'].sudo().search([('name', '=', order_no[0])], limit=1) + if order_id: + partner_mobile = order_id.order_mobile_number + partner_name = order_id.order_name + kwargs = { + "auth": "Bearer " + acq.hyperpay_authorization, + "entityId": acq.hyperpay_merchant_id, + "amount": '%.2f'%tx.amount, + "currency": tx.currency_id and tx.sudo().currency_id.name or '', + "paymentType": "DB", + "env": acq.state, + "customParameters[SHOPPER_tx_id]": tx.id, + "merchantTransactionId": tx.reference, + "billing.street1": partner_id.street or 'Riyadh', + "billing.street2": partner_id.street2 or '', + "billing.city": partner_id.city or 'Riyadh', + "billing.state": partner_id.state_id.name or 'Riyadh', + "billing.postcode": partner_id.zip or '', + "billing.country": partner_id.country_id.code or 'SA', + "customer.givenName": partner_name, + "customer.surname": '', + "customer.email": partner_id and partner_id.email or '', + "customer.mobile": partner_mobile, + "customer.phone": partner_id and partner_id.phone or partner_id.mobile or '', + } + resp = _get_checkout_id(**kwargs) + tx.hyperpay_checkout_id = resp.get('id') + domain = live_domain if acq.state == 'enabled' else test_domain + #payment_acq = request.env['payment.acquirer'].sudo() + #hyperpay =payment_acq.search([('name','=','HyperPay')]) + payment_icons = acq.payment_icon_ids.mapped('name') + data_brands = "VISA" + if(len(payment_icon)>1): + brands = [payment_icon[i.upper()] for i in payment_icons if i.upper() in payment_icon.keys()] + data_brands = brands and " ".join(brands) or data_brands + + final_response = { + "checkoutId": resp.get('id',''), + 'domain': domain, + 'base_url': base_url, + 'data_brands':data_brands, + 'acq':acq.id + } + return final_response + + + @http.route('/payment/hyperpay/result', type='http', auth='public', csrf=False,website=True ,save_session=True) + def hyperpay_shopper_result(self, **post): + acq = request.env['payment.provider'].sudo().search([('id', '=', post.get('acq'))]) + if acq.state == 'enabled': + url = live_domain + else: + url = test_domain + url += '/' + post.get('resourcePath')+"?entityId=%s"%(acq.hyperpay_merchant_id) + headers = { + "Authorization" : "Bearer " + acq.hyperpay_authorization, + } + resp = requests.get(url=url, headers=headers).json() + + _logger.info("-----/payment/hyperpay/result-----response------------%r----", resp) + + payment = request.env['payment.transaction'].sudo() + tx_id = payment.search([('hyperpay_checkout_id', '=', post.get('id',''))]) + tx = resp.get('customParameters',{}).get('SHOPPER_tx_id') or tx_id and tx_id.id or '' + resp.update({'tx_id': tx}) + #if tx: + # PaymentProcessing.add_payment_transaction(payment.browse(int(tx))) + + res = tx_id._handle_notification_data('hyperpay',resp) + return werkzeug.utils.redirect(f'/payment/status') diff --git a/odex25_donation/payment_hyperpay/data/__init__.py b/odex25_donation/payment_hyperpay/data/__init__.py new file mode 100644 index 000000000..62d27bc4a --- /dev/null +++ b/odex25_donation/payment_hyperpay/data/__init__.py @@ -0,0 +1 @@ +from . import payment_icon diff --git a/odex25_donation/payment_hyperpay/data/payment_acquirer_data.xml b/odex25_donation/payment_hyperpay/data/payment_acquirer_data.xml new file mode 100644 index 000000000..1d05140fc --- /dev/null +++ b/odex25_donation/payment_hyperpay/data/payment_acquirer_data.xml @@ -0,0 +1,29 @@ + + + + + HyperPay + hyperpay + + + + + test + OGE4Mjk0MTc0ZDA1OTViYjAxNGQwNWQ4MjllNzAxZDF8OVRuSlBjMm45aA== + 8a8294174d0595bb014d05d82e5b01d2 + Testing Credential for Hyperpay Test Mode +
Card Number : 4200000000000000
+
CVV : any 3 digits
+
Expiry Date : any date after today
+ ]]> +
+
+ + HyperPay + hyperpay + inbound + + +
+
diff --git a/odex25_donation/payment_hyperpay/data/payment_icon.py b/odex25_donation/payment_hyperpay/data/payment_icon.py new file mode 100644 index 000000000..699e5d9fd --- /dev/null +++ b/odex25_donation/payment_hyperpay/data/payment_icon.py @@ -0,0 +1,9 @@ +payment_icon = {"VISA":"VISA", +"AMERICAN EXPRESS":"AMEX", +"DINERS CLUB INTERNATIONAL":"DINERS", +"DISCOVER":"DISCOVER", +"JCB":"JCB", +"MAESTRO":"MAESTRO", +"MASTERCARD":"MASTER", +"WESTERN UNION":"WESTERN_UNION", +'AFFIRM': 'AFFIRM', 'AIRPLUS': 'AIRPLUS', 'ALIA': 'ALIA', 'ALIADEBIT': 'ALIADEBIT', 'APPLEPAY': 'APPLEPAY', 'ARGENCARD': 'ARGENCARD', 'BCMC': 'BCMC', 'CABAL': 'CABAL', 'CARNET': 'CARNET', 'CARTEBANCAIRE': 'CARTEBANCAIRE', 'CARTEBLEUE': 'CARTEBLEUE', 'CENCOSUD': 'CENCOSUD', 'DANKORT': 'DANKORT', 'ELO': 'ELO', 'FACILYPAY_3X': 'FACILYPAY_3X', 'FACILYPAY_3XSANSFRAIS': 'FACILYPAY_3XSANSFRAIS', 'FACILYPAY_4X': 'FACILYPAY_4X', 'FACILYPAY_4XSANSFRAIS': 'FACILYPAY_4XSANSFRAIS', 'GOOGLEPAY': 'GOOGLEPAY', 'HIPERCARD': 'HIPERCARD', 'MADA': 'MADA', 'MASTERDEBIT': 'MASTERDEBIT', 'MERCADOLIVRE': 'MERCADOLIVRE', 'NARANJA': 'NARANJA', 'NATIVA': 'NATIVA', 'SERVIRED': 'SERVIRED', 'TARJETASHOPPING': 'TARJETASHOPPING', 'TCARD': 'TCARD', 'TCARDDEBIT': 'TCARDDEBIT', 'VISADEBIT': 'VISADEBIT', 'VISAELECTRON': 'VISAELECTRON', 'VPAY': 'VPAY', 'WORLD': 'WORLD', 'Virtual Account Brands': 'Virtual Account Brands', 'AFTERPAY': 'AFTERPAY', 'ALIPAY': 'ALIPAY', 'APOSTAR': 'APOSTAR', 'ASTROPAY_STREAMLINE_CASH': 'ASTROPAY_STREAMLINE_CASH', 'ASTROPAY_STREAMLINE_OT': 'ASTROPAY_STREAMLINE_OT', 'BALOTO': 'BALOTO', 'BANCOLOMBIA': 'BANCOLOMBIA', 'BBVA_CONTINENTAL': 'BBVA_CONTINENTAL', 'BCP': 'BCP', 'BEVALIDA': 'BEVALIDA', 'BOTON_PSE': 'BOTON_PSE', 'CAJA_AREQUIPA': 'CAJA_AREQUIPA', 'CAJA_CUSCO': 'CAJA_CUSCO', 'CAJA_HUANCAYO': 'CAJA_HUANCAYO', 'CAJA_ICA': 'CAJA_ICA', 'CAJA_PIURA': 'CAJA_PIURA', 'CAJA_TACNA': 'CAJA_TACNA', 'CAJA_TRUJILLO': 'CAJA_TRUJILLO', 'CASHU': 'CASHU', 'CHINAUNIONPAY': 'CHINAUNIONPAY', 'DAOPAY': 'DAOPAY', 'DIMONEX': 'DIMONEX', 'EFECTY': 'EFECTY', 'ENTERPAY': 'ENTERPAY', 'GANA': 'GANA', 'IKANOOI_SE': 'IKANOOI_SE', 'INICIS': 'INICIS', 'INTERBANK': 'INTERBANK', 'KLARNA_PAYMENTS_BILLPAY': 'KLARNA_PAYMENTS_BILLPAY', 'KLARNA_PAYMENTS_PAYLATER': 'KLARNA_PAYMENTS_PAYLATER', 'KLARNA_PAYMENTS_PAYNOW': 'KLARNA_PAYMENTS_PAYNOW', 'KLARNA_PAYMENTS_SLICEIT': 'KLARNA_PAYMENTS_SLICEIT', 'MASTERPASS': 'MASTERPASS', 'MBWAY': 'MBWAY', 'MONEYBOOKERS': 'MONEYBOOKERS', 'MONEYSAFE': 'MONEYSAFE', 'NEQUI': 'NEQUI', 'ONECARD': 'ONECARD', 'PAGO_EFECTIVO': 'PAGO_EFECTIVO', 'PAGO_FACIL': 'PAGO_FACIL', 'PAYBOX': 'PAYBOX', 'PAYDIREKT': 'PAYDIREKT', 'PAYNET': 'PAYNET', 'PAYOLUTION_ELV': 'PAYOLUTION_ELV', 'PAYOLUTION_INS': 'PAYOLUTION_INS', 'PAYOLUTION_INVOICE': 'PAYOLUTION_INVOICE', 'PAYPAL': 'PAYPAL', 'PAYSAFECARD': 'PAYSAFECARD', 'PAYTRAIL': 'PAYTRAIL', 'PF_KARTE_DIRECT': 'PF_KARTE_DIRECT', 'PRZELEWY': 'PRZELEWY', 'PUNTO_RED': 'PUNTO_RED', 'QIWI': 'QIWI', 'RAPI_PAGO': 'RAPI_PAGO', 'RATENKAUF': 'RATENKAUF', 'RED_SERVI': 'RED_SERVI', 'SCOTIABANK': 'SCOTIABANK', 'SENCILLITO': 'SENCILLITO', 'SHETAB': 'SHETAB', 'SIBS_MULTIBANCO': 'SIBS_MULTIBANCO', 'STC_PAY': 'STC_PAY', 'SU_RED': 'SU_RED', 'SU_SUERTE': 'SU_SUERTE', 'TENPAY': 'TENPAY', 'TRUSTLY': 'TRUSTLY', 'WECHAT_PAY': 'WECHAT_PAY','YANDEX': 'YANDEX', 'Bank Account Brands': 'Bank Account Brands', 'BITCOIN': 'BITCOIN', 'BOLETO': 'BOLETO', 'DIRECTDEBIT_SEPA': 'DIRECTDEBIT_SEPA', 'ENTERCASH': 'ENTERCASH', 'EPS': 'EPS', 'GIROPAY': 'GIROPAY', 'IDEAL': 'IDEAL', 'INTERAC_ONLINE': 'INTERAC_ONLINE', 'OXXO': 'OXXO', 'POLI': 'POLI', 'PREPAYMENT': 'PREPAYMENT', 'SADAD': 'SADAD', 'SEPA': 'SEPA', 'SOFORTUEBERWEISUNG': 'SOFORTUEBERWEISUNG', 'TRUSTPAY_VA': 'TRUSTPAY_VA'} diff --git a/odex25_donation/payment_hyperpay/models/__init__.py b/odex25_donation/payment_hyperpay/models/__init__.py new file mode 100644 index 000000000..abf027f7c --- /dev/null +++ b/odex25_donation/payment_hyperpay/models/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +################################################################################# +# +# Copyright (c) 2015-Present Webkul Software Pvt. Ltd. () +# +################################################################################# +from . import payment +from . import acount_payment_method diff --git a/odex25_donation/payment_hyperpay/models/acount_payment_method.py b/odex25_donation/payment_hyperpay/models/acount_payment_method.py new file mode 100644 index 000000000..bba00c83e --- /dev/null +++ b/odex25_donation/payment_hyperpay/models/acount_payment_method.py @@ -0,0 +1,13 @@ +from odoo import api, models +import logging +_logger = logging.getLogger(__name__) + +class AccountPaymentMethod(models.Model): + _inherit = 'account.payment.method' + + @api.model + def _get_payment_method_information(self): + res = super()._get_payment_method_information() + _logger.info("this is res %r",res) + res['hyperpay'] = {'mode': 'unique', 'domain': [('type', '=', 'bank')]} + return res diff --git a/odex25_donation/payment_hyperpay/models/payment.py b/odex25_donation/payment_hyperpay/models/payment.py new file mode 100644 index 000000000..5497c0351 --- /dev/null +++ b/odex25_donation/payment_hyperpay/models/payment.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +################################################################################# +# +# Copyright (c) 2015-Present Webkul Software Pvt. Ltd. () +# +################################################################################# +import re +import logging + +import dateutil.parser +import pytz +from odoo import api, fields, models, _ +from odoo.addons.payment.models.payment_provider import ValidationError +import pprint +from odoo.fields import Datetime + +_logger = logging.getLogger(__name__) + + +class AcquirerHyperPay(models.Model): + _inherit = 'payment.provider' + + code = fields.Selection(selection_add=[('hyperpay', 'HyperPay')],ondelete={'hyperpay': 'set default'}) + hyperpay_authorization = fields.Char('Authorization', required_if_provider='hyperpay', groups='base.group_user', help='Authorization header with Bearer authentication scheme') + hyperpay_merchant_id = fields.Char( + 'Merchant Id', groups='base.group_user', + help='The Merchant ID is required to authorize the request') + + #New method added to core + def _get_default_payment_method_id(self,code): + provider_method_id = self._get_provider_payment_method(code) + if provider_method_id: + return provider_method_id.id + return self.env.ref('account.account_payment_method_manual_in').id + + def hyperpay_form_generate_values(self, values): + hyperpay_tx_values = dict(values) + if values.get('reference','/') != "/": + tx = self.env['payment.transaction'].sudo().search([('reference', '=', values.get('reference'))]) + hyperpay_tx_values.update({ + "txId": tx.id + }) + return hyperpay_tx_values + +class HyperPayPaymentTransaction(models.Model): + _inherit = 'payment.transaction' + + hyperpay_checkout_id = fields.Char('Checkout Id', groups='base.group_user', help='Unique checkout id for every hyper transasction') + + + def _get_specific_rendering_values(self, processing_values): + """ Override of payment to return Alipay-specific rendering values. + Note: self.ensure_one() from `_get_processing_values` + :param dict processing_values: The generic and specific processing values of the transaction + :return: The dict of acquirer-specific processing values + :rtype: dict + """ + res = super()._get_specific_rendering_values(processing_values) + if self.provider_code != 'hyperpay': + return res + + _logger.info('--specific------%r',(processing_values,self.reference)) + hyperpay_tx_values={} + tx = self.env['payment.transaction'].sudo().search([('reference', '=', self.reference)]) + _logger.info('--specific------%r',(processing_values,self.reference,tx.id)) + hyperpay_tx_values.update({ + "txId": tx.id, + 'reference':self.reference + }) + return hyperpay_tx_values + + + @api.model + def _get_tx_from_notification_data(self,provider, data): + reference = data.get('ndc') + tx_id = data.get('tx_id') + tx = tx_id and self.sudo().browse(int(tx_id)) + if not tx or len(tx) > 1: + error_msg = _('received data for reference %s') % (pprint.pformat(reference)) + if not tx: + error_msg += _('; no order found') + else: + error_msg += _('; multiple order found') + _logger.info(error_msg) + raise ValidationError(error_msg) + return tx + + + def _process_notification_data(self, data): + + res = super()._process_notification_data(data) + if self.provider_code != 'hyperpay': + return res + + _logger.info('Validated transfer payment for tx %s: set as pending' % (self.reference)) + result = data.get('result') + result_code = result.get('code') + res ={} + success_pattern = [ + '^(000\.000\.|000\.100\.1|000\.[36])', + '^(000\.400\.0[^3]|000\.400\.100)' + ] + pending_pattern =[ + '^(000\.200)', + '^(800\.400\.5|100\.400\.500)' + ] + _logger.info('------feedback-%r',result) + if re.match(success_pattern[0], result_code) or re.match(success_pattern[1], result_code): + date_validate = dateutil.parser.parse(data.get('timestamp')).astimezone(pytz.utc).replace(tzinfo=None) + res.update(provider_reference=data.get('id'), last_state_change=date_validate, state_message= result.get('description','')) + self._set_done() + elif re.match(pending_pattern[0], result_code) or re.match(pending_pattern[1], result_code): + res.update(state_message= result.get('description','')) + self._set_pending() + elif re.match('/^(000\.100\.2)/', result_code): + res.update(state_message= result.get('description','')) + self._set_error(result.get('description','')) + else: + res.update(state_message= result.get('description','')) + self._set_canceled() + _logger.info('------feedback-%r',(res,self.write(res),self)) + return self.write(res) diff --git a/odex25_donation/payment_hyperpay/static/description/Banner.png b/odex25_donation/payment_hyperpay/static/description/Banner.png new file mode 100644 index 000000000..7345ca59b Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/Banner.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/Odoo1.jpg b/odex25_donation/payment_hyperpay/static/description/Odoo1.jpg new file mode 100644 index 000000000..79a78e783 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/Odoo1.jpg differ diff --git a/odex25_donation/payment_hyperpay/static/description/Odoo2.jpg b/odex25_donation/payment_hyperpay/static/description/Odoo2.jpg new file mode 100644 index 000000000..37016b1c0 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/Odoo2.jpg differ diff --git a/odex25_donation/payment_hyperpay/static/description/Odoo3.jpg b/odex25_donation/payment_hyperpay/static/description/Odoo3.jpg new file mode 100644 index 000000000..3e33036a1 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/Odoo3.jpg differ diff --git a/odex25_donation/payment_hyperpay/static/description/Odoo4.jpg b/odex25_donation/payment_hyperpay/static/description/Odoo4.jpg new file mode 100644 index 000000000..3b08b9e02 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/Odoo4.jpg differ diff --git a/odex25_donation/payment_hyperpay/static/description/Odoo5.jpg b/odex25_donation/payment_hyperpay/static/description/Odoo5.jpg new file mode 100644 index 000000000..989fc9594 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/Odoo5.jpg differ diff --git a/odex25_donation/payment_hyperpay/static/description/Odoo6.jpg b/odex25_donation/payment_hyperpay/static/description/Odoo6.jpg new file mode 100644 index 000000000..b57f547a2 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/Odoo6.jpg differ diff --git a/odex25_donation/payment_hyperpay/static/description/Odoo7.jpg b/odex25_donation/payment_hyperpay/static/description/Odoo7.jpg new file mode 100644 index 000000000..e93871010 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/Odoo7.jpg differ diff --git a/odex25_donation/payment_hyperpay/static/description/Old-Banner.png b/odex25_donation/payment_hyperpay/static/description/Old-Banner.png new file mode 100644 index 000000000..32fa12e76 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/Old-Banner.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/banner.gif b/odex25_donation/payment_hyperpay/static/description/banner.gif new file mode 100644 index 000000000..929596979 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/banner.gif differ diff --git a/odex25_donation/payment_hyperpay/static/description/feature-icon-1.png b/odex25_donation/payment_hyperpay/static/description/feature-icon-1.png new file mode 100644 index 000000000..e0b615935 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/feature-icon-1.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/feature-icon-2.png b/odex25_donation/payment_hyperpay/static/description/feature-icon-2.png new file mode 100644 index 000000000..180807a2f Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/feature-icon-2.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/feature-icon-3.png b/odex25_donation/payment_hyperpay/static/description/feature-icon-3.png new file mode 100644 index 000000000..f41397d44 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/feature-icon-3.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/feature-icon-4.png b/odex25_donation/payment_hyperpay/static/description/feature-icon-4.png new file mode 100644 index 000000000..d1c1a6e2c Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/feature-icon-4.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/feature-icon-5.png b/odex25_donation/payment_hyperpay/static/description/feature-icon-5.png new file mode 100644 index 000000000..e3f361f71 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/feature-icon-5.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/feature-icon-6.png b/odex25_donation/payment_hyperpay/static/description/feature-icon-6.png new file mode 100644 index 000000000..707c6a648 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/feature-icon-6.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/feature-icon-7.png b/odex25_donation/payment_hyperpay/static/description/feature-icon-7.png new file mode 100644 index 000000000..88ecbc6d5 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/feature-icon-7.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/hyperpay3.png b/odex25_donation/payment_hyperpay/static/description/hyperpay3.png new file mode 100644 index 000000000..244812313 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/hyperpay3.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/icon-1.png b/odex25_donation/payment_hyperpay/static/description/icon-1.png new file mode 100644 index 000000000..e90fdb7bb Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/icon-1.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/icon-2.png b/odex25_donation/payment_hyperpay/static/description/icon-2.png new file mode 100644 index 000000000..112db0e41 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/icon-2.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/icon-features.png b/odex25_donation/payment_hyperpay/static/description/icon-features.png new file mode 100644 index 000000000..10e23486e Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/icon-features.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/icon-help.png b/odex25_donation/payment_hyperpay/static/description/icon-help.png new file mode 100644 index 000000000..303f9e248 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/icon-help.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/icon-support.png b/odex25_donation/payment_hyperpay/static/description/icon-support.png new file mode 100644 index 000000000..5f9759099 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/icon-support.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/icon-user-guide.png b/odex25_donation/payment_hyperpay/static/description/icon-user-guide.png new file mode 100644 index 000000000..e15905a7a Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/icon-user-guide.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/icon.png b/odex25_donation/payment_hyperpay/static/description/icon.png new file mode 100644 index 000000000..628a1126d Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/icon.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/index.html b/odex25_donation/payment_hyperpay/static/description/index.html new file mode 100644 index 000000000..fd4ac8439 --- /dev/null +++ b/odex25_donation/payment_hyperpay/static/description/index.html @@ -0,0 +1,750 @@ + + + + + + + + + + + +
+

Odoo Hyperpay Payment Acquirer

+

Promote Cashless Payment on the Website Using Odoo HyperPay Payment Acquirer! +

+ +
+
+ Integrate the HyperPay payment gateway with Odoo and make it available to clients as a payment option on your Odoo website. When making purchases from the Odoo website, clients may complete payments quickly and easily thanks to HyperPay integration. +
+ +
+
+ +
+
+
+
+ + + Quick Odoo HyperPay Payment Integration + +
+
+
+

+ Utilize HyperPay credentials to integrate HyperPay Payment Acquirer with your Odoo website to promote a rapid and secure payment gateway. +

+

+ With HyperPay, your clients may now pay for their orders online with a wallet, debit or credit card, or net banking. +

+

+ To ensure faster payments, customers are not transferred to any other pages and the transaction is completed on the Odoo website checkout page. +

+

+ The module also keeps track of all transactions in the backend of Odoo. +

+
+
+
+
+
+
+
+
+
+ + + Now, Accept Payments Using HyperPay From Your Customers! + +
+
+
+

+ As digitization takes hold globally, people's reliance on currency is decreasing. A payment gateway is therefore necessary on a website. +

+

+ As you are well aware, conversions depend on having a trustworthy payment provider that clients can rely on to process payments securely and frequently on your website. +

+
+

+ A cashless society is becoming more prevalent across the world. Integrate HyperPay Payment Acquirer with Odoo to encourage cashless transactions on your Odoo website. +

+
+

+ Having a dependable Payment Gateway can increase the number of people who visit your website. It helps to decrease abandoned carts, which are less common now that there are more payment options available. +

+
+
+
+
+ +
+
+
+ Highlighted-features +
+
+ Below is the detailed list of Feature for Hyperpay Payment Acquirer +
+
+
+
+
+
+
+ +
+
+ + Adaptable, secure, and speedy + +
+
+
+
+
+
+ +
+
+ + Simple installation and configuration + +
+
+
+
+
+
+ +
+
+ + Reduce payment troubles at checkout + +
+
+
+
+
+
+
+
+ +
+
+ + Give clients extra payment choices + +
+
+
+
+
+
+ +
+
+ + Stop shopping cart idling + +
+
+
+
+
+
+ +
+
+ + Favor cashless transactions + +
+
+
+
+
+
+
+
+ +
+
+ + On your Odoo website, lower the COD payment. + +
+
+
+
+
+
+
+
+ +
+
+
+
+

Detailed Features List

+

Below is the list of features Hyperpay Payment Acquirer

+
+ +
+
+

+ Add A New Payment Method To Odoo Website +

+
    +
  • + The module facilitates quick payments for customers on their online orders on Odoo website using HyperPay payment Gateway. +
  • + +
  • + HyperPay Payment shows up as one of the payment methods on the check out page on Odoo website. +
  • +
+
+
+

+ Merchant Authentication +

+
    +
  • The module assigns easy steps for HyperPay Payment acquirer integration with Odoo. +
  • +
  • The admin just needs a Merchant ID and authorization code from HyperPay in Odoo. + +
  • +
+
+
+
+
+

+ Secure And Fast Payment +

+
    +
  • + On selecting HyperPay, the customers are not redirected to any other page. The transaction is completed on the checkout page itself. +
  • + +
  • + The customer needs to fill in the required details to complete the transaction. +
  • + +
  • + After the transaction is complete, the customers are notified on the Odoo website checkout page. +
  • + +
+
+
+

+ Track Transaction History +

+
    +
  • The Odoo admin can see the transaction details of the orders in the Odoo backend. +
  • +
  • The order form shows the details of the mode of payment used by the customer to make the payment for his/her order. +
  • +
  • The list of the transaction is also maintained in the HyperPay merchant portal. +
  • + +
+
+
+
+
+
+
+ +
+
+
+
+

Admin side Payment configuration .

+
+
+ + + +
+
+
+ + + +
+
+
+

Website View

+
+
+

View of the Hyperpay payment button in the website.

+ + + +
+
+
+ + + +
+
+
+

After completion of Payment .

+ + + +
+
+
+

HyperPay Account View

+
+
+
+

Hyperpay gateway homepage

+ + + +
+
+
+

HyperPay Account View

+
+
+

Transaction entry inside gateway .

+ + + +
+
+ + +
+
+
+
+
+
+ +
+ +
+
+
+
+

Support

+

Get Immediate support for any of your query

+
+
+

You will get 90 days free support for any doubt, queries, and bug fixing (excluding data recovery) or any type of issue related to this module.

+
+

+
+
+
+ mail +
+
+

Write To Us At

+ support@webkul.com +

For any help and doubt or issue regarding the module, Drop a mail to our technical team.

+
+ +
+
+
+
+
+ support-icon +
+
+

Raise A Ticket At:

+ https://webkul.uvdesk.com/en/customer/create-ticket/ +

For support or to request customization, Create A Support Ticket by copying the link and opening it in a new tab.

+
+
+
+
+
+ + diff --git a/odex25_donation/payment_hyperpay/static/description/mail.png b/odex25_donation/payment_hyperpay/static/description/mail.png new file mode 100644 index 000000000..8f5913e96 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/mail.png differ diff --git a/odex25_donation/payment_hyperpay/static/description/support-icon.png b/odex25_donation/payment_hyperpay/static/description/support-icon.png new file mode 100644 index 000000000..9c1f7e476 Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/description/support-icon.png differ diff --git a/odex25_donation/payment_hyperpay/static/src/css/hyperpay_style.css b/odex25_donation/payment_hyperpay/static/src/css/hyperpay_style.css new file mode 100644 index 000000000..365d4cb3f --- /dev/null +++ b/odex25_donation/payment_hyperpay/static/src/css/hyperpay_style.css @@ -0,0 +1,11 @@ +@-moz-document url-prefix() { + .wpwl-container{ + display: block !important; + } + } +.wpwl-apple-pay-button{-webkit-appearance: -apple-pay-button !important;} +@supports (-moz-appearance:none) { + .wpwl-container{ + display: block !important; + } + } diff --git a/odex25_donation/payment_hyperpay/static/src/css/loader.css b/odex25_donation/payment_hyperpay/static/src/css/loader.css new file mode 100644 index 000000000..27de3f1e0 --- /dev/null +++ b/odex25_donation/payment_hyperpay/static/src/css/loader.css @@ -0,0 +1,78 @@ +.hyperpay_loader { + border: 5px solid #f3f3f3; + border-radius: 50%; + border-top: 5px solid #777777; + width: 50px; + height: 50px; + -webkit-animation: spin 2s linear infinite; /* Safari */ + animation: spin 2s linear infinite; +} +.wpwl-apple-pay-button{-webkit-appearance: -apple-pay-button !important;} +/* Safari */ +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} +.apple-pay-button { + display: inline-block; + -webkit-appearance: -apple-pay-button; + -apple-pay-button-type: donate; /* Use any supported button type. */ +} +.apple-pay-button-black { + -apple-pay-button-style: black; +} +.apple-pay-button-white { + -apple-pay-button-style: white; +} +.apple-pay-button-white-with-line { + -apple-pay-button-style: white-outline; +} +@supports (-webkit-appearance: -apple-pay-button) { + .apple-pay-button { + display: inline-block; + -webkit-appearance: -apple-pay-button; + } + .apple-pay-button-black { + -apple-pay-button-style: black; + + } + .apple-pay-button-white { + -apple-pay-button-style: white; + } + .apple-pay-button-white-with-line { + -apple-pay-button-style: white-outline; + } +} + +@supports not (-webkit-appearance: -apple-pay-button) { + .apple-pay-button { + display: inline-block; + background-size: 100% 60%; + background-repeat: no-repeat; + background-position: 50% 50%; + border-radius: 5px; + padding: 0px; + box-sizing: border-box; + min-width: 200px; + min-height: 32px; + max-height: 64px; + } + .apple-pay-button-black { + background-image: -webkit-named-image(apple-pay-logo-white); + background-color: black; + } + .apple-pay-button-white { + background-image: -webkit-named-image(apple-pay-logo-black); + background-color: white; + } + .apple-pay-button-white-with-line { + background-image: -webkit-named-image(apple-pay-logo-black); + background-color: white; + border: .5px solid black; + } +} \ No newline at end of file diff --git a/odex25_donation/payment_hyperpay/static/src/img/hyperpay-logo.jpg b/odex25_donation/payment_hyperpay/static/src/img/hyperpay-logo.jpg new file mode 100644 index 000000000..be8e3b5ef Binary files /dev/null and b/odex25_donation/payment_hyperpay/static/src/img/hyperpay-logo.jpg differ diff --git a/odex25_donation/payment_hyperpay/static/src/js/hyperpay.js b/odex25_donation/payment_hyperpay/static/src/js/hyperpay.js new file mode 100644 index 000000000..a8041916a --- /dev/null +++ b/odex25_donation/payment_hyperpay/static/src/js/hyperpay.js @@ -0,0 +1,15 @@ +var wpwlOptions = { + onReady: function(){ + var shopOrigin = $('input[name="shopOrigin"]'); + var origin = parent.window.location.origin; + parent_iframe = $('#hyperpay_iframe', window.parent.document); + parent_iframe.css({"width":"100%", "height":"21em", "border":"none", "display":""}); + $('.hyperpay_loader', window.parent.document).remove(); + $('#hyperpay_close', window.parent.document).on('click', function(){ + parent.window.location.reload(true); + }); + if (shopOrigin.length != 0 && shopOrigin.val() == 'null'){ + shopOrigin.val(origin); + } + } + } diff --git a/odex25_donation/payment_hyperpay/static/src/js/payment_hyperpay.js b/odex25_donation/payment_hyperpay/static/src/js/payment_hyperpay.js new file mode 100644 index 000000000..fa46b82d7 --- /dev/null +++ b/odex25_donation/payment_hyperpay/static/src/js/payment_hyperpay.js @@ -0,0 +1,160 @@ +odoo.define('payment_hyperpay.payment_hyperpay', function (require) { + "use strict"; + + var core = require('web.core'); + var Dialog = require('web.Dialog'); + var publicWidget = require('web.public.widget'); + var ajax = require('web.ajax'); + const {assets} = require('@web/core/assets'); + + var qweb = core.qweb; + var _t = core._t; + + if ($.blockUI) { + $.blockUI.defaults.css.border = '0'; + $.blockUI.defaults.css["background-color"] = ''; + $.blockUI.defaults.overlayCSS["opacity"] = '0.5'; + $.blockUI.defaults.overlayCSS["z-index"] = '1050'; + } + + // Reference + // https://dev.to/pulljosh/how-to-load-html-css-and-js-code-into-an-iframe-2blc + const getGeneratedPageURL = ({ html, css, js}) => { + const getBlobURL = (code, type) => { + const blob = new Blob([code], { type }) + return URL.createObjectURL(blob) + } + + const source = ` + + + ${css} + ${js} + + + + + ${html || ''} + + + ` + + return getBlobURL(source, 'text/html') + } + + var HyperpayPaymentForm = publicWidget.Widget.extend({ + init: function() { + this.tx_id = $('.clasic_hyperpay_tx').val(); + this._initBlockUI(_t("Loading...")); + this.start(); + }, + start: function() { + var self = this; + self._createHyperpayCheckoutId(); + }, + _createHyperpayCheckoutId: function() { + var self = this; + ajax.jsonRpc('/payment/hyperpay/checkout/create', 'call', { + 'txId': self.tx_id + }) + .then(function (result) { + if (result) { + self._renderHyperpayModal(result.checkoutId, result.domain, result.base_url,result.data_brands,result.acq); + } else { + console.log('Error Occured'); + } + }); + }, + _renderHyperpayModal: function(checkoutId, domain, base_url,data_brands,acq) { + var self = this; + try{ + var $modal_html = $($('.payment_hyper_modal').get()[0]); + $modal_html.appendTo($('body')).modal({keyboard: false, backdrop: 'static'}); + var style_css = '' + var script = '' + var js_script = '' + var shopperResultUrlTag = '
' +console.log(shopperResultUrlTag); + var theIframe = document.createElement("iframe"); + theIframe.id = "hyperpay_iframe"; + theIframe.style = "display:none"; + var html = script + shopperResultUrlTag; + + const url = getGeneratedPageURL({ + html: html, + css: style_css, + js: js_script + }) + theIframe.src = url; + $('#hyperpay-modal-body')[0].appendChild(theIframe); + $modal_html.modal('show'); + } + catch(err){ + console.log('component error:', err); + } + + }, + _initBlockUI: function(message) { + if ($.blockUI) { + $.blockUI({ + 'message': '

' + + '
' + message + + '

' + }); + } + $("#o_payment_form_pay").attr('disabled', 'disabled'); + }, + + }); + + new HyperpayPaymentForm(); + +}); diff --git a/odex25_donation/payment_hyperpay/static/src/xml/hyperpay.xml b/odex25_donation/payment_hyperpay/static/src/xml/hyperpay.xml new file mode 100644 index 000000000..e346dbb11 --- /dev/null +++ b/odex25_donation/payment_hyperpay/static/src/xml/hyperpay.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/odex25_donation/payment_hyperpay/views/payment_hyperpay_templates.xml b/odex25_donation/payment_hyperpay/views/payment_hyperpay_templates.xml new file mode 100644 index 000000000..af03ade16 --- /dev/null +++ b/odex25_donation/payment_hyperpay/views/payment_hyperpay_templates.xml @@ -0,0 +1,34 @@ + + + + + + diff --git a/odex25_donation/payment_hyperpay/views/payment_views.xml b/odex25_donation/payment_hyperpay/views/payment_views.xml new file mode 100644 index 000000000..d7d651736 --- /dev/null +++ b/odex25_donation/payment_hyperpay/views/payment_views.xml @@ -0,0 +1,19 @@ + + + + + + provider.form.hyperpay + payment.provider + + + + + + + + + + + + diff --git a/odex25_donation/payment_hyperpay/views/website_assets.xml b/odex25_donation/payment_hyperpay/views/website_assets.xml new file mode 100644 index 000000000..33c2de03d --- /dev/null +++ b/odex25_donation/payment_hyperpay/views/website_assets.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/odex25_donation/product_data_feed_brand/LICENSE b/odex25_donation/product_data_feed_brand/LICENSE new file mode 100644 index 000000000..d499adb92 --- /dev/null +++ b/odex25_donation/product_data_feed_brand/LICENSE @@ -0,0 +1,28 @@ +Odoo Proprietary License v1.0 + +This software and associated files (the “Software”) may only be used (executed, +modified, executed after modifications) if you have purchased a valid license +from the authors, typically via Odoo Apps, or if you have received a written +agreement from the authors of the Software (see the COPYRIGHT file). + +You may develop Odoo modules that use the Software as a library (typically by +depending on it, importing it and using its resources), but without copying any +source code or material from the Software. You may distribute those modules +under the license of your choice, provided that this license is compatible with +the terms of the Odoo Proprietary License (For example: LGPL, MIT, or +proprietary licenses similar to this one). + +It is forbidden to publish, distribute, sublicense, or sell copies of the +Software or modified copies of the Software. + +The above copyright notice and this permission notice must be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/odex25_donation/product_data_feed_brand/__init__.py b/odex25_donation/product_data_feed_brand/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/odex25_donation/product_data_feed_brand/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/odex25_donation/product_data_feed_brand/__manifest__.py b/odex25_donation/product_data_feed_brand/__manifest__.py new file mode 100644 index 000000000..4d2c7b2fb --- /dev/null +++ b/odex25_donation/product_data_feed_brand/__manifest__.py @@ -0,0 +1,28 @@ +# Copyright © 2022 Garazd Creation (https://garazd.biz) +# @author: Yurii Razumovskyi (support@garazd.biz) +# @author: Iryna Razumovska (support@garazd.biz) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html). + +{ + 'name': 'Product Brands for Data Feeds', + 'version': '16.0.1.0.0', + 'category': 'eCommerce', + 'author': 'Garazd Creation', + 'website': 'https://garazd.biz/shop', + 'license': 'LGPL-3', + 'summary': 'Manage Product Brands', + 'images': ['static/description/banner.png', 'static/description/icon.png'], + 'live_test_url': 'https://garazd.biz/r/9UY', + 'depends': [ + 'product', + ], + 'data': [ + 'security/ir.model.access.csv', + 'views/product_data_feed_brand_views.xml', + 'views/product_template_views.xml', + ], + 'support': 'support@garazd.biz', + 'application': False, + 'installable': True, + 'auto_install': False, +} diff --git a/odex25_donation/product_data_feed_brand/doc/changelog.rst b/odex25_donation/product_data_feed_brand/doc/changelog.rst new file mode 100644 index 000000000..0f102bd06 --- /dev/null +++ b/odex25_donation/product_data_feed_brand/doc/changelog.rst @@ -0,0 +1,11 @@ +.. _changelog: + +Changelog +========= + +`16.0.1.0.0` +------------ + +- Migration from 15.0. + + diff --git a/odex25_donation/product_data_feed_brand/models/__init__.py b/odex25_donation/product_data_feed_brand/models/__init__.py new file mode 100644 index 000000000..945a39ce9 --- /dev/null +++ b/odex25_donation/product_data_feed_brand/models/__init__.py @@ -0,0 +1,2 @@ +from . import product_data_feed_brand +from . import product_template diff --git a/odex25_donation/product_data_feed_brand/models/product_data_feed_brand.py b/odex25_donation/product_data_feed_brand/models/product_data_feed_brand.py new file mode 100644 index 000000000..3fa1d8654 --- /dev/null +++ b/odex25_donation/product_data_feed_brand/models/product_data_feed_brand.py @@ -0,0 +1,17 @@ +# Copyright © 2022 Garazd Creation () +# @author: Yurii Razumovskyi () +# @author: Iryna Razumovska () +# License OPL-1 (https://www.odoo.com/documentation/14.0/legal/licenses.html). + +from odoo import fields, models, _ + + +class ProductDataFeedBrand(models.Model): + _name = "product.data.feed.brand" + _description = 'Product Brands for Feeds' + + name = fields.Char(translate=True) + + _sql_constraints = [('product_data_feed_brand_uniq', + 'UNIQUE (name)', + 'Product Brand Name must be unique.')] diff --git a/odex25_donation/product_data_feed_brand/models/product_template.py b/odex25_donation/product_data_feed_brand/models/product_template.py new file mode 100644 index 000000000..31df275f8 --- /dev/null +++ b/odex25_donation/product_data_feed_brand/models/product_template.py @@ -0,0 +1,11 @@ +from odoo import fields, models, _ + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + feed_brand_id = fields.Many2one( + comodel_name='product.data.feed.brand', + string='Brand', + ) + diff --git a/odex25_donation/product_data_feed_brand/security/ir.model.access.csv b/odex25_donation/product_data_feed_brand/security/ir.model.access.csv new file mode 100644 index 000000000..cb799e321 --- /dev/null +++ b/odex25_donation/product_data_feed_brand/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_product_data_feed_brand_public_read,access_product_data_feed_brand_public_read,model_product_data_feed_brand,,1,0,0,0 +access_product_data_feed_brand_user,access_product_data_feed_brand_user,model_product_data_feed_brand,base.group_user,1,1,1,0 +access_product_data_feed_brand_admin,access_product_data_feed_brand_admin,model_product_data_feed_brand,base.group_system,1,1,1,1 diff --git a/odex25_donation/product_data_feed_brand/static/description/banner.png b/odex25_donation/product_data_feed_brand/static/description/banner.png new file mode 100644 index 000000000..564b105cc Binary files /dev/null and b/odex25_donation/product_data_feed_brand/static/description/banner.png differ diff --git a/odex25_donation/product_data_feed_brand/static/description/banner_facebook_shop.png b/odex25_donation/product_data_feed_brand/static/description/banner_facebook_shop.png new file mode 100644 index 000000000..051f91c2a Binary files /dev/null and b/odex25_donation/product_data_feed_brand/static/description/banner_facebook_shop.png differ diff --git a/odex25_donation/product_data_feed_brand/static/description/banner_product_data_feed_ceneo_pl.png b/odex25_donation/product_data_feed_brand/static/description/banner_product_data_feed_ceneo_pl.png new file mode 100644 index 000000000..b38490458 Binary files /dev/null and b/odex25_donation/product_data_feed_brand/static/description/banner_product_data_feed_ceneo_pl.png differ diff --git a/odex25_donation/product_data_feed_brand/static/description/banner_product_data_feed_google.png b/odex25_donation/product_data_feed_brand/static/description/banner_product_data_feed_google.png new file mode 100644 index 000000000..d9a1ca2da Binary files /dev/null and b/odex25_donation/product_data_feed_brand/static/description/banner_product_data_feed_google.png differ diff --git a/odex25_donation/product_data_feed_brand/static/description/icon.png b/odex25_donation/product_data_feed_brand/static/description/icon.png new file mode 100644 index 000000000..03d538064 Binary files /dev/null and b/odex25_donation/product_data_feed_brand/static/description/icon.png differ diff --git a/odex25_donation/product_data_feed_brand/static/description/index.html b/odex25_donation/product_data_feed_brand/static/description/index.html new file mode 100644 index 000000000..3aa809972 --- /dev/null +++ b/odex25_donation/product_data_feed_brand/static/description/index.html @@ -0,0 +1,263 @@ +
+
+ +
+
Community
+
+
+
Enterprise
+
+
+
Odoo.sh
+
+ +
+
Odoo.sh
+
Enterprise
+
Community
+
+ +
+
+ +
+
+
Odoo product brand management
+
+
+ +
+
+
+
Description
+
+
Using manufacturer brands for product management in Odoo allows you to structure your warehouse, purchasing and sales processes. It adds one more analytic criteria to use in reports and external analytic services.
+
+
+
+
+ +
+
+
+
Features
+
+
+
+
+
+
+ +
+
Easy & Simple
+

Easy to activate and configure

+
+
+
+
+
+
+
+ +
+
Customize
+

Contact us for improvements and changes.

+
+
+
+
+
+
+
+ +
+
Support
+

Free 30 days support and 180 days bug-fixing

+
+
+
+
+
+
+
+ +
+
Try me
+

Demo & Test. Click on the "Live Preview" button

+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Using
+
+
+ +
+ Go to the menu "Products" and on the "General Information" tab create a new brand or select one of the existing ones. +
+
+ Odoo False Product Brands for Data Feeds +
+
+ The appropriated field will be added to the product list view, and you will be able to group products by brand. +
+
+ Odoo False Product Brands for Data Feeds group by +
+ +
+
+
+
+
+
+ +
+ +
+ +
+
+ +
+
Contact Us
+
Support, customizations, and development
+ +
+ + Skype: + GarazdCreation +
+ +
+ +
+
Our expertise
+
+
+ Odoo Learning Partner +
+
+ OCA Member +
+
+ With Odoo since 2014 +
+
+ Over 6,000 app downloads and purchases +
+
+
+ +
+
Explore our apps
+ +
Watch and subscribe
+ +
+
+ +
+ +
+
+
Version: 16.0.1.0.0
+ + + +
Module design is reserved
Copyright © Garazd Creation
+ +
+
+
    +
  • + +
    +
    16.0.1.0.0 2022-12-12
    +
    Migration from 15.0.
    +
    +
  • +
+
+
+
+
+ diff --git a/odex25_donation/product_data_feed_brand/static/description/product_data_feed_brand.png b/odex25_donation/product_data_feed_brand/static/description/product_data_feed_brand.png new file mode 100644 index 000000000..945d463e3 Binary files /dev/null and b/odex25_donation/product_data_feed_brand/static/description/product_data_feed_brand.png differ diff --git a/odex25_donation/product_data_feed_brand/static/description/product_data_feed_brand_group.png b/odex25_donation/product_data_feed_brand/static/description/product_data_feed_brand_group.png new file mode 100644 index 000000000..a9be8a3e6 Binary files /dev/null and b/odex25_donation/product_data_feed_brand/static/description/product_data_feed_brand_group.png differ diff --git a/odex25_donation/product_data_feed_brand/views/product_data_feed_brand_views.xml b/odex25_donation/product_data_feed_brand/views/product_data_feed_brand_views.xml new file mode 100644 index 000000000..d9f9226f8 --- /dev/null +++ b/odex25_donation/product_data_feed_brand/views/product_data_feed_brand_views.xml @@ -0,0 +1,19 @@ + + + + + product.data.feed.brand.view.form + product.data.feed.brand + +
+ +
+
+
+
+
+
+ +s
diff --git a/odex25_donation/product_data_feed_brand/views/product_template_views.xml b/odex25_donation/product_data_feed_brand/views/product_template_views.xml new file mode 100644 index 000000000..2955f8a37 --- /dev/null +++ b/odex25_donation/product_data_feed_brand/views/product_template_views.xml @@ -0,0 +1,37 @@ + + + + + product.template.common.form.inherit.product.data.feed.brand + product.template + + + + + + + + + + product.template.product.tree.inherit.product.data.feed.brand + product.template + + + + + + + + + + product.template.search.inherit.product.data.feed.brand + product.template + + + + + + + + + diff --git a/odex25_donation/product_google_category/__init__.py b/odex25_donation/product_google_category/__init__.py new file mode 100644 index 000000000..9b4296142 --- /dev/null +++ b/odex25_donation/product_google_category/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/odex25_donation/product_google_category/__manifest__.py b/odex25_donation/product_google_category/__manifest__.py new file mode 100644 index 000000000..a39909984 --- /dev/null +++ b/odex25_donation/product_google_category/__manifest__.py @@ -0,0 +1,31 @@ +# Copyright © 2021 Garazd Creation (https://garazd.biz) +# @author: Yurii Razumovskyi (support@garazd.biz) +# @author: Iryna Razumovska (support@garazd.biz) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html). + +{ + 'name': 'Google Product Category', + 'version': '16.0.1.1.0', + 'category': 'eCommerce', + 'author': 'Garazd Creation', + 'website': 'https://garazd.biz/shop', + 'license': 'LGPL-3', + 'summary': 'Google Product Categories (Taxonomy) in your products', + 'images': ['static/description/banner.png', 'static/description/icon.png'], + 'live_test_url': 'https://garazd.biz/r/1QZ', + 'depends': [ + 'website_sale', + 'base_import_helper', + ], + 'data': [ + 'security/ir.model.access.csv', + 'views/product_google_category_views.xml', + 'views/product_template_views.xml', + 'wizard/base_import_helper_views.xml', + 'data/ir_action_todo_data.xml', + ], + 'support': 'support@garazd.biz', + 'application': False, + 'installable': True, + 'auto_install': False, +} diff --git a/odex25_donation/product_google_category/data/ir_action_todo_data.xml b/odex25_donation/product_google_category/data/ir_action_todo_data.xml new file mode 100644 index 000000000..b40aabef6 --- /dev/null +++ b/odex25_donation/product_google_category/data/ir_action_todo_data.xml @@ -0,0 +1,11 @@ + + + + + Open Import Wizard + + 100 + open + + + diff --git a/odex25_donation/product_google_category/doc/changelog.rst b/odex25_donation/product_google_category/doc/changelog.rst new file mode 100644 index 000000000..f4cefb32d --- /dev/null +++ b/odex25_donation/product_google_category/doc/changelog.rst @@ -0,0 +1,14 @@ +.. _changelog: + +Changelog +========= + +`16.0.1.1.0` +------------ + +`16.0.1.0.0` +------------ + +- Migration from 15.0. + + diff --git a/odex25_donation/product_google_category/models/__init__.py b/odex25_donation/product_google_category/models/__init__.py new file mode 100644 index 000000000..f857b3d75 --- /dev/null +++ b/odex25_donation/product_google_category/models/__init__.py @@ -0,0 +1,2 @@ +from . import product_google_category +from . import product_template diff --git a/odex25_donation/product_google_category/models/product_google_category.py b/odex25_donation/product_google_category/models/product_google_category.py new file mode 100644 index 000000000..28b43b69f --- /dev/null +++ b/odex25_donation/product_google_category/models/product_google_category.py @@ -0,0 +1,73 @@ +# Copyright © 2021 Garazd Creation () +# @author: Yurii Razumovskyi () +# @author: Iryna Razumovska () +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html). + +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError + + +class ProductGoogleCategory(models.Model): + _name = "product.google.category" + _description = 'Google Product Category' + _parent_store = True + _order = "sequence, name, id" + + name = fields.Char( + string='Name', + required=True, + translate=True, + ) + sequence = fields.Integer(index=True) + code = fields.Char( + string='Code', + required=True, + ) + parent_id = fields.Many2one( + comodel_name='product.google.category', + string='Parent', + index=True, + ondelete="cascade", + ) + parent_path = fields.Char(index=True, unaccent=False) + child_id = fields.One2many( + 'product.google.category', + 'parent_id', + string='Children Categories', + ) + parents_and_self = fields.Many2many( + 'product.google.category', + compute='_compute_parents_and_self', + ) + + @api.constrains('parent_id') + def check_parent_id(self): + if not self._check_recursion(): + raise ValueError(_( + 'Error ! You cannot create recursive categories.')) + + @api.constrains('code') + def _check_code(self): + for category in self: + recs = self.search_count([('code', '=', category.code)]) + if recs > 1: + raise ValidationError(_( + 'The code of the Google category must be unique.')) + + def name_get(self): + res = [] + for category in self: + res.append((category.id, " > ".join( + category.parents_and_self.mapped('name')))) + return res + + def unlink(self): + self.child_id.parent_id = None + return super(ProductGoogleCategory, self).unlink() + + def _compute_parents_and_self(self): + for category in self: + if category.parent_path: + category.parents_and_self = self.env['product.google.category'].browse([int(p) for p in category.parent_path.split('/')[:-1]]) + else: + category.parents_and_self = category diff --git a/odex25_donation/product_google_category/models/product_template.py b/odex25_donation/product_google_category/models/product_template.py new file mode 100644 index 000000000..e464a972a --- /dev/null +++ b/odex25_donation/product_google_category/models/product_template.py @@ -0,0 +1,15 @@ +# Copyright © 2021 Garazd Creation () +# @author: Yurii Razumovskyi () +# @author: Iryna Razumovska () +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html). + +from odoo import fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + google_category_id = fields.Many2one( + comodel_name='product.google.category', + string='Google Category', + ) diff --git a/odex25_donation/product_google_category/security/ir.model.access.csv b/odex25_donation/product_google_category/security/ir.model.access.csv new file mode 100644 index 000000000..c4d025b46 --- /dev/null +++ b/odex25_donation/product_google_category/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_product_google_category_user_read,access_product_google_category_user_read,model_product_google_category,base.group_user,1,0,1,0 +access_product_google_category_admin,access_product_google_category_admin,model_product_google_category,base.group_system,1,1,1,1 diff --git a/odex25_donation/product_google_category/static/description/banner.png b/odex25_donation/product_google_category/static/description/banner.png new file mode 100644 index 000000000..92ccc4d7b Binary files /dev/null and b/odex25_donation/product_google_category/static/description/banner.png differ diff --git a/odex25_donation/product_google_category/static/description/banner_facebook_shop.png b/odex25_donation/product_google_category/static/description/banner_facebook_shop.png new file mode 100644 index 000000000..051f91c2a Binary files /dev/null and b/odex25_donation/product_google_category/static/description/banner_facebook_shop.png differ diff --git a/odex25_donation/product_google_category/static/description/banner_product_data_feed_google.png b/odex25_donation/product_google_category/static/description/banner_product_data_feed_google.png new file mode 100644 index 000000000..d9a1ca2da Binary files /dev/null and b/odex25_donation/product_google_category/static/description/banner_product_data_feed_google.png differ diff --git a/odex25_donation/product_google_category/static/description/banner_website_sale_google_analytics_4.png b/odex25_donation/product_google_category/static/description/banner_website_sale_google_analytics_4.png new file mode 100644 index 000000000..8ca9af4b7 Binary files /dev/null and b/odex25_donation/product_google_category/static/description/banner_website_sale_google_analytics_4.png differ diff --git a/odex25_donation/product_google_category/static/description/icon.png b/odex25_donation/product_google_category/static/description/icon.png new file mode 100644 index 000000000..8256f65ba Binary files /dev/null and b/odex25_donation/product_google_category/static/description/icon.png differ diff --git a/odex25_donation/product_google_category/static/description/index.html b/odex25_donation/product_google_category/static/description/index.html new file mode 100644 index 000000000..1fe52141c --- /dev/null +++ b/odex25_donation/product_google_category/static/description/index.html @@ -0,0 +1,380 @@ +
+
+ +
+
Community
+
+
+
Enterprise
+
+
+
Odoo.sh
+
+ +
+
Odoo.sh
+
Enterprise
+
Community
+
+ +
+
+ +
+
+
+
+

Module Features

+
+
+
+
+ Sync with Google product taxonomy by link +
+
+
+
+ Use for eCommerce with Facebook Shop, Facebook Pixel, and Pinterest Tag modules +
+
+ +
+
+
+
+ +
+
+
Assigning Google product categories to your products in Odoo
+
+
+ +
+
+
+
Description
+
+

The app allows importing predefined Google product categories to your Odoo database. After that you will have a full Google's product taxonomy with the category IDs and the full path of the product category. You can use them to define the "google_product_category" field in your data feed (the additional modules Facebook Catalog Product Feed, Pinterest Tag Catalog Product Data Feed are required).

+ +

Setting of the Google product categories allow improving your Google and Facebook Ads, and bidding on Shopping campaigns. Use for eCommerce with Facebook Shop, Facebook Pixel, and Pinterest Tag modules.

+
+
+
+
+ +
+
+
+
Features
+
+
+
+
+
+
+ +
+
Tested
+

Include unit tests

+
+
+
+
+
+
+
+ +
+
Customize
+

Contact us for improvements and changes.

+
+
+
+
+
+
+
+ +
+
Support
+

Free 30 days support and 180 days bug-fixing

+
+
+
+
+
+
+
+ +
+
Try me
+

Demo & Test. Click on the "Live Preview" button

+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Configuration
+
+
+ +
Import Google Product Categories
+
+ Go to the menu "Website" - "Configuration" - "Import Google Categories" and click on the "Import/Update" button. + +
+
+ Odoo 16.0 Google Product Category import +
+ +
+ +
+ +
View Categories
+
+ After importing go to the "Website" - "eCommerce" - "Products" - "Google Categories" menu to view them. +
+
+ Odoo 16.0 Google Product Category list +
+ +
Set a Google Category
+
+ A Google product category can be specified on the "Sale" tab in the "eCommerce Shop" section on the product form. +
+
+ Odoo 16.0 Google Product Category setting +
+ +
+
+
+
+
+
+ +
+ +
+ +
+ +
+ +
+
+
+
+

Support, customizations, and development

+
+ +
+
+
+ +
+
+ +
+
Contact Us
+
Support, customizations, and development
+ +
+ + Skype: + GarazdCreation +
+ +
+ +
+
Our expertise
+
+
+ Odoo Learning Partner +
+
+ OCA Member +
+
+ With Odoo since 2014 +
+
+ Over 6,000 app downloads and purchases +
+
+
+ +
+
Explore our apps
+ +
Watch and subscribe
+ +
+
+ +
+ +
+
+
Version: 16.0.1.1.0
+ + + +
Module design is reserved
Copyright © Garazd Creation
+ +
+
+
    +
  • + +
    +
    16.0.1.1.0 2023-02-12
    +
    +
  • +
  • + +
    +
    16.0.1.0.0 2022-11-04
    +
    Migration from 15.0.
    +
    +
  • +
+
+
+
+
+ diff --git a/odex25_donation/product_google_category/static/description/product_google_categories.png b/odex25_donation/product_google_category/static/description/product_google_categories.png new file mode 100644 index 000000000..667c51121 Binary files /dev/null and b/odex25_donation/product_google_category/static/description/product_google_categories.png differ diff --git a/odex25_donation/product_google_category/static/description/product_google_categories_16.png b/odex25_donation/product_google_category/static/description/product_google_categories_16.png new file mode 100644 index 000000000..5730890a8 Binary files /dev/null and b/odex25_donation/product_google_category/static/description/product_google_categories_16.png differ diff --git a/odex25_donation/product_google_category/static/description/product_google_category_field.png b/odex25_donation/product_google_category/static/description/product_google_category_field.png new file mode 100644 index 000000000..744641ecc Binary files /dev/null and b/odex25_donation/product_google_category/static/description/product_google_category_field.png differ diff --git a/odex25_donation/product_google_category/static/description/product_google_category_field_16.png b/odex25_donation/product_google_category/static/description/product_google_category_field_16.png new file mode 100644 index 000000000..cb752f2fd Binary files /dev/null and b/odex25_donation/product_google_category/static/description/product_google_category_field_16.png differ diff --git a/odex25_donation/product_google_category/static/description/product_google_category_import.png b/odex25_donation/product_google_category/static/description/product_google_category_import.png new file mode 100644 index 000000000..030839e03 Binary files /dev/null and b/odex25_donation/product_google_category/static/description/product_google_category_import.png differ diff --git a/odex25_donation/product_google_category/static/description/product_google_category_import_16.png b/odex25_donation/product_google_category/static/description/product_google_category_import_16.png new file mode 100644 index 000000000..a28332450 Binary files /dev/null and b/odex25_donation/product_google_category/static/description/product_google_category_import_16.png differ diff --git a/odex25_donation/product_google_category/tests/__init__.py b/odex25_donation/product_google_category/tests/__init__.py new file mode 100644 index 000000000..281408ca6 --- /dev/null +++ b/odex25_donation/product_google_category/tests/__init__.py @@ -0,0 +1 @@ +from . import test_import diff --git a/odex25_donation/product_google_category/tests/test_import.py b/odex25_donation/product_google_category/tests/test_import.py new file mode 100644 index 000000000..7e58d79e2 --- /dev/null +++ b/odex25_donation/product_google_category/tests/test_import.py @@ -0,0 +1,28 @@ +from odoo.tests import tagged +from odoo.tests.common import TransactionCase + + +@tagged('post_install', '-at_install') +class TestProductGoogleCategory(TransactionCase): + + def setUp(self): + super(TestProductGoogleCategory, self).setUp() + self.google_category = self.env['product.google.category'] + self.user = self.env.ref('base.user_demo') + + def test_import_from_url(self): + + wizard = self.env['base_import.helper'].with_user(self.user).create({ + 'mode': 'google_categ', + 'url': 'https://www.google.com/basepages/producttype/taxonomy-with-ids.en-US.txt', + }) + + result = wizard.open_url(wizard.url) + self.assertEqual(result['error'], None) + + wizard.with_user(self.user).action_import() + + self.assertEqual( + self.google_category.search_count([]), + len(result['content'].split('\n')) - 2, # Exclude the 1st and the last lines + ) diff --git a/odex25_donation/product_google_category/views/product_google_category_views.xml b/odex25_donation/product_google_category/views/product_google_category_views.xml new file mode 100644 index 000000000..ea8b6b848 --- /dev/null +++ b/odex25_donation/product_google_category/views/product_google_category_views.xml @@ -0,0 +1,52 @@ + + + + + product.google.category.form + product.google.category + +
+ +
+
+ + + +
+
+
+
+ + + product.google.category.tree + product.google.category + + + + + + + + + + + + + Google Categories + product.google.category + tree,form + + + + +
diff --git a/odex25_donation/product_google_category/views/product_template_views.xml b/odex25_donation/product_google_category/views/product_template_views.xml new file mode 100644 index 000000000..ba56128fc --- /dev/null +++ b/odex25_donation/product_google_category/views/product_template_views.xml @@ -0,0 +1,15 @@ + + + + + product.template.product.website.form.inherit.product.google.category + product.template + + + + + + + + + diff --git a/odex25_donation/product_google_category/wizard/__init__.py b/odex25_donation/product_google_category/wizard/__init__.py new file mode 100644 index 000000000..a5c22fe76 --- /dev/null +++ b/odex25_donation/product_google_category/wizard/__init__.py @@ -0,0 +1 @@ +from . import base_import_helper diff --git a/odex25_donation/product_google_category/wizard/base_import_helper.py b/odex25_donation/product_google_category/wizard/base_import_helper.py new file mode 100644 index 000000000..a04f1f307 --- /dev/null +++ b/odex25_donation/product_google_category/wizard/base_import_helper.py @@ -0,0 +1,72 @@ +import logging +import mimetypes + +from odoo import fields, models, _ +from odoo.exceptions import UserError + +_logger = logging.getLogger(__name__) + + +class ImportHelper(models.TransientModel): + _inherit = 'base_import.helper' + + url = fields.Char( + default='https://www.google.com/basepages/producttype/taxonomy-with-ids.en-US.txt', + help='Specify the Google Taxonomy URL to download a list of all Google product categories (only Plain text .txt)', + required=True, + ) + mode = fields.Selection( + selection_add=[('google_categ', 'Google category')], + ) + + def action_import(self): + self.ensure_one() + if self.mode != 'google_categ': + return super(ImportHelper, self).action_import() + + mimetype, encoding = mimetypes.guess_type(self.url) + if mimetype != 'text/plain': + raise UserError(_('Only the Plain text (.txt) format is allowed.')) + + res = self.open_url(self.url) + if res['error']: + raise UserError(_('Error opening URL: %s') % res['error']) + content = res['content'] + + index = 1 + for line in content.split('\n'): + + # Skip comments + if line[:1] == '#': + continue + + elif line: + code, category = line.split(' - ', 1) + category_hierarchy = category.split(' > ') + vals = { + 'name': category_hierarchy[-1:][0], + 'code': code, + 'sequence': index, + } + if len(category_hierarchy) > 1: + parent_category = self.env['product.google.category'].search([ + ('name', '=', category_hierarchy[-2:-1][0]), + ]) + vals['parent_id'] = parent_category.id + + google_category = self.env['product.google.category'].search([ + ('code', '=', code), + ]) + if not google_category: + self.env['product.google.category'].create(vals) + elif self.do_rewrite: + google_category.write(vals) + index += 1 + + return { + 'name': _('Google Categories'), + 'type': 'ir.actions.act_window', + 'res_model': 'product.google.category', + 'view_mode': 'tree,form', + 'target': 'current', + } diff --git a/odex25_donation/product_google_category/wizard/base_import_helper_views.xml b/odex25_donation/product_google_category/wizard/base_import_helper_views.xml new file mode 100644 index 000000000..994995a4f --- /dev/null +++ b/odex25_donation/product_google_category/wizard/base_import_helper_views.xml @@ -0,0 +1,36 @@ + + + + + base_import.helper.view.form + base_import.helper + + + + Import/Update + + + + + + Import Google product categories + base_import.helper + form + new + { + 'default_mode': 'google_categ', + 'default_url': 'https://www.google.com/basepages/producttype/taxonomy-with-ids.en-US.txt', + 'default_help_url': 'https://support.google.com/merchants/answer/6324436', + } + + + + + diff --git a/odex25_donation/public_user_email_reset/__init__.py b/odex25_donation/public_user_email_reset/__init__.py new file mode 100644 index 000000000..9a7e03ede --- /dev/null +++ b/odex25_donation/public_user_email_reset/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/odex25_donation/public_user_email_reset/__manifest__.py b/odex25_donation/public_user_email_reset/__manifest__.py new file mode 100644 index 000000000..2763ed6ad --- /dev/null +++ b/odex25_donation/public_user_email_reset/__manifest__.py @@ -0,0 +1,11 @@ + +{ + "name": "Public User Email Reset", + "author": "Ritsol Allied", + "version": "16.0", + "depends": ['sale','sale_management'], + "data": + { + + }, +} diff --git a/odex25_donation/public_user_email_reset/models/__init__.py b/odex25_donation/public_user_email_reset/models/__init__.py new file mode 100644 index 000000000..67427f49a --- /dev/null +++ b/odex25_donation/public_user_email_reset/models/__init__.py @@ -0,0 +1 @@ +from . import sale_order \ No newline at end of file diff --git a/odex25_donation/public_user_email_reset/models/sale_order.py b/odex25_donation/public_user_email_reset/models/sale_order.py new file mode 100644 index 000000000..aa28189ae --- /dev/null +++ b/odex25_donation/public_user_email_reset/models/sale_order.py @@ -0,0 +1,21 @@ +from odoo import api, fields, models +from odoo.exceptions import UserError, ValidationError +import random + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + + def action_confirm(self): + res = super(SaleOrder, self).action_confirm() + for rec in self: + partner = rec.env['res.partner'].search([('id','=',4),('active','=',False)]) + partner.email = '{seq}@ensan.sa'.format(seq=random.randint(0,10000)) + partner.phone = rec.order_mobile_number + + + return res + + + diff --git a/odex25_donation/sale_order_line_report/__init__.py b/odex25_donation/sale_order_line_report/__init__.py new file mode 100644 index 000000000..9a7e03ede --- /dev/null +++ b/odex25_donation/sale_order_line_report/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/odex25_donation/sale_order_line_report/__manifest__.py b/odex25_donation/sale_order_line_report/__manifest__.py new file mode 100644 index 000000000..be62084b4 --- /dev/null +++ b/odex25_donation/sale_order_line_report/__manifest__.py @@ -0,0 +1,12 @@ + +{ + 'name': 'sale_order_line_report', + 'version': '16.0', + 'sequence': 1, + 'author': 'Raqmyat.', + 'depends': ['sale','sale_management','p_donation_theme'], + 'data': [ + 'view/sale_order_line_list.xml', + ], + +} \ No newline at end of file diff --git a/odex25_donation/sale_order_line_report/models/__init__.py b/odex25_donation/sale_order_line_report/models/__init__.py new file mode 100644 index 000000000..b4f633669 --- /dev/null +++ b/odex25_donation/sale_order_line_report/models/__init__.py @@ -0,0 +1 @@ +from . import sale_order_line \ No newline at end of file diff --git a/odex25_donation/sale_order_line_report/models/sale_order_line.py b/odex25_donation/sale_order_line_report/models/sale_order_line.py new file mode 100644 index 000000000..6060906af --- /dev/null +++ b/odex25_donation/sale_order_line_report/models/sale_order_line.py @@ -0,0 +1,10 @@ +from odoo import api, models,fields + + + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + order_name= fields.Char(string='Donor Name ', related='order_id.order_name', store =True) + order_mobile_number = fields.Char(string='Donor Number', related='order_id.order_mobile_number', store =True) + date_order= fields.Datetime(string='Order Date', related='order_id.date_order', store =True) diff --git a/odex25_donation/sale_order_line_report/view/sale_order_line_list.xml b/odex25_donation/sale_order_line_report/view/sale_order_line_list.xml new file mode 100644 index 000000000..e476247d0 --- /dev/null +++ b/odex25_donation/sale_order_line_report/view/sale_order_line_list.xml @@ -0,0 +1,49 @@ + + + + + sale.order.line.tree + sale.order.line + + + + + + + + + + + + + + + + + + + + + Sale Order Lines + sale.order.line + tree + + + + sale.order.line.select.inherited + sale.order.line + + + + + + + + + + + + + diff --git a/odex25_donation/sale_order_report/__init__.py b/odex25_donation/sale_order_report/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/odex25_donation/sale_order_report/__manifest__.py b/odex25_donation/sale_order_report/__manifest__.py new file mode 100644 index 000000000..189ad04e9 --- /dev/null +++ b/odex25_donation/sale_order_report/__manifest__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +{ + 'name' : 'sale order report', + 'version' : '1.0', + 'summary': 'sale order report', + + 'description': """ +sale order report +==================== +Customize the sale order report """, + 'depends' : ['sale','sale_management'], + 'data': [ + 'reports/sale_order_report.xml', + + + + ], + "images": ['img/header.png','img/footer.png' ,'img/111.png','img/header2.png'], + 'assets': { + 'web.assets_backend': [ + 'sale_order_report/static/src/css/style.css', + ], + + }, + } diff --git a/odex25_donation/sale_order_report/reports/sale_order_report.xml b/odex25_donation/sale_order_report/reports/sale_order_report.xml new file mode 100644 index 000000000..07fa50d0e --- /dev/null +++ b/odex25_donation/sale_order_report/reports/sale_order_report.xml @@ -0,0 +1,624 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odex25_donation/sale_order_report/static/src/css/style.css b/odex25_donation/sale_order_report/static/src/css/style.css new file mode 100644 index 000000000..75817bcba --- /dev/null +++ b/odex25_donation/sale_order_report/static/src/css/style.css @@ -0,0 +1,21 @@ +.font{ +font-family:'traditional_arabic';;font-weight:100;font-size: 13px; +} + +@font-face { + font-family: 'GretaArabicBold'; + src: url('/sale_order_report/static/src/fonts/Greta-Arabic-AR-LT-Bold.ttf') format('truetype'); + font-weight: bold; + font-style: normal; + } + +@font-face { + font-family: 'GretaArabicRegular'; + src: url('/sale_order_report/static/src/fonts/Greta-Arabic-AR-LT.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +.arabic{ + font-family:GretaArabicRegular !important; +} diff --git a/odex25_donation/sale_order_report/static/src/fonts/DroidKufi-Bold.ttf b/odex25_donation/sale_order_report/static/src/fonts/DroidKufi-Bold.ttf new file mode 100644 index 000000000..650919e26 Binary files /dev/null and b/odex25_donation/sale_order_report/static/src/fonts/DroidKufi-Bold.ttf differ diff --git a/odex25_donation/sale_order_report/static/src/fonts/DroidKufi-Regular.ttf b/odex25_donation/sale_order_report/static/src/fonts/DroidKufi-Regular.ttf new file mode 100644 index 000000000..af859750b Binary files /dev/null and b/odex25_donation/sale_order_report/static/src/fonts/DroidKufi-Regular.ttf differ diff --git a/odex25_donation/sale_order_report/static/src/fonts/Greta-Arabic-AR-LT-Bold.ttf b/odex25_donation/sale_order_report/static/src/fonts/Greta-Arabic-AR-LT-Bold.ttf new file mode 100644 index 000000000..a8c10987c Binary files /dev/null and b/odex25_donation/sale_order_report/static/src/fonts/Greta-Arabic-AR-LT-Bold.ttf differ diff --git a/odex25_donation/sale_order_report/static/src/fonts/Greta-Arabic-AR-LT.ttf b/odex25_donation/sale_order_report/static/src/fonts/Greta-Arabic-AR-LT.ttf new file mode 100644 index 000000000..825a4cf44 Binary files /dev/null and b/odex25_donation/sale_order_report/static/src/fonts/Greta-Arabic-AR-LT.ttf differ diff --git a/odex25_donation/sale_order_report/static/src/img/111.png b/odex25_donation/sale_order_report/static/src/img/111.png new file mode 100644 index 000000000..77772bc38 Binary files /dev/null and b/odex25_donation/sale_order_report/static/src/img/111.png differ diff --git a/odex25_donation/sale_order_report/static/src/img/footer.png b/odex25_donation/sale_order_report/static/src/img/footer.png new file mode 100644 index 000000000..e890aa554 Binary files /dev/null and b/odex25_donation/sale_order_report/static/src/img/footer.png differ diff --git a/odex25_donation/sale_order_report/static/src/img/header.png b/odex25_donation/sale_order_report/static/src/img/header.png new file mode 100644 index 000000000..29cfdd6f9 Binary files /dev/null and b/odex25_donation/sale_order_report/static/src/img/header.png differ diff --git a/odex25_donation/sale_order_report/static/src/img/header2.png b/odex25_donation/sale_order_report/static/src/img/header2.png new file mode 100644 index 000000000..fc6cb14d7 Binary files /dev/null and b/odex25_donation/sale_order_report/static/src/img/header2.png differ diff --git a/odex25_donation/sh_website_wtsapp/README.md b/odex25_donation/sh_website_wtsapp/README.md new file mode 100644 index 000000000..93e230cf0 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/README.md @@ -0,0 +1,22 @@ +About +============ +Now your customers can chat with you at WhatsApp, directly from your odoo website to the mobile!! No need to add your mobile phone number to the mobile address book. + +Chat with your customers through WhatsApp, the most popular messaging app. Vital extension for your odoo website, which allows you to create stronger relationships with your customers by guiding and advising them in their purchases in real time. +Now your customers can chat with you at WhatsApp, directly from your odoo website to the mobile!! No need to add your mobile phone number to the mobile address book. +An online chat system provides customers immediate access to help. Wait times are often much less than a call center, and customers can easily multi-task while waiting. +This extension allows you to create a WhatsApp chat button, highly configurable, to show it in different parts of your site to chat with your customers through WhatsApp, the most popular messaging app. +Installation +============ +1) Copy module files to addon folder. +2) Restart odoo service (sudo service odoo-server restart). +3) Go to your odoo instance and open apps (make sure to activate debug mode). +4) click on update app list. +5) search module name and hit install button. + +Softhealer Technologies Support Team +===================================== +Skype: live:softhealertechnologies +What's app: +917984575681 +E-Mail: suppport@softhealer.com +Website: https://softhealer.com diff --git a/odex25_donation/sh_website_wtsapp/__init__.py b/odex25_donation/sh_website_wtsapp/__init__.py new file mode 100644 index 000000000..6092dcb1f --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from . import models diff --git a/odex25_donation/sh_website_wtsapp/__manifest__.py b/odex25_donation/sh_website_wtsapp/__manifest__.py new file mode 100644 index 000000000..0fee2c9bb --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/__manifest__.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. +{ + "name": "WhatsApp Live Chat", + "author": "Softhealer Technologies", + "website": "https://www.softhealer.com", + "support": "support@softhealer.com", + "category": "Website", + "license": "OPL-1", + "summary": """ +whatsapp live chat app,Customer Whatsapp, +whatsup live chat, whatsup chat Odoo +whatsapp chat by odoo website, client whatsup chat module +""", + "description": """ +Chat with your customers through WhatsApp, the most popular messaging app. +Vital extension for your odoo website, +which allows you to create stronger relationships with your +customers by guiding and advising them in their purchases in real time. +Now your customers can chat with you at WhatsApp, +directly from your odoo website to the mobile!! +No need to add your mobile phone number to the mobile address book. +An online chat system provides customers immediate access to help. +Wait times are often much less than a call center, +and customers can easily multi-task while waiting. +This extension allows you to create a WhatsApp chat button, +highly configurable, +to show it in different parts of your site to chat +with your customers through WhatsApp, the most popular messaging app. +""", + "version": "15.0.1", + "depends": ["website", "portal"], + "application": True, + "data": [ + "data/whatsapp_data.xml", + "views/whatsapp.xml", + "views/res_config_settings_view.xml", + "views/website_view.xml", + ], + 'assets': { + 'web.assets_frontend': [ + 'sh_website_wtsapp/static/src/js/detect_mobile.js', + 'sh_website_wtsapp/static/src/css/wtsapp.css' + ], + }, + "images": ["static/description/background.png", ], + "auto_install": False, + "installable": True, + "price": 25, + "currency": "EUR" +} diff --git a/odex25_donation/sh_website_wtsapp/data/whatsapp_data.xml b/odex25_donation/sh_website_wtsapp/data/whatsapp_data.xml new file mode 100644 index 000000000..b682b86d9 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/data/whatsapp_data.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/odex25_donation/sh_website_wtsapp/doc/changelog.rst b/odex25_donation/sh_website_wtsapp/doc/changelog.rst new file mode 100644 index 000000000..394ffa47e --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/doc/changelog.rst @@ -0,0 +1,5 @@ +15.0.1 (Date :17th-Sep-2021) +---------------------------- +- Initial Release + + \ No newline at end of file diff --git a/odex25_donation/sh_website_wtsapp/i18n/ar.po b/odex25_donation/sh_website_wtsapp/i18n/ar.po new file mode 100644 index 000000000..c318254a9 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/i18n/ar.po @@ -0,0 +1,200 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sh_website_wtsapp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.1alpha1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-10-02 09:25+0000\n" +"PO-Revision-Date: 2020-10-02 09:25+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_color +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_color +msgid "Background Color" +msgstr "لون الخلفية" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-center +msgid "Bottom Center" +msgstr "مركز القاع" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-left +msgid "Bottom Left" +msgstr "أسفل اليسار" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-right +msgid "Bottom Right" +msgstr "أسفل اليمين" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_link_btn_title +msgid "Button Title" +msgstr "عنوان الزر" + +#. module: sh_website_wtsapp +#: model:ir.model,name:sh_website_wtsapp.model_res_config_settings +msgid "Config Settings" +msgstr "إعدادات التكوين" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_type__contact +msgid "Contact" +msgstr "اتصل" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__display_name +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__display_name +msgid "Display Name" +msgstr "اسم العرض" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_style__fball +msgid "Floating Ball" +msgstr "الكرة العائمة" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_style__fbutton +msgid "Floating Button" +msgstr "زر عائم" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_type__chat +msgid "Group Chat" +msgstr "مجموعة محادثة" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__id +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__id +msgid "ID" +msgstr "هوية شخصية" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_banner_img +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_banner_img +msgid "Image" +msgstr "صورة" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings____last_update +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website____last_update +msgid "Last Modified on" +msgstr "تاريخ آخر تعديل" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_link_btn_title +msgid "Link Button Name" +msgstr "اسم زر الارتباط" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__center +msgid "Mid Center" +msgstr "منتصف المركز" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__left +msgid "Mid Left" +msgstr "منتصف اليسار" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__right +msgid "Mid Right" +msgstr "منتصف اليمين" + +#. module: sh_website_wtsapp +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_inherit_res_config_settings_view_form_for_whatsapp_chat_and_share +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_website_whatsapp_website_form +msgid "" +"Omit any zeroes, brackets or dashes when adding the phone number in " +"international format." +msgstr "" +"احذف أي أصفار أو أقواس أو شرطات عند إضافة رقم الهاتف" +"تنسيق دولي." + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_position +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_position +msgid "Position" +msgstr "موضع" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_style +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_style +msgid "Style" +msgstr "أسلوب" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_text_color +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_text_color +msgid "Text Color" +msgstr "لون الخط" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-center +msgid "Top Center" +msgstr "مركز أعلى" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-left +msgid "Top Left" +msgstr "أعلى اليسار" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-right +msgid "Top Right" +msgstr "اعلى اليمين" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_type +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_type +msgid "Type" +msgstr "اكتب" + +#. module: sh_website_wtsapp +#: model:res.config.settings,sww_link_btn_title:sh_website_wtsapp.sh_default_website_whatsapp_data +msgid "WHATSAPP" +msgstr "ال WHATSAPP" + +#. module: sh_website_wtsapp +#: model:ir.model,name:sh_website_wtsapp.model_website +msgid "Website" +msgstr "موقع الكتروني" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_is_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_is_wtsapp +msgid "WhatsApp Chat" +msgstr "دردشة WhatsApp" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_cn +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_cn +msgid "WhatsApp Contact No" +msgstr "رقم جهة اتصال WhatsApp" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_message +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_message +msgid "WhatsApp Default Message" +msgstr "رسالة WhatsApp الافتراضية" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_chat +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_chat +msgid "WhatsApp Group Chat" +msgstr "دردشة مجموعة WhatsApp" + +#. module: sh_website_wtsapp +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_inherit_res_config_settings_view_form_for_whatsapp_chat_and_share +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_website_whatsapp_website_form +msgid "WhatsApp Live Chat" +msgstr "WhatsApp Live Chat" diff --git a/odex25_donation/sh_website_wtsapp/i18n/de.po b/odex25_donation/sh_website_wtsapp/i18n/de.po new file mode 100644 index 000000000..9432f138c --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/i18n/de.po @@ -0,0 +1,200 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sh_website_wtsapp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.1alpha1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-10-02 09:25+0000\n" +"PO-Revision-Date: 2020-10-02 09:25+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_color +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_color +msgid "Background Color" +msgstr "Hintergrundfarbe" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-center +msgid "Bottom Center" +msgstr "Unten in der Mitte" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-left +msgid "Bottom Left" +msgstr "Unten links" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-right +msgid "Bottom Right" +msgstr "Unten rechts" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_link_btn_title +msgid "Button Title" +msgstr "Schaltflächentitel" + +#. module: sh_website_wtsapp +#: model:ir.model,name:sh_website_wtsapp.model_res_config_settings +msgid "Config Settings" +msgstr "Konfigurationseinstellungen" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_type__contact +msgid "Contact" +msgstr "Kontakt" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__display_name +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__display_name +msgid "Display Name" +msgstr "Anzeigename" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_style__fball +msgid "Floating Ball" +msgstr "Schwimmender Ball" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_style__fbutton +msgid "Floating Button" +msgstr "Schwimmender Knopf" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_type__chat +msgid "Group Chat" +msgstr "Gruppenchat" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__id +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__id +msgid "ID" +msgstr "ICH WÜRDE" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_banner_img +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_banner_img +msgid "Image" +msgstr "Bild" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings____last_update +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website____last_update +msgid "Last Modified on" +msgstr "Zuletzt geändert am" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_link_btn_title +msgid "Link Button Name" +msgstr "Name der Verknüpfungsschaltfläche" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__center +msgid "Mid Center" +msgstr "Mittleres Zentrum" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__left +msgid "Mid Left" +msgstr "Mitte links" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__right +msgid "Mid Right" +msgstr "Mitte rechts" + +#. module: sh_website_wtsapp +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_inherit_res_config_settings_view_form_for_whatsapp_chat_and_share +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_website_whatsapp_website_form +msgid "" +"Omit any zeroes, brackets or dashes when adding the phone number in " +"international format." +msgstr "" +"Lassen Sie beim Hinzufügen der Telefonnummer Nullen, Klammern oder Bindestriche weg." +"internationales Format." + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_position +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_position +msgid "Position" +msgstr "Position" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_style +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_style +msgid "Style" +msgstr "Stil" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_text_color +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_text_color +msgid "Text Color" +msgstr "Textfarbe" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-center +msgid "Top Center" +msgstr "Oben in der Mitte" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-left +msgid "Top Left" +msgstr "Oben links" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-right +msgid "Top Right" +msgstr "Oben rechts" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_type +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_type +msgid "Type" +msgstr "Art" + +#. module: sh_website_wtsapp +#: model:res.config.settings,sww_link_btn_title:sh_website_wtsapp.sh_default_website_whatsapp_data +msgid "WHATSAPP" +msgstr "WHATSAPP" + +#. module: sh_website_wtsapp +#: model:ir.model,name:sh_website_wtsapp.model_website +msgid "Website" +msgstr "Webseite" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_is_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_is_wtsapp +msgid "WhatsApp Chat" +msgstr "WhatsApp Chat" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_cn +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_cn +msgid "WhatsApp Contact No" +msgstr "WhatsApp Kontakt-Nr" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_message +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_message +msgid "WhatsApp Default Message" +msgstr "WhatsApp-Standardnachricht" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_chat +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_chat +msgid "WhatsApp Group Chat" +msgstr "WhatsApp-Gruppenchat" + +#. module: sh_website_wtsapp +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_inherit_res_config_settings_view_form_for_whatsapp_chat_and_share +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_website_whatsapp_website_form +msgid "WhatsApp Live Chat" +msgstr "WhatsApp Live Chat" diff --git a/odex25_donation/sh_website_wtsapp/i18n/es.po b/odex25_donation/sh_website_wtsapp/i18n/es.po new file mode 100644 index 000000000..6cd5e2d9c --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/i18n/es.po @@ -0,0 +1,200 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sh_website_wtsapp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.1alpha1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-10-02 09:25+0000\n" +"PO-Revision-Date: 2020-10-02 09:25+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_color +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_color +msgid "Background Color" +msgstr "Color de fondo" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-center +msgid "Bottom Center" +msgstr "Parte inferior central" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-left +msgid "Bottom Left" +msgstr "Abajo a la izquierda" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-right +msgid "Bottom Right" +msgstr "Abajo a la derecha" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_link_btn_title +msgid "Button Title" +msgstr "Título del botón" + +#. module: sh_website_wtsapp +#: model:ir.model,name:sh_website_wtsapp.model_res_config_settings +msgid "Config Settings" +msgstr "Ajustes de configuración" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_type__contact +msgid "Contact" +msgstr "Contacto" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__display_name +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__display_name +msgid "Display Name" +msgstr "Nombre para mostrar" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_style__fball +msgid "Floating Ball" +msgstr "Bola flotante" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_style__fbutton +msgid "Floating Button" +msgstr "Botón flotante" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_type__chat +msgid "Group Chat" +msgstr "Grupo de chat" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__id +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__id +msgid "ID" +msgstr "CARNÉ DE IDENTIDAD" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_banner_img +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_banner_img +msgid "Image" +msgstr "Imagen" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings____last_update +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_link_btn_title +msgid "Link Button Name" +msgstr "Nombre del botón de enlace" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__center +msgid "Mid Center" +msgstr "Centro medio" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__left +msgid "Mid Left" +msgstr "Medio Izquierdo" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__right +msgid "Mid Right" +msgstr "Media derecha" + +#. module: sh_website_wtsapp +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_inherit_res_config_settings_view_form_for_whatsapp_chat_and_share +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_website_whatsapp_website_form +msgid "" +"Omit any zeroes, brackets or dashes when adding the phone number in " +"international format." +msgstr "" +"Omita los ceros, corchetes o guiones cuando agregue el número de teléfono en" +"formato internacional." + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_position +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_position +msgid "Position" +msgstr "Posición" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_style +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_style +msgid "Style" +msgstr "Estilo" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_text_color +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_text_color +msgid "Text Color" +msgstr "Color de texto" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-center +msgid "Top Center" +msgstr "Centro Superior" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-left +msgid "Top Left" +msgstr "Arriba a la izquierda" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-right +msgid "Top Right" +msgstr "Parte superior derecha" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_type +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_type +msgid "Type" +msgstr "Tipo" + +#. module: sh_website_wtsapp +#: model:res.config.settings,sww_link_btn_title:sh_website_wtsapp.sh_default_website_whatsapp_data +msgid "WHATSAPP" +msgstr "WHATSAPP" + +#. module: sh_website_wtsapp +#: model:ir.model,name:sh_website_wtsapp.model_website +msgid "Website" +msgstr "Sitio web" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_is_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_is_wtsapp +msgid "WhatsApp Chat" +msgstr "Chat de WhatsApp" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_cn +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_cn +msgid "WhatsApp Contact No" +msgstr "Contacto de WhatsApp No" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_message +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_message +msgid "WhatsApp Default Message" +msgstr "Mensaje predeterminado de WhatsApp" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_chat +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_chat +msgid "WhatsApp Group Chat" +msgstr "Chat grupal de WhatsApp" + +#. module: sh_website_wtsapp +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_inherit_res_config_settings_view_form_for_whatsapp_chat_and_share +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_website_whatsapp_website_form +msgid "WhatsApp Live Chat" +msgstr "Chat en vivo de WhatsApp" diff --git a/odex25_donation/sh_website_wtsapp/i18n/fr.po b/odex25_donation/sh_website_wtsapp/i18n/fr.po new file mode 100644 index 000000000..7b66e404d --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/i18n/fr.po @@ -0,0 +1,200 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sh_website_wtsapp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.1alpha1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-10-02 09:25+0000\n" +"PO-Revision-Date: 2020-10-02 09:25+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_color +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_color +msgid "Background Color" +msgstr "Couleur de l'arrière plan" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-center +msgid "Bottom Center" +msgstr "Centre inférieur" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-left +msgid "Bottom Left" +msgstr "En bas à gauche" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-right +msgid "Bottom Right" +msgstr "En bas à droite" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_link_btn_title +msgid "Button Title" +msgstr "Titre du bouton" + +#. module: sh_website_wtsapp +#: model:ir.model,name:sh_website_wtsapp.model_res_config_settings +msgid "Config Settings" +msgstr "Paramètres de configuration" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_type__contact +msgid "Contact" +msgstr "Contact" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__display_name +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__display_name +msgid "Display Name" +msgstr "Afficher un nom" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_style__fball +msgid "Floating Ball" +msgstr "Balle flottante" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_style__fbutton +msgid "Floating Button" +msgstr "Bouton flottant" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_type__chat +msgid "Group Chat" +msgstr "Discussion de groupe" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__id +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__id +msgid "ID" +msgstr "identifiant" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_banner_img +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_banner_img +msgid "Image" +msgstr "Image" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings____last_update +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website____last_update +msgid "Last Modified on" +msgstr "Dernière modification sur" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_link_btn_title +msgid "Link Button Name" +msgstr "Nom du bouton de liaison" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__center +msgid "Mid Center" +msgstr "Milieu centre" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__left +msgid "Mid Left" +msgstr "Mi-gauche" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__right +msgid "Mid Right" +msgstr "Mi-droit" + +#. module: sh_website_wtsapp +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_inherit_res_config_settings_view_form_for_whatsapp_chat_and_share +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_website_whatsapp_website_form +msgid "" +"Omit any zeroes, brackets or dashes when adding the phone number in " +"international format." +msgstr "" +"Omettez des zéros, des crochets ou des tirets lorsque vous ajoutez le numéro de téléphone dans" +"Format international." + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_position +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_position +msgid "Position" +msgstr "Position" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_style +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_style +msgid "Style" +msgstr "Style" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_text_color +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_text_color +msgid "Text Color" +msgstr "Couleur de texte" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-center +msgid "Top Center" +msgstr "Centre supérieur" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-left +msgid "Top Left" +msgstr "En haut à gauche" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-right +msgid "Top Right" +msgstr "En haut à droite" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_type +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_type +msgid "Type" +msgstr "Taper" + +#. module: sh_website_wtsapp +#: model:res.config.settings,sww_link_btn_title:sh_website_wtsapp.sh_default_website_whatsapp_data +msgid "WHATSAPP" +msgstr "Whatsapp" + +#. module: sh_website_wtsapp +#: model:ir.model,name:sh_website_wtsapp.model_website +msgid "Website" +msgstr "Site Internet" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_is_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_is_wtsapp +msgid "WhatsApp Chat" +msgstr "WhatsApp Chat" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_cn +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_cn +msgid "WhatsApp Contact No" +msgstr "WhatsApp contact non" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_message +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_message +msgid "WhatsApp Default Message" +msgstr "Message par défaut WhatsApp" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_chat +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_chat +msgid "WhatsApp Group Chat" +msgstr "WhatsApp Group Chat" + +#. module: sh_website_wtsapp +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_inherit_res_config_settings_view_form_for_whatsapp_chat_and_share +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_website_whatsapp_website_form +msgid "WhatsApp Live Chat" +msgstr "WhatsApp Live Chat" diff --git a/odex25_donation/sh_website_wtsapp/i18n/zh_HK.po b/odex25_donation/sh_website_wtsapp/i18n/zh_HK.po new file mode 100644 index 000000000..60ef86989 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/i18n/zh_HK.po @@ -0,0 +1,200 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sh_website_wtsapp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.1alpha1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-10-02 09:25+0000\n" +"PO-Revision-Date: 2020-10-02 09:25+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_color +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_color +msgid "Background Color" +msgstr "背景颜色" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-center +msgid "Bottom Center" +msgstr "底部中心" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-left +msgid "Bottom Left" +msgstr "左下方" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__bottom-right +msgid "Bottom Right" +msgstr "右下方" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_link_btn_title +msgid "Button Title" +msgstr "按钮标题" + +#. module: sh_website_wtsapp +#: model:ir.model,name:sh_website_wtsapp.model_res_config_settings +msgid "Config Settings" +msgstr "配置设置" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_type__contact +msgid "Contact" +msgstr "接触" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__display_name +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__display_name +msgid "Display Name" +msgstr "显示名称" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_style__fball +msgid "Floating Ball" +msgstr "浮球" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_style__fbutton +msgid "Floating Button" +msgstr "浮动按钮" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_type__chat +msgid "Group Chat" +msgstr "小组聊天" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__id +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__id +msgid "ID" +msgstr "ID" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_banner_img +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_banner_img +msgid "Image" +msgstr "图片" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings____last_update +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website____last_update +msgid "Last Modified on" +msgstr "最后修改了" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_link_btn_title +msgid "Link Button Name" +msgstr "链接按钮名称" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__center +msgid "Mid Center" +msgstr "中间中心" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__left +msgid "Mid Left" +msgstr "左中旬" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__right +msgid "Mid Right" +msgstr "中旬" + +#. module: sh_website_wtsapp +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_inherit_res_config_settings_view_form_for_whatsapp_chat_and_share +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_website_whatsapp_website_form +msgid "" +"Omit any zeroes, brackets or dashes when adding the phone number in " +"international format." +msgstr "" +"添加电话号码时省略任何零点,括号或破折号" +"国际格式。" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_position +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_position +msgid "Position" +msgstr "位置" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_style +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_style +msgid "Style" +msgstr "风格" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_text_color +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_text_color +msgid "Text Color" +msgstr "文字颜色" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-center +msgid "Top Center" +msgstr "顶部中心" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-left +msgid "Top Left" +msgstr "左上方" + +#. module: sh_website_wtsapp +#: model:ir.model.fields.selection,name:sh_website_wtsapp.selection__website__sww_position__top-right +msgid "Top Right" +msgstr "右上" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_type +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_type +msgid "Type" +msgstr "类型" + +#. module: sh_website_wtsapp +#: model:res.config.settings,sww_link_btn_title:sh_website_wtsapp.sh_default_website_whatsapp_data +msgid "WHATSAPP" +msgstr "whatsapp." + +#. module: sh_website_wtsapp +#: model:ir.model,name:sh_website_wtsapp.model_website +msgid "Website" +msgstr "网站" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_is_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_is_wtsapp +msgid "WhatsApp Chat" +msgstr "whatsapp chat." + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_cn +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_cn +msgid "WhatsApp Contact No" +msgstr "Whatsapp联系号码" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_message +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_message +msgid "WhatsApp Default Message" +msgstr "whatsapp默认消息" + +#. module: sh_website_wtsapp +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_res_config_settings__sww_chat +#: model:ir.model.fields,field_description:sh_website_wtsapp.field_website__sww_chat +msgid "WhatsApp Group Chat" +msgstr "whatsapp小组聊天" + +#. module: sh_website_wtsapp +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_inherit_res_config_settings_view_form_for_whatsapp_chat_and_share +#: model_terms:ir.ui.view,arch_db:sh_website_wtsapp.sh_website_whatsapp_website_form +msgid "WhatsApp Live Chat" +msgstr "WhatsApp在线聊天" diff --git a/odex25_donation/sh_website_wtsapp/models/__init__.py b/odex25_donation/sh_website_wtsapp/models/__init__.py new file mode 100644 index 000000000..573f9fd82 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from . import res_config_model diff --git a/odex25_donation/sh_website_wtsapp/models/res_config_model.py b/odex25_donation/sh_website_wtsapp/models/res_config_model.py new file mode 100644 index 000000000..2f2545b74 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/models/res_config_model.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +# Part of Softhealer Technologies. + +from odoo import fields, models + + +class WebisteConfiguration(models.TransientModel): + _inherit = "res.config.settings" + + sww_is_wtsapp = fields.Boolean( + related="website_id.sww_is_wtsapp", + string="WhatsApp Chat", + readonly=False + ) + sww_cn = fields.Char( + related="website_id.sww_cn", + string="WhatsApp Contact No", + readonly=False + ) + sww_chat = fields.Char( + related="website_id.sww_chat", + string="WhatsApp Group Chat", + readonly=False + ) + sww_message = fields.Text( + related="website_id.sww_message", + string="WhatsApp Default Message", + readonly=False + ) + sww_link_btn_title = fields.Char( + related="website_id.sww_link_btn_title", + string="Button Title", + readonly=False + ) + sww_banner_img = fields.Binary( + related="website_id.sww_banner_img", + string="Image", + readonly=False + ) + sww_type = fields.Selection( + related="website_id.sww_type", + string="Type", + readonly=False + ) + sww_style = fields.Selection( + related="website_id.sww_style", + string="Style", + readonly=False + ) + sww_position = fields.Selection( + related="website_id.sww_position", + string="Position", + readonly=False + ) + sww_color = fields.Char( + related="website_id.sww_color", + string="Background Color", + readonly=False + ) + sww_text_color = fields.Char( + related="website_id.sww_text_color", + string="Text Color", + readonly=False + ) + + +class Website(models.Model): + _inherit = "website" + + sww_is_wtsapp = fields.Boolean(string="WhatsApp Chat") + sww_cn = fields.Char(string="WhatsApp Contact No") + sww_chat = fields.Char(string="WhatsApp Group Chat") + sww_message = fields.Text(string="WhatsApp Default Message") + sww_link_btn_title = fields.Char(string="Link Button Name", translate=True) + sww_banner_img = fields.Binary(string="Image") + sww_style = fields.Selection( + [("fball", "Floating Ball"), + ("fbutton", "Floating Button")], + string="Style", + default="fball" + ) + sww_position = fields.Selection([ + ("top-left", "Top Left"), + ("top-center", "Top Center"), + ("top-right", "Top Right"), + ("left", "Mid Left"), + ("center", "Mid Center"), + ("right", "Mid Right"), + ("bottom-left", "Bottom Left"), + ("bottom-center", "Bottom Center"), + ("bottom-right", "Bottom Right")], + string="Position" + ) + sww_type = fields.Selection( + [("chat", "Group Chat"), + ("contact", "Contact")], + string="Type") + sww_color = fields.Char(string="Background Color") + sww_text_color = fields.Char(string="Text Color") diff --git a/odex25_donation/sh_website_wtsapp/static/description/1.png b/odex25_donation/sh_website_wtsapp/static/description/1.png new file mode 100644 index 000000000..baafe7b5f Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/1.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/2.png b/odex25_donation/sh_website_wtsapp/static/description/2.png new file mode 100644 index 000000000..85efad5cf Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/2.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/3.png b/odex25_donation/sh_website_wtsapp/static/description/3.png new file mode 100644 index 000000000..e60b2f706 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/3.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/4.png b/odex25_donation/sh_website_wtsapp/static/description/4.png new file mode 100644 index 000000000..f1a836ab9 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/4.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/5.png b/odex25_donation/sh_website_wtsapp/static/description/5.png new file mode 100644 index 000000000..d649e1c58 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/5.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/6.png b/odex25_donation/sh_website_wtsapp/static/description/6.png new file mode 100644 index 000000000..3f9da4bee Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/6.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/7.png b/odex25_donation/sh_website_wtsapp/static/description/7.png new file mode 100644 index 000000000..9dcdd5e01 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/7.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/8.png b/odex25_donation/sh_website_wtsapp/static/description/8.png new file mode 100644 index 000000000..345cc0931 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/8.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/9.png b/odex25_donation/sh_website_wtsapp/static/description/9.png new file mode 100644 index 000000000..ca37e5271 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/9.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/aarab.png b/odex25_donation/sh_website_wtsapp/static/description/aarab.png new file mode 100644 index 000000000..143ffc978 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/aarab.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/background.png b/odex25_donation/sh_website_wtsapp/static/description/background.png new file mode 100644 index 000000000..22891edb1 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/background.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/center - 2.png b/odex25_donation/sh_website_wtsapp/static/description/center - 2.png new file mode 100644 index 000000000..4d6235ab8 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/center - 2.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/chinese.png b/odex25_donation/sh_website_wtsapp/static/description/chinese.png new file mode 100644 index 000000000..fcab84521 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/chinese.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/d1.png b/odex25_donation/sh_website_wtsapp/static/description/d1.png new file mode 100644 index 000000000..b405fbf6b Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/d1.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/d2.png b/odex25_donation/sh_website_wtsapp/static/description/d2.png new file mode 100644 index 000000000..f2d4965bd Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/d2.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/d3.png b/odex25_donation/sh_website_wtsapp/static/description/d3.png new file mode 100644 index 000000000..13d9aa960 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/d3.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/d4.png b/odex25_donation/sh_website_wtsapp/static/description/d4.png new file mode 100644 index 000000000..607ef77b6 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/d4.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/d5.png b/odex25_donation/sh_website_wtsapp/static/description/d5.png new file mode 100644 index 000000000..5967573e3 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/d5.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/d6.png b/odex25_donation/sh_website_wtsapp/static/description/d6.png new file mode 100644 index 000000000..c5b14beae Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/d6.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/default_image.png b/odex25_donation/sh_website_wtsapp/static/description/default_image.png new file mode 100644 index 000000000..c61c4ef73 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/default_image.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/eng.png b/odex25_donation/sh_website_wtsapp/static/description/eng.png new file mode 100644 index 000000000..91ed5242a Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/eng.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/french.png b/odex25_donation/sh_website_wtsapp/static/description/french.png new file mode 100644 index 000000000..15ac75126 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/french.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/german.png b/odex25_donation/sh_website_wtsapp/static/description/german.png new file mode 100644 index 000000000..13efbe59e Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/german.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/heading.png b/odex25_donation/sh_website_wtsapp/static/description/heading.png new file mode 100644 index 000000000..347482183 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/heading.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/heading1.png b/odex25_donation/sh_website_wtsapp/static/description/heading1.png new file mode 100644 index 000000000..599eb075d Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/heading1.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/icon.png b/odex25_donation/sh_website_wtsapp/static/description/icon.png new file mode 100644 index 000000000..56ad7b65c Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/icon.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/index.html b/odex25_donation/sh_website_wtsapp/static/description/index.html new file mode 100644 index 000000000..a44484b18 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/static/description/index.html @@ -0,0 +1,714 @@ + + + + + + + + + + + + + +
+
+
+
+
+ logo +
+
+ Community + Enterprise + Odoo.sh +
+
+
+
+
+ +
+
+
+

WhatsApp Live Chat

+ + heading +

+ Now your customers can chat with you at WhatsApp, directly from your odoo website to the mobile!! No need to add your mobile phone number to the mobile address book. +

+Chat with your customers through WhatsApp, the most popular messaging app. Vital extension for your odoo website, which allows you to create stronger relationships with your customers by guiding and advising them in their purchases in real time. +
+Now your customers can chat with you at WhatsApp, directly from your odoo website to the mobile!! No need to add your mobile phone number to the mobile address book. +
+An online chat system provides customers immediate access to help. Wait times are often much less than a call center, and customers can easily multi-task while waiting. +
+This extension allows you to create a WhatsApp chat button, highly configurable, to show it in different parts of your site to chat with your customers through WhatsApp, the most popular messaging app. +
+

+
+
+
+ +
+
+
+

Hot Features

+ + heading +
+
+
+
+ + Chat at WhatsApp from Odoo Website + +
+
+
+
+ No Need to Add Mobile Number + +
+
+
+
+ Display Block in Multiple Position + +
+
+
+
+ + Mobile Compatible + +
+
+
+
+ One Time Configure + +
+
+
+
+ Customer Friendly + +
+
+
+
+ +
+ +
+
+
+

Features

+ + heading +
+
+
    +
  • +You can display the block in multiple positions like the top left, top center, top right, mid-left, mid-center, mid-right, bottom left, bottom center, bottom right. + +
  • +
  • +Your customer does not need to add your mobile phone number to the mobile address book. The chat will be opened automatically with your phone number, even on desktop and on mobile. + +
  • +
  • +You can configure the button to open a WhatsApp group. + +
  • +
  • +Predefined message to send. You can define a predefined message to send when your customer clicks on WhatsApp button. +
  • +
  • +Adaptive and responsive design (RWD), valid for all resolutions of your computer and mobile device. + +
  • +
  • +Mobile Compatibility. + +
  • +
  • +Multi Website Supported. + +
  • +
  • +No special configuration required just install it and cheers! +
  • +
  • + +This module saves your important time. + +
  • + +
  • + +It reduces human efforts. + +
  • +
+
+
+
+
+
+ +
+ + +
+
+
+
+

In website settings, you must configure below fields in order to display "WhatsApp Chat" icon in website. +

+ +
+
+ +

"ball" style "WhatsApp Chat" icon looks like below. +

+ +
+
+ + +

"Button" style "WhatsApp Chat" icon looks like below. +

+ +
+
+

In mobile view, icon looks like below. +

+ +
+
+ + +

Multi website localhost and 0.0.0.0 below. +

+ +
+
+

Whatsapp live chat settings in localhost website(website 1) +

+ +
+
+

Whatsapp live chat in localhost website(website 1) +

+ +
+
+ + +

Whatsapp live chat settings in 0.0.0.0 website(website 2) +

+ +
+
+

Whatsapp live chat in 0.0.0.0 website(website 2) +

+ +
+
+ + + + +
+
+
+
+ + +
+ + +
+

Version 15.0.1 | Released on : 10 October 2021

+
+
+ + Initial + + Initial Release.
+
+
+ +
+ + +
+
+
+
+ +
+
+
    +
  • Yes, this app works perfectly with Odoo Enterprise (Odoo.sh & Premise) as well as Community.
  • +
+
+
+
+
+ +
+
+
    +
  • Yes, This app is compatible with Odoo's Multi-Company/Multi-Website Feature.
  • +
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+
    +
  • Yes, we provide free support for 100 days.
  • +
+
+
+
+ + +
+ +
+
+
    +
  • Yes, you will get free update for lifetime.
  • +
+
+
+
+ +
+ +
+
+
    +
  • No, you don't need to install addition libraries.
  • +
+
+
+
+ +
+ +
+
+
    +
  • Yes, You have to download module for each version (13,14,15) except in version 12 or lower.
  • +
+
+
+
+ +
+ +
+
+
    +
  • No, We do not provide any kind of exchange.
  • +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+

Multi-Languages

+ heading +
+
+ + We have added predefined some languages(English, German / Deutsch, Arabic, Spanish / Espanol, French / Francais, Chinese) in module, If you want to add other language you can contact us on support@softhealer.com. We use google translator tools for multi-languages so possible translations can be not accurate. we accept suggest to make more accurate translations also on support@softhealer.com. +

+
+
+
+
+
+ english + germany + arab + spanish + Chinese + French +
+
+
+
+
+
+
+ +
+
+
+ Our Apps +
+ +
+
+
+
+ +
+
+
+

You May Also Like

+ heading +
+
+ + +
+
+
+ + + +
+
+
+
+
+
+ + + +
+
+
+
+
+
+ + + +
+
+
+
+
+
+ + + +
+
+
+
+
+
+ + + +
+
+
+
+
+
+ + + +
+
+
+ +
+
+
+ + + +
+
+
+ +
+
+
+ + + +
+
+
+ + +
+
+
+ +
+
+
+

Most Demanded Apps

+ heading +
+
+
+
+
+ + sh_all_in_one_mbs + +
+
+
+
+
+
+ + sh_activities_management + +
+
+
+
+
+
+ + sh_all_in_one_helpdesk + +
+
+
+
+
+
+ + sh_secondary_unit + +
+
+
+
+
+
+ + sh_barcode_scanner + +
+
+
+ +
+
+
+ + sh_all_in_one_basic_import + +
+
+
+
+
+
+ + +
+ +
+
+
+ +
+
+
+ Skype +
+
+ Email +
+
+
+
+
+ + \ No newline at end of file diff --git a/odex25_donation/sh_website_wtsapp/static/description/info.png b/odex25_donation/sh_website_wtsapp/static/description/info.png new file mode 100644 index 000000000..2317ee9e4 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/info.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/mobileapp.png b/odex25_donation/sh_website_wtsapp/static/description/mobileapp.png new file mode 100644 index 000000000..cf31da458 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/mobileapp.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/setting.png b/odex25_donation/sh_website_wtsapp/static/description/setting.png new file mode 100644 index 000000000..a7c850879 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/setting.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/sh_website_faq.png b/odex25_donation/sh_website_wtsapp/static/description/sh_website_faq.png new file mode 100644 index 000000000..b1e5e663f Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/sh_website_faq.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/sh_website_gdpr.png b/odex25_donation/sh_website_wtsapp/static/description/sh_website_gdpr.png new file mode 100644 index 000000000..cc3585a54 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/sh_website_gdpr.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/sh_website_helpdesk.png b/odex25_donation/sh_website_wtsapp/static/description/sh_website_helpdesk.png new file mode 100644 index 000000000..49aaf36e2 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/sh_website_helpdesk.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/sh_website_offers.jpg b/odex25_donation/sh_website_wtsapp/static/description/sh_website_offers.jpg new file mode 100644 index 000000000..db22b4c16 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/sh_website_offers.jpg differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/sh_website_popup.png b/odex25_donation/sh_website_wtsapp/static/description/sh_website_popup.png new file mode 100644 index 000000000..1c63d4244 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/sh_website_popup.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/sh_website_quote.png b/odex25_donation/sh_website_wtsapp/static/description/sh_website_quote.png new file mode 100644 index 000000000..689e61083 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/sh_website_quote.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/sh_website_skype.png b/odex25_donation/sh_website_wtsapp/static/description/sh_website_skype.png new file mode 100644 index 000000000..9c1c3c32a Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/sh_website_skype.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/sh_website_tnc.png b/odex25_donation/sh_website_wtsapp/static/description/sh_website_tnc.png new file mode 100644 index 000000000..5145f4427 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/sh_website_tnc.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/shape.png b/odex25_donation/sh_website_wtsapp/static/description/shape.png new file mode 100644 index 000000000..5063a6bf5 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/shape.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/softhealer.png b/odex25_donation/sh_website_wtsapp/static/description/softhealer.png new file mode 100644 index 000000000..2540e7750 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/softhealer.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/spanish.jpg b/odex25_donation/sh_website_wtsapp/static/description/spanish.jpg new file mode 100644 index 000000000..4a6df1f9f Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/spanish.jpg differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/user.png b/odex25_donation/sh_website_wtsapp/static/description/user.png new file mode 100644 index 000000000..3717e4f28 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/user.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/vd_btn.png b/odex25_donation/sh_website_wtsapp/static/description/vd_btn.png new file mode 100644 index 000000000..68a5c4c62 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/vd_btn.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/description/website_maintainance.jpg b/odex25_donation/sh_website_wtsapp/static/description/website_maintainance.jpg new file mode 100644 index 000000000..f19609d9d Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/description/website_maintainance.jpg differ diff --git a/odex25_donation/sh_website_wtsapp/static/src/css/wtsapp.css b/odex25_donation/sh_website_wtsapp/static/src/css/wtsapp.css new file mode 100644 index 000000000..de34a4142 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/static/src/css/wtsapp.css @@ -0,0 +1,413 @@ +.whatsapp { + clear: both; + /*padding: 10px 0;*/ + border-radius: 4px; +} + +.whatsapp:focus { + border: 0; + outline: none !important; +} + +.whatsapp span { + border-radius: 4px; + background: #25d366; + color: #fff; + font-size: 13px; + padding: 6px 8px; + display: inline-block; + outline: none; +} + +.whatsapp a:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + +.whatsapp i.icon-whatsapp { + font-size: 21px; + line-height: 21px; + padding-right: 7px; +} + +.whatsapp.left { + position: fixed; + top: 45%; + background: none !important; +} + +.whatsapp.center { + position: fixed; + background: none !important; + text-align: center; + margin: -35px -80px 0 0; + top: 50%; + right: 50%; +} + +.whatsapp.right { + position: fixed; + right: 5px; + top: 40%; + background: none !important; +} + +.whatsapp.bottom-left { + left: 0; +} + +.whatsapp.bottom-right { + right: 0; +} + +.whatsapp.bottom-center { + right: 45%; +} + +.whatsapp.top-left { + top: 0; + left: 0; + bottom: auto; +} + +.whatsapp.top-right { + top: 0; + right: 0; + bottom: auto; +} + +.whatsapp.top-center { + top: 0; + right: 45%; + bottom: auto; +} + +.whatsapp-hookDisplayFooter { + clear: none; +} + +.whatsapp-hookDisplayNav { + clear: none; + float: left; + margin-left: 15px; + padding: 0; +} + +.whatsapp-hookDisplayNav span { + float: left; + padding: 5px 0 10px; + line-height: 18px; + background: none; +} + +.whatsapp-hookDisplayNav i.icon-whatsapp { + vertical-align: 0; +} + +.whatsapp-badge { + position: fixed; + bottom: 0; + z-index: 999999; + margin: 10px; + width: auto !important; +} + +.whatsapp-widget { + bottom: 0; + z-index: 999999; + margin: 10px; + width: auto !important; +} + +.whatsapp-topWidth { + padding: 0; + text-align: center; +} + +.whatsapp-sticky { + position: fixed; + bottom: 0; + z-index: 999999; + margin: 0; + padding: 0; + width: 100% !important; + text-align: center; + border-radius: 0; +} + +.whatsapp-sticky.bottom-right { + text-align: right; +} + +.whatsapp-sticky.bottom-left { + text-align: left; +} + +.whatsapp-sticky.bottom-center { + right: auto; +} + +.whatsapp-sticky.top-right { + text-align: right; +} + +.whatsapp-sticky.top-left { + text-align: left; +} + +.whatsapp-sticky.top-center { + right: auto; +} + +.whatsapp-sticky.right { + text-align: right; + bottom: 46%; +} + +.whatsapp-sticky.left { + text-align: left; + bottom: 46%; +} + +.whatsapp-sticky.center { + right: auto; + bottom: 46%; +} + +/** FLOATING BUTTON **/ + +.label-container { + position: fixed; + bottom: 35px; + right: 90px; + display: table; + visibility: hidden; +} + +.label-container-top-right { + position: fixed; + top: 34px; + right: 90px; + display: table; + visibility: hidden; +} + +.label-container-top-left { + position: fixed; + top: 35px; + left: 6.5%; + display: table; + visibility: hidden; +} + +.label-container-top-center { + position: fixed; + top: 34px; + left: 46%; + display: table; + visibility: hidden; +} + +.label-container-bottom-left { + position: fixed; + bottom: 35px; + left: 90px; + display: table; + visibility: hidden; +} + +.label-container-bottom-center { + position: fixed; + bottom: 30px; + left: 46.5%; + display: table; + visibility: hidden; +} + +.label-container-left { + top: 47.5%; + position: fixed; + bottom: 30px; + left: 85px; + display: table; + visibility: hidden; +} + +.label-container-right { + top: 47.5%; + position: fixed; + bottom: 30px; + right: 85px; + display: table; + visibility: hidden; +} + +.label-container-center { + position: fixed; + bottom: 46%; + left: 51.5%; + display: table; + visibility: hidden; +} + +.label-text { + color: #fff; + background: rgba(51, 51, 51, 0.5); + display: table-cell; + vertical-align: middle; + padding: 10px; + border-radius: 3px; +} + +.label-arrow { + display: table-cell; + vertical-align: middle; + color: #333; + opacity: 0.5; +} + +.sh_watsapp_live_chate_fball.float-center { + position: fixed; + width: 60px; + height: 60px; + bottom: 25px; + left: 47.5%; + color: #fff; + + text-align: center; +} + +.sh_watsapp_live_chate_fball.float-floating.float-left { + top: 46%; + position: fixed; + width: 60px; + height: 60px; + left: 20px; + color: #fff; + + text-align: center; +} + +.sh_watsapp_live_chate_fball.float-floating.float-right { + top: 46%; + position: fixed; + width: 60px; + height: 60px; + right: 20px; + color: #fff; + + text-align: center; +} + +.sh_watsapp_live_chate_fball.float-top-left { + position: fixed; + width: 60px; + height: 60px; + top: 25px; + left: 25px; + color: #fff; + + text-align: center; +} + +.sh_watsapp_live_chate_fball.float-top-right { + position: fixed; + width: 60px; + height: 60px; + top: 25px; + right: 25px; + color: #fff; + + text-align: center; +} + +.sh_watsapp_live_chate_fball.float-top-center { + position: fixed; + width: 60px; + height: 60px; + top: 25px; + right: 46%; + color: #fff; + + text-align: center; +} + +.sh_watsapp_live_chate_fball.float-bottom-right { + position: fixed; + width: 60px; + height: 60px; + bottom: 25px; + right: 25px; + color: #fff; + + text-align: center; +} + +.sh_watsapp_live_chate_fball.float-bottom-left { + position: fixed; + width: 60px; + height: 60px; + bottom: 25px; + left: 25px; + color: #fff; + + text-align: center; +} + +.sh_watsapp_live_chate_fball.float-bottom-center { + position: fixed; + width: 60px; + height: 60px; + bottom: 25px; + right: 46%; + color: #fff; + + text-align: center; +} + +.sh_watsapp_live_chate_fball.float-bottom { + z-index: 9999999; +} + +.sh_watsapp_live_chate_fball.float-center { + top: 46%; + z-index: 9999999; +} + +.sh_watsapp_live_chate_fball.float-floating i.icon-whatsapp { + position: relative; + top: 11px; + left: 1px; +} + +.sh_watsapp_live_chate_fball.float-floating { + z-index: 9999999; +} + +.my-float { + font-size: 24px; + margin-top: 18px; +} + +a.float + div.label-container { + visibility: hidden; + opacity: 0; + transition: visibility 0s, opacity 0.5s ease; + z-index: 9999999; +} + +a.float:hover + div.label-container { + visibility: visible; + opacity: 1; +} + +.sh_watsapp_live_chate_fball.float .fa-whatsapp:before { + font-size: xx-large; + top: 14px; + left: 1px; + position: relative; +} + +.whatsapp-offline { + background-color: #ff0000 !important; +} diff --git a/odex25_donation/sh_website_wtsapp/static/src/img/default_image.png b/odex25_donation/sh_website_wtsapp/static/src/img/default_image.png new file mode 100644 index 000000000..073dd5ad8 Binary files /dev/null and b/odex25_donation/sh_website_wtsapp/static/src/img/default_image.png differ diff --git a/odex25_donation/sh_website_wtsapp/static/src/js/detect_mobile.js b/odex25_donation/sh_website_wtsapp/static/src/js/detect_mobile.js new file mode 100644 index 000000000..2eb0c972a --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/static/src/js/detect_mobile.js @@ -0,0 +1,25 @@ +// show all automatic active when page load +$(document).ready(function () { + jQuery(function () { + //put your mobile detection code here + var isMobile = false; //initiate as false + // device detection + if ( + /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test( + navigator.userAgent + ) || + /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( + navigator.userAgent.substr(0, 4) + ) + ) { + isMobile = true; + } + if (isMobile) { + $("#sh_website_wtsapp_contact_mobile").show(); + $("#sh_website_wtsapp_contact_web").hide(); + } else { + $("#sh_website_wtsapp_contact_mobile").hide(); + $("#sh_website_wtsapp_contact_web").show(); + } + }); +}); diff --git a/odex25_donation/sh_website_wtsapp/views/res_config_settings_view.xml b/odex25_donation/sh_website_wtsapp/views/res_config_settings_view.xml new file mode 100644 index 000000000..6cc3552d9 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/views/res_config_settings_view.xml @@ -0,0 +1,40 @@ + + + + sh.inherit.res.config.settings.view.form.for.whatapp.chat.and.share + res.config.settings + + + +

WhatsApp Live Chat

+
+
+ + + + + + + + + + + + + +
+
+
+
+
+
diff --git a/odex25_donation/sh_website_wtsapp/views/website_view.xml b/odex25_donation/sh_website_wtsapp/views/website_view.xml new file mode 100644 index 000000000..db7d49c83 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/views/website_view.xml @@ -0,0 +1,43 @@ + + + + + sh.website.whatsapp.website.form + website + + + +
+
+ + + + + + + + + + + + + + + + +
+
+
+
+
+
diff --git a/odex25_donation/sh_website_wtsapp/views/whatsapp.xml b/odex25_donation/sh_website_wtsapp/views/whatsapp.xml new file mode 100644 index 000000000..1ca2d6265 --- /dev/null +++ b/odex25_donation/sh_website_wtsapp/views/whatsapp.xml @@ -0,0 +1,90 @@ + + + + diff --git a/odex25_donation/sms_no_alter_body/README.rst b/odex25_donation/sms_no_alter_body/README.rst new file mode 100644 index 000000000..83c555680 --- /dev/null +++ b/odex25_donation/sms_no_alter_body/README.rst @@ -0,0 +1,74 @@ +================= +SMS no atler body +================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fconnector--telephony-lightgray.png?logo=github + :target: https://github.com/OCA/connector-telephony/tree/14.0/sms_no_alter_body + :alt: OCA/connector-telephony +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/connector-telephony-14-0/connector-telephony-14-0-sms_no_alter_body + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/228/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Skipping the formatting of sms between html and text by using the original "body" of messages. +For exemple, this module cancels the duplicate URL at the sms's end. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Akretion + +Contributors +~~~~~~~~~~~~ + +Kévin Roche + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/connector-telephony `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/odex25_donation/sms_no_alter_body/__init__.py b/odex25_donation/sms_no_alter_body/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/odex25_donation/sms_no_alter_body/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/odex25_donation/sms_no_alter_body/__manifest__.py b/odex25_donation/sms_no_alter_body/__manifest__.py new file mode 100644 index 000000000..1b13f4659 --- /dev/null +++ b/odex25_donation/sms_no_alter_body/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2021 Akretion (https://www.akretion.com). +# @author Kévin Roche +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "SMS no atler body", + "summary": "Avoid sms formatting between html and text", + "version": "14.0.1.0.0", + "category": "Phone", + "website": "https://github.com/OCA/connector-telephony", + "author": "Akretion, Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "depends": [ + "sms", + ], +} diff --git a/odex25_donation/sms_no_alter_body/models/__init__.py b/odex25_donation/sms_no_alter_body/models/__init__.py new file mode 100644 index 000000000..ee0d881a0 --- /dev/null +++ b/odex25_donation/sms_no_alter_body/models/__init__.py @@ -0,0 +1,2 @@ +from . import sms_sms +from . import mail_thread diff --git a/odex25_donation/sms_no_alter_body/models/mail_thread.py b/odex25_donation/sms_no_alter_body/models/mail_thread.py new file mode 100644 index 000000000..3d450d53b --- /dev/null +++ b/odex25_donation/sms_no_alter_body/models/mail_thread.py @@ -0,0 +1,14 @@ +# Copyright (C) 2021 Akretion (). +# @author Kévin Roche +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class MailThread(models.AbstractModel): + _inherit = "mail.thread" + + @api.returns("mail.message", lambda value: value.id) + def _message_sms(self, body, **kwargs): + self = self.with_context(force_sms_body=body) + return super()._message_sms(body, **kwargs) diff --git a/odex25_donation/sms_no_alter_body/models/sms_sms.py b/odex25_donation/sms_no_alter_body/models/sms_sms.py new file mode 100644 index 000000000..6217d83df --- /dev/null +++ b/odex25_donation/sms_no_alter_body/models/sms_sms.py @@ -0,0 +1,16 @@ +# Copyright (C) 2021 Akretion (). +# @author Kévin Roche +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class SmsSms(models.Model): + _inherit = "sms.sms" + + @api.model_create_multi + def create(self, vals_list): + if self._context.get("force_sms_body"): + for vals in vals_list: + vals["body"] = self._context["force_sms_body"] + return super().create(vals_list) diff --git a/odex25_donation/sms_no_alter_body/readme/CONTRIBUTORS.rst b/odex25_donation/sms_no_alter_body/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..45780ad58 --- /dev/null +++ b/odex25_donation/sms_no_alter_body/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +Kévin Roche diff --git a/odex25_donation/sms_no_alter_body/readme/DESCRIPTION.rst b/odex25_donation/sms_no_alter_body/readme/DESCRIPTION.rst new file mode 100644 index 000000000..1371ef280 --- /dev/null +++ b/odex25_donation/sms_no_alter_body/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +Skipping the formatting of sms between html and text by using the original "body" of messages. +For exemple, this module cancels the duplicate URL at the sms's end. diff --git a/odex25_donation/sms_no_alter_body/static/description/icon.png b/odex25_donation/sms_no_alter_body/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/odex25_donation/sms_no_alter_body/static/description/icon.png differ diff --git a/odex25_donation/sms_no_alter_body/static/description/index.html b/odex25_donation/sms_no_alter_body/static/description/index.html new file mode 100644 index 000000000..e33eb7837 --- /dev/null +++ b/odex25_donation/sms_no_alter_body/static/description/index.html @@ -0,0 +1,418 @@ + + + + + + +SMS no atler body + + + +
+

SMS no atler body

+ + +

Beta License: AGPL-3 OCA/connector-telephony Translate me on Weblate Try me on Runbot

+

Skipping the formatting of sms between html and text by using the original “body” of messages. +For exemple, this module cancels the duplicate URL at the sms’s end.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
+
+ +
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/connector-telephony project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/odex25_donation/sms_no_alter_body/tests/__init__.py b/odex25_donation/sms_no_alter_body/tests/__init__.py new file mode 100644 index 000000000..5e28067cb --- /dev/null +++ b/odex25_donation/sms_no_alter_body/tests/__init__.py @@ -0,0 +1 @@ +from . import test_sms_no_alter_body diff --git a/odex25_donation/sms_no_alter_body/tests/test_sms_no_alter_body.py b/odex25_donation/sms_no_alter_body/tests/test_sms_no_alter_body.py new file mode 100644 index 000000000..4e63b171e --- /dev/null +++ b/odex25_donation/sms_no_alter_body/tests/test_sms_no_alter_body.py @@ -0,0 +1,20 @@ +# Copyright (C) 2021 Akretion (). +# @author Kévin Roche +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestSmsNoAlterBody(TransactionCase): + def setUp(self): + super().setUp() + self.partner = self.env["res.partner"].create( + {"name": "FOO", "mobile": "+3360707070707"} + ) + + def test_force_sms_body(self): + message = self.partner._message_sms("Welcome to https://akretion.com/fr") + message_sms_body = ( + self.env["sms.sms"].search([("mail_message_id", "=", message.id)]).body + ) + self.assertEqual(message_sms_body, "Welcome to https://akretion.com/fr") diff --git a/odex25_donation/theme_prime/CHANGELOG.md b/odex25_donation/theme_prime/CHANGELOG.md new file mode 100644 index 000000000..a15a00dde --- /dev/null +++ b/odex25_donation/theme_prime/CHANGELOG.md @@ -0,0 +1,30 @@ +## [16.0.0.0.7] - 02/02/2023 +### Fixed +- Cart lines issue when loyalty installed + +## [16.0.0.0.5] - 07/01/2023 +### Improved +- Apply color for mobile menu same as header which containing logo + +## [16.0.0.0.4] - 27/12/2022 +### Fixed +- Don't cache user info in header + +## [16.0.0.0.3] - 26/12/2022 +### Fixed +- Highlight active menu in menu sidebar + +## [16.0.0.0.2] - 22/12/2022 +### Fixed +- Fix product color preview swatches + +## [16.0.0.0.1] - 20/12/2022 +### Added +- User Guide links + +### Fixed +- Open Sidebar for public user + +## [16.0.0.0.0] +### Added +- Initial release. diff --git a/odex25_donation/theme_prime/COPYRIGHT b/odex25_donation/theme_prime/COPYRIGHT new file mode 100644 index 000000000..e27598c6a --- /dev/null +++ b/odex25_donation/theme_prime/COPYRIGHT @@ -0,0 +1,16 @@ + +Most of the files are + +Copyright (c) 2019 - present Droggol Infotech Private Limited. + +Some javascript files might be from from third +parties libraries. In that case the original +copyright of the contributions can be traced +through the history of the source version +control system. + +When that is not the case, the files contain a prominent +notice stating the original copyright and applicable +license, or come with their own dedicated COPYRIGHT +and/or LICENSE file. + diff --git a/odex25_donation/theme_prime/LICENSE b/odex25_donation/theme_prime/LICENSE new file mode 100644 index 000000000..7a5c68e71 --- /dev/null +++ b/odex25_donation/theme_prime/LICENSE @@ -0,0 +1,27 @@ +Odoo Proprietary License v1.0 + +This software and associated files (the "Software") may only be used (executed, +modified, executed after modifications) if you have purchased a valid license +from the authors, typically via Odoo Apps, or if you have received a written +agreement from the authors of the Software (see the COPYRIGHT file). + +You may develop Odoo modules that use the Software as a library (typically +by depending on it, importing it and using its resources), but without copying +any source code or material from the Software. You may distribute those +modules under the license of your choice, provided that this license is +compatible with the terms of the Odoo Proprietary License (For example: +LGPL, MIT, or proprietary licenses similar to this one). + +It is forbidden to publish, distribute, sublicense, or sell copies of the Software +or modified copies of the Software. + +The above copyright notice and this permission notice must be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/odex25_donation/theme_prime/__init__.py b/odex25_donation/theme_prime/__init__.py new file mode 100644 index 000000000..3a586451a --- /dev/null +++ b/odex25_donation/theme_prime/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from . import controllers +from . import models diff --git a/odex25_donation/theme_prime/__manifest__.py b/odex25_donation/theme_prime/__manifest__.py new file mode 100644 index 000000000..a1e64082a --- /dev/null +++ b/odex25_donation/theme_prime/__manifest__.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +{ + 'name': 'Theme Prime', + 'description': 'Powerful multipurpose eCommerce theme suitable for all kind of businesses like Electronics, Fashion, Sports, Beauty, Furniture and many more.', + 'summary': 'Powerful multipurpose eCommerce theme suitable for all kind of businesses like Electronics, Fashion, Sports, Beauty, Furniture and many more.', + 'category': 'Theme/eCommerce', + 'version': '16.0.0.0.8', + 'depends': ['droggol_theme_common'], + + 'license': 'OPL-1', + 'author': 'Droggol Infotech Private Limited', + 'company': 'Droggol Infotech Private Limited', + 'maintainer': 'Droggol Infotech Private Limited', + 'website': 'https://www.droggol.com/', + + 'price': 289.00, + 'currency': 'USD', + 'live_test_url': 'https://prime-16-electronics-1.droggol.com/', + + 'images': [ + 'static/description/prime_cover.png', + 'static/description/prime_screenshot.gif', + ], + 'data': [ + 'data/theme.ir.attachment.csv', + + 'views/sidebar.xml', + 'views/templates.xml', + 'views/components.xml', + 'views/layout.xml', + 'views/shop_layout.xml', + 'views/product_detail_page.xml', + 'views/pages.xml', + 'views/snippets.xml', + 'views/svg_images.xml', + + # Headers / Footers + 'views/headers.xml', + 'views/preheaders.xml', + 'views/footers.xml', + + # Snippets + 'views/snippets/dynamic_snippets.xml', + 'views/snippets/s_banner.xml', + 'views/snippets/s_blog.xml', + 'views/snippets/s_clients.xml', + 'views/snippets/s_coming_soon.xml', + 'views/snippets/s_countdown.xml', + 'views/snippets/s_cover.xml', + 'views/snippets/s_cta.xml', + 'views/snippets/s_gallery.xml', + 'views/snippets/s_heading.xml', + 'views/snippets/s_icon_block.xml', + 'views/snippets/s_info_block.xml', + 'views/snippets/s_pricing.xml', + 'views/snippets/s_shop_offer.xml', + 'views/snippets/s_stats.xml', + 'views/snippets/s_subscribe.xml', + 'views/snippets/s_team.xml', + 'views/snippets/s_testimonial.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'theme_prime/static/src/components/dialog.xml', + 'theme_prime/static/src/components/record_selection.xml', + 'theme_prime/static/src/components/ui_component.xml', + 'theme_prime/static/src/components/search_input.xml', + 'theme_prime/static/src/components/dropdown.xml', + + 'theme_prime/static/src/components/dialog.js', + 'theme_prime/static/src/components/abstract_component.js', + 'theme_prime/static/src/components/theme_service.js', + 'theme_prime/static/src/components/dialog.scss', + 'theme_prime/static/src/components/record_selection.js', + 'theme_prime/static/src/components/ui_component.js', + 'theme_prime/static/src/components/search_input.js', + ], + 'web.assets_frontend': [ + # Libraries + 'theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.carousel.css', + 'theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.theme.default.css', + # Frontend + 'theme_prime/static/src/js/website.js', + 'theme_prime/static/src/js/website_sale.js', + 'theme_prime/static/src/js/website_sale_wishlist.js', + + 'theme_prime/static/src/js/sidebar.js', + 'theme_prime/static/src/xml/sidebar.xml', + + 'theme_prime/static/src/js/suggested_product_slider.js', + 'theme_prime/static/src/xml/frontend/suggested_product_slider.xml', + + 'theme_prime/static/src/js/service_worker_register.js', + 'theme_prime/static/src/xml/pwa.xml', + + 'theme_prime/static/src/js/core/mixins.js', + 'theme_prime/static/src/js/frontend/comparison.js', + 'theme_prime/static/src/js/frontend/quick_view_dialog.js', + 'theme_prime/static/src/js/frontend/bottombar.js', + + 'theme_prime/static/src/scss/theme.scss', + 'theme_prime/static/src/scss/rtl.scss', + 'theme_prime/static/src/scss/website.scss', + 'theme_prime/static/src/scss/website_sale.scss', + 'theme_prime/static/src/scss/sliders.scss', + 'theme_prime/static/src/scss/icon-packs/website.scss', + 'theme_prime/static/src/scss/utils.scss', + 'theme_prime/static/src/scss/snippets/cards.scss', + 'theme_prime/static/src/scss/front_end/quick_view.scss', + 'theme_prime/static/src/scss/front_end/dynamic_snippets.scss', + 'theme_prime/static/src/scss/front_end/category_filters.scss', + 'theme_prime/static/src/scss/front_end/image_hotspot.scss', + 'theme_prime/static/src/scss/snippets/2_col_deal.scss', + 'theme_prime/static/src/scss/snippets/image_products.scss', + 'theme_prime/static/src/scss/front_end/bottom_bar.scss', + 'theme_prime/static/src/snippets/s_blog_posts/000.scss', + # Core + 'theme_prime/static/src/js/core/snippet_root_widget.js', + 'theme_prime/static/src/xml/core/snippet_root_widget.xml', + + 'theme_prime/static/src/js/core/product_root_widget.js', + + 'theme_prime/static/src/js/core/cart_manager.js', + 'theme_prime/static/src/xml/frontend/notification_template.xml', + + 'theme_prime/static/src/js/core/cart_confirmation_dialog.js', + 'theme_prime/static/src/xml/core/cart_confirmation_dialog.xml', + + # Snippets + 'theme_prime/static/src/snippets/s_tp_countdown/000.xml', + 'theme_prime/static/src/js/frontend/dynamic_snippets.js', + 'theme_prime/static/src/xml/frontend/dynamic_snippets.xml', + 'theme_prime/static/src/xml/cards.xml', + 'theme_prime/static/src/xml/listing_cards.xml', + 'theme_prime/static/src/xml/frontend/utils.xml', + 'theme_prime/static/src/xml/frontend/category_filters.xml', + 'theme_prime/static/src/xml/frontend/2_col_deal.xml', + 'theme_prime/static/src/xml/frontend/s_image_products.xml', + 'theme_prime/static/src/xml/frontend/s_product_grid.xml', + 'theme_prime/static/src/xml/frontend/hierarchical_category_templates.xml', + 'theme_prime/static/src/xml/frontend/s_category.xml', + 'theme_prime/static/src/xml/frontend/brands.xml', + 'theme_prime/static/src/xml/frontend/image_hotspot.xml', # TODO: kishan + + # Editor + ('replace', 'web_editor/static/src/scss/web_editor.frontend.scss', 'theme_prime/static/src/scss/web_editor.frontend.scss'), + + # Search + 'theme_prime/static/src/js/frontend/search.js', + 'theme_prime/static/src/xml/frontend/search_autocomplete.xml', + ], + 'web._assets_primary_variables': [ + 'theme_prime/static/src/scss/primary_variables.scss', + 'theme_prime/static/src/scss/mixins.scss', + ], + 'web._assets_frontend_helpers': [ + 'theme_prime/static/src/scss/bootstrap_overridden.scss', + ], + 'website.assets_wysiwyg': [ + 'theme_prime/static/src/js/editor/snippets.editor.js', + 'theme_prime/static/src/scss/editor/editor.scss', + + # 'theme_prime/static/src/scss/editor/dialogs/dialog_snippet_configurator.scss', + 'theme_prime/static/src/xml/editor/dialogs/snippet_configurator_dialog.xml', + 'theme_prime/static/src/xml/frontend/image_hotspot.xml', + + 'theme_prime/static/src/js/editor/snippets/snippets.options.js', + 'theme_prime/static/src/js/editor/registries.js', + 'theme_prime/static/src/xml/frontend/documents.xml', + ], + + }, +} diff --git a/odex25_donation/theme_prime/controllers/__init__.py b/odex25_donation/theme_prime/controllers/__init__.py new file mode 100644 index 000000000..ef9adf569 --- /dev/null +++ b/odex25_donation/theme_prime/controllers/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from . import main diff --git a/odex25_donation/theme_prime/controllers/main.py b/odex25_donation/theme_prime/controllers/main.py new file mode 100644 index 000000000..773247452 --- /dev/null +++ b/odex25_donation/theme_prime/controllers/main.py @@ -0,0 +1,930 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +import base64 +import hashlib +import io +import json +import re +import string +from collections import defaultdict +from datetime import datetime, timedelta +from functools import partial + +try: + from werkzeug.utils import send_file +except ImportError: + from odoo.tools._vendor.send_file import send_file + +from odoo import _, http +from odoo.addons.website.controllers.main import Website +from odoo.addons.website_sale.controllers.main import WebsiteSale +from odoo.addons.website_sale_wishlist.controllers.main import WebsiteSaleWishlist +from odoo.http import request +from odoo.modules.module import get_resource_path +from odoo.osv import expression +from odoo.tools import html_escape +from odoo.tools.mimetypes import guess_mimetype + + +class ThemePrimeWebsiteSale(WebsiteSale): + + def _get_search_domain(self, search, category, attrib_values, search_in_description=True, search_rating=True): + """ Overrided method used to apply extra filters. + + Extra parameters are added to skip some filters (Used for attribute count) + :param search_rating: if false rating domain will not be added + """ + domains = super()._get_search_domain(search, category, attrib_values, search_in_description) + + # Hide out of stock + if request.httprequest.args.get('hide_out_of_stock'): + domains = expression.AND([domains, ['|', '|', ('detailed_type', '!=', 'product'), ('allow_out_of_stock_order', '=', True), '&', ('dr_free_qty', '>', 0), ('allow_out_of_stock_order', '=', False)]]) + + # Tag + tag = request.httprequest.args.getlist('tag') + if tag: + domains = expression.AND([domains, [('product_tag_ids', 'in', [int(x) for x in tag])]]) + + # Rating + ratings = request.httprequest.args.getlist('rating') + if ratings and search_rating: + result = request.env['rating.rating'].sudo().read_group([('res_model', '=', 'product.template')], ['rating:avg'], groupby=['res_id'], lazy=False) + rating_product_ids = [] + for rating in ratings: + rating_product_ids.extend([item['res_id'] for item in result if item['rating'] >= int(rating)]) + if rating_product_ids: + domains = expression.AND([domains, [('id', 'in', rating_product_ids)]]) + else: + domains = expression.AND([domains, [('id', 'in', [])]]) + return domains + + def _get_search_options(self, category=None, attrib_values=None, pricelist=None, min_price=0.0, max_price=0.0, conversion_rate=1, **post): + res = super()._get_search_options(category=category, attrib_values=attrib_values, pricelist=pricelist, min_price=min_price, max_price=max_price, conversion_rate=conversion_rate, **post) + if request.httprequest.args.get('hide_out_of_stock'): + res['hide_out_of_stock'] = request.httprequest.args.get('hide_out_of_stock') + if request.httprequest.args.getlist('tag'): + res['tag'] = request.httprequest.args.getlist('tag') + if request.httprequest.args.getlist('rating'): + res['rating'] = request.httprequest.args.getlist('rating') + return res + + def _shop_get_query_url_kwargs(self, category, search, min_price, max_price, **post): + result = super()._shop_get_query_url_kwargs(category, search, min_price, max_price, **post) + result.update( + view_mode=post.get('view_mode'), + hide_out_of_stock=post.get('hide_out_of_stock'), + tag=post.get('tag'), + rating=post.get('rating'), + ) + return result + + @http.route() + def shop(self, page=0, category=None, search='', min_price=0.0, max_price=0.0, ppg=False, **post): + response = super().shop(page=page, category=category, search=search, min_price=min_price, max_price=max_price, ppg=ppg, **post) + theme_id = request.website.sudo().theme_id + if theme_id and theme_id.name.startswith('theme_prime'): + ProductTemplate = request.env['product.template'] + request_args = request.httprequest.args + + attrib_list = request_args.getlist('attrib') + attrib_values = [[int(x) for x in v.split('-')] for v in attrib_list if v] + attributes_ids = [v[0] for v in attrib_values] + + fuzzy_search_term = response.qcontext.get('search') or search + if request.website._get_dr_theme_config('json_shop_filters')['show_category_count']: + # Categories + domain = self._get_search_domain(fuzzy_search_term, None, attrib_values) + response.qcontext.update(get_category_count=ProductTemplate._get_product_category_count(domain=domain)) + if request.website._get_dr_theme_config('json_shop_filters')['show_attribute_count'] or request.website._get_dr_theme_config('json_shop_filters')['hide_extra_attrib_value']: + # Attributes + domain = self._get_search_domain(fuzzy_search_term, category, []) + response.qcontext.update(get_attrib_count=ProductTemplate._get_product_attrib_count(attrib_values, domain=domain)) + # Rating + domain = self._get_search_domain(fuzzy_search_term, category, attrib_values, search_rating=False) + response.qcontext.update(get_ratings_count=ProductTemplate._get_product_rating_count(domain=domain)) + + selected_tags = [int(x) for x in request_args.getlist('tag')] + selected_ratings = [int(x) for x in request_args.getlist('rating')] + selected_hide_out_of_stock = request_args.get('hide_out_of_stock') + + _config_shop_layout = request.website._get_dr_theme_config('json_shop_layout') + if _config_shop_layout.get('layout') == 'prime': + response.template = 'theme_prime.shop_layout' + + response.qcontext.update( + _config_shop_layout=_config_shop_layout, + _config_product_item=request.website._get_dr_theme_config('json_shop_product_item'), + _config_shop_filters=request.website._get_dr_theme_config('json_shop_filters'), + _config_category_pills=request.website._get_dr_theme_config('json_shop_category_pills'), + view_mode=request_args.get('view_mode', _config_shop_layout.get('default_view_mode')), + page=page, + tags=request.env['product.tag'].search(request.website.website_domain()), + attributes_ids=attributes_ids, + selected_tags=selected_tags, + selected_ratings=selected_ratings, + selected_hide_out_of_stock=selected_hide_out_of_stock, + selected_attributes=response.qcontext.get('attrib_set') or request_args.get('min_price') or request_args.get('max_price') or selected_tags or selected_ratings or selected_hide_out_of_stock + ) + return response + + def _prepare_product_values(self, product, category, search, **kwargs): + res = super()._prepare_product_values(product, category, search, **kwargs) + if request.website._get_dr_theme_config('bool_show_products_nav'): + ProductTemplate = request.env['product.template'] + res['prev_product_id'] = ProductTemplate.search([('website_sequence', '<', product.website_sequence)] + request.website.website_domain(), limit=1, order='website_sequence desc') + res['next_product_id'] = ProductTemplate.search([('website_sequence', '>', product.website_sequence)] + request.website.website_domain(), limit=1, order='website_sequence') + return res + + @http.route(['/shop/cart'], type='http', auth='public', website=True, sitemap=False) + def cart(self, access_token=None, revive='', **post): + res = super(ThemePrimeWebsiteSale, self).cart(access_token=access_token, revive=revive, **post) + if post.get('type') == 'tp_cart_sidebar_request': + order = request.website.sale_get_order() + if order and order.state != 'draft': + request.session['sale_order_id'] = None + return request.render('theme_prime.cart_sidebar', {'order': order}, headers={'Cache-Control': 'no-cache'}) + return res + + @http.route('/theme_prime/get_search_sidebar', type='http', auth='public', website=True, sitemap=False) + def search_sidebar(self, **post): + return request.render('theme_prime.search_sidebar') + + @http.route('/theme_prime/get_categories_list', type='json', auth='public', website=True, sitemap=False) + def _get_categories_list(self, **post): + return { + 'categories': request.env['product.public.category'].search_read(request.website.website_domain()), + 'category_count': request.env['product.template']._get_product_category_count(domain=request.website.website_domain()) if request.website._get_dr_theme_config('json_sidebar_config').get('category_sidebar_show_count') else {}, + } + + @http.route('/theme_prime/get_quick_view_html', type='json', auth='public', website=True) + def get_quick_view_html(self, options, **kwargs): + IrUiView = request.env['ir.ui.view'] + productID = options.get('productID') + variantID = options.get('variantID') + if variantID: + productID = request.env['product.product'].browse(variantID).product_tmpl_id.id + domain = expression.AND([request.website.sale_product_domain(), [('id', '=', productID)]]) + product = request.env['product.template'].search(domain, limit=1) + + # If moved to another website or delete + if not product: + return False + + values = self._prepare_product_values(product, category='', search='', **kwargs) + result = request.website.get_theme_prime_shop_config() + values.update(result) + values['d_url_root'] = request.httprequest.url_root[:-1] + + if options.get('variant_selector'): + values['auto_add_product'] = product.product_variant_count == 1 + return IrUiView._render_template('theme_prime.product_variant_selector_dialog', values=values) + + if options.get('right_panel'): + return IrUiView._render_template('theme_prime.tp_product_right_panel', values=values) + return IrUiView._render_template('theme_prime.tp_product_quick_view', values=values) + + @http.route(['/shop/cart/update_json'], type='json', auth="public", methods=['POST'], website=True, csrf=False) + def cart_update_json(self, product_id, line_id=None, add_qty=None, set_qty=None, display=True, **kw): + response = super(ThemePrimeWebsiteSale, self).cart_update_json(product_id, line_id=line_id, add_qty=add_qty, set_qty=set_qty, display=display, **kw) + + if kw.get('dr_cart_flow') and response: + sale_order = request.website.sale_get_order(force_create=True) + monetary_options = {'display_currency': sale_order.pricelist_id.currency_id} + FieldMonetary = request.env['ir.qweb.field.monetary'] + cart_amount_html = FieldMonetary.value_to_html(sale_order.amount_total, monetary_options) + product = request.env['product.product'].browse(int(product_id)) + response.update({ + 'cart_quantity': sale_order.cart_quantity, + 'product_name': product.name, + 'product_id': int(product_id), + 'cart_amount_html': cart_amount_html, + 'accessory_product_ids': product.accessory_product_ids and product.accessory_product_ids.mapped('product_tmpl_id').ids or [] + }) + + return response + + +class DroggolWishlist(WebsiteSaleWishlist): + @http.route('/theme_prime/wishlist_general', auth="public", type='json', website=True) + def wishlist_general(self, product_id=False, **post): + res = {} + if product_id: + res['wishlist_id'] = self.add_to_wishlist(product_id).id + res.update({ + 'products': request.env['product.wishlist'].with_context(display_default_code=False).current().mapped('product_id').ids, + 'name': request.env['product.product'].browse(product_id).name + }) + return res + + +class ThemePrimeMainClass(http.Controller): + + # ---------------------------------------------------------- + # Helper methods + # ---------------------------------------------------------- + + def _get_products(self, domain=None, fields=[], limit=25, order=None, options={}): + pricelist = request.website.get_current_pricelist() + website_sale_domain = request.website.sale_product_domain() + final_domain = expression.AND([website_sale_domain, domain]) + + # bestseller is not a real field + bestseller_ids, old_limit = [], limit + if order == 'bestseller': + bestseller_ids, limit, order = self._get_bestseller_products(old_limit) + + products = request.env['product.template'].with_context(pricelist=pricelist.id).search(final_domain, limit=limit, order=order) + + default_fields = ['id', 'name', 'website_url', 'default_code'] + fields = set(default_fields + fields) + + if bestseller_ids: + bestseller_ids_filtered = set(bestseller_ids) & set(products.ids) + bestseller_sorted_ids = [p_id for p_id in bestseller_ids if p_id in bestseller_ids_filtered] + remain_products = set(products.ids) - set(bestseller_sorted_ids) + final_product_ids = bestseller_sorted_ids + list(remain_products) + products = request.env['product.template'].with_context(pricelist=pricelist.id).browse(final_product_ids[:old_limit]) + + return self._prepare_product_data(products, fields) + + def _prepare_product_data(self, products, fields, options=None): + + options = options or {} + pricelist = request.website.get_current_pricelist() + price_public_visibility = request.website._dr_has_b2b_access() + visibility_label = False + showStockLabel = False + + if not price_public_visibility: + visibility_label = self._get_tp_view_template('theme_prime.tp_b2b_price_label') + + extra_data = {'rating', 'offer_data', 'dr_stock_label', 'colors'} & set(fields) + fields = list(set(fields) - extra_data) + + if 'dr_stock_label' in extra_data: + showStockLabel = request.website._get_dr_theme_config('json_shop_product_item').get('show_stock_label') + currency_id = pricelist.currency_id + + result = products.read(fields) + + for res_product, product in zip(result, products): + combination_info = product._get_combination_info(only_template=True) + res_product.update(combination_info) + price_info = self._get_computed_product_price(product, res_product, price_public_visibility, visibility_label, currency_id) + res_product.update(price_info) + res_product['product_variant_id'] = product._get_first_possible_variant_id() + + sha = hashlib.sha1(str(getattr(product, '__last_update')).encode('utf-8')).hexdigest()[0:7] + # Images + res_product['img_small'] = '/web/image/product.template/' + str(product.id) + '/image_256?unique=' + sha + res_product['img_medium'] = '/web/image/product.template/' + str(product.id) + '/image_512?unique=' + sha + res_product['img_large'] = '/web/image/product.template/' + str(product.id) + '/image_1024?unique=' + sha + + # short Description + if 'description_sale' in fields: + description = res_product.get('description_sale') + res_product['short_description'] = description[:125] + '...' if description and len(description) > 125 else description or False + # label and color + if 'colors' in extra_data: + res_product['colors'] = self._get_tp_view_template('theme_prime.product_preview_swatches', {'product': product, '_limit': 4, 'parent_selector': '.card', 'img_selector': '.d-product-img'}) + # label and color + if 'dr_label_id' in fields and product.dr_label_id: + res_product['label'] = product.dr_label_id + res_product['label_id'] = product.dr_label_id.id + res_product['label_template'] = self._get_tp_view_template('theme_prime.product_label', {'label': product.dr_label_id}) + if 'dr_stock_label' in extra_data and showStockLabel and product.dr_show_out_of_stock: + res_product['dr_stock_label'] = self._get_tp_view_template('theme_prime.product_label', {'product': product, 'stock': True}) + res_product['dr_show_out_of_stock'] = product.dr_show_out_of_stock + # rating + if 'offer_data' in extra_data: + offer = product._get_product_pricelist_offer() + if offer: + rule = offer.get('rule') + res_product['offer_data'] = { + 'date_end': offer.get('date_end'), + 'offer_msg': rule.dr_offer_msg, + 'offer_finish_msg': rule.dr_offer_finish_msg + } + + if 'rating' in extra_data: + res_product['rating'] = self._get_rating_template(product.rating_avg) + res_product['rating_avg'] = product.rating_avg + # images + if 'product_variant_ids' in fields: + res_product['images'] = product.product_variant_ids.ids + # website_category + if 'public_categ_ids' in fields and product.public_categ_ids: + first_category = product.public_categ_ids[0] + res_product['category_info'] = { + 'name': first_category.name, + 'id': first_category.id, + 'website_url': '/shop/category/' + str(first_category.id), + } + # brand + if 'dr_brand_value_id' in fields: + res_product['brand_info'] = False + if product.dr_brand_value_id: + res_product['brand_info'] = { + 'name': product.dr_brand_value_id.name, + 'id': product.dr_brand_value_id.id, + } + + return result + + def _get_computed_product_price(self, product, product_data, price_public_visibility, visibility_label, currency_id): + FieldMonetary = request.env['ir.qweb.field.monetary'] + monetary_options = {'display_currency': currency_id} + return { + 'visibility': price_public_visibility, + 'price_raw': product_data['price'] if price_public_visibility else visibility_label, + 'list_price_raw': product_data['list_price'] if price_public_visibility else ' ', + 'price': FieldMonetary.value_to_html(product_data['price'], monetary_options) if price_public_visibility else visibility_label, + 'list_price': FieldMonetary.value_to_html(product_data['list_price'], monetary_options) if price_public_visibility else ' ' + } + + def _get_tp_view_template(self, tmpl, values={}): + IrUiView = request.env['ir.ui.view'] + return IrUiView._render_template(tmpl, values=values) + + def _get_bestseller_products(self, old_limit): + past_date = datetime.now() - timedelta(days=30) + result = request.env['sale.report'].sudo().read_group([('date', '>', past_date), ('website_id', '=', request.website.id), ('state', 'in', ['sale', 'done'])], ['product_tmpl_id', 'product_uom_qty:sum'], ['product_tmpl_id'], orderby="product_uom_qty desc") + return [product_line['product_tmpl_id'][0] for product_line in result], None if len(result) else old_limit, None + + def _get_shop_related_data(self, options): + shop_data = {} + if (options.get('shop_config_params')): + shop_data['shop_config_params'] = request.website.get_theme_prime_shop_config() + if (options.get('wishlist_enabled')) and shop_data.get('shop_config_params', {}).get('is_wishlist_active'): + shop_data['wishlist_products'] = request.env['product.wishlist'].with_context(display_default_code=False).current().mapped('product_id').ids + return shop_data + + def _get_rating_template(self, rating_avg, rating_count=False): + return request.website._get_theme_prime_rating_template(rating_avg, rating_count) + + def _get_categories(self, domain=[], fields=['name', 'display_name', 'id'], limit=20, order=None, extras={}): + final_domain = expression.AND([request.website.website_domain(), domain]) + final_list = False + # Pure Shit + if extras.get('count', False): + count_dict = {k: v for k, v in sorted(self.get_categories_count().items(), key=lambda item: item[1], reverse=True)} + if order == 'count': + order = 'sequence asc' + category_ids = count_dict.keys() + final_list = [i for i in category_ids if i not in extras.get('ids', [])][:limit] + final_domain = expression.AND([[['id', 'in', final_list]], final_domain]) + result = request.env['product.public.category'].search_read(final_domain, fields=fields + ['display_name'], limit=limit, order=order) + for res in result: + if extras.get('count', False): + res.update({'count': count_dict.get(res.get('id'))}) + if final_list: + final_result = [] + for res_id in final_list: + for res in result: + if res.get('id') == res_id: + final_result.append(res) + return final_result + return result + + def _get_products_for_top_categories(self, params): + result = {} + categoryIDs = params.get('categoryIDs') + order = params.get('sortBy') + operator = '=' + if params.get('includesChild'): + operator = 'child_of' + initial_domain = expression.AND([request.website.website_domain(), [('website_published', '=', True)]]) + for id in categoryIDs: + domain = expression.AND([initial_domain, [['public_categ_ids', operator, id]]]) + products = self._get_products(domain, ['id'], 4, order) + result[id] = [product['id'] for product in products] + return result + + @http.route('/theme_prime/tp_search_read', type='json', auth='public', website=True, sitemap=False) + def _tp_search_read(self, model, domain=None, fields=[], order=None, limit=20, extras={}, **post): + if model == 'product.template': + return self._get_products(domain, fields, limit, order) + elif model == 'product.public.category': + extras.update({'count': True}) + return self._get_categories(domain, fields, limit, order, extras) + elif model == 'product.attribute.value': + if extras.get('brands'): + brand_attributes = request.website._get_brand_attributes() + domain = expression.AND([domain, [('attribute_id', 'in', brand_attributes.ids)]]) + return request.env[model].with_context(show_attribute=False).search_read(domain, fields=fields, limit=limit, order=order) + return request.env[model].search_read(domain, fields=fields, limit=limit, order=order) + elif model in ['dr.product.label', 'product.tag']: + return request.env[model].search_read(domain, fields=fields, limit=limit, order=order) + elif model == 'ir.ui.view': + tmpl = request.env.ref(extras.get('templateID')) + return { + 'name': tmpl.name, + 'content': request.env[model]._render_template(extras.get('templateID')) + } + + @http.route('/theme_prime/get_similar_products_sidebar', type='http', auth='public', website=True, sitemap=False) + def _get_similar_products_sidebar(self, productID, **post): + product_tmpl_id = request.env['product.template'].browse(int(productID)) + return request.render('theme_prime.similar_products_sidebar', {'products': product_tmpl_id.alternative_product_ids}, headers={'Cache-Control': 'no-cache'}) + + @http.route('/theme_prime/get_tab_listing_products', type='json', auth='public', website=True) + def get_tab_listing_products(self, domain=None, fields=[], options={}, limit=25, order=None, **kwargs): + result = {} + if options.get('categoryID', False): + category_domain = [('id', '=', options.get('categoryID'))] + category = self._get_categories(category_domain) + if category: + result['listing_category'] = category + domain = expression.AND([domain, [('public_categ_ids', 'child_of', options.get('categoryID'))]]) + result['products'] = self._get_products(domain, fields, limit, order) + result.update(self._get_shop_related_data(options)) + return result + + @http.route('/theme_prime/get_listing_products', type='json', auth='public', website=True) + def get_listing_products(self, domain=None, fields=[], options={}, limit=5, **kwargs): + result = {} + # [TO-DO] even snippet don't allow manual selection it will set the attrs + domain = None if options.get('mode') == 'manual' else domain + if options.get('bestseller'): + result['bestseller'] = self._get_products(domain, fields, limit, 'bestseller') + if options.get('newArrived'): + result['newArrived'] = self._get_products(domain, fields, limit, 'create_date desc') + if options.get('discount'): + if domain: + domain = expression.AND([[("dr_has_discount", "!=", False)], domain]) + else: + domain = [["dr_has_discount", "!=", False]] + result['discount'] = self._get_products(domain, fields, limit) + final = {} + final['products'] = result + final.update(self._get_shop_related_data(options)) + return final + + @http.route('/theme_prime/get_products_data', type='json', auth='public', website=True) + def get_products_data(self, domain=None, fields=[], options={}, limit=25, order=None, **kwargs): + result = { + 'products': self._get_products(domain, fields, limit, order), + } + result.update(self._get_shop_related_data(options)) + return result + + @http.route('/theme_prime/get_products_by_category', type='json', auth='public', website=True) + def get_products_by_category(self, domain, fields=[], options={}, **kwargs): + final_domain = expression.AND([[('website_published', '=', True)], domain]) + result = { + 'products': self._get_products(domain=final_domain, fields=fields, order=options.get('order', False), limit=options.get('limit', False)), + } + result.update(self._get_shop_related_data(options)) + if (options.get('get_categories')): + # get category names for snippet + domain = [('id', 'in', options.get('categoryIDs'))] + result['categories'] = self._get_categories(domain) + if (options.get('get_brands')): + # get category names for snippet + domain = [('id', 'in', options.get('categoryIDs'))] + result['categories'] = request.website._get_brands(domain).read(['name', 'id']) + return result + + @http.route('/theme_prime/get_top_categories', type='json', auth='public', website=True) + def get_top_categories(self, options={}): + params = options.get('params') + result = [] + website_sale_domain = request.website.sale_product_domain() + if params: + categoryIDs = params.get('categoryIDs') + if categoryIDs: + domain = [('id', 'in', categoryIDs)] + category_names = {i['id']: i['name'] for i in self._get_categories(domain)} + # Update categoryIDs if already set category moved to other website + categoryIDs = category_names.keys() + params['categoryIDs'] = categoryIDs + categories = self._get_products_for_top_categories(params) + price_public_visibility = request.website._dr_has_b2b_access() + for category_id in categoryIDs: + category_data = {} + product_ids = categories.get(category_id) + category_data['name'] = category_names.get(category_id) + category_data['id'] = category_id + category_data['website_url'] = '/shop/category/' + str(category_id) + category_data['productIDs'] = product_ids + final_domain = expression.AND([website_sale_domain, [('public_categ_ids', 'child_of', category_id)]]) + products = self._get_products(domain=final_domain, fields=[], limit=1, order="list_price asc") + if len(products): + category_data['min_price'] = products[0].get('price') + category_data['price_public_visibility'] = price_public_visibility + result.append(category_data) + return result + + @http.route(['/theme_prime/get_dialog_content'], type='json', website=True, auth="public") + def get_dialog_content(self, res_id, res_model, fields, **post): + return request.env[res_model].sudo().search_read([('id', '=', res_id)], fields=fields) + + @http.route('/theme_prime/get_categories_count', type='json', auth='public', website=True) + def get_categories_count(self): + return request.env['product.template']._get_product_category_count(domain=request.env['website'].sale_product_domain()) + + @http.route('/theme_prime/get_categories_info', type='json', auth='public', website=True) + def get_categories_info(self, fields=[], options={}, **kwargs): + categoryIDs = options.get('categoryIDs', []) + fields = ['name', 'display_name', 'id'] + fields + domain = expression.AND([request.website.website_domain(), [('id', 'in', categoryIDs)]]) + categories = request.env['product.public.category'].search(domain) + result = categories.read(fields) + if options.get('getCount', False): + get_category_count = self.get_categories_count() + for res_category, category in zip(result, categories): + if 'dr_category_label_id' in fields and category.dr_category_label_id: + category_label = category.dr_category_label_id + res_category['category_lable_info'] = { + 'id': category_label.id, + 'name': category_label.name, + 'background_color': category_label.background_color, + 'text_color': category_label.text_color, + } + if options.get('getCount', False): + res_category['count'] = get_category_count.get(category.id) + res_category['website_url'] = '/shop/category/' + str(category.id) + res_category['image_url'] = '/web/image?model=product.public.category&id=%d&field=image_512' % (category.id) + res_category['cover_image'] = '/web/image?model=product.public.category&id=%d&field=dr_category_cover_image' % (category.id) + return result + + @http.route('/theme_prime/get_brands', type='json', auth='public', website=True) + def get_brands(self, fields=['id', 'name', 'attribute_id'], options={}): + if options.get('categories'): + domain = expression.AND([request.website.sale_product_domain(), [('public_categ_ids', 'child_of', options.get('categories'))]]) + brands = request.env['product.template'].search(domain).mapped('dr_brand_value_id')[:options.get('limit', 12)] + else: + brands = request.website._get_brands([], options.get('limit', 12)) + domain = request.env['website'].sale_product_domain() + get_attrib_count = request.env['product.template']._get_product_attrib_count(attrib_values=[[brand.attribute_id.id, brand.id] for brand in brands], domain=domain) + return [{**brand_data, 'product_count': get_attrib_count.get(brand_data['id'], 0)} for brand_data in brands.read(fields)] + + @http.route('/theme_prime/get_preview_body', type='http', auth="user", website=True, sitemap=False, multilang=False) + def get_preview_body(self, **kw): + return request.env['ir.ui.view']._render_template('theme_prime.tp_preview_body', {'mobile': kw.get('mobile')}) + + @http.route('/theme_prime/get_megamenu_categories', type='json', auth='public', website=True) + def get_megamenu_categories(self, options={}, limit=5, fields=['name', 'id'], order='count', **kwargs): + category_ids = request.env['product.public.category'].browse(options.get('categoryIDs', [])).exists().ids + final_domain = expression.AND([request.website.website_domain(), [('parent_id', 'child_of', category_ids)]]) + categories = request.env['product.public.category'].search(final_domain, limit=None) + + all_categories = [] + all_category_count = request.env['product.template']._get_product_category_count(request.env['website'].sale_product_domain()) + for category in categories: + all_categories.append({ + 'id': category.id, 'name': category.name, 'parent_id': category.parent_id.id, + 'count': all_category_count.get(category['id'], 0), + 'website_url': '/shop/category/' + str(category.id), + 'image_url': '/web/image?model=product.public.category&id=%d&field=image_512' % (category.id), + 'cover_image': '/web/image?model=product.public.category&id=%d&field=dr_category_cover_image' % (category.id), + 'dr_category_icon': '/web/image?model=product.public.category&id=%d&field=dr_category_icon' % (category.id), + 'category_label_info': category.dr_category_label_id and {f: category.dr_category_label_id[f] for f in ['name', 'background_color', 'text_color']} or False, + }) + + parent_categories = filter(lambda category: category.get('id') in category_ids, all_categories) + return [self._get_megamenu_child_categories(category_id, limit, all_categories, order) for category_id in parent_categories] + + def _get_megamenu_child_categories(self, parent_category, limit, all_categories, order): + child_categories = [categ for categ in all_categories if categ.get('parent_id') == parent_category.get('id')] + if not child_categories: + return {'category': parent_category, 'child': []} + if order == 'count' or not order: + child_categories = sorted(child_categories, key=lambda category: category.get('count', 0), reverse=True) + child_categories = child_categories[:limit] + remain_limit = limit - len(child_categories) + + if remain_limit <= 0: + return {'category': parent_category, 'child': child_categories} + + for child_category in child_categories: + new_born_child = self._get_megamenu_child_categories(child_category, remain_limit, all_categories, order).get('child') + child_categories.extend(new_born_child) + remain_limit = limit - len(child_categories) + if remain_limit <= 0: + break + return {'category': parent_category, 'child': child_categories} + + +class ThemeWebsite(Website): + + @http.route('/website/dr_search', type='json', auth="public", website=True) + def dr_search(self, term, max_nb_chars, options, **kw): + + fuzzy_term, global_match = False, False + search_config = request.website._get_dr_theme_config('json_product_search') + has_formulate = self._dr_has_formulate(search_config) + fuzzy_enabled = search_config.get('search_fuzzy') + limit = max(min(search_config.get('search_limit'), 10), 5) + search_types = ['products', 'categories', 'autocomplete', 'suggestions'] + results = {search_type: {'results': [], 'results_count': 0, 'parts': {}} for search_type in search_types} + product_limit = max(min(search_config.get('search_max_product'), 5), 0) + options = {'allowFuzzy': fuzzy_enabled, 'displayDescription': False, 'displayDetail': True, 'displayExtraLink': True, 'displayImage': True} + if product_limit: + results['products'] = self.autocomplete(search_type='products_only', term=term, order='name asc', limit=product_limit, options=options) + product_fuzzy_term = results['products'].get('fuzzy_search') + + if search_config.get('search_category') and not has_formulate: + results['categories'] = self.autocomplete(search_type='product_categories_only', term=term, order='sequence, name, id', limit=5, options=options) + category_fuzzy_term = results['categories'].get('fuzzy_search') + if fuzzy_enabled: + empty_search = {'results': [], 'results_count': 0, 'parts': {}} + if category_fuzzy_term == product_fuzzy_term: + fuzzy_term = product_fuzzy_term + elif not category_fuzzy_term and results['categories'].get('results_count'): + results['products'], fuzzy_term = empty_search, False + elif not product_fuzzy_term and results['products'].get('results_count'): + results['categories'], fuzzy_term = empty_search, False + elif product_fuzzy_term and not category_fuzzy_term: # category will be always empty based on above conditions + fuzzy_term = product_fuzzy_term + elif category_fuzzy_term and not product_fuzzy_term: # products will be always empty based on above conditions + fuzzy_term = category_fuzzy_term + else: # super rare case + all_results = self.autocomplete(search_type='products', term=term, order='sequence, name, id', limit=limit, options=options) + products_result = [res for res in all_results['results'] if res.get('_fa') == 'fa-shopping-cart'] + category_result = [res for res in all_results['results'] if res.get('_fa') == 'fa-folder-o'] + fuzzy_term = all_results.get('fuzzy_search') + results = {'products': {'results': products_result, 'results_count': len(products_result), 'parts': {}}, 'categories': {'results': category_result, 'results_count': len(category_result), 'parts': {}}} + + # suggestion search + if search_config.get('search_attribute') or search_config.get('search_suggestion'): + remain_limit = limit - min(product_limit, results['products'].get('results_count', 0)) # Odoo results_count returns count for full result (without limit) + words = [i for i in term.split(' ') if i] # split and filter spaces + matchs, matched_dicts = False, {} + for word in words: + if matchs: + for match in matchs: + match_dict = matched_dicts[match] + if match_dict['remaining_words']: + match_dict['remaining_words'].append(word) + else: + unmatched_record_name = match_dict['unmatched_record_name'] + regex_match = re.search(re.escape(word), unmatched_record_name, re.IGNORECASE) + if regex_match: + match_dict['matched_words'].append(word) + match_dict['unmatched_record_name'] = re.sub(re.escape(word), ' ', unmatched_record_name, flags=re.I) + else: + match_dict['remaining_words'].append(word) + else: + matchs = self._match_attr_or_category(word) + if matchs: + for match in matchs: + matched_dicts[match] = match_dict = {'match': match, 'matched_words': [word], 'remaining_words': []} + match_dict['unmatched_record_name'] = re.sub(re.escape(match_dict['matched_words'][0]), ' ', match.ds_name, flags=re.I) + + match_list = list(matched_dicts.values()) + match_list.sort(key=lambda m: len(m['matched_words']), reverse=True) + autocomplete_result = [] + + for match_dict in match_list: + autocomplete_data = [] + if match_dict['remaining_words']: + autocomplete_data = self._get_autocomplete_data(match_dict, remain_limit, search_config) + elif not search_config.get('search_category') and match_dict['match']._name == 'product.public.category': + autocomplete_data = [self.generate_result_dict(match_dict['match'], False, match_dict['matched_words'], '')] + if not match_dict['remaining_words']: + # if no remaining_words that means full data matched with record so suggestions become autocomplete + autocomplete_data += self._get_suggestions_data(match_dict, autocomplete_result, remain_limit, search_config, ignore_config=True) + remain_limit -= len(autocomplete_data) + autocomplete_result.extend(autocomplete_data) + if not remain_limit: + break + + suggestions_result = [] + for match_dict in match_list: + suggestions_data = self._get_suggestions_data(match_dict, autocomplete_result, min(remain_limit, 5), search_config) + remain_limit -= len(suggestions_data) + suggestions_result.extend(suggestions_data) + if not remain_limit: + break + + results['autocomplete'] = {'results': autocomplete_result, 'results_count': len(autocomplete_result), "parts": {"name": True, "website_url": True}} + results['suggestions'] = {'results': suggestions_result, 'results_count': len(suggestions_result), "parts": {"name": True, "website_url": True}} + + global_match = False + if matchs and len(matchs) == 1 and (results['autocomplete'].get('results_count') or results['suggestions'].get('results_count')): + if matchs._name == 'product.public.category': + fixed_str = _('View all products with category') + global_match = {'name': f'{fixed_str} {matchs.ds_name}', 'website_url': f'/shop?category={matchs.id}'} + else: + fixed_str = _('View all products with') + global_match = {'name': f'{fixed_str} {matchs.attribute_id.name.lower()} {matchs.ds_name}', 'website_url': f'/shop?&attrib={matchs.attribute_id.id}-{matchs.id}'} + + return {**results, 'fuzzy_search': fuzzy_term, 'results': [], 'global_match': global_match, + 'result_length': sum([results.get(r_type, {}).get('results_count', 0) for r_type in search_types]), + } + + def _get_autocomplete_data(self, match_dict, remain_limit, search_config): + match, remaining_words, matched_words = match_dict['match'], match_dict['remaining_words'], match_dict['matched_words'] + results = [] + if search_config.get('search_attribute') and remaining_words and match: + for related_match, word in self.match_remaining_words(match, remaining_words): + results.append(self.generate_result_dict(match, related_match, matched_words, word)) + matched_words.append(word) + if len(results) >= remain_limit: + break + return results + + def _get_suggestions_data(self, match_dict, autocomplete_data, remain_limit, search_config, ignore_config=False): + results = [] + match, matched_words = match_dict['match'], match_dict['matched_words'] + if (search_config.get('search_suggestion') or ignore_config) and remain_limit > 0: + if match._name == 'product.public.category': + for related_match in self._category_counterpart_iterator(match, search_type=['auto_suggestion']): + term = self.generate_result_dict(match, related_match, matched_words) + if not self.is_search_added(autocomplete_data, results, term): + results.append(term) + if len(results) >= remain_limit: + break + else: + domain = request.website.sale_product_domain() + [('attribute_line_ids.value_ids', 'in', match.ids)] + all_related_records = request.env['product.template'].with_context(bin_size=True).search(domain).mapped('public_categ_ids') + for related_match in all_related_records: + term = self.generate_result_dict(match, related_match, matched_words) + if not self.is_search_added(autocomplete_data, results, term): + results.append(term) + if len(results) >= remain_limit: + break + return results + + def _match_attr_or_category(self, term, return_on_match=True): + result = self._match_category(term) + if not result: + result = self._match_attr(term) + return result + + def _match_category(self, term): + ProductCategory = request.env['product.public.category'] + matched_categories = ProductCategory.search([('ds_name', 'ilike', term)] + request.website.website_domain()) + return matched_categories + + def _match_attr(self, term): + all_active_attributes = self._website_active_attributes() + matched_values = request.env['product.attribute.value'] + if all_active_attributes: + matched_values = matched_values.search([('ds_name', 'ilike', term), ('attribute_id', 'in', all_active_attributes.ids)]) + return matched_values + + def _website_active_attributes(self): + all_products = request.env['product.template'].with_context(bin_size=True).search(request.website.sale_product_domain()) + return request.env['product.attribute'].search([ + ('product_tmpl_ids', 'in', all_products.ids), ('visibility', '=', 'visible'), ('dr_search_suggestion', '!=', False) + ]) + + def match_remaining_words(self, match, remaining_words): + if match._name == 'product.public.category': + for word in remaining_words: + for attribute_value in self._category_counterpart_iterator(match): + regex_match = re.search(re.escape(word), attribute_value.ds_name, re.IGNORECASE) + if regex_match: + yield attribute_value, word + + if match._name == 'product.attribute.value': + domain = request.website.sale_product_domain() + [('attribute_line_ids.value_ids', 'in', match.ids)] + categories = request.env['product.template'].with_context(bin_size=True).search(domain).mapped('public_categ_ids') + for word in remaining_words: + for category in categories: + regex_match = re.search(re.escape(word), category.ds_name, re.IGNORECASE) + if regex_match: + yield category, word + + def _category_counterpart_iterator(self, category, search_type=['auto_suggestion', 'auto']): + attribute_values = category.mapped('product_tmpl_ids.attribute_line_ids').filtered(lambda line: line.attribute_id.dr_search_suggestion in search_type).mapped('value_ids') + for value in attribute_values: + yield value + + # Child category + child_categories = request.env['product.public.category'].search([('parent_id', 'child_of', category.id)]) - category + child_attribute_values = child_categories.mapped('product_tmpl_ids.attribute_line_ids').filtered(lambda line: line.attribute_id.dr_search_suggestion in search_type).mapped('value_ids') # plus to maintain order + for value in child_attribute_values: + if value not in attribute_values: + yield value + + def generate_result_dict(self, primary_match, secondary_match, matched_words, word=False): + category, attribute = (primary_match, secondary_match) if primary_match._name == 'product.public.category' else (secondary_match, primary_match) + attribute_str = f"&attrib={attribute.attribute_id.id}-{attribute.id}" if attribute else '' # just for category + return { + 'name': self.format_result(matched_words + (word and [word] or []), f"{primary_match.ds_name} {secondary_match and secondary_match.ds_name or ''}"), + 'website_url': f"/shop?category={category.id}{attribute_str}" + } + + def format_result(self, matched_words, value): + pattern = '|'.join(map(re.escape, matched_words)) + parts = re.split(f'({pattern})', value, flags=re.IGNORECASE) + if len(parts) > 1: + value = request.env['ir.ui.view'].sudo()._render_template("website.search_text_with_highlight", {'parts': parts}) + html_val = request.env[('ir.qweb.field.html')].value_to_html(value, {'template_options': {}}) + return html_escape(html_val) + return False + + def is_search_added(self, autocomplete_result, suggestions_results, new_term): + auto_found = len([term for term in autocomplete_result if new_term['website_url'] == term['website_url']]) + sugg_found = len([term for term in suggestions_results if new_term['website_url'] == term['website_url']]) + return auto_found + sugg_found + + def _dr_has_formulate(self, search_config): # for performance + if search_config.get('search_attribute') or search_config.get('search_suggestion'): + formulate_category = request.env['product.public.category'].search(([('dr_search_formulate', '=', True)] + request.website.website_domain()), limit=1) + if formulate_category: + request.update_context(dr_formulate=True) + return len(formulate_category) + return False + + +class ThemePrimeBrand(http.Controller): + + @http.route('/shop/all-brands', type='http', auth='public', website=True, sitemap=True) + def brands(self, search='', **args): + is_disable_grouping = request.website._get_dr_theme_config('json_brands_page')['disable_brands_grouping'] + brands = request.website._get_brands([('name', 'ilike', search)] if search else []) + + grouped_brands = defaultdict(list) + if is_disable_grouping: + grouped_brands = {'All Brands': brands} + else: + alphabet_range = string.ascii_uppercase + grouped_brands.update((alphabet, []) for alphabet in alphabet_range) + for brand in brands: + first_char = str.upper(brand.name[:1]) + grouped_brands[first_char].append(brand) + + get_brand_count = request.env['product.template']._get_product_attrib_count(attrib_values=[[brand.attribute_id.id, brand.id] for brand in brands], domain=request.env['website'].sale_product_domain()) + return request.render('theme_prime.all_brands', {'is_disable_grouping': is_disable_grouping, 'brands': brands, 'grouped_brands': grouped_brands, 'search': search, 'get_brand_count': get_brand_count}) + + +class ThemePrimePWA(http.Controller): + + @http.route('/pwa//manifest.json', type='http', auth='public', website=True) + def get_pwa_manifest(self, website_id, **kargs): + manifest_data = {"fake": 1} + website = request.website + if website and website.id == website_id and website.dr_pwa_activated: + manifest_data = { + "name": website.dr_pwa_name, + "short_name": website.dr_pwa_short_name, + "display": "standalone", + "background_color": website.dr_pwa_background_color, + "theme_color": website.dr_pwa_theme_color, + "id": website.dr_pwa_start_url, + "start_url": website.dr_pwa_start_url, + "scope": "/", + "icons": [{ + "src": "/web/image/website/%s/dr_pwa_icon_192/192x192" % website.id, + "sizes": "192x192", + "type": "image/png", + }, { + "src": "/web/image/website/%s/dr_pwa_icon_512/512x512" % website.id, + "sizes": "512x512", + "type": "image/png", + }] + } + if website.dr_pwa_shortcuts: + manifest_data['shortcuts'] = [{ + "name": shortcut.name, + "short_name": shortcut.short_name or '', + "description": shortcut.description or '', + "url": shortcut.url, + "icons": [{"src": "/web/image/dr.pwa.shortcuts/%s/icon/192x192" % shortcut.id, "sizes": "192x192"}] + } for shortcut in website.dr_pwa_shortcuts] + return request.make_response( + data=json.dumps(manifest_data), + headers=[('Content-Type', 'application/json')] + ) + + @http.route('/service_worker.js', type='http', auth='public', website=True, sitemap=False) + def get_pwa_service_worker(self, **kargs): + website = request.website + js_folder = partial(get_resource_path, 'theme_prime', 'static', 'src', 'js') + file_path = js_folder('service_worker.js') + offline_bool = 'true' if website.dr_pwa_offline_page else 'false' + data = open(file_path).read() + data = data.replace('"##1##"', str(website.dr_pwa_version)) + data = data.replace('"##2##"', offline_bool) + + return request.make_response( + data=data, + headers=[('Content-Type', 'text/javascript')] + ) + + @http.route('/pwa/offline_page', type='http', auth='public', website=True, cors='*', sitemap=False) + def get_pwa_offline_page(self, **kargs): + return request.render('theme_prime.pwa_offline_page', {}) + + @http.route('/pwa/logo.png', type='http', auth='public', website=True, cors='*', sitemap=False) + def get_pwa_logo(self, **kargs): + website = request.website + imgname = 'logo' + imgext = '.png' + placeholder = partial(get_resource_path, 'web', 'static', 'img') + if not website.logo: + response = http.Stream.from_path(placeholder('nologo.png')).get_response() + else: + image_base64 = base64.b64decode(website.logo) + image_data = io.BytesIO(image_base64) + mimetype = guess_mimetype(image_base64, default='image/png') + imgext = '.' + mimetype.split('/')[1] + if imgext == '.svg+xml': + imgext = '.svg' + response = send_file(image_data, request.httprequest.environ, download_name=imgname + imgext, mimetype=mimetype, last_modified=website.write_date) + return response diff --git a/odex25_donation/theme_prime/data/theme.ir.attachment.csv b/odex25_donation/theme_prime/data/theme.ir.attachment.csv new file mode 100644 index 000000000..38475bc4d --- /dev/null +++ b/odex25_donation/theme_prime/data/theme.ir.attachment.csv @@ -0,0 +1,117 @@ +id,key,name,url +s_banner_1_1,theme_prime.s_banner_1_1,theme_prime.s_banner_1_1,/theme_prime/static/src/img/snippets/s_banner_1_1.jpg +s_banner_1_2,theme_prime.s_banner_1_2,theme_prime.s_banner_1_2,/theme_prime/static/src/img/snippets/s_banner_1_2.jpg +s_banner_1_3,theme_prime.s_banner_1_3,theme_prime.s_banner_1_3,/theme_prime/static/src/img/snippets/s_banner_1_3.jpg +s_banner_3_1,theme_prime.s_banner_3_1,theme_prime.s_banner_3_1,/theme_prime/static/src/img/snippets/s_banner_3_1.jpg +s_banner_3_2,theme_prime.s_banner_3_2,theme_prime.s_banner_3_2,/theme_prime/static/src/img/snippets/s_banner_3_2.jpg +s_banner_3_3,theme_prime.s_banner_3_3,theme_prime.s_banner_3_3,/theme_prime/static/src/img/snippets/s_banner_3_3.jpg +s_banner_4_1,theme_prime.s_banner_4_1,theme_prime.s_banner_4_1,/theme_prime/static/src/img/snippets/s_banner_4_1.jpg +s_banner_4_2,theme_prime.s_banner_4_2,theme_prime.s_banner_4_2,/theme_prime/static/src/img/snippets/s_banner_4_2.jpg +s_banner_4_3,theme_prime.s_banner_4_3,theme_prime.s_banner_4_3,/theme_prime/static/src/img/snippets/s_banner_4_3.jpg +s_banner_5_1,theme_prime.s_banner_5_1,theme_prime.s_banner_5_1,/theme_prime/static/src/img/snippets/s_banner_5_1.png +s_banner_5_2,theme_prime.s_banner_5_2,theme_prime.s_banner_5_2,/theme_prime/static/src/img/snippets/s_banner_5_2.png +s_banner_6_1,theme_prime.s_banner_6_1,theme_prime.s_banner_6_1,/theme_prime/static/src/img/snippets/s_banner_6_1.jpg +s_banner_6_2,theme_prime.s_banner_6_2,theme_prime.s_banner_6_2,/theme_prime/static/src/img/snippets/s_banner_6_2.jpg +s_banner_6_3,theme_prime.s_banner_6_3,theme_prime.s_banner_6_3,/theme_prime/static/src/img/snippets/s_banner_6_3.jpg +s_brand_1,theme_prime.s_brand_1,theme_prime.s_brand_1,/theme_prime/static/src/img/snippets/s_brand_1.png +s_brand_2,theme_prime.s_brand_2,theme_prime.s_brand_2,/theme_prime/static/src/img/snippets/s_brand_2.png +s_brand_3,theme_prime.s_brand_3,theme_prime.s_brand_3,/theme_prime/static/src/img/snippets/s_brand_3.png +s_banner_7_1,theme_prime.s_banner_7_1,theme_prime.s_banner_7_1,/theme_prime/static/src/img/snippets/s_banner_7_1.jpg +s_banner_7_2,theme_prime.s_banner_7_2,theme_prime.s_banner_7_2,/theme_prime/static/src/img/snippets/s_banner_7_2.jpg +s_banner_7_3,theme_prime.s_banner_7_3,theme_prime.s_banner_7_3,/theme_prime/static/src/img/snippets/s_banner_7_3.jpg +s_banner_8_1,theme_prime.s_banner_8_1,theme_prime.s_banner_8_1,/theme_prime/static/src/img/snippets/s_banner_8_1.jpg +s_banner_8_2,theme_prime.s_banner_8_2,theme_prime.s_banner_8_2,/theme_prime/static/src/img/snippets/s_banner_8_2.jpg +s_banner_8_3,theme_prime.s_banner_8_3,theme_prime.s_banner_8_3,/theme_prime/static/src/img/snippets/s_banner_8_3.jpg +s_banner_9_1,theme_prime.s_banner_9_1,theme_prime.s_banner_9_1,/theme_prime/static/src/img/snippets/s_banner_9_1.jpg +s_banner_9_2,theme_prime.s_banner_9_2,theme_prime.s_banner_9_2,/theme_prime/static/src/img/snippets/s_banner_9_2.jpg +s_banner_9_3,theme_prime.s_banner_9_3,theme_prime.s_banner_9_3,/theme_prime/static/src/img/snippets/s_banner_9_3.jpg +s_banner_10_1,theme_prime.s_banner_10_1,theme_prime.s_banner_10_1,/theme_prime/static/src/img/snippets/s_banner_10_1.png +s_banner_12_1,theme_prime.s_banner_12_1,theme_prime.s_banner_12_1,/theme_prime/static/src/img/snippets/s_banner_12_1.jpg +s_banner_12_2,theme_prime.s_banner_12_2,theme_prime.s_banner_12_2,/theme_prime/static/src/img/snippets/s_banner_12_2.jpg +s_banner_13_1,theme_prime.s_banner_13_1,theme_prime.s_banner_13_1,/theme_prime/static/src/img/snippets/s_banner_13_1.jpg +s_banner_13_2,theme_prime.s_banner_13_2,theme_prime.s_banner_13_2,/theme_prime/static/src/img/snippets/s_banner_13_2.jpg +s_banner_13_3,theme_prime.s_banner_13_3,theme_prime.s_banner_13_3,/theme_prime/static/src/img/snippets/s_banner_13_3.jpg +s_banner_13_4,theme_prime.s_banner_13_4,theme_prime.s_banner_13_4,/theme_prime/static/src/img/snippets/s_banner_13_4.jpg +s_banner_14_1,theme_prime.s_banner_14_1,theme_prime.s_banner_14_1,/theme_prime/static/src/img/snippets/s_banner_14_1.png +s_banner_14_2,theme_prime.s_banner_14_2,theme_prime.s_banner_14_2,/theme_prime/static/src/img/snippets/s_banner_14_2.png +s_banner_15_1,theme_prime.s_banner_15_1,theme_prime.s_banner_15_1,/theme_prime/static/src/img/snippets/s_banner_15_1.jpg +s_client_01,theme_prime.s_client_01,theme_prime.s_client_01,/theme_prime/static/src/img/snippets/s_client_01.png +s_client_02,theme_prime.s_client_02,theme_prime.s_client_02,/theme_prime/static/src/img/snippets/s_client_02.png +s_client_03,theme_prime.s_client_03,theme_prime.s_client_03,/theme_prime/static/src/img/snippets/s_client_03.png +s_client_04,theme_prime.s_client_04,theme_prime.s_client_04,/theme_prime/static/src/img/snippets/s_client_04.png +s_client_05,theme_prime.s_client_05,theme_prime.s_client_05,/theme_prime/static/src/img/snippets/s_client_05.png +s_client_06,theme_prime.s_client_06,theme_prime.s_client_06,/theme_prime/static/src/img/snippets/s_client_06.png +s_client_07,theme_prime.s_client_07,theme_prime.s_client_07,/theme_prime/static/src/img/snippets/s_client_07.png +s_client_08,theme_prime.s_client_08,theme_prime.s_client_08,/theme_prime/static/src/img/snippets/s_client_08.png +s_client_09,theme_prime.s_client_09,theme_prime.s_client_09,/theme_prime/static/src/img/snippets/s_client_09.png +s_client_10,theme_prime.s_client_10,theme_prime.s_client_10,/theme_prime/static/src/img/snippets/s_client_10.png +s_client_11,theme_prime.s_client_11,theme_prime.s_client_11,/theme_prime/static/src/img/snippets/s_client_11.png +s_client_12,theme_prime.s_client_12,theme_prime.s_client_12,/theme_prime/static/src/img/snippets/s_client_12.png +s_coming_soon_2_1,theme_prime.s_coming_soon_2_1,theme_prime.s_coming_soon_2_1,/theme_prime/static/src/img/snippets/s_coming_soon_2_1.png +s_coming_soon_2_2,theme_prime.s_coming_soon_2_2,theme_prime.s_coming_soon_2_2,/theme_prime/static/src/img/snippets/s_coming_soon_2_2.jpg +s_info_block_1_1,theme_prime.s_info_block_1_1,theme_prime.s_info_block_1_1,/theme_prime/static/src/img/snippets/s_info_block_1_1.jpg +s_info_block_2_1,theme_prime.s_info_block_2_1,theme_prime.s_info_block_2_1,/theme_prime/static/src/img/snippets/s_info_block_2_1.jpg +s_info_block_3_1,theme_prime.s_info_block_3_1,theme_prime.s_info_block_3_1,/theme_prime/static/src/img/snippets/s_info_block_3_1.jpg +s_info_block_3_2,theme_prime.s_info_block_3_2,theme_prime.s_info_block_3_2,/theme_prime/static/src/img/snippets/s_info_block_3_2.jpg +s_info_block_4_1,theme_prime.s_info_block_4_1,theme_prime.s_info_block_4_1,/theme_prime/static/src/img/snippets/s_info_block_4_1.jpg +s_info_block_4_2,theme_prime.s_info_block_4_2,theme_prime.s_info_block_4_2,/theme_prime/static/src/img/snippets/s_info_block_4_2.jpg +s_info_block_4_3,theme_prime.s_info_block_4_3,theme_prime.s_info_block_4_3,/theme_prime/static/src/img/snippets/s_info_block_4_3.jpg +s_info_block_5_1,theme_prime.s_info_block_5_1,theme_prime.s_info_block_5_1,/theme_prime/static/src/img/snippets/s_info_block_5_1.jpg +s_info_block_5_2,theme_prime.s_info_block_5_2,theme_prime.s_info_block_5_2,/theme_prime/static/src/img/snippets/s_info_block_5_2.jpg +s_info_block_6_1,theme_prime.s_info_block_6_1,theme_prime.s_info_block_6_1,/theme_prime/static/src/img/snippets/s_info_block_6_1.jpg +s_info_block_7_1,theme_prime.s_info_block_7_1,theme_prime.s_info_block_7_1,/theme_prime/static/src/img/snippets/s_info_block_7_1.jpeg +s_info_block_8_1,theme_prime.s_info_block_8_1,theme_prime.s_info_block_8_1,/theme_prime/static/src/img/snippets/s_info_block_8_1.png +s_cover_1_1,theme_prime.s_cover_1_1,theme_prime.s_cover_1_1,/theme_prime/static/src/img/snippets/s_cover_1_1.png +s_cover_1_2,theme_prime.s_cover_1_2,theme_prime.s_cover_1_2,/theme_prime/static/src/img/snippets/s_cover_1_2.png +s_cover_1_brand_1,theme_prime.s_cover_1_brand_1,theme_prime.s_cover_1_brand_1,/theme_prime/static/src/img/snippets/s_cover_1_brand_1.png +s_cover_1_brand_2,theme_prime.s_cover_1_brand_2,theme_prime.s_cover_1_brand_2,/theme_prime/static/src/img/snippets/s_cover_1_brand_2.png +s_cover_2_1,theme_prime.s_cover_2_1,theme_prime.s_cover_2_1,/theme_prime/static/src/img/snippets/s_cover_2_1.jpg +s_cover_2_2,theme_prime.s_cover_2_2,theme_prime.s_cover_2_2,/theme_prime/static/src/img/snippets/s_cover_2_2.jpg +s_cover_3_1,theme_prime.s_cover_3_1,theme_prime.s_cover_3_1,/theme_prime/static/src/img/snippets/s_cover_3_1.jpg +s_cover_4_1,theme_prime.s_cover_4_1,theme_prime.s_cover_4_1,/theme_prime/static/src/img/snippets/s_cover_4_1.png +s_cover_4_2,theme_prime.s_cover_4_2,theme_prime.s_cover_4_2,/theme_prime/static/src/img/snippets/s_cover_4_2.png +s_cover_4_3,theme_prime.s_cover_4_3,theme_prime.s_cover_4_3,/theme_prime/static/src/img/snippets/s_cover_4_3.png +s_cover_4_4,theme_prime.s_cover_4_4,theme_prime.s_cover_4_4,/theme_prime/static/src/img/snippets/s_cover_4_4.png +s_cover_4_5,theme_prime.s_cover_4_5,theme_prime.s_cover_4_5,/theme_prime/static/src/img/snippets/s_cover_4_5.png +s_call_to_action_5_1,theme_prime.s_call_to_action_5_1,theme_prime.s_call_to_action_5_1,/theme_prime/static/src/img/snippets/s_call_to_action_5_1.jpg +s_gallery_01,theme_prime.s_gallery_01,theme_prime.s_gallery_01,/theme_prime/static/src/img/snippets/s_gallery_01.jpg +s_gallery_02,theme_prime.s_gallery_02,theme_prime.s_gallery_02,/theme_prime/static/src/img/snippets/s_gallery_02.jpg +s_gallery_03,theme_prime.s_gallery_03,theme_prime.s_gallery_03,/theme_prime/static/src/img/snippets/s_gallery_03.jpg +s_gallery_04,theme_prime.s_gallery_04,theme_prime.s_gallery_04,/theme_prime/static/src/img/snippets/s_gallery_04.jpg +s_gallery_05,theme_prime.s_gallery_05,theme_prime.s_gallery_05,/theme_prime/static/src/img/snippets/s_gallery_05.jpg +s_gallery_06,theme_prime.s_gallery_06,theme_prime.s_gallery_06,/theme_prime/static/src/img/snippets/s_gallery_06.jpg +s_gallery_07,theme_prime.s_gallery_07,theme_prime.s_gallery_07,/theme_prime/static/src/img/snippets/s_gallery_07.jpg +s_gallery_08,theme_prime.s_gallery_08,theme_prime.s_gallery_08,/theme_prime/static/src/img/snippets/s_gallery_08.jpg +s_gallery_09,theme_prime.s_gallery_09,theme_prime.s_gallery_09,/theme_prime/static/src/img/snippets/s_gallery_09.jpg +s_gallery_10,theme_prime.s_gallery_10,theme_prime.s_gallery_10,/theme_prime/static/src/img/snippets/s_gallery_10.jpg +s_gallery_11,theme_prime.s_gallery_11,theme_prime.s_gallery_11,/theme_prime/static/src/img/snippets/s_gallery_11.jpg +s_gallery_12,theme_prime.s_gallery_12,theme_prime.s_gallery_12,/theme_prime/static/src/img/snippets/s_gallery_12.jpg +s_mega_menu_prime_2_1,theme_prime.s_mega_menu_prime_2_1,theme_prime.s_mega_menu_prime_2_1,/theme_prime/static/src/img/snippets/s_mega_menu_prime_2_1.jpg +s_mega_menu_prime_3_1,theme_prime.s_mega_menu_prime_3_1,theme_prime.s_mega_menu_prime_3_1,/theme_prime/static/src/img/snippets/s_mega_menu_prime_3_1.png +s_mega_menu_prime_4_1,theme_prime.s_mega_menu_prime_4_1,theme_prime.s_mega_menu_prime_4_1,/theme_prime/static/src/img/snippets/s_mega_menu_prime_4_1.jpg +s_mega_menu_prime_5_1,theme_prime.s_mega_menu_prime_5_1,theme_prime.s_mega_menu_prime_5_1,/theme_prime/static/src/img/snippets/s_mega_menu_prime_5_1.jpg +s_mega_menu_prime_5_2,theme_prime.s_mega_menu_prime_5_2,theme_prime.s_mega_menu_prime_5_2,/theme_prime/static/src/img/snippets/s_mega_menu_prime_5_2.jpg +s_mega_menu_prime_5_3,theme_prime.s_mega_menu_prime_5_3,theme_prime.s_mega_menu_prime_5_3,/theme_prime/static/src/img/snippets/s_mega_menu_prime_5_3.jpg +s_mega_menu_prime_5_4,theme_prime.s_mega_menu_prime_5_4,theme_prime.s_mega_menu_prime_5_4,/theme_prime/static/src/img/snippets/s_mega_menu_prime_5_4.jpg +s_mega_menu_prime_6_1,theme_prime.s_mega_menu_prime_6_1,theme_prime.s_mega_menu_prime_6_1,/theme_prime/static/src/img/snippets/s_mega_menu_prime_6_1.jpg +s_mega_menu_prime_6_2,theme_prime.s_mega_menu_prime_6_2,theme_prime.s_mega_menu_prime_6_2,/theme_prime/static/src/img/snippets/s_mega_menu_prime_6_2.png +s_mega_menu_prime_6_3,theme_prime.s_mega_menu_prime_6_3,theme_prime.s_mega_menu_prime_6_3,/theme_prime/static/src/img/snippets/s_mega_menu_prime_6_3.jpg +s_pricing_01,theme_prime.s_pricing_01,theme_prime.s_pricing_01,/theme_prime/static/src/img/snippets/s_pricing_01.jpg +s_pricing_02,theme_prime.s_pricing_02,theme_prime.s_pricing_02,/theme_prime/static/src/img/snippets/s_pricing_02.jpg +s_pricing_03,theme_prime.s_pricing_03,theme_prime.s_pricing_03,/theme_prime/static/src/img/snippets/s_pricing_03.jpg +s_pricing_04,theme_prime.s_pricing_04,theme_prime.s_pricing_04,/theme_prime/static/src/img/snippets/s_pricing_04.jpg +s_shop_offer_1_1,theme_prime.s_shop_offer_1_1,theme_prime.s_shop_offer_1_1,/theme_prime/static/src/img/snippets/s_shop_offer_1_1.jpg +s_shop_offer_3_1,theme_prime.s_shop_offer_3_1,theme_prime.s_shop_offer_3_1,/theme_prime/static/src/img/snippets/s_shop_offer_3_1.jpg +s_shop_offer_4_1,theme_prime.s_shop_offer_4_1,theme_prime.s_shop_offer_4_1,/theme_prime/static/src/img/snippets/s_shop_offer_4_1.jpg +s_subscribe_4_1,theme_prime.s_subscribe_4_1,theme_prime.s_subscribe_4_1,/theme_prime/static/src/img/snippets/s_subscribe_4_1.jpg +s_team_01,theme_prime.s_team_01,theme_prime.s_team_01,/theme_prime/static/src/img/snippets/s_team_01.png +s_team_02,theme_prime.s_team_02,theme_prime.s_team_02,/theme_prime/static/src/img/snippets/s_team_02.png +s_team_03,theme_prime.s_team_03,theme_prime.s_team_03,/theme_prime/static/src/img/snippets/s_team_03.png +s_team_04,theme_prime.s_team_04,theme_prime.s_team_04,/theme_prime/static/src/img/snippets/s_team_04.png +s_team_square_01,theme_prime.s_team_square_01,theme_prime.s_team_square_01,/theme_prime/static/src/img/snippets/s_team_square_01.png +s_team_square_02,theme_prime.s_team_square_02,theme_prime.s_team_square_02,/theme_prime/static/src/img/snippets/s_team_square_02.png +s_team_square_03,theme_prime.s_team_square_03,theme_prime.s_team_square_03,/theme_prime/static/src/img/snippets/s_team_square_03.png +s_team_square_04,theme_prime.s_team_square_04,theme_prime.s_team_square_04,/theme_prime/static/src/img/snippets/s_team_square_04.png +s_testimonial_author_01,theme_prime.s_testimonial_author_01,theme_prime.s_testimonial_author_01,/theme_prime/static/src/img/snippets/s_testimonial_author_01.jpg +s_testimonial_author_02,theme_prime.s_testimonial_author_02,theme_prime.s_testimonial_author_02,/theme_prime/static/src/img/snippets/s_testimonial_author_02.jpg +s_testimonial_author_03,theme_prime.s_testimonial_author_03,theme_prime.s_testimonial_author_03,/theme_prime/static/src/img/snippets/s_testimonial_author_03.jpg \ No newline at end of file diff --git a/odex25_donation/theme_prime/doc/README.txt b/odex25_donation/theme_prime/doc/README.txt new file mode 100644 index 000000000..2338ae8e2 --- /dev/null +++ b/odex25_donation/theme_prime/doc/README.txt @@ -0,0 +1 @@ +The documentation is available at https://prime-docs-v16-25092021.droggol.com/ \ No newline at end of file diff --git a/odex25_donation/theme_prime/i10n/ar.po b/odex25_donation/theme_prime/i10n/ar.po new file mode 100644 index 000000000..441f4089b --- /dev/null +++ b/odex25_donation/theme_prime/i10n/ar.po @@ -0,0 +1,6382 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * theme_prime +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-16 10:27+0000\n" +"PO-Revision-Date: 2023-03-16 10:27+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "\" category." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +msgid "" +"\"Etiam semper molestie sapien a egestas. In consequat venenatis ex, sit " +"amet ultrices ante pretium et. Suspendisse nec hendrerit nulla, vitae " +"convallis risus. Morbi quis tincidunt magna. Sed nec libero.\"" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_5 +msgid "" +"\"Fusce sagittis ac orci sed tristique. Suspendisse a lobortis augue. " +"Maecenas scelerisque varius mattis. Sed auctor fermentum libero, sed " +"ullamcorper elit laoreet venenatis. Cras ac ex enim. Suspendisse sodales " +"volutpat.\"" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +msgid "" +"\"Fusce sagittis ac orci sed tristique. Suspendisse a lobortis augue. " +"Maecenas scelerisque varius mattis. Sed auctor fermentum libero, sed " +"ullamcorper elit laoreet venenatis. Cras ac ex enim. Suspendisse sodales.\"" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_2 +msgid "" +"\"Proin a nisi id turpis pharetra fermentum ac eu sem. Morbi ullamcorper mi " +"quis porttitor interdum. Maecenas luctus varius interdum. Duis commodo " +"tincidunt velit non bibendum. Phasellus placerat sodales nunc. Proin a nisi " +"id turpis pharetra fermentum ac eu sem. Morbi ullamcorper mi quis porttitor " +"interdum.\"" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_5 +msgid "" +"\"Proin a nisi id turpis pharetra fermentum ac eu sem. Morbi ullamcorper mi " +"quis porttitor interdum. Maecenas luctus varius interdum. Duis commodo " +"tincidunt velit non bibendum. Phasellus placerat sodales nunc.\"" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_grid_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_grid_2 +msgid "#{rating_stats['total']} Reviews" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid "$ 15.80" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid "$ 21.00" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid "$ 8.80" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid "$20.50" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +msgid "$330.00" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid "$35.00" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid "$42.00" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +msgid "$430.00" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +msgid "$530.00" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid "$9.99" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/image_hotspot.xml:0 +#, python-format +msgid "% OFF" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.discount_percentage +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_price +msgid "% OFF)" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +msgid "%s review" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +msgid "%s reviews" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/search_autocomplete.xml:0 +#, python-format +msgid "'. Showing results for '" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/website_sale.js:0 +#, python-format +msgid "(%d%% OFF)" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +msgid "(+800) 123 456 789" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +msgid "(Clear Cart)" +msgstr "(مسح الكل)" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +msgid "+ Explore Now" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_7 +msgid "+ Shop Now" +msgstr "+ فرص التبرع" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "+1 (650) 691-3277" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_header_style_8 +msgid "+123 4567 780" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_6 +msgid "+91 70466 01320" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid ", .tp-editor-inner-snippet" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid ". Please try another search." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_2 +msgid "100% Genuine" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_11 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "100% Genuine product" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_custom_text +msgid "100% original guarantee" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +msgid "100% secure payment" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "12" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +msgid "128 GB Harddisk" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +msgid "12k+ Customers" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_4 +msgid "156" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "16" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "2 column deals, dynamic, countdown" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_4 +msgid "200+" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +msgid "24 X 7 support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "24/7 customer support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_8 +msgid "24X7 Support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "" +"250 Executive Park Blvd, Suite 3400
San Francisco CA 94134
United" +" States" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_2 +msgid "30 Days Return" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_9 +msgid "30 Days Support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_4 +msgid "365 x 7" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid "50" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +msgid "64 MP Camara" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_4 +msgid "97 %" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_5 +msgid "$19.00" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_5 +msgid "$48.99" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_6 +msgid "" +"First purchase offer: Get 15% off. Code applied at checkout. " +"Exclusion apply*" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_2 +msgid "Designer" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_5 +msgid "" +"New " +"Arrivals" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_9 +msgid "+ Explore More" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +msgid "" +"In hac habitasse platea dictumst. Praesent " +"cursus congue felis, nec pellentesque nulla ornare sed." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_3 +msgid "1200" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_3 +msgid "1340" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "156" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "200+" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_3 +msgid "237" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "365 x 7" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_3 +msgid "8000" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "97%" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid "$12" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid "$3" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid "$8" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_variant_selector_dialog +msgid " Buy Now" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_variant_selector_dialog +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_right_panel +msgid " Add to Cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid " Set Product" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_grid_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_grid_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_list_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.suggested_products_list +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_mobile_bottombar_component +msgid " Add to Cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_compare +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +msgid " Add to cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_actions +msgid "" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_header_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_2 +msgid " info@yourcompany.example.com" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_header_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_2 +msgid " 1 (650) 691-3277" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_actions +msgid "" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +msgid "" +"\n" +" We'll notify you once the product is back in stock." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid " 100% secure payment" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid " 12k+ happy customers" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid " 24x7 customer support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid " 30 days replacement" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid " Cash on delivery" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid " Easy returns" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid " Fast delivery" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid " Quality products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid " Manage Documents" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_tabs +msgid " Download" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_3 +msgid " information@mail.com" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_12 +msgid " Free returns" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_mobile_bottombar_component +msgid "" +" Filters " +"" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid " ADD HOTSPOT" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +msgid " Full Product Information" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_12 +msgid " Free support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_3 +msgid " +12 345 6789 101" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid " Load more" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid " Manage Snippet" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +msgid "" +"\n" +" Invalid email" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_12 +msgid " Free Shipping for order over $200" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_documents_snippet +msgid " External Documents will not work" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_4 +msgid "" +"Follow " +"us" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +msgid "Temporarily out of stock" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +msgid "" +"\n" +" \n" +" Get notified when back in stock\n" +" " +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +msgid "" +"\n" +" Add to compare\n" +" " +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "" +" * Subscribe to our newsletter to receive early discount offers and " +"new products info. " +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +msgid "Proceed " +msgstr "التالي " + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_3 +msgid "Discover" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "" +" Show " +"Filters" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "Sort By :" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +msgid "Compare" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_2 +msgid "" +"\n" +" Previous" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +msgid "" +"\n" +" Previous" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_2 +msgid "" +"\n" +" Next" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +msgid "" +"\n" +" Next" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_tabs +msgid " Reviews & Rating" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_2 +msgid " information@mail.com" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_tabs +msgid " Documents" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_tabs +msgid " Description" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_2 +msgid " +12 345 6789 101" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_2 +msgid " 30 Days Return Policy" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_tabs +msgid " Specifications" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_2 +msgid " 24 x 7 Support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_2 +msgid " Free Delivery" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "Pricelist :" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +msgid "Shop By Categories" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.dynamic_filter_template_blog_post_prime_layout_1 +msgid "Posted by" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +msgid " Register" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "by" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.dynamic_filter_template_blog_post_prime_layout_1 +msgid "" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid " Cras justo odio" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid " Dapibus ac facilisis" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid " Vestibulum at eros" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid " 24 x Support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid " 50 GB Disk Space" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid " Email Support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid "" +" Unlimited Email Addresses" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid " Unlimited SQL Database" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid " Cras justo odio" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid " Dapibus ac facilisis" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid " Vestibulum at eros" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid " Cras justo odio" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid " Dapibus ac facilisis" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid " Vestibulum at eros" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid " 24 x Support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid " Email Support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid " Cras justo odio" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid " Dapibus ac facilisis" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid " Vestibulum at eros" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_5 +msgid "" +"\n" +" BEST\n" +" " +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_b2b_price_label +msgid " to see price" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.selected_attributes +msgid "" +"\n" +" Hide out of stock\n" +" \n" +" " +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid "" +"%\n" +" off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_documents_snippet +msgid "" +" Add Documents" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout_filters +msgid " & above" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.selected_attributes +msgid "" +"& above\n" +" " +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +msgid "Apple Ltd." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout_filters +msgid "Availability" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.all_brands +msgid "Brands" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout_filters +msgid "Categories" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.selected_attributes +msgid "" +"Clear Filters\n" +" " +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_5 +msgid "Designer" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_5 +msgid "Developer" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +msgid "Droggol" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +msgid "Full battery in no time" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +msgid "Google Inc." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +msgid "More content" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +msgid "Powerful Performance" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout_filters +msgid "Price" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout_filters +msgid "Rating" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout_filters +msgid "Tags" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +msgid "Tester" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +msgid "With super Macro Lens" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_right_panel +msgid "A short description that will also appear on documents." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/2_col_deal.xml:0 +#, python-format +msgid "ADD TO CART" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_9 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_5 +msgid "About Us" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "About us" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_1 +msgid "Access wide range of products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Accessorie" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "Accessories" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +msgid "Accessory Products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.component_account_info +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_mobile_bottombar_component +msgid "Account" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Account & other info" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.component_account_info +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_mobile_bottombar_component +msgid "Account Info" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "Actions" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Add New Rule" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +msgid "Add finishing touch to your outfit" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_variant_selector_dialog +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_right_panel +msgid "Add one" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +msgid "Add product to my cart but keep it in my wishlist" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/2_col_deal.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/2_col_deal.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/dynamic_snippets.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/dynamic_snippets.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/dynamic_snippets.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/dynamic_snippets.xml:0 +#: code:addons/theme_prime/static/src/xml/listing_cards.xml:0 +#: code:addons/theme_prime/static/src/xml/listing_cards.xml:0 +#, python-format +msgid "Add to Cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_actions +msgid "Add to Compare" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/listing_cards.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_actions +#, python-format +msgid "Add to Wishlist" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.optional_product_items +msgid "Add to cart" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/core/cart_confirmation_dialog.xml:0 +#, python-format +msgid "Added successfully to cart." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/mixins.js:0 +#, python-format +msgid "Added to your cart." +msgstr "تم اضافته للسله" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/product_root_widget.js:0 +#, python-format +msgid "Added to your wishlist." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_6 +msgid "Address" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.js:0 +#, python-format +msgid "Advance" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid "Advanced" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_5 +msgid "Advanced Pass" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +msgid "" +"Aenean varius ligula vel augue condimentum scelerisque. In a urna at tortor " +"tincidunt gravida sit amet vel eros. Integer et." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +msgid "" +"Aenean varius ligula vel augue condimentum scelerisque. In a urna at tortor " +"tincidunt gravida sit." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +msgid "Alignment" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/hierarchical_category_templates.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.all_brands +#, python-format +msgid "All" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_category_pills +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout_filters +msgid "All Products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_11 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "All oders over $100" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/core/snippet_root_widget.xml:0 +#, python-format +msgid "All products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "All products are loaded." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "All services" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_8 +msgid "" +"All the lorem ipsum generators on the Internet
tend to repeat " +"predefined chunks as necessary." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_9 +msgid "Amazing beauty products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "American Express" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Any" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Apple" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Apply" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.xml:0 +#, python-format +msgid "Apply different configuration for mobile." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.xml:0 +#, python-format +msgid "Apply different configuration to each category." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_1 +msgid "Are you ready?" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown +msgid "As promised, we will offer surprise coupon for our next sale." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Athletic Apparel" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Attribute" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +#, python-format +msgid "Attributes" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_5 +msgid "Author Image 01" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_5 +msgid "Author Image 02" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +msgid "Author Image 03" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.js:0 +#, python-format +msgid "Availability" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_6 +msgid "Available 24/7 at (001) 123-4567" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.configure_optional_products +msgid "Available Options" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#, python-format +msgid "BUY" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/sidebar.xml:0 +#, python-format +msgid "Back" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +msgid "Back to products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Back to top button" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "Bags" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Banner" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_7 +msgid "Banner Brand Image 01" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_7 +msgid "Banner Brand Image 02" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_7 +msgid "Banner Brand Image 03" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_11 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_12 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_15 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_9 +msgid "Banner Image 01" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_11 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_12 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_9 +msgid "Banner Image 02" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_9 +msgid "Banner Image 03" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +msgid "Banner Image 04" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid "Basic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_5 +msgid "Basic Pass" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_3 +msgid "Be the first to find out all the latest news, products and trends." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid "Beginner" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +msgid "Belts" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_5 +msgid "Best Products In Every Categories." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_5 +msgid "Best Quality" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#, python-format +msgid "Best Seller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#, python-format +msgid "Best Sellers" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Bestseller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Bg. Image" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +msgid "Blog" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +msgid "Bluetooth Headset" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_options +msgid "Bold" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Brand" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Brand Best Seller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Brand Discounted Best Seller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Brand Discounted Products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Brand New Arrival" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_14 +msgid "Brand New Shoes On Sale" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.all_brands +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#, python-format +msgid "Brands" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid "Business" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Button" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Button Text" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/dynamic_snippets.xml:0 +#, python-format +msgid "Buy" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "CATEGORY" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "CLOSE" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "COMPARE" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_5 +msgid "CTA Image 01" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Call To Action" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_header_style_8 +msgid "Call us now" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Camera" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +msgid "Careers" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +msgid "Cart" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/core/cart_confirmation_dialog.xml:0 +#, python-format +msgid "Cart Total:" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/xml/sidebar.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_category_pills +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +#, python-format +msgid "Categories" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Categories - Info" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Categories Grid" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Categories Listing" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Categories Tabs" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/search_autocomplete.xml:0 +#, python-format +msgid "Categories:" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Category" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Category Best Seller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Category Discounted Best Seller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Category Discounted Products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Category New Arrival" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +msgid "Change Password" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/mixins.js:0 +#, python-format +msgid "Checkout" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Child Order" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_4 +msgid "Children" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Choose Template" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +msgid "Clean code" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "Clear Selection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "" +"Click'New' in the top-right corner to create your first product." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_clients_4 +msgid "Client Image #{client}" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_clients_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_clients_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_clients_3 +msgid "Client Image #{number}" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Clients" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "Clogs & Mules" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/mixins.js:0 +#: code:addons/theme_prime/static/src/xml/sidebar.xml:0 +#: code:addons/theme_prime/static/src/xml/sidebar.xml:0 +#: code:addons/theme_prime/static/src/xml/sidebar.xml:0 +#: code:addons/theme_prime/static/src/xml/sidebar.xml:0 +#: code:addons/theme_prime/static/src/xml/sidebar.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_variant_selector_dialog +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +#, python-format +msgid "Close" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Collapse Category Recursive" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_4 +msgid "Collections" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +#, python-format +msgid "Colors" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/utils.xml:0 +#, python-format +msgid "Colors:" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Coming Soon" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_2 +msgid "Coming Soon..." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +msgid "Community" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_actions +#, python-format +msgid "Compare" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_compare +msgid "Comparison" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_7 +msgid "Complimentary Gift" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_8 +msgid "" +"Consectetur, from a Lorem Ipsum passage, and
going through the cites of" +" the word in classical." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_compare +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_variant_selector_dialog +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_9 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_header_style_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_right_panel +msgid "Contact Us" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.404 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Contact us" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_2 +msgid "Contact us at" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +msgid "Contacts" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Content - Menus" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.dynamic_filter_template_blog_post_prime_layout_1 +msgid "Continue Reading" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/core/cart_confirmation_dialog.xml:0 +#, python-format +msgid "Continue Shopping" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_9 +msgid "Copyright &copy; MyCompany" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Count" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Cover" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +msgid "Cover Brand Image 01" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_single_product_cover_snippet +msgid "Cover Image 01" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +msgid "Cover Image 02" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_2 +msgid "Cras in feugiat eros" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_8 +msgid "Creative ideas" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +msgid "Customer Care" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_8 +msgid "Customer Satisfaction" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_11 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Customer Support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "Customers" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#, python-format +msgid "DAYS" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "DESCRIPTION" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "DESKTOP" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid "Dapibus ac facilisis." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Dark" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#, python-format +msgid "Days" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Default Sort" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Delivery data" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Delivery info" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +msgid "Denim Jeans" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "Design" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +msgid "Details " +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +msgid "Diffrent content looks good so not repeating the content here." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "" +"Diffrent content looks good so not repeating the content here. Diffrent " +"content looks good so not repeating the content here." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Discount" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Discounted Best Seller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Discounted Products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Discover" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +msgid "Discover More" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_5 +msgid "Discover Now" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Display label" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_4 +msgid "Don't miss out. Stay Informed! Monthly Tips, Tracks, and Discounts." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +msgid "Donec Int" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_options +msgid "Dot Position" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/documents.xml:0 +#, python-format +msgid "Download" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Download our apps" +msgstr "" + +#. module: theme_prime +#: model:ir.model.fields,field_description:theme_prime.field_product_product__dr_has_discount +#: model:ir.model.fields,field_description:theme_prime.field_product_template__dr_has_discount +msgid "Dr Has Discount" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "Drag building blocks here to customize the header for \"" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +msgid "Due Date" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Dynamic Snippet" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_2 +msgid "EXPLORE GREAT RANGE OF PRODUCTS" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_11 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Easy Returns" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Edit" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +msgid "Edit Profile" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_6 +msgid "Email" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Enable Lazy Loading" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Enable hotspot" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/website_sale.js:0 +#, python-format +msgid "Enter valid value." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +msgid "Enter your email below to know latest collection and product launch." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_8 +msgid "Excellent features" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +msgid "Expert" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +msgid "Extensive documentation" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_5 +msgid "FAQ" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.filter_attribute_range +msgid "FILTER" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_9 +msgid "FREE RETURNS" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_9 +msgid "FREE SHIPPING" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_9 +msgid "FREE SUPPORT" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_gallery_4 +msgid "Fashion card" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_8 +msgid "Fast Service" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +msgid "Fast Shipping" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "Fast and free delivery" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_5 +msgid "Featured" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_2_column_snippet +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_3 +msgid "Featured Products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Field :" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/website_sale.js:0 +#, python-format +msgid "Filters" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +msgid "" +"Find a location nearest
\n" +" you." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +msgid "Find your perfect outfit" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.404 +msgid "Find your product" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_7 +msgid "Flat 50% Off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_2 +msgid "Flexible Styled Collection By Prime" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_3 +msgid "Follow Us" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_9 +msgid "Follow Us On" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_5 +msgid "Follow Us On:" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +msgid "Follow us" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Footwear" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_single_category_snippet +msgid "For Women" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +msgid "Forums" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_11 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Free Delivery" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +msgid "Free Returns" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_5 +msgid "Free Returns. Standard Shipping. Orders $99." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +msgid "Free Shipping" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +msgid "Free Support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "Free delivery for all orders" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_custom_text +msgid "Free delivery on all orders" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_3 +msgid "Free shipping for all order of $150" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_5 +msgid "Fresh Arrival" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +msgid "Fresh Collection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +msgid "Fresh Collection By Prime" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_11 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "Friendly 24/7 customer support" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.filter_attribute_range +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +msgid "From" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +msgid "From world's top designer" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_8 +msgid "Fully responsive" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_2 +msgid "GET FLAT 20% OFF" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Gallery" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_gallery_1 +msgid "Gallery Image #{img}" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_gallery_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_gallery_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_gallery_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_gallery_5 +msgid "Gallery Image #{number}" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_8 +msgid "Genuine Product" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_12 +msgid "Get 10% Off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_12 +msgid "Get 15% Off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_2 +msgid "Get 30-day money-back guarantee" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_12 +msgid "Get Best Burger" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_12 +msgid "Get Big Pizzas" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_11 +msgid "Get discount on shoes on order above $150." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_3 +msgid "Get in touch" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.404 +msgid "Get in touch with us" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_3 +msgid "Get it Now" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_snippet_options_background_options +msgid "Gradient Animation" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +#, python-format +msgid "Grid" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "Grid View" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +msgid "Guest" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#, python-format +msgid "HOURS" +msgstr "" + +#. module: theme_prime +#: model:ir.model,name:theme_prime.model_ir_http +msgid "HTTP Routing" +msgstr "مسار HTTP" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_10 +msgid "HUGE SALE!" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Handset" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "Happy Clients" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +msgid "Happy Customers" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown +msgid "Happy Shopping!" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +msgid "Hats" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Header Style" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Heading" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +msgid "Help Center" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.404 +msgid "Here are some helpful links instead" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "Hey, You don't need to be a designer to configure the snippet." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout_filters +msgid "Hide out of stock" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_2 +msgid "High Quality Fabric Collection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +msgid "High Quality Products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_3 +msgid "Hire Us!" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.all_brands +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_9 +msgid "Home" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.404 +msgid "Homepage" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +msgid "Hot Collection" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#, python-format +msgid "Hours" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "How it works?" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Huawei" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_14 +msgid "Hurry up to reserve your spot now" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_10 +msgid "Hurry up!" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_14 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_image_product_listing_cards +msgid "Hurry up! Limited time offer" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Icon Block" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Icon Pack" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.js:0 +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "Image" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_9 +msgid "In 2-3 Days" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +msgid "" +"In hac habitasse platea dictumst. Praesent cursus congue felis, nec " +"pellentesque nulla ornare sed." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +msgid "" +"In hac habitasse platea dictumst. Praesent cursus congue felis, nec " +"pellentesque nulla ornare sed. Aliquam eget aliquam urna." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_8 +msgid "" +"In hac habitasse platea dictumst. Praesent cursus congue felis, nec " +"pellentesque nulla ornare sed. In hac habitasse platea dictumst. " +"pellentesque nulla sed." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_7 +msgid "" +"In hac habitasse platea dictumst. Praesent cursus congue felis, nec " +"pellentesque nulla ornare sed. Orci varius natoque penatibus et magnis dis " +"parturient montes, nascetur mus." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_1 +msgid "" +"In hac habitasse platea dictumst. Praesent cursus congue felis, nec " +"pellentesque nulla ornare." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_2 +msgid "" +"In hac habitasse platea dictumst. Praesent cursus congue felis, nec " +"pellentesque nulla." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "In stock" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Info Block" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_8 +msgid "Info Block Image 01" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_5 +msgid "Info Block Image 02" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_4 +msgid "Info Block Image 03" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +msgid "Information" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_9 +msgid "International style" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "JCB" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_2 +msgid "JUST NEWLY ARRIVED!" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Jeans" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +msgid "Jewelry" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_5 +msgid "John Doe" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_4 +msgid "Join Our Mailing List" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_3 +msgid "Join Our Newsletter Now" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "" +"Just activate options from the right panel as per your need and see the " +"magic." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_gallery_4 +msgid "Just adding some random string heresit." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_5 +msgid "Just some random content to break this paragraph into two line." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +msgid "Just some random string to reach eighty charater limit to break." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "" +"Just some random string to reach eighty charater limit to break. Just some " +"random string to reach eighty charater limit to break." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_4 +msgid "Kids" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Kidswear" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "LABEL" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Label" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Label Best Seller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Label Discounted Best Seller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Label Discounted Products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Label New Arrival" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Laptop" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.xml:0 +#, python-format +msgid "Layout" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_8 +msgid "Learn More" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_14 +msgid "Learn more" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Left" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Left Panel" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Light" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_4 +msgid "Limited Collection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_options +msgid "Line Position" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Link" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "List View" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "Load more" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/sidebar.js:0 +#, python-format +msgid "Loading Categories..." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/sidebar.xml:0 +#: code:addons/theme_prime/static/src/xml/sidebar.xml:0 +#, python-format +msgid "Loading..." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Locate store" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/mixins.js:0 +#, python-format +msgid "Log in" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/mixins.js:0 +#, python-format +msgid "Log in to place an order" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_b2b_price_label +msgid "Login" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Logitech" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_9 +msgid "Logo of MyCompany" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +msgid "Logout" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_options +msgid "Long" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/core/snippet_root_widget.xml:0 +#, python-format +msgid "Looks like you migrated to Odoo version 16.0" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_image_products_block +msgid "" +"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " +"tempor incididunt ut labore et." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#, python-format +msgid "MINUTES" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "MOBILE" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Maestro" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +msgid "Manage Payment Methods" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.js:0 +#, python-format +msgid "Manual" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_8 +msgid "" +"Many desktop publishing packages and web
page editors now use lorem " +"ipsum as their." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Match:" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/website_sale.js:0 +#, python-format +msgid "Maximum value should be greater than minimum." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +msgid "Maximus Note 8i" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_4 +msgid "Men" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_3 +msgid "Mens" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Menus" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Menus - Content" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Menus - Image - Logos" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Menus - Images" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Microsoft" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#, python-format +msgid "Minutes" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Mobile Settings" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Mobile Style" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Modal" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +#, python-format +msgid "Mode" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +msgid "Modern design" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "Money back guarantee" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Monitor" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +msgid "Morbi tincidunt ultrices" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid "Morbi tincidunt ultrices fermentum. Suspendisse egestas ipsum eu." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid "Morbi tincidunt ultrices." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Motorola" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Mouse" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Mouses Pad" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_header_style_4 +msgid "My Account" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.component_account_info +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_header_style_4 +msgid "My Cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +msgid "My Orders" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_header_style_4 +msgid "My Wishlist" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "My account" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_9 +msgid "MyCompany" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid "NEW" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_2 +msgid "NEW PRODUCTS EVERY DAY" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +msgid "" +"Nam blandit arcu vel mi mollis faucibus. Nam justo velit, maximus viverra " +"volutpat eu, hendrerit et velit." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +msgid "" +"Nam blandit arcu vel mi mollis faucibus. Nam justo velit, maximus viverra " +"volutpat eu, hendrerit et velit. Pellentesque tincidunt." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Name" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Name: A to Z" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Name: Z to A" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_5 +msgid "Need to do calculations?" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_2 +#, python-format +msgid "New Arrival" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_5 +msgid "New Arrivals" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +msgid "New Collection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_image_product_listing_cards +msgid "New Hoodie Collection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "New Ideas" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_6 +msgid "New York, United States" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#, python-format +msgid "Newly Arrived" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_4 +msgid "Newly Launched" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "News" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +msgid "Next" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_11 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_9 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "No Questions Asked" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_tabs +msgid "No Specifications" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#, python-format +msgid "No brands are found!" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#, python-format +msgid "No categories found!" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "No product defined in category" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#, python-format +msgid "No product found" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/snippet_root_widget.js:0 +#, python-format +msgid "No products found!" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "No records are selected" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "No results found for" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/search_autocomplete.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/search_autocomplete.xml:0 +#, python-format +msgid "No results found for '" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "No rules are added." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.similar_products_sidebar +msgid "No similar products found!" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.xml:0 +#, python-format +msgid "No specific mobile configuration available for this snippet" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "No. of Child" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "No. of Products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "No. of items" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Nokia" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "None" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_options +msgid "Normal" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Number of brands" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_3 +msgid "OR" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "On Click" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#, python-format +msgid "On Sale" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_8 +msgid "On order above $100" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_8 +msgid "On order above $60" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_8 +msgid "On order above $80" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +msgid "On the Ear" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_mobile_bottombar_component +msgid "Open menu" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Operators :" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Options" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_5 +msgid "" +"Orci varius natoque penatibus et magnis dis parturient montes, nascetur " +"ridiculus mus." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +msgid "" +"Orci varius natoque penatibus et magnis dis parturient montes, nascetur " +"ridiculus mus. Aenean pretium ac enim eget dignissim." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_7 +msgid "" +"Orci varius natoque penatibus et magnis dis parturient montes, nascetur " +"ridiculus mus. Orci varius natoque penatibus et magnis dis parturient " +"montes, nascetur ridiculus mus." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_8 +msgid "" +"Orci varius natoque penatibus et magnis dis parturient montes, nascetur " +"ridiculus mus. Orci varius natoque penatibus et magnis. nascetur ridiculus " +"mus." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Order By" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid "Order Now" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_11 +msgid "Order above $250 and get free gift voucher." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_1 +msgid "Order now and get 15% OFF" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Order tracking" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_4 +msgid "Our Creative Team" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Our Policy" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Our Stores" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +msgid "" +"Our products are designed for small to medium size companies willing to " +"optimize their performance." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +msgid "Our store" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "Out Of Stock" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Override all components border radius to 0" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +msgid "Payment" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid "Per Month" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_9 +msgid "Personal Care" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Phablet" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_6 +msgid "Phone Number" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Play Station" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Please add some rules and make snippet more powerful." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "Please check the spelling or try searching something else" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/mixins.js:0 +#, python-format +msgid "Please log in first." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "Please search and add few records from the input." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/search_autocomplete.xml:0 +#, python-format +msgid "Please try another search." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Polo T-shirts" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Popover" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.dynamic_filter_template_blog_post_prime_layout_4 +msgid "Posted by" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +msgid "" +"Powered by a 10 nm octa-core Qualcomm Snapdragon 712 AIE processor, this " +"phone can seamlessly execute any task. You can game more and multitask " +"without experiencing any lag. Experience a boost in performance and " +"efficiency with this phone." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_2 +msgid "Praesent ornare mi quis" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Preheader" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid "Premium" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid "Premium Collection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +msgid "Prev" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Preview" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +msgid "Previous" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.suggested_products_list +#, python-format +msgid "Price" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Price Filter" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_mobile_bottombar_component +msgid "Price:" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Price: High to Low" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Price: Low to High" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Pricing" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +msgid "Pricing Image 01" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +msgid "Pricing Image 02" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +msgid "Pricing Image 03" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid "Pricing Image 04" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +msgid "Pricing and Plans" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Primary" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Footer Style - 1" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Footer Style - 10" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Footer Style - 2" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Footer Style - 3" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Footer Style - 4" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Footer Style - 5" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Footer Style - 6" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Footer Style - 7" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Footer Style - 8" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Footer Style - 9" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Header Style - 1" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Header Style - 2" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Header Style - 3" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Header Style - 4" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Header Style - 5" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Header Style - 6" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Header Style - 7" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Header Style - 8" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Preheader Style - 1" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Preheader Style - 2" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Preheader Style - 3" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Preheader Style - 4" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Preheader Style - 5" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Prime Preheader Style - 6" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_9 +msgid "Printed T-Shirts" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_9 +msgid "Privacy Policy" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#: model:ir.model,name:theme_prime.model_product_template +#: model_terms:theme.ir.ui.view,arch:theme_prime.suggested_products_list +#, python-format +msgid "Product" +msgstr "المنتج" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +msgid "Product Compare" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Product Listing" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_variant_selector_dialog +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +msgid "Product Name" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Product Per Row" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#: code:addons/theme_prime/static/src/xml/sidebar.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.all_brands +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#, python-format +msgid "Products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Products Page" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Products on page" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_3 +msgid "Professional" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_1 +msgid "Proin est justo, euismod sit." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +msgid "" +"Proin purus dui, feugiat id ipsum eu, varius ornare ex. Mauris elit dolor, " +"consectetur ac accumsan eu, commodo et odio eget." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +msgid "" +"Proin purus dui, feugiat id ipsum eu, varius ornare ex. Mauris elit dolor, " +"consectetur ac accumsan eu." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_5 +msgid "Purchase" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_2 +msgid "Purchase Now" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "QUICK VIEW" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_2 +msgid "Quality Product" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_11 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Quality Products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_5 +msgid "Quality products by Prime team" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_1 +msgid "Quality products from our shop." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Quick Actions" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +msgid "Quick Links" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/listing_cards.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_actions +#, python-format +msgid "Quick View" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +msgid "Quick links" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "RATING" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_2 +msgid "READ MORE" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.pwa_offline_page +msgid "RELOAD" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "RESET" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_2 +msgid "Receive 100% genuine products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "Records Selection Mode:" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Refunds & replacements" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_b2b_price_label +msgid "Register" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Remove" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Remove Background" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +msgid "Remove from Cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_lines +#: model_terms:theme.ir.ui.view,arch:theme_prime.optional_product_items +msgid "Remove from cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_compare +msgid "Remove from comparison" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +msgid "Remove from wishlist" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_variant_selector_dialog +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_right_panel +msgid "Remove one" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.404 +msgid "Return to homepage" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_custom_text +msgid "Return within 30days" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.d_rating_widget_stars_static +msgid "Reviews)" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "SAVE" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#, python-format +msgid "SECONDS" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "SIMILAR" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_1 +msgid "STAY TUNED" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_10 +msgid "Safe Payment" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Same as Desktop" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Samsung" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +msgid "Sandals" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.option_back_to_top +msgid "Scroll back to top" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/sidebar.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.404 +#: model_terms:theme.ir.ui.view,arch:theme_prime.component_account_info +#, python-format +msgid "Search" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.all_brands +msgid "Search brands..." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_5 +msgid "Search for products, brands and more ..." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.filter_attribute +msgid "Search..." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/snippets/s_tp_countdown/000.xml:0 +#, python-format +msgid "Seconds" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "Secure online payment" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_category_pills +msgid "See All " +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +msgid "See Our Stores" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/search_autocomplete.xml:0 +#, python-format +msgid "See all products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Select any template and modify as per your need." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "Selection" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Selection Rules" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Sequence" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +msgid "Share :" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Shipping Info" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_9 +msgid "Shirts, Jeans & Waistcoats" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "Shop" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/hierarchical_category_templates.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_12 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_image_products_block +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_single_category_snippet +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_4 +#, python-format +msgid "Shop Now" +msgstr "فرص التبرع" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Shop Offer" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_4 +msgid "Shop Offer Image 01" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_brand_snippet +msgid "Shop by brand" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Shop departments" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/dynamic_snippets.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_14 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_image_product_listing_cards +#, python-format +msgid "Shop now" +msgstr "فرص التبرع" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart +msgid "Shopping Cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_actions +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_grid_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_grid_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_list_1 +msgid "Shopping cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_options +msgid "Short" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#, python-format +msgid "Show Similar Products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show best seller products based on last 30 days sales" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "" +"Show best seller products based on last 30 days sales from selected brands." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "" +"Show best seller products based on last 30 days sales from selected " +"categories." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "" +"Show best seller products based on last 30 days sales from selected label." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "" +"Show best seller products based on last 30 days sales from selected tags." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show best seller products with discount" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show best seller products with discount from the selected brands" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show best seller products with discount from the selected categories" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show best seller products with discount from the selected label" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show best seller products with discount from the selected tags" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show discounted products based on product pricelist" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "" +"Show discounted products based on product pricelist from selected brands." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "" +"Show discounted products based on product pricelist from selected categories" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "" +"Show discounted products based on product pricelist from selected label" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show discounted products based on product pricelist from selected tags" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show newly arrived products based on creation date" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show newly arrived products from selected brands" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show newly arrived products from selected categories" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show newly arrived products from selected label." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Show newly arrived products from selected tags" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Show variant image" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/mixins.js:0 +#, python-format +msgid "Sign Up" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_3 +msgid "" +"Sign up for all the news about our latest arrivals and get an exclusive " +"early access shopping." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/sidebar.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.product +#, python-format +msgid "Similar Products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +#, python-format +msgid "Slider" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Smartphone" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Sneakers & Athletic" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "Snippet:" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Sony" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#, python-format +msgid "Sorry, We couldn't find any brands right now" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/snippet_root_widget.js:0 +#, python-format +msgid "Sorry, We couldn't find any products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/mixins.js:0 +#, python-format +msgid "Sorry, We couldn't find any products under this category" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/frontend/dynamic_snippets.js:0 +#, python-format +msgid "Sorry, this product is not available right now" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "Sort By" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +#, python-format +msgid "Sort by" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Speakers" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +msgid "Special Collection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_4 +msgid "Spring Collections" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Square UI" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +msgid "Starting at $120.00" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +msgid "Starting at $150." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +msgid "Starting at $200." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_single_category_snippet +msgid "Starting at $24" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_1 +msgid "Starting at $35.00" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +msgid "Starting at $99." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/dynamic_snippets.xml:0 +#, python-format +msgid "Starting from" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Static" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Stats" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Stay informed" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Store Information" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +#, python-format +msgid "Style" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Style - ${index + 1}" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Style - 1" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Style - 2" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Style - 3" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Style - 4" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +msgid "Subscribe" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_4 +msgid "Subscribe Image 01" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_2 +msgid "" +"Subscribe and stay in touch with the latest news, deals and promotions." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_1 +msgid "Subscribe to get a notification as soon as we launch!" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +msgid "Subscribe to our weekly newsletter" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Subtitle" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_lines_subtotal +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +msgid "Subtotal" +msgstr "المجموع الفرعي" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.suggested_products_list +msgid "Suggested Products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/search_autocomplete.xml:0 +#, python-format +msgid "Suggestions:" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_1 +msgid "" +"Summer Special | Get 50% Off | Code #GET50" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Sunglasses & Eyewear" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_2_column_snippet +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_image_products_block +msgid "Super Deal" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +msgid "Super Fast CPU" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid "Suspendisse egestas ipsum eu." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_1 +msgid "" +"Suspendisse est nunc, laoreet eget odio id, finibus convallis ipsum. " +"Praesent eu nisi egestas, gravida dolor eget, suscipit lectus. Class aptent " +"taciti sociosqu ad litora torquent per conubia nostra, per inceptos " +"himenaeos. Nulla tincidunt eu." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_2 +msgid "" +"Suspendisse est nunc, laoreet eget odio id, finibus convallis ipsum. " +"Praesent eu nisi egestas." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_4 +msgid "" +"Suspendisse potenti. Cras a dui et nisl egestas ornare eu quis odio. Sed " +"bibendum in ante vel accumsan." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_3 +msgid "" +"Suspendisse potenti. Cras a dui et nisl egestas ornare eu quis odio. Sed " +"bibendum in ante vel accumsan. Praesent scelerisque." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_2 +msgid "" +"Suspendisse potenti. Cras a dui et nisl egestas ornare eu quis odio. Sed " +"bibendum in ante." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_7 +msgid "" +"Suspendisse potenti. Cras a dui et nisl egestas ornare eu quis odio. Sed " +"bibendum in ante. Orci varius natoque penatibus et magnis dis parturient " +"montes, nascetur ridiculus mus." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_8 +msgid "" +"Suspendisse potenti. Cras a dui et nisl egestas ornare eu quis odio. Sed " +"bibendum in ante. Suspendisse potenti. Cras a dui et nisl. Sed bibendum in " +"ante." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Swimwear" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "T-Shirts" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "T-shirts" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "Tab Style" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Tablet" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.xml:0 +#, python-format +msgid "Tabs Settings" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Tags" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_extra_fields +msgid "Tags :" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Tags Best Seller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Tags Discounted Best Seller" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Tags Discounted Products" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "Tags New Arrival" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +msgid "Taxes" +msgstr "الضرائب" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Taxes & fees" +msgstr "Taxes" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Team" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_team_5 +msgid "Team Image #{team}" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_5 +msgid "Terms" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_custom_text +msgid "Terms and Conditions :" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_8 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_9 +msgid "Terms of Use" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "Testimonial" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +msgid "Thanks" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown +msgid "" +"The following message will become visible only once the " +"countdown ends." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_tp_countdown_options +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Theme" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/editor/snippets.editor.js:0 +#, python-format +msgid "Theme Prime Options" +msgstr "" + +#. module: theme_prime +#: model:ir.model,name:theme_prime.model_theme_utils +msgid "Theme Utils" +msgstr "أدوات السمة" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/core/cart_confirmation_dialog.xml:0 +#, python-format +msgid "There are" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_options +msgid "Thickness" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/core/snippet_root_widget.xml:0 +#, python-format +msgid "" +"This block is depricated in theme prime Odoo version 16.0. We have more cool" +" things in this version." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_variant_selector_dialog +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_right_panel +msgid "This combination does not exist." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +msgid "This is the last paragraph, and i am out of idea what to write." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "" +"This is the last paragraph, and i am out of idea what to write. This is the " +"last paragraph, and i am out of idea what to write." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_variant_selector_dialog +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_right_panel +msgid "This product has no valid combination." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_variant_selector_dialog +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_quick_view +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_product_right_panel +msgid "This product is no longer available." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Title" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.filter_attribute_range +msgid "To" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_2 +msgid "To break the lines we are writing some random string here." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_stats_5 +msgid "" +"To break the lines we are writing some random string here. To break the " +"lines we are writing some random string here." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#, python-format +msgid "To cart" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/pwa.xml:0 +#, python-format +msgid "To install this web app on your iOS device: tap" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Top" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "Top Bar" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_2 +msgid "Trending Collection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_image_products_block +msgid "Trending Products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_5 +msgid "Trendy Collection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_options +msgid "Type" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_tabs +msgid "Uncategorized" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/product_root_widget.js:0 +#, python-format +msgid "Undo" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "Units Left" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_11 +msgid "Up To 10% Off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_11 +msgid "Up To 20% Off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_8 +msgid "Up To 25% Off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_8 +msgid "Up To 40% Off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_8 +msgid "Up To 50% Off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_7 +msgid "Up To 60% Off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_10 +msgid "Up to 20% off on all products." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +msgid "Up to 70% off on selected item" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_1 +msgid "Up to 20% off" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +msgid "Useful Links" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_5 +msgid "" +"Ut ac pellentesque tortor. Sed fringilla nibh vel urna porttitor feugiat sit" +" amet ac ex. Duis ut mattis est, eget venenatis leo. Sed et facilisis leo. " +"Class aptent taciti sociosqu." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_1 +msgid "Ut efficitur sem sed." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "Value :" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_6 +msgid "" +"Vestibulum id laoreet sapien. Aliquam porttitor neque ut urna efficitur, " +"eget tincidunt diam convallis. Vestibulum molestie nunc consectetur cursus " +"tincidunt. Aenean interdum justo a tellus condimentum gravida." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_4 +msgid "" +"Vestibulum id laoreet sapien. Aliquam porttitor neque ut urna efficitur, eget tincidunt diam convallis.
\n" +" interdum justo a tellus condimentum gretur cursus tincidunt. Aenean interdum justo a tellus condimentum gravida.
\n" +" cursus id laoreet sapien. Aliquam porttitor neque ut urna efficitur, eget tincidunt diam convallis.
\n" +" tellus justo a tellus condimentum gretur cursus tincidunt. Aenean interdum justo a tellus condimentum gravida." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +#, python-format +msgid "View" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_d_brand_snippet +msgid "View All Brands" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/core/cart_confirmation_dialog.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_header_style_4 +#, python-format +msgid "View Cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_4 +msgid "View More" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/dynamic_snippets.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/s_category.xml:0 +#, python-format +msgid "View Products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_item_actions +msgid "View Similar Products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_header_style_4 +msgid "View Wishlist" +msgstr "" + +#. module: theme_prime +#. odoo-python +#: code:addons/theme_prime/controllers/main.py:0 +#, python-format +msgid "View all products with" +msgstr "" + +#. module: theme_prime +#. odoo-python +#: code:addons/theme_prime/controllers/main.py:0 +#, python-format +msgid "View all products with category" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/mixins.js:0 +#, python-format +msgid "View cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Visa" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_testimonial_5 +msgid "Vivamus Tem" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_5 +msgid "" +"Vivamus at tempor arcu. Vestibulum fermentum facilisis dui, vitae iaculis " +"purus accumsan quis. Quisque sit amet dignissim justo. Nullam ac sodales " +"lorem, id volutpat arcu. Sed justo neque." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_1 +msgid "WE ARE LAUNCHING SOON!" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.js:0 +#, python-format +msgid "WISHLIST" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Watch" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "We Accept" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "We accept" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_3 +msgid "We add new products every day. Explore our great range of products." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "" +"We are a team of passionate people whose goal is to improve everyone's life " +"through disruptive products. We build great products to solve your business " +"problems." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +msgid "" +"We are a team of passionate people whose goal is to improve everyone's life " +"through disruptive products. We build great products to solve your business " +"problems. Our products are designed for small to medium size companies " +"willing to optimize their performance." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_2 +msgid "" +"We are glad to see you, but please be patient. This page is under " +"construction." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_info_block_7 +msgid "" +"We are the creative team of theme prime. No one actually read this so let me" +" write any thing here until it paragraph breaks into to multiple lines. " +"Thanks for reading this." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_3 +msgid "" +"We are the creative team of theme prime. No one actually read this so let me" +" write any thing here until the content is long enough to break this lines " +"in to multiple lines so this block looks nice and cool. We are creative team" +" but paragraph in not so long so writing again." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_5 +msgid "" +"We are the creative team of theme prime. No one actually read this so let me" +" write any thing here until the content is long enough to break this lines " +"in to multiple lines." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_2 +msgid "" +"We are the creative team of theme prime. No one actually read this so let me" +" write any thing here until the content is long enough." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_5 +msgid "" +"We are the creative team of theme prime. No one actually read this so let me" +" write any thing here." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.404 +msgid "We can't seem to find the page you are looking for" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "We couldn't find any matches!" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "We couldn't find any product!" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_5 +msgid "We have everything that you need for your next adventure." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_4 +msgid "We offer best in class service for your needs" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "We process SSL сertificate" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +msgid "We return money within 30 days" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.page_sidebars +msgid "Welcome !" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_options +msgid "Width" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_1 +msgid "Winter Collection" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_9 +msgid "Winter Wear Fest" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_cover_4 +msgid "Wireless Charging" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/product_root_widget.js:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: code:addons/theme_prime/static/src/xml/cards.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.component_account_info +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#, python-format +msgid "Wishlist" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_shop_offer_2 +msgid "Within 48 hours get free delivery" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_preheader_style_4 +msgid "Women" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_13 +msgid "Women Tops" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_3 +msgid "Womens" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +msgid "Xbox" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "You can select only" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.pwa_offline_page +msgid "You do not have internet connection !" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/core/cart_confirmation_dialog.xml:0 +#, python-format +msgid "You may also like" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "You searched for" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "You're editing page:" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_banner_14 +msgid "Your Add Text Here" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/js/core/mixins.js:0 +#: code:addons/theme_prime/static/src/js/sidebar.js:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +#, python-format +msgid "Your Cart" +msgstr "السله" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +msgid "Your Orders" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "Your account" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +msgid "Your cart is empty!" +msgstr "سلتك فارغه" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/search_autocomplete.xml:0 +#, python-format +msgid "Your search:" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_heading_6 +msgid "Your title here" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/ui_component.js:0 +#, python-format +msgid "add Products From Child Categories" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "banner, hero" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "brands, dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "brands, dynamic, tabs" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "call to action, cta" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "cards, categories, dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "cards, product, listing" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "cards, product, listing, image" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "cards, product, listing, tabs" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "cards, products, dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "categories, dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "categories, top, dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "clients, logo, reference" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "coming soon, countdown, timer" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "count down, products, dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "countdown, timer" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "covers" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "covers, carousel" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "documents, attachments" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_svg_cart +msgid "empty_cart" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "featured, categories, dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "full product, cover, dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "full product, dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "gallery, album, portfolio" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "heading, title" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "icon, features" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "image, dynamic, products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_icon_block_6 +msgid "info@droggol.com" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_7 +msgid "info@yourcompany.com" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "information, content" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/s_category.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/s_category.xml:0 +#: model_terms:theme.ir.ui.view,arch:theme_prime.cart_sidebar +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_compare +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +#, python-format +msgid "items" +msgstr "فرصه تبرع" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.shop_layout +msgid "items found." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/core/cart_confirmation_dialog.xml:0 +#, python-format +msgid "items in your cart." +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/record_selection.xml:0 +#, python-format +msgid "items." +msgstr "فرصه تبرع" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "newsletter, subscribe, mail, email, marketing, mass mailing" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/search_input.xml:0 +#, python-format +msgid "of" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "offer" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_tabs +msgid "or" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_call_to_action_2 +msgid "or give us a call" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.tp_svg_404 +msgid "page not found" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_pricing_5 +msgid "per month" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#: code:addons/theme_prime/static/src/components/dialog.xml:0 +#, python-format +msgid "phone" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "pricing, comparison, table" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/frontend/brands.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/brands.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/hierarchical_category_templates.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/hierarchical_category_templates.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/hierarchical_category_templates.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/hierarchical_category_templates.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/s_category.xml:0 +#: code:addons/theme_prime/static/src/xml/frontend/s_category.xml:0 +#, python-format +msgid "products" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "products, dynamic" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "stats, counter, number" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "team, avatar, profile, organisation, structure" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippets +msgid "testimonials, quotes" +msgstr "" + +#. module: theme_prime +#. odoo-javascript +#: code:addons/theme_prime/static/src/xml/pwa.xml:0 +#, python-format +msgid "then Add to Home Screen." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_coming_soon_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.s_subscribe_4 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_1 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_10 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_2 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_3 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_5 +#: model_terms:theme.ir.ui.view,arch:theme_prime.template_footer_style_6 +msgid "your email..." +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.product_wishlist +msgid "youremail@gmail.com" +msgstr "" + +#. module: theme_prime +#: model_terms:theme.ir.ui.view,arch:theme_prime.snippet_options +msgid "⌙ Colors" +msgstr "" diff --git a/odex25_donation/theme_prime/models/__init__.py b/odex25_donation/theme_prime/models/__init__.py new file mode 100644 index 000000000..53de46f3a --- /dev/null +++ b/odex25_donation/theme_prime/models/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from . import theme_prime +from . import ir_http +from . import product_template diff --git a/odex25_donation/theme_prime/models/ir_http.py b/odex25_donation/theme_prime/models/ir_http.py new file mode 100644 index 000000000..900069fe1 --- /dev/null +++ b/odex25_donation/theme_prime/models/ir_http.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import models + + +class IrHttp(models.AbstractModel): + _inherit = 'ir.http' + + @classmethod + def _get_translation_frontend_modules_name(cls): + mods = super(IrHttp, cls)._get_translation_frontend_modules_name() + return mods + ['droggol_theme_common', 'theme_prime'] diff --git a/odex25_donation/theme_prime/models/product_template.py b/odex25_donation/theme_prime/models/product_template.py new file mode 100644 index 000000000..bb8d04cdd --- /dev/null +++ b/odex25_donation/theme_prime/models/product_template.py @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import models, fields, api, tools + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + dr_has_discount = fields.Boolean(compute="_compute_dr_has_discount", search="_search_dr_has_discount") + + def _search_dr_has_discount(self, operator, value): + pricelist_id = self._context.get('pricelist') + if pricelist_id: + all_product_data, discounted_product_ids = self._get_product_pricelist_data(pricelist_id) + operator = 'in' if operator == '!=' else 'not in' + return [('id', operator, discounted_product_ids)] + return [] + + def _need_catch_update(self, pricelist_id, catch_date): + catch_date_obj = fields.Datetime.to_datetime(catch_date) + item_ids_catch = self._pricelist_items_for_date(pricelist_id, catch_date) + item_ids_now = self._pricelist_items_for_date(pricelist_id, fields.Datetime.to_string(fields.Datetime.now())) + if set(item_ids_catch) != set(item_ids_now): + return True + + if self.env['product.pricelist'].browse(pricelist_id).write_date > catch_date_obj: + return True + + product_grouped_data = self.env['product.template'].read_group([('sale_ok', '=', True)], ['write_date:max'], ['sale_ok']) + if product_grouped_data: + product_date = product_grouped_data[0].get('write_date') + if product_date > catch_date_obj: + return True + return False + + @api.model + def _pricelist_items_for_date(self, pricelist_id, date): + self.env['product.pricelist.item'].flush(['price', 'currency_id', 'company_id']) + self.env.cr.execute( + """ SELECT item.id FROM product_pricelist_item AS item + WHERE (item.pricelist_id = %s) AND (item.date_start IS NULL OR item.date_start<=%s) AND (item.date_end IS NULL OR item.date_end>=%s) + """, (pricelist_id, date, date)) + return [x[0] for x in self.env.cr.fetchall()] + + def _get_product_pricelist_data(self, pricelist_id): + all_product_data, discounted_product_ids, catch_date = self._get_product_pricelist_cache(pricelist_id) + need_catch_update = self._need_catch_update(pricelist_id, catch_date) + if need_catch_update: + self.clear_caches() + all_product_data, discounted_product_ids, catch_date = self._get_product_pricelist_cache(pricelist_id) + return all_product_data, discounted_product_ids + + @tools.ormcache('pricelist_id') + def _get_product_pricelist_cache(self, pricelist_id): + products = self.sudo().search([('sale_ok', '=', True)]) # Need sudo so all products are calculated + pricelist = self.env['product.pricelist'].browse(pricelist_id) + discounted_product_ids = [] + all_products_data = [] + for product in products: + product_data = product._get_combination_info(pricelist=pricelist, only_template=True) + all_products_data.append(self._dr_process_product_data(product_data, product)) + if product_data.get('has_discounted_price'): + discounted_product_ids.append(product.id) + return all_products_data, discounted_product_ids, fields.Datetime.to_string(fields.Datetime.now()) + + def _dr_process_product_data(self, product_pricelist_data, product): + return {'display_name': product_pricelist_data['display_name'], 'price': product_pricelist_data['price'], 'id': product_pricelist_data['product_template_id']} + + def _compute_dr_has_discount(self): + for product in self: + product.dr_has_discount = False + + def _get_product_category_count(self, domain=[]): + tables, where_clause, where_clause_params = self._dr_prepare_query_parts(domain) + query = """ + SELECT + count(product_template.id), + product_public_category.parent_path as path, + product_public_category.parent_id as parent_id, + product_public_category.id as product_public_category_id + FROM product_public_category_product_template_rel + JOIN product_template ON product_template.id = product_public_category_product_template_rel.product_template_id + """ + tables + """ + RIGHT JOIN product_public_category ON product_public_category.id = product_public_category_product_template_rel.product_public_category_id + WHERE """ + where_clause + """ or product_template.id is NULL + GROUP BY product_public_category.id; + """ + + self.env.cr.execute(query, where_clause_params) + query_res = self.env.cr.dictfetchall() + + result_count = dict([(line.get('product_public_category_id'), 0) for line in query_res]) + + for line in query_res: + for line2 in query_res: + if line.get('parent_id'): + path_pattern = '/%s/' % line.get('product_public_category_id') + if path_pattern in line2.get('path'): + result_count[line.get('product_public_category_id')] += line2.get('count') + else: + path_pattern = '%s/' % line.get('product_public_category_id') + if line2.get('path').startswith(path_pattern): + result_count[line.get('product_public_category_id')] += line2.get('count') + + return result_count + + def _get_product_attrib_count(self, attrib_values, domain=[]): + tables, where_clause, where_clause_params = self._dr_prepare_query_parts(domain) + + query = """ + SELECT + array_agg(product_template_attribute_line.product_tmpl_id) as product_tmpl_ids, + min(product_template_attribute_line.attribute_id) as product_attrib_id, + product_attribute_value.id + FROM product_template_attribute_line + JOIN product_attribute_value_product_template_attribute_line_rel + ON product_attribute_value_product_template_attribute_line_rel.product_template_attribute_line_id = product_template_attribute_line.id + JOIN product_attribute_value + ON product_attribute_value.id = product_attribute_value_product_template_attribute_line_rel.product_attribute_value_id + JOIN product_template ON product_template.id = product_template_attribute_line.product_tmpl_id + """ + tables + """ + WHERE """ + where_clause + """ or product_template.id is NULL + GROUP BY product_attribute_value.id + ORDER BY product_attrib_id; + """ + + self.env.cr.execute(query, where_clause_params) + query_res = self.env.cr.dictfetchall() + + result_count = {} + + if attrib_values: + + attrib_values_ids = [v[1] for v in attrib_values] + attrib_ids = [v[0] for v in attrib_values] + attrib_value_list = dict([(line.get('id'), line.get('product_tmpl_ids') or []) for line in query_res]) + + # Attribute -> Attribute Vals map + attrib_vals_map = {} + for line in query_res: + if not attrib_vals_map.get(line['product_attrib_id']): + attrib_vals_map[line['product_attrib_id']] = [] + attrib_vals_map[line['product_attrib_id']].append(line['id']) + + # Attribute -> active product list + attrib_p_list = {} + for line in query_res: + + value_id_1 = line.get('id') + product_ids_1 = line.get('product_tmpl_ids') or [] + attrib_id_1 = line.get('product_attrib_id') + + if not attrib_p_list.get(attrib_id_1): + attrib_p_list[attrib_id_1] = set() + + if value_id_1 in attrib_values_ids: + attrib_p_list[attrib_id_1] = attrib_p_list[attrib_id_1] | set(product_ids_1) + + # Attribute -> final list + attrib_product_list = {} + for line in query_res: + value_id_1 = line.get('id') + product_ids_1 = line.get('product_tmpl_ids') or [] + attrib_id_1 = line.get('product_attrib_id') + + if not attrib_product_list.get(value_id_1): + attrib_product_list[value_id_1] = set(product_ids_1) + + for line_2 in query_res: + value_id_2 = line_2.get('id') + product_ids_2 = line_2.get('product_tmpl_ids') or [] + attrib_id_2 = line_2.get('product_attrib_id') + + if value_id_2 not in attrib_vals_map.get(attrib_id_1, []) and value_id_2 in attrib_values_ids: + attrib_product_list[value_id_1] = attrib_product_list[value_id_1] & attrib_p_list.get(attrib_id_2, set()) + + result_count = dict([(val_id, len(product_ids)) for val_id, product_ids in attrib_product_list.items()]) + else: + result_count = dict([(line.get('id'), len(line.get('product_tmpl_ids') or [])) for line in query_res]) + return result_count + + def _get_product_rating_count(self, domain=[]): + tables, where_clause, where_clause_params = self._dr_prepare_query_parts(domain) + query = """ + SELECT avg_rating, count(*) FROM ( + SELECT FLOOR(avg(rating)) as avg_rating, rating_rating.res_id FROM rating_rating JOIN product_template ON product_template.id = rating_rating.res_id """ + tables + """ + WHERE (""" + where_clause + """) AND rating_rating.res_model = 'product.template' AND rating_rating.is_internal = False + GROUP BY rating_rating.res_id) AS rating_count group by avg_rating; """ + + self.env.cr.execute(query, where_clause_params) + query_result = dict(self.env.cr.fetchall()) + total = 0 + ratings_result = {rating: 0 for rating in range(1, 6)} + for result in range(5, 0, -1): + total += query_result.get(result, 0) + ratings_result[result] = total + return ratings_result + + def _dr_prepare_query_parts(self, domain): + query = self._where_calc(domain) + self._apply_ir_rules(query) + tables, where_clause, where_clause_params = query.get_sql() + tables = tables.replace('"product_template"', ' ', 1) + return tables, where_clause, where_clause_params + + def _search_render_results(self, fetch_fields, mapping, icon, limit): + current_website = self.env['website'].get_current_website() + if not current_website._dr_has_b2b_access(): + mapping.pop("detail", None) + return super()._search_render_results(fetch_fields, mapping, icon, limit) diff --git a/odex25_donation/theme_prime/models/theme_prime.py b/odex25_donation/theme_prime/models/theme_prime.py new file mode 100644 index 000000000..5f56a869f --- /dev/null +++ b/odex25_donation/theme_prime/models/theme_prime.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019-Present Droggol Infotech Private Limited. () + +from odoo import api, models + + +class ThemePrime(models.AbstractModel): + _inherit = 'theme.utils' + + @api.model + def _reset_default_config(self): + header_styles = list(range(1, 9)) + for style in header_styles: + self.disable_view('theme_prime.template_header_style_%s' % style) + + footer_styles = list(range(1, 11)) + for style in footer_styles: + self.disable_view('theme_prime.template_footer_style_%s' % style) + + super()._reset_default_config() diff --git a/odex25_donation/theme_prime/static/description/icon.png b/odex25_donation/theme_prime/static/description/icon.png new file mode 100644 index 000000000..94cae5d06 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/icon.png differ diff --git a/odex25_donation/theme_prime/static/description/images/Copy of Cart Flow Options.png b/odex25_donation/theme_prime/static/description/images/Copy of Cart Flow Options.png new file mode 100644 index 000000000..9e37edd9d Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/Copy of Cart Flow Options.png differ diff --git a/odex25_donation/theme_prime/static/description/images/b2b-mode.png b/odex25_donation/theme_prime/static/description/images/b2b-mode.png new file mode 100644 index 000000000..5f8d96078 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/b2b-mode.png differ diff --git a/odex25_donation/theme_prime/static/description/images/card-features.gif b/odex25_donation/theme_prime/static/description/images/card-features.gif new file mode 100644 index 000000000..f3d37556b Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/card-features.gif differ diff --git a/odex25_donation/theme_prime/static/description/images/cards.gif b/odex25_donation/theme_prime/static/description/images/cards.gif new file mode 100644 index 000000000..9c9dea469 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/cards.gif differ diff --git a/odex25_donation/theme_prime/static/description/images/cards.png b/odex25_donation/theme_prime/static/description/images/cards.png new file mode 100644 index 000000000..c63ead2bb Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/cards.png differ diff --git a/odex25_donation/theme_prime/static/description/images/cart-1.png b/odex25_donation/theme_prime/static/description/images/cart-1.png new file mode 100644 index 000000000..12cbedea6 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/cart-1.png differ diff --git a/odex25_donation/theme_prime/static/description/images/cart-2.png b/odex25_donation/theme_prime/static/description/images/cart-2.png new file mode 100644 index 000000000..b483a372c Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/cart-2.png differ diff --git a/odex25_donation/theme_prime/static/description/images/cart-icon.png b/odex25_donation/theme_prime/static/description/images/cart-icon.png new file mode 100644 index 000000000..59029fc37 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/cart-icon.png differ diff --git a/odex25_donation/theme_prime/static/description/images/config-footer.png b/odex25_donation/theme_prime/static/description/images/config-footer.png new file mode 100644 index 000000000..e4fffa452 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/config-footer.png differ diff --git a/odex25_donation/theme_prime/static/description/images/contact.png b/odex25_donation/theme_prime/static/description/images/contact.png new file mode 100644 index 000000000..d912a8ac6 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/contact.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/01-quick-view.png b/odex25_donation/theme_prime/static/description/images/features/01-quick-view.png new file mode 100644 index 000000000..32f70a47e Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/01-quick-view.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/02-tabs.png b/odex25_donation/theme_prime/static/description/images/features/02-tabs.png new file mode 100644 index 000000000..b1e147697 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/02-tabs.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/03-pricelist.png b/odex25_donation/theme_prime/static/description/images/features/03-pricelist.png new file mode 100644 index 000000000..c084c2e34 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/03-pricelist.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/04-portal.png b/odex25_donation/theme_prime/static/description/images/features/04-portal.png new file mode 100644 index 000000000..7065dcba5 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/04-portal.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/05-offers-popup.png b/odex25_donation/theme_prime/static/description/images/features/05-offers-popup.png new file mode 100644 index 000000000..50fccb1ae Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/05-offers-popup.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/06-attr-popup.png b/odex25_donation/theme_prime/static/description/images/features/06-attr-popup.png new file mode 100644 index 000000000..32094cec4 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/06-attr-popup.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/07-doc.png b/odex25_donation/theme_prime/static/description/images/features/07-doc.png new file mode 100644 index 000000000..aa47248c8 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/07-doc.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/08-doc.png b/odex25_donation/theme_prime/static/description/images/features/08-doc.png new file mode 100644 index 000000000..cd6d3fe8b Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/08-doc.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/09-brand.png b/odex25_donation/theme_prime/static/description/images/features/09-brand.png new file mode 100644 index 000000000..ddab23df1 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/09-brand.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/10-countdown.png b/odex25_donation/theme_prime/static/description/images/features/10-countdown.png new file mode 100644 index 000000000..abdd4a140 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/10-countdown.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/11-icons.png b/odex25_donation/theme_prime/static/description/images/features/11-icons.png new file mode 100644 index 000000000..eac7a0955 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/11-icons.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/12-coming-soon.png b/odex25_donation/theme_prime/static/description/images/features/12-coming-soon.png new file mode 100644 index 000000000..1c684dd40 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/12-coming-soon.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/13-zoom.png b/odex25_donation/theme_prime/static/description/images/features/13-zoom.png new file mode 100644 index 000000000..169cf519f Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/13-zoom.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/14-pricelist-timer.png b/odex25_donation/theme_prime/static/description/images/features/14-pricelist-timer.png new file mode 100644 index 000000000..0752a956f Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/14-pricelist-timer.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/15-multi-website.png b/odex25_donation/theme_prime/static/description/images/features/15-multi-website.png new file mode 100644 index 000000000..621ee5520 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/15-multi-website.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/16-rtl.png b/odex25_donation/theme_prime/static/description/images/features/16-rtl.png new file mode 100644 index 000000000..824a5f069 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/16-rtl.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/17-highlited-menu.png b/odex25_donation/theme_prime/static/description/images/features/17-highlited-menu.png new file mode 100644 index 000000000..ba86c5fe8 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/17-highlited-menu.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/18-all-brands-page.png b/odex25_donation/theme_prime/static/description/images/features/18-all-brands-page.png new file mode 100644 index 000000000..182b37f60 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/18-all-brands-page.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/19-layload-products.png b/odex25_donation/theme_prime/static/description/images/features/19-layload-products.png new file mode 100644 index 000000000..f9e785b11 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/19-layload-products.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/20-product-tags.png b/odex25_donation/theme_prime/static/description/images/features/20-product-tags.png new file mode 100644 index 000000000..7312692dd Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/20-product-tags.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/90-demo-1.png b/odex25_donation/theme_prime/static/description/images/features/90-demo-1.png new file mode 100644 index 000000000..f8688f45a Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/90-demo-1.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/90-demo-2.png b/odex25_donation/theme_prime/static/description/images/features/90-demo-2.png new file mode 100644 index 000000000..5b1151bb2 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/90-demo-2.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/90-demo-3.png b/odex25_donation/theme_prime/static/description/images/features/90-demo-3.png new file mode 100644 index 000000000..03bea86fe Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/90-demo-3.png differ diff --git a/odex25_donation/theme_prime/static/description/images/features/docs_screenshot.png b/odex25_donation/theme_prime/static/description/images/features/docs_screenshot.png new file mode 100644 index 000000000..c3dda8f81 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/features/docs_screenshot.png differ diff --git a/odex25_donation/theme_prime/static/description/images/filter-footer.png b/odex25_donation/theme_prime/static/description/images/filter-footer.png new file mode 100644 index 000000000..8aff36ff2 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/filter-footer.png differ diff --git a/odex25_donation/theme_prime/static/description/images/filter.gif b/odex25_donation/theme_prime/static/description/images/filter.gif new file mode 100644 index 000000000..92dc6d006 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/filter.gif differ diff --git a/odex25_donation/theme_prime/static/description/images/filters-hero.png b/odex25_donation/theme_prime/static/description/images/filters-hero.png new file mode 100644 index 000000000..92ccb076d Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/filters-hero.png differ diff --git a/odex25_donation/theme_prime/static/description/images/header.gif b/odex25_donation/theme_prime/static/description/images/header.gif new file mode 100644 index 000000000..60d474890 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/header.gif differ diff --git a/odex25_donation/theme_prime/static/description/images/header.png b/odex25_donation/theme_prime/static/description/images/header.png new file mode 100644 index 000000000..7e614f33d Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/header.png differ diff --git a/odex25_donation/theme_prime/static/description/images/headers-2.png b/odex25_donation/theme_prime/static/description/images/headers-2.png new file mode 100644 index 000000000..01cbfbf75 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/headers-2.png differ diff --git a/odex25_donation/theme_prime/static/description/images/hero-2.png b/odex25_donation/theme_prime/static/description/images/hero-2.png new file mode 100644 index 000000000..c2fb09115 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/hero-2.png differ diff --git a/odex25_donation/theme_prime/static/description/images/hero.png b/odex25_donation/theme_prime/static/description/images/hero.png new file mode 100644 index 000000000..e49cf0444 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/hero.png differ diff --git a/odex25_donation/theme_prime/static/description/images/hotspot-1.gif b/odex25_donation/theme_prime/static/description/images/hotspot-1.gif new file mode 100644 index 000000000..7678dc450 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/hotspot-1.gif differ diff --git a/odex25_donation/theme_prime/static/description/images/hotspot-3.png b/odex25_donation/theme_prime/static/description/images/hotspot-3.png new file mode 100644 index 000000000..4454e2564 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/hotspot-3.png differ diff --git a/odex25_donation/theme_prime/static/description/images/hotspot-4.gif b/odex25_donation/theme_prime/static/description/images/hotspot-4.gif new file mode 100644 index 000000000..1981e282f Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/hotspot-4.gif differ diff --git a/odex25_donation/theme_prime/static/description/images/hotspot.png b/odex25_donation/theme_prime/static/description/images/hotspot.png new file mode 100644 index 000000000..11e302fcf Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/hotspot.png differ diff --git a/odex25_donation/theme_prime/static/description/images/megamenu-footer.png b/odex25_donation/theme_prime/static/description/images/megamenu-footer.png new file mode 100644 index 000000000..cf03d71ec Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/megamenu-footer.png differ diff --git a/odex25_donation/theme_prime/static/description/images/megamenu-hero-2.png b/odex25_donation/theme_prime/static/description/images/megamenu-hero-2.png new file mode 100644 index 000000000..8224dd95f Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/megamenu-hero-2.png differ diff --git a/odex25_donation/theme_prime/static/description/images/megamenu-hero.png b/odex25_donation/theme_prime/static/description/images/megamenu-hero.png new file mode 100644 index 000000000..749d6949c Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/megamenu-hero.png differ diff --git a/odex25_donation/theme_prime/static/description/images/megamenu.gif b/odex25_donation/theme_prime/static/description/images/megamenu.gif new file mode 100644 index 000000000..22d621412 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/megamenu.gif differ diff --git a/odex25_donation/theme_prime/static/description/images/megamenu.mp4 b/odex25_donation/theme_prime/static/description/images/megamenu.mp4 new file mode 100644 index 000000000..507bdbd93 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/megamenu.mp4 differ diff --git a/odex25_donation/theme_prime/static/description/images/menus.png b/odex25_donation/theme_prime/static/description/images/menus.png new file mode 100644 index 000000000..51b16da30 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/menus.png differ diff --git a/odex25_donation/theme_prime/static/description/images/mobile.mp4 b/odex25_donation/theme_prime/static/description/images/mobile.mp4 new file mode 100644 index 000000000..ad44bd116 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/mobile.mp4 differ diff --git a/odex25_donation/theme_prime/static/description/images/mobile.png b/odex25_donation/theme_prime/static/description/images/mobile.png new file mode 100644 index 000000000..12bf837bc Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/mobile.png differ diff --git a/odex25_donation/theme_prime/static/description/images/prime-logo.png b/odex25_donation/theme_prime/static/description/images/prime-logo.png new file mode 100644 index 000000000..a69d46871 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/prime-logo.png differ diff --git a/odex25_donation/theme_prime/static/description/images/pwa.png b/odex25_donation/theme_prime/static/description/images/pwa.png new file mode 100644 index 000000000..6b843e31c Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/pwa.png differ diff --git a/odex25_donation/theme_prime/static/description/images/search-ss.gif b/odex25_donation/theme_prime/static/description/images/search-ss.gif new file mode 100644 index 000000000..a55c856f7 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/search-ss.gif differ diff --git a/odex25_donation/theme_prime/static/description/images/search.gif b/odex25_donation/theme_prime/static/description/images/search.gif new file mode 100644 index 000000000..dfea44701 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/search.gif differ diff --git a/odex25_donation/theme_prime/static/description/images/searchss.mp4 b/odex25_donation/theme_prime/static/description/images/searchss.mp4 new file mode 100644 index 000000000..8d647bb6e Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/searchss.mp4 differ diff --git a/odex25_donation/theme_prime/static/description/images/settings.png b/odex25_donation/theme_prime/static/description/images/settings.png new file mode 100644 index 000000000..aa7f63257 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/settings.png differ diff --git a/odex25_donation/theme_prime/static/description/images/smart-search.png b/odex25_donation/theme_prime/static/description/images/smart-search.png new file mode 100644 index 000000000..ad4c50502 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/smart-search.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/1.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/1.png new file mode 100644 index 000000000..7d62fa395 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/1.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/10.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/10.png new file mode 100644 index 000000000..fe3fd84cd Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/10.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/11.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/11.png new file mode 100644 index 000000000..ef9362bac Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/11.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/12.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/12.png new file mode 100644 index 000000000..7af6a012c Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/12.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/13.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/13.png new file mode 100644 index 000000000..d68143c06 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/13.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/14.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/14.png new file mode 100644 index 000000000..510585a2a Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/14.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/15.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/15.png new file mode 100644 index 000000000..71cb55dd2 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/15.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/16.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/16.png new file mode 100644 index 000000000..bf3634704 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/16.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/17.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/17.png new file mode 100644 index 000000000..4779e3b07 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/17.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/2.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/2.png new file mode 100644 index 000000000..34f997722 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/2.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/3.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/3.png new file mode 100644 index 000000000..b1902cc55 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/3.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/4.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/4.png new file mode 100644 index 000000000..f44c4d594 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/4.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/5.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/5.png new file mode 100644 index 000000000..ea195fb1a Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/5.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/6.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/6.png new file mode 100644 index 000000000..98aaaa82a Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/6.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/7.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/7.png new file mode 100644 index 000000000..9054033df Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/7.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/8.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/8.png new file mode 100644 index 000000000..7b399b6ad Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/8.png differ diff --git a/odex25_donation/theme_prime/static/description/images/snippet_thumb/9.png b/odex25_donation/theme_prime/static/description/images/snippet_thumb/9.png new file mode 100644 index 000000000..eb09f195e Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/snippet_thumb/9.png differ diff --git a/odex25_donation/theme_prime/static/description/images/theme-configurator-old.png b/odex25_donation/theme_prime/static/description/images/theme-configurator-old.png new file mode 100644 index 000000000..32046b869 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/theme-configurator-old.png differ diff --git a/odex25_donation/theme_prime/static/description/images/theme-configurator.png b/odex25_donation/theme_prime/static/description/images/theme-configurator.png new file mode 100644 index 000000000..060bc3575 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/theme-configurator.png differ diff --git a/odex25_donation/theme_prime/static/description/images/tools-text.png b/odex25_donation/theme_prime/static/description/images/tools-text.png new file mode 100644 index 000000000..3977b342d Binary files /dev/null and b/odex25_donation/theme_prime/static/description/images/tools-text.png differ diff --git a/odex25_donation/theme_prime/static/description/index.html b/odex25_donation/theme_prime/static/description/index.html new file mode 100644 index 000000000..196109cb5 --- /dev/null +++ b/odex25_donation/theme_prime/static/description/index.html @@ -0,0 +1,732 @@ +
+
+
+
+
+ + +
+
+
+ +
+ + Need a help? + +
+ info@droggol.com +
+
+ +
+
+
+ + +
+ + +
+ +
+
+
+ +
+
+
+
+ + + +
+
+
+ +
+ +
+ +
+

Answer your visitors questions instantly.
Messages pop up on your backend.

+
+
+

Create customized forms to convert more, and integrate them in your business flow in just a few clicks.

+
+
+

Let people review and rate your products. Showcase your best products thanks to customers' comments.

+
+
+

Boost your sales with cross-selling and upselling opportunities on product pages, in the cart, or at checkout.

+
+
+

Encourage potential customers to buy your products with coupons and promotion campaigns.

+
+ + +
+ + + +
+
+ + +
+
+
+ +
+ + + +
+
+
+
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+ +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ + + +
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+

Explore Live Demo
for Electronic Store

+
+
+ Copy Given URL for Demo
+
+

+ droggol.com/r/demo16-1

+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+

Explore Live Demo
for Electronic Store 2 +

+
+
+ Copy Given URL for Demo
+
+

+ droggol.com/r/demo16-2

+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+

Explore Live Demo
for Food Store

+
+
+ Copy Given URL for Demo
+
+

+ droggol.com/r/demo16-3 +

+
+
+
+
+
+
+
+
+ +
+
+
+ +
+
+
+
+
+

Why theme prime

+

+ There several reasons to choose theme prime. One of them is, its wide range of + configuration options. + With tons of configuration option you can mold your eCommerce based on your choice. + These configuration options are so easy to use that even user with no technical + knowledge can configure the eCommerce. +

+ Theme prime has all the options that are required to run any modern eCommerce theme. It + supports multi-language and multi-website + so you can run multiple website with different configuration in the same odoo instance. +

+

+ Theme prime is developed by experience developers so it has top notch quality. Even if + it has tones of feature it does not slow down and runs without any hassle. +

+
+
+
+
+
+
+

Full Documentation

+

We would like explain each and every feature of our theme that's why we have created + detailed documentation. + We are constantly improving and adding new content and videos. +

+
+ A full documentation + can be accessed after purchasing the theme. It is available in /docs folder of + theme module. +
+
+
+ +
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+

Changelog

+
+ +

+ v16.0.0.0-Dec 19, 2022 +

+
    +
  • + Initial release for v16 +
  • +
+
+
+ +
+ diff --git a/odex25_donation/theme_prime/static/description/other_apps/app_1.png b/odex25_donation/theme_prime/static/description/other_apps/app_1.png new file mode 100644 index 000000000..0f5c5e30f Binary files /dev/null and b/odex25_donation/theme_prime/static/description/other_apps/app_1.png differ diff --git a/odex25_donation/theme_prime/static/description/other_apps/app_2.png b/odex25_donation/theme_prime/static/description/other_apps/app_2.png new file mode 100644 index 000000000..9a7e19641 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/other_apps/app_2.png differ diff --git a/odex25_donation/theme_prime/static/description/other_apps/app_3.png b/odex25_donation/theme_prime/static/description/other_apps/app_3.png new file mode 100644 index 000000000..e4fc1e8a1 Binary files /dev/null and b/odex25_donation/theme_prime/static/description/other_apps/app_3.png differ diff --git a/odex25_donation/theme_prime/static/description/prime_cover.png b/odex25_donation/theme_prime/static/description/prime_cover.png new file mode 100644 index 000000000..cdffa589a Binary files /dev/null and b/odex25_donation/theme_prime/static/description/prime_cover.png differ diff --git a/odex25_donation/theme_prime/static/description/prime_screenshot.gif b/odex25_donation/theme_prime/static/description/prime_screenshot.gif new file mode 100644 index 000000000..dbe9e648a Binary files /dev/null and b/odex25_donation/theme_prime/static/description/prime_screenshot.gif differ diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-1.css b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-1.css new file mode 100644 index 000000000..6019d1d27 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-1.css @@ -0,0 +1,93 @@ +@font-face { + font-family: 'Droggol-Pack'; + src: url('fonts/Droggol-Pack.eot?4iwoe7'); + src: url('fonts/Droggol-Pack.eot?4iwoe7#iefix') format('embedded-opentype'), + url('fonts/Droggol-Pack.ttf?4iwoe7') format('truetype'), + url('fonts/Droggol-Pack.woff?4iwoe7') format('woff'), + url('fonts/Droggol-Pack.svg?4iwoe7#Droggol-Pack') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +[class^="dri-"], [class*=" dri-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'Droggol-Pack' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.dri-eye:before { + content: "\e905"; +} +.dri-wishlist:before { + content: "\e906"; +} +.dri-compare:before { + content: "\e900"; +} +.dri-search:before { + content: "\e901"; +} +.dri-cart:before { + content: "\e902"; +} +.dri-user:before { + content: "\e903"; +} +.dri-bolt:before { + content: "\e904"; +} +.dri-home-l:before { + content: "\e800"; +} +.dri-tag-l:before { + content: "\e82f"; +} +.dri-phone-l:before { + content: "\e830"; +} +.dri-rocket-l:before { + content: "\e84b"; +} +.dri-cross-l:before { + content: "\e870"; +} +.dri-chevron-up-l:before { + content: "\e873"; +} +.dri-chevron-down-l:before { + content: "\e874"; +} +.dri-chevron-left-l:before { + content: "\e875"; +} +.dri-chevron-right-l:before { + content: "\e876"; +} +.dri-arrow-left-l:before { + content: "\e879"; +} +.dri-arrow-right-l:before { + content: "\e87a"; +} +.dri-search-l:before { + content: "\e86f"; +} +.dri-sync-l:before { + content: "\e862"; +} +.dri-menu-circle-l:before { + content: "\e87e"; +} +.dri-category:before { + content: "\e923"; +} diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-2.css b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-2.css new file mode 100644 index 000000000..0b688fd96 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-2.css @@ -0,0 +1,93 @@ +@font-face { + font-family: 'Droggol-Pack'; + src: url('fonts/Droggol-Pack.eot?4iwoe7'); + src: url('fonts/Droggol-Pack.eot?4iwoe7#iefix') format('embedded-opentype'), + url('fonts/Droggol-Pack.ttf?4iwoe7') format('truetype'), + url('fonts/Droggol-Pack.woff?4iwoe7') format('woff'), + url('fonts/Droggol-Pack.svg?4iwoe7#Droggol-Pack') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +[class^="dri-"], [class*=" dri-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'Droggol-Pack' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.dri-home-l:before { + content: "\e800"; +} +.dri-tag-l:before { + content: "\e82f"; +} +.dri-phone-l:before { + content: "\e830"; +} +.dri-rocket-l:before { + content: "\e84b"; +} +.dri-cross-l:before { + content: "\e870"; +} +.dri-chevron-up-l:before { + content: "\e873"; +} +.dri-chevron-down-l:before { + content: "\e874"; +} +.dri-chevron-left-l:before { + content: "\e875"; +} +.dri-chevron-right-l:before { + content: "\e876"; +} +.dri-arrow-left-l:before { + content: "\e879"; +} +.dri-arrow-right-l:before { + content: "\e87a"; +} +.dri-search:before { + content: "\f002"; +} +.dri-wishlist:before { + content: "\f004"; +} +.dri-user:before { + content: "\f007"; +} +.dri-eye:before { + content: "\f06e"; +} +.dri-cart:before { + content: "\f07a"; +} +.dri-bolt:before { + content: "\f0e7"; +} +.dri-compare:before { + content: "\f0ec"; +} +.dri-search-l:before { + content: "\e86f"; +} +.dri-sync-l:before { + content: "\e862"; +} +.dri-menu-circle-l:before { + content: "\e87e"; +} +.dri-category:before { + content: "\e923"; +} diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-3.css b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-3.css new file mode 100644 index 000000000..cba4f6b60 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-3.css @@ -0,0 +1,93 @@ +@font-face { + font-family: 'Droggol-Pack'; + src: url('fonts/Droggol-Pack.eot?4iwoe7'); + src: url('fonts/Droggol-Pack.eot?4iwoe7#iefix') format('embedded-opentype'), + url('fonts/Droggol-Pack.ttf?4iwoe7') format('truetype'), + url('fonts/Droggol-Pack.woff?4iwoe7') format('woff'), + url('fonts/Droggol-Pack.svg?4iwoe7#Droggol-Pack') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +[class^="dri-"], [class*=" dri-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'Droggol-Pack' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.dri-eye:before { + content: "\ecb5"; +} +.dri-bolt:before { + content: "\ed3d"; +} +.dri-wishlist:before { + content: "\ee0b"; +} +.dri-compare:before { + content: "\f074"; +} +.dri-search:before { + content: "\f0d1"; +} +.dri-cart:before { + content: "\f120"; +} +.dri-user:before { + content: "\f264"; +} +.dri-home-l:before { + content: "\e800"; +} +.dri-tag-l:before { + content: "\e82f"; +} +.dri-phone-l:before { + content: "\e830"; +} +.dri-rocket-l:before { + content: "\e84b"; +} +.dri-cross-l:before { + content: "\e870"; +} +.dri-chevron-up-l:before { + content: "\e873"; +} +.dri-chevron-down-l:before { + content: "\e874"; +} +.dri-chevron-left-l:before { + content: "\e875"; +} +.dri-chevron-right-l:before { + content: "\e876"; +} +.dri-arrow-left-l:before { + content: "\e879"; +} +.dri-arrow-right-l:before { + content: "\e87a"; +} +.dri-search-l:before { + content: "\e86f"; +} +.dri-sync-l:before { + content: "\e862"; +} +.dri-menu-circle-l:before { + content: "\e87e"; +} +.dri-category:before { + content: "\e923"; +} diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-4.css b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-4.css new file mode 100644 index 000000000..479c97e95 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-4.css @@ -0,0 +1,93 @@ +@font-face { + font-family: 'Droggol-Pack'; + src: url('fonts/Droggol-Pack.eot?4iwoe7'); + src: url('fonts/Droggol-Pack.eot?4iwoe7#iefix') format('embedded-opentype'), + url('fonts/Droggol-Pack.ttf?4iwoe7') format('truetype'), + url('fonts/Droggol-Pack.woff?4iwoe7') format('woff'), + url('fonts/Droggol-Pack.svg?4iwoe7#Droggol-Pack') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +[class^="dri-"], [class*=" dri-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'Droggol-Pack' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.dri-bolt:before { + content: "\e913"; +} +.dri-wishlist:before { + content: "\e914"; +} +.dri-compare:before { + content: "\e915"; +} +.dri-search:before { + content: "\e916"; +} +.dri-cart:before { + content: "\e917"; +} +.dri-user:before { + content: "\e91b"; +} +.dri-eye:before { + content: "\e918"; +} +.dri-home-l:before { + content: "\e800"; +} +.dri-tag-l:before { + content: "\e82f"; +} +.dri-phone-l:before { + content: "\e830"; +} +.dri-rocket-l:before { + content: "\e84b"; +} +.dri-cross-l:before { + content: "\e870"; +} +.dri-chevron-up-l:before { + content: "\e873"; +} +.dri-chevron-down-l:before { + content: "\e874"; +} +.dri-chevron-left-l:before { + content: "\e875"; +} +.dri-chevron-right-l:before { + content: "\e876"; +} +.dri-arrow-left-l:before { + content: "\e879"; +} +.dri-arrow-right-l:before { + content: "\e87a"; +} +.dri-search-l:before { + content: "\e86f"; +} +.dri-sync-l:before { + content: "\e862"; +} +.dri-menu-circle-l:before { + content: "\e87e"; +} +.dri-category:before { + content: "\e923"; +} diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-5.css b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-5.css new file mode 100644 index 000000000..3bf0ca78f --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-5.css @@ -0,0 +1,93 @@ +@font-face { + font-family: 'Droggol-Pack'; + src: url('fonts/Droggol-Pack.eot?4iwoe7'); + src: url('fonts/Droggol-Pack.eot?4iwoe7#iefix') format('embedded-opentype'), + url('fonts/Droggol-Pack.ttf?4iwoe7') format('truetype'), + url('fonts/Droggol-Pack.woff?4iwoe7') format('woff'), + url('fonts/Droggol-Pack.svg?4iwoe7#Droggol-Pack') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +[class^="dri-"], [class*=" dri-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'Droggol-Pack' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.dri-eye:before { + content: "\e90d"; +} +.dri-bolt:before { + content: "\e90e"; +} +.dri-wishlist:before { + content: "\e90f"; +} +.dri-search:before { + content: "\e911"; +} +.dri-cart:before { + content: "\e912"; +} +.dri-compare:before { + content: "\e910"; +} +.dri-user:before { + content: "\e91a"; +} +.dri-home-l:before { + content: "\e800"; +} +.dri-tag-l:before { + content: "\e82f"; +} +.dri-phone-l:before { + content: "\e830"; +} +.dri-rocket-l:before { + content: "\e84b"; +} +.dri-cross-l:before { + content: "\e870"; +} +.dri-chevron-up-l:before { + content: "\e873"; +} +.dri-chevron-down-l:before { + content: "\e874"; +} +.dri-chevron-left-l:before { + content: "\e875"; +} +.dri-chevron-right-l:before { + content: "\e876"; +} +.dri-arrow-left-l:before { + content: "\e879"; +} +.dri-arrow-right-l:before { + content: "\e87a"; +} +.dri-search-l:before { + content: "\e86f"; +} +.dri-sync-l:before { + content: "\e862"; +} +.dri-menu-circle-l:before { + content: "\e87e"; +} +.dri-category:before { + content: "\e923"; +} diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-6.css b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-6.css new file mode 100644 index 000000000..58d0b393a --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-6.css @@ -0,0 +1,93 @@ +@font-face { + font-family: 'Droggol-Pack'; + src: url('fonts/Droggol-Pack.eot?4iwoe7'); + src: url('fonts/Droggol-Pack.eot?4iwoe7#iefix') format('embedded-opentype'), + url('fonts/Droggol-Pack.ttf?4iwoe7') format('truetype'), + url('fonts/Droggol-Pack.woff?4iwoe7') format('woff'), + url('fonts/Droggol-Pack.svg?4iwoe7#Droggol-Pack') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +[class^="dri-"], [class*=" dri-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'Droggol-Pack' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.dri-eye:before { + content: "\e907"; +} +.dri-cart:before { + content: "\e908"; +} +.dri-user:before { + content: "\e919"; +} +.dri-wishlist:before { + content: "\e909"; +} +.dri-search:before { + content: "\e90a"; +} +.dri-compare:before { + content: "\e90b"; +} +.dri-bolt:before { + content: "\e90c"; +} +.dri-home-l:before { + content: "\e800"; +} +.dri-tag-l:before { + content: "\e82f"; +} +.dri-phone-l:before { + content: "\e830"; +} +.dri-rocket-l:before { + content: "\e84b"; +} +.dri-cross-l:before { + content: "\e870"; +} +.dri-chevron-up-l:before { + content: "\e873"; +} +.dri-chevron-down-l:before { + content: "\e874"; +} +.dri-chevron-left-l:before { + content: "\e875"; +} +.dri-chevron-right-l:before { + content: "\e876"; +} +.dri-arrow-left-l:before { + content: "\e879"; +} +.dri-arrow-right-l:before { + content: "\e87a"; +} +.dri-search-l:before { + content: "\e86f"; +} +.dri-sync-l:before { + content: "\e862"; +} +.dri-menu-circle-l:before { + content: "\e87e"; +} +.dri-category:before { + content: "\e923"; +} diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-7.css b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-7.css new file mode 100644 index 000000000..362025eb5 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-7.css @@ -0,0 +1,93 @@ +@font-face { + font-family: 'Droggol-Pack'; + src: url('fonts/Droggol-Pack.eot?4iwoe7'); + src: url('fonts/Droggol-Pack.eot?4iwoe7#iefix') format('embedded-opentype'), + url('fonts/Droggol-Pack.ttf?4iwoe7') format('truetype'), + url('fonts/Droggol-Pack.woff?4iwoe7') format('woff'), + url('fonts/Droggol-Pack.svg?4iwoe7#Droggol-Pack') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +[class^="dri-"], [class*=" dri-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'Droggol-Pack' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.dri-search:before { + content: "\e91c"; +} +.dri-user:before { + content: "\e91d"; +} +.dri-wishlist:before { + content: "\e91e"; +} +.dri-cart:before { + content: "\e91f"; +} +.dri-eye:before { + content: "\e920"; +} +.dri-bolt:before { + content: "\e921"; +} +.dri-compare:before { + content: "\e922"; +} +.dri-home-l:before { + content: "\e800"; +} +.dri-tag-l:before { + content: "\e82f"; +} +.dri-phone-l:before { + content: "\e830"; +} +.dri-rocket-l:before { + content: "\e84b"; +} +.dri-cross-l:before { + content: "\e870"; +} +.dri-chevron-up-l:before { + content: "\e873"; +} +.dri-chevron-down-l:before { + content: "\e874"; +} +.dri-chevron-left-l:before { + content: "\e875"; +} +.dri-chevron-right-l:before { + content: "\e876"; +} +.dri-arrow-left-l:before { + content: "\e879"; +} +.dri-arrow-right-l:before { + content: "\e87a"; +} +.dri-search-l:before { + content: "\e86f"; +} +.dri-sync-l:before { + content: "\e862"; +} +.dri-menu-circle-l:before { + content: "\e87e"; +} +.dri-category:before { + content: "\e923"; +} diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-8.css b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-8.css new file mode 100644 index 000000000..450fb29ef --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/droggol-pack-8.css @@ -0,0 +1,93 @@ +@font-face { + font-family: 'Droggol-Pack'; + src: url('fonts/Droggol-Pack.eot?4iwoe7'); + src: url('fonts/Droggol-Pack.eot?4iwoe7#iefix') format('embedded-opentype'), + url('fonts/Droggol-Pack.ttf?4iwoe7') format('truetype'), + url('fonts/Droggol-Pack.woff?4iwoe7') format('woff'), + url('fonts/Droggol-Pack.svg?4iwoe7#Droggol-Pack') format('svg'); + font-weight: normal; + font-style: normal; + font-display: block; +} + +[class^="dri-"], [class*=" dri-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'Droggol-Pack' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.dri-home-l:before { + content: "\e800"; +} +.dri-bolt:before { + content: "\e803"; +} +.dri-wishlist:before { + content: "\e813"; +} +.dri-eye:before { + content: "\e81b"; +} +.dri-user:before { + content: "\e82a"; +} +.dri-cart:before { + content: "\e82e"; +} +.dri-tag-l:before { + content: "\e82f"; +} +.dri-phone-l:before { + content: "\e830"; +} +.dri-rocket-l:before { + content: "\e84b"; +} +.dri-compare:before { + content: "\e862"; +} +.dri-search:before { + content: "\e86f"; +} +.dri-cross-l:before { + content: "\e870"; +} +.dri-chevron-up-l:before { + content: "\e873"; +} +.dri-chevron-down-l:before { + content: "\e874"; +} +.dri-chevron-left-l:before { + content: "\e875"; +} +.dri-chevron-right-l:before { + content: "\e876"; +} +.dri-arrow-left-l:before { + content: "\e879"; +} +.dri-arrow-right-l:before { + content: "\e87a"; +} +.dri-search-l:before { + content: "\e86f"; +} +.dri-sync-l:before { + content: "\e862"; +} +.dri-menu-circle-l:before { + content: "\e87e"; +} +.dri-category:before { + content: "\e923"; +} diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.eot b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.eot new file mode 100644 index 000000000..4e30985a5 Binary files /dev/null and b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.eot differ diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.svg b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.svg new file mode 100644 index 000000000..dabb19548 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.svg @@ -0,0 +1,101 @@ + + + + + + +{ + "fontFamily": "Droggol-Pack", + "fontURL": "https://droggol.com/", + "designerURL": "https://droggol.com/", + "license": "", + "licenseURL": "", + "description": "Font generated by IcoMoon.", + "copyright": "Droggol", + "majorVersion": 1, + "minorVersion": 0, + "designer": "https://droggol.com/", + "version": "Version 1.0", + "fontId": "Droggol-Pack", + "psName": "Droggol-Pack", + "subFamily": "Regular", + "fullName": "Droggol-Pack" +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.ttf b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.ttf new file mode 100644 index 000000000..0d0d192ae Binary files /dev/null and b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.ttf differ diff --git a/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.woff b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.woff new file mode 100644 index 000000000..bbfe0bef4 Binary files /dev/null and b/odex25_donation/theme_prime/static/lib/Droggol-Pack-v1.0/fonts/Droggol-Pack.woff differ diff --git a/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/LICENSE b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/LICENSE new file mode 100644 index 000000000..052211da5 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2014 Owl +Modified work Copyright 2016-2018 David Deutsch + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/README.md b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/README.md new file mode 100644 index 000000000..e912df2d5 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/README.md @@ -0,0 +1,122 @@ +# Owl Carousel 2 + +Touch enabled [jQuery](https://jquery.com/) plugin that lets you create a beautiful, responsive carousel slider. **To get started, check out https://owlcarousel2.github.io/OwlCarousel2/.** + +**Notice:** The old Owl Carousel site (owlgraphic [dot] com) is no longer in use. Please delete all references to this in bookmarks and your own products' documentation as it's being used for malicious purposes. + +## Quick start + +### Install + +This package can be installed with: + +- [npm](https://www.npmjs.com/package/owl.carousel): `npm install --save owl.carousel` or `yarn add owl.carousel jquery` +- [bower](http://bower.io/search/?q=owl.carousel): `bower install --save owl.carousel` + +Or download the [latest release](https://github.com/OwlCarousel2/OwlCarousel2/releases). + +### Load + +#### Webpack + +Add jQuery via the "webpack.ProvidePlugin" to your webpack configuration: + + const webpack = require('webpack'); + + //... + plugins: [ + new webpack.ProvidePlugin({ + $: 'jquery', + jQuery: 'jquery', + 'window.jQuery': 'jquery' + }), + ], + //... + +Load the required stylesheet and JS: + +```js +import 'owl.carousel/dist/assets/owl.carousel.css'; +import 'owl.carousel'; +``` + +#### Static HTML + +Put the required stylesheet at the [top](https://developer.yahoo.com/performance/rules.html#css_top) of your markup: + +```html + +``` + +```html + +``` + +**NOTE:** If you want to use the default navigation styles, you will also need to include `owl.theme.default.css`. + + +Put the script at the [bottom](https://developer.yahoo.com/performance/rules.html#js_bottom) of your markup right after jQuery: + +```html + + +``` + +```html + + +``` + +### Usage + +Wrap your items (`div`, `a`, `img`, `span`, `li` etc.) with a container element (`div`, `ul` etc.). Only the class `owl-carousel` is mandatory to apply proper styles: + +```html + +``` +**NOTE:** The `owl-theme` class is optional, but without it, you will need to style navigation features on your own. + + +Call the [plugin](https://learn.jquery.com/plugins/) function and your carousel is ready. + +```javascript +$(document).ready(function(){ + $('.owl-carousel').owlCarousel(); +}); +``` + +## Documentation + +The documentation, included in this repo in the root directory, is built with [Assemble](http://assemble.io/) and publicly available at https://owlcarousel2.github.io/OwlCarousel2/. The documentation may also be run locally. + +## Building + +This package comes with [Grunt](http://gruntjs.com/) and [Bower](http://bower.io/). The following tasks are available: + + * `default` compiles the CSS and JS into `/dist` and builds the doc. + * `dist` compiles the CSS and JS into `/dist` only. + * `watch` watches source files and builds them automatically whenever you save. + * `test` runs [JSHint](http://www.jshint.com/) and [QUnit](http://qunitjs.com/) tests headlessly in [PhantomJS](http://phantomjs.org/). + +To define which plugins are build into the distribution just edit `/_config.json` to fit your needs. + +## Contributing + +Please read [CONTRIBUTING.md](CONTRIBUTING.md). + +## Roadmap + +Please make sure to check out our [Roadmap Discussion](https://github.com/OwlCarousel2/OwlCarousel2/issues/1756). + + +## License + +The code and the documentation are released under the [MIT License](LICENSE). diff --git a/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/ajax-loader.gif b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/ajax-loader.gif new file mode 100644 index 000000000..d3962f969 Binary files /dev/null and b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/ajax-loader.gif differ diff --git a/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.carousel.css b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.carousel.css new file mode 100644 index 000000000..40237bc65 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.carousel.css @@ -0,0 +1,186 @@ +/** + * Owl Carousel v2.3.4 + * Copyright 2013-2018 David Deutsch + * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE + */ +/* + * Owl Carousel - Core + */ +.owl-carousel { + display: none; + width: 100%; + -webkit-tap-highlight-color: transparent; + /* position relative and z-index fix webkit rendering fonts issue */ + position: relative; + z-index: 1; } + .owl-carousel .owl-stage { + position: relative; + -ms-touch-action: pan-Y; + touch-action: manipulation; + -moz-backface-visibility: hidden; + /* fix firefox animation glitch */ } + .owl-carousel .owl-stage:after { + content: "."; + display: block; + clear: both; + visibility: hidden; + line-height: 0; + height: 0; } + .owl-carousel .owl-stage-outer { + position: relative; + overflow: hidden; + /* fix for flashing background */ + -webkit-transform: translate3d(0px, 0px, 0px); } + .owl-carousel .owl-wrapper, + .owl-carousel .owl-item { + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + -ms-backface-visibility: hidden; + -webkit-transform: translate3d(0, 0, 0); + -moz-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); } + .owl-carousel .owl-item { + position: relative; + min-height: 1px; + float: left; + -webkit-backface-visibility: hidden; + -webkit-tap-highlight-color: transparent; + -webkit-touch-callout: none; } + .owl-carousel .owl-item img { + display: block; + width: 100%; } + .owl-carousel .owl-nav.disabled, + .owl-carousel .owl-dots.disabled { + display: none; } + .owl-carousel .owl-nav .owl-prev, + .owl-carousel .owl-nav .owl-next, + .owl-carousel .owl-dot { + cursor: pointer; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + .owl-carousel .owl-nav button.owl-prev, + .owl-carousel .owl-nav button.owl-next, + .owl-carousel button.owl-dot { + background: none; + color: inherit; + border: none; + padding: 0 !important; + font: inherit; } + .owl-carousel.owl-loaded { + display: block; } + .owl-carousel.owl-loading { + opacity: 0; + display: block; } + .owl-carousel.owl-hidden { + opacity: 0; } + .owl-carousel.owl-refresh .owl-item { + visibility: hidden; } + .owl-carousel.owl-drag .owl-item { + -ms-touch-action: pan-y; + touch-action: pan-y; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + .owl-carousel.owl-grab { + cursor: move; + cursor: grab; } + .owl-carousel.owl-rtl { + direction: rtl; } + .owl-carousel.owl-rtl .owl-item { + float: right; } + +/* No Js */ +.no-js .owl-carousel { + display: block; } + +/* + * Owl Carousel - Animate Plugin + */ +.owl-carousel .animated { + animation-duration: 1000ms; + animation-fill-mode: both; } + +.owl-carousel .owl-animated-in { + z-index: 0; } + +.owl-carousel .owl-animated-out { + z-index: 1; } + +.owl-carousel .fadeOut { + animation-name: fadeOut; } + +@keyframes fadeOut { + 0% { + opacity: 1; } + 100% { + opacity: 0; } } + +/* + * Owl Carousel - Auto Height Plugin + */ +.owl-height { + transition: height 500ms ease-in-out; } + +/* + * Owl Carousel - Lazy Load Plugin + */ +.owl-carousel .owl-item { + /** + This is introduced due to a bug in IE11 where lazy loading combined with autoheight plugin causes a wrong + calculation of the height of the owl-item that breaks page layouts + */ } + .owl-carousel .owl-item .owl-lazy { + opacity: 0; + transition: opacity 400ms ease; } + .owl-carousel .owl-item .owl-lazy[src^=""], .owl-carousel .owl-item .owl-lazy:not([src]) { + max-height: 0; } + .owl-carousel .owl-item img.owl-lazy { + transform-style: preserve-3d; } + +/* + * Owl Carousel - Video Plugin + */ +.owl-carousel .owl-video-wrapper { + position: relative; + height: 100%; + background: #000; } + +.owl-carousel .owl-video-play-icon { + position: absolute; + height: 80px; + width: 80px; + left: 50%; + top: 50%; + margin-left: -40px; + margin-top: -40px; + background: url("owl.video.play.png") no-repeat; + cursor: pointer; + z-index: 1; + -webkit-backface-visibility: hidden; + transition: transform 100ms ease; } + +.owl-carousel .owl-video-play-icon:hover { + -ms-transform: scale(1.3, 1.3); + transform: scale(1.3, 1.3); } + +.owl-carousel .owl-video-playing .owl-video-tn, +.owl-carousel .owl-video-playing .owl-video-play-icon { + display: none; } + +.owl-carousel .owl-video-tn { + opacity: 0; + height: 100%; + background-position: center center; + background-repeat: no-repeat; + background-size: contain; + transition: opacity 400ms ease; } + +.owl-carousel .owl-video-frame { + position: relative; + z-index: 1; + height: 100%; + width: 100%; } diff --git a/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.theme.default.css b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.theme.default.css new file mode 100644 index 000000000..e2020fb10 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.theme.default.css @@ -0,0 +1,50 @@ +/** + * Owl Carousel v2.3.4 + * Copyright 2013-2018 David Deutsch + * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE + */ +/* + * Default theme - Owl Carousel CSS File + */ +.owl-theme .owl-nav { + margin-top: 10px; + text-align: center; + -webkit-tap-highlight-color: transparent; } + .owl-theme .owl-nav [class*='owl-'] { + color: #FFF; + font-size: 14px; + margin: 5px; + padding: 4px 7px; + background: #D6D6D6; + display: inline-block; + cursor: pointer; + border-radius: 3px; } + .owl-theme .owl-nav [class*='owl-']:hover { + background: #869791; + color: #FFF; + text-decoration: none; } + .owl-theme .owl-nav .disabled { + opacity: 0.5; + cursor: default; } + +.owl-theme .owl-nav.disabled + .owl-dots { + margin-top: 10px; } + +.owl-theme .owl-dots { + text-align: center; + -webkit-tap-highlight-color: transparent; } + .owl-theme .owl-dots .owl-dot { + display: inline-block; + zoom: 1; + *display: inline; } + .owl-theme .owl-dots .owl-dot span { + width: 10px; + height: 10px; + margin: 5px 7px; + background: #D6D6D6; + display: block; + -webkit-backface-visibility: visible; + transition: opacity 200ms ease; + border-radius: 30px; } + .owl-theme .owl-dots .owl-dot.active span, .owl-theme .owl-dots .owl-dot:hover span { + background: #869791; } diff --git a/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.theme.green.css b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.theme.green.css new file mode 100644 index 000000000..5235fbe3b --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.theme.green.css @@ -0,0 +1,50 @@ +/** + * Owl Carousel v2.3.4 + * Copyright 2013-2018 David Deutsch + * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE + */ +/* + * Green theme - Owl Carousel CSS File + */ +.owl-theme .owl-nav { + margin-top: 10px; + text-align: center; + -webkit-tap-highlight-color: transparent; } + .owl-theme .owl-nav [class*='owl-'] { + color: #FFF; + font-size: 14px; + margin: 5px; + padding: 4px 7px; + background: #D6D6D6; + display: inline-block; + cursor: pointer; + border-radius: 3px; } + .owl-theme .owl-nav [class*='owl-']:hover { + background: #4DC7A0; + color: #FFF; + text-decoration: none; } + .owl-theme .owl-nav .disabled { + opacity: 0.5; + cursor: default; } + +.owl-theme .owl-nav.disabled + .owl-dots { + margin-top: 10px; } + +.owl-theme .owl-dots { + text-align: center; + -webkit-tap-highlight-color: transparent; } + .owl-theme .owl-dots .owl-dot { + display: inline-block; + zoom: 1; + *display: inline; } + .owl-theme .owl-dots .owl-dot span { + width: 10px; + height: 10px; + margin: 5px 7px; + background: #D6D6D6; + display: block; + -webkit-backface-visibility: visible; + transition: opacity 200ms ease; + border-radius: 30px; } + .owl-theme .owl-dots .owl-dot.active span, .owl-theme .owl-dots .owl-dot:hover span { + background: #4DC7A0; } diff --git a/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.video.play.png b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.video.play.png new file mode 100644 index 000000000..5d0218d46 Binary files /dev/null and b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/assets/owl.video.play.png differ diff --git a/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/owl.carousel.js b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/owl.carousel.js new file mode 100644 index 000000000..66c67ebe0 --- /dev/null +++ b/odex25_donation/theme_prime/static/lib/OwlCarousel2-2.3.4/owl.carousel.js @@ -0,0 +1,3448 @@ +/** + * Owl Carousel v2.3.4 + * Copyright 2013-2018 David Deutsch + * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE + */ +/** + * Owl carousel + * @version 2.3.4 + * @author Bartosz Wojciechowski + * @author David Deutsch + * @license The MIT License (MIT) + * @todo Lazy Load Icon + * @todo prevent animationend bubling + * @todo itemsScaleUp + * @todo Test Zepto + * @todo stagePadding calculate wrong active classes + */ +;(function($, window, document, undefined) { + + /** + * Creates a carousel. + * @class The Owl Carousel. + * @public + * @param {HTMLElement|jQuery} element - The element to create the carousel for. + * @param {Object} [options] - The options + */ + function Owl(element, options) { + + /** + * Current settings for the carousel. + * @public + */ + this.settings = null; + + /** + * Current options set by the caller including defaults. + * @public + */ + this.options = $.extend({}, Owl.Defaults, options); + + /** + * Plugin element. + * @public + */ + this.$element = $(element); + + /** + * Proxied event handlers. + * @protected + */ + this._handlers = {}; + + /** + * References to the running plugins of this carousel. + * @protected + */ + this._plugins = {}; + + /** + * Currently suppressed events to prevent them from being retriggered. + * @protected + */ + this._supress = {}; + + /** + * Absolute current position. + * @protected + */ + this._current = null; + + /** + * Animation speed in milliseconds. + * @protected + */ + this._speed = null; + + /** + * Coordinates of all items in pixel. + * @todo The name of this member is missleading. + * @protected + */ + this._coordinates = []; + + /** + * Current breakpoint. + * @todo Real media queries would be nice. + * @protected + */ + this._breakpoint = null; + + /** + * Current width of the plugin element. + */ + this._width = null; + + /** + * All real items. + * @protected + */ + this._items = []; + + /** + * All cloned items. + * @protected + */ + this._clones = []; + + /** + * Merge values of all items. + * @todo Maybe this could be part of a plugin. + * @protected + */ + this._mergers = []; + + /** + * Widths of all items. + */ + this._widths = []; + + /** + * Invalidated parts within the update process. + * @protected + */ + this._invalidated = {}; + + /** + * Ordered list of workers for the update process. + * @protected + */ + this._pipe = []; + + /** + * Current state information for the drag operation. + * @todo #261 + * @protected + */ + this._drag = { + time: null, + target: null, + pointer: null, + stage: { + start: null, + current: null + }, + direction: null + }; + + /** + * Current state information and their tags. + * @type {Object} + * @protected + */ + this._states = { + current: {}, + tags: { + 'initializing': [ 'busy' ], + 'animating': [ 'busy' ], + 'dragging': [ 'interacting' ] + } + }; + + $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { + this._handlers[handler] = $.proxy(this[handler], this); + }, this)); + + $.each(Owl.Plugins, $.proxy(function(key, plugin) { + this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] + = new plugin(this); + }, this)); + + $.each(Owl.Workers, $.proxy(function(priority, worker) { + this._pipe.push({ + 'filter': worker.filter, + 'run': $.proxy(worker.run, this) + }); + }, this)); + + this.setup(); + this.initialize(); + } + + /** + * Default options for the carousel. + * @public + */ + Owl.Defaults = { + items: 3, + loop: false, + center: false, + rewind: false, + checkVisibility: true, + + mouseDrag: true, + touchDrag: true, + pullDrag: true, + freeDrag: false, + + margin: 0, + stagePadding: 0, + + merge: false, + mergeFit: true, + autoWidth: false, + + startPosition: 0, + rtl: false, + + smartSpeed: 250, + fluidSpeed: false, + dragEndSpeed: false, + + responsive: {}, + responsiveRefreshRate: 200, + responsiveBaseElement: window, + + fallbackEasing: 'swing', + slideTransition: '', + + info: false, + + nestedItemSelector: false, + itemElement: 'div', + stageElement: 'div', + + refreshClass: 'owl-refresh', + loadedClass: 'owl-loaded', + loadingClass: 'owl-loading', + rtlClass: 'owl-rtl', + responsiveClass: 'owl-responsive', + dragClass: 'owl-drag', + itemClass: 'owl-item', + stageClass: 'owl-stage', + stageOuterClass: 'owl-stage-outer', + grabClass: 'owl-grab' + }; + + /** + * Enumeration for width. + * @public + * @readonly + * @enum {String} + */ + Owl.Width = { + Default: 'default', + Inner: 'inner', + Outer: 'outer' + }; + + /** + * Enumeration for types. + * @public + * @readonly + * @enum {String} + */ + Owl.Type = { + Event: 'event', + State: 'state' + }; + + /** + * Contains all registered plugins. + * @public + */ + Owl.Plugins = {}; + + /** + * List of workers involved in the update process. + */ + Owl.Workers = [ { + filter: [ 'width', 'settings' ], + run: function() { + this._width = this.$element.width(); + } + }, { + filter: [ 'width', 'items', 'settings' ], + run: function(cache) { + cache.current = this._items && this._items[this.relative(this._current)]; + } + }, { + filter: [ 'items', 'settings' ], + run: function() { + this.$stage.children('.cloned').remove(); + } + }, { + filter: [ 'width', 'items', 'settings' ], + run: function(cache) { + var margin = this.settings.margin || '', + grid = !this.settings.autoWidth, + rtl = this.settings.rtl, + css = { + 'width': 'auto', + 'margin-left': rtl ? margin : '', + 'margin-right': rtl ? '' : margin + }; + + !grid && this.$stage.children().css(css); + + cache.css = css; + } + }, { + filter: [ 'width', 'items', 'settings' ], + run: function(cache) { + var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin, + merge = null, + iterator = this._items.length, + grid = !this.settings.autoWidth, + widths = []; + + cache.items = { + merge: false, + width: width + }; + + while (iterator--) { + merge = this._mergers[iterator]; + merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; + + cache.items.merge = merge > 1 || cache.items.merge; + + widths[iterator] = !grid ? this._items[iterator].width() : width * merge; + } + + this._widths = widths; + } + }, { + filter: [ 'items', 'settings' ], + run: function() { + var clones = [], + items = this._items, + settings = this.settings, + // TODO: Should be computed from number of min width items in stage + view = Math.max(settings.items * 2, 4), + size = Math.ceil(items.length / 2) * 2, + repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, + append = '', + prepend = ''; + + repeat /= 2; + + while (repeat > 0) { + // Switch to only using appended clones + clones.push(this.normalize(clones.length / 2, true)); + append = append + items[clones[clones.length - 1]][0].outerHTML; + clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); + prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; + repeat -= 1; + } + + this._clones = clones; + + $(append).addClass('cloned').appendTo(this.$stage); + $(prepend).addClass('cloned').prependTo(this.$stage); + } + }, { + filter: [ 'width', 'items', 'settings' ], + run: function() { + var rtl = this.settings.rtl ? 1 : -1, + size = this._clones.length + this._items.length, + iterator = -1, + previous = 0, + current = 0, + coordinates = []; + + while (++iterator < size) { + previous = coordinates[iterator - 1] || 0; + current = this._widths[this.relative(iterator)] + this.settings.margin; + coordinates.push(previous + current * rtl); + } + + this._coordinates = coordinates; + } + }, { + filter: [ 'width', 'items', 'settings' ], + run: function() { + var padding = this.settings.stagePadding, + coordinates = this._coordinates, + css = { + 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, + 'padding-left': padding || '', + 'padding-right': padding || '' + }; + + this.$stage.css(css); + } + }, { + filter: [ 'width', 'items', 'settings' ], + run: function(cache) { + var iterator = this._coordinates.length, + grid = !this.settings.autoWidth, + items = this.$stage.children(); + + if (grid && cache.items.merge) { + while (iterator--) { + cache.css.width = this._widths[this.relative(iterator)]; + items.eq(iterator).css(cache.css); + } + } else if (grid) { + cache.css.width = cache.items.width; + items.css(cache.css); + } + } + }, { + filter: [ 'items' ], + run: function() { + this._coordinates.length < 1 && this.$stage.removeAttr('style'); + } + }, { + filter: [ 'width', 'items', 'settings' ], + run: function(cache) { + cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; + cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); + this.reset(cache.current); + } + }, { + filter: [ 'position' ], + run: function() { + this.animate(this.coordinates(this._current)); + } + }, { + filter: [ 'width', 'position', 'items', 'settings' ], + run: function() { + var rtl = this.settings.rtl ? 1 : -1, + padding = this.settings.stagePadding * 2, + begin = this.coordinates(this.current()) + padding, + end = begin + this.width() * rtl, + inner, outer, matches = [], i, n; + + for (i = 0, n = this._coordinates.length; i < n; i++) { + inner = this._coordinates[i - 1] || 0; + outer = Math.abs(this._coordinates[i]) + padding * rtl; + + if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) + || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { + matches.push(i); + } + } + + this.$stage.children('.active').removeClass('active'); + this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); + + this.$stage.children('.center').removeClass('center'); + if (this.settings.center) { + this.$stage.children().eq(this.current()).addClass('center'); + } + } + } ]; + + /** + * Create the stage DOM element + */ + Owl.prototype.initializeStage = function() { + this.$stage = this.$element.find('.' + this.settings.stageClass); + + // if the stage is already in the DOM, grab it and skip stage initialization + if (this.$stage.length) { + return; + } + + this.$element.addClass(this.options.loadingClass); + + // create stage + this.$stage = $('<' + this.settings.stageElement + '>', { + "class": this.settings.stageClass + }).wrap( $( '
', { + "class": this.settings.stageOuterClass + })); + + // append stage + this.$element.append(this.$stage.parent()); + }; + + /** + * Create item DOM elements + */ + Owl.prototype.initializeItems = function() { + var $items = this.$element.find('.owl-item'); + + // if the items are already in the DOM, grab them and skip item initialization + if ($items.length) { + this._items = $items.get().map(function(item) { + return $(item); + }); + + this._mergers = this._items.map(function() { + return 1; + }); + + this.refresh(); + + return; + } + + // append content + this.replace(this.$element.children().not(this.$stage.parent())); + + // check visibility + if (this.isVisible()) { + // update view + this.refresh(); + } else { + // invalidate width + this.invalidate('width'); + } + + this.$element + .removeClass(this.options.loadingClass) + .addClass(this.options.loadedClass); + }; + + /** + * Initializes the carousel. + * @protected + */ + Owl.prototype.initialize = function() { + this.enter('initializing'); + this.trigger('initialize'); + + this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); + + if (this.settings.autoWidth && !this.is('pre-loading')) { + var imgs, nestedSelector, width; + imgs = this.$element.find('img'); + nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; + width = this.$element.children(nestedSelector).width(); + + if (imgs.length && width <= 0) { + this.preloadAutoWidthImages(imgs); + } + } + + this.initializeStage(); + this.initializeItems(); + + // register event handlers + this.registerEventHandlers(); + + this.leave('initializing'); + this.trigger('initialized'); + }; + + /** + * @returns {Boolean} visibility of $element + * if you know the carousel will always be visible you can set `checkVisibility` to `false` to + * prevent the expensive browser layout forced reflow the $element.is(':visible') does + */ + Owl.prototype.isVisible = function() { + return this.settings.checkVisibility + ? this.$element.is(':visible') + : true; + }; + + /** + * Setups the current settings. + * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? + * @todo Support for media queries by using `matchMedia` would be nice. + * @public + */ + Owl.prototype.setup = function() { + var viewport = this.viewport(), + overwrites = this.options.responsive, + match = -1, + settings = null; + + if (!overwrites) { + settings = $.extend({}, this.options); + } else { + $.each(overwrites, function(breakpoint) { + if (breakpoint <= viewport && breakpoint > match) { + match = Number(breakpoint); + } + }); + + settings = $.extend({}, this.options, overwrites[match]); + if (typeof settings.stagePadding === 'function') { + settings.stagePadding = settings.stagePadding(); + } + delete settings.responsive; + + // responsive class + if (settings.responsiveClass) { + this.$element.attr('class', + this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) + ); + } + } + + this.trigger('change', { property: { name: 'settings', value: settings } }); + this._breakpoint = match; + this.settings = settings; + this.invalidate('settings'); + this.trigger('changed', { property: { name: 'settings', value: this.settings } }); + }; + + /** + * Updates option logic if necessery. + * @protected + */ + Owl.prototype.optionsLogic = function() { + if (this.settings.autoWidth) { + this.settings.stagePadding = false; + this.settings.merge = false; + } + }; + + /** + * Prepares an item before add. + * @todo Rename event parameter `content` to `item`. + * @protected + * @returns {jQuery|HTMLElement} - The item container. + */ + Owl.prototype.prepare = function(item) { + var event = this.trigger('prepare', { content: item }); + + if (!event.data) { + event.data = $('<' + this.settings.itemElement + '/>') + .addClass(this.options.itemClass).append(item) + } + + this.trigger('prepared', { content: event.data }); + + return event.data; + }; + + /** + * Updates the view. + * @public + */ + Owl.prototype.update = function() { + var i = 0, + n = this._pipe.length, + filter = $.proxy(function(p) { return this[p] }, this._invalidated), + cache = {}; + + while (i < n) { + if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { + this._pipe[i].run(cache); + } + i++; + } + + this._invalidated = {}; + + !this.is('valid') && this.enter('valid'); + }; + + /** + * Gets the width of the view. + * @public + * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. + * @returns {Number} - The width of the view in pixel. + */ + Owl.prototype.width = function(dimension) { + dimension = dimension || Owl.Width.Default; + switch (dimension) { + case Owl.Width.Inner: + case Owl.Width.Outer: + return this._width; + default: + return this._width - this.settings.stagePadding * 2 + this.settings.margin; + } + }; + + /** + * Refreshes the carousel primarily for adaptive purposes. + * @public + */ + Owl.prototype.refresh = function() { + this.enter('refreshing'); + this.trigger('refresh'); + + this.setup(); + + this.optionsLogic(); + + this.$element.addClass(this.options.refreshClass); + + this.update(); + + this.$element.removeClass(this.options.refreshClass); + + this.leave('refreshing'); + this.trigger('refreshed'); + }; + + /** + * Checks window `resize` event. + * @protected + */ + Owl.prototype.onThrottledResize = function() { + window.clearTimeout(this.resizeTimer); + this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); + }; + + /** + * Checks window `resize` event. + * @protected + */ + Owl.prototype.onResize = function() { + if (!this._items.length) { + return false; + } + + if (this._width === this.$element.width()) { + return false; + } + + if (!this.isVisible()) { + return false; + } + + this.enter('resizing'); + + if (this.trigger('resize').isDefaultPrevented()) { + this.leave('resizing'); + return false; + } + + this.invalidate('width'); + + this.refresh(); + + this.leave('resizing'); + this.trigger('resized'); + }; + + /** + * Registers event handlers. + * @todo Check `msPointerEnabled` + * @todo #261 + * @protected + */ + Owl.prototype.registerEventHandlers = function() { + if ($.support.transition) { + this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); + } + + if (this.settings.responsive !== false) { + this.on(window, 'resize', this._handlers.onThrottledResize); + } + + if (this.settings.mouseDrag) { + this.$element.addClass(this.options.dragClass); + this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); + this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); + } + + if (this.settings.touchDrag){ + this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); + this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); + } + }; + + /** + * Handles `touchstart` and `mousedown` events. + * @todo Horizontal swipe threshold as option + * @todo #261 + * @protected + * @param {Event} event - The event arguments. + */ + Owl.prototype.onDragStart = function(event) { + var stage = null; + + if (event.which === 3) { + return; + } + + if ($.support.transform) { + stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); + stage = { + x: stage[stage.length === 16 ? 12 : 4], + y: stage[stage.length === 16 ? 13 : 5] + }; + } else { + stage = this.$stage.position(); + stage = { + x: this.settings.rtl ? + stage.left + this.$stage.width() - this.width() + this.settings.margin : + stage.left, + y: stage.top + }; + } + + if (this.is('animating')) { + $.support.transform ? this.animate(stage.x) : this.$stage.stop() + this.invalidate('position'); + } + + this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); + + this.speed(0); + + this._drag.time = new Date().getTime(); + this._drag.target = $(event.target); + this._drag.stage.start = stage; + this._drag.stage.current = stage; + this._drag.pointer = this.pointer(event); + + $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); + + $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { + var delta = this.difference(this._drag.pointer, this.pointer(event)); + + $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); + + if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { + return; + } + + event.preventDefault(); + + this.enter('dragging'); + this.trigger('drag'); + }, this)); + }; + + /** + * Handles the `touchmove` and `mousemove` events. + * @todo #261 + * @protected + * @param {Event} event - The event arguments. + */ + Owl.prototype.onDragMove = function(event) { + var minimum = null, + maximum = null, + pull = null, + delta = this.difference(this._drag.pointer, this.pointer(event)), + stage = this.difference(this._drag.stage.start, delta); + + if (!this.is('dragging')) { + return; + } + + event.preventDefault(); + + if (this.settings.loop) { + minimum = this.coordinates(this.minimum()); + maximum = this.coordinates(this.maximum() + 1) - minimum; + stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; + } else { + minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); + maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); + pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; + stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); + } + + this._drag.stage.current = stage; + + this.animate(stage.x); + }; + + /** + * Handles the `touchend` and `mouseup` events. + * @todo #261 + * @todo Threshold for click event + * @protected + * @param {Event} event - The event arguments. + */ + Owl.prototype.onDragEnd = function(event) { + var delta = this.difference(this._drag.pointer, this.pointer(event)), + stage = this._drag.stage.current, + direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; + + $(document).off('.owl.core'); + + this.$element.removeClass(this.options.grabClass); + + if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { + this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); + this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); + this.invalidate('position'); + this.update(); + + this._drag.direction = direction; + + if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { + this._drag.target.one('click.owl.core', function() { return false; }); + } + } + + if (!this.is('dragging')) { + return; + } + + this.leave('dragging'); + this.trigger('dragged'); + }; + + /** + * Gets absolute position of the closest item for a coordinate. + * @todo Setting `freeDrag` makes `closest` not reusable. See #165. + * @protected + * @param {Number} coordinate - The coordinate in pixel. + * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. + * @return {Number} - The absolute position of the closest item. + */ + Owl.prototype.closest = function(coordinate, direction) { + var position = -1, + pull = 30, + width = this.width(), + coordinates = this.coordinates(); + + if (!this.settings.freeDrag) { + // check closest item + $.each(coordinates, $.proxy(function(index, value) { + // on a left pull, check on current index + if (direction === 'left' && coordinate > value - pull && coordinate < value + pull) { + position = index; + // on a right pull, check on previous index + // to do so, subtract width from value and set position = index + 1 + } else if (direction === 'right' && coordinate > value - width - pull && coordinate < value - width + pull) { + position = index + 1; + } else if (this.op(coordinate, '<', value) + && this.op(coordinate, '>', coordinates[index + 1] !== undefined ? coordinates[index + 1] : value - width)) { + position = direction === 'left' ? index + 1 : index; + } + return position === -1; + }, this)); + } + + if (!this.settings.loop) { + // non loop boundries + if (this.op(coordinate, '>', coordinates[this.minimum()])) { + position = coordinate = this.minimum(); + } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { + position = coordinate = this.maximum(); + } + } + + return position; + }; + + /** + * Animates the stage. + * @todo #270 + * @public + * @param {Number} coordinate - The coordinate in pixels. + */ + Owl.prototype.animate = function(coordinate) { + var animate = this.speed() > 0; + + this.is('animating') && this.onTransitionEnd(); + + if (animate) { + this.enter('animating'); + this.trigger('translate'); + } + + if ($.support.transform3d && $.support.transition) { + this.$stage.css({ + transform: 'translate3d(' + coordinate + 'px,0px,0px)', + transition: (this.speed() / 1000) + 's' + ( + this.settings.slideTransition ? ' ' + this.settings.slideTransition : '' + ) + }); + } else if (animate) { + this.$stage.animate({ + left: coordinate + 'px' + }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); + } else { + this.$stage.css({ + left: coordinate + 'px' + }); + } + }; + + /** + * Checks whether the carousel is in a specific state or not. + * @param {String} state - The state to check. + * @returns {Boolean} - The flag which indicates if the carousel is busy. + */ + Owl.prototype.is = function(state) { + return this._states.current[state] && this._states.current[state] > 0; + }; + + /** + * Sets the absolute position of the current item. + * @public + * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. + * @returns {Number} - The absolute position of the current item. + */ + Owl.prototype.current = function(position) { + if (position === undefined) { + return this._current; + } + + if (this._items.length === 0) { + return undefined; + } + + position = this.normalize(position); + + if (this._current !== position) { + var event = this.trigger('change', { property: { name: 'position', value: position } }); + + if (event.data !== undefined) { + position = this.normalize(event.data); + } + + this._current = position; + + this.invalidate('position'); + + this.trigger('changed', { property: { name: 'position', value: this._current } }); + } + + return this._current; + }; + + /** + * Invalidates the given part of the update routine. + * @param {String} [part] - The part to invalidate. + * @returns {Array.} - The invalidated parts. + */ + Owl.prototype.invalidate = function(part) { + if ($.type(part) === 'string') { + this._invalidated[part] = true; + this.is('valid') && this.leave('valid'); + } + return $.map(this._invalidated, function(v, i) { return i }); + }; + + /** + * Resets the absolute position of the current item. + * @public + * @param {Number} position - The absolute position of the new item. + */ + Owl.prototype.reset = function(position) { + position = this.normalize(position); + + if (position === undefined) { + return; + } + + this._speed = 0; + this._current = position; + + this.suppress([ 'translate', 'translated' ]); + + this.animate(this.coordinates(position)); + + this.release([ 'translate', 'translated' ]); + }; + + /** + * Normalizes an absolute or a relative position of an item. + * @public + * @param {Number} position - The absolute or relative position to normalize. + * @param {Boolean} [relative=false] - Whether the given position is relative or not. + * @returns {Number} - The normalized position. + */ + Owl.prototype.normalize = function(position, relative) { + var n = this._items.length, + m = relative ? 0 : this._clones.length; + + if (!this.isNumeric(position) || n < 1) { + position = undefined; + } else if (position < 0 || position >= n + m) { + position = ((position - m / 2) % n + n) % n + m / 2; + } + + return position; + }; + + /** + * Converts an absolute position of an item into a relative one. + * @public + * @param {Number} position - The absolute position to convert. + * @returns {Number} - The converted position. + */ + Owl.prototype.relative = function(position) { + position -= this._clones.length / 2; + return this.normalize(position, true); + }; + + /** + * Gets the maximum position for the current item. + * @public + * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. + * @returns {Number} + */ + Owl.prototype.maximum = function(relative) { + var settings = this.settings, + maximum = this._coordinates.length, + iterator, + reciprocalItemsWidth, + elementWidth; + + if (settings.loop) { + maximum = this._clones.length / 2 + this._items.length - 1; + } else if (settings.autoWidth || settings.merge) { + iterator = this._items.length; + if (iterator) { + reciprocalItemsWidth = this._items[--iterator].width(); + elementWidth = this.$element.width(); + while (iterator--) { + reciprocalItemsWidth += this._items[iterator].width() + this.settings.margin; + if (reciprocalItemsWidth > elementWidth) { + break; + } + } + } + maximum = iterator + 1; + } else if (settings.center) { + maximum = this._items.length - 1; + } else { + maximum = this._items.length - settings.items; + } + + if (relative) { + maximum -= this._clones.length / 2; + } + + return Math.max(maximum, 0); + }; + + /** + * Gets the minimum position for the current item. + * @public + * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. + * @returns {Number} + */ + Owl.prototype.minimum = function(relative) { + return relative ? 0 : this._clones.length / 2; + }; + + /** + * Gets an item at the specified relative position. + * @public + * @param {Number} [position] - The relative position of the item. + * @return {jQuery|Array.} - The item at the given position or all items if no position was given. + */ + Owl.prototype.items = function(position) { + if (position === undefined) { + return this._items.slice(); + } + + position = this.normalize(position, true); + return this._items[position]; + }; + + /** + * Gets an item at the specified relative position. + * @public + * @param {Number} [position] - The relative position of the item. + * @return {jQuery|Array.} - The item at the given position or all items if no position was given. + */ + Owl.prototype.mergers = function(position) { + if (position === undefined) { + return this._mergers.slice(); + } + + position = this.normalize(position, true); + return this._mergers[position]; + }; + + /** + * Gets the absolute positions of clones for an item. + * @public + * @param {Number} [position] - The relative position of the item. + * @returns {Array.} - The absolute positions of clones for the item or all if no position was given. + */ + Owl.prototype.clones = function(position) { + var odd = this._clones.length / 2, + even = odd + this._items.length, + map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; + + if (position === undefined) { + return $.map(this._clones, function(v, i) { return map(i) }); + } + + return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); + }; + + /** + * Sets the current animation speed. + * @public + * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. + * @returns {Number} - The current animation speed in milliseconds. + */ + Owl.prototype.speed = function(speed) { + if (speed !== undefined) { + this._speed = speed; + } + + return this._speed; + }; + + /** + * Gets the coordinate of an item. + * @todo The name of this method is missleanding. + * @public + * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. + * @returns {Number|Array.} - The coordinate of the item in pixel or all coordinates. + */ + Owl.prototype.coordinates = function(position) { + var multiplier = 1, + newPosition = position - 1, + coordinate; + + if (position === undefined) { + return $.map(this._coordinates, $.proxy(function(coordinate, index) { + return this.coordinates(index); + }, this)); + } + + if (this.settings.center) { + if (this.settings.rtl) { + multiplier = -1; + newPosition = position + 1; + } + + coordinate = this._coordinates[position]; + coordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier; + } else { + coordinate = this._coordinates[newPosition] || 0; + } + + coordinate = Math.ceil(coordinate); + + return coordinate; + }; + + /** + * Calculates the speed for a translation. + * @protected + * @param {Number} from - The absolute position of the start item. + * @param {Number} to - The absolute position of the target item. + * @param {Number} [factor=undefined] - The time factor in milliseconds. + * @returns {Number} - The time in milliseconds for the translation. + */ + Owl.prototype.duration = function(from, to, factor) { + if (factor === 0) { + return 0; + } + + return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); + }; + + /** + * Slides to the specified item. + * @public + * @param {Number} position - The position of the item. + * @param {Number} [speed] - The time in milliseconds for the transition. + */ + Owl.prototype.to = function(position, speed) { + var current = this.current(), + revert = null, + distance = position - this.relative(current), + direction = (distance > 0) - (distance < 0), + items = this._items.length, + minimum = this.minimum(), + maximum = this.maximum(); + + if (this.settings.loop) { + if (!this.settings.rewind && Math.abs(distance) > items / 2) { + distance += direction * -1 * items; + } + + position = current + distance; + revert = ((position - minimum) % items + items) % items + minimum; + + if (revert !== position && revert - distance <= maximum && revert - distance > 0) { + current = revert - distance; + position = revert; + this.reset(current); + } + } else if (this.settings.rewind) { + maximum += 1; + position = (position % maximum + maximum) % maximum; + } else { + position = Math.max(minimum, Math.min(maximum, position)); + } + + this.speed(this.duration(current, position, speed)); + this.current(position); + + if (this.isVisible()) { + this.update(); + } + }; + + /** + * Slides to the next item. + * @public + * @param {Number} [speed] - The time in milliseconds for the transition. + */ + Owl.prototype.next = function(speed) { + speed = speed || false; + this.to(this.relative(this.current()) + 1, speed); + }; + + /** + * Slides to the previous item. + * @public + * @param {Number} [speed] - The time in milliseconds for the transition. + */ + Owl.prototype.prev = function(speed) { + speed = speed || false; + this.to(this.relative(this.current()) - 1, speed); + }; + + /** + * Handles the end of an animation. + * @protected + * @param {Event} event - The event arguments. + */ + Owl.prototype.onTransitionEnd = function(event) { + + // if css2 animation then event object is undefined + if (event !== undefined) { + event.stopPropagation(); + + // Catch only owl-stage transitionEnd event + if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { + return false; + } + } + + this.leave('animating'); + this.trigger('translated'); + }; + + /** + * Gets viewport width. + * @protected + * @return {Number} - The width in pixel. + */ + Owl.prototype.viewport = function() { + var width; + if (this.options.responsiveBaseElement !== window) { + width = $(this.options.responsiveBaseElement).width(); + } else if (window.innerWidth) { + width = window.innerWidth; + } else if (document.documentElement && document.documentElement.clientWidth) { + width = document.documentElement.clientWidth; + } else { + console.warn('Can not detect viewport width.'); + } + return width; + }; + + /** + * Replaces the current content. + * @public + * @param {HTMLElement|jQuery|String} content - The new content. + */ + Owl.prototype.replace = function(content) { + this.$stage.empty(); + this._items = []; + + if (content) { + content = (content instanceof jQuery) ? content : $(content); + } + + if (this.settings.nestedItemSelector) { + content = content.find('.' + this.settings.nestedItemSelector); + } + + content.filter(function() { + return this.nodeType === 1; + }).each($.proxy(function(index, item) { + item = this.prepare(item); + this.$stage.append(item); + this._items.push(item); + this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); + }, this)); + + this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); + + this.invalidate('items'); + }; + + /** + * Adds an item. + * @todo Use `item` instead of `content` for the event arguments. + * @public + * @param {HTMLElement|jQuery|String} content - The item content to add. + * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. + */ + Owl.prototype.add = function(content, position) { + var current = this.relative(this._current); + + position = position === undefined ? this._items.length : this.normalize(position, true); + content = content instanceof jQuery ? content : $(content); + + this.trigger('add', { content: content, position: position }); + + content = this.prepare(content); + + if (this._items.length === 0 || position === this._items.length) { + this._items.length === 0 && this.$stage.append(content); + this._items.length !== 0 && this._items[position - 1].after(content); + this._items.push(content); + this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); + } else { + this._items[position].before(content); + this._items.splice(position, 0, content); + this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); + } + + this._items[current] && this.reset(this._items[current].index()); + + this.invalidate('items'); + + this.trigger('added', { content: content, position: position }); + }; + + /** + * Removes an item by its position. + * @todo Use `item` instead of `content` for the event arguments. + * @public + * @param {Number} position - The relative position of the item to remove. + */ + Owl.prototype.remove = function(position) { + position = this.normalize(position, true); + + if (position === undefined) { + return; + } + + this.trigger('remove', { content: this._items[position], position: position }); + + this._items[position].remove(); + this._items.splice(position, 1); + this._mergers.splice(position, 1); + + this.invalidate('items'); + + this.trigger('removed', { content: null, position: position }); + }; + + /** + * Preloads images with auto width. + * @todo Replace by a more generic approach + * @protected + */ + Owl.prototype.preloadAutoWidthImages = function(images) { + images.each($.proxy(function(i, element) { + this.enter('pre-loading'); + element = $(element); + $(new Image()).one('load', $.proxy(function(e) { + element.attr('src', e.target.src); + element.css('opacity', 1); + this.leave('pre-loading'); + !this.is('pre-loading') && !this.is('initializing') && this.refresh(); + }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); + }, this)); + }; + + /** + * Destroys the carousel. + * @public + */ + Owl.prototype.destroy = function() { + + this.$element.off('.owl.core'); + this.$stage.off('.owl.core'); + $(document).off('.owl.core'); + + if (this.settings.responsive !== false) { + window.clearTimeout(this.resizeTimer); + this.off(window, 'resize', this._handlers.onThrottledResize); + } + + for (var i in this._plugins) { + this._plugins[i].destroy(); + } + + this.$stage.children('.cloned').remove(); + + this.$stage.unwrap(); + this.$stage.children().contents().unwrap(); + this.$stage.children().unwrap(); + this.$stage.remove(); + this.$element + .removeClass(this.options.refreshClass) + .removeClass(this.options.loadingClass) + .removeClass(this.options.loadedClass) + .removeClass(this.options.rtlClass) + .removeClass(this.options.dragClass) + .removeClass(this.options.grabClass) + .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) + .removeData('owl.carousel'); + }; + + /** + * Operators to calculate right-to-left and left-to-right. + * @protected + * @param {Number} [a] - The left side operand. + * @param {String} [o] - The operator. + * @param {Number} [b] - The right side operand. + */ + Owl.prototype.op = function(a, o, b) { + var rtl = this.settings.rtl; + switch (o) { + case '<': + return rtl ? a > b : a < b; + case '>': + return rtl ? a < b : a > b; + case '>=': + return rtl ? a <= b : a >= b; + case '<=': + return rtl ? a >= b : a <= b; + default: + break; + } + }; + + /** + * Attaches to an internal event. + * @protected + * @param {HTMLElement} element - The event source. + * @param {String} event - The event name. + * @param {Function} listener - The event handler to attach. + * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. + */ + Owl.prototype.on = function(element, event, listener, capture) { + if (element.addEventListener) { + element.addEventListener(event, listener, capture); + } else if (element.attachEvent) { + element.attachEvent('on' + event, listener); + } + }; + + /** + * Detaches from an internal event. + * @protected + * @param {HTMLElement} element - The event source. + * @param {String} event - The event name. + * @param {Function} listener - The attached event handler to detach. + * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. + */ + Owl.prototype.off = function(element, event, listener, capture) { + if (element.removeEventListener) { + element.removeEventListener(event, listener, capture); + } else if (element.detachEvent) { + element.detachEvent('on' + event, listener); + } + }; + + /** + * Triggers a public event. + * @todo Remove `status`, `relatedTarget` should be used instead. + * @protected + * @param {String} name - The event name. + * @param {*} [data=null] - The event data. + * @param {String} [namespace=carousel] - The event namespace. + * @param {String} [state] - The state which is associated with the event. + * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. + * @returns {Event} - The event arguments. + */ + Owl.prototype.trigger = function(name, data, namespace, state, enter) { + var status = { + item: { count: this._items.length, index: this.current() } + }, handler = $.camelCase( + $.grep([ 'on', name, namespace ], function(v) { return v }) + .join('-').toLowerCase() + ), event = $.Event( + [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), + $.extend({ relatedTarget: this }, status, data) + ); + + if (!this._supress[name]) { + $.each(this._plugins, function(name, plugin) { + if (plugin.onTrigger) { + plugin.onTrigger(event); + } + }); + + this.register({ type: Owl.Type.Event, name: name }); + this.$element.trigger(event); + + if (this.settings && typeof this.settings[handler] === 'function') { + this.settings[handler].call(this, event); + } + } + + return event; + }; + + /** + * Enters a state. + * @param name - The state name. + */ + Owl.prototype.enter = function(name) { + $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { + if (this._states.current[name] === undefined) { + this._states.current[name] = 0; + } + + this._states.current[name]++; + }, this)); + }; + + /** + * Leaves a state. + * @param name - The state name. + */ + Owl.prototype.leave = function(name) { + $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { + this._states.current[name]--; + }, this)); + }; + + /** + * Registers an event or state. + * @public + * @param {Object} object - The event or state to register. + */ + Owl.prototype.register = function(object) { + if (object.type === Owl.Type.Event) { + if (!$.event.special[object.name]) { + $.event.special[object.name] = {}; + } + + if (!$.event.special[object.name].owl) { + var _default = $.event.special[object.name]._default; + $.event.special[object.name]._default = function(e) { + if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { + return _default.apply(this, arguments); + } + return e.namespace && e.namespace.indexOf('owl') > -1; + }; + $.event.special[object.name].owl = true; + } + } else if (object.type === Owl.Type.State) { + if (!this._states.tags[object.name]) { + this._states.tags[object.name] = object.tags; + } else { + this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); + } + + this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { + return $.inArray(tag, this._states.tags[object.name]) === i; + }, this)); + } + }; + + /** + * Suppresses events. + * @protected + * @param {Array.} events - The events to suppress. + */ + Owl.prototype.suppress = function(events) { + $.each(events, $.proxy(function(index, event) { + this._supress[event] = true; + }, this)); + }; + + /** + * Releases suppressed events. + * @protected + * @param {Array.} events - The events to release. + */ + Owl.prototype.release = function(events) { + $.each(events, $.proxy(function(index, event) { + delete this._supress[event]; + }, this)); + }; + + /** + * Gets unified pointer coordinates from event. + * @todo #261 + * @protected + * @param {Event} - The `mousedown` or `touchstart` event. + * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. + */ + Owl.prototype.pointer = function(event) { + var result = { x: null, y: null }; + + event = event.originalEvent || event || window.event; + + event = event.touches && event.touches.length ? + event.touches[0] : event.changedTouches && event.changedTouches.length ? + event.changedTouches[0] : event; + + if (event.pageX) { + result.x = event.pageX; + result.y = event.pageY; + } else { + result.x = event.clientX; + result.y = event.clientY; + } + + return result; + }; + + /** + * Determines if the input is a Number or something that can be coerced to a Number + * @protected + * @param {Number|String|Object|Array|Boolean|RegExp|Function|Symbol} - The input to be tested + * @returns {Boolean} - An indication if the input is a Number or can be coerced to a Number + */ + Owl.prototype.isNumeric = function(number) { + return !isNaN(parseFloat(number)); + }; + + /** + * Gets the difference of two vectors. + * @todo #261 + * @protected + * @param {Object} - The first vector. + * @param {Object} - The second vector. + * @returns {Object} - The difference. + */ + Owl.prototype.difference = function(first, second) { + return { + x: first.x - second.x, + y: first.y - second.y + }; + }; + + /** + * The jQuery Plugin for the Owl Carousel + * @todo Navigation plugin `next` and `prev` + * @public + */ + $.fn.owlCarousel = function(option) { + var args = Array.prototype.slice.call(arguments, 1); + + return this.each(function() { + var $this = $(this), + data = $this.data('owl.carousel'); + + if (!data) { + data = new Owl(this, typeof option == 'object' && option); + $this.data('owl.carousel', data); + + $.each([ + 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' + ], function(i, event) { + data.register({ type: Owl.Type.Event, name: event }); + data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { + if (e.namespace && e.relatedTarget !== this) { + this.suppress([ event ]); + data[event].apply(this, [].slice.call(arguments, 1)); + this.release([ event ]); + } + }, data)); + }); + } + + if (typeof option == 'string' && option.charAt(0) !== '_') { + data[option].apply(data, args); + } + }); + }; + + /** + * The constructor for the jQuery Plugin + * @public + */ + $.fn.owlCarousel.Constructor = Owl; + +})(window.Zepto || window.jQuery, window, document); + +/** + * AutoRefresh Plugin + * @version 2.3.4 + * @author Artus Kolanowski + * @author David Deutsch + * @license The MIT License (MIT) + */ +;(function($, window, document, undefined) { + + /** + * Creates the auto refresh plugin. + * @class The Auto Refresh Plugin + * @param {Owl} carousel - The Owl Carousel + */ + var AutoRefresh = function(carousel) { + /** + * Reference to the core. + * @protected + * @type {Owl} + */ + this._core = carousel; + + /** + * Refresh interval. + * @protected + * @type {number} + */ + this._interval = null; + + /** + * Whether the element is currently visible or not. + * @protected + * @type {Boolean} + */ + this._visible = null; + + /** + * All event handlers. + * @protected + * @type {Object} + */ + this._handlers = { + 'initialized.owl.carousel': $.proxy(function(e) { + if (e.namespace && this._core.settings.autoRefresh) { + this.watch(); + } + }, this) + }; + + // set default options + this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); + + // register event handlers + this._core.$element.on(this._handlers); + }; + + /** + * Default options. + * @public + */ + AutoRefresh.Defaults = { + autoRefresh: true, + autoRefreshInterval: 500 + }; + + /** + * Watches the element. + */ + AutoRefresh.prototype.watch = function() { + if (this._interval) { + return; + } + + this._visible = this._core.isVisible(); + this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); + }; + + /** + * Refreshes the element. + */ + AutoRefresh.prototype.refresh = function() { + if (this._core.isVisible() === this._visible) { + return; + } + + this._visible = !this._visible; + + this._core.$element.toggleClass('owl-hidden', !this._visible); + + this._visible && (this._core.invalidate('width') && this._core.refresh()); + }; + + /** + * Destroys the plugin. + */ + AutoRefresh.prototype.destroy = function() { + var handler, property; + + window.clearInterval(this._interval); + + for (handler in this._handlers) { + this._core.$element.off(handler, this._handlers[handler]); + } + for (property in Object.getOwnPropertyNames(this)) { + typeof this[property] != 'function' && (this[property] = null); + } + }; + + $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; + +})(window.Zepto || window.jQuery, window, document); + +/** + * Lazy Plugin + * @version 2.3.4 + * @author Bartosz Wojciechowski + * @author David Deutsch + * @license The MIT License (MIT) + */ +;(function($, window, document, undefined) { + + /** + * Creates the lazy plugin. + * @class The Lazy Plugin + * @param {Owl} carousel - The Owl Carousel + */ + var Lazy = function(carousel) { + + /** + * Reference to the core. + * @protected + * @type {Owl} + */ + this._core = carousel; + + /** + * Already loaded items. + * @protected + * @type {Array.} + */ + this._loaded = []; + + /** + * Event handlers. + * @protected + * @type {Object} + */ + this._handlers = { + 'initialized.owl.carousel change.owl.carousel resized.owl.carousel': $.proxy(function(e) { + if (!e.namespace) { + return; + } + + if (!this._core.settings || !this._core.settings.lazyLoad) { + return; + } + + if ((e.property && e.property.name == 'position') || e.type == 'initialized') { + var settings = this._core.settings, + n = (settings.center && Math.ceil(settings.items / 2) || settings.items), + i = ((settings.center && n * -1) || 0), + position = (e.property && e.property.value !== undefined ? e.property.value : this._core.current()) + i, + clones = this._core.clones().length, + load = $.proxy(function(i, v) { this.load(v) }, this); + //TODO: Need documentation for this new option + if (settings.lazyLoadEager > 0) { + n += settings.lazyLoadEager; + // If the carousel is looping also preload images that are to the "left" + if (settings.loop) { + position -= settings.lazyLoadEager; + n++; + } + } + + while (i++ < n) { + this.load(clones / 2 + this._core.relative(position)); + clones && $.each(this._core.clones(this._core.relative(position)), load); + position++; + } + } + }, this) + }; + + // set the default options + this._core.options = $.extend({}, Lazy.Defaults, this._core.options); + + // register event handler + this._core.$element.on(this._handlers); + }; + + /** + * Default options. + * @public + */ + Lazy.Defaults = { + lazyLoad: false, + lazyLoadEager: 0 + }; + + /** + * Loads all resources of an item at the specified position. + * @param {Number} position - The absolute position of the item. + * @protected + */ + Lazy.prototype.load = function(position) { + var $item = this._core.$stage.children().eq(position), + $elements = $item && $item.find('.owl-lazy'); + + if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { + return; + } + + $elements.each($.proxy(function(index, element) { + var $element = $(element), image, + url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src') || $element.attr('data-srcset'); + + this._core.trigger('load', { element: $element, url: url }, 'lazy'); + + if ($element.is('img')) { + $element.one('load.owl.lazy', $.proxy(function() { + $element.css('opacity', 1); + this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); + }, this)).attr('src', url); + } else if ($element.is('source')) { + $element.one('load.owl.lazy', $.proxy(function() { + this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); + }, this)).attr('srcset', url); + } else { + image = new Image(); + image.onload = $.proxy(function() { + $element.css({ + 'background-image': 'url("' + url + '")', + 'opacity': '1' + }); + this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); + }, this); + image.src = url; + } + }, this)); + + this._loaded.push($item.get(0)); + }; + + /** + * Destroys the plugin. + * @public + */ + Lazy.prototype.destroy = function() { + var handler, property; + + for (handler in this.handlers) { + this._core.$element.off(handler, this.handlers[handler]); + } + for (property in Object.getOwnPropertyNames(this)) { + typeof this[property] != 'function' && (this[property] = null); + } + }; + + $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; + +})(window.Zepto || window.jQuery, window, document); + +/** + * AutoHeight Plugin + * @version 2.3.4 + * @author Bartosz Wojciechowski + * @author David Deutsch + * @license The MIT License (MIT) + */ +;(function($, window, document, undefined) { + + /** + * Creates the auto height plugin. + * @class The Auto Height Plugin + * @param {Owl} carousel - The Owl Carousel + */ + var AutoHeight = function(carousel) { + /** + * Reference to the core. + * @protected + * @type {Owl} + */ + this._core = carousel; + + this._previousHeight = null; + + /** + * All event handlers. + * @protected + * @type {Object} + */ + this._handlers = { + 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { + if (e.namespace && this._core.settings.autoHeight) { + this.update(); + } + }, this), + 'changed.owl.carousel': $.proxy(function(e) { + if (e.namespace && this._core.settings.autoHeight && e.property.name === 'position'){ + this.update(); + } + }, this), + 'loaded.owl.lazy': $.proxy(function(e) { + if (e.namespace && this._core.settings.autoHeight + && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { + this.update(); + } + }, this) + }; + + // set default options + this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); + + // register event handlers + this._core.$element.on(this._handlers); + this._intervalId = null; + var refThis = this; + + // These changes have been taken from a PR by gavrochelegnou proposed in #1575 + // and have been made compatible with the latest jQuery version + $(window).on('load', function() { + if (refThis._core.settings.autoHeight) { + refThis.update(); + } + }); + + // Autoresize the height of the carousel when window is resized + // When carousel has images, the height is dependent on the width + // and should also change on resize + $(window).resize(function() { + if (refThis._core.settings.autoHeight) { + if (refThis._intervalId != null) { + clearTimeout(refThis._intervalId); + } + + refThis._intervalId = setTimeout(function() { + refThis.update(); + }, 250); + } + }); + + }; + + /** + * Default options. + * @public + */ + AutoHeight.Defaults = { + autoHeight: false, + autoHeightClass: 'owl-height' + }; + + /** + * Updates the view. + */ + AutoHeight.prototype.update = function() { + var start = this._core._current, + end = start + this._core.settings.items, + lazyLoadEnabled = this._core.settings.lazyLoad, + visible = this._core.$stage.children().toArray().slice(start, end), + heights = [], + maxheight = 0; + + $.each(visible, function(index, item) { + heights.push($(item).height()); + }); + + maxheight = Math.max.apply(null, heights); + + if (maxheight <= 1 && lazyLoadEnabled && this._previousHeight) { + maxheight = this._previousHeight; + } + + this._previousHeight = maxheight; + + this._core.$stage.parent() + .height(maxheight) + .addClass(this._core.settings.autoHeightClass); + }; + + AutoHeight.prototype.destroy = function() { + var handler, property; + + for (handler in this._handlers) { + this._core.$element.off(handler, this._handlers[handler]); + } + for (property in Object.getOwnPropertyNames(this)) { + typeof this[property] !== 'function' && (this[property] = null); + } + }; + + $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; + +})(window.Zepto || window.jQuery, window, document); + +/** + * Video Plugin + * @version 2.3.4 + * @author Bartosz Wojciechowski + * @author David Deutsch + * @license The MIT License (MIT) + */ +;(function($, window, document, undefined) { + + /** + * Creates the video plugin. + * @class The Video Plugin + * @param {Owl} carousel - The Owl Carousel + */ + var Video = function(carousel) { + /** + * Reference to the core. + * @protected + * @type {Owl} + */ + this._core = carousel; + + /** + * Cache all video URLs. + * @protected + * @type {Object} + */ + this._videos = {}; + + /** + * Current playing item. + * @protected + * @type {jQuery} + */ + this._playing = null; + + /** + * All event handlers. + * @todo The cloned content removale is too late + * @protected + * @type {Object} + */ + this._handlers = { + 'initialized.owl.carousel': $.proxy(function(e) { + if (e.namespace) { + this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); + } + }, this), + 'resize.owl.carousel': $.proxy(function(e) { + if (e.namespace && this._core.settings.video && this.isInFullScreen()) { + e.preventDefault(); + } + }, this), + 'refreshed.owl.carousel': $.proxy(function(e) { + if (e.namespace && this._core.is('resizing')) { + this._core.$stage.find('.cloned .owl-video-frame').remove(); + } + }, this), + 'changed.owl.carousel': $.proxy(function(e) { + if (e.namespace && e.property.name === 'position' && this._playing) { + this.stop(); + } + }, this), + 'prepared.owl.carousel': $.proxy(function(e) { + if (!e.namespace) { + return; + } + + var $element = $(e.content).find('.owl-video'); + + if ($element.length) { + $element.css('display', 'none'); + this.fetch($element, $(e.content)); + } + }, this) + }; + + // set default options + this._core.options = $.extend({}, Video.Defaults, this._core.options); + + // register event handlers + this._core.$element.on(this._handlers); + + this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { + this.play(e); + }, this)); + }; + + /** + * Default options. + * @public + */ + Video.Defaults = { + video: false, + videoHeight: false, + videoWidth: false + }; + + /** + * Gets the video ID and the type (YouTube/Vimeo/vzaar only). + * @protected + * @param {jQuery} target - The target containing the video data. + * @param {jQuery} item - The item containing the video. + */ + Video.prototype.fetch = function(target, item) { + var type = (function() { + if (target.attr('data-vimeo-id')) { + return 'vimeo'; + } else if (target.attr('data-vzaar-id')) { + return 'vzaar' + } else { + return 'youtube'; + } + })(), + id = target.attr('data-vimeo-id') || target.attr('data-youtube-id') || target.attr('data-vzaar-id'), + width = target.attr('data-width') || this._core.settings.videoWidth, + height = target.attr('data-height') || this._core.settings.videoHeight, + url = target.attr('href'); + + if (url) { + + /* + Parses the id's out of the following urls (and probably more): + https://www.youtube.com/watch?v=:id + https://youtu.be/:id + https://vimeo.com/:id + https://vimeo.com/channels/:channel/:id + https://vimeo.com/groups/:group/videos/:id + https://app.vzaar.com/videos/:id + + Visual example: https://regexper.com/#(http%3A%7Chttps%3A%7C)%5C%2F%5C%2F(player.%7Cwww.%7Capp.)%3F(vimeo%5C.com%7Cyoutu(be%5C.com%7C%5C.be%7Cbe%5C.googleapis%5C.com)%7Cvzaar%5C.com)%5C%2F(video%5C%2F%7Cvideos%5C%2F%7Cembed%5C%2F%7Cchannels%5C%2F.%2B%5C%2F%7Cgroups%5C%2F.%2B%5C%2F%7Cwatch%5C%3Fv%3D%7Cv%5C%2F)%3F(%5BA-Za-z0-9._%25-%5D*)(%5C%26%5CS%2B)%3F + */ + + id = url.match(/(http:|https:|)\/\/(player.|www.|app.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com|be\-nocookie\.com)|vzaar\.com)\/(video\/|videos\/|embed\/|channels\/.+\/|groups\/.+\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/); + + if (id[3].indexOf('youtu') > -1) { + type = 'youtube'; + } else if (id[3].indexOf('vimeo') > -1) { + type = 'vimeo'; + } else if (id[3].indexOf('vzaar') > -1) { + type = 'vzaar'; + } else { + throw new Error('Video URL not supported.'); + } + id = id[6]; + } else { + throw new Error('Missing video URL.'); + } + + this._videos[url] = { + type: type, + id: id, + width: width, + height: height + }; + + item.attr('data-video', url); + + this.thumbnail(target, this._videos[url]); + }; + + /** + * Creates video thumbnail. + * @protected + * @param {jQuery} target - The target containing the video data. + * @param {Object} info - The video info object. + * @see `fetch` + */ + Video.prototype.thumbnail = function(target, video) { + var tnLink, + icon, + path, + dimensions = video.width && video.height ? 'width:' + video.width + 'px;height:' + video.height + 'px;' : '', + customTn = target.find('img'), + srcType = 'src', + lazyClass = '', + settings = this._core.settings, + create = function(path) { + icon = '
'; + + if (settings.lazyLoad) { + tnLink = $('
',{ + "class": 'owl-video-tn ' + lazyClass, + "srcType": path + }); + } else { + tnLink = $( '
', { + "class": "owl-video-tn", + "style": 'opacity:1;background-image:url(' + path + ')' + }); + } + target.after(tnLink); + target.after(icon); + }; + + // wrap video content into owl-video-wrapper div + target.wrap( $( '
', { + "class": "owl-video-wrapper", + "style": dimensions + })); + + if (this._core.settings.lazyLoad) { + srcType = 'data-src'; + lazyClass = 'owl-lazy'; + } + + // custom thumbnail + if (customTn.length) { + create(customTn.attr(srcType)); + customTn.remove(); + return false; + } + + if (video.type === 'youtube') { + path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; + create(path); + } else if (video.type === 'vimeo') { + $.ajax({ + type: 'GET', + url: '//vimeo.com/api/v2/video/' + video.id + '.json', + jsonp: 'callback', + dataType: 'jsonp', + success: function(data) { + path = data[0].thumbnail_large; + create(path); + } + }); + } else if (video.type === 'vzaar') { + $.ajax({ + type: 'GET', + url: '//vzaar.com/api/videos/' + video.id + '.json', + jsonp: 'callback', + dataType: 'jsonp', + success: function(data) { + path = data.framegrab_url; + create(path); + } + }); + } + }; + + /** + * Stops the current video. + * @public + */ + Video.prototype.stop = function() { + this._core.trigger('stop', null, 'video'); + this._playing.find('.owl-video-frame').remove(); + this._playing.removeClass('owl-video-playing'); + this._playing = null; + this._core.leave('playing'); + this._core.trigger('stopped', null, 'video'); + }; + + /** + * Starts the current video. + * @public + * @param {Event} event - The event arguments. + */ + Video.prototype.play = function(event) { + var target = $(event.target), + item = target.closest('.' + this._core.settings.itemClass), + video = this._videos[item.attr('data-video')], + width = video.width || '100%', + height = video.height || this._core.$stage.height(), + html, + iframe; + + if (this._playing) { + return; + } + + this._core.enter('playing'); + this._core.trigger('play', null, 'video'); + + item = this._core.items(this._core.relative(item.index())); + + this._core.reset(item.index()); + + html = $( '' ); + html.attr( 'height', height ); + html.attr( 'width', width ); + if (video.type === 'youtube') { + html.attr( 'src', '//www.youtube.com/embed/' + video.id + '?autoplay=1&rel=0&v=' + video.id ); + } else if (video.type === 'vimeo') { + html.attr( 'src', '//player.vimeo.com/video/' + video.id + '?autoplay=1' ); + } else if (video.type === 'vzaar') { + html.attr( 'src', '//view.vzaar.com/' + video.id + '/player?autoplay=true' ); + } + + iframe = $(html).wrap( '
' ).insertAfter(item.find('.owl-video')); + + this._playing = item.addClass('owl-video-playing'); + }; + + /** + * Checks whether an video is currently in full screen mode or not. + * @todo Bad style because looks like a readonly method but changes members. + * @protected + * @returns {Boolean} + */ + Video.prototype.isInFullScreen = function() { + var element = document.fullscreenElement || document.mozFullScreenElement || + document.webkitFullscreenElement; + + return element && $(element).parent().hasClass('owl-video-frame'); + }; + + /** + * Destroys the plugin. + */ + Video.prototype.destroy = function() { + var handler, property; + + this._core.$element.off('click.owl.video'); + + for (handler in this._handlers) { + this._core.$element.off(handler, this._handlers[handler]); + } + for (property in Object.getOwnPropertyNames(this)) { + typeof this[property] != 'function' && (this[property] = null); + } + }; + + $.fn.owlCarousel.Constructor.Plugins.Video = Video; + +})(window.Zepto || window.jQuery, window, document); + +/** + * Animate Plugin + * @version 2.3.4 + * @author Bartosz Wojciechowski + * @author David Deutsch + * @license The MIT License (MIT) + */ +;(function($, window, document, undefined) { + + /** + * Creates the animate plugin. + * @class The Navigation Plugin + * @param {Owl} scope - The Owl Carousel + */ + var Animate = function(scope) { + this.core = scope; + this.core.options = $.extend({}, Animate.Defaults, this.core.options); + this.swapping = true; + this.previous = undefined; + this.next = undefined; + + this.handlers = { + 'change.owl.carousel': $.proxy(function(e) { + if (e.namespace && e.property.name == 'position') { + this.previous = this.core.current(); + this.next = e.property.value; + } + }, this), + 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { + if (e.namespace) { + this.swapping = e.type == 'translated'; + } + }, this), + 'translate.owl.carousel': $.proxy(function(e) { + if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { + this.swap(); + } + }, this) + }; + + this.core.$element.on(this.handlers); + }; + + /** + * Default options. + * @public + */ + Animate.Defaults = { + animateOut: false, + animateIn: false + }; + + /** + * Toggles the animation classes whenever an translations starts. + * @protected + * @returns {Boolean|undefined} + */ + Animate.prototype.swap = function() { + + if (this.core.settings.items !== 1) { + return; + } + + if (!$.support.animation || !$.support.transition) { + return; + } + + this.core.speed(0); + + var left, + clear = $.proxy(this.clear, this), + previous = this.core.$stage.children().eq(this.previous), + next = this.core.$stage.children().eq(this.next), + incoming = this.core.settings.animateIn, + outgoing = this.core.settings.animateOut; + + if (this.core.current() === this.previous) { + return; + } + + if (outgoing) { + left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); + previous.one($.support.animation.end, clear) + .css( { 'left': left + 'px' } ) + .addClass('animated owl-animated-out') + .addClass(outgoing); + } + + if (incoming) { + next.one($.support.animation.end, clear) + .addClass('animated owl-animated-in') + .addClass(incoming); + } + }; + + Animate.prototype.clear = function(e) { + $(e.target).css( { 'left': '' } ) + .removeClass('animated owl-animated-out owl-animated-in') + .removeClass(this.core.settings.animateIn) + .removeClass(this.core.settings.animateOut); + this.core.onTransitionEnd(); + }; + + /** + * Destroys the plugin. + * @public + */ + Animate.prototype.destroy = function() { + var handler, property; + + for (handler in this.handlers) { + this.core.$element.off(handler, this.handlers[handler]); + } + for (property in Object.getOwnPropertyNames(this)) { + typeof this[property] != 'function' && (this[property] = null); + } + }; + + $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; + +})(window.Zepto || window.jQuery, window, document); + +/** + * Autoplay Plugin + * @version 2.3.4 + * @author Bartosz Wojciechowski + * @author Artus Kolanowski + * @author David Deutsch + * @author Tom De Caluwé + * @license The MIT License (MIT) + */ +;(function($, window, document, undefined) { + + /** + * Creates the autoplay plugin. + * @class The Autoplay Plugin + * @param {Owl} scope - The Owl Carousel + */ + var Autoplay = function(carousel) { + /** + * Reference to the core. + * @protected + * @type {Owl} + */ + this._core = carousel; + + /** + * The autoplay timeout id. + * @type {Number} + */ + this._call = null; + + /** + * Depending on the state of the plugin, this variable contains either + * the start time of the timer or the current timer value if it's + * paused. Since we start in a paused state we initialize the timer + * value. + * @type {Number} + */ + this._time = 0; + + /** + * Stores the timeout currently used. + * @type {Number} + */ + this._timeout = 0; + + /** + * Indicates whenever the autoplay is paused. + * @type {Boolean} + */ + this._paused = true; + + /** + * All event handlers. + * @protected + * @type {Object} + */ + this._handlers = { + 'changed.owl.carousel': $.proxy(function(e) { + if (e.namespace && e.property.name === 'settings') { + if (this._core.settings.autoplay) { + this.play(); + } else { + this.stop(); + } + } else if (e.namespace && e.property.name === 'position' && this._paused) { + // Reset the timer. This code is triggered when the position + // of the carousel was changed through user interaction. + this._time = 0; + } + }, this), + 'initialized.owl.carousel': $.proxy(function(e) { + if (e.namespace && this._core.settings.autoplay) { + this.play(); + } + }, this), + 'play.owl.autoplay': $.proxy(function(e, t, s) { + if (e.namespace) { + this.play(t, s); + } + }, this), + 'stop.owl.autoplay': $.proxy(function(e) { + if (e.namespace) { + this.stop(); + } + }, this), + 'mouseover.owl.autoplay': $.proxy(function() { + if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { + this.pause(); + } + }, this), + 'mouseleave.owl.autoplay': $.proxy(function() { + if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { + this.play(); + } + }, this), + 'touchstart.owl.core': $.proxy(function() { + if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { + this.pause(); + } + }, this), + 'touchend.owl.core': $.proxy(function() { + if (this._core.settings.autoplayHoverPause) { + this.play(); + } + }, this) + }; + + // register event handlers + this._core.$element.on(this._handlers); + + // set default options + this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); + }; + + /** + * Default options. + * @public + */ + Autoplay.Defaults = { + autoplay: false, + autoplayTimeout: 5000, + autoplayHoverPause: false, + autoplaySpeed: false + }; + + /** + * Transition to the next slide and set a timeout for the next transition. + * @private + * @param {Number} [speed] - The animation speed for the animations. + */ + Autoplay.prototype._next = function(speed) { + this._call = window.setTimeout( + $.proxy(this._next, this, speed), + this._timeout * (Math.round(this.read() / this._timeout) + 1) - this.read() + ); + + if (this._core.is('interacting') || document.hidden) { + return; + } + this._core.next(speed || this._core.settings.autoplaySpeed); + } + + /** + * Reads the current timer value when the timer is playing. + * @public + */ + Autoplay.prototype.read = function() { + return new Date().getTime() - this._time; + }; + + /** + * Starts the autoplay. + * @public + * @param {Number} [timeout] - The interval before the next animation starts. + * @param {Number} [speed] - The animation speed for the animations. + */ + Autoplay.prototype.play = function(timeout, speed) { + var elapsed; + + if (!this._core.is('rotating')) { + this._core.enter('rotating'); + } + + timeout = timeout || this._core.settings.autoplayTimeout; + + // Calculate the elapsed time since the last transition. If the carousel + // wasn't playing this calculation will yield zero. + elapsed = Math.min(this._time % (this._timeout || timeout), timeout); + + if (this._paused) { + // Start the clock. + this._time = this.read(); + this._paused = false; + } else { + // Clear the active timeout to allow replacement. + window.clearTimeout(this._call); + } + + // Adjust the origin of the timer to match the new timeout value. + this._time += this.read() % timeout - elapsed; + + this._timeout = timeout; + this._call = window.setTimeout($.proxy(this._next, this, speed), timeout - elapsed); + }; + + /** + * Stops the autoplay. + * @public + */ + Autoplay.prototype.stop = function() { + if (this._core.is('rotating')) { + // Reset the clock. + this._time = 0; + this._paused = true; + + window.clearTimeout(this._call); + this._core.leave('rotating'); + } + }; + + /** + * Pauses the autoplay. + * @public + */ + Autoplay.prototype.pause = function() { + if (this._core.is('rotating') && !this._paused) { + // Pause the clock. + this._time = this.read(); + this._paused = true; + + window.clearTimeout(this._call); + } + }; + + /** + * Destroys the plugin. + */ + Autoplay.prototype.destroy = function() { + var handler, property; + + this.stop(); + + for (handler in this._handlers) { + this._core.$element.off(handler, this._handlers[handler]); + } + for (property in Object.getOwnPropertyNames(this)) { + typeof this[property] != 'function' && (this[property] = null); + } + }; + + $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; + +})(window.Zepto || window.jQuery, window, document); + +/** + * Navigation Plugin + * @version 2.3.4 + * @author Artus Kolanowski + * @author David Deutsch + * @license The MIT License (MIT) + */ +;(function($, window, document, undefined) { + 'use strict'; + + /** + * Creates the navigation plugin. + * @class The Navigation Plugin + * @param {Owl} carousel - The Owl Carousel. + */ + var Navigation = function(carousel) { + /** + * Reference to the core. + * @protected + * @type {Owl} + */ + this._core = carousel; + + /** + * Indicates whether the plugin is initialized or not. + * @protected + * @type {Boolean} + */ + this._initialized = false; + + /** + * The current paging indexes. + * @protected + * @type {Array} + */ + this._pages = []; + + /** + * All DOM elements of the user interface. + * @protected + * @type {Object} + */ + this._controls = {}; + + /** + * Markup for an indicator. + * @protected + * @type {Array.} + */ + this._templates = []; + + /** + * The carousel element. + * @type {jQuery} + */ + this.$element = this._core.$element; + + /** + * Overridden methods of the carousel. + * @protected + * @type {Object} + */ + this._overrides = { + next: this._core.next, + prev: this._core.prev, + to: this._core.to + }; + + /** + * All event handlers. + * @protected + * @type {Object} + */ + this._handlers = { + 'prepared.owl.carousel': $.proxy(function(e) { + if (e.namespace && this._core.settings.dotsData) { + this._templates.push('
' + + $(e.content).find('[data-dot]').addBack('[data-dot]').attr('data-dot') + '
'); + } + }, this), + 'added.owl.carousel': $.proxy(function(e) { + if (e.namespace && this._core.settings.dotsData) { + this._templates.splice(e.position, 0, this._templates.pop()); + } + }, this), + 'remove.owl.carousel': $.proxy(function(e) { + if (e.namespace && this._core.settings.dotsData) { + this._templates.splice(e.position, 1); + } + }, this), + 'changed.owl.carousel': $.proxy(function(e) { + if (e.namespace && e.property.name == 'position') { + this.draw(); + } + }, this), + 'initialized.owl.carousel': $.proxy(function(e) { + if (e.namespace && !this._initialized) { + this._core.trigger('initialize', null, 'navigation'); + this.initialize(); + this.update(); + this.draw(); + this._initialized = true; + this._core.trigger('initialized', null, 'navigation'); + } + }, this), + 'refreshed.owl.carousel': $.proxy(function(e) { + if (e.namespace && this._initialized) { + this._core.trigger('refresh', null, 'navigation'); + this.update(); + this.draw(); + this._core.trigger('refreshed', null, 'navigation'); + } + }, this) + }; + + // set default options + this._core.options = $.extend({}, Navigation.Defaults, this._core.options); + + // register event handlers + this.$element.on(this._handlers); + }; + + /** + * Default options. + * @public + * @todo Rename `slideBy` to `navBy` + */ + Navigation.Defaults = { + nav: false, + navText: [ + '', + '' + ], + navSpeed: false, + navElement: 'button type="button" role="presentation"', + navContainer: false, + navContainerClass: 'owl-nav', + navClass: [ + 'owl-prev', + 'owl-next' + ], + slideBy: 1, + dotClass: 'owl-dot', + dotsClass: 'owl-dots', + dots: true, + dotsEach: false, + dotsData: false, + dotsSpeed: false, + dotsContainer: false + }; + + /** + * Initializes the layout of the plugin and extends the carousel. + * @protected + */ + Navigation.prototype.initialize = function() { + var override, + settings = this._core.settings; + + // create DOM structure for relative navigation + this._controls.$relative = (settings.navContainer ? $(settings.navContainer) + : $('
').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); + + this._controls.$previous = $('<' + settings.navElement + '>') + .addClass(settings.navClass[0]) + .html(settings.navText[0]) + .prependTo(this._controls.$relative) + .on('click', $.proxy(function(e) { + this.prev(settings.navSpeed); + }, this)); + this._controls.$next = $('<' + settings.navElement + '>') + .addClass(settings.navClass[1]) + .html(settings.navText[1]) + .appendTo(this._controls.$relative) + .on('click', $.proxy(function(e) { + this.next(settings.navSpeed); + }, this)); + + // create DOM structure for absolute navigation + if (!settings.dotsData) { + this._templates = [ $(' + + + +
+
+ +
+

Snippet: +

+
You're editing page:
+
+
+
+ + + + + DESKTOP + + + + + + MOBILE + +
+ +
+ +
+
+
+
+
+
+
+ phone +
+