class Profile(models.Model): user = models.OneToOneField('accounts.User', related_name='profile', on_delete=models.CASCADE) address = models.TextField() GENDER = Choices( (1, 'male', 'Male'), (2, 'female', 'Female'), ) gender = models.PositiveIntegerField(choices=GENDER, blank=True, null=True) birthday = models.DateField(blank=True, null=True) specialization = models.CharField(max_length=200, blank=True, null=True) avatar = models.ImageField(upload_to=image_upload_path('avatar'), blank=True, null=True) # Social fields linkedin = models.URLField(blank=True, max_length=255) git_repo = models.URLField(blank=True, max_length=255) blog = models.URLField(blank=True, max_length=255) facebook = models.URLField(blank=True, max_length=255) youtube = models.URLField(blank=True, max_length=255) twitter = models.CharField(blank=True, max_length=30) instagram = models.CharField(blank=True, max_length=30) telegram_id = models.CharField(blank=True, max_length=50) def __str__(self): return self.user.username def save(self, *args, **kwargs): super().save(*args, **kwargs) if self.avatar: # Fit avatar to 200px x 200px img = Image.open(self.avatar) img = ImageOps.fit(img, (200, 200)) img.save(self.avatar.path)
class Banner(models.Model): title = models.CharField(max_length=255) link = models.CharField(max_length=512) image = models.ImageField( upload_to=image_upload_path('banners', use_dir_date=False)) show_web = models.BooleanField() show_app = models.BooleanField() def __str__(self): return self.title
class LogoSponsor(models.Model): name = models.CharField(max_length=150) image = models.ImageField( upload_to=image_upload_path('sponsors', use_dir_date=False)) display_order = models.PositiveSmallIntegerField() is_visible = models.BooleanField(default=True) website = models.URLField(max_length=255) def __str__(self): return self.name
class Campus(models.Model): name = models.CharField(max_length=255) logo = models.ImageField(upload_to=image_upload_path('campuses', use_dir_date=False), blank=True, null=True) description = models.TextField(blank=True, null=True, default=None) address = models.TextField(blank=True, null=True, default=None) email = models.EmailField(blank=True, null=True, default=None, unique=True) phone = models.CharField(max_length=30, blank=True, null=True, default=None, validators=[validate_mobile_phone]) open_registration = models.BooleanField(default=False) def __str__(self): return self.name
class Setting(models.Model): name = models.CharField(max_length=50, default="Apperance") logo_light = models.ImageField( upload_to=image_upload_path('settings', use_dir_date=False), help_text=_("Akan digunakan pada latar terang"), blank=True, null=True) logo_dark = models.ImageField( upload_to=image_upload_path('settings', use_dir_date=False), help_text=_("Akan digunakan pada latar gelap"), blank=True, null=True) favicon = models.ImageField(upload_to=image_upload_path( 'settings', use_dir_date=False), blank=True, null=True) hide_logo = models.BooleanField(default=False) site_name = models.CharField( max_length=50, help_text=_("Menyumbunyikan logo pada Nav bar")) site_desc = models.TextField("Site Description", blank=True, null=True) hide_site_name = models.BooleanField( default=False, help_text=_("Menyumbunyikan site name pada Nav bar")) footer_title = models.CharField(max_length=100, blank=True, null=True) footer_url = models.CharField(max_length=200, blank=True, null=True) COLOR_THEME = Choices( (1, 'danger', 'danger'), (2, 'warning', 'warning'), (3, 'primary', 'primary'), (4, 'success', 'success'), (5, 'dark', 'dark'), ) color_theme = models.PositiveIntegerField(choices=COLOR_THEME, default=COLOR_THEME.danger) SIDEBAR_COLOR = Choices( (1, 'light', 'light'), (2, 'dark', 'dark'), ) sidebar_color = models.PositiveIntegerField(choices=SIDEBAR_COLOR, default=SIDEBAR_COLOR.light) def __str__(self): return self.name def get_logo_light(self, with_host=False): if self.hide_logo: return "" if self.logo_light: logo = self.logo_light.url else: return static('website/images/logo/logo-polos-warna-30.png') if with_host: return settings.MEDIA_HOST + logo return logo def get_logo_dark(self, with_host=False): if self.hide_logo: return "" if self.logo_dark: logo = self.logo_dark.url else: return static('website/images/logo/logo-polos.png') if with_host: return settings.MEDIA_HOST + logo return logo def get_logo(self, with_host=False): if self.hide_logo: return "" if self.sidebar_color == self.SIDEBAR_COLOR.light: return self.get_logo_light(with_host) else: return self.get_logo_dark(with_host) def get_favicon(self): if self.favicon: return self.favicon.url else: return static('website/images/nolsatu.ico') @classmethod def get_data(cls): setting = cls.objects.first() key = f'setting-{settings.SESSION_COOKIE_DOMAIN}' expired = 3600 * 24 * 7 # cache data to consume course app setting.set_cache_for_course(expired) query_cached = cache.get(key, None) if query_cached: return query_cached cache.set(key, setting, expired) return setting def set_cache_for_course(self, expired): key = f"course-appearance-{settings.SESSION_COOKIE_DOMAIN}" cached = cache.get(key, None) if not cached: cache.set(key, SettingSerializer(self).data, expired) def save(self, *args, **kwargs): super().save(*args, **kwargs) cache.delete(f'setting-{settings.SESSION_COOKIE_DOMAIN}') cache.delete(f"course-appearance-{settings.SESSION_COOKIE_DOMAIN}")
class Graduate(models.Model): certificate_number = models.CharField(max_length=200, blank=True, null=True) user = models.ForeignKey('accounts.User', related_name='graduates', on_delete=models.SET(get_sentinel_user)) student = models.OneToOneField('students.Student', null=True, on_delete=models.SET_NULL) certificate_file = models.FileField( upload_to=image_upload_path('certificates'), blank=True, null=True) created = AutoCreatedField() def __str__(self): return f"{self.user.name} - #{self.certificate_number}" def save(self, *args, **kwargs): if not self.certificate_number: self.certificate_number = self.generate_certificate_number() graduate = super().save(*args, **kwargs) return graduate def generate_certificate_number(self): batch = str(self.student.training.batch) batch = "0" + batch if len(batch) == 1 else batch user_id = str(self.user_id) user_id = "0" + user_id if len(user_id) == 1 else user_id date = self.created.strftime("%Y-%m%d") certificate_number = f"NS-{batch}{user_id}-{date}" return certificate_number def generate_certificate_file(self, force=False): if force: self.generate_and_save_certificate() if not self.certificate_file: self.generate_and_save_certificate() def generate_and_save_certificate(self): filename = 'certificate-%s.pdf' % slugify(self.user.name) filepath = '/tmp/%s' % filename html_template = get_template('backoffice/graduates/certificate.html') last_name = (self.user.last_name if self.user.last_name else self.user.first_name) context = { 'graduate': self, 'user': self.user, 'host': settings.HOST, 'data_qr': f"{self.certificate_number}:{last_name}" } rendered_html = html_template.render(context) options = { 'page-size': 'A4', 'orientation': 'Landscape', 'margin-top': '0in', 'margin-right': '0in', 'margin-bottom': '0in', 'margin-left': '0in', 'no-outline': None } pdf = pdfkit.from_string(rendered_html, filepath, options=options) response = HttpResponse(pdf, content_type='application/pdf') response['Content-Disposition'] = f'attachment; filename={filename}' certificate_file = open(filepath, 'rb') upload_file = SimpleUploadedFile(filename, certificate_file.read()) self.certificate_file = upload_file self.save()
class Graduate(models.Model): certificate_number = models.CharField(max_length=200, blank=True, null=True) user = models.ForeignKey('accounts.User', related_name='graduates', on_delete=models.SET(get_sentinel_user)) student = models.OneToOneField('students.Student', null=True, on_delete=models.SET_NULL) certificate_file = models.FileField( upload_to=image_upload_path('certificates'), blank=True, null=True) is_channeled = models.BooleanField(default=False) channeled_at = models.CharField(max_length=200, default='') created = AutoCreatedField() def __str__(self): return f"{self.user.name} - #{self.certificate_number}" def save(self, *args, **kwargs): if not self.certificate_number: self.certificate_number = self.generate_certificate_number() graduate = super().save(*args, **kwargs) return graduate def generate_certificate_number(self): batch = str(self.student.training.batch) batch = "0" + batch if len(batch) == 1 else batch user_id = str(self.user_id) user_id = "0" + user_id if len(user_id) == 1 else user_id date = self.created.strftime("%Y-%m%d") certificate_number = f"NS-{batch}{user_id}-{date}" return certificate_number def generate_certificate_file(self, force=False): if force: self.generate_and_save_certificate() if not self.certificate_file: self.generate_and_save_certificate() def generate_and_save_certificate(self): filename = 'certificate-%s.pdf' % slugify(self.user.name) filepath = '/tmp/%s' % filename html_template = get_template('backoffice/graduates/certificate.html') last_name = (self.user.last_name if self.user.last_name else self.user.first_name) context = { 'graduate': self, 'user': self.user, 'host': settings.HOST, 'data_qr': f"{self.certificate_number}:{last_name}" } rendered_html = html_template.render(context) options = { 'page-size': 'A4', 'orientation': 'Landscape', 'margin-top': '0in', 'margin-right': '0in', 'margin-bottom': '0in', 'margin-left': '0in', 'no-outline': None } pdf = pdfkit.from_string(rendered_html, filepath, options=options) response = HttpResponse(pdf, content_type='application/pdf') response['Content-Disposition'] = f'attachment; filename={filename}' certificate_file = open(filepath, 'rb') upload_file = SimpleUploadedFile(filename, certificate_file.read()) self.certificate_file = upload_file self.save() @property def valid_until(self): return self.created + timedelta(days=1095) def rating_accumulation(self): return self.ratings.aggregate(avg=Avg('rating'))['avg'] def get_rating_stars(self, rating_accumulation=None): html_stars = [] if rating_accumulation: count = rating_accumulation else: count = self.rating_accumulation() if not count: return "-" for i in range(0, 5): i += 1 if i <= int(count): html_stars.append('<i class="fa fa-star"></i>') else: html_stars.append('<i class="far fa-star"></i>') return "".join(html_stars) def is_name_valid(self, last_name): cond1 = (self.user.last_name and self.user.last_name.lower() == last_name.lower()) cond2 = (not self.user.last_name and self.user.first_name and self.user.first_name.lower() == last_name.lower()) return cond1 or cond2
class Certificate(models.Model): """ Model ini digunakan untuk menyimpan sertifikat secara jamak yang terkait dengan user. tidak terikat dengan model Graduate """ title = models.CharField(max_length=200) number = models.CharField(max_length=200) user = models.ForeignKey('accounts.User', related_name='certificates', on_delete=models.CASCADE) certificate_file = models.FileField( upload_to=image_upload_path('certificates'), blank=True, null=True) created = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.number} - {self.title}" @property def valid_until(self): return self.created + timedelta(days=1095) def generate(self): filename = 'cert-%s-%s.pdf' % (slugify( self.user.username), self.number) filepath = '/tmp/%s' % filename rendered_html = self.preview() options = { 'page-size': 'A4', 'orientation': 'Landscape', 'margin-top': '0.15in', 'margin-right': '0in', 'margin-bottom': '0in', 'margin-left': '0in', 'no-outline': None, 'dpi': 300 } pdf = pdfkit.from_string(rendered_html, filepath, options=options) response = HttpResponse(pdf, content_type='application/pdf') response['Content-Disposition'] = f'attachment; filename={filename}' certificate_file = open(filepath, 'rb') upload_file = SimpleUploadedFile(filename, certificate_file.read()) self.certificate_file = upload_file self.save() def preview(self): html_template = get_template( 'backoffice/graduates/certificate-adinusa.html') last_name = (self.user.last_name if self.user.last_name else self.user.first_name) context = { 'certificate': self, 'user': self.user, 'host': settings.HOST, 'data_qr': f"{self.number}:{last_name}" } rendered_html = html_template.render(context) return rendered_html def is_name_valid(self, last_name): cond1 = (self.user.last_name and self.user.last_name.lower() == last_name.lower()) cond2 = (not self.user.last_name and self.user.first_name and self.user.first_name.lower() == last_name.lower()) return cond1 or cond2
class Profile(models.Model): user = models.OneToOneField('accounts.User', related_name='profile', on_delete=models.CASCADE) address = models.TextField(blank=True, null=True) GENDER = Choices( (1, 'male', 'Male'), (2, 'female', 'Female'), ) gender = models.PositiveIntegerField(choices=GENDER, blank=True, null=True) birthday = models.DateField(blank=True, null=True) specialization = models.CharField(max_length=200, blank=True, null=True) avatar = models.ImageField(upload_to=image_upload_path('avatar'), blank=True, null=True) # Social fields linkedin = models.URLField(blank=True, max_length=255) git_repo = models.URLField(blank=True, max_length=255) blog = models.URLField(blank=True, max_length=255) facebook = models.URLField(blank=True, max_length=255) youtube = models.URLField(blank=True, max_length=255) twitter = models.CharField(blank=True, max_length=30) instagram = models.CharField(blank=True, max_length=30) telegram_id = models.CharField(blank=True, max_length=50) curriculum_vitae = models.FileField(upload_to=file_upload_path('cv'), blank=True, null=True) def __str__(self): return self.user.username def save(self, *args, **kwargs): super().save(*args, **kwargs) if self.avatar: # Fit avatar to 200px x 200px img = Image.open(self.avatar) img = ImageOps.fit(img, (200, 200)) img.save(self.avatar.path) def get_avatar(self, with_host=False): if self.avatar: avatar = self.avatar.url else: avatar = static('website/images/avatar_placeholder.png') if with_host: return settings.MEDIA_HOST + avatar return avatar @property def avatar_with_host(self): return self.get_avatar(with_host=True) @property def curriculum_vitae_with_host(self): if self.curriculum_vitae: return settings.MEDIA_HOST + self.curriculum_vitae.url else: return None