Пример #1
0
class Component(models.Model):
    name = models.CharField(max_length=64)
    category = models.ForeignKey(ComponentCategory,
                                 db_constraint=False,
                                 on_delete=models.DO_NOTHING)
    uid = models.CharField(max_length=64, null=False,
                           default="")  #uuid.uuid4().hex)
    unit = mysql_models.EnumField(
        choices=['in', 'mm', 'oz', 'ml', 'hours', 'each'], default='each')
    thumbnail = models.ImageField(blank=True, null=True)
    unit_price = models.DecimalField(decimal_places=4, max_digits=10)
    in_stock = models.IntegerField(default=0)
    unit_threshold = models.IntegerField(default=0)
    vendor_url = models.URLField(blank=True, null=True)
    active = models.BooleanField(default=True)

    def __str__(self):
        return self.name

    def inactive(self, page=0):
        return Paginator.page(Component.objects.filter(active=False), page)

    def low(self, page=0):
        return Paginator.page(
            Component.objects.filter(active=True,
                                     in_stock__lte='unit_threshold'))

    def shortfall(self):
        if (self.unit_threshold > 0):
            return abs(self.in_stock - self.unit_threshold)
        else:
            return 0

    shortfall.admin_order_field = "shortfall"
Пример #2
0
class ProductionQueue(models.Model):
    product_option = models.ForeignKey(ProductOption, on_delete=models.CASCADE)
    units = models.IntegerField(default=0)
    status = mysql_models.EnumField(
        choices=['Pending', 'In Progress', 'On Hold'], default="Pending")

    def __str__(self):
        return self.product_option.__str__()
Пример #3
0
class Greencheck(mysql_models.Model):
    # NOTE: ideally we would have these two as Foreign keys, as the greencheck
    # table links back to where the recorded ip ranges we checked against are.
    # However, some `GreencheckIP` ip range objects have been deleted over
    # the years.
    # Also,
    # We might be better off with a special 'DELETED' Greencheck IP
    # to at least track this properly.
    hostingprovider = models.IntegerField(db_column="id_hp", default=0)
    # hostingprovider = models.ForeignKey(
    #     ac_models.Hostingprovider,
    #     db_column="id_hp",
    #     on_delete=models.CASCADE,
    #     blank=True,
    #     null=True,
    # )
    greencheck_ip = models.IntegerField(db_column="id_greencheck", default=0)
    # greencheck_ip = models.ForeignKey(
    #     GreencheckIp,
    #     on_delete=models.CASCADE,
    #     db_column="id_greencheck",
    #     blank=True,
    #     null=True,
    # )
    date = models.DateTimeField(db_column="datum")
    green = dj_mysql_models.EnumField(choices=gc_choices.BoolChoice.choices)
    ip = IpAddressField()
    tld = models.CharField(max_length=64)
    type = dj_mysql_models.EnumField(
        choices=gc_choices.GreenlistChoice.choices,
        default=gc_choices.GreenlistChoice.NONE,
    )

    url = models.CharField(max_length=255)

    class Meta:
        db_table = "greencheck_2021"

    def __str__(self):
        return f"{self.url} - {self.ip}"
Пример #4
0
class GreenList(models.Model):
    greencheck = models.ForeignKey(Greencheck,
                                   on_delete=models.CASCADE,
                                   db_column="id_greencheck")
    hostingprovider = models.ForeignKey(ac_models.Hostingprovider,
                                        on_delete=models.CASCADE,
                                        db_column="id_hp")
    last_checked = models.DateTimeField()
    name = models.CharField(max_length=255, db_column="naam")
    type = dj_mysql_models.EnumField(choices=gc_choices.ActionChoice.choices)
    url = models.CharField(max_length=255)
    website = models.CharField(max_length=255)

    class Meta:
        # managed = False
        db_table = "greenlist"
        indexes = [
            models.Index(fields=["url"], name="url"),
        ]
