diff --git a/new_module/s_license/__init__.py b/new_module/s_license/__init__.py index 408a6001bdace28f0811aa10474dc3ece2af2e1e..ac3823d19f465e37f0857127ccbfbc3fa4773887 100644 --- a/new_module/s_license/__init__.py +++ b/new_module/s_license/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- from . import models from . import wizard +from . import controllers diff --git a/new_module/s_license/__manifest__.py b/new_module/s_license/__manifest__.py index d7b579c0c0b7f342663f8a6858a44eda657c2e39..153d9a759a0e94f5d7da2a6e624c39e2fe27701d 100644 --- a/new_module/s_license/__manifest__.py +++ b/new_module/s_license/__manifest__.py @@ -13,7 +13,9 @@ 'security/group_security.xml', 'security/ir.model.access.csv', 'views/views.xml', + 'views/license_registration.xml', 'wizard/license_wizard_views.xml', + 'views/import_license.xml', 'views/menu_item.xml', ], 'installable': True, diff --git a/new_module/s_license/controllers/__init__.py b/new_module/s_license/controllers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..f15990643090e623374de05461ea677547aae32d --- /dev/null +++ b/new_module/s_license/controllers/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -* +from . import license_registration +from . import license_check diff --git a/new_module/s_license/controllers/license_check.py b/new_module/s_license/controllers/license_check.py new file mode 100644 index 0000000000000000000000000000000000000000..f461043b14cde9459d5f688b3e1240450d14c074 --- /dev/null +++ b/new_module/s_license/controllers/license_check.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -* +from odoo import http +from odoo.http import request +import json + +class LicenseCheckController(http.Controller): + + @http.route('/api/license/check', type='http', auth='public', methods=['GET', 'POST'], csrf=False) + def check_license(self, key=None, **kwargs): + if not key: + return json.dumps({'error': 'Missing key parameter'}) + + license = request.env['license.manager'].sudo().search([('key', '=', key)], limit=1) + if not license: + return json.dumps({'status': 'Not found'}) + + return json.dumps({'status': license.status}) diff --git a/new_module/s_license/controllers/license_registration.py b/new_module/s_license/controllers/license_registration.py new file mode 100644 index 0000000000000000000000000000000000000000..1f7c509280ce1ef875000d25e8a9a49b4474c855 --- /dev/null +++ b/new_module/s_license/controllers/license_registration.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -* +from odoo import http +from odoo.http import request +import uuid + + +class LicenseController(http.Controller): + @http.route('/license/register', type='http', auth='public', website=True) + def license_registration_form(self, **kw): + return request.render('s_license.license_registration_form') + + @http.route('/license/register/submit', type='http', auth='public', methods=['POST'], website=True, csrf=False) + def submit_license_registration(self, **post): + license_values = { + 'name': post.get('name'), + 'start_date': post.get('start_date'), + 'end_date': post.get('end_date'), + 'key': str(uuid.uuid4()), + 'status': 'pending' + } + request.env['license.manager'].sudo().create(license_values) + return request.render('s_license.license_registration_success') diff --git a/new_module/s_license/models/__init__.py b/new_module/s_license/models/__init__.py index a0fdc10fe11b9eb562881952079e34c2982f8604..82d929f630f16c9e87b78d61614e1d6ee0235167 100644 --- a/new_module/s_license/models/__init__.py +++ b/new_module/s_license/models/__init__.py @@ -1,2 +1,2 @@ # -*- coding: utf-8 -*- -from . import models +from . import license_manager diff --git a/new_module/s_license/models/models.py b/new_module/s_license/models/license_manager.py similarity index 89% rename from new_module/s_license/models/models.py rename to new_module/s_license/models/license_manager.py index 3d5c2d9db5fcecddfb09cefb0ee10da46cf0c718..ad607c1085994a46de4d2e4b523f62b24da5c110 100644 --- a/new_module/s_license/models/models.py +++ b/new_module/s_license/models/license_manager.py @@ -19,7 +19,7 @@ class LicenseManager(models.Model): ('cancelled', 'Cancelled') ], string='Status', default='pending', track_visibility='onchange') - @api.constrains("name", "start_date", "end_date", "key") + @api.constrains("name", "start_date", "end_date") def check_change(self): for record in self: if record.status != "pending": @@ -41,9 +41,9 @@ class LicenseManager(models.Model): 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', - 'res_model': 'enter.date.reason.wizard', + 'res_model': 'license.wizard', 'target': 'new', - 'view_id': self.env.ref("s_license.view_form_enter_date_reason_wizard").id, + 'view_id': self.env.ref("s_license.view_form_license_wizard").id, 'context': { 'default_license_id': self.id, 'default_action_name': action_name, diff --git a/new_module/s_license/security/ir.model.access.csv b/new_module/s_license/security/ir.model.access.csv index 140a494525faa956010cfdd5742c15e03f28afb9..3b12e3034d34397c00554a1dcee7829b8be02f27 100644 --- a/new_module/s_license/security/ir.model.access.csv +++ b/new_module/s_license/security/ir.model.access.csv @@ -1,4 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_s_license_admin,access_s_license_admin,model_license_manager,group_admin_li,1,1,1,1 -access_date_reason,access_date_reason,model_enter_date_reason_wizard,,1,1,1,1 +access_date_reason,access_date_reason,model_license_wizard,,1,1,1,1 +access_import_license,access_import_license,model_license_import_wizard,,1,1,1,1 access_s_license_user,access_s_license_user,model_license_manager,group_user_li,1,0,0,0 diff --git a/new_module/s_license/views/import_license.xml b/new_module/s_license/views/import_license.xml new file mode 100644 index 0000000000000000000000000000000000000000..b4f61fd1e8de80a0229504b3990842ca913a7cfd --- /dev/null +++ b/new_module/s_license/views/import_license.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <record id="view_license_import_wizard_form" model="ir.ui.view"> + <field name="name">license.import.wizard.form</field> + <field name="model">license.import.wizard</field> + <field name="arch" type="xml"> + <form string="Import License"> + <group> + <field name="file" filename="file_name" string="File" widget="binary" accept="*.xlsx,*.csv" + required="True"/> + <field name="file_type"/> + </group> + <footer> + <button name="import_file" string="Import" type="object" class="btn-primary"/> + <button string="Cancel" class="btn-secondary" special="cancel"/> + </footer> + </form> + </field> + </record> + <record id="action_import_license" model="ir.actions.act_window"> + <field name="name">Import Licenses</field> + <field name="res_model">license.import.wizard</field> + <field name="view_mode">form</field> + <field name="target">new</field> + </record> +</odoo> diff --git a/new_module/s_license/views/license_registration.xml b/new_module/s_license/views/license_registration.xml new file mode 100644 index 0000000000000000000000000000000000000000..101197bc8203bf1a1947a1c66b5b95f70572d8da --- /dev/null +++ b/new_module/s_license/views/license_registration.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <template id="license_registration_form" name="License Registration Form"> + <t t-call="website.layout"> + <div class="container mt-5"> + <h1>Register for a license</h1> + <form action="/license/register/submit" method="post"> + <div class="form-group"> + <label for="name">Name</label> + <input type="text" class="form-control" id="name" name="name" required=""/> + </div> + <div class="form-group"> + <label for="start_date">Start date</label> + <input type="date" class="form-control" id="start_date" name="start_date" required=""/> + </div> + <div class="form-group"> + <label for="end_date">End date</label> + <input type="date" class="form-control" id="end_date" name="end_date" required=""/> + </div> + <button type="submit" class="btn btn-primary">Register</button> + </form> + </div> + </t> + </template> + + <template id="license_registration_success" name="License Registration Success"> + <t t-call="website.layout"> + <div class="container mt-5"> + <h1>Registered successfully</h1> + </div> + </t> + </template> +</odoo> diff --git a/new_module/s_license/views/menu_item.xml b/new_module/s_license/views/menu_item.xml index bb47af6c0aa1d75c6771b8b004e7bc5bcaced4d0..0656cbe7cbfbda75f4d16fbfe59d107c94727bd2 100644 --- a/new_module/s_license/views/menu_item.xml +++ b/new_module/s_license/views/menu_item.xml @@ -1,5 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <odoo> <menuitem id="menu_license_module_root" name="License Module"/> - <menuitem id="menu_license_manager" name="Licenses" parent="menu_license_module_root" action="action_license_manager"/> + <menuitem id="menu_license_manager" name="Licenses" parent="menu_license_module_root" + action="action_license_manager"/> + <menuitem id="menu_license_import" parent="menu_license_module_root" name="Import Licenses" + action="action_import_license"/> </odoo> diff --git a/new_module/s_license/views/views.xml b/new_module/s_license/views/views.xml index 9aff8fbc611dd8d83fb7c4d865e6eb836467141d..25dea065b8e640c22c4f301620bf06988bb941ce 100644 --- a/new_module/s_license/views/views.xml +++ b/new_module/s_license/views/views.xml @@ -23,7 +23,7 @@ <field name="name"/> <field name="start_date"/> <field name="end_date"/> - <field name="key"/> + <field name="key" readonly="1"/> <field name="note" readonly="1"/> </group> </sheet> diff --git a/new_module/s_license/wizard/__init__.py b/new_module/s_license/wizard/__init__.py index 7c0a66137bd45e69a2ccbde9fda8021fc811ca50..874969f6f86b72aa8a205f37201f92ef77f40faa 100644 --- a/new_module/s_license/wizard/__init__.py +++ b/new_module/s_license/wizard/__init__.py @@ -1,2 +1,3 @@ # -*- coding: utf-8 -*- from . import license_wizard +from . import import_license diff --git a/new_module/s_license/wizard/import_license.py b/new_module/s_license/wizard/import_license.py new file mode 100644 index 0000000000000000000000000000000000000000..eea2bbb9fab16ab31bf86568aab6b9240ee3bc1f --- /dev/null +++ b/new_module/s_license/wizard/import_license.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +from odoo import models, fields, api +import base64 +import tempfile +import binascii +import xlrd +import csv +import io +from datetime import datetime + + +class LicenseImportWizard(models.TransientModel): + _name = 'license.import.wizard' + _description = 'Wizard for importing licenses from Excel file' + + file = fields.Binary(string='File', required=True) + file_type = fields.Selection([('CSV', 'CSV File'), ('XLSX', 'XLSX File')], string='File Type', default='XLSX') + file_name = fields.Char(string='File Name') + + def process_imported_data(self, values): + values['key'] + existing_contact = self.env['license.manager'].search([ + ('key', '=', values['key']) + ]) + if not existing_contact: + self.create_license(values) + else: + self.update_license(existing_contact, values) + + def import_file(self): + if not self.file_type: + return self.show_message("Please upload a file.") + elif self.file_type == 'XLSX': + try: + file = tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") + file.write(binascii.a2b_base64(self.file)) + file.seek(0) + values = {} + workbook = xlrd.open_workbook(file.name) + sheet = workbook.sheet_by_index(0) + except Exception as e: + return self.show_message(e) + keys = ['name', 'start_date', 'end_date', 'key', 'status'] + + for row_no in range(1, sheet.nrows): + # val = {} + line = list( + map(lambda row: isinstance(row.value, bytes) and row.value.encode('utf-8') or str(row.value), + sheet.row(row_no))) + try: + start_date = datetime(*xlrd.xldate_as_tuple(float(line[1]), workbook.datemode)).date() + except ValueError as ve: + self.show_message(f"Invalid start date in row {row_no + 1}: {ve}") + continue + + try: + end_date = datetime(*xlrd.xldate_as_tuple(float(line[2]), workbook.datemode)).date() + except ValueError as ve: + self.show_message(f"Invalid end date in row {row_no + 1}: {ve}") + continue + values.update({ + 'name': line[0], + 'start_date': start_date, + 'end_date': end_date, + 'key': line[3], + 'status': line[4] + }) + self.process_imported_data(values) + elif self.file_type == "CSV": + try: + csv_data = base64.b64decode(self.file) + data_file = io.StringIO(csv_data.decode("utf-8")) + data_file.seek(0) + file_reader = [] + csv_reader = csv.reader(data_file, delimiter=',') + file_reader.extend(csv_reader) + except Exception as e: + return self.show_message(e) + + keys = ['name', 'start_date', 'end_date', 'key', 'status'] + + for i in range(len(file_reader)): + field = list(map(str, file_reader[i])) + values = dict(zip(keys, field)) + if values and i != 0: + self.process_imported_data(values) + + def create_license(self, values): + contact = self.env['license.manager'] + res = contact.create(values) + return res + + def update_license(self, existing_contact, values): + existing_contact.write(values) + + def show_message(self, message): + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'title': 'Import Error', + 'message': message, + 'sticky': False, + } + } diff --git a/new_module/s_license/wizard/license_wizard_views.xml b/new_module/s_license/wizard/license_wizard_views.xml index e7fb894e7ed292c94745ff79c7bfb8a755a1f8ef..5e985f072cb6171d9874dc2a4664a4b924251374 100644 --- a/new_module/s_license/wizard/license_wizard_views.xml +++ b/new_module/s_license/wizard/license_wizard_views.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <odoo> - <record id="view_form_enter_date_reason_wizard" model="ir.ui.view"> + <record id="view_form_license_wizard" model="ir.ui.view"> <field name="name">license.wizard.form</field> <field name="model">license.wizard</field> <field name="arch" type="xml">