Ejemplo n.º 1
0
class RecordModel(db.Document):

    # 系統紀錄
    created_by = db.ReferenceField('sttapp.users.models.SttUser')
    created_at = db.DateTimeField(default=datetime.datetime.utcnow)
    updated_by = db.ObjectIdField()
    updated_at = db.DateTimeField()

    meta = {
        'abstract': True,
    }

    @staticmethod
    def _dt_to_str(dt):
        tz_dt = get_local_dt(dt)
        return tz_dt.strftime("%Y/%m/%d %H:%M")

    @staticmethod
    def _d_to_str(dt):
        # 不可進行時區轉換
        return dt.strftime("%Y/%m/%d")

    @property
    def created_at_str(self):
        return self._dt_to_str(self.created_at)

    @property
    def updated_at_str(self):
        return self._dt_to_str(self.updated_at)
Ejemplo n.º 2
0
class MyHistory(RecordModel):

    order = db.IntField()
    title = db.StringField()
    start_date = db.DateTimeField()
    end_date = db.DateTimeField()
    days = db.IntField()
    event_type = db.StringField()
    link = db.URLField()
    user_id = db.ObjectIdField()

    meta = {'ordering': ['order'], 'indexes': ['user_id']}

    @property
    def start_date_str(self):
        if self.start_date:
            return super()._d_to_str(self.start_date)
        return ""

    @property
    def end_date_str(self):
        if self.end_date:
            return super()._d_to_str(self.end_date)
        return ""

    @property
    def difficulty(self):
        if self.days <= 3:
            return Difficulty.LEVEL_D
        if self.days <= 5:
            return Difficulty.LEVEL_C
        if self.days <= 8:
            return Difficulty.LEVEL_B
        else:
            return Difficulty.LEVEL_A

    def serialize(self):
        obj = {
            'id':
            str(self.id),
            'order':
            self.order,
            'date_str':
            "{}~{}".format(self.start_date_str, self.end_date_str),
            'title':
            self.title or "",
            'event_type':
            self.event_type or "",
            'days':
            self.days or "",
            'difficulty':
            self.difficulty or "",
            'link':
            '''
                <a type="button" class="btn btn-default btn-round-full" 
                href="{}" target="_blank"><i class="tf-attachment"></i></a>
            '''.format(self.link) if self.link else "",
        }
        return obj
Ejemplo n.º 3
0
class SttUser(User):

    # 基本資料
    name = db.StringField()  # 真實姓名
    password_hash = db.StringField()
    birthday = db.DateTimeField()
    cellphone_number = db.StringField()
    introduction = db.StringField()

    # 學校資料
    department = db.StringField()  # 系所,例如:物理、水利
    graduation_year = db.IntField()  # 畢業年,例如:102

    # 社團相關資料
    group = db.StringField(choices=Group.get_choices())  # 嚮導隊
    position = db.StringField(choices=Position.get_choices())  # 工作組,總務、教學
    level = db.StringField(choices=Level.get_choices())  # 新生、隊員、幹部等
    member_id = db.ObjectIdField()
    identity = db.StringField(choices=Identity.get_choices())  # 在校狀態

    # 系統紀錄
    updated_at = db.DateTimeField()
    invitation_info = db.EmbeddedDocumentField(InvitationInfo)

    meta = {
        'ordering': ['-created_at'],
        'indexes': [
            'name',
        ]
    }

    @property
    def birthday_str(self):
        if self.birthday:
            return self.birthday.strftime("%Y/%m/%d")
        return ""

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)
Ejemplo n.º 4
0
class User(UserMixin, RecordModel):

    username = db.StringField()  # 網站顯示的綽號
    email = db.EmailField(unique=True)  # 登入帳號

    last_login_at = db.DateTimeField()
    social_login_with = db.StringField()
    social_login_id = db.StringField()
    profile_img = db.URLField()

    meta = {
        'abstract': True,
    }

    @property
    def last_login_at_str(self):
        return super()._dt_to_str(self.last_login_at)
Ejemplo n.º 5
0
class Event(RecordModel):

    proposal = db.ReferenceField('sttapp.proposals.models.Proposal',
                                 unique=True,
                                 reverse_delete_rule=mongoengine.DENY)
    img_url = db.URLField()
    real_title = db.StringField()
    real_itinerary_list = db.EmbeddedDocumentListField(Itinerary)
    real_days = db.IntField()
    feedback = db.StringField()
    gathering_time = db.DateTimeField()
    gathering_point = db.StringField()
    status = db.StringField(choices=EventStatus.get_choices(False),
                            default=EventStatus.get_map()[EventStatus.NORM])

    # more about indexes: https://docs.mongoengine.org/guide/defining-documents.html#indexes
    meta = {
        'ordering': ['-created_at'],
        'indexes': ['real_title', 'created_at']
    }

    @property
    def gathering_time_str(self):
        return self.gathering_time.strftime("%Y/%m/%d %H:%M")

    @property
    def itinerary_same_check(self):
        if self.status == EventStatus.get_map()[
                EventStatus.BACK] and not self.real_itinerary_list:
            return True
        return False

    @property
    def title(self):
        return self.real_title or self.proposal.title

    @property
    def days(self):
        return self.real_days or self.proposal.days