Пример #5
0
class Parent(models.Model):
    hid = models.CharField(max_length=7, null=True)
    first = models.CharField(max_length=20)
    family_id = models.PositiveIntegerField()
    alt_last = models.CharField(default='', max_length=30)
    sex_choices = sex_choices
    sex = models.CharField(max_length=1, choices=sex_choices)
    alt_phone = custom.PhoneNumberField(null=True)
    phone_type = sqlmod.EnumField(choices=['', 'Home', 'Cell', 'Work'],
                                  default='')
    alt_email = models.EmailField(default='')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    rest_model = "parent"
    objects = Parents

    def last(self):
        return self.alt_last if self.alt_last else self.family.last if self.family else "_____"

    def phone(self):
        return self.alt_phone if self.alt_phone > 0 else self.family.phone if self.family else 0

    def unique_phone(self):
        if self.alt_phone.value != self.family.phone.value:
            return self.alt_phone

    def email(self):
        return self.alt_email if self.alt_email else self.family.email if self.family else "_____"

    def unique_email(self):
        if self.alt_email != self.family.email:
            if self.sex == 'M' or (self.family.father and self.alt_email !=
                                   self.family.father.alt_email):
                return self.alt_email

    def family(self):
        return Families.fetch(id=self.family_id)

    def emoji(self):
        return "👨" if self.sex == 'M' else "👩"

    def stand(self, me):
        if me.owner_type == 'Family':
            family = me.owner
        elif me.owner_type == 'Student':
            family = me.owner.family
        else:
            family = None
        return self.family.id == family.id

    def __getattribute__(self, field):
        if field in ['last', 'phone', 'email', 'family', 'emoji']:
            call = super(Parent, self).__getattribute__(field)
            return call()
        else:
            return super(Parent, self).__getattribute__(field)

    def __str__(self):
        if self.sex == 'M':
            prefix = 'Mr. '
        elif self.sex == 'F':
            prefix = 'Mrs. '
        return prefix + self.first + ' ' + self.last
