diff --git a/base_accounting_kit/__manifest__.py b/base_accounting_kit/__manifest__.py index 1521e624e..890029e05 100644 --- a/base_accounting_kit/__manifest__.py +++ b/base_accounting_kit/__manifest__.py @@ -22,7 +22,7 @@ { 'name': 'Odoo 14 Full Accounting Kit', - 'version': '14.0.3.13.14', + 'version': '14.0.3.13.16', 'category': 'Accounting', 'live_test_url': 'https://www.youtube.com/watch?v=peAp2Tx_XIs', 'summary': """ Asset and Budget Management, diff --git a/base_accounting_kit/models/payment_matching.py b/base_accounting_kit/models/payment_matching.py index 9882fc09f..583bcb454 100644 --- a/base_accounting_kit/models/payment_matching.py +++ b/base_accounting_kit/models/payment_matching.py @@ -234,7 +234,6 @@ class AccountReconciliation(models.AbstractModel): results = self.get_bank_statement_line_data(bank_statement_lines.ids) bank_statement_lines_left = self.env['account.bank.statement.line'].browse([line['st_line']['id'] for line in results['lines']]) bank_statements_left = bank_statement_lines_left.mapped('statement_id') - results.update({ 'statement_name': len(bank_statements_left) == 1 and bank_statements_left.name or False, 'journal_id': bank_statements and bank_statements[0].journal_id.id or False, @@ -253,7 +252,6 @@ class AccountReconciliation(models.AbstractModel): 'ids': results['reconciled_aml_ids'], } }) - return results @api.model @@ -731,10 +729,9 @@ class AccountReconciliation(models.AbstractModel): amount_currency = amount amount_currency_str = "" amount_str = formatLang(self.env, abs(amount), currency_obj=st_line.currency_id or statement_currency) - data = { 'id': st_line.id, - 'ref': st_line.ref, + 'payment_ref': st_line.payment_ref, 'note': st_line.narration or "", 'name': st_line.name, 'date': format_date(self.env, st_line.date), @@ -756,7 +753,6 @@ class AccountReconciliation(models.AbstractModel): } if st_line.partner_id: data['open_balance_account_id'] = amount > 0 and st_line.partner_id.property_account_receivable_id.id or st_line.partner_id.property_account_payable_id.id - return data @api.model @@ -1129,9 +1125,8 @@ class AccountBankStatementLine(models.Model): elif self.move_name: raise UserError(_('Operation not allowed. Since your statement line already received a number (%s), you cannot reconcile it entirely with existing journal entries otherwise it would make a gap in the numbering. You should book an entry and make a regular revert of it in case you want to cancel it.')% (self.move_name)) - # create the res.partner.bank if needed - if self.account_number and self.partner_id and not self.bank_account_id: + if self.account_number and self.partner_id and not self.statement_id: # Search bank account without partner to handle the case the res.partner.bank already exists but is set # on a different partner. self.partner_bank_id = self._find_or_create_bank_account() diff --git a/duplicate_contact_details_alert/README.rst b/duplicate_contact_details_alert/README.rst new file mode 100644 index 000000000..610465755 --- /dev/null +++ b/duplicate_contact_details_alert/README.rst @@ -0,0 +1,39 @@ +Duplicate Contact Details Alert +=============================== +* Duplicate Contact Details Alert module for Odoo 14. + +Installation +============ + - www.odoo.com/documentation/14.0/setup/install.html + - Install our custom addon + +License +------- +General Public License, Version 3 (AGPL v3). +(https://www.odoo.com/documentation/user/14.0/legal/licenses/licenses.html) + +Company +------- +* 'Cybrosys Techno Solutions '__ + +Credits +------- +* 'Cybrosys Techno Solutions '__ + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit https://www.cybrosys.com + +Further information +=================== +HTML Description: ``__ diff --git a/duplicate_contact_details_alert/__init__.py b/duplicate_contact_details_alert/__init__.py new file mode 100644 index 000000000..3367fdfdb --- /dev/null +++ b/duplicate_contact_details_alert/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import models diff --git a/duplicate_contact_details_alert/__manifest__.py b/duplicate_contact_details_alert/__manifest__.py new file mode 100644 index 000000000..947aa120a --- /dev/null +++ b/duplicate_contact_details_alert/__manifest__.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +{ + 'name': "Duplicate Contact Details Alert", + 'version': '14.0.1.0.0', + 'summary': """Duplicate Contact Details Alert""", + "category": 'Extra Tools', + 'description': """Duplicate Contact Details Alert""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': 'https://www.cybrosys.com', + 'depends': ['base', 'contacts'], + 'data': [ + 'views/res_config_settings_views.xml', + ], + 'images': ['static/description/banner.png'], + 'license': "LGPL-3", + 'installable': True, + 'application': False, + 'auto_install': False, +} diff --git a/duplicate_contact_details_alert/doc/RELEASE_NOTES.md b/duplicate_contact_details_alert/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..e39681810 --- /dev/null +++ b/duplicate_contact_details_alert/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 24.10.2022 +#### Version 14.0.1.0.0 +#### ADD +- Initial commit for Duplicate Contact Details Alert Module \ No newline at end of file diff --git a/duplicate_contact_details_alert/models/__init__.py b/duplicate_contact_details_alert/models/__init__.py new file mode 100644 index 000000000..facecdb3a --- /dev/null +++ b/duplicate_contact_details_alert/models/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import res_partner +from . import res_config_settings diff --git a/duplicate_contact_details_alert/models/res_config_settings.py b/duplicate_contact_details_alert/models/res_config_settings.py new file mode 100644 index 000000000..01e98bbf5 --- /dev/null +++ b/duplicate_contact_details_alert/models/res_config_settings.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import api, fields, models +from ast import literal_eval + + +class ResConfig(models.TransientModel): + _inherit = 'res.config.settings' + + def _get_contacts_fields_domain(self): + return [ + ('model', '=', 'res.partner'), ('store', '=', True), + ('ttype', 'in', ['binary', 'char'])] + + is_unique_contact = fields.Boolean(string="Unique Contacts Alert") + unique_contact_ids = fields.Many2many( + 'ir.model.fields', string='Contact Fields', + domain=_get_contacts_fields_domain, + help='Warning to avoid duplication of customer/vendor' + ' details in the system') + + def set_values(self): + super(ResConfig, self).set_values() + self.env['ir.config_parameter'].set_param( + 'duplicate_contact_details_alert.is_unique_contact', + self.is_unique_contact) + + self.env['ir.config_parameter'].set_param( + 'duplicate_contact_details_alert.unique_contact_ids', + self.unique_contact_ids.ids) + + @api.model + def get_values(self): + res = super(ResConfig, self).get_values() + params = self.env['ir.config_parameter'].sudo() + contact_field_ids = params.get_param( + 'duplicate_contact_details_alert.unique_contact_ids') + if contact_field_ids: + res.update( + is_unique_contact=params.get_param( + 'duplicate_contact_details_alert.is_unique_contact'), + unique_contact_ids=[(6, 0, literal_eval(contact_field_ids))], + ) + return res + else: + return res diff --git a/duplicate_contact_details_alert/models/res_partner.py b/duplicate_contact_details_alert/models/res_partner.py new file mode 100644 index 000000000..63ef73756 --- /dev/null +++ b/duplicate_contact_details_alert/models/res_partner.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError, ValidationError +import ast + + +class ResPartner(models.Model): + _inherit = 'res.partner' + + @api.model + def create(self, vals): + unique_contact_ids = self.env[ + 'ir.config_parameter'].sudo().get_param( + 'duplicate_contact_details_alert.unique_contact_ids') + if unique_contact_ids: + fields_list = ast.literal_eval(unique_contact_ids) + for x in fields_list: + contact_fields = self.env['ir.model.fields'].browse(x) + field_vals = contact_fields.name + if vals.get(field_vals): + partner = self.env['res.partner'].search( + [(field_vals, '=', vals.get(field_vals))], limit=1) + if partner: + raise ValidationError( + _("The %s is already" + " used for contact %s.") % + (contact_fields.name, partner.name)) + else: + res = super(ResPartner, self).create(vals) + return res + else: + res = super(ResPartner, self).create(vals) + return res + + def write(self, vals): + unique_contact_ids = self.env[ + 'ir.config_parameter'].sudo().get_param( + 'duplicate_contact_details_alert.unique_contact_ids') + if unique_contact_ids: + fields_list = ast.literal_eval(unique_contact_ids) + for x in fields_list: + contact_fields = self.env['ir.model.fields'].browse(x) + field_vals = contact_fields.name + if vals.get(field_vals): + partner = self.env['res.partner'].search( + [(field_vals, '=', vals.get(field_vals))], limit=1) + if partner: + raise ValidationError( + _("The %s is already" + " used for contact %s.") % + (contact_fields.name, partner.name)) + else: + res = super(ResPartner, self).write(vals) + return res + + else: + res = super(ResPartner, self).write(vals) + return res diff --git a/duplicate_contact_details_alert/static/description/assets/icons/check.png b/duplicate_contact_details_alert/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/check.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/chevron.png b/duplicate_contact_details_alert/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/chevron.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/cogs.png b/duplicate_contact_details_alert/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/cogs.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/consultation.png b/duplicate_contact_details_alert/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/consultation.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/ecom-black.png b/duplicate_contact_details_alert/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/ecom-black.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/education-black.png b/duplicate_contact_details_alert/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/education-black.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/hotel-black.png b/duplicate_contact_details_alert/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/hotel-black.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/license.png b/duplicate_contact_details_alert/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/license.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/lifebuoy.png b/duplicate_contact_details_alert/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/lifebuoy.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/logo.png b/duplicate_contact_details_alert/static/description/assets/icons/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/logo.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/manufacturing-black.png b/duplicate_contact_details_alert/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/manufacturing-black.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/pos-black.png b/duplicate_contact_details_alert/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/pos-black.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/puzzle.png b/duplicate_contact_details_alert/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/puzzle.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/restaurant-black.png b/duplicate_contact_details_alert/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/restaurant-black.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/service-black.png b/duplicate_contact_details_alert/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/service-black.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/trading-black.png b/duplicate_contact_details_alert/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/trading-black.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/training.png b/duplicate_contact_details_alert/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/training.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/update.png b/duplicate_contact_details_alert/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/update.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/user.png b/duplicate_contact_details_alert/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/user.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/icons/wrench.png b/duplicate_contact_details_alert/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/icons/wrench.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/modules/budget_image.png b/duplicate_contact_details_alert/static/description/assets/modules/budget_image.png new file mode 100644 index 000000000..b50130c7d Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/modules/budget_image.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/modules/credit_image.png b/duplicate_contact_details_alert/static/description/assets/modules/credit_image.png new file mode 100644 index 000000000..3ad04ecfd Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/modules/credit_image.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/modules/employee_image.png b/duplicate_contact_details_alert/static/description/assets/modules/employee_image.png new file mode 100644 index 000000000..30ad58232 Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/modules/employee_image.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/modules/export_image.png b/duplicate_contact_details_alert/static/description/assets/modules/export_image.png new file mode 100644 index 000000000..492980ad0 Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/modules/export_image.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/modules/gantt_image.png b/duplicate_contact_details_alert/static/description/assets/modules/gantt_image.png new file mode 100644 index 000000000..1ae7cfe3b Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/modules/gantt_image.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/modules/quotation_image.png b/duplicate_contact_details_alert/static/description/assets/modules/quotation_image.png new file mode 100644 index 000000000..499b1a72f Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/modules/quotation_image.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/screenshots/dup_con1.png b/duplicate_contact_details_alert/static/description/assets/screenshots/dup_con1.png new file mode 100644 index 000000000..7bab659f1 Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/screenshots/dup_con1.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/screenshots/dup_con2.png b/duplicate_contact_details_alert/static/description/assets/screenshots/dup_con2.png new file mode 100644 index 000000000..a851fa3ce Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/screenshots/dup_con2.png differ diff --git a/duplicate_contact_details_alert/static/description/assets/screenshots/hero.gif b/duplicate_contact_details_alert/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..5786116fd Binary files /dev/null and b/duplicate_contact_details_alert/static/description/assets/screenshots/hero.gif differ diff --git a/duplicate_contact_details_alert/static/description/banner.png b/duplicate_contact_details_alert/static/description/banner.png new file mode 100644 index 000000000..9d89058ea Binary files /dev/null and b/duplicate_contact_details_alert/static/description/banner.png differ diff --git a/duplicate_contact_details_alert/static/description/icon.png b/duplicate_contact_details_alert/static/description/icon.png new file mode 100644 index 000000000..c608ac41e Binary files /dev/null and b/duplicate_contact_details_alert/static/description/icon.png differ diff --git a/duplicate_contact_details_alert/static/description/index.html b/duplicate_contact_details_alert/static/description/index.html new file mode 100644 index 000000000..c1fafd2d7 --- /dev/null +++ b/duplicate_contact_details_alert/static/description/index.html @@ -0,0 +1,559 @@ +
+
+
+
+ +
+
+
+ Community +
+ +
+
+
+
+ +
+
+
+

+ Duplicate Contact Alert

+

+ Duplicate contact alert module helps to detect duplicate contact values. +

+ +
+
+ + + +
+
+

+ Overview +

+
+ +
+

+ The Duplicate contact alert module helps to detect duplicate contact values. When a user enters the same value in the contact, it returns a validation error message, which helps customers prevent duplicate entries. +

+
+

+ +
+ + +
+
+

+ Features +

+
+ +
+
+ +
+
+

+ Select Multiple Fields

+

+ User can select multiple fields to check for duplicate values. + +

+
+
+ + +
+
+ +
+
+

+ Validation Alert

+

+ Validation warning is triggered when users enter duplicate values. +

+
+
+ + +
+ +
+
+

+ Screenshots +

+
+
+

+ Enable the "Unique Contacts" button.

+

+ Go to Settings --> Enable "Unique Contacts" button and select Fields. +

+ +
+ +
+

+ Validation alert for duplicate contact values

+

+ When you enter the same value in the contact fields, it raises a validation error message. +

+ +
+ +
+ +
+
+

Suggested Products

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

Our Services

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

Our Industries

+
+
+ +
+
+ +
+ 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

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

Need Help?

+
+
+
+ + +
+ +
+ + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+ + +
\ No newline at end of file diff --git a/duplicate_contact_details_alert/views/res_config_settings_views.xml b/duplicate_contact_details_alert/views/res_config_settings_views.xml new file mode 100644 index 000000000..7a1deb2ac --- /dev/null +++ b/duplicate_contact_details_alert/views/res_config_settings_views.xml @@ -0,0 +1,39 @@ + + + + + res.config.settings.view.form.inherit.duplicate_contact_details_alert + res.config.settings + + + + +
+
+
+
+ +
+
+ Unique Contacts + +
Validation alerts for duplicate contact details
+
+
+
+
+
+
+
+
+
+ +
\ No newline at end of file diff --git a/hide_cost_price/README.rst b/hide_cost_price/README.rst new file mode 100644 index 000000000..51ce09e81 --- /dev/null +++ b/hide_cost_price/README.rst @@ -0,0 +1,41 @@ +Hide Product Cost Price v14 +=========================== + +The cost price of the product will be only visible for the users added in the group "view cost price". +If user is not there in the group, the cost price of the product will remain invisible for the user. +By default administrator will be added to this group + +Depends +======= +[product] addon Odoo + +Tech +==== +* [XML] - Odoo views + +Installation +============ +- www.odoo.com/documentation/14.0/setup/install.html +- Install our custom addon + +License +======= +GNU AGPL, Version 3 (AGPLv3) +(http://www.gnu.org/licenses/agpl.html) + +Bug Tracker +=========== + +Contact odoo@cybrosys.com + +Authors +------- +* Sonu Soman + + +Maintainer +---------- + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit https://www.cybrosys.com. diff --git a/hide_cost_price/__init__.py b/hide_cost_price/__init__.py new file mode 100644 index 000000000..b780467e6 --- /dev/null +++ b/hide_cost_price/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- + +################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2018-TODAY Cybrosys Technologies(). +# Author: Niyas Raphy() +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 . +# +################################################################################### diff --git a/hide_cost_price/__manifest__.py b/hide_cost_price/__manifest__.py new file mode 100644 index 000000000..e7cf0a769 --- /dev/null +++ b/hide_cost_price/__manifest__.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2021-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions() +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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': 'Hide Product Cost Price', + 'summary': """Product Cost Price Will be Visible Only for Specified Group""", + 'version': '14.0.1.0.0', + 'description': """Product cost price will be visible only for specified group""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'https://www.cybrosys.com', + 'category': 'Extra Tools', + 'depends': ['base', 'product'], + 'license': 'AGPL-3', + 'data': [ + 'security/view_cost_price.xml', + 'views/hide_product_cost.xml' + ], + 'images': ['static/description/banner.png'], + 'installable': True, + 'auto_install': False, + +} diff --git a/hide_cost_price/doc/RELEASE_NOTES.md b/hide_cost_price/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..401dc4bd8 --- /dev/null +++ b/hide_cost_price/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 22.07.2021 +#### Version 14.0.1.0.0 +##### ADD +- Initial commit \ No newline at end of file diff --git a/hide_cost_price/security/view_cost_price.xml b/hide_cost_price/security/view_cost_price.xml new file mode 100644 index 000000000..7e9bef790 --- /dev/null +++ b/hide_cost_price/security/view_cost_price.xml @@ -0,0 +1,11 @@ + + + + + + View Cost Price + + + + + \ No newline at end of file diff --git a/hide_cost_price/static/description/assets/icons/chevron.png b/hide_cost_price/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/chevron.png differ diff --git a/hide_cost_price/static/description/assets/icons/cogs.png b/hide_cost_price/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/cogs.png differ diff --git a/hide_cost_price/static/description/assets/icons/consultation.png b/hide_cost_price/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/consultation.png differ diff --git a/hide_cost_price/static/description/assets/icons/ecom-black.png b/hide_cost_price/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/ecom-black.png differ diff --git a/hide_cost_price/static/description/assets/icons/education-black.png b/hide_cost_price/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/education-black.png differ diff --git a/hide_cost_price/static/description/assets/icons/hotel-black.png b/hide_cost_price/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/hotel-black.png differ diff --git a/hide_cost_price/static/description/assets/icons/license.png b/hide_cost_price/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/license.png differ diff --git a/hide_cost_price/static/description/assets/icons/lifebuoy.png b/hide_cost_price/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/lifebuoy.png differ diff --git a/hide_cost_price/static/description/assets/icons/manufacturing-black.png b/hide_cost_price/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/manufacturing-black.png differ diff --git a/hide_cost_price/static/description/assets/icons/pos-black.png b/hide_cost_price/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/pos-black.png differ diff --git a/hide_cost_price/static/description/assets/icons/puzzle.png b/hide_cost_price/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/puzzle.png differ diff --git a/hide_cost_price/static/description/assets/icons/restaurant-black.png b/hide_cost_price/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/restaurant-black.png differ diff --git a/hide_cost_price/static/description/assets/icons/service-black.png b/hide_cost_price/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/service-black.png differ diff --git a/hide_cost_price/static/description/assets/icons/trading-black.png b/hide_cost_price/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/trading-black.png differ diff --git a/hide_cost_price/static/description/assets/icons/training.png b/hide_cost_price/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/training.png differ diff --git a/hide_cost_price/static/description/assets/icons/update.png b/hide_cost_price/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/update.png differ diff --git a/hide_cost_price/static/description/assets/icons/user.png b/hide_cost_price/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/user.png differ diff --git a/hide_cost_price/static/description/assets/icons/wrench.png b/hide_cost_price/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/hide_cost_price/static/description/assets/icons/wrench.png differ diff --git a/hide_cost_price/static/description/banner.png b/hide_cost_price/static/description/banner.png new file mode 100644 index 000000000..855023bfa Binary files /dev/null and b/hide_cost_price/static/description/banner.png differ diff --git a/hide_cost_price/static/description/icon.png b/hide_cost_price/static/description/icon.png new file mode 100644 index 000000000..ccaad58fc Binary files /dev/null and b/hide_cost_price/static/description/icon.png differ diff --git a/hide_cost_price/static/description/images/checked.png b/hide_cost_price/static/description/images/checked.png new file mode 100644 index 000000000..e6c63d582 Binary files /dev/null and b/hide_cost_price/static/description/images/checked.png differ diff --git a/hide_cost_price/static/description/images/hero.png b/hide_cost_price/static/description/images/hero.png new file mode 100644 index 000000000..bcf8f7283 Binary files /dev/null and b/hide_cost_price/static/description/images/hero.png differ diff --git a/hide_cost_price/static/description/images/modules/approval_image.png b/hide_cost_price/static/description/images/modules/approval_image.png new file mode 100644 index 000000000..84fe94e80 Binary files /dev/null and b/hide_cost_price/static/description/images/modules/approval_image.png differ diff --git a/hide_cost_price/static/description/images/modules/dynamic_image.png b/hide_cost_price/static/description/images/modules/dynamic_image.png new file mode 100644 index 000000000..74ce220e6 Binary files /dev/null and b/hide_cost_price/static/description/images/modules/dynamic_image.png differ diff --git a/hide_cost_price/static/description/images/modules/mulitple-ref_image.png b/hide_cost_price/static/description/images/modules/mulitple-ref_image.png new file mode 100644 index 000000000..e0964f1e3 Binary files /dev/null and b/hide_cost_price/static/description/images/modules/mulitple-ref_image.png differ diff --git a/hide_cost_price/static/description/images/modules/pos_image.png b/hide_cost_price/static/description/images/modules/pos_image.png new file mode 100644 index 000000000..c5932894b Binary files /dev/null and b/hide_cost_price/static/description/images/modules/pos_image.png differ diff --git a/hide_cost_price/static/description/images/modules/shopify_image.png b/hide_cost_price/static/description/images/modules/shopify_image.png new file mode 100644 index 000000000..c6d92c16d Binary files /dev/null and b/hide_cost_price/static/description/images/modules/shopify_image.png differ diff --git a/hide_cost_price/static/description/images/screen1.png b/hide_cost_price/static/description/images/screen1.png new file mode 100644 index 000000000..704bb40e5 Binary files /dev/null and b/hide_cost_price/static/description/images/screen1.png differ diff --git a/hide_cost_price/static/description/images/screen2.png b/hide_cost_price/static/description/images/screen2.png new file mode 100644 index 000000000..42f264844 Binary files /dev/null and b/hide_cost_price/static/description/images/screen2.png differ diff --git a/hide_cost_price/static/description/images/screen3.png b/hide_cost_price/static/description/images/screen3.png new file mode 100644 index 000000000..c35575d7f Binary files /dev/null and b/hide_cost_price/static/description/images/screen3.png differ diff --git a/hide_cost_price/static/description/index.html b/hide_cost_price/static/description/index.html new file mode 100644 index 000000000..cf9e68ffd --- /dev/null +++ b/hide_cost_price/static/description/index.html @@ -0,0 +1,535 @@ +
+
+ +
+
+

Hide Product Cost Price

+

+ Cost price will be visible only for selected users

+ +
+
+ + + +
+
+

Overview

+
+

+ With the module create a custom new group, add users to this group and only the memebers of this + group can view the cost price of the product. +

+
+
+ + + + +
+
+

Key Features

+
+
+ + +
+ +
+ +

+ Cost price visibility restricted. +

+
+ +
+ +

+ Visible only for the users in the group. +

+
+
+ +

+ By default administrator will be added to this group. +

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

Screenshots

+
+ + +
+
+

+ 01

+
+
+

+ Adding user to the View Cost Price group +

+

+ User will see the product cost price only if he is added in this group. +

+
+
+ + + + +
+
+

+ 02

+
+
+

+ Product View for users not in the Group +

+

+ Product form view without cost price. +

+ +
+
+ + + +
+
+

+ 03

+
+
+

+ Product tree view without cost price +

+

+ Product tree view without cost price. +

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

Suggested Products

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

Our Services

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

Our Industries

+
+
+ +
+
+ +
+ 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

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

Need Help?

+
+
+
+ + +
+ +
+ + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+ + + +
+
\ No newline at end of file diff --git a/hide_cost_price/views/hide_product_cost.xml b/hide_cost_price/views/hide_product_cost.xml new file mode 100644 index 000000000..5e362858c --- /dev/null +++ b/hide_cost_price/views/hide_product_cost.xml @@ -0,0 +1,60 @@ + + + + + + + product.template.cost + product.template + + + + hide_cost_price.view_cost_price + + + hide_cost_price.view_cost_price + + + + + + + product.product.cost + product.product + + + + hide_cost_price.view_cost_price + + + hide_cost_price.view_cost_price + + + + + + + product.template.cost + product.template + + + + hide_cost_price.view_cost_price + + + + + + + product.product.cost + product.product + + + + hide_cost_price.view_cost_price + + + + + + diff --git a/hide_menu_user/__manifest__.py b/hide_menu_user/__manifest__.py index 05f1d9f78..67ab224ba 100644 --- a/hide_menu_user/__manifest__.py +++ b/hide_menu_user/__manifest__.py @@ -22,7 +22,7 @@ { 'name': 'Hide Any Menu User Wise', - 'version': '14.0.1.0.0', + 'version': '14.0.1.0.1', 'summary': 'Hide Any Menu Item User Wise', 'description': 'Hide Any Menu Item User Wise, Hide Menu Items, Hide Menu', 'author': 'Cybrosys Techno Solutions', diff --git a/hide_menu_user/models/res_user.py b/hide_menu_user/models/res_user.py index f70fb4f46..a0347e276 100644 --- a/hide_menu_user/models/res_user.py +++ b/hide_menu_user/models/res_user.py @@ -22,16 +22,16 @@ from odoo import models, fields, api - class HideMenuUser(models.Model): _inherit = 'res.users' - @api.model - def create(self, vals): + @api.model_create_multi + def create(self, vals_list): """ Else the menu will be still hidden even after removing from the list """ - self.clear_caches() + for vals in vals_list: + self.clear_caches() return super(HideMenuUser, self).create(vals) def write(self, vals): @@ -43,6 +43,7 @@ class HideMenuUser(models.Model): menu.write({ 'restrict_user_ids': [(4, self.id)] }) + print(res,'resssssssssss') self.clear_caches() return res @@ -61,7 +62,6 @@ class HideMenuUser(models.Model): 'hidden to this user ') is_admin = fields.Boolean(compute=_get_is_admin) - class RestrictMenu(models.Model): _inherit = 'ir.ui.menu' diff --git a/hr_payroll_dashboard/__manifest__.py b/hr_payroll_dashboard/__manifest__.py index b21a87a1c..484a7ab9e 100644 --- a/hr_payroll_dashboard/__manifest__.py +++ b/hr_payroll_dashboard/__manifest__.py @@ -21,7 +21,7 @@ ############################################################################# { 'name': "HR Payroll Dashboard", - 'version': '14.0.1.0.0', + 'version': '14.0.1.1.1', 'summary': """HR Payroll Dashboard""", 'description': """HR Payroll Dashboard""", 'category': 'Human Resource', diff --git a/hr_payroll_dashboard/models/employee.py b/hr_payroll_dashboard/models/employee.py index 8ef9bdd78..2e0ce3bf4 100644 --- a/hr_payroll_dashboard/models/employee.py +++ b/hr_payroll_dashboard/models/employee.py @@ -47,37 +47,38 @@ class Employee(models.Model): def get_user_employee_info(self): """To get the employee information""" uid = request.session.uid - employee_id = self.env['hr.employee'].sudo().search([ - ('user_id', '=', uid)], limit=1) + employee_user_id = self.env['hr.employee'].sudo().search([ + ('user_id', '=', uid) + ], limit=1) employee = self.env['hr.employee'].sudo().search_read([ ('user_id', '=', uid)], limit=1) attendance_count = self.env['hr.attendance'].sudo().search( - [('employee_id', '=', employee_id.id), + [('employee_id', '=', employee_user_id.id), ('attendance_date', '=', date.today())]) manager_attendance_count = self.env['hr.attendance'].sudo().search( [('attendance_date', '=', date.today())]) leave_request_count = self.env['hr.leave'].sudo().search( - [('employee_id', '=', employee_id.id), + [('employee_id', '=', employee_user_id.id), ('request_date_from', '=', date.today())]) manager_leave_request = self.env['hr.leave'].sudo().search( [('request_date_from', '=', date.today())]) employee_contracts = self.env['hr.contract'].sudo().search([ - ('employee_id', '=', employee_id.id)]) + ('employee_id', '=', employee_user_id.id)]) payslips = self.env['hr.payslip'].sudo().search([ - ('employee_id', '=', employee_id.id)]) + ('employee_id', '=', employee_user_id.id)]) salary_rules = self.env['hr.salary.rule'].sudo().search([]) salary_structures = self.env['hr.payroll.structure'].sudo().search([]) salary_rule_count = len(salary_rules) salary_structure_count = len(salary_structures) - emp_leave = len(manager_leave_request) if employee_id.is_manager \ + emp_leave = len(manager_leave_request) if employee_user_id.is_manager \ else len(leave_request_count) - payslip_count = len(payslips) if not employee_id.is_manager \ + payslip_count = len(payslips) if not employee_user_id.is_manager \ else len(self.env['hr.payslip'].sudo().search([])) emp_contracts_count = len(employee_contracts) \ - if not employee_id.is_manager else len( + if not employee_user_id.is_manager else len( self.env['hr.contract'].sudo().search([])) attendance_today = len(manager_attendance_count) \ - if employee_id.is_manager else len(attendance_count) + if employee_user_id.is_manager else len(attendance_count) if employee: data = { 'emp_timesheets': attendance_today, @@ -128,20 +129,34 @@ class Employee(models.Model): @api.model def get_department_leave(self): """return department wise leave details""" + employee = False month_list = [] graph_result = [] uid = request.session.uid - employee = self.env['hr.employee'].sudo().search_read([ - ('user_id', '=', uid)], limit=1) + employee_user = self.env['hr.employee'].sudo().search_read([ + ('user_id', '=', uid) + ], limit=1) + employees = self.env['hr.employee'].sudo().search_read([], limit=1) + if employee_user: + employee = self.env['hr.employee'].sudo().search_read([ + ('user_id', '=', uid)], limit=1) + employee_id = self.env['hr.employee'].browse( + employee[0]['id']) + elif employees: + employee = self.env['hr.employee'].sudo().search_read([], limit=1) + employee_id = self.env['hr.employee'].browse( + employee[0]['id']) for i in range(5, -1, -1): last_month = datetime.now() - relativedelta(months=i) text = format(last_month, '%B %Y') month_list.append(text) + self.env.cr.execute("""select id, name from hr_department where active=True""") departments = self.env.cr.dictfetchall() department_list = [x['name'] for x in departments] + for month in month_list: leave = {} for dept in departments: @@ -151,65 +166,81 @@ class Employee(models.Model): 'leave': leave } graph_result.append(vals) - employee_id = self.env['hr.employee'].browse(employee[0]['id']) - - sql = """ - SELECT h.id, h.employee_id,h.department_id - , extract('month' FROM y)::int AS leave_month - , to_char(y, 'Month YYYY') as month_year - , GREATEST(y , h.date_from) AS date_from - , LEAST (y + interval '1 month', h.date_to) AS date_to - FROM (select * from hr_leave where state = 'validate') h - , generate_series(date_trunc('month', date_from::timestamp) - , date_trunc('month', date_to::timestamp) - , interval '1 month') y - where date_trunc('month', GREATEST(y , h.date_from)) >= - date_trunc('month', now()) - interval '6 month' and - date_trunc('month', GREATEST(y , h.date_from)) <= - date_trunc('month', now()) - and h.department_id is not null - """ - self.env.cr.execute(sql) - results = self.env.cr.dictfetchall() - leave_lines = [] - for line in results: - employee = self.browse(line['employee_id']) - from_dt = fields.Datetime.from_string(line['date_from']) - to_dt = fields.Datetime.from_string(line['date_to']) - days = employee.get_work_days_dashboard(from_dt, to_dt) - line['days'] = days - vals = { - 'department': line['department_id'], - 'l_month': line['month_year'], - 'days': days - } - leave_lines.append(vals) - if leave_lines: - df = pd.DataFrame(leave_lines) - rf = df.groupby(['l_month', 'department']).sum() - result_lines = rf.to_dict('index') - for month in month_list: - for line in result_lines: - if month.replace(' ', '') == line[0].replace(' ', ''): - match = list(filter(lambda d: d['l_month'] in [month], - graph_result))[0]['leave'] - dept_name = self.env['hr.department'].browse( - line[1]).name - if match: - match[dept_name] = result_lines[line]['days'] - for result in graph_result: - result['l_month'] = result['l_month'].split(' ')[:1][0].strip()[:3] \ - + " " + result['l_month'].split(' ')[1:2][0] - return graph_result, department_list + if employee: + sql = """ + SELECT h.id, h.employee_id,h.department_id + , extract('month' FROM y)::int AS leave_month + , to_char(y, 'Month YYYY') as month_year + , GREATEST(y , h.date_from) AS date_from + , LEAST (y + interval '1 month', h.date_to) AS date_to + FROM (select * from hr_leave where state = 'validate') h + , generate_series(date_trunc('month', date_from::timestamp) + , date_trunc('month', date_to::timestamp) + , interval '1 month') y + where date_trunc('month', GREATEST(y , h.date_from)) >= + date_trunc('month', now()) - interval '6 month' and + date_trunc('month', GREATEST(y , h.date_from)) <= + date_trunc('month', now()) + and h.department_id is not null + """ + self.env.cr.execute(sql) + results = self.env.cr.dictfetchall() + leave_lines = [] + + for line in results: + employee = self.browse(line['employee_id']) + from_dt = fields.Datetime.from_string(line['date_from']) + to_dt = fields.Datetime.from_string(line['date_to']) + days = employee.get_work_days_dashboard(from_dt, to_dt) + line['days'] = days + vals = { + 'department': line['department_id'], + 'l_month': line['month_year'], + 'days': days + } + leave_lines.append(vals) + + if leave_lines: + df = pd.DataFrame(leave_lines) + rf = df.groupby(['l_month', 'department']).sum() + result_lines = rf.to_dict('index') + for month in month_list: + for line in result_lines: + if month.replace(' ', '') == line[0].replace(' ', ''): + match = list(filter( + lambda d: d['l_month'] in [month], + graph_result))[0]['leave'] + dept_name = self.env['hr.department'].browse( + line[1]).name + if match: + match[dept_name] = result_lines[line]['days'] + + for result in graph_result: + result['l_month'] = result[ + 'l_month' + ].split(' ')[:1][0].strip()[:3] + " " +\ + result['l_month'].split(' ')[1:2][0] + return graph_result, department_list + else: + return False @api.model def get_employee_expense(self): """return employee expense details""" month_list = [] graph_result = [] uid = request.session.uid - employee = self.env['hr.employee'].sudo().search_read([ - ('user_id', '=', uid)], limit=1) + employee = False + employee_user = self.env['hr.employee'].sudo().search_read([ + ('user_id', '=', uid) + ], limit=1) + employees = self.env['hr.employee'].sudo().search_read([], limit=1) + if employee_user: + employee = self.env['hr.employee'].sudo().search_read([ + ('user_id', '=', uid) + ], limit=1) + elif employees: + employees = self.env['hr.employee'].sudo().search_read([], limit=1) for i in range(5, -1, -1): last_month = datetime.now() - relativedelta(months=i) @@ -228,47 +259,50 @@ class Employee(models.Model): 'leave': leave } graph_result.append(vals) - employee_id = self.env['hr.employee'].browse(employee[0]['id']) - - sql = """ - SELECT h.id, h.employee_id,h.date, - extract('month' FROM h.date)::int AS leave_month, - to_char(h.date, 'Month YYYY') as month_year - FROM (select * from hr_expense where state = 'approved') h - """ - self.env.cr.execute(sql, (employee[0]['id'],)) + if employee: + employee_id = self.env['hr.employee'].browse(employee[0]['id']) + + sql = """ + SELECT h.id, h.employee_id,h.date, + extract('month' FROM h.date)::int AS leave_month, + to_char(h.date, 'Month YYYY') as month_year + FROM (select * from hr_expense where state = 'approved') h + """ + self.env.cr.execute(sql, (employee[0]['id'],)) - results = self.env.cr.dictfetchall() - leave_lines = [] - for line in results: - employee = self.browse(line['employee_id']) - from_dt = fields.Datetime.from_string(line['date']) - to_dt = fields.Datetime.from_string(line['date']) - days = employee.get_work_days_dashboard(from_dt, to_dt) - line['days'] = days - vals = { - 'department': line['employee_id'], - 'l_month': line['month_year'], - 'days': days - } - leave_lines.append(vals) - if leave_lines: - df = pd.DataFrame(leave_lines) - rf = df.groupby(['l_month', 'department']).sum() - result_lines = rf.to_dict('index') - for month in month_list: - for line in result_lines: - if month.replace(' ', '') == line[0].replace(' ', ''): - match = list(filter(lambda d: d['l_month'] in [month], - graph_result))[0]['leave'] - dept_name = self.env['hr.department'].browse( - line[1]).name - if match: - match[dept_name] = result_lines[line]['days'] - for result in graph_result: - result['l_month'] = result['l_month'].split(' ')[:1][0].strip()[:3] \ - + " " + result['l_month'].split(' ')[1:2][0] - return graph_result, department_list + results = self.env.cr.dictfetchall() + leave_lines = [] + for line in results: + employee = self.browse(line['employee_id']) + from_dt = fields.Datetime.from_string(line['date']) + to_dt = fields.Datetime.from_string(line['date']) + days = employee.get_work_days_dashboard(from_dt, to_dt) + line['days'] = days + vals = { + 'department': line['employee_id'], + 'l_month': line['month_year'], + 'days': days + } + leave_lines.append(vals) + if leave_lines: + df = pd.DataFrame(leave_lines) + rf = df.groupby(['l_month', 'department']).sum() + result_lines = rf.to_dict('index') + for month in month_list: + for line in result_lines: + if month.replace(' ', '') == line[0].replace(' ', ''): + match = list(filter(lambda d: d['l_month'] in [month], + graph_result))[0]['leave'] + dept_name = self.env['hr.department'].browse( + line[1]).name + if match: + match[dept_name] = result_lines[line]['days'] + for result in graph_result: + result['l_month'] = result['l_month'].split(' ')[:1][0].strip()[:3] \ + + " " + result['l_month'].split(' ')[1:2][0] + return graph_result, department_list + else: + return False @api.model def employee_leave_trend(self): @@ -281,8 +315,19 @@ class Employee(models.Model): text = format(last_month, '%B %Y') month_list.append(text) uid = request.session.uid - employee = self.env['hr.employee'].sudo().search_read([ - ('user_id', '=', uid)], limit=1) + employee = False + employee_user = self.env['hr.employee'].sudo().search_read([ + ('user_id', '=', uid) + ], limit=1) + employees = self.env['hr.employee'].sudo().search_read([], limit=1) + + if employee_user: + employee = self.env['hr.employee'].sudo().search_read([ + ('user_id', '=', uid) + ], limit=1) + elif employees: + employee = self.env['hr.employee'].sudo().search_read([], limit=1) + for month in month_list: vals = { 'l_month': month, @@ -305,32 +350,35 @@ class Employee(models.Model): date_trunc('month', now()) and h.employee_id = %s """ - self.env.cr.execute(sql, (employee[0]['id'],)) - results = self.env.cr.dictfetchall() - for line in results: - employee = self.browse(line['employee_id']) - from_dt = fields.Datetime.from_string(line['date_from']) - to_dt = fields.Datetime.from_string(line['date_to']) - days = employee.get_work_days_dashboard(from_dt, to_dt) - line['days'] = days - vals = { - 'l_month': line['month_year'], - 'days': days - } - leave_lines.append(vals) - if leave_lines: - df = pd.DataFrame(leave_lines) - rf = df.groupby(['l_month']).sum() - result_lines = rf.to_dict('index') - for line in result_lines: - match = list(filter(lambda d: d['l_month'].replace( - ' ', '') == line.replace(' ', ''), graph_result)) - if match: - match[0]['leave'] = result_lines[line]['days'] - for result in graph_result: - result['l_month'] = result['l_month'].split(' ')[:1][0].strip()[:3] \ - + " " + result['l_month'].split(' ')[1:2][0] - return graph_result + if employee: + self.env.cr.execute(sql, (employee[0]['id'],)) + results = self.env.cr.dictfetchall() + for line in results: + employee = self.browse(line['employee_id']) + from_dt = fields.Datetime.from_string(line['date_from']) + to_dt = fields.Datetime.from_string(line['date_to']) + days = employee.get_work_days_dashboard(from_dt, to_dt) + line['days'] = days + vals = { + 'l_month': line['month_year'], + 'days': days + } + leave_lines.append(vals) + if leave_lines: + df = pd.DataFrame(leave_lines) + rf = df.groupby(['l_month']).sum() + result_lines = rf.to_dict('index') + for line in result_lines: + match = list(filter(lambda d: d['l_month'].replace( + ' ', '') == line.replace(' ', ''), graph_result)) + if match: + match[0]['leave'] = result_lines[line]['days'] + for result in graph_result: + result['l_month'] = result['l_month'].split(' ')[:1][0].strip()[:3] \ + + " " + result['l_month'].split(' ')[1:2][0] + return graph_result + else: + return False class Contract(models.Model): @@ -383,47 +431,63 @@ class HrExpense(models.Model): last_month = datetime.now() - relativedelta(months=i) text = format(last_month, '%B %Y') month_list.append(text) + for month in month_list: vals = { 'l_month': month, 'count': 0 } approved_trend.append(vals) + uid = request.session.uid - employee = self.env['hr.employee'].sudo().search_read([ - ('user_id', '=', uid)], limit=1) - employee_id = self.env['hr.employee'].browse(employee[0]['id']) - if not employee_id.is_manager: - sql = ('''select to_char(date, 'Month YYYY') as l_month, - count(id) from hr_expense - WHERE date BETWEEN CURRENT_DATE - INTERVAL '12 months' - AND CURRENT_DATE + interval '1 month - 1 day' - AND hr_expense.employee_id = %s - group by l_month''') - self.env.cr.execute(sql, (employee[0]['id'],)) + employee = False + employee_user = self.env['hr.employee'].sudo().search_read([ + ('user_id', '=', uid) + ], limit=1) + employees = self.env['hr.employee'].sudo().search_read([], limit=1) + + if employee_user: + employee = self.env['hr.employee'].sudo().search_read([ + ('user_id', '=', uid) + ], limit=1) + elif employees: + employee = self.env['hr.employee'].sudo().search_read([], limit=1) + + if employee: + employee_id = self.env['hr.employee'].browse(employee[0]['id']) + if not employee_id.is_manager: + sql = ('''select to_char(date, 'Month YYYY') as l_month, + count(id) from hr_expense + WHERE date BETWEEN CURRENT_DATE - INTERVAL '12 months' + AND CURRENT_DATE + interval '1 month - 1 day' + AND hr_expense.employee_id = %s + group by l_month''') + self.env.cr.execute(sql, (employee[0]['id'],)) + else: + sql = ('''select to_char(date, 'Month YYYY') as l_month, + count(id) from hr_expense WHERE date + BETWEEN CURRENT_DATE - INTERVAL + '12 months' AND CURRENT_DATE + interval '1 month - 1 day' + group by l_month''') + self.env.cr.execute(sql) + approved_data = cr.fetchall() + for line in approved_data: + match = list(filter(lambda d: d['l_month'].replace( + ' ', '') == line[0].replace(' ', ''), approved_trend)) + if match: + match[0]['count'] = line[1] + + for expense in approved_trend: + expense['l_month'] = expense[ + 'l_month'].split(' ')[:1][0].strip()[:3] + + graph_result = [{ + + 'values': approved_trend + }] + return graph_result else: - sql = ('''select to_char(date, 'Month YYYY') as l_month, - count(id) from hr_expense WHERE date - BETWEEN CURRENT_DATE - INTERVAL - '12 months' AND CURRENT_DATE + interval '1 month - 1 day' - group by l_month''') - self.env.cr.execute(sql) - approved_data = cr.fetchall() - for line in approved_data: - match = list(filter(lambda d: d['l_month'].replace( - ' ', '') == line[0].replace(' ', ''), approved_trend)) - if match: - match[0]['count'] = line[1] - - for expense in approved_trend: - expense['l_month'] = expense[ - 'l_month'].split(' ')[:1][0].strip()[:3] - - graph_result = [{ - - 'values': approved_trend - }] - return graph_result + return False class HrAttendance(models.Model): diff --git a/hr_payroll_dashboard/static/src/js/hr_payroll_dashboard.js b/hr_payroll_dashboard/static/src/js/hr_payroll_dashboard.js index c31cc3546..39a84887b 100644 --- a/hr_payroll_dashboard/static/src/js/hr_payroll_dashboard.js +++ b/hr_payroll_dashboard/static/src/js/hr_payroll_dashboard.js @@ -223,80 +223,80 @@ var PayrollDashboard = AbstractAction.extend({ model: "hr.expense", method: "get_employee_expense", }).then(function (data) { - data.forEach(function(d) { - d.values.forEach(function(d) { - d.l_month = d.l_month; - d.count = +d.count; - }); - }); - var margin = {top: 30, right: 10, bottom: 30, left: 30}, - width = 400 - margin.left - margin.right, - height = 250 - margin.top - margin.bottom; - - // Set the ranges - var x = d3.scale.ordinal() - .rangeRoundBands([0, width], 1); - - var y = d3.scale.linear() - .range([height, 0]); - - // Define the axes - var xAxis = d3.svg.axis().scale(x) - .orient("bottom"); - - var yAxis = d3.svg.axis().scale(y) - .orient("left").ticks(5); - - x.domain(data[0].values.map(function(d) { return d.l_month; })); - y.domain([0, d3.max(data[0].values, d => d.count)]) - - var svg = d3.select(elem[0]).append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); - - // Add the X Axis - svg.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0," + height + ")") - .call(xAxis); - - // Add the Y Axis - svg.append("g") - .attr("class", "y axis") - .call(yAxis); - - - var line = d3.svg.line() - .x(function(d) {return x(d.l_month); }) - .y(function(d) {return y(d.count); }); - - let lines = svg.append('g') - .attr('class', 'lines'); - - lines.selectAll('.line-group') - .data(data).enter() - .append('g') - .attr('class', 'line-group') - .append('path') - .attr('class', 'line') - .attr('d', function(d) { return line(d.values); }) - .style('stroke', (d, i) => color(i)); - - lines.selectAll("circle-group") - .data(data).enter() - .append("g") - .selectAll("circle") - .data(function(d) { return d.values;}).enter() - .append("g") - .attr("class", "circle") - .append("circle") - .attr("cx", function(d) { return x(d.l_month)}) - .attr("cy", function(d) { return y(d.count)}) - .attr("r", 3); - - + if(data){ + data.forEach(function(d) { + d.values.forEach(function(d) { + d.l_month = d.l_month; + d.count = +d.count; + }); + }); + var margin = {top: 30, right: 10, bottom: 30, left: 30}, + width = 400 - margin.left - margin.right, + height = 250 - margin.top - margin.bottom; + + // Set the ranges + var x = d3.scale.ordinal() + .rangeRoundBands([0, width], 1); + + var y = d3.scale.linear() + .range([height, 0]); + + // Define the axes + var xAxis = d3.svg.axis().scale(x) + .orient("bottom"); + + var yAxis = d3.svg.axis().scale(y) + .orient("left").ticks(5); + + x.domain(data[0].values.map(function(d) { return d.l_month; })); + y.domain([0, d3.max(data[0].values, d => d.count)]) + + var svg = d3.select(elem[0]).append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + // Add the X Axis + svg.append("g") + .attr("class", "x axis") + .attr("transform", "translate(0," + height + ")") + .call(xAxis); + + // Add the Y Axis + svg.append("g") + .attr("class", "y axis") + .call(yAxis); + + + var line = d3.svg.line() + .x(function(d) {return x(d.l_month); }) + .y(function(d) {return y(d.count); }); + + let lines = svg.append('g') + .attr('class', 'lines'); + + lines.selectAll('.line-group') + .data(data).enter() + .append('g') + .attr('class', 'line-group') + .append('path') + .attr('class', 'line') + .attr('d', function(d) { return line(d.values); }) + .style('stroke', (d, i) => color(i)); + + lines.selectAll("circle-group") + .data(data).enter() + .append("g") + .selectAll("circle") + .data(function(d) { return d.values;}).enter() + .append("g") + .attr("class", "circle") + .append("circle") + .attr("cx", function(d) { return x(d.l_month)}) + .attr("cy", function(d) { return y(d.count)}) + .attr("r", 3); + } }); }, @@ -309,212 +309,214 @@ var PayrollDashboard = AbstractAction.extend({ model: "hr.employee", method: "get_department_leave", }).then(function (data) { - var fData = data[0]; - var dept = data[1]; - var id = self.$('.leave_graph')[0]; - var barColor = '#ff618a'; - fData.forEach(function(d){ - var total = 0; - for (var dpt in dept){ - total += d.leave[dept[dpt]]; - } - d.total=total; - }); - - // function to handle histogram. - function histoGram(fD){ - var hG={}, hGDim = {t: 60, r: 0, b: 30, l: 0}; - hGDim.w = 350 - hGDim.l - hGDim.r, - hGDim.h = 200 - hGDim.t - hGDim.b; - - //create svg for histogram. - var hGsvg = d3.select(id).append("svg") - .attr("width", hGDim.w + hGDim.l + hGDim.r) - .attr("height", hGDim.h + hGDim.t + hGDim.b).append("g") - .attr("transform", "translate(" + hGDim.l + "," + hGDim.t + ")"); - - // create function for x-axis mapping. - var x = d3.scale.ordinal().rangeRoundBands([0, hGDim.w], 0.1) - .domain(fD.map(function(d) { return d[0]; })); - - // Add x-axis to the histogram svg. - hGsvg.append("g").attr("class", "x axis") - .attr("transform", "translate(0," + hGDim.h + ")") - .call(d3.svg.axis().scale(x).orient("bottom")); - - // Create function for y-axis map. - var y = d3.scale.linear().range([hGDim.h, 0]) - .domain([0, d3.max(fD, function(d) { return d[1]; })]); - - // Create bars for histogram to contain rectangles and freq labels. - var bars = hGsvg.selectAll(".bar").data(fD).enter() - .append("g").attr("class", "bar"); - - //create the rectangles. - bars.append("rect") - .attr("x", function(d) { return x(d[0]); }) - .attr("y", function(d) { return y(d[1]); }) - .attr("width", x.rangeBand()) - .attr("height", function(d) { return hGDim.h - y(d[1]); }) - .attr('fill',barColor) - .on("mouseover",mouseover)// mouseover is defined below. - .on("mouseout",mouseout);// mouseout is defined below. - - //Create the frequency labels above the rectangles. - bars.append("text").text(function(d){ return d3.format(",")(d[1])}) - .attr("x", function(d) { return x(d[0])+x.rangeBand()/2; }) - .attr("y", function(d) { return y(d[1])-5; }) - .attr("text-anchor", "middle"); - - function mouseover(d){ // utility function to be called on mouseover. - // filter for selected state. - var st = fData.filter(function(s){ return s.l_month == d[0];})[0], - nD = d3.keys(st.leave).map(function(s){ return {type:s, leave:st.leave[s]};}); - - // call update functions of pie-chart and legend. - pC.update(nD); - leg.update(nD); - } - - function mouseout(d){ // utility function to be called on mouseout. - // reset the pie-chart and legend. - pC.update(tF); - leg.update(tF); - } - - // create function to update the bars. This will be used by pie-chart. - hG.update = function(nD, color){ - // update the domain of the y-axis map to reflect change in frequencies. - y.domain([0, d3.max(nD, function(d) { return d[1]; })]); - - // Attach the new data to the bars. - var bars = hGsvg.selectAll(".bar").data(nD); - - // transition the height and color of rectangles. - bars.select("rect").transition().duration(500) - .attr("y", function(d) {return y(d[1]); }) + if (data){ + var fData = data[0]; + var dept = data[1]; + var id = self.$('.leave_graph')[0]; + var barColor = '#ff618a'; + fData.forEach(function(d){ + var total = 0; + for (var dpt in dept){ + total += d.leave[dept[dpt]]; + } + d.total=total; + }); + + // function to handle histogram. + function histoGram(fD){ + var hG={}, hGDim = {t: 60, r: 0, b: 30, l: 0}; + hGDim.w = 350 - hGDim.l - hGDim.r, + hGDim.h = 200 - hGDim.t - hGDim.b; + + //create svg for histogram. + var hGsvg = d3.select(id).append("svg") + .attr("width", hGDim.w + hGDim.l + hGDim.r) + .attr("height", hGDim.h + hGDim.t + hGDim.b).append("g") + .attr("transform", "translate(" + hGDim.l + "," + hGDim.t + ")"); + + // create function for x-axis mapping. + var x = d3.scale.ordinal().rangeRoundBands([0, hGDim.w], 0.1) + .domain(fD.map(function(d) { return d[0]; })); + + // Add x-axis to the histogram svg. + hGsvg.append("g").attr("class", "x axis") + .attr("transform", "translate(0," + hGDim.h + ")") + .call(d3.svg.axis().scale(x).orient("bottom")); + + // Create function for y-axis map. + var y = d3.scale.linear().range([hGDim.h, 0]) + .domain([0, d3.max(fD, function(d) { return d[1]; })]); + + // Create bars for histogram to contain rectangles and freq labels. + var bars = hGsvg.selectAll(".bar").data(fD).enter() + .append("g").attr("class", "bar"); + + //create the rectangles. + bars.append("rect") + .attr("x", function(d) { return x(d[0]); }) + .attr("y", function(d) { return y(d[1]); }) + .attr("width", x.rangeBand()) .attr("height", function(d) { return hGDim.h - y(d[1]); }) - .attr("fill", color); - - // transition the frequency labels location and change value. - bars.select("text").transition().duration(500) - .text(function(d){ return d3.format(",")(d[1])}) - .attr("y", function(d) {return y(d[1])-5; }); + .attr('fill',barColor) + .on("mouseover",mouseover)// mouseover is defined below. + .on("mouseout",mouseout);// mouseout is defined below. + + //Create the frequency labels above the rectangles. + bars.append("text").text(function(d){ return d3.format(",")(d[1])}) + .attr("x", function(d) { return x(d[0])+x.rangeBand()/2; }) + .attr("y", function(d) { return y(d[1])-5; }) + .attr("text-anchor", "middle"); + + function mouseover(d){ // utility function to be called on mouseover. + // filter for selected state. + var st = fData.filter(function(s){ return s.l_month == d[0];})[0], + nD = d3.keys(st.leave).map(function(s){ return {type:s, leave:st.leave[s]};}); + + // call update functions of pie-chart and legend. + pC.update(nD); + leg.update(nD); + } + + function mouseout(d){ // utility function to be called on mouseout. + // reset the pie-chart and legend. + pC.update(tF); + leg.update(tF); + } + + // create function to update the bars. This will be used by pie-chart. + hG.update = function(nD, color){ + // update the domain of the y-axis map to reflect change in frequencies. + y.domain([0, d3.max(nD, function(d) { return d[1]; })]); + + // Attach the new data to the bars. + var bars = hGsvg.selectAll(".bar").data(nD); + + // transition the height and color of rectangles. + bars.select("rect").transition().duration(500) + .attr("y", function(d) {return y(d[1]); }) + .attr("height", function(d) { return hGDim.h - y(d[1]); }) + .attr("fill", color); + + // transition the frequency labels location and change value. + bars.select("text").transition().duration(500) + .text(function(d){ return d3.format(",")(d[1])}) + .attr("y", function(d) {return y(d[1])-5; }); + } + return hG; } - return hG; - } - - // function to handle pieChart. - function pieChart(pD){ - var pC ={}, pieDim ={w:250, h: 250}; - pieDim.r = Math.min(pieDim.w, pieDim.h) / 2; - - // create svg for pie chart. - var piesvg = d3.select(id).append("svg") - .attr("width", pieDim.w).attr("height", pieDim.h).append("g") - .attr("transform", "translate("+pieDim.w/2+","+pieDim.h/2+")"); - - // create function to draw the arcs of the pie slices. - var arc = d3.svg.arc().outerRadius(pieDim.r - 10).innerRadius(0); - // create a function to compute the pie slice angles. - var pie = d3.layout.pie().sort(null).value(function(d) { return d.leave; }); - - // Draw the pie slices. - piesvg.selectAll("path").data(pie(pD)).enter().append("path").attr("d", arc) - .each(function(d) { this._current = d; }) - .attr("fill", function(d, i){return color(i);}) - .on("mouseover",mouseover).on("mouseout",mouseout); - - // create function to update pie-chart. This will be used by histogram. - pC.update = function(nD){ - piesvg.selectAll("path").data(pie(nD)).transition().duration(500) - .attrTween("d", arcTween); - } - // Utility function to be called on mouseover a pie slice. - function mouseover(d, i){ - // call the update function of histogram with new data. - hG.update(fData.map(function(v){ - return [v.l_month,v.leave[d.data.type]];}),color(i)); + // function to handle pieChart. + function pieChart(pD){ + var pC ={}, pieDim ={w:250, h: 250}; + pieDim.r = Math.min(pieDim.w, pieDim.h) / 2; + + // create svg for pie chart. + var piesvg = d3.select(id).append("svg") + .attr("width", pieDim.w).attr("height", pieDim.h).append("g") + .attr("transform", "translate("+pieDim.w/2+","+pieDim.h/2+")"); + + // create function to draw the arcs of the pie slices. + var arc = d3.svg.arc().outerRadius(pieDim.r - 10).innerRadius(0); + + // create a function to compute the pie slice angles. + var pie = d3.layout.pie().sort(null).value(function(d) { return d.leave; }); + + // Draw the pie slices. + piesvg.selectAll("path").data(pie(pD)).enter().append("path").attr("d", arc) + .each(function(d) { this._current = d; }) + .attr("fill", function(d, i){return color(i);}) + .on("mouseover",mouseover).on("mouseout",mouseout); + + // create function to update pie-chart. This will be used by histogram. + pC.update = function(nD){ + piesvg.selectAll("path").data(pie(nD)).transition().duration(500) + .attrTween("d", arcTween); + } + // Utility function to be called on mouseover a pie slice. + function mouseover(d, i){ + // call the update function of histogram with new data. + hG.update(fData.map(function(v){ + return [v.l_month,v.leave[d.data.type]];}),color(i)); + } + //Utility function to be called on mouseout a pie slice. + function mouseout(d){ + // call the update function of histogram with all data. + hG.update(fData.map(function(v){ + return [v.l_month,v.total];}), barColor); + + } + // Animating the pie-slice requiring a custom function which specifies + // how the intermediate paths should be drawn. + function arcTween(a) { + var i = d3.interpolate(this._current, a); + this._current = i(0); + return function(t) { return arc(i(t)); }; + } + return pC; } - //Utility function to be called on mouseout a pie slice. - function mouseout(d){ - // call the update function of histogram with all data. - hG.update(fData.map(function(v){ - return [v.l_month,v.total];}), barColor); - } - // Animating the pie-slice requiring a custom function which specifies - // how the intermediate paths should be drawn. - function arcTween(a) { - var i = d3.interpolate(this._current, a); - this._current = i(0); - return function(t) { return arc(i(t)); }; - } - return pC; - } + // function to handle legend. + function legend(lD){ + var leg = {}; -// function to handle legend. - function legend(lD){ - var leg = {}; + // create table for legend. + var legend = d3.select(id).append("table").attr('class','legend'); - // create table for legend. - var legend = d3.select(id).append("table").attr('class','legend'); + // create one row per segment. + var tr = legend.append("tbody").selectAll("tr").data(lD).enter().append("tr"); - // create one row per segment. - var tr = legend.append("tbody").selectAll("tr").data(lD).enter().append("tr"); + // create the first column for each segment. + tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") + .attr("width", '16').attr("height", '16') + .attr("fill", function(d, i){return color(i);}) - // create the first column for each segment. - tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") - .attr("width", '16').attr("height", '16') - .attr("fill", function(d, i){return color(i);}) + // create the second column for each segment. + tr.append("td").text(function(d){ return d.type;}); - // create the second column for each segment. - tr.append("td").text(function(d){ return d.type;}); + // create the third column for each segment. + tr.append("td").attr("class",'legendFreq') + .text(function(d){ return d.l_month;}); - // create the third column for each segment. - tr.append("td").attr("class",'legendFreq') - .text(function(d){ return d.l_month;}); + // create the fourth column for each segment. + tr.append("td").attr("class",'legendPerc') + .text(function(d){ return getLegend(d,lD);}); - // create the fourth column for each segment. - tr.append("td").attr("class",'legendPerc') - .text(function(d){ return getLegend(d,lD);}); + // Utility function to be used to update the legend. + leg.update = function(nD){ + // update the data attached to the row elements. + var l = legend.select("tbody").selectAll("tr").data(nD); - // Utility function to be used to update the legend. - leg.update = function(nD){ - // update the data attached to the row elements. - var l = legend.select("tbody").selectAll("tr").data(nD); + // update the frequencies. + l.select(".legendFreq").text(function(d){ return d3.format(",")(d.leave);}); - // update the frequencies. - l.select(".legendFreq").text(function(d){ return d3.format(",")(d.leave);}); + // update the percentage column. + l.select(".legendPerc").text(function(d){ return getLegend(d,nD);}); + } - // update the percentage column. - l.select(".legendPerc").text(function(d){ return getLegend(d,nD);}); - } + function getLegend(d,aD){ // Utility function to compute percentage. + var perc = (d.leave/d3.sum(aD.map(function(v){ return v.leave; }))); + if (isNaN(perc)){ + return d3.format("%")(0); + } + else{ + return d3.format("%")(d.leave/d3.sum(aD.map(function(v){ return v.leave; }))); + } + } - function getLegend(d,aD){ // Utility function to compute percentage. - var perc = (d.leave/d3.sum(aD.map(function(v){ return v.leave; }))); - if (isNaN(perc)){ - return d3.format("%")(0); - } - else{ - return d3.format("%")(d.leave/d3.sum(aD.map(function(v){ return v.leave; }))); - } + return leg; } + // calculate total frequency by segment for all state. + var tF = dept.map(function(d){ + return {type:d, leave: d3.sum(fData.map(function(t){ return t.leave[d];}))}; + }); - return leg; - } - // calculate total frequency by segment for all state. - var tF = dept.map(function(d){ - return {type:d, leave: d3.sum(fData.map(function(t){ return t.leave[d];}))}; - }); - - // calculate total frequency by state for all segment. - var sF = fData.map(function(d){return [d.l_month,d.total];}); + // calculate total frequency by state for all segment. + var sF = fData.map(function(d){return [d.l_month,d.total];}); - var hG = histoGram(sF), // create the histogram. - pC = pieChart(tF), // create the pie-chart. - leg= legend(tF); // create the legend. + var hG = histoGram(sF), // create the histogram. + pC = pieChart(tF), // create the pie-chart. + leg= legend(tF); // create the legend. + } }); }, render_graphs: function(){ @@ -543,36 +545,37 @@ var PayrollDashboard = AbstractAction.extend({ method: "get_employee_time_off", }).then(function (data) { - var segColor = {}; - var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); - var pie = d3.layout.pie().value(function(d){return d.value;}); - var arc = d3.svg.arc().outerRadius(r); - var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); - arcs.append("svg:path") - .attr("fill", function(d, i){ - return color(i); - }) - .attr("d", function (d) { - return arc(d); - }); - - var legend = d3.select(elem[0]).append("table").attr('class','legend'); - - // create one row per segment. - var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); - - // create the first column for each segment. - tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") - .attr("width", '16').attr("height", '16') - .attr("fill",function(d, i){ return color(i) }); - - // create the second column for each segment. - tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); - - // create the third column for each segment. - tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") - .text(function(d){ return d.value;}); - + if (data){ + var segColor = {}; + var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); + var pie = d3.layout.pie().value(function(d){return d.value;}); + var arc = d3.svg.arc().outerRadius(r); + var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); + arcs.append("svg:path") + .attr("fill", function(d, i){ + return color(i); + }) + .attr("d", function (d) { + return arc(d); + }); + + var legend = d3.select(elem[0]).append("table").attr('class','legend'); + + // create one row per segment. + var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); + + // create the first column for each segment. + tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") + .attr("width", '16').attr("height", '16') + .attr("fill",function(d, i){ return color(i) }); + + // create the second column for each segment. + tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); + + // create the third column for each segment. + tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") + .text(function(d){ return d.value;}); + } }); }, @@ -590,35 +593,37 @@ var PayrollDashboard = AbstractAction.extend({ model: "hr.payslip", method: "get_employee_payslips", }).then(function (data) { - var segColor = {}; - var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); - var pie = d3.layout.pie().value(function(d){return d.value;}); - var arc = d3.svg.arc().outerRadius(r); - var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); - arcs.append("svg:path") - .attr("fill", function(d, i){ - return color(i); - }) - .attr("d", function (d) { - return arc(d); - }); - - var legend = d3.select(elem[0]).append("table").attr('class','legend'); - - // create one row per segment. - var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); - - // create the first column for each segment. - tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") - .attr("width", '16').attr("height", '16') - .attr("fill",function(d, i){ return color(i) }); - - // create the second column for each segment. - tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); - - // create the third column for each segment. - tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") - .text(function(d){ return d.value;}); + if(data){ + var segColor = {}; + var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); + var pie = d3.layout.pie().value(function(d){return d.value;}); + var arc = d3.svg.arc().outerRadius(r); + var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); + arcs.append("svg:path") + .attr("fill", function(d, i){ + return color(i); + }) + .attr("d", function (d) { + return arc(d); + }); + + var legend = d3.select(elem[0]).append("table").attr('class','legend'); + + // create one row per segment. + var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); + + // create the first column for each segment. + tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") + .attr("width", '16').attr("height", '16') + .attr("fill",function(d, i){ return color(i) }); + + // create the second column for each segment. + tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); + + // create the third column for each segment. + tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") + .text(function(d){ return d.value;}); + } }); }, @@ -636,35 +641,37 @@ var PayrollDashboard = AbstractAction.extend({ model: "hr.contract", method: "get_employee_contract", }).then(function (data) { - var segColor = {}; - var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); - var pie = d3.layout.pie().value(function(d){return d.value;}); - var arc = d3.svg.arc().outerRadius(r); - var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); - arcs.append("svg:path") - .attr("fill", function(d, i){ - return color(i); - }) - .attr("d", function (d) { - return arc(d); - }); - - var legend = d3.select(elem[0]).append("table").attr('class','legend'); - - // create one row per segment. - var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); - - // create the first column for each segment. - tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") - .attr("width", '16').attr("height", '16') - .attr("fill",function(d, i){ return color(i) }); - - // create the second column for each segment. - tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); - - // create the third column for each segment. - tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") - .text(function(d){ return d.value;}); + if(data){ + var segColor = {}; + var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); + var pie = d3.layout.pie().value(function(d){return d.value;}); + var arc = d3.svg.arc().outerRadius(r); + var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); + arcs.append("svg:path") + .attr("fill", function(d, i){ + return color(i); + }) + .attr("d", function (d) { + return arc(d); + }); + + var legend = d3.select(elem[0]).append("table").attr('class','legend'); + + // create one row per segment. + var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); + + // create the first column for each segment. + tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") + .attr("width", '16').attr("height", '16') + .attr("fill",function(d, i){ return color(i) }); + + // create the second column for each segment. + tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); + + // create the third column for each segment. + tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") + .text(function(d){ return d.value;}); + } }); }, @@ -674,93 +681,94 @@ var PayrollDashboard = AbstractAction.extend({ model: "hr.employee", method: "employee_leave_trend", }).then(function (data) { - var elem = self.$('.leave_trend'); - var margin = {top: 30, right: 20, bottom: 30, left: 80}, - width = 500 - margin.left - margin.right, - height = 250 - margin.top - margin.bottom; - - // Set the ranges - var x = d3.scale.ordinal() - .rangeRoundBands([0, width], 1); - - var y = d3.scale.linear() - .range([height, 0]); - - // Define the axes - var xAxis = d3.svg.axis().scale(x) - .orient("bottom"); - - var yAxis = d3.svg.axis().scale(y) - .orient("left").ticks(5); - - var valueline = d3.svg.line() - .x(function(d) { return x(d.l_month); }) - .y(function(d) { return y(d.leave); }); - - - var svg = d3.select(elem[0]).append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); - - x.domain(data.map(function(d) { return d.l_month; })); - y.domain([0, d3.max(data, function(d) { return d.leave; })]); - - // Add the X Axis - svg.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0," + height + ")") - .call(xAxis); - - // Add the Y Axis - svg.append("g") - .attr("class", "y axis") - .call(yAxis); - - svg.append("path") - .attr("class", "line") - .attr("d", valueline(data)); - - // Add the scatterplot - svg.selectAll("dot") - .data(data) - .enter().append("circle") - .attr("r", 3) - .attr("cx", function(d) { return x(d.l_month); }) - .attr("cy", function(d) { return y(d.leave); }) -// .on('mouseover', function() { d3.select(this).transition().duration(500).ease("elastic").attr('r', 3 * 2) }) -// .on('mouseout', function() { d3.select(this).transition().duration(500).ease("in-out").attr('r', 3) }); - .on("mouseover", function() { tooltip.style("display", null); - d3.select(this).transition().duration(500).ease("elastic").attr('r', 3 * 2) - }) - .on("mouseout", function() { tooltip.style("display", "none"); - d3.select(this).transition().duration(500).ease("in-out").attr('r', 3) - }) - .on("mousemove", function(d) { - var xPosition = d3.mouse(this)[0] - 15; - var yPosition = d3.mouse(this)[1] - 25; - tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")"); - tooltip.select("text").text(d.leave); - }); - - var tooltip = svg.append("g") - .attr("class", "tooltip") - .style("display", "none"); - - tooltip.append("rect") - .attr("width", 30) - .attr("height", 20) - .attr("fill", "black") - .style("opacity", 0.5); - - tooltip.append("text") - .attr("x", 15) - .attr("dy", "1.2em") - .style("text-anchor", "middle") - .attr("font-size", "12px") - .attr("font-weight", "bold"); - + if(data){ + var elem = self.$('.leave_trend'); + var margin = {top: 30, right: 20, bottom: 30, left: 80}, + width = 500 - margin.left - margin.right, + height = 250 - margin.top - margin.bottom; + + // Set the ranges + var x = d3.scale.ordinal() + .rangeRoundBands([0, width], 1); + + var y = d3.scale.linear() + .range([height, 0]); + + // Define the axes + var xAxis = d3.svg.axis().scale(x) + .orient("bottom"); + + var yAxis = d3.svg.axis().scale(y) + .orient("left").ticks(5); + + var valueline = d3.svg.line() + .x(function(d) { return x(d.l_month); }) + .y(function(d) { return y(d.leave); }); + + + var svg = d3.select(elem[0]).append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + x.domain(data.map(function(d) { return d.l_month; })); + y.domain([0, d3.max(data, function(d) { return d.leave; })]); + + // Add the X Axis + svg.append("g") + .attr("class", "x axis") + .attr("transform", "translate(0," + height + ")") + .call(xAxis); + + // Add the Y Axis + svg.append("g") + .attr("class", "y axis") + .call(yAxis); + + svg.append("path") + .attr("class", "line") + .attr("d", valueline(data)); + + // Add the scatterplot + svg.selectAll("dot") + .data(data) + .enter().append("circle") + .attr("r", 3) + .attr("cx", function(d) { return x(d.l_month); }) + .attr("cy", function(d) { return y(d.leave); }) + // .on('mouseover', function() { d3.select(this).transition().duration(500).ease("elastic").attr('r', 3 * 2) }) + // .on('mouseout', function() { d3.select(this).transition().duration(500).ease("in-out").attr('r', 3) }); + .on("mouseover", function() { tooltip.style("display", null); + d3.select(this).transition().duration(500).ease("elastic").attr('r', 3 * 2) + }) + .on("mouseout", function() { tooltip.style("display", "none"); + d3.select(this).transition().duration(500).ease("in-out").attr('r', 3) + }) + .on("mousemove", function(d) { + var xPosition = d3.mouse(this)[0] - 15; + var yPosition = d3.mouse(this)[1] - 25; + tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")"); + tooltip.select("text").text(d.leave); + }); + + var tooltip = svg.append("g") + .attr("class", "tooltip") + .style("display", "none"); + + tooltip.append("rect") + .attr("width", 30) + .attr("height", 20) + .attr("fill", "black") + .style("opacity", 0.5); + + tooltip.append("text") + .attr("x", 15) + .attr("dy", "1.2em") + .style("text-anchor", "middle") + .attr("font-size", "12px") + .attr("font-weight", "bold"); + } }); }, diff --git a/hr_payroll_dashboard/static/src/xml/payroll_dashboard.xml b/hr_payroll_dashboard/static/src/xml/payroll_dashboard.xml index e000f4cbe..2247b1b29 100644 --- a/hr_payroll_dashboard/static/src/xml/payroll_dashboard.xml +++ b/hr_payroll_dashboard/static/src/xml/payroll_dashboard.xml @@ -6,6 +6,20 @@ + +
+
+
+
+
+

Error : Could not find employee linked to user

+

Please contact system admin for the setup

+
+
+
+
+
+
@@ -83,7 +97,7 @@
- +
Salary Rules
@@ -100,7 +114,7 @@
- +
Salary Structures
@@ -175,8 +189,8 @@ -

-

+
+
diff --git a/insta_feed_snippet/README.rst b/insta_feed_snippet/README.rst new file mode 100644 index 000000000..b88228f34 --- /dev/null +++ b/insta_feed_snippet/README.rst @@ -0,0 +1,44 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Insta Feed Snippet +=================== + +Insta Feed Snippet + +Installation +============ +- www.odoo.com/documentation/15.0/setup/install.html +- Install our custom addon + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developer: + vishnu@cybrosys.info + Version 14.0.1.0.0: + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ diff --git a/insta_feed_snippet/__init__.py b/insta_feed_snippet/__init__.py new file mode 100644 index 000000000..f7209b171 --- /dev/null +++ b/insta_feed_snippet/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import controllers diff --git a/insta_feed_snippet/__manifest__.py b/insta_feed_snippet/__manifest__.py new file mode 100644 index 000000000..f5fb4254a --- /dev/null +++ b/insta_feed_snippet/__manifest__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +{ + 'name': 'Instagram Feed Snippet', + 'version': '14.0.1.0.0', + 'summary': 'Instagram Feed Snippet', + 'description': """Instagram Feed Snippet""", + 'category': 'Website', + 'author': "Cybrosys Techno Solutions", + 'website': "https://www.cybrosys.com", + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'license': 'LGPL-3', + 'depends': ['base', 'product', 'website', 'website_sale', 'sale'], + 'data': ['security/ir.model.access.csv', + 'views/insta_post.xml', + 'views/insta_profile.xml', + 'views/snippet_structure_inherit.xml', + 'views/website.xml' + ], + 'installable': True, + 'application': True, + 'auto_install': False, + +} diff --git a/insta_feed_snippet/controllers/__init__.py b/insta_feed_snippet/controllers/__init__.py new file mode 100644 index 000000000..deec4a8b8 --- /dev/null +++ b/insta_feed_snippet/controllers/__init__.py @@ -0,0 +1 @@ +from . import main \ No newline at end of file diff --git a/insta_feed_snippet/controllers/main.py b/insta_feed_snippet/controllers/main.py new file mode 100644 index 000000000..66d035fcd --- /dev/null +++ b/insta_feed_snippet/controllers/main.py @@ -0,0 +1,30 @@ +from odoo import http +from odoo.http import request +import time + + +class DashbaordCarousel(http.Controller): + @http.route('/get_dashbaord_carousel', auth="public", type='json') + def get_dashbaord_carousel(self): + events_per_slide = 3 + records = request.env['insta.post'].sudo().search( + []) + records_grouped = [] + record_list = [] + for index, record in enumerate(records, 1): + record_list.append(record) + if index % events_per_slide == 0: + records_grouped.append(record_list) + record_list = [] + if any(record_list): + records_grouped.append(record_list) + values = { + "objects": records_grouped, + "events_per_slide": events_per_slide, + "num_slides": len(records_grouped), + "uniqueId": "pc-%d" % int(time.time() * 1000), + } + print(len(records_grouped)) + response = http.Response( + template='insta_feed_snippet.s_carousel_template_items', qcontext=values) + return response.render() diff --git a/insta_feed_snippet/doc/RELEASE_NOTES.md b/insta_feed_snippet/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..f1f1465e2 --- /dev/null +++ b/insta_feed_snippet/doc/RELEASE_NOTES.md @@ -0,0 +1,7 @@ +## Module + +#### 09.11.2022 +#### Version 14.0.1.0.0 +#### ADD +Initial Commit + diff --git a/insta_feed_snippet/models/__init__.py b/insta_feed_snippet/models/__init__.py new file mode 100644 index 000000000..c70d72b19 --- /dev/null +++ b/insta_feed_snippet/models/__init__.py @@ -0,0 +1,2 @@ +from . import insta_profile +from . import insta_post diff --git a/insta_feed_snippet/models/insta_post.py b/insta_feed_snippet/models/insta_post.py new file mode 100644 index 000000000..caf4bcd5b --- /dev/null +++ b/insta_feed_snippet/models/insta_post.py @@ -0,0 +1,27 @@ +from odoo import models, fields, api, _ +import requests + +from odoo.exceptions import UserError + + +class InstaPost(models.Model): + _name = 'insta.post' + + name = fields.Char(string="Media ID") + caption = fields.Char("Caption") + post_image = fields.Binary(string='Post Image', attachment=True) + profile_id = fields.Many2one('insta.profile') + + def action_update_post(self, access_token): + + url = 'https://graph.facebook.com/v15.0/%s?fields=id,caption,comments_count,is_comment_enabled,like_count,media_product_type,media_type,media_url,owner,permalink,thumbnail_url,timestamp,username&access_token=%s' % ( + self.name, access_token) + media_content = requests.get(url, timeout=5).json() + if not media_content.get('error'): + if media_content.get('caption'): + self.write({ + 'caption': media_content['caption'], + + }) + else: + raise UserError(_('%s', media_content['error']['message'])) diff --git a/insta_feed_snippet/models/insta_profile.py b/insta_feed_snippet/models/insta_profile.py new file mode 100644 index 000000000..b1f0df361 --- /dev/null +++ b/insta_feed_snippet/models/insta_profile.py @@ -0,0 +1,81 @@ +import base64 +from odoo import models, fields, api, _ +import requests + +from odoo.exceptions import UserError + + +class InstaProfile(models.Model): + _name = 'insta.profile' + + name = fields.Char(string="Name", readonly=True) + access_token = fields.Text("Access Token") + username = fields.Char('Username', readonly=True) + account_id = fields.Char('Account ID', readonly=True) + profile_image_url = fields.Binary(attachment=True) + + def action_fetch(self): + url = 'https://graph.facebook.com/v15.0/me/accounts?access_token=%s' % self.access_token + page = requests.get(url) + page_content = page.json() + if not page_content.get('error'): + if page_content['data'][0]['id']: + url = 'https://graph.facebook.com/v14.0/%s?fields=instagram_business_account&access_token=%s' % ( + page_content['data'][0]['id'], self.access_token) + business_account = requests.get(url) + instagram_business_account = business_account.json()['instagram_business_account']['id'] + url = 'https://graph.facebook.com/v15.0/%s?fields=name,username,biography,website,followers_count,follows_count,media_count,profile_picture_url&access_token=%s' % ( + instagram_business_account, self.access_token) + val = requests.get(url) + content = val.json() + if content.get('name'): + self.name = content['name'] + if content.get('username'): + self.username = content['username'] + if content.get('id'): + self.account_id = content['id'] + if content.get('profile_picture_url'): + img = base64.b64encode(requests.get(content['profile_picture_url']).content) + self.profile_image_url = img + + else: + raise UserError(_('%s', page_content['error']['message'])) + + def action_get_post(self): + url = 'https://graph.facebook.com/v15.0/%s/media?access_token=%s' % (self.account_id, self.access_token) + content = requests.get(url, timeout=5).json() + if not content.get('error'): + post_list = [] + records = self.env['insta.post'].search([]) + for post in records: + post_list.append(post.name) + if content.get('data'): + for vals in content['data']: + if vals['id'] not in post_list: + url = 'https://graph.facebook.com/v14.0/%s?fields=id,caption,comments_count,is_comment_enabled,like_count,media_product_type,media_type,media_url,owner,permalink,thumbnail_url,timestamp,username&access_token=%s' % ( + vals['id'], self.access_token) + media_content = requests.get(url, timeout=5).json() + + if media_content.get('media_type'): + if media_content['media_type'] == 'IMAGE': + res = self.env['insta.post'].create({ + 'name': media_content['id'], + 'profile_id':self.id, + }) + + image_data = base64.b64encode(requests.get(media_content['media_url']).content) + res.write({ + + 'post_image': image_data, + }) + if media_content.get('caption'): + res.write({ + 'caption': media_content['caption'], + + }) + + else: + record = self.env['insta.post'].search([('name', '=', vals['id'])]) + record.action_update_post(self.access_token) + else: + raise UserError(_('%s', content['error']['message'])) diff --git a/insta_feed_snippet/security/ir.model.access.csv b/insta_feed_snippet/security/ir.model.access.csv new file mode 100644 index 000000000..2d8fb6c49 --- /dev/null +++ b/insta_feed_snippet/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 +insta_profile_id,insta.profile.name,model_insta_profile,,1,1,1,1 +insta_post_id,insta.post.name,model_insta_post,,1,1,1,1 + diff --git a/insta_feed_snippet/static/description/assets/icons/check.png b/insta_feed_snippet/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/check.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/chevron.png b/insta_feed_snippet/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/chevron.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/cogs.png b/insta_feed_snippet/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/cogs.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/consultation.png b/insta_feed_snippet/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/consultation.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/ecom-black.png b/insta_feed_snippet/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/ecom-black.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/education-black.png b/insta_feed_snippet/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/education-black.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/hotel-black.png b/insta_feed_snippet/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/hotel-black.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/insta_feed_snippet_icon.png b/insta_feed_snippet/static/description/assets/icons/insta_feed_snippet_icon.png new file mode 100644 index 000000000..9af668a31 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/insta_feed_snippet_icon.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/license.png b/insta_feed_snippet/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/license.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/lifebuoy.png b/insta_feed_snippet/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/lifebuoy.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/logo.png b/insta_feed_snippet/static/description/assets/icons/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/logo.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/manufacturing-black.png b/insta_feed_snippet/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/manufacturing-black.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/pos-black.png b/insta_feed_snippet/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/pos-black.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/puzzle.png b/insta_feed_snippet/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/puzzle.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/restaurant-black.png b/insta_feed_snippet/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/restaurant-black.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/service-black.png b/insta_feed_snippet/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/service-black.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/trading-black.png b/insta_feed_snippet/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/trading-black.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/training.png b/insta_feed_snippet/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/training.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/update.png b/insta_feed_snippet/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/update.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/user.png b/insta_feed_snippet/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/user.png differ diff --git a/insta_feed_snippet/static/description/assets/icons/wrench.png b/insta_feed_snippet/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/insta_feed_snippet/static/description/assets/icons/wrench.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/categories.png b/insta_feed_snippet/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/categories.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/check-box.png b/insta_feed_snippet/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/check-box.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/compass.png b/insta_feed_snippet/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/compass.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/corporate.png b/insta_feed_snippet/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/corporate.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/customer-support.png b/insta_feed_snippet/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/customer-support.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/cybrosys-logo.png b/insta_feed_snippet/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/cybrosys-logo.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/features.png b/insta_feed_snippet/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/features.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/logo.png b/insta_feed_snippet/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/logo.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/pictures.png b/insta_feed_snippet/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/pictures.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/pie-chart.png b/insta_feed_snippet/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/pie-chart.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/right-arrow.png b/insta_feed_snippet/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/right-arrow.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/star.png b/insta_feed_snippet/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/star.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/support.png b/insta_feed_snippet/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/support.png differ diff --git a/insta_feed_snippet/static/description/assets/misc/whatsapp.png b/insta_feed_snippet/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/misc/whatsapp.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/1.png b/insta_feed_snippet/static/description/assets/modules/1.png new file mode 100644 index 000000000..5238bdeab Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/1.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/2.png b/insta_feed_snippet/static/description/assets/modules/2.png new file mode 100644 index 000000000..1ae7cfe3b Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/2.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/3.png b/insta_feed_snippet/static/description/assets/modules/3.png new file mode 100644 index 000000000..3c3ff1afb Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/3.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/4.png b/insta_feed_snippet/static/description/assets/modules/4.png new file mode 100644 index 000000000..3fae4631e Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/4.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/5.gif b/insta_feed_snippet/static/description/assets/modules/5.gif new file mode 100644 index 000000000..2a5f8e659 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/5.gif differ diff --git a/insta_feed_snippet/static/description/assets/modules/6.png b/insta_feed_snippet/static/description/assets/modules/6.png new file mode 100644 index 000000000..7f2815273 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/6.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/budget_image.png b/insta_feed_snippet/static/description/assets/modules/budget_image.png new file mode 100644 index 000000000..b50130c7d Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/budget_image.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/credit_image.png b/insta_feed_snippet/static/description/assets/modules/credit_image.png new file mode 100644 index 000000000..3ad04ecfd Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/credit_image.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/employee_image.png b/insta_feed_snippet/static/description/assets/modules/employee_image.png new file mode 100644 index 000000000..30ad58232 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/employee_image.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/export_image.png b/insta_feed_snippet/static/description/assets/modules/export_image.png new file mode 100644 index 000000000..492980ad0 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/export_image.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/gantt_image.png b/insta_feed_snippet/static/description/assets/modules/gantt_image.png new file mode 100644 index 000000000..1ae7cfe3b Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/gantt_image.png differ diff --git a/insta_feed_snippet/static/description/assets/modules/quotation_image.png b/insta_feed_snippet/static/description/assets/modules/quotation_image.png new file mode 100644 index 000000000..499b1a72f Binary files /dev/null and b/insta_feed_snippet/static/description/assets/modules/quotation_image.png differ diff --git a/insta_feed_snippet/static/description/assets/screenshots/hero.gif b/insta_feed_snippet/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..52183da2d Binary files /dev/null and b/insta_feed_snippet/static/description/assets/screenshots/hero.gif differ diff --git a/insta_feed_snippet/static/description/assets/screenshots/in_1.png b/insta_feed_snippet/static/description/assets/screenshots/in_1.png new file mode 100644 index 000000000..436c8fa92 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/screenshots/in_1.png differ diff --git a/insta_feed_snippet/static/description/assets/screenshots/in_2.png b/insta_feed_snippet/static/description/assets/screenshots/in_2.png new file mode 100644 index 000000000..ef45ee585 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/screenshots/in_2.png differ diff --git a/insta_feed_snippet/static/description/assets/screenshots/in_3.png b/insta_feed_snippet/static/description/assets/screenshots/in_3.png new file mode 100644 index 000000000..0a0eecd40 Binary files /dev/null and b/insta_feed_snippet/static/description/assets/screenshots/in_3.png differ diff --git a/insta_feed_snippet/static/description/assets/screenshots/in_4.png b/insta_feed_snippet/static/description/assets/screenshots/in_4.png new file mode 100644 index 000000000..49d52373d Binary files /dev/null and b/insta_feed_snippet/static/description/assets/screenshots/in_4.png differ diff --git a/insta_feed_snippet/static/description/assets/screenshots/in_5.png b/insta_feed_snippet/static/description/assets/screenshots/in_5.png new file mode 100644 index 000000000..4cca0c1de Binary files /dev/null and b/insta_feed_snippet/static/description/assets/screenshots/in_5.png differ diff --git a/insta_feed_snippet/static/description/banner.png b/insta_feed_snippet/static/description/banner.png new file mode 100644 index 000000000..44ed6e8f2 Binary files /dev/null and b/insta_feed_snippet/static/description/banner.png differ diff --git a/insta_feed_snippet/static/description/icon.png b/insta_feed_snippet/static/description/icon.png new file mode 100644 index 000000000..f29fe2ff4 Binary files /dev/null and b/insta_feed_snippet/static/description/icon.png differ diff --git a/insta_feed_snippet/static/description/index.html b/insta_feed_snippet/static/description/index.html new file mode 100644 index 000000000..bb1856df4 --- /dev/null +++ b/insta_feed_snippet/static/description/index.html @@ -0,0 +1,592 @@ +
+
+
+
+ +
+
+
+ Community +
+
+ Enterprise +
+ +
+
+
+
+ +
+
+
+

+ Instagram Feed snippet

+

+ A Module For Instagram Feed Snippet +

+ +
+
+ + + +
+
+

+ Overview +

+
+ +
+

+ As we all know, Instagram is one of the most used and popular social networking sites all over the + world. With approx. 1 billion monthly active users on Instagram, it is a perfect way to reach out to + potential users + easily. Adding your Instagram profile option on your Odoo website enables you to promote your website + products + on Instagram. The Odoo Instagram Feed Snippet module provides a feature to add an Instagram feed in + Odoo.

+
+

+ +
+ + +
+
+

+ Features +

+
+ +
+
+ +
+
+

+ The Odoo Instagram Feed Snippet module provides a feature to add an Instagram feed in Odoo

+
+
+ +
+
+ +
+
+

+ You can simply drag and drop Instagram snippets on any page of your website to show your Instagram + feed.

+
+
+ + +
+ +
+
+

+ Screenshots +

+
+
+

+ Website Backend

+

+ Once the installation + is completed, visit the Odoo website app from the backend. Here, click on Configuration>>Instagram.You + can set up your instagram profile by adding access key and click fetch account button.Once the profile + is generated click the fetch post button to fetch instagram post into odoo

+ +
+ +
+

+ Profile

+

+ +

+ +
+ +
+

+ Instagram Posts

+ +
+ + +
+

+ Website Frontend

+ In Odoo website frontend click on the Edit option.After that, select the Instagram widget and drag it + to the place where you want to showcase it on your Odoo website frontend, and click on the Save + button.

+ +
+ + +
+

After that, once you + save it, the Instagram widget will let you show your Instagram feed on your Odoo website as shown + below.

+ +
+ + +
+ +
+
+

Suggested Products

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

Our Services

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

Our Industries

+
+
+ +
+
+ +
+ 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

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

Need Help?

+
+
+
+ + +
+ +
+ + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+ + +
\ No newline at end of file diff --git a/insta_feed_snippet/static/src/css/owl.carousel.min.css b/insta_feed_snippet/static/src/css/owl.carousel.min.css new file mode 100644 index 000000000..a71df11c0 --- /dev/null +++ b/insta_feed_snippet/static/src/css/owl.carousel.min.css @@ -0,0 +1,6 @@ +/** + * 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,.owl-carousel .owl-item{-webkit-tap-highlight-color:transparent;position:relative}.owl-carousel{display:none;width:100%;z-index:1}.owl-carousel .owl-stage{position:relative;-ms-touch-action:pan-Y;touch-action:manipulation;-moz-backface-visibility:hidden}.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;-webkit-transform:translate3d(0,0,0)}.owl-carousel .owl-item,.owl-carousel .owl-wrapper{-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{min-height:1px;float:left;-webkit-backface-visibility:hidden;-webkit-touch-callout:none}.owl-carousel .owl-item img{display:block;width:100%}.owl-carousel .owl-dots.disabled,.owl-carousel .owl-nav.disabled{display:none}.no-js .owl-carousel,.owl-carousel.owl-loaded{display:block}.owl-carousel .owl-dot,.owl-carousel .owl-nav .owl-next,.owl-carousel .owl-nav .owl-prev{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-next,.owl-carousel .owl-nav button.owl-prev,.owl-carousel button.owl-dot{background:0 0;color:inherit;border:none;padding:0!important;font:inherit}.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}.owl-carousel .animated{animation-duration:1s;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-height{transition:height .5s ease-in-out}.owl-carousel .owl-item .owl-lazy{opacity:0;transition:opacity .4s ease}.owl-carousel .owl-item .owl-lazy:not([src]),.owl-carousel .owl-item .owl-lazy[src^=""]{max-height:0}.owl-carousel .owl-item img.owl-lazy{transform-style:preserve-3d}.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 .1s 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-play-icon,.owl-carousel .owl-video-playing .owl-video-tn{display:none}.owl-carousel .owl-video-tn{opacity:0;height:100%;background-position:center center;background-repeat:no-repeat;background-size:contain;transition:opacity .4s ease}.owl-carousel .owl-video-frame{position:relative;z-index:1;height:100%;width:100%} \ No newline at end of file diff --git a/insta_feed_snippet/static/src/css/owl.theme.default.min.css b/insta_feed_snippet/static/src/css/owl.theme.default.min.css new file mode 100644 index 000000000..487088d2e --- /dev/null +++ b/insta_feed_snippet/static/src/css/owl.theme.default.min.css @@ -0,0 +1,6 @@ +/** + * Owl Carousel v2.3.4 + * Copyright 2013-2018 David Deutsch + * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE + */ +.owl-theme .owl-dots,.owl-theme .owl-nav{text-align:center;-webkit-tap-highlight-color:transparent}.owl-theme .owl-nav{margin-top:10px}.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:.5;cursor:default}.owl-theme .owl-nav.disabled+.owl-dots{margin-top:10px}.owl-theme .owl-dots .owl-dot{display:inline-block;zoom:1}.owl-theme .owl-dots .owl-dot span{width:10px;height:10px;margin:5px 7px;background:#D6D6D6;display:block;-webkit-backface-visibility:visible;transition:opacity .2s ease;border-radius:30px}.owl-theme .owl-dots .owl-dot.active span,.owl-theme .owl-dots .owl-dot:hover span{background:#869791} \ No newline at end of file diff --git a/insta_feed_snippet/static/src/image/carousel.png b/insta_feed_snippet/static/src/image/carousel.png new file mode 100644 index 000000000..b08c3d1df Binary files /dev/null and b/insta_feed_snippet/static/src/image/carousel.png differ diff --git a/insta_feed_snippet/static/src/js/caroursel.js b/insta_feed_snippet/static/src/js/caroursel.js new file mode 100644 index 000000000..714baa2ee --- /dev/null +++ b/insta_feed_snippet/static/src/js/caroursel.js @@ -0,0 +1,23 @@ +odoo.define('insta_feed_snippet.carousel_dashboard', function(require){ + 'use strict'; + var Animation = require('website.content.snippets.animation'); + var ajax = require('web.ajax'); + + Animation.registry.get_dashbaord_carousel = Animation.Class.extend({ + selector : '.s_carousel_template', + init: function() { + this._super.apply(this, arguments); + console.log("Init loaded"); + }, + start: function(){ + console.log("Test"); + var self = this; + ajax.jsonRpc('/get_dashbaord_carousel', 'call', {}) + .then(function (data) { + if(data){ + self.$target.empty().append(data); + } + }); + } + }); +}); diff --git a/insta_feed_snippet/static/src/js/custom.js b/insta_feed_snippet/static/src/js/custom.js new file mode 100644 index 000000000..c61ec6880 --- /dev/null +++ b/insta_feed_snippet/static/src/js/custom.js @@ -0,0 +1,34 @@ + \ No newline at end of file diff --git a/insta_feed_snippet/views/insta_post.xml b/insta_feed_snippet/views/insta_post.xml new file mode 100644 index 000000000..e0b1cbb32 --- /dev/null +++ b/insta_feed_snippet/views/insta_post.xml @@ -0,0 +1,85 @@ + + + + + + insta.post.kanban + insta.post + + + + + +
+
+ + +
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+ + insta.post.form + insta.post + +
+ +
+
+

+ + + + +

+
+
+
+ +
+
+
+ + insta.post.tree + insta.post + + + + + + + + insta.post.search + insta.post + + + + + + + + + Instagram Posts + insta.post + kanban,tree,form + + + + +
\ No newline at end of file diff --git a/insta_feed_snippet/views/insta_profile.xml b/insta_feed_snippet/views/insta_profile.xml new file mode 100644 index 000000000..57a019c3b --- /dev/null +++ b/insta_feed_snippet/views/insta_profile.xml @@ -0,0 +1,119 @@ + + + + insta.profile.form + insta.profile + +
+ +
+ +
+ + +
+

+ +

+
+
+
+ + + + + + +
+
+
+
+
+
+ + insta.profile.form + insta.profile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/insta_feed_snippet/views/snippet_structure_inherit.xml b/insta_feed_snippet/views/snippet_structure_inherit.xml new file mode 100644 index 000000000..638619150 --- /dev/null +++ b/insta_feed_snippet/views/snippet_structure_inherit.xml @@ -0,0 +1,86 @@ + + + + + + + + + \ No newline at end of file diff --git a/insta_feed_snippet/views/website.xml b/insta_feed_snippet/views/website.xml new file mode 100644 index 000000000..ce08bb023 --- /dev/null +++ b/insta_feed_snippet/views/website.xml @@ -0,0 +1,22 @@ + + + + + Insta profile + ir.actions.act_window + kanban,tree,form + insta.profile + + +