summaryrefslogtreecommitdiff
path: root/indoteknik_custom/models/voucher.py
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2023-09-11 13:18:02 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2023-09-11 13:18:02 +0700
commit1694e042acb29b476815d29f54f2ec95d37883be (patch)
treed502c76d333cc4c0602e01a98eeb7fb7f0461c01 /indoteknik_custom/models/voucher.py
parent02c2304b242245250177fec6ab3c911d9acba781 (diff)
parent9a630354c1d00e218595db9b2e8cd0b7df9ed97c (diff)
Merge branch 'feature/voucher-group' into production
Diffstat (limited to 'indoteknik_custom/models/voucher.py')
-rw-r--r--indoteknik_custom/models/voucher.py182
1 files changed, 160 insertions, 22 deletions
diff --git a/indoteknik_custom/models/voucher.py b/indoteknik_custom/models/voucher.py
index a7151398..4865db2f 100644
--- a/indoteknik_custom/models/voucher.py
+++ b/indoteknik_custom/models/voucher.py
@@ -1,6 +1,7 @@
from odoo import models, fields, api
from datetime import datetime, timedelta
from odoo.exceptions import ValidationError
+import locale
class Voucher(models.Model):
@@ -13,22 +14,20 @@ class Voucher(models.Model):
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(
+ discount_type = fields.Selection(string='Discount Type',
selection=[
('percentage', 'Percentage'),
('fixed_price', 'Fixed Price'),
- ],
- string='Discount Type',
+ ],
help='Select the type of discount:\n'
- '- Percentage: Persentage dari total harga.\n'
+ '- Percentage: Persentase dari total harga.\n'
'- Fixed Price: Jumlah tetap yang dikurangi dari harga total.'
)
- visibility = fields.Selection(
+ visibility = fields.Selection(string='Visibility',
selection=[
('public', 'Public'),
('private', 'Private')
],
- string='Visibility',
help='Select the visibility:\n'
'- Public: Ditampilkan kepada seluruh pengguna.\n'
'- Private: Tidak ditampilkan kepada seluruh pengguna.'
@@ -37,43 +36,60 @@ class Voucher(models.Model):
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')
+ order_ids = fields.One2many('sale.order', 'applied_voucher_id', string='Order')
+ limit = fields.Integer(
+ string='Limit',
+ default=0,
+ help='Batas penggunaan voucher keseluruhan. Isi dengan angka 0 untuk penggunaan tanpa batas'
+ )
+ limit_user = fields.Integer(
+ string='Limit User',
+ default=0,
+ help='Batas penggunaan voucher per pengguna. Misalnya, jika diisi dengan angka 1, maka setiap pengguna hanya dapat menggunakan voucher ini satu kali. Isi dengan angka 0 untuk penggunaan tanpa batas'
+ )
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')
+ voucher_line = fields.One2many('voucher.line', 'voucher_id', 'Voucher Line')
+ terms_conditions = fields.Html('Terms and Conditions')
+ apply_type = fields.Selection(string='Apply Type', default="all", selection=[
+ ('all', "All product"),
+ ('brand', "Selected product brand"),
+ ])
+ count_order = fields.Integer(string='Count Order', compute='_compute_count_order')
@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')
+ raise ValidationError('Deskripsi tidak boleh lebih dari 120 karakter')
+
+ @api.constrains('limit', 'limit_user')
+ def _check_limit(self):
+ for rec in self:
+ if rec.limit_user > rec.limit:
+ raise ValidationError('Limit user tidak boleh lebih besar dari limit keseluruhan')
def _compute_display_name(self):
for voucher in self:
voucher.display_name = f'{voucher.name} ({voucher.code})'
+ def _compute_count_order(self):
+ for rec in self:
+ rec.count_order = len([x for x in rec.order_ids if x.state != 'cancel'])
+
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
@@ -97,6 +113,82 @@ class Voucher(models.Model):
calculate_time = self.end_time - datetime.now()
return round(calculate_time.total_seconds())
+ def filter_order_line(self, order_line):
+ voucher_manufacture_ids = self.collect_manufacture_ids()
+ results = []
+ for line in order_line:
+ manufacture_id = line['product_id'].x_manufacture.id or None
+ if self.apply_type == 'brand' and manufacture_id not in voucher_manufacture_ids:
+ continue
+
+ product_flashsale = line['product_id']._get_active_flash_sale()
+ if len(product_flashsale) > 0:
+ continue
+
+ results.append(line)
+
+ return results
+
+ def calc_total_order_line(self, order_line):
+ result = { 'all': 0, 'brand': {} }
+ for line in order_line:
+ manufacture_id = line['product_id'].x_manufacture.id or None
+ manufacture_total = result['brand'].get(manufacture_id, 0)
+ result['brand'][manufacture_id] = manufacture_total + line['subtotal']
+ result['all'] += line['subtotal']
+
+ return result
+
+ def calc_discount_amount(self, total):
+ result = { 'all': 0, 'brand': {} }
+
+ if self.apply_type == 'all':
+ if total['all'] < self.min_purchase_amount:
+ return result
+
+ if self.discount_type == 'percentage':
+ decimal_discount = self.discount_amount / 100
+ discount_all = total['all'] * decimal_discount
+ result['all'] = min(discount_all, self.max_discount_amount) if self.max_discount_amount > 0 else discount_all
+ else:
+ result['all'] = self.discount_amount
+
+ return result
+
+ for line in self.voucher_line:
+ manufacture_id = line.manufacture_id.id
+ total_brand = total['brand'].get(manufacture_id, 0)
+
+ discount_brand = 0
+ if total_brand < line.min_purchase_amount:
+ discount_brand = 0
+ elif line.discount_type == 'percentage':
+ decimal_discount = line.discount_amount / 100
+ discount_brand = total_brand * decimal_discount
+ discount_brand = min(discount_brand, line.max_discount_amount) if line.max_discount_amount > 0 else discount_brand
+ else:
+ discount_brand = line.discount_amount
+
+ result['brand'][manufacture_id] = round(discount_brand, 2)
+ result['all'] += discount_brand
+
+ result['all'] = round(result['all'], 2)
+ return result
+
+ def apply(self, order_line):
+ order_line = self.filter_order_line(order_line)
+ amount_total = self.calc_total_order_line(order_line)
+ discount = self.calc_discount_amount(amount_total)
+ return {
+ 'discount': discount,
+ 'total': amount_total,
+ 'type': self.apply_type,
+ 'valid_order': order_line
+ }
+
+ def collect_manufacture_ids(self):
+ return [x.manufacture_id.id for x in self.voucher_line]
+
def calculate_discount(self, price):
if price < self.min_purchase_amount:
return 0
@@ -111,11 +203,57 @@ class Voucher(models.Model):
return 0
- def get_active_voucher(self, parameter):
+ def get_active_voucher(self, domain):
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- parameter += [
+ domain += [
('start_time', '<=', current_time),
('end_time', '>=', current_time),
]
- vouchers = self.search(parameter, order='min_purchase_amount ASC')
- return vouchers \ No newline at end of file
+ vouchers = self.search(domain, order='min_purchase_amount ASC')
+ return vouchers
+
+ def generate_tnc(self):
+ tnc = []
+
+ tnc.append('<ol>')
+ tnc.append('<li>Voucher hanya berlaku apabila pembelian Pengguna sudah memenuhi syarat dan ketentuan yang tertera pada voucher</li>')
+ tnc.append(f'<li>Voucher berlaku {self._res_remaining_time()} lagi</li>')
+ if len(self.voucher_line) > 0:
+ brand_names = ', '.join([x.manufacture_id.x_name for x in self.voucher_line])
+ tnc.append(f'<li>Voucher berlaku untuk produk dari brand {brand_names}</li>')
+ tnc.append(self.generate_detail_tnc())
+ tnc.append('</ol>')
+
+ return ' '.join(tnc)
+
+ def generate_detail_tnc(self):
+ def format_currency(amount):
+ locale.setlocale(locale.LC_ALL, 'id_ID')
+ formatted_amount = locale.format("%d", amount, grouping=True)
+ return f'Rp{formatted_amount}'
+
+ tnc = []
+ if self.apply_type == 'all':
+ tnc.append('<li>')
+ tnc.append('Nominal potongan yang bisa didapatkan sebesar')
+ tnc.append(f'{self.discount_amount}%' if self.discount_type == 'percentage' else format_currency(self.discount_amount))
+
+ if self.discount_type == 'percentage' and self.max_discount_amount > 0:
+ tnc.append(f'hingga {format_currency(self.max_discount_amount)}')
+
+ tnc.append(f'dengan minimum pembelian {format_currency(self.min_purchase_amount)}' if self.min_purchase_amount > 0 else 'tanpa minimum pembelian')
+ tnc.append('</li>')
+ else:
+ for line in self.voucher_line:
+ line_tnc = []
+ line_tnc.append(f'Nominal potongan produk {line.manufacture_id.x_name} yang bisa didapatkan sebesar')
+ line_tnc.append(f'{line.discount_amount}%' if line.discount_type == 'percentage' else format_currency(line.discount_amount))
+
+ if line.discount_type == 'percentage' and line.max_discount_amount > 0:
+ line_tnc.append(f'hingga {format_currency(line.max_discount_amount)}')
+
+ line_tnc.append(f'dengan minimum pembelian {format_currency(line.min_purchase_amount)}' if line.min_purchase_amount > 0 else 'tanpa minimum pembelian')
+ line_tnc = ' '.join(line_tnc)
+ tnc.append(f'<li>{line_tnc}</li>')
+ return ' '.join(tnc)
+