from odoo import models, fields, api from datetime import datetime, timedelta from odoo.exceptions import ValidationError class Voucher(models.Model): _name = 'voucher' _rec_name = 'display_name' display_name = fields.Char(string='Display Name', compute='_compute_display_name') name = fields.Char(string='Name') image = fields.Binary(string='Image') code = fields.Char(string='Code', help='Kode voucher yang akan berlaku untuk pengguna') description = fields.Text(string='Description') discount_amount = fields.Integer(string='Discount Amount') discount_type = fields.Selection( selection=[ ('percentage', 'Percentage'), ('fixed_price', 'Fixed Price'), ], string='Discount Type', help='Select the type of discount:\n' '- Percentage: Persentage dari total harga.\n' '- Fixed Price: Jumlah tetap yang dikurangi dari harga total.' ) visibility = fields.Selection( selection=[ ('public', 'Public'), ('private', 'Private') ], string='Visibility', help='Select the visibility:\n' '- Public: Ditampilkan kepada seluruh pengguna.\n' '- Private: Tidak ditampilkan kepada seluruh pengguna.' ) start_time = fields.Datetime(string='Start Time') end_time = fields.Datetime(string='End Time') min_purchase_amount = fields.Integer(string='Min. Purchase Amount', help='Nominal minimum untuk dapat menggunakan voucher. Isi 0 jika tidak ada minimum purchase amount') max_discount_amount = fields.Integer(string='Max. Discount Amount', help='Max nominal terhadap persentase diskon') order_ids = fields.One2many('sale.order', 'voucher_id', string='Order') limit = fields.Integer(string='Limit', help='Voucher limit by sale order. Masukan 0 untuk tanpa limit') manufacture_ids = fields.Many2many('x_manufactures', string='Brands', help='Voucher appplied only for brand') excl_pricelist_ids = fields.Many2many('product.pricelist', string='Excluded Pricelists', help='Hide voucher from selected exclude pricelist') @api.constrains('description') def _check_description_length(self): for record in self: if record.description and len(record.description) > 120: raise ValidationError('Description cannot exceed 120 characters') def _compute_display_name(self): for voucher in self: voucher.display_name = f'{voucher.name} ({voucher.code})' def res_format(self): datas = [voucher.format() for voucher in self] return datas def format(self): ir_attachment = self.env['ir.attachment'] discount_type = self.discount_type max_discount_amount = self.max_discount_amount if discount_type == 'percentage' else 0 data = { 'id': self.id, 'image': ir_attachment.api_image('voucher', 'image', self.id), 'name': self.name, 'code': self.code, 'description': self.description, 'discount_amount': self.discount_amount, 'discount_type': discount_type, 'remaining_time': self._res_remaining_time(), 'min_purchase_amount': self.min_purchase_amount, 'max_discount_amount': max_discount_amount, 'manufacture_names': ", ".join([x.x_name for x in self.manufacture_ids]), 'manufacture_ids': [x.id for x in self.manufacture_ids], 'excl_pricelist_ids': [x.id for x in self.excl_pricelist_ids], } return data def _res_remaining_time(self): seconds = self._get_remaining_time() remaining_time = timedelta(seconds=seconds) hours = remaining_time.seconds // 3600 minutes = remaining_time.seconds // 60 if remaining_time.days > 0: time = remaining_time.days unit = 'hari' elif hours > 0: time = hours unit = 'jam' else: time = minutes unit = 'menit' return f'{time} {unit}' def _get_remaining_time(self): calculate_time = self.end_time - datetime.now() return round(calculate_time.total_seconds()) def calculate_discount(self, price): if price < self.min_purchase_amount: return 0 if self.discount_type == 'fixed_price': return self.discount_amount if self.discount_type == 'percentage': discount = price * self.discount_amount / 100 max_disc = self.max_discount_amount return discount if max_disc == 0 else min(discount, max_disc) return 0 def get_active_voucher(self, parameter): current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') parameter += [ ('start_time', '<=', current_time), ('end_time', '>=', current_time), ] vouchers = self.search(parameter, order='min_purchase_amount ASC') return vouchers