Пример #6
0
class Family(models.Model):
    hid = models.CharField(max_length=10, null=True)
    oid = models.PositiveIntegerField(default=0)
    last = models.CharField(max_length=30)
    name_num = models.PositiveIntegerField(default=0)
    phone = custom.PhoneNumberField()
    phone_type = sqlmod.EnumField(choices=['', 'Home', 'Cell', 'Work'],
                                  default='')
    email = models.EmailField()
    mother = models.ForeignKey(Parent, null=True, related_name='mother')
    father = models.ForeignKey(Parent, null=True, related_name='father')
    address = models.OneToOneField(Address,
                                   null=True,
                                   primary_key=False,
                                   rel=True)
    policyYear = models.DecimalField(max_digits=4, decimal_places=0, null=True)
    policyPage = models.PositiveIntegerField(default=0)
    policyDate = models.DateTimeField(null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    rest_model = "family"
    objects = Families

    def stand(self, me):
        if me.owner_type == 'Family':
            family = me.owner
        elif me.owner_type == 'Student':
            family = me.owner.family
        else:
            family = None
        return self.id == family.id

    def has_accepted_policy(self, year=getyear()):
        policy = Policies.fetch(year=year)
        return not policy or self.policyYear == year and self.policyPage == policy.nPages

    def unique_last(self):
        return '{} #{}'.format(self.last,
                               self.name_num) if self.name_num else self.last

    def unique_last_in(self, year):
        clashes = Families.filter(
            last=self.last,
            children__enrollment__course__year=year).exclude(id=self.id)
        if clashes:
            return self.unique_last
        else:
            return self.last

    def emoji(self):
        people = []
        if self.father:
            people.append("👨")
        if self.mother:
            people.append("👩")
        if not people:
            people = ["👨", "👩"]
        nGirls = len(self.children.filter(sex='F'))
        nBoys = len(self.children.filter(sex='M'))
        if nGirls:
            people.append("👧")
        if nBoys:
            people.append("👦")
        if nGirls > 1 and nBoys == 0:
            people.append("👧")
        if nBoys > 1 and nGirls == 0:
            people.append("👦")
        return "‍".join(people)

    def accounts(self):
        return Users.filter(owner_type='Family', owner_id=self.id)

    def invoices(self):
        return Invoices.filter(family=self)

    # def children(self):
    # 	return Students.filter(family_id=self.id).order_by('birthday')
    def children_eligible_in(self, year):
        ids = []
        for child in self.children.all():
            if set(Each(list(child.course_menu())).status) - set(['not_elig']):
                ids.append(child.id)
        return Students.filter(id__in=ids)

    def children_enrolled_in(self, year):
        return self.children.filter(enrollment__course__year=year).distinct()

    def all_enrollments_in(self, year):
        return Enrollments.filter(student__family=self, course__year=year)

    def all_enrollments(self):
        return self.all_enrollments_in(getyear())

    def enrollments_in(self, year):
        qset = self.all_enrollments_in(year)
        qset = qset.exclude(status__in=['nonexist', 'aud_fail', 'aud_drop'])
        qset = qset.order_by('created_at')
        return qset

    def enrollments(self):
        return self.enrollments_in(getyear())

    def live_enrollments_in(self, year):
        qset = self.all_enrollments_in(year)
        qset = qset.filter(status__in=[
            'enrolled', 'invoiced', 'need_pay', 'aud_pend', 'pendpass',
            'pendfail', 'pend_pub', 'fail_pub', 'aud_pass', 'aud_drop',
            'aud_lock', 'maydefer', 'deferred'
        ])
        qset = qset.order_by('created_at')
        return qset

    def live_enrollments(self):
        return self.live_enrollments_in(getyear())

    def total_tuition_in(self, year):
        return sum(Each(self.enrollments_in(year)).course.tuition)

    def paid_tuition_in(self, year):
        return sum(Each(Invoices.filter(family=self, status='P')).amount)
        # return sum(collect(self.enrollments_in(year), lambda enr: 0 if enr.isAudition else enr.course.tuition()))
    def pend_tuition_in(self, year):
        return sum(Each(self.pend_enrollments_in(year)).course.tuition)
        # return sum(Each(Invoices.filter(family=self,status='N')).amount) + sum(Each(Enrollments.filter(student__family=self, course__year=year, isAudition=True, happened=False)).course).tuition)
    def unpaid_tuition_in(self, year):
        return self.total_tuition_in(year) - self.pend_tuition_in(
            year) - self.paid_tuition_in(year)

    def volunteer_total_in(self, year):
        return max([0.0] + list(
            collect(self.enrollments_in(year),
                    lambda enr: enr.course.vol_hours)))

    def hours_worked_in(self, year):
        return 0.0

    def hours_signed_in(self, year):
        return 0.0

    def fate(self, year=None):
        if not year:
            year = getyear()
        Each(self.children.all()).fate(year)

    def delete(self):
        # Manual cascading for Parents and Users
        safe_delete(self.mother)
        safe_delete(self.father)
        safe_delete(self.address)
        Users.filter(owner=self).delete()
        return super(Family, self).delete()

    def clear_name_num(self):
        self.name_num = 0
        self.save()

    def update_name_num(self, fix_all=False):
        clashes = Families.filter(last=self.last).exclude(id=self.id)
        older = clashes.filter(created_at__lt=self.created_at)
        if fix_all:
            Each(older).update_name_num()
        if older:
            self.name_num = max(Each(older).name_num) + 1
        else:
            self.name_num = int(bool(clashes))
        self.save()
        if fix_all:
            newer = clashes.filter(created_at__lt=self.created_at)
            Each(newer).update_name_num()
        return self.name_num

    def __str__(self):
        # return ('{} Family #{}' if self.name_num else '{} Family').format(self.last,self.name_num)
        return '{} Family'.format(self.last)

    def __getattribute__(self, field):
        if field in [
                'unique_last', 'enrollments', 'hours_worked', 'accounts',
                'invoices', 'emoji'
        ]:
            call = super(Family, self).__getattribute__(field)
            return call()
        else:
            return super(Family, self).__getattribute__(field)
Пример #7
0
class CourseTrad(models.Model):
	# General:
	id         = models.CharField(max_length=2, primary_key=True)
	oid        = models.CharField(max_length=10,default='')
	title      = models.CharField(max_length=50)
	abbr       = models.CharField(max_length=13)
	alias      = models.ForeignKey('self', null=True)
	order      = models.FloatField(null=True)
	e          = models.BooleanField(default=True) # Whether course appears in Shopping Cart
	m          = models.BooleanField(default=True) # Whether course appears in Course Menu
	r          = models.BooleanField(default=True) # Whether Courses can inherit from this CourseTrad
	# Commitment:
	day        = custom.DayOfWeekField(default='')
	start      = models.TimeField(default="00:00:00")
	end        = models.TimeField(default="00:00:00")
	nMeets     = models.PositiveIntegerField(default=0)
	place      = models.ForeignKey(Venue, null=True)
	show       = models.CharField(max_length=2, default="")
	sa         = models.BooleanField(default=False)
	semester_choices = [
		('N','Neither'),
		('F','Fall'),
		('S','Spring'),
		('B','Both'),
	]
	semester   = models.CharField(max_length=1,default='N')
	# Prerequisites
	nSlots  = models.PositiveIntegerField(default=0)
	min_age = models.PositiveIntegerField(default=9)
	max_age = models.PositiveIntegerField(default=18)
	min_grd = models.PositiveIntegerField(default=1)
	max_grd = models.PositiveIntegerField(default=12)
	eligex  = models.TextField(default="#")
	default = models.CharField(max_length=8,choices=status_choices)
	# Cost
	early_tuit = models.DecimalField(max_digits=6, decimal_places=2, default=0)
	after_tuit = models.DecimalField(max_digits=6, decimal_places=2, default=0)
	vol_hours  = models.FloatField(default=0)
	the_hours  = models.FloatField(default=0)
	# Behavior
	action_choices = ['none','trig','casc','stat']
	action     = sqlmod.EnumField(choices=action_choices, default='none')
	deferrable = models.BooleanField(default=False) # Whether course may be paid for in October
	droppable  = models.BooleanField(default=True)  # Whether course may be dropped AFTER a successful audition
	# Meta
	created_at = models.DateTimeField(auto_now_add=True)
	updated_at = models.DateTimeField(auto_now=True)
	rest_model = "coursetrad"
	emoji = "🎩"
	objects = CourseTrads

	def stand(self, me):
		if me.owner_type == 'Family':
			return bool(self.courses.filter(enrollment__student__family=me.owner))
		elif me.owner_type == 'Student':
			return bool(self.courses.filter(enrollment__student=me.owner))

	genre_codes = {
		'A':'Acting',
		'B':'Ballet', # Historical
		'C':'Choir',
		'D':'DanceIntensive', # Historical
		# 'E':'',
		'F':'Finale',
		'G':'GeneralAudition',
		'H':'HipHop',
		'I':'Irish',
		'J':'Jazz',
		'K':'PrepaidTickets', # Admin
		'L':'SignLanguage', # Historical
		'M':'Makeup', 
		# 'N':'',
		'O':'Overture', # Historical
		'P':'Tap', # Broadway (Older Beginners)
		# 'Q':'',
		'R':'Statistical',
		'S':'Troupe',
		'T':'Tap',
		# 'U':'',
		# 'V':'',
		'W':'Workshop',
		'X':'Tech',
		# 'Y':'',
		'Z':'Jazz', # Broadway (Older Beginners)
	}
	def genre(self):
		code = self.id[0]
		if code in self.genre_codes:
			return self.genre_codes[code]

	def subid(self):
		return sub(self.id, {
			'SB':'TT',
			'SG':'GB',
			'SJ':'JR',
			'P1':'BT1',
			'P2':'BT2',
			'Z1':'BJ1',
			'Z2':'BJ2',
		})

	def display_semester(self):
		sem = self.semester
		return ' ({})'.format(sem) if sem in 'FS' else ''

	def byFamily(self):
		return '+' in self.eligex

	def courses(self):
		return Courses.filter(tradition_id=self.id)

	def make(self, year):
		course = Courses.fetch(tradition=self, year=year)
		if course:
			return course
		else:
			return Courses.create(tradition=self, year=year)

	def find(self, year, all_students=None):
		course = Courses.fetch(tradition=self, year=year)

	def __str__(self):
		return self.title.upper()
	def __getattribute__(self, field):
		if field in ['courses','genre','subid','display_semester']:
			function = super(CourseTrad, self).__getattribute__(field)
			return function()
		else:
			return super(CourseTrad, self).__getattribute__(field)
	
	def eligible(self, student, year):
		if not student.family.has_accepted_policy(year):
			return False
		course = Courses.fetch(tradition=self, year=year)
		if course:
			return course.eligible(student)
		else:
			return self.check_eligex(student, year)
Пример #8
0
class Enrollment(models.Model):
	student    = models.ForeignKey('people.Student', related_name='enrollment')
	course     = models.ForeignKey(Course, related_name='enrollment')
	invoice    = models.ForeignKey('payment.Invoice', null=True)
	tuition    = models.DecimalField(max_digits=6, decimal_places=2, default=0)
	role       = models.TextField(null=True)
	role_type  = sqlmod.EnumField(choices=['','Chorus','Support','Lead'])
	status_choices = status_choices
	status     = models.CharField(max_length=8,choices=status_choices)
	created_at = models.DateTimeField(auto_now_add=True)
	updated_at = models.DateTimeField(auto_now=True)
	rest_model = "enrollment"
	objects = Enrollments

	def title(self):
		display = self.get_status_display()
		kwargs = self.title_kwargs()
		# if self.course.tradition.byFamily():
		# 	display = '{family} {proverb} recieving {course} {year}'
		return display.format(**kwargs)
	def title_kwargs(self):
		return {
			'student' : self.student.family if self.course.tradition.byFamily() else self.student,
			'family'  : self.student.family,
			'course'  : self.course.title,
			'year'    : self.course.year,
			'invoice' : self.invoice.id if self.invoice else 0,
			'pronoun' : 'he' if self.student.sex == 'M' else 'she',
			'proverb' : 'was' if self.course.year < getyear() else 'is',
			'audskil' : 'audition' if self.course.id[2] in 'SC' else 'skill assessment',
			'article' : 'an' if self.course.id[2] in 'SC' else 'a',		
		}

	def public_status(self):
		return sub(self.status, {"pendpass":"******","pendfail":"aud_pend","aud_fail":"fail_pub"})
	def public_title(self):
		real_status = self.status
		self.status = self.public_status
		title = self.title
		self.status = real_status
		return title

	def emoji(self):
		red    = "&#x2764;&#xfe0f;"
		orange = "&#x1f9e1;"
		yellow = "&#x1f49b;"
		green  = "&#x1f49a;"
		blue   = "&#x1f499;"
		purple = "&#x1f49c;"
		black  = "&#x1f5a4;"
		decor  = "&#x1f49f;"
		ribbon = "&#x1f49d;"
		status_emoji = {
			"enrolled":green,
			"eligible":black,
			"invoiced":orange,
			"need_pay":yellow,
			"not_elig":black,
			"aud_need":black,
			"aud_pend":blue,
			"pendpass":blue,
			"pendfail":blue,
			"pend_pub":blue,
			"fail_pub":black,
			"aud_pass":yellow,
			"aud_fail":black,
			"aud_drop":red,
			"aud_lock":ribbon,
			"conflict":black,
			"need_cur":black,
			"needboth":black,
			"nonexist":black,
			"nopolicy":black,
			"clasfull":black,
			"maydefer":yellow,
			"deferred":purple,
		}
		if self.status in status_emoji:
			return status_emoji[self.status]
		else:
			return ""

	def stand(self, me):
		if me.owner_type == 'Family':
			return self.student.family.id == me.owner.id
		elif me.owner_type == 'Student':
			return self.student.id == me.owner.id

	def price(self):
		if self.tuition:
			return self.tuition
		elif self.status == "enrolled" and self.invoice:
			return self.course.tuition(self.invoice.updated_at)
		else:
			return self.course.tuition()
		
	def pay(self):
		if self.status == "invoiced":
			self.tuition = self.course.tuition()
			self.status = "enrolled"
			self.save()
		return self.tuition

	def accept(self, user):
		if self.status in ["aud_pend","pendpass","pendfail"]:
			if user.permission >= 5:
				# self.course.accept(self.student)
				self.status = "aud_pass" if self.course.tradition.droppable else "aud_lock"
			elif user.permission >= 4:
				self.status = "pendpass"
			self.save()
			self.student.trigger(self.course.year)

	def reject(self, user):
		if self.status in ["aud_pend","pendpass","pendfail"]:
			if user.permission >= 5:
				self.status = "aud_fail"
			elif user.permission >= 4:
				self.status = "pendfail"
			self.save()
			self.student.trigger(self.course.year)

	def fate(self):
		self.status = calc_status(self)
		self.save()
		if self.status in ["not_elig","aud_need","conflict","need_cur","needboth"]:
			self.delete()

	def drop(self):
		if self.status == "aud_pass" and self.course.tradition.droppable:
			self.status = "aud_drop"
			self.save()
			# self.student.family.fate(self.course.year)
		elif self.status == "need_pay":
			self.delete()
		elif self.status == "aud_pend":
			self.status = "aud_need"
			self.save()
		elif self.status == "invoiced":
			invoice = self.invoice
			self.delete()
			invoice.update_amount()
		# if self.course.tradition.action == 'trig':
		self.student.family.fate(self.course.year)

	def defer(self):
		if self.status == "maydefer":
			self.status = "deferred"
			self.save()

	# def cancel(self):
	# 	if self.status == "invoiced":
	# 		self.status = "nonexist"
	# 		self.save()

	def cancel(self):
		if self.status == "invoiced" and self.invoice:
			self.invoice.cancel()

	def __str__(self):
		return '{} in {}'.format(self.student, self.course)

	def __getattribute__(self, field):
		if field in ['paid','eligible','display_student','title','public_title','public_status','emoji']:
			call = super(Enrollment, self).__getattribute__(field)
			return call()
		elif field in Students.fields:
			return self.student.__getattribute__(field)
		elif field in Courses.fields:
			return self.course.__getattribute__(field)
		else:
			return super(Enrollment, self).__getattribute__(field)