diff --git a/event_ticket_registration_limit/__init__.py b/event_ticket_registration_limit/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/event_ticket_registration_limit/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/event_ticket_registration_limit/__manifest__.py b/event_ticket_registration_limit/__manifest__.py new file mode 100644 index 00000000000..0120f76feef --- /dev/null +++ b/event_ticket_registration_limit/__manifest__.py @@ -0,0 +1,19 @@ +{ + 'name': 'Event Ticket Registration Limit', + 'description': 'adds a feature to restrict the maximum number of tickets per registration', + 'category': 'Event/Event Ticket', + 'depends': ['base', 'event', 'website_event'], + + 'version': '1.0', + 'author': 'Kishan B. Gajera', + + 'installable': True, + 'application': True, + + 'license': 'LGPL-3', + + 'data': [ + 'views/event_ticket_view.xml', + 'views/modal_ticket_registration_web_view.xml', + ] +} diff --git a/event_ticket_registration_limit/models/__init__.py b/event_ticket_registration_limit/models/__init__.py new file mode 100644 index 00000000000..34b3cee397f --- /dev/null +++ b/event_ticket_registration_limit/models/__init__.py @@ -0,0 +1 @@ +from . import event_ticket diff --git a/event_ticket_registration_limit/models/event_ticket.py b/event_ticket_registration_limit/models/event_ticket.py new file mode 100644 index 00000000000..97123318296 --- /dev/null +++ b/event_ticket_registration_limit/models/event_ticket.py @@ -0,0 +1,6 @@ +from odoo import models, fields + +class EventTicket(models.Model): + _inherit = "event.event.ticket" + + max_tickets_per_registration = fields.Integer(string="Max Tickets per Registration", help="Define the maximum number of tickets that can be booked per registration.") diff --git a/event_ticket_registration_limit/views/event_ticket_view.xml b/event_ticket_registration_limit/views/event_ticket_view.xml new file mode 100644 index 00000000000..64c4c364cd8 --- /dev/null +++ b/event_ticket_registration_limit/views/event_ticket_view.xml @@ -0,0 +1,13 @@ + + + + event.event.ticket.view.list.inherit + event.event.ticket + + + + + + + + diff --git a/event_ticket_registration_limit/views/modal_ticket_registration_web_view.xml b/event_ticket_registration_limit/views/modal_ticket_registration_web_view.xml new file mode 100644 index 00000000000..29adcba272c --- /dev/null +++ b/event_ticket_registration_limit/views/modal_ticket_registration_web_view.xml @@ -0,0 +1,20 @@ + + + + diff --git a/sale_extension/__init__.py b/sale_extension/__init__.py new file mode 100644 index 00000000000..9b4296142f4 --- /dev/null +++ b/sale_extension/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/sale_extension/__manifest__.py b/sale_extension/__manifest__.py new file mode 100644 index 00000000000..4d895d8a2ab --- /dev/null +++ b/sale_extension/__manifest__.py @@ -0,0 +1,21 @@ +{ + 'name': 'Sale Extension', + 'version': '1.0', + 'depends': ['base', 'sale', 'sale_management'], + 'author': "Kishan B. Gajera", + 'category': 'Sale/Sale', + 'description': """ + A sample sale extension + """, + + 'application': True, + 'installable': True, + + 'data': [ + 'security/ir.model.access.csv', + 'views/sale_order_views.xml', + 'wizard/cost_distribution_wizard.xml', + ], + + 'license':'LGPL-3', +} diff --git a/sale_extension/models/__init__.py b/sale_extension/models/__init__.py new file mode 100644 index 00000000000..8eb9d1d4046 --- /dev/null +++ b/sale_extension/models/__init__.py @@ -0,0 +1 @@ +from . import sale_order_line diff --git a/sale_extension/models/sale_order_line.py b/sale_extension/models/sale_order_line.py new file mode 100644 index 00000000000..270fc42f072 --- /dev/null +++ b/sale_extension/models/sale_order_line.py @@ -0,0 +1,20 @@ +from odoo import models, fields + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + distributed_cost = fields.Float("Distributed Cost") + + def action_distribute_cost(self): + return { + 'type': 'ir.actions.act_window', + 'name': 'Distribute Cost', + 'res_model': 'cost.distribution.wizard', + 'view_mode': 'form', + 'target': 'new', + 'context': { + 'order_id': self.order_id.id, + 'default_order_line_id': self.id, + 'default_price_subtotal': self.price_subtotal, + } + } diff --git a/sale_extension/security/ir.model.access.csv b/sale_extension/security/ir.model.access.csv new file mode 100644 index 00000000000..1f4f31dfaef --- /dev/null +++ b/sale_extension/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +sale_extension.access_cost_distribution_wizard,access_cost_distribution_wizard,sale_extension.model_cost_distribution_wizard,base.group_user,1,1,1,1 diff --git a/sale_extension/views/sale_order_views.xml b/sale_extension/views/sale_order_views.xml new file mode 100644 index 00000000000..ecc7091488a --- /dev/null +++ b/sale_extension/views/sale_order_views.xml @@ -0,0 +1,18 @@ + + + + + sale.order.view.form.inherit + sale.order + + + + + + + + + + + + diff --git a/sale_extension/wizard/__init__.py b/sale_extension/wizard/__init__.py new file mode 100644 index 00000000000..d331964c545 --- /dev/null +++ b/sale_extension/wizard/__init__.py @@ -0,0 +1 @@ +from . import cost_distribution_wizard diff --git a/sale_extension/wizard/cost_distribution_wizard.py b/sale_extension/wizard/cost_distribution_wizard.py new file mode 100644 index 00000000000..e52582e175f --- /dev/null +++ b/sale_extension/wizard/cost_distribution_wizard.py @@ -0,0 +1,52 @@ +from odoo import models, fields, api +from odoo.exceptions import UserError + +class CostDistributionWizard(models.TransientModel): + _name = "cost.distribution.wizard" + _description = "A Wizard to distribute cost over other sales order lines." + + order_line_id = fields.Many2one("sale.order.line", string="Order Line") + order_line_ids = fields.Many2many("sale.order.line", string="Order Lines") + order_line_cost = fields.Float(string="Cost to Distribute") + order_id = fields.Many2one("sale.order") + price_subtotal = fields.Float("Price Subtotal") + + @api.model + def default_get(self, fields_list): + res = super(CostDistributionWizard, self).default_get(fields_list) + order_id = self.env.context.get("order_id") + default_order_line_id = self.env.context.get("default_order_line_id") + default_price_subtotal = self.env.context.get("default_price_subtotal", 0) + + if order_id: + order = self.env["sale.order"].browse(order_id) + order_line_ids = order.order_line.ids + if default_order_line_id in order_line_ids: + order_line_ids.remove(default_order_line_id) + + res.update({ + "order_id": order_id, + "order_line_ids": [(6, 0, order_line_ids)], + "order_line_cost": default_price_subtotal, + }) + + distributed_cost = round(default_price_subtotal / len(order_line_ids), 2) if order_line_ids else 0 + for line in self.env["sale.order.line"].browse(order_line_ids): + line.write({"distributed_cost": distributed_cost}) + + return res + + def distribute_cost(self): + total_cost_distributed = sum(line.distributed_cost for line in self.order_line_ids) + + if total_cost_distributed > self.price_subtotal: + raise UserError("Distributed price is greater than the distributable price.") + + for line in self.order_line_ids: + line.price_subtotal += line.distributed_cost + + original_order_line = self.env["sale.order.line"].browse(self.env.context.get("default_order_line_id")) + original_order_line.price_subtotal -= total_cost_distributed + + if total_cost_distributed == original_order_line.price_subtotal: + pass diff --git a/sale_extension/wizard/cost_distribution_wizard.xml b/sale_extension/wizard/cost_distribution_wizard.xml new file mode 100644 index 00000000000..639fe4d74de --- /dev/null +++ b/sale_extension/wizard/cost_distribution_wizard.xml @@ -0,0 +1,27 @@ + + + + cost.distribution.wizard.form + cost.distribution.wizard + +
+ + + + + + + + + + + + + +
+
+
+
diff --git a/website_appointment_filters/__init__.py b/website_appointment_filters/__init__.py new file mode 100644 index 00000000000..e046e49fbe2 --- /dev/null +++ b/website_appointment_filters/__init__.py @@ -0,0 +1 @@ +from . import controllers diff --git a/website_appointment_filters/__manifest__.py b/website_appointment_filters/__manifest__.py new file mode 100644 index 00000000000..14224a0b6f7 --- /dev/null +++ b/website_appointment_filters/__manifest__.py @@ -0,0 +1,19 @@ +{ + 'name': 'Website Appointment Filters', + 'version': '1.0', + 'depends': ['base', 'website_appointment', 'appointment_account_payment'], + 'author': 'Kishan B. Gajera', + 'category': 'Appointment', + 'description': """ + A sample module to add filters in Appointment Website View + """, + + 'application': True, + 'installable': True, + + 'data': [ + 'views/appointment_templates_appointment_filters.xml' + ], + + 'license':'LGPL-3', +} diff --git a/website_appointment_filters/controllers/__init__.py b/website_appointment_filters/controllers/__init__.py new file mode 100644 index 00000000000..12a7e529b67 --- /dev/null +++ b/website_appointment_filters/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/website_appointment_filters/controllers/main.py b/website_appointment_filters/controllers/main.py new file mode 100644 index 00000000000..6b2ec7f07e4 --- /dev/null +++ b/website_appointment_filters/controllers/main.py @@ -0,0 +1,73 @@ +from odoo import http +from odoo.http import request +from odoo.addons.website_appointment.controllers.appointment import WebsiteAppointment + +class WebsiteAppointmentFiltersController(WebsiteAppointment): + @http.route(['/appointment'], type='http', auth='public', website=True) + def appointment_type_index(self, page=1, **filters): + filtered_appointments_by_mode = set() + filtered_appointments_by_type = set() + filtered_appointments_by_schedule = set() + + if 'mode' in filters: + if filters['mode'] == 'online': + for appointment in request.env['appointment.type'].search([('location_id', '=', None)]): + filtered_appointments_by_mode.add(appointment.id) + elif filters['mode'] == 'offline': + for appointment in request.env['appointment.type'].search([('location_id', '!=', None)]): + filtered_appointments_by_mode.add(appointment.id) + elif filters['mode'] == 'all': + for appointment in request.env['appointment.type'].search([]): + filtered_appointments_by_mode.add(appointment.id) + else: + for appointment in request.env['appointment.type'].search([]): + filtered_appointments_by_mode.add(appointment.id) + + if 'type' in filters: + if filters['type'] == 'paid': + for appointment in request.env['appointment.type'].search([('has_payment_step', '=', 'true')]): + filtered_appointments_by_type.add(appointment.id) + elif filters['type'] == 'free': + for appointment in request.env['appointment.type'].search([('has_payment_step', '!=', 'null')]): + filtered_appointments_by_type.add(appointment.id) + elif filters['type'] == 'all': + for appointment in request.env['appointment.type'].search([]): + filtered_appointments_by_type.add(appointment.id) + else: + for appointment in request.env['appointment.type'].search([]): + filtered_appointments_by_type.add(appointment.id) + + if 'schedule' in filters: + if filters['schedule'] == 'resources': + for appointment in request.env['appointment.type'].search([('schedule_based_on', '=', 'resources')]): + filtered_appointments_by_schedule.add(appointment.id) + elif filters['schedule'] == 'users': + for appointment in request.env['appointment.type'].search([('schedule_based_on', '=', 'users')]): + filtered_appointments_by_schedule.add(appointment.id) + elif filters['schedule'] == 'all': + for appointment in request.env['appointment.type'].search([]): + filtered_appointments_by_schedule.add(appointment.id) + else: + for appointment in request.env['appointment.type'].search([]): + filtered_appointments_by_schedule.add(appointment.id) + + filtered_appointments_by_mode = set(map(lambda id: str(id), filtered_appointments_by_mode)) + filtered_appointments_by_type = set(map(lambda id: str(id), filtered_appointments_by_type)) + filtered_appointments_by_schedule = set(map(lambda id: str(id), filtered_appointments_by_schedule)) + + filters['filter_appointment_type_ids'] = f"[{','.join(filtered_appointments_by_mode & filtered_appointments_by_type & filtered_appointments_by_schedule)}]" + + if 'mode' not in filters.keys(): + filters['mode'] = 'all' + if 'type' not in filters.keys(): + filters['type'] = 'all' + if 'schedule' not in filters.keys(): + filters['schedule'] = 'all' + + + return super().appointment_type_index(**filters) + + def _prepare_appointments_cards_data(self, page, appointment_types, **kwargs): + res = super()._prepare_appointments_cards_data(page, appointment_types, **kwargs) + res.update(kwargs) + return res diff --git a/website_appointment_filters/views/appointment_templates_appointment_filters.xml b/website_appointment_filters/views/appointment_templates_appointment_filters.xml new file mode 100644 index 00000000000..9cc9ac195b9 --- /dev/null +++ b/website_appointment_filters/views/appointment_templates_appointment_filters.xml @@ -0,0 +1,70 @@ + + + + + + + + + +