diff --git a/hr_linkedin_recruitment/README.rst b/hr_linkedin_recruitment/README.rst
new file mode 100644
index 000000000..55ac78c4e
--- /dev/null
+++ b/hr_linkedin_recruitment/README.rst
@@ -0,0 +1,31 @@
+==========================================
+ Basic HR-LinkedIn Connector v12
+==========================================
+
+The module integrates LinkedIn with Odoo HR Recruitment.
+ * Share Job Opening Posts With LinkedIn.
+ * Automate Odoo HRMS with LinkedIn.
+
+Company
+-------
+* `Cybrosys Technologies `__
+
+Developers
+----------
+* `Nilmar Shereef `__
+* `Jesni Banu
+* `v11 & v12 Milind Mohan
+
+Contact
+-------
+* Mail Contact : odoo@cybrosys.com
+* Mail Contact : info@cybrosys.com
+
+Related Blog
+-------
+* `Cybrosys LinkedIn Blog `__
+
+Further information
+===================
+HTML Description: ``__
+Technical instructions: ``__
diff --git a/hr_linkedin_recruitment/__init__.py b/hr_linkedin_recruitment/__init__.py
new file mode 100644
index 000000000..c555c50ec
--- /dev/null
+++ b/hr_linkedin_recruitment/__init__.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Author: Nilmar Shereef ()
+# Copyright (C) 2018-TODAY Cybrosys Technologies ().
+#
+# 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 .
+#
+###################################################################################
+from . import models
+
diff --git a/hr_linkedin_recruitment/__manifest__.py b/hr_linkedin_recruitment/__manifest__.py
new file mode 100644
index 000000000..af236af95
--- /dev/null
+++ b/hr_linkedin_recruitment/__manifest__.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Author: Nilmar Shereef ()
+# Copyright (C) 2019-TODAY Cybrosys Technologies ().
+#
+# 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': 'HR-LinkedIn Integration',
+ 'summary': "Integrates LinkedIn with HR Recruitment",
+ 'description': "Basic module for LnkedIn-HR Recruitment connector",
+ 'category': 'Generic Modules/Human Resources',
+ 'version': "12.0.1.0.0",
+ 'depends': ['hr_recruitment', 'auth_oauth'],
+ 'author': 'Cybrosys Techno Solutions',
+ 'company': 'Cybrosys Techno Solutions',
+ 'website': "https://www.cybrosys.com",
+ 'data': [
+ 'data/auth_linkedin_data.xml',
+ 'views/recruitment_config_settings.xml',
+ 'views/hr_job_linkedin.xml',
+ 'views/oauth_view.xml',
+ ],
+ 'external_dependencies':
+ {
+ 'python': ['mechanize', 'linkedin'],
+ },
+ 'images': ['static/description/banner.jpg'],
+ 'license': 'AGPL-3',
+ 'installable': True,
+ 'auto_install': False,
+ 'application': False,
+}
diff --git a/hr_linkedin_recruitment/data/auth_linkedin_data.xml b/hr_linkedin_recruitment/data/auth_linkedin_data.xml
new file mode 100644
index 000000000..11b8338ef
--- /dev/null
+++ b/hr_linkedin_recruitment/data/auth_linkedin_data.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ LinkedIn
+ https://www.linkedin.com/oauth/v2/authorization
+ r_basicprofile r_emailaddress w_share w_member_social
+ https://api.linkedin.com/v2/me
+ https://api.linkedin.com/v2/me
+ fa fa-linkedin-square
+ Share post with LinkedIn
+
+
+
diff --git a/hr_linkedin_recruitment/doc/RELEASE_NOTES.md b/hr_linkedin_recruitment/doc/RELEASE_NOTES.md
new file mode 100644
index 000000000..79692b9ba
--- /dev/null
+++ b/hr_linkedin_recruitment/doc/RELEASE_NOTES.md
@@ -0,0 +1,6 @@
+## Module
+
+#### 03.05.2019
+#### Version 12.0.1.0.0
+##### ADD
+- Initial Commit (linkedin api v2)
diff --git a/hr_linkedin_recruitment/doc/requirment.txt b/hr_linkedin_recruitment/doc/requirment.txt
new file mode 100644
index 000000000..6a8ad0917
--- /dev/null
+++ b/hr_linkedin_recruitment/doc/requirment.txt
@@ -0,0 +1,8 @@
+Odoo integration module "hr_linkedin_recruitment" depends on the several external python package.
+Please ensure that listed packaged has installed in your system:
+
+* python-linkedin (sudo python-linkedin)
+* mechanize (sudo pip install mechanize)
+
+
+
diff --git a/hr_linkedin_recruitment/models/__init__.py b/hr_linkedin_recruitment/models/__init__.py
new file mode 100644
index 000000000..81806be4b
--- /dev/null
+++ b/hr_linkedin_recruitment/models/__init__.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Author: Nilmar Shereef ()
+# Copyright (C) 2018-TODAY Cybrosys Technologies ().
+#
+# 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 .
+#
+###################################################################################
+from . import mechanize_op
+from . import recruitment_config
+from . import hr_job
+from . import auth_outh
diff --git a/hr_linkedin_recruitment/models/auth_outh.py b/hr_linkedin_recruitment/models/auth_outh.py
new file mode 100644
index 000000000..e95b08e8f
--- /dev/null
+++ b/hr_linkedin_recruitment/models/auth_outh.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Author: Nilmar Shereef ()
+# Copyright (C) 2018-TODAY Cybrosys Technologies ().
+#
+# 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 .
+#
+###################################################################################
+from odoo import models, fields, api
+
+
+class OAuthProviderLinkedin(models.Model):
+
+ _inherit = 'auth.oauth.provider'
+
+ """ Adding client_secret field because some apps likes twitter,
+ linkedIn are using this value for its API operations """
+
+ client_secret = fields.Char(string='Client Secret', help="Only need LinkedIn, Twitter etc..")
diff --git a/hr_linkedin_recruitment/models/hr_job.py b/hr_linkedin_recruitment/models/hr_job.py
new file mode 100644
index 000000000..3b890e430
--- /dev/null
+++ b/hr_linkedin_recruitment/models/hr_job.py
@@ -0,0 +1,172 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Author: Nilmar Shereef ()
+# Copyright (C) 2018-TODAY Cybrosys Technologies ().
+#
+# 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 .
+#
+###################################################################################
+import logging
+
+_logger = logging.getLogger(__name__)
+try:
+ import mechanize
+ from linkedin import linkedin
+ from urllib.request import HTTPRedirectHandler as MechanizeRedirectHandler
+
+except ImportError:
+ _logger.error('Odoo module hr_linkedin_recruitment depends on the several external python package'
+ 'Please read the doc/requirement.txt file inside the module.')
+
+import requests
+import mechanicalsoup
+import json
+from urllib.parse import urlsplit
+from urllib.parse import parse_qs
+from urllib.parse import urlparse
+from odoo import models, fields, api, _
+from odoo.exceptions import ValidationError, Warning
+import builtins as exceptions
+
+
+class HrJobShare(models.Model):
+ _inherit = 'hr.job'
+
+ update_key = fields.Char(string='Update Key', readonly=True)
+
+ @api.multi
+ def share_linkedin(self):
+ """ Button function for sharing post """
+ credential_dict = self.get_authorize()
+ access_token = credential_dict['access_token']
+ li_credential = credential_dict['li_credential']
+ share_data = {
+ "author": "urn:li:person:"+li_credential['profile_urn'],
+ "lifecycleState": "PUBLISHED",
+ "specificContent": {
+ "com.linkedin.ugc.ShareContent": {
+ "shareCommentary": {
+ "text": self.description
+ },
+ "shareMediaCategory": "NONE"
+ }
+ },
+ "visibility": {
+ "com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC"
+ }
+ }
+
+ # URLS
+
+ page_share_url = 'https://api.linkedin.com/v2/ugcPosts'
+ if self.description:
+ response = self.share_request('POST', page_share_url, access_token, data=json.dumps(share_data))
+ share_response_text = response.json()
+ share_response_code = response.status_code
+
+ if share_response_code == 201:
+ self.update_key = True
+
+ elif share_response_code == 404:
+ raise Warning("Resource does not exist.!")
+ elif share_response_code == 409:
+ raise Warning("Already shared!")
+ else:
+ raise Warning("Error!! Check your connection...")
+ else:
+ raise Warning("Provide a Job description....")
+
+ def share_request(self, method, page_share_url, access_token, data):
+ """ Function will return UPDATED KEY , [201] if sharing is OK """
+ headers = {'x-li-format': 'json', 'Content-Type': 'application/json'}
+ params = {}
+ params.update({'oauth2_access_token': access_token})
+ kw = dict(data=data, params=params, headers=headers, timeout=60)
+ req_response = requests.request(method.upper(), page_share_url, **kw)
+ return req_response
+
+ def get_urn(self, method, has_access_url, access_token):
+ """ Function will return TRUE if credentials user has the access to update """
+ headers = {'x-li-format': 'json', 'Content-Type': 'application/json'}
+ params = {}
+ params.update({'oauth2_access_token': access_token})
+ kw = dict(params=params, headers=headers, timeout=60)
+ req_response = requests.request(method.upper(), has_access_url, **kw)
+ return req_response
+
+ def get_authorize(self):
+ """ Supporting function for authenticating operations """
+ li_credential = {}
+ linkedin_auth_provider = self.env.ref('hr_linkedin_recruitment.provider_linkedin')
+ if linkedin_auth_provider.client_id and linkedin_auth_provider.client_secret:
+ li_credential['api_key'] = linkedin_auth_provider.client_id
+ li_credential['secret_key'] = linkedin_auth_provider.client_secret
+ else:
+ raise ValidationError(_('LinkedIn Access Credentials are empty.!\n'
+ 'Please fill up in Auth Provider form.'))
+
+ if self.env['ir.config_parameter'].sudo().get_param('recruitment.li_username'):
+ li_credential['un'] = self.env['ir.config_parameter'].sudo().get_param('recruitment.li_username')
+ else:
+ raise exceptions.Warning(_('Please fill up username in LinkedIn Credential settings.'))
+
+ if self.env['ir.config_parameter'].sudo().get_param('recruitment.li_password'):
+ li_credential['pw'] = self.env['ir.config_parameter'].sudo().get_param('recruitment.li_password')
+ else:
+ raise exceptions.Warning(_('Please fill up password in LinkedIn Credential settings.'))
+
+ # Browser Data Posting And Signing
+ br = mechanicalsoup.StatefulBrowser()
+ br.set_cookiejar(mechanize.CookieJar())
+ return_uri = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
+ li_permissions = ['r_liteprofile', 'r_emailaddress', 'w_share', 'rw_company_admin', 'w_member_social']
+
+ auth = linkedin.LinkedInAuthentication(li_credential['api_key'],
+ li_credential['secret_key'],
+ return_uri,
+ li_permissions)
+ try:
+ br.open(auth.authorization_url)
+ br.select_form(selector='form', nr=0)
+ br['session_key'] = li_credential['un']
+ br['session_password'] = li_credential['pw']
+ br.submit_selected()
+ try:
+ auth.authorization_code = parse_qs(urlsplit(br.get_url()).query)['code']
+ except:
+ br.open(br.get_url())
+ br.select_form(selector='form', nr=1)
+ q = br.submit_selected()
+ auth.authorization_code = parse_qs(urlsplit(br.get_url()).query)['code']
+ if not auth.authorization_code:
+ raise Warning("Please check Redirect URLs in the LinkedIn app settings!")
+ except:
+ raise Warning("Please check Redirect URLs in the LinkedIn app settings!")
+
+ li_suit_credent = {}
+ li_suit_credent['access_token'] = str(auth.get_access_token().access_token)
+ member_url = 'https://api.linkedin.com/v2/me'
+ response = self.get_urn('GET', member_url, li_suit_credent['access_token'])
+ urn_response_text = response.json()
+
+ li_credential['profile_urn'] = urn_response_text['id']
+
+ li_suit_credent['li_credential'] = li_credential
+
+ return li_suit_credent
+
+
diff --git a/hr_linkedin_recruitment/models/mechanize_op.py b/hr_linkedin_recruitment/models/mechanize_op.py
new file mode 100644
index 000000000..d6df1bbf5
--- /dev/null
+++ b/hr_linkedin_recruitment/models/mechanize_op.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Author: Nilmar Shereef ()
+# Copyright (C) 2018-TODAY Cybrosys Technologies ().
+#
+# 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 .
+#
+###################################################################################
+import logging
+import urllib
+_logger = logging.getLogger(__name__)
+try:
+ import mechanize
+ from mechanize import _response
+ from mechanize import _rfc3986
+ import re
+
+
+ class MechanizeRedirectHandler(mechanize.HTTPRedirectHandler):
+ def http_error_302(self, req, fp, code, msg, headers):
+ # Code from mechanize._urllib2_fork.HTTPRedirectHandler:
+ if 'location' in headers:
+ newurl = headers.getheaders('location')[0]
+ elif 'uri' in headers:
+ newurl = headers.getheaders('uri')[0]
+ else:
+ return
+ newurl = _rfc3986.clean_url(newurl, "latin-1")
+ newurl = _rfc3986.urljoin(req.get_full_url(), newurl)
+
+ new = self.redirect_request(req, fp, code, msg, headers, newurl)
+ if new is None:
+ return
+
+ if hasattr(req, 'redirect_dict'):
+ visited = new.redirect_dict = req.redirect_dict
+ if (visited.get(newurl, 0) >= self.max_repeats or
+ len(visited) >= self.max_redirections):
+ raise urllib.error.HTTPError(req.get_full_url(), code,
+ self.inf_msg + msg, headers, fp)
+ else:
+ visited = new.redirect_dict = req.redirect_dict = {}
+ visited[newurl] = visited.get(newurl, 0) + 1
+
+ fp.read()
+ fp.close()
+
+ # If the redirected URL doesn't match
+ new_url = new.get_full_url()
+ if not re.search('^http(?:s)?\:\/\/.*www\.linkedin\.com', new_url):
+ return _response.make_response('', headers.items(), new_url, 200, 'OK')
+ else:
+ return self.parent.open(new)
+
+ http_error_301 = http_error_303 = http_error_307 = http_error_302
+ http_error_refresh = http_error_302
+
+except ImportError:
+ _logger.warning('Odoo module hr_linkedin_recruitment depends on the several external python package'
+ 'Please read the doc/requirement.txt file inside the module.')
+
+
diff --git a/hr_linkedin_recruitment/models/recruitment_config.py b/hr_linkedin_recruitment/models/recruitment_config.py
new file mode 100644
index 000000000..e123d796c
--- /dev/null
+++ b/hr_linkedin_recruitment/models/recruitment_config.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Author: Nilmar Shereef ()
+# Copyright (C) 2018-TODAY Cybrosys Technologies ().
+#
+# 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 .
+#
+###################################################################################
+from odoo import models, fields, api
+
+
+class ResConfigSettings(models.TransientModel):
+ _inherit = 'res.config.settings'
+
+ li_username = fields.Char(string="User Name", help="Your Linkedin Username")
+ li_password = fields.Char(string="Password", help="Your Linkedin Password")
+
+ def set_values(self):
+
+ super(ResConfigSettings, self).set_values()
+ self.env['ir.config_parameter'].sudo().set_param('recruitment.company_page_id', self.company_page_id)
+ self.env['ir.config_parameter'].sudo().set_param('recruitment.li_username', self.li_username)
+ self.env['ir.config_parameter'].sudo().set_param('recruitment.li_password', self.li_password)
+
+ def get_values(self):
+ res = super(ResConfigSettings, self).get_values()
+ res.update(
+ company_page_id=self.env['ir.config_parameter'].sudo().get_param('recruitment.company_page_id'),
+ li_username = self.env['ir.config_parameter'].sudo().get_param('recruitment.li_username'),
+ li_password = self.env['ir.config_parameter'].sudo().get_param('recruitment.li_password')
+ )
+ return res
+
+
+
+
diff --git a/hr_linkedin_recruitment/static/description/banner.jpg b/hr_linkedin_recruitment/static/description/banner.jpg
new file mode 100644
index 000000000..ab7676dc6
Binary files /dev/null and b/hr_linkedin_recruitment/static/description/banner.jpg differ
diff --git a/hr_linkedin_recruitment/static/description/cybro_logo.png b/hr_linkedin_recruitment/static/description/cybro_logo.png
new file mode 100644
index 000000000..bb309114c
Binary files /dev/null and b/hr_linkedin_recruitment/static/description/cybro_logo.png differ
diff --git a/hr_linkedin_recruitment/static/description/hr-linkedin-integration1.png b/hr_linkedin_recruitment/static/description/hr-linkedin-integration1.png
new file mode 100644
index 000000000..a244f44ee
Binary files /dev/null and b/hr_linkedin_recruitment/static/description/hr-linkedin-integration1.png differ
diff --git a/hr_linkedin_recruitment/static/description/hr-linkedin-integration2.png b/hr_linkedin_recruitment/static/description/hr-linkedin-integration2.png
new file mode 100644
index 000000000..4be08b2d9
Binary files /dev/null and b/hr_linkedin_recruitment/static/description/hr-linkedin-integration2.png differ
diff --git a/hr_linkedin_recruitment/static/description/hr-linkedin-integration3.png b/hr_linkedin_recruitment/static/description/hr-linkedin-integration3.png
new file mode 100644
index 000000000..5d13f24c6
Binary files /dev/null and b/hr_linkedin_recruitment/static/description/hr-linkedin-integration3.png differ
diff --git a/hr_linkedin_recruitment/static/description/hr-linkedin-integration4.png b/hr_linkedin_recruitment/static/description/hr-linkedin-integration4.png
new file mode 100644
index 000000000..d6797421f
Binary files /dev/null and b/hr_linkedin_recruitment/static/description/hr-linkedin-integration4.png differ
diff --git a/hr_linkedin_recruitment/static/description/hr-linkedin-integration5.png b/hr_linkedin_recruitment/static/description/hr-linkedin-integration5.png
new file mode 100644
index 000000000..c58d5884a
Binary files /dev/null and b/hr_linkedin_recruitment/static/description/hr-linkedin-integration5.png differ
diff --git a/hr_linkedin_recruitment/static/description/icon.png b/hr_linkedin_recruitment/static/description/icon.png
new file mode 100644
index 000000000..b49949830
Binary files /dev/null and b/hr_linkedin_recruitment/static/description/icon.png differ
diff --git a/hr_linkedin_recruitment/static/description/index.html b/hr_linkedin_recruitment/static/description/index.html
new file mode 100644
index 000000000..c69dd6d68
--- /dev/null
+++ b/hr_linkedin_recruitment/static/description/index.html
@@ -0,0 +1,377 @@
+
+
+
+
+
+
+
+
+
diff --git a/vouchers_pos/README.rst b/vouchers_pos/README.rst
new file mode 100644
index 000000000..230a7ae96
--- /dev/null
+++ b/vouchers_pos/README.rst
@@ -0,0 +1,36 @@
+
+Coupons & Vouchers in Point of Sale V12
+=======================================
+
+This module allow special discounts to your customers using Gift Vouchers and Coupon codes.
+
+Depends
+=======
+[point_of_sale] addon Odoo
+
+
+Installation
+============
+
+- www.odoo.com/documentation/12.0/setup/install.html
+- Install our custom addon
+
+Credits
+=======
+* Cybrosys Techno Solutions
+
+Author
+------
+
+Developers: v10.0 LINTO CT
+ v11.0 LINTO CT
+ v12.0 Kavya Raveendran
+
+
+Maintainer
+----------
+
+This module is maintained by Cybrosys Technologies.
+
+For support and more information, please visit https://www.cybrosys.com.
+
diff --git a/vouchers_pos/__init__.py b/vouchers_pos/__init__.py
new file mode 100644
index 000000000..8556c16b7
--- /dev/null
+++ b/vouchers_pos/__init__.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2019-TODAY Cybrosys Technologies().
+# Author:LINTO CT()
+
+# 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 .
+#
+###################################################################################
+
+from. import models
diff --git a/vouchers_pos/__manifest__.py b/vouchers_pos/__manifest__.py
new file mode 100644
index 000000000..7714a1947
--- /dev/null
+++ b/vouchers_pos/__manifest__.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2019-TODAY Cybrosys Technologies().
+# Author:LINTO CT()
+
+# 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': 'Coupons & Vouchers in Point of Sale',
+ 'version': '12.0.1.0.0',
+ 'category': 'Point of Sale',
+ 'summary': 'Manage Point of Sale Vouchers & Coupon Codes',
+ 'author': 'Cybrosys Techno Solutions',
+ 'website': "https://www.cybrosys.com",
+ 'company': 'Cybrosys Techno Solutions',
+ 'depends': ['point_of_sale'],
+ 'data': [
+ 'data/product_data.xml',
+ 'views/gift_voucher.xml',
+ 'views/applied_coupons.xml',
+ 'views/pos_template.xml',
+ 'security/ir.model.access.csv'
+ ],
+ 'qweb': ['static/src/xml/coupons.xml'],
+ 'images': ['static/description/banner.jpg'],
+ 'license': 'AGPL-3',
+ 'installable': True,
+ 'application': False,
+ 'auto_install': False,
+}
diff --git a/vouchers_pos/data/product_data.xml b/vouchers_pos/data/product_data.xml
new file mode 100644
index 000000000..660a0685c
--- /dev/null
+++ b/vouchers_pos/data/product_data.xml
@@ -0,0 +1,11 @@
+
+
+
+ Gift-Coupon
+ Gift-Coupon
+ True
+ service
+
+
+
+
diff --git a/vouchers_pos/doc/RELEASE_NOTES.md b/vouchers_pos/doc/RELEASE_NOTES.md
new file mode 100644
index 000000000..bd1d6b523
--- /dev/null
+++ b/vouchers_pos/doc/RELEASE_NOTES.md
@@ -0,0 +1,7 @@
+## Module
+
+#### 29.04.2019
+#### Version 12.0.1.0.0
+##### ADD
+- Initial commit
+
diff --git a/vouchers_pos/models/__init__.py b/vouchers_pos/models/__init__.py
new file mode 100644
index 000000000..84646df3e
--- /dev/null
+++ b/vouchers_pos/models/__init__.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2017-TODAY Cybrosys Technologies().
+# Author:LINTO CT()
+
+# 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 .
+#
+###################################################################################
+
+from . import gift_voucher
diff --git a/vouchers_pos/models/gift_voucher.py b/vouchers_pos/models/gift_voucher.py
new file mode 100644
index 000000000..c2159602f
--- /dev/null
+++ b/vouchers_pos/models/gift_voucher.py
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+###################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2019-TODAY Cybrosys Technologies().
+# Author:LINTO CT()
+
+# 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 .
+#
+###################################################################################
+import string
+import random
+from odoo import models, fields, api, _
+from odoo.exceptions import UserError
+
+
+class GiftVoucherPos(models.Model):
+ _name = 'gift.voucher.pos'
+
+ name = fields.Char(string="Name", required=True)
+ voucher_type = fields.Selection(
+ selection=[
+ ('product', 'Product'),
+ ('category', 'POS Category'),
+ ('all', 'All Products'),
+ ], string="Applicable on ", default='product'
+ )
+ product_id = fields.Many2one('product.product', string="Product")
+ product_categ = fields.Many2one('pos.category', string="Product Category")
+ min_value = fields.Integer(string="Minimum Voucher Value", required=True)
+ max_value = fields.Integer(string="Maximum Voucher Value", required=True)
+ expiry_date = fields.Date(string="Expiry Date", required=True, help='The expiry date of Voucher.')
+
+
+class GiftCouponPos(models.Model):
+ _name = 'gift.coupon.pos'
+
+ def get_code(self):
+ size = 7
+ chars = string.ascii_uppercase + string.digits
+ return ''.join(random.choice(chars) for _ in range(size))
+
+ _sql_constraints = [
+ ('name_uniq', 'unique (code)', "Code already exists !"),
+ ]
+
+ name = fields.Char(string="Name", required=True)
+ code = fields.Char(string="Code", default=get_code)
+ voucher = fields.Many2one('gift.voucher.pos', string="Voucher", required=True)
+ start_date = fields.Date(string="Start Date")
+ end_date = fields.Date(string="End Date")
+ partner_id = fields.Many2one('res.partner', string="Limit to a Single Partner", help='Limit to a Single Partner')
+ limit = fields.Integer(string="Total Available For Each User", default=1, help='Total Available For Each User')
+ total_avail = fields.Integer(string="Total Available", default=1)
+
+ voucher_val = fields.Float(string="Voucher Value", help='The amount for the voucher.')
+ type = fields.Selection([
+ ('fixed', 'Fixed Amount'),
+ ('percentage', 'Percentage'),
+ ], store=True, default='fixed')
+
+ @api.onchange('voucher_val')
+ def check_val(self):
+ if self.voucher_val > self.voucher.max_value or self.voucher_val < self.voucher.min_value:
+ raise UserError(_("Please check the voucher value"))
+
+
+class CouponPartnerPos(models.Model):
+ _name = 'partner.coupon.pos'
+
+ partner_id = fields.Many2one('res.partner', string="Partner")
+ coupon_pos = fields.Char(string="Coupon Applied")
+ number_pos = fields.Integer(string="Number of Times Used")
+
+ def update_history(self, vals):
+ if vals:
+ h_obj = self.env['partner.coupon.pos']
+ history = h_obj.search([('coupon_pos', '=', vals['coupon_pos']),('partner_id', '=', vals['partner_id'])], limit=1)
+ coupon = self.env['gift.coupon.pos'].search([('code', '=', vals['coupon_pos'])], limit=1)
+ if history:
+ history.number_pos += 1
+ coupon.total_avail -= 1
+ else:
+ coupon.total_avail -= 1
+ rec = {
+ 'partner_id': vals['partner_id'],
+ 'number_pos': 1,
+ 'coupon_pos': vals['coupon_pos']
+ }
+ h_obj.create(rec)
+ return True
+
+
+class PartnerExtendedPos(models.Model):
+ _inherit = 'res.partner'
+
+ applied_coupon_pos = fields.One2many('partner.coupon.pos', 'partner_id', string="Coupons Applied From POS")
diff --git a/vouchers_pos/security/ir.model.access.csv b/vouchers_pos/security/ir.model.access.csv
new file mode 100644
index 000000000..be5525444
--- /dev/null
+++ b/vouchers_pos/security/ir.model.access.csv
@@ -0,0 +1,7 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+voucher_mgr,access_voucher_mgr,vouchers_pos.model_gift_voucher_pos,point_of_sale.group_pos_manager,1,1,1,1
+coupon_mgr,access_coupon_mgr,vouchers_pos.model_gift_coupon_pos,point_of_sale.group_pos_manager,1,1,1,1
+partner_coupon_mgr,access_partner_coupon_mgr,vouchers_pos.model_partner_coupon_pos,point_of_sale.group_pos_manager,1,1,1,1
+voucher_usr,access_voucher_usr,vouchers_pos.model_gift_voucher_pos,point_of_sale.group_pos_user,1,0,0,0
+coupon_usr,access_coupon_usr,vouchers_pos.model_gift_coupon_pos,point_of_sale.group_pos_user,1,0,0,0
+partner_coupon_usr,access_partner_coupon_usr,vouchers_pos.model_partner_coupon_pos,point_of_sale.group_pos_user,1,0,0,0
diff --git a/vouchers_pos/static/description/banner.jpg b/vouchers_pos/static/description/banner.jpg
new file mode 100644
index 000000000..384d5d6c6
Binary files /dev/null and b/vouchers_pos/static/description/banner.jpg differ
diff --git a/vouchers_pos/static/description/cybro_logo.png b/vouchers_pos/static/description/cybro_logo.png
new file mode 100644
index 000000000..bb309114c
Binary files /dev/null and b/vouchers_pos/static/description/cybro_logo.png differ
diff --git a/vouchers_pos/static/description/icon.png b/vouchers_pos/static/description/icon.png
new file mode 100644
index 000000000..df9234a31
Binary files /dev/null and b/vouchers_pos/static/description/icon.png differ
diff --git a/vouchers_pos/static/description/index.html b/vouchers_pos/static/description/index.html
new file mode 100644
index 000000000..f97799c0b
--- /dev/null
+++ b/vouchers_pos/static/description/index.html
@@ -0,0 +1,404 @@
+
+
+
+ Vouchers and Coupons
+
+
+ Manage Gift Vouchers and Coupon Codes in Point of Sale
+