Ejemplo n.º 6
0
class Member(RecordModel):

    # 基本資料
    name = db.StringField()
    nickname = db.StringField()
    security_number = db.StringField(unique=True, sparse=True)
    birthday = db.DateTimeField()
    cellphone_number = db.StringField()

    # 進階資料
    drug_allergy = db.StringField(default="NKDA")
    blood_type = db.StringField()
    level = db.StringField(choices=CHOICES["level"])  # 新生、隊員、幹部等
    group = db.StringField(choices=CHOICES["group"])

    # 學校資訊
    student_id = db.StringField()
    department_and_grade = db.StringField()  # ex: 水利四 / ob / 物理所 / 校外

    # 最高資歷
    highest_difficulty = db.StringField(choices=CHOICES["difficulty"])  # 級數
    highest_difficulty_experience = db.StringField()  # 手動輸入出隊資歷,ex: 哈崙鐵道

    # 緊急聯絡人
    emergency_contact = db.StringField()
    emergency_contact_phone = db.StringField()
    emergency_contact_relationship = db.StringField()  # ex: 父子、母子

    user_id = db.ObjectIdField()
    event_ids = db.ListField(db.ObjectIdField(), default=list)

    meta = {
        'indexes': ['security_number', 'cellphone_number', ]
    }

    @property
    def display_name(self):
        return self.nickname or self.name

    @property
    def selected_name(self):
        return "{}|{}".format(self.name, self.security_number)

    @property
    def gender(self):
        if self.security_number[1] == "1":
            return Gender.MALE
        elif self.security_number[1] == "2":
            return Gender.FEMALE
        else:
            return ""
    
    @property
    def birthday_str(self):
        return self.birthday.strftime("%Y/%m/%d")

    @property
    def is_adult(self):
        today = get_local_dt(datetime.datetime.utcnow()).date()
        return today.replace(year=today.year-20) >= self.birthday.date()

    @property
    def attendee_display(self):
        return "{}({}{})".format(
            self.display_name,
            self.get_level_display()[0] if self.level else "",
            "、{}".format(self.get_group_display()[-1]) if self.group else ""
        )
Ejemplo n.º 7
0
class Proposal(RecordModel):
    title = db.StringField()
    start_date = db.DateTimeField()
    end_date = db.DateTimeField()
    has_d0 = db.BooleanField(default=False)
    event_type = db.StringField(choices=EventType.get_choices())
    days = db.IntField(default=1)
    leader = db.ReferenceField('sttapp.members.models.Member', reverse_delete_rule=mongoengine.DENY)
    guide = db.ReferenceField('sttapp.members.models.Member', reverse_delete_rule=mongoengine.DENY)
    itinerary_list = db.EmbeddedDocumentListField(Itinerary)
    supporter = db.StringField()
    return_plan = db.StringField()
    buffer_days = db.IntField(default=1)
    approach_way = db.StringField()
    radio = db.StringField()
    satellite_telephone = db.StringField()
    attendees = db.ListField(
        db.ReferenceField('sttapp.members.models.Member', reverse_delete_rule=mongoengine.DENY))
    open_time = db.StringField()
    event_id = db.ObjectIdField()

    meta = {
        'ordering': ['-created_at'],
        'indexes': ['title', 'created_at']
    }

    @property
    def start_date_str(self):
        return self.start_date.strftime("%Y/%m/%d")

    @property
    def end_date_str(self):
        return self.end_date.strftime("%Y/%m/%d")

    @property
    def gathering_time_str(self):
        return self._dt_to_str(self.gathering_time)

    @property
    def total_number(self):
        return len(self.attendees)
    
    @property
    def gender_structure(self):
        gender_dict = {display: 0 for field, display in Gender.get_choices(False)}
        for a in self.attendees:
            if not a.gender:
                continue
            gender_dict[a.gender] += 1
        return gender_dict

    @property
    def level_structure(self):
        level_dict = {field: 0 for field, display in Level.get_choices()}
        for a in self.attendees:
            if not getattr(a, 'level'):
                continue
            level_dict[getattr(a, 'level')] += 1
        return level_dict
    
    @property
    def difficulty(self):
        if self.days <= 3:
            return Difficulty.LEVEL_D
        if self.days <= 5:
            return Difficulty.LEVEL_C
        if self.days <= 8:
            return Difficulty.LEVEL_B
        else:
            return Difficulty.LEVEL_A

    @property
    def attendees_display(self):
        if not self.attendees:
            return ""
        return ", ".join(att.selected_name for att in self.attendees) + ", "

    @property
    def leader_display(self):
        if not self.leader:
            return ""
        return self.leader.selected_name

    @property
    def guide_display(self):
        if not self.guide:
            return ""
        return self.guide.selected_name

    def validate_for_publishing(self):
        required_fields = {
            "title": "隊伍名稱", 
            "start_date": "上山日期", 
            "days": "天數",
            "leader": "領隊", 
            "guide": "嚮導",          
            "supporter": "留守", 
            "buffer_days": "預備天數", 
            "attendees": "成員", 
            "return_plan": "撤退計畫",
            "approach_way": "交通方式", 
            "event_type": "隊伍類型", 
        }
        failed_fields = []
        for field, name in required_fields.items():
            if not getattr(self, field):
                failed_fields.append(name)
        
        failed_itinerary = []
        for itinerary in self.itinerary_list:
            if not itinerary.content:
                failed_itinerary.append("D{}".format(itinerary.day_number))
        return failed_fields, failed_itinerary
Ejemplo n.º 8
0
class InvitationInfo(db.EmbeddedDocument):

    invited_by = db.ObjectIdField()
    invited_at = db.DateTimeField()
    email = db.EmailField()
    token = db.StringField()