Beispiel #1
0
    def GetOrCreateTroop(self, name, troop_id, group_key, semester_key):
        if len(name) == 0:
            return None
        troop = Troop.get_by_id(Troop.getid(troop_id, group_key, semester_key),
                                use_memcache=True)
        if troop != None:
            if troop.name != name:
                troop.name = name
                if self.commit:
                    troop.put()
        else:
            self.result.append("Ny avdelning %s, ID=%s" % (name, troop_id))
            troop = Troop.create(name, troop_id, group_key, semester_key)
            troop.rapportID = self.rapportID  # TODO: should check the highest number in the sgroup, will work for full imports
            troop.scoutnetID = int(troop_id)
            self.rapportID += 1
            if self.commit:
                troop.put()

        if troop.scoutnetID != int(troop_id):
            troop.scoutnetID = int(troop_id)
            self.result.append("Nytt ID=%d för avdelning %s" %
                               (troop.scoutnetID, name))
            troop.put()

        return troop
Beispiel #2
0
def meeting_date_count_deferred(start_cursor):
    start_time = time.time()
    # collect meetings per scoutgroup and day, count number of trooppersons and meeting attendees 
    meeting_date_counter_dict = memcache.get("meeting_date_counter_dict") # dict: datetime => number of attendee that day
    # {"Scoutgroup X": {meetings:[{"date": 2020-01-01, pers:"23"}, {"date": 2020-01-02, pers:"33"}]}, "Scoutgroup Y": {meetings:[{"date": 2020-01-01, pers:"23"}, {"date": 2020-01-02, pers:"33"}]}}
    there_is_more = true
    while there_is_more:
        sgs, start_cursor, there_is_more = ScoutGroup.query().fetch_page(page_size=1, start_cursor=start_cursor):
        for sg in sgs:
            logging.info("Updating:%s" % (semester.getname()))
            for semester in Semester.query().fetch():
                for troop_key in Troop.query(Troop.scoutgroup==sg.key, Troop.semester_key==semester.key).fetch(keys_only=True):
                    #troopPersonKeys = TroopPerson.query(TroopPerson.troop == troop.key).fetch(keys_only=True)
                    #numTroopPersons = len(TroopPerson)
                    for meeting in Meeting.query(Meeting.troop == troop_key).fetch():
                        attending_count = len(meeting.attendingPersons)
                        meeting_day = meeting.datetime.strftime('%Y-%m-%d')

                        if meeting_date_counter_dict.has_key(meeting_day):
                            attending_count += meeting_date_counter_dict[meeting_day]
                        
                        meeting_date_counter_dict[meeting_day] = attending_count
            
            if there_is_more:
                memcache.delete("meeting_date_counter_dict")
                memcache.add("meeting_date_counter_dict", meeting_date_counter_dict)
                deferred.defer(meeting_date_count_deferred, start_cursor)


    meeting_date_counter = [{"date" : day_key, "delt": meeting_date_counter_dict[day_key]} for day_key in sorted(meeting_date_counter_dict)]
    
    logging.info("meeting_date_count update done")
    memcache.delete("meeting_date_count")
    memcache.add("meeting_date_count", meeting_date_counter)
    memcache.delete("update_meeting_date_count_is_running")
Beispiel #3
0
def dosettroopsemester():
    semester_key = Semester.getOrCreateCurrent().key
    troops = Troop.query().fetch()
    for troop in troops:
        #if troop.semester_key != semester_key:
        troop.semester_key = semester_key
        logging.info("updating semester for: %s", troop.getname())
        troop.put()
Beispiel #4
0
def render_lagerbidrag(request,
                       scoutgroup,
                       context,
                       sgroup_key=None,
                       user=None,
                       trooppersons=None,
                       troop_key=None):
    if context == "group":
        assert sgroup_key is not None
        assert user is not None
        troops = Troop.getTroopsForUser(sgroup_key, user)
    elif context == "troop":
        assert trooppersons is not None
        assert troop_key is not None
    else:
        raise ValueError("Context %s unknown" % context)

    region = request.args.get('region')
    limits = LIMITS[region]
    bidrag = LagerBidrag(scoutgroup.getname())
    bidrag.foreningsID = scoutgroup.foreningsID
    bidrag.firmatecknare = scoutgroup.firmatecknare
    bidrag.firmatecknartelefon = scoutgroup.firmatecknartelefon
    bidrag.firmatecknaremail = scoutgroup.firmatecknaremail
    bidrag.organisationsnummer = scoutgroup.organisationsnummer
    bidrag.email = scoutgroup.epost
    bidrag.phone = scoutgroup.telefon
    bidrag.address = scoutgroup.adress
    bidrag.zipCode = scoutgroup.postadress
    bidrag.account = scoutgroup.bankkonto
    bidrag.contact = request.form['contactperson']
    bidrag.contactemail = request.form.get('contactemail', '')
    bidrag.contactphone = request.form.get('contactphone', '')
    bidrag.site = request.form['site']
    bidrag.dateFrom = request.form['fromDate']
    bidrag.dateTo = request.form['toDate']
    bidrag.hikeduringbreak = request.form.get('hikeduringbreak')
    try:
        if context == "group":
            bidragcontainer = createLagerbidragGroup(limits, scoutgroup,
                                                     troops, bidrag)
        else:
            bidragcontainer = createLagerbidrag(limits, scoutgroup,
                                                trooppersons, troop_key,
                                                bidrag)

        if region == 'gbg':
            return response_gbg(bidragcontainer)
        elif region == 'sthlm':
            return response_sthlm(bidragcontainer)
        else:
            raise ValueError("Unknown region %s" % region)

    except ValueError as e:
        return render_template('error.html', error=str(e))
Beispiel #5
0
def DeleteAllData():
    entries = []
    entries.extend(Person.query().fetch(keys_only=True))
    entries.extend(Troop.query().fetch(keys_only=True))
    entries.extend(ScoutGroup.query().fetch(keys_only=True))
    entries.extend(Meeting.query().fetch(keys_only=True))
    entries.extend(TroopPerson.query().fetch(keys_only=True))
    entries.extend(Semester.query().fetch(keys_only=True))
    entries.extend(TaskProgress.query().fetch(keys_only=True))
    entries.extend(UserPrefs.query().fetch(keys_only=True))
    ndb.delete_multi(entries)
    ndb.get_context().clear_cache()  # clear memcache
Beispiel #6
0
    def DoImport(self, data, semester):
        """
        :param data: from scoutnet
        :type data: str
        :type semester: data.Semester
        :rtype bool
        """
        if not self.commit:
            self.result.append("*** sparar inte, test mode ***")

        if data == None or len(data) < 80:
            self.result.error(u"ingen data från scoutnet")
            return False

        list = scoutnet.GetScoutnetDataListJson(data)
        self.result.append("antal personer=%d" % len(list))
        if len(list) < 1:
            self.result.error(u"för få rader: %d st" % len(list))
            return False

        personsToSave = []
        troopPersonsToSave = []
        activePersonIds = set()  # person.ids that was seen in this import

        leadersToAddToTroops = []  # tuple: (troop_id, person)
        allTroops = {}  # dict: int(troop_id): troop
        for p in list:
            person_id = int(p["id"])  # type: int
            personnr = p["personnr"].replace('-', '')
            person = Person.getByMemberNo(person_id)
            if len(personnr) < 12:
                self.result.warning(
                    u"%d %s %s har inte korrekt personnummer: '%s', hoppar över personen"
                    % (person_id, p["firstname"], p["lastname"], personnr))
                continue

            if person == None:
                person = Person.getByPersonNr(
                    personnr
                )  # fallback lookup, these records will be converted to member_no.

            if person != None:
                person_id = person.key.id()
                person.firstname = p["firstname"]
                person.lastname = p["lastname"]
                person.setpersonnr(personnr)
                if person.notInScoutnet != None:
                    person.notInScoutnet = False
            else:
                person = Person.create(person_id, p["firstname"],
                                       p["lastname"], personnr)
                self.result.append(
                    "Ny person:%s %s %s" %
                    (str(person_id), p["firstname"], p["lastname"]))

            activePersonIds.add(person.key.id())
            person.removed = False
            person.patrool = p["patrool"]
            person.email = p["email"]
            person.member_no = p["member_no"]
            person.phone = p["phone"]
            person.mobile = p["mobile"]
            person.alt_email = p["contact_alt_email"]
            person.mum_name = p["mum_name"]
            person.mum_email = p["mum_email"]
            person.mum_mobile = p["mum_mobile"]
            person.dad_name = p["dad_name"]
            person.dad_email = p["dad_email"]
            person.dad_mobile = p["dad_mobile"]
            person.street = p["street"]
            person.zip_code = p["zip_code"]
            person.zip_name = p["zip_name"]
            person.troop_roles = p["troop_roles"]
            person.group_roles = p["group_roles"]
            if semester.year not in person.member_years:
                person.member_years.append(semester.year)
                person._dirty = True

            scoutgroup = self.GetOrCreateGroup(p["group"], p["group_id"])
            person.scoutgroup = scoutgroup.key
            if len(p["troop"]) == 0:
                self.result.warning(
                    u"Ingen avdelning vald för %s %s %s" %
                    (str(person.member_no), p["firstname"], p["lastname"]))

            troop = self.GetOrCreateTroop(p["troop"], p["troop_id"],
                                          scoutgroup.key, semester.key)
            troop_key = troop.key if troop is not None else None
            if troop is not None:
                allTroops[troop.scoutnetID] = troop

            if person._dirty:
                self.result.append(
                    u"Sparar ändringar:%s %s %s" %
                    (str(person.member_no), p["firstname"], p["lastname"]))
                if self.commit:
                    personsToSave.append(person)

            if troop_key != None:
                if self.commit:
                    tp = TroopPerson.create_if_missing(troop_key, person.key,
                                                       False)
                    if tp:
                        troopPersonsToSave.append(tp)
                        self.result.append(
                            u"Ny avdelning '%s' för:%s %s" %
                            (p["troop"], p["firstname"], p["lastname"]))

            # collect leaders that are assigned to troops in scoutnet
            roles = p['roles']
            if "value" in roles:
                values = roles["value"]
                if len(values) > 0:
                    for name, value in values.items():
                        if name == "troop":
                            for troop_id, troop_roles in value.items():
                                for troop_role_id in troop_roles:
                                    if int(
                                            troop_role_id
                                    ) in scoutnet.Roles.Troop_leader_role_set:
                                        leadersToAddToTroops.append(
                                            (int(troop_id), person))
                                        break

        # pass 2, add leaders to troops according to roles
        for troop_leader in leadersToAddToTroops:
            troop_id = troop_leader[0]
            person = troop_leader[1]
            troop = allTroops.get(troop_id)
            if troop is None:
                troop = Troop.getById(troop_id, semester.key)

            if troop is not None:
                tp = None
                # search among the TroopPersons we are about to add to the database
                for tpcandidate in troopPersonsToSave:
                    if tpcandidate.troop == troop.key and tpcandidate.person == person.key:
                        tpcandidate.leader = True
                        tp = tpcandidate
                        break

                if tp is None:
                    # try finding the TroopPerson in the database and set to leader
                    tp = TroopPerson.create_or_set_as_leader(
                        troop.key, person.key)
                    if tp:
                        # new or changed leader TroopPerson needs to be saved
                        troopPersonsToSave.append(tp)
                        self.result.append(u"Avdelning '%s' ny ledare:%s" %
                                           (troop.getname(), person.getname()))

        # check if old persons are still members, mark persons not imported in this import session as removed
        if len(
                personsToSave
        ) > 0:  # protect agains a failed import, with no persons marking everyone as removed
            previousPersons = Person.query(Person.scoutgroup == scoutgroup.key,
                                           Person.removed != True)
            for previousPersonKey in previousPersons.iter(keys_only=True):
                if previousPersonKey.id() not in activePersonIds:
                    personToMarkAsRemoved = previousPersonKey.get()
                    personToMarkAsRemoved.removed = True
                    self.result.append(
                        u"%s finns inte i scoutnet, markeras som borttagen. id:%s"
                        % (personToMarkAsRemoved.getname(),
                           str(previousPersonKey.id())))
                    if personToMarkAsRemoved in personsToSave:
                        raise Exception(
                            'A removed person cannot be in that list')
                    personsToSave.append(personToMarkAsRemoved)

        if self.commit:
            ndb.put_multi(personsToSave)
            ndb.put_multi(troopPersonsToSave)

        return True
Beispiel #7
0
def update_person_ids(commit, sgroup_key, start_cursor, stage, taskProgress):
    start_time = time.time()
    time_is_out = False
    there_is_more = True
    oldToNewDict = {}

    # --- Stage 0 ---
    if stage == 0:
        while there_is_more:

            if time.time() - start_time > max_time_seconds:
                time_is_out = True
                break # time out

            person_keys, start_cursor, there_is_more = Person.query(Person.scoutgroup ==sgroup_key) \
                                                        .fetch_page(page_size=PAGE_SIZE, start_cursor=start_cursor, keys_only=True)
            for person_key in person_keys:
                if len(str(person_key.id())) < 12: # cannot be a personnr if shorter than 12 chars
                    taskProgress.info("Not updating id=%s" % (str(person_key.id())))
                    continue
                person = person_key.get()
                if person.version == 1 or person.version == 2:
                    taskProgress.info("Already updated id=%s" % (str(person_key.id())))
                    continue
                if person.member_no is None:
                    taskProgress.warning("Cannot update, member_no is None id=%s, %s" % (str(person_key.id()), person.getname()))
                    continue

                taskProgress.info("Updating Person: id=%s, pnr=%s, no=%s, %s" % (str(person.key.id()), person.personnr, str(person.member_no), person.getname()))

                newPerson, pendingKeyChange = person.updateKey()

                if newPerson is not None:
                    if commit and newPerson._dirty:
                        k = newPerson.put()
                        assert(k == newPerson.key)
                if commit and person._dirty:
                    person.put()
                if pendingKeyChange is not None:
                    if pendingKeyChange._dirty:
                        pendingKeyChange.put() # safe to put, to be able to test the rest of the method

        if there_is_more:
            return start_cursor, there_is_more, stage
        else:
            taskProgress.info("Updated all persons Persons")
            stage = 1
            start_cursor = None
            there_is_more = True
            return start_cursor, there_is_more, stage # restart to start fresh and let datastore catch up


    taskProgress.info("Loading PendingPersonKeyChange records")
    ppkc_more = True
    ppkc_start_cursor = None
    while ppkc_more:
        ppkcs, ppkc_start_cursor, ppkc_more = PendingPersonKeyChange.query().fetch_page(page_size=1000, start_cursor=ppkc_start_cursor)
        for ppkc in ppkcs:
            oldToNewDict[ppkc.old_key] = ppkc.new_key
        
        taskProgress.info("Loaded persons to convert %d" % (len(oldToNewDict)))

    taskProgress.info("Number of persons to convert %d" % (len(oldToNewDict)))

    # --- Stage 1 ---
    if stage == 1:
        num_meetings_updated = 0
        troop_count = 0
        there_is_more = True
        taskProgress.info("Updating Meetings")
        while there_is_more:
            if time.time() - start_time > max_time_seconds:
                return start_cursor, there_is_more, stage

            troop_keys, start_cursor, there_is_more = Troop.query(Troop.scoutgroup == sgroup_key) \
                                                    .fetch_page(page_size=5, start_cursor=start_cursor, keys_only=True)
            for troop_key in troop_keys:
                troop_count += 1
                meetings = Meeting.query(Meeting.troop == troop_key).fetch()
                for meeting in meetings:
                    if meeting.uppdateOldPersonKeys(oldToNewDict):
                        num_meetings_updated += 1
                        if commit:
                            meeting.put()

            if num_meetings_updated % 10 == 0:
                taskProgress.info("Updated %d meetings, %d troop_count" % (num_meetings_updated, troop_count))

        if there_is_more:
            return start_cursor, there_is_more, stage
        else:
            taskProgress.info("Updated all meetings, time taken: %s s" % (str(time.time() - start_time)))
            stage = 2
            there_is_more = True
            start_cursor = None
            return start_cursor, there_is_more, stage

    # --- Stage 2 ---
    if stage == 2:
        update_counter = 0
        if start_cursor == None:
            start_cursor = 0

        taskProgress.info("Updating TroopPersons")
        for index, (old_person_key, new_person_key) in enumerate(oldToNewDict.items()):
            if index < start_cursor:
                continue

            for troopPerson in TroopPerson.query(TroopPerson.person==old_person_key).fetch():
                troopPerson.person = new_person_key
                update_counter += 1
                if commit:
                    troopPerson.put()
                if update_counter % 10 == 0:
                    taskProgress.info("Updated %d TroopPersons" % (update_counter))

            if time.time() - start_time > max_time_seconds:
                start_cursor = index
                there_is_more = True
                return start_cursor, there_is_more, stage

        taskProgress.info("Updated all TroopPersons")
        there_is_more = True
        stage = 3
        start_cursor = None
        return start_cursor, there_is_more, stage # restart to start fresh and let datastore catch up

    # --- Stage 3 ---
    if stage == 3:
        taskProgress.info("Deleting old persons")
        if commit and len(oldToNewDict) != 0:
            old_person_keys = [old_person_key for index, (old_person_key, new_person_key) in enumerate(oldToNewDict.items())]
            ndb.delete_multi(old_person_keys)
            taskProgress.info("Deleted %d old persons" % (len(old_person_keys)))

        there_is_more = False
        start_cursor = None
        stage = 4

    taskProgress.info("Done updating Person keys!")
    return None, False, stage
Beispiel #8
0
def merge_scout_group(oldname, newname, commit, taskProgress, user, move_users, move_persons, move_troops, delete_sg, semester_id):
    start_time = time.time()
    oldsg = ScoutGroup.getbyname(oldname)
    if oldsg is None:
        raise RuntimeError("Old sg name:%s not found" % oldname)

    newsg = ScoutGroup.getbyname(newname)
    if newsg is None:
        raise RuntimeError("New sg name:%s not found" % newname)

    if not commit:
        taskProgress.info("*** testmode ***")

    keys_to_delete = []
    entities_to_put_first = []
    entities_to_put = []

    taskProgress.info("termin: %s" % semester_id)
    
    convertsemester = Semester.getbyId(semester_id)
    if convertsemester is None:
        taskProgress.error("termin: %s does not exist" % semester_id)

    currentsemester = Semester.getOrCreateCurrent()

    if move_users:
        taskProgress.info("Update all users to the new scoutgroup")
        for u in UserPrefs.query(UserPrefs.groupaccess == oldsg.key).fetch():
            logging.info(" * * moving user for %s" % (u.getname()))
            u.groupaccess = newsg.key
            u.activeSemester = currentsemester.key
            entities_to_put.append(u)

    if move_persons:
        taskProgress.info("Moving all persons to the new ScoutGroup:%s" % newsg.getname())
        for oldp in Person.query(Person.scoutgroup == oldsg.key).fetch():
            oldp.scoutgroup = newsg.key
            entities_to_put.append(oldp)

    if move_troops:
        taskProgress.info("Move all troops to the new ScoutGroup:%s, semester: %s" % (newsg.getname(), convertsemester.getname()))
        for oldt in Troop.query(Troop.scoutgroup == oldsg.key, Troop.semester_key == convertsemester.key).fetch():
            taskProgress.info(" * found old troop for %s, semester=%s" % (str(oldt.key.id()), oldt.semester_key.get().getname()))
            keys_to_delete.append(oldt.key)
            newt = Troop.get_by_id(Troop.getid(oldt.scoutnetID, newsg.key, oldt.semester_key), use_memcache=True)
            if newt is None:
                taskProgress.info(" * * creating new troop for %s, semester=%s" % (str(oldt.key.id()), oldt.semester_key.get().getname()))
                newt = Troop.create(oldt.name, oldt.scoutnetID, newsg.key, oldt.semester_key)
                entities_to_put_first.append(newt) # put first to be able to reference it
            else:
                taskProgress.info(" * * already has new troop for %s, semester=%s" % (str(newt.key.id()), newt.semester_key.get().getname()))

            taskProgress.info(" * Move all trooppersons to the new group")
            for oldtp in TroopPerson.query(TroopPerson.troop == oldt.key).fetch():
                keys_to_delete.append(oldtp.key)
                newtp = TroopPerson.get_by_id(TroopPerson.getid(newt.key, oldtp.person), use_memcache=True)
                if newtp is None:
                    logging.info(" * * creating new TroopPerson for %s:%s" % (newt.getname(), oldtp.getname()))
                    newtp = TroopPerson.create_or_update(newt.key, oldtp.person, oldtp.leader)
                    entities_to_put.append(newtp)
                else:
                    logging.info(" * * already has TroopPerson for %s:%s" % (newt.getname(), oldtp.getname()))

            taskProgress.info(" * Move all old meetings to the new troop")
            for oldm in Meeting.query(Meeting.troop==oldt.key).fetch():
                keys_to_delete.append(oldm.key)
                newm = Meeting.get_by_id(Meeting.getId(oldm.datetime, newt.key), use_memcache=True)
                if newm is None:
                    logging.info(" * * creating new Meeting for %s:%s" % (newt.getname(), oldm.datetime.strftime("%Y-%m-%d %H:%M")))
                    newm = Meeting(id=Meeting.getId(oldm.datetime, newt.key),
                                        datetime=oldm.datetime,
                                        name=oldm.name,
                                        troop=newt.key,
                                        duration=oldm.duration,
                                        ishike=oldm.ishike)
                    newm.attendingPersons = oldm.attendingPersons
                    entities_to_put.append(newm)
                else:
                    logging.info(" * * merging Meeting %s->%s :%s" % (oldm.getname(), newm.getname(), oldm.datetime.strftime("%Y-%m-%d %H:%M")))
                    need_to_put = False
                    if len(oldm.name) > len(newm.name): # take the longer name.
                        newm.name = oldm.name
                        need_to_put = True
                    
                    for oldattendingpersonkey in oldm.attendingPersons:
                        if oldattendingpersonkey not in newm.attendingPersons:
                            newm.attendingPersons.append(oldattendingpersonkey)
                            need_to_put = True
                    
                    if need_to_put:
                        entities_to_put.append(newm)

        if delete_sg:
            keys_to_delete.append(oldsg.key)

    taskProgress.info("time before put: %s s" % str(time.time() - start_time))

    logging.info("Putting %d entities first" % len(entities_to_put_first))
    if commit: ndb.put_multi(entities_to_put_first)
    logging.info("Putting %d entities" % len(entities_to_put))
    if commit: ndb.put_multi(entities_to_put)
    logging.info("Deleting %d keys" % len(keys_to_delete))
    if commit: ndb.delete_multi(keys_to_delete)
    logging.info("clear memcache")
    if commit: ndb.get_context().clear_cache()

    taskProgress.info("Done! time: %s s" % str(time.time() - start_time))
Beispiel #9
0
def show(sgroup_url=None, troop_url=None, key_url=None):
    user = UserPrefs.current()
    if not user.hasAccess():
        return "denied", 403

    breadcrumbs = [{'link': '/', 'text': 'Hem'}]
    section_title = u'Kårer'
    breadcrumbs.append({'link': '/start', 'text': section_title})
    baselink = '/start/'

    scoutgroup = None
    if sgroup_url is not None:
        sgroup_key = ndb.Key(urlsafe=sgroup_url)
        scoutgroup = sgroup_key.get()
        baselink += sgroup_url + "/"
        breadcrumbs.append({'link': baselink, 'text': scoutgroup.getname()})

    troop = None
    semester = user.activeSemester.get()
    if troop_url is not None and troop_url != 'lagerbidrag':
        baselink += troop_url + "/"
        troop_key = ndb.Key(urlsafe=troop_url)
        troop = troop_key.get()
        breadcrumbs.append({'link': baselink, 'text': troop.getname()})
        semester = troop.semester_key.get()

    if key_url == "settings":
        section_title = u'Inställningar'
        baselink += "settings/"
        breadcrumbs.append({'link': baselink, 'text': section_title})
        if request.method == "POST":
            troop.defaultstarttime = request.form['defaultstarttime']
            troop.defaultduration = int(request.form['defaultduration'])
            troop.rapportID = int(request.form['rapportID'])
            troop.put()

        form = htmlform.HtmlForm('troopsettings')
        form.AddField('defaultstarttime', troop.defaultstarttime,
                      'Avdelningens vanliga starttid')
        form.AddField('defaultduration', troop.defaultduration,
                      u'Avdelningens vanliga mötestid i minuter', 'number')
        form.AddField('rapportID', troop.rapportID,
                      u'Unik rapport ID för kommunens närvarorapport',
                      'number')
        return render_template('form.html',
                               heading=section_title,
                               baselink=baselink,
                               form=str(form),
                               breadcrumbs=breadcrumbs)
    if key_url == "delete":
        if troop is None:
            return "", 404
        if request.form and "confirm" in request.form:
            if not user.isGroupAdmin():
                return "", 403
            troop.delete()
            troop = None
            del breadcrumbs[-1]
            baselink = breadcrumbs[-1]["link"]
        else:
            form = htmlform.HtmlForm(
                'deletetroop',
                submittext="Radera",
                buttonType="btn-danger",
                descriptionText=
                u"Vill du verkligen radera avdelningen och all registrerad närvaro?\n"
                u"Det går här inte att ångra.")
            form.AddField('confirm', '', '', 'hidden')
            return render_template('form.html',
                                   heading=section_title,
                                   baselink=baselink,
                                   form=str(form),
                                   breadcrumbs=breadcrumbs)

    if key_url == "newperson":
        section_title = "Ny person"
        baselink += key_url + "/"
        breadcrumbs.append({'link': baselink, 'text': section_title})
        if request.method == "GET":
            return render_template('person.html',
                                   heading=section_title,
                                   baselink=baselink,
                                   breadcrumbs=breadcrumbs,
                                   troop_persons=[],
                                   scoutgroup=scoutgroup)
        elif request.method == "POST":
            pnr = request.form['personnummer'].replace('-', '')
            person = Person.createlocal(request.form['firstname'],
                                        request.form['lastname'], pnr,
                                        request.form['mobile'],
                                        request.form['phone'],
                                        request.form['email'])
            person.street = request.form["street"]
            person.zip_code = request.form["zip_code"]
            person.zip_name = request.form["zip_name"]
            if "patrol" in request.form:
                person.setpatrol(request.form["patrol"])
            person.scoutgroup = sgroup_key
            logging.info("created local person %s", person.getname())
            person.put()
            troop_person = TroopPerson.create(troop_key, person.key, False)
            troop_person.commit()
            if scoutgroup.canAddToWaitinglist():
                try:
                    if scoutnet.AddPersonToWaitinglist(
                            scoutgroup, person.firstname, person.lastname,
                            person.personnr, person.email, person.street,
                            person.zip_code, person.zip_name, person.phone,
                            person.mobile, troop,
                            request.form['anhorig1_name'],
                            request.form['anhorig1_email'],
                            request.form['anhorig1_mobile'],
                            request.form['anhorig1_phone'],
                            request.form['anhorig2_name'],
                            request.form['anhorig2_email'],
                            request.form['anhorig2_mobile'],
                            request.form['anhorig2_phone']):
                        person.notInScoutnet = False
                        person.put()
                except scoutnet.ScoutnetException as exp:
                    return render_template('error.html', error=str(exp))
            return redirect(breadcrumbs[-2]['link'])

    if request.method == "GET" and request.args and "action" in request.args:
        action = request.args["action"]
        logging.debug("action %s", action)
        if action == "lookupperson":
            if scoutgroup is None:
                raise ValueError('Missing group')
            name = request.args['name'].lower()
            if len(name) < 2:
                return "[]"
            logging.debug("name=%s", name)
            json_str = '['
            person_counter = 0
            for person in Person().query(
                    Person.scoutgroup == sgroup_key).order(
                        Person.removed, Person.firstname, Person.lastname):
                if person.getname().lower().find(name) != -1:
                    if person_counter != 0:
                        json_str += ', '
                    json_str += '{"name": "' + person.getnameWithStatus(
                    ) + '", "url": "' + person.key.urlsafe() + '"}'
                    person_counter += 1
                    if person_counter == 8:
                        break
            json_str += ']'
            return json_str
        elif action == "addperson":
            if troop is None or key_url is None:
                raise ValueError('Missing troop or person')
            person_key = ndb.Key(urlsafe=key_url)
            person = person_key.get()
            logging.info("adding person=%s to troop=%d", person.getname(),
                         troop.getname())
            troop_person = TroopPerson.create(troop_key, person_key,
                                              person.isLeader())
            troop_person.commit()
            return redirect(breadcrumbs[-1]['link'])
        elif action == "setsemester":
            if user is None or "semester" not in request.args:
                raise ValueError('Missing user or semester arg')
            semester_url = request.args["semester"]
            user.activeSemester = ndb.Key(urlsafe=semester_url)
            user.put()
        elif action == "removefromtroop" or action == "setasleader" or action == "removeasleader":
            if troop is None or key_url is None:
                raise ValueError('Missing troop or person')
            person_key = ndb.Key(urlsafe=key_url)
            tps = TroopPerson.query(TroopPerson.person == person_key,
                                    TroopPerson.troop == troop_key).fetch(1)
            if len(tps) == 1:
                troop_person = tps[0]
                if action == "removefromtroop":
                    troop_person.delete()
                else:
                    troop_person.leader = (action == "setasleader")
                    troop_person.put()
            return "ok"
        else:
            logging.error('unknown action=%s', action)
            return "", 404

    if request.method == "POST" and request.form and "action" in request.form:
        action = request.form["action"]
        if action == "saveattendance":
            if troop is None or scoutgroup is None or key_url is None:
                raise ValueError('Missing troop or group')

            meeting = ndb.Key(urlsafe=key_url).get()
            meeting.attendingPersons[:] = []  # clear the list
            for person_url in request.form["persons"].split(","):
                #logging.debug("person_url=%s", person_url)
                if len(person_url) > 0:
                    person_key = ndb.Key(urlsafe=person_url)
                    meeting.attendingPersons.append(person_key)
            meeting.put()
            return "ok"
        elif action == "addmeeting" or action == "updatemeeting":
            mname = request.form['name']
            mdate = request.form['date']
            mishike = bool(request.form.get('ishike'))
            mtime = request.form['starttime'].replace('.', ':')
            dtstring = mdate + "T" + mtime
            mduration = request.form['duration']
            date_str = datetime.datetime.strptime(dtstring, "%Y-%m-%dT%H:%M")
            if action == "addmeeting":
                meeting = Meeting.getOrCreate(troop_key, mname, date_str,
                                              int(mduration), mishike)
            else:
                meeting = ndb.Key(urlsafe=key_url).get()

            meeting.name = mname
            meeting.datetime = date_str
            meeting.duration = int(mduration)
            meeting.ishike = mishike
            meeting.commit()
            return redirect(breadcrumbs[-1]['link'])
        elif action == "deletemeeting":
            meeting = ndb.Key(urlsafe=key_url).get()
            logging.debug("deleting meeting=%s", meeting.getname())
            meeting.delete()
            return redirect(breadcrumbs[-1]['link'])
        elif action == "addhike":
            mname = request.form['name']
            mdate = request.form['date']
            mdays = int(request.form['days'])
            date_str = datetime.datetime.strptime(mdate, "%Y-%m-%d")
            for i in range(mdays):
                day_time = date_str + datetime.timedelta(days=i)
                meeting = Meeting.getOrCreate(
                    troop_key,
                    mname,
                    day_time,
                    duration=1440,  # 24h (needs some value)
                    ishike=True)
                meeting.commit()
            return redirect(breadcrumbs[-1]['link'])

        elif action == "savepatrol":
            patrolperson = ndb.Key(urlsafe=request.form['person']).get()
            patrolperson.setpatrol(request.form['patrolName'])
            patrolperson.put()
            return "ok"
        elif action == "newtroop":
            troopname = request.form['troopname']
            troop_id = hash(troopname)
            conflict = Troop.get_by_id(Troop.getid(troop_id, scoutgroup.key,
                                                   user.activeSemester),
                                       use_memcache=True)
            if conflict is not None:
                return "Avdelningen finns redan", 404
            troop = Troop.create(troopname, troop_id, scoutgroup.key,
                                 user.activeSemester)
            troop.put()
            troop_key = troop.key
            logging.info("created local troop %s", troopname)
            action = ""
            return redirect(breadcrumbs[-1]['link'])
        else:
            logging.error('unknown action=%s', action)
            return "", 404

    # render main pages
    if scoutgroup is None:
        return render_template('index.html',
                               heading=section_title,
                               baselink=baselink,
                               items=ScoutGroup.getgroupsforuser(user),
                               breadcrumbs=breadcrumbs)
    elif troop_url == "lagerbidrag":
        return lagerbidrag.render_lagerbidrag(request,
                                              scoutgroup,
                                              "group",
                                              user=user,
                                              sgroup_key=sgroup_key)
    elif troop is None:
        section_title = 'Avdelningar'
        return render_template(
            'troops.html',
            heading=section_title,
            baselink=baselink,
            scoutgroupinfolink='/scoutgroupinfo/' + sgroup_url + '/',
            groupsummarylink='/groupsummary/' + sgroup_url + '/',
            user=user,
            semester=semester,
            semesters=sorted(Semester.query(), semester_sort),
            troops=sorted(Troop.getTroopsForUser(sgroup_key, user),
                          key=attrgetter('name')),
            lagerplats=scoutgroup.default_lagerplats,
            breadcrumbs=breadcrumbs)
    elif key_url is not None and key_url not in ("dak", "sensus",
                                                 "lagerbidrag", "excel",
                                                 "excel_sthlm", "json"):
        meeting = ndb.Key(urlsafe=key_url).get()
        section_title = meeting.getname()
        baselink += key_url + "/"
        breadcrumbs.append({'link': baselink, 'text': section_title})

        return render_template('meeting.html',
                               heading=section_title,
                               baselink=baselink,
                               existingmeeting=meeting,
                               breadcrumbs=breadcrumbs,
                               semester=troop.semester_key.get(),
                               troop=troop)
    else:
        meeting_count = 0
        sum_male_attendance_count = 0
        sum_female_attendance_count = 0
        sum_male_leader_attendance_count = 0
        sum_female_leader_attendance_count = 0
        no_leader_meeting_count = 0
        too_small_group_meeting_count = 0
        age_problem_count = 0
        age_problem_desc = []

        section_title = troop.getname()
        troop_persons = TroopPerson.getTroopPersonsForTroop(troop_key)
        meetings = Meeting.gettroopmeetings(troop_key)

        attendances = []  # [meeting][person]
        persons = []
        persons_dict = {}
        for troop_person in troop_persons:
            person_key = troop_person.person
            person = troop_person.person.get()
            persons.append(person)
            persons_dict[person_key] = person

        year = semester.year
        for meeting in meetings:
            male_attendance_count = 0
            female_attendence_count = 0
            male_leader_attendance_count = 0
            female_leader_attendence_count = 0
            meeting_attendance = []
            for troop_person in troop_persons:
                is_attending = troop_person.person in meeting.attendingPersons
                meeting_attendance.append(is_attending)
                if is_attending:
                    person = persons_dict[troop_person.person]
                    age = person.getyearsoldthisyear(year)
                    if troop_person.leader:
                        if 13 <= age <= 100:
                            if female_leader_attendence_count + male_leader_attendance_count < 2:
                                if person.isFemale():
                                    female_leader_attendence_count += 1
                                else:
                                    male_leader_attendance_count += 1
                        else:
                            age_problem_count += 1
                            age_problem_desc.append(person.getname() + ": " +
                                                    str(age))
                    else:
                        if 7 <= age <= 25:
                            if person.isFemale():
                                female_attendence_count += 1
                            else:
                                male_attendance_count += 1
                        else:
                            age_problem_count += 1
                            age_problem_desc.append(person.getname() + ": " +
                                                    str(age))

            attendances.append(meeting_attendance)
            total_attendance = male_attendance_count + female_attendence_count
            # max 40 people
            if total_attendance > 40:
                surplus_people = total_attendance - 40
                removed_men = min(male_attendance_count, surplus_people)
                male_attendance_count -= removed_men
                surplus_people -= removed_men
                female_attendence_count -= surplus_people

            max_leaders = 1 if total_attendance <= 10 else 2
            total_leaders = female_leader_attendence_count + male_leader_attendance_count
            if total_attendance < 3:
                too_small_group_meeting_count += 1
            else:
                if total_leaders == 0:
                    no_leader_meeting_count += 1
                else:
                    meeting_count += 1
                    sum_female_attendance_count += female_attendence_count
                    sum_male_attendance_count += male_attendance_count
                    if total_leaders > max_leaders:
                        if male_leader_attendance_count > max_leaders and female_leader_attendence_count == 0:
                            male_leader_attendance_count = max_leaders
                        elif male_leader_attendance_count == 0 and female_leader_attendence_count > max_leaders:
                            female_leader_attendence_count = max_leaders
                        else:
                            female_leader_attendence_count = max_leaders / 2
                            max_leaders -= female_leader_attendence_count
                            male_leader_attendance_count = max_leaders

                    sum_female_leader_attendance_count += female_leader_attendence_count
                    sum_male_leader_attendance_count += male_leader_attendance_count

        if key_url in ("dak", "excel", "excel_sthlm", "json"):
            dak = DakData()
            dak.foerenings_namn = scoutgroup.getname()
            dak.forenings_id = scoutgroup.foreningsID
            dak.organisationsnummer = scoutgroup.organisationsnummer
            dak.kommun_id = scoutgroup.kommunID
            dak.kort.namn_paa_kort = troop.getname()
            # hack generate an "unique" id, if there is none
            if troop.rapportID is None or troop.rapportID == 0:
                troop.rapportID = random.randint(1000, 1000000)
                troop.put()

            dak.kort.naervarokort_nummer = str(troop.rapportID)

            for troop_person in troop_persons:
                p = persons_dict[troop_person.person]
                if troop_person.leader:
                    dak.kort.ledare.append(
                        Deltagare(p.getReportID(), p.firstname, p.lastname,
                                  p.getpersonnr(), True, p.email, p.mobile,
                                  p.zip_code))
                else:
                    dak.kort.deltagare.append(
                        Deltagare(p.getReportID(), p.firstname, p.lastname,
                                  p.getpersonnr(), False, p.email, p.mobile,
                                  p.zip_code))

            for m in meetings:
                if (not scoutgroup.attendance_incl_hike) and m.ishike:
                    continue
                sammankomst = Sammankomst(str(m.key.id()[:50]), m.datetime,
                                          m.duration, m.getname())
                for troop_person in troop_persons:
                    is_attending = troop_person.person in m.attendingPersons
                    if is_attending:
                        p = persons_dict[troop_person.person]
                        if troop_person.leader:
                            sammankomst.ledare.append(
                                Deltagare(p.getReportID(),
                                          p.firstname, p.lastname,
                                          p.getpersonnr(), True, p.email,
                                          p.mobile, p.zip_code))
                        else:
                            sammankomst.deltagare.append(
                                Deltagare(p.getReportID(),
                                          p.firstname, p.lastname,
                                          p.getpersonnr(), False, p.email,
                                          p.mobile, p.zip_code))

                dak.kort.sammankomster.append(sammankomst)
            if key_url in ("excel", "excel_sthlm"):
                if key_url == "excel":
                    excel_report = ExcelReport(dak, semester)
                else:
                    dak.kort.lokal = scoutgroup.default_lagerplats
                    excel_report = ExcelReportSthlm(dak, semester)
                resultbytes = excel_report.getFilledInExcelSpreadsheet()
                response = make_response(resultbytes)
                response.headers[
                    'Content-Type'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
                response.headers['Content-Disposition'] = (
                    'attachment; filename=' +
                    urllib.quote(str(dak.kort.namn_paa_kort), safe='') + '-' +
                    semester.getname() + '.xlsx;')
                return response
            elif key_url == "json":
                json_report = JsonReport(dak, semester)
                resultbytes = json_report.get_report_string()
                response = make_response(resultbytes)
                response.headers['Content-Type'] = json_report.get_mime_type()
                response.headers[
                    'Content-Disposition'] = 'attachment; filename=' + urllib.quote(
                        json_report.get_filename(), safe='') + ';'
                return response
            else:
                result = render_template('dak.xml', dak=dak)
                response = make_response(result)
                response.headers['Content-Type'] = 'application/xml'
                response.headers['Content-Disposition'] = (
                    'attachment; filename=' +
                    urllib.quote(str(dak.kort.namn_paa_kort), safe='') + '-' +
                    semester.getname() + '.xml;')
                return response
        elif key_url == "sensus":
            leaders = []
            for troop_person in troop_persons:
                if troop_person.leader:
                    leaders.append(troop_person.getname())

            patrols = []
            for p in persons:
                if p.getpatrol() not in patrols:
                    patrols.append(p.getpatrol())

            sensusdata = sensus.SensusData()
            sensusdata.foereningsNamn = scoutgroup.getname()
            sensusdata.foreningsID = scoutgroup.foreningsID
            sensusdata.organisationsnummer = scoutgroup.organisationsnummer
            sensusdata.kommunID = scoutgroup.kommunID
            sensusdata.verksamhetsAar = semester.getname()

            for patrol in patrols:
                sensuslista = sensus.SensusLista()
                sensuslista.NamnPaaKort = troop.getname() + "/" + patrol

                for troop_person in troop_persons:
                    p = persons_dict[troop_person.person]
                    if p.getpatrol() != patrol:
                        continue
                    if troop_person.leader:
                        sensuslista.ledare.append(
                            sensus.Deltagare(p.getReportID(),
                                             p.firstname, p.lastname,
                                             p.getpersonnr(), True, p.email,
                                             p.mobile))
                    else:
                        sensuslista.deltagare.append(
                            sensus.Deltagare(p.getReportID(),
                                             p.firstname, p.lastname,
                                             p.getpersonnr(), False))

                for m in meetings:
                    sammankomst = sensus.Sammankomst(str(m.key.id()[:50]),
                                                     m.datetime, m.duration,
                                                     m.getname())
                    for troop_person in troop_persons:
                        p = persons_dict[troop_person.person]
                        if p.getpatrol() != patrol:
                            continue
                        is_attending = troop_person.person in m.attendingPersons

                        if troop_person.leader:
                            sammankomst.ledare.append(
                                sensus.Deltagare(p.getReportID(),
                                                 p.firstname, p.lastname,
                                                 p.getpersonnr(), True,
                                                 p.email, p.mobile,
                                                 is_attending))
                        else:
                            sammankomst.deltagare.append(
                                sensus.Deltagare(p.getReportID(),
                                                 p.firstname, p.lastname,
                                                 p.getpersonnr(), False,
                                                 p.email, p.mobile,
                                                 is_attending))

                    sensuslista.Sammankomster.append(sammankomst)

                sensusdata.listor.append(sensuslista)

            result = render_template('sensusnarvaro.html',
                                     sensusdata=sensusdata)
            response = make_response(result)
            return response
        elif key_url == "lagerbidrag":
            return lagerbidrag.render_lagerbidrag(request,
                                                  scoutgroup,
                                                  "troop",
                                                  trooppersons=troop_persons,
                                                  troop_key=troop_key)
        else:
            allowance = []
            allowance.append({'name': 'Antal möten:', 'value': meeting_count})
            allowance.append({'name': 'Deltagartillfällen', 'value': ''})
            allowance.append({
                'name': 'Kvinnor:',
                'value': sum_female_attendance_count
            })
            allowance.append({
                'name': 'Män:',
                'value': sum_male_attendance_count
            })
            allowance.append({
                'name': 'Ledare Kvinnor:',
                'value': sum_female_leader_attendance_count
            })
            allowance.append({
                'name': 'Ledare Män:',
                'value': sum_male_leader_attendance_count
            })
            if no_leader_meeting_count > 0:
                allowance.append({
                    'name': 'Antal möten utan ledare',
                    'value': no_leader_meeting_count
                })
            if too_small_group_meeting_count > 0:
                allowance.append({
                    'name': 'Antal möten med för få deltagare',
                    'value': too_small_group_meeting_count
                })
            if age_problem_count > 0:
                allowance.append({
                    'name': 'Ålder utanför intervall:',
                    'value': age_problem_count
                })
            if age_problem_desc != "":
                age_problem_desc_str = ','.join(age_problem_desc[:3])
                if len(age_problem_desc) > 3:
                    age_problem_desc_str += "..."
                allowance.append({'name': '', 'value': age_problem_desc_str})

            return render_template('troop.html',
                                   heading=section_title,
                                   semestername=semester.getname(),
                                   baselink='/persons/' +
                                   scoutgroup.key.urlsafe() + '/',
                                   persons=persons,
                                   trooppersons=troop_persons,
                                   meetings=meetings,
                                   attendances=attendances,
                                   breadcrumbs=breadcrumbs,
                                   allowance=allowance,
                                   troop=troop,
                                   user=user,
                                   semester=semester,
                                   lagerplats=scoutgroup.default_lagerplats)
Beispiel #10
0
def merge_sg(oldname, newname, commit):
    oldsg = ScoutGroup.getbyname(oldname)
    if oldsg is None:
        raise RuntimeError("Old sg name:%s not found" % oldname)

    newsg = ScoutGroup.getbyname(newname)
    if newsg is None:
        raise RuntimeError("New sg name:%s not found" % newname)

    if not commit: logging.info("*** testmode ***")

    keys_to_delete = []
    entities_to_put_first = []
    entities_to_put = []
    semester = Semester.getOrCreateCurrent()

    keys_to_delete.append(oldsg.key)

    logging.info("Update all users to the new scoutgroup")
    for u in UserPrefs.query(UserPrefs.groupaccess == oldsg.key).fetch():
        u.groupaccess = newsg.key
        u.activeSemester = semester.key
        entities_to_put.append(u)

    logging.info("Moving all persons to the new ScoutGroup:%s", newsg.getname())
    for oldp in Person.query(Person.scoutgroup == oldsg.key).fetch():
        logging.info(" * Moving %s %s", oldp.getname(), oldp.personnr)
        oldp.scoutgroup = newsg.key
        entities_to_put.append(oldp)

    logging.info("Move all troops to the new ScoutGroup:%s", newsg.getname())
    for oldt in Troop.query(Troop.scoutgroup == oldsg.key).fetch():
        logging.info(" * found old troop for %s, semester=%s", str(oldt.key.id()), oldt.semester_key.get().getname())
        keys_to_delete.append(oldt.key)
        newt = Troop.get_by_id(Troop.getid(oldt.scoutnetID, newsg.key, oldt.semester_key), use_memcache=True)
        if newt is None:
            logging.info(" * * creating new troop for %s, semester=%s", str(oldt.key.id()), oldt.semester_key.get().getname())
            newt = Troop.create(oldt.name, oldt.scoutnetID, newsg.key, oldt.semester_key)
            entities_to_put_first.append(newt) # put first to be able to reference it
        else:
            logging.info(" * * already has new troop for %s, semester=%s", str(newt.key.id()), newt.semester_key.get().getname())

        logging.info(" * Move all trooppersons to the new group (it they don't already exist there)")
        for oldtp in TroopPerson.query(TroopPerson.troop == oldt.key).fetch():
            keys_to_delete.append(oldtp.key)
            newtp = TroopPerson.get_by_id(TroopPerson.getid(newt.key, oldtp.person), use_memcache=True)
            if newtp is None:
                logging.info(" * * creating new TroopPerson for %s:%s", newt.getname(), oldtp.getname())
                newtp = TroopPerson.create(newt.key, oldtp.person, oldtp.leader)
                entities_to_put.append(newtp)
            else:
                logging.info(" * * already has TroopPerson for %s:%s", newt.getname(), oldtp.getname())

        logging.info(" * Move all old meetings to the new troop")
        for oldm in Meeting.query(Meeting.troop==oldt.key).fetch():
            keys_to_delete.append(oldm.key)
            newm = Meeting.get_by_id(Meeting.getId(oldm.datetime, newt.key), use_memcache=True)
            if newm is None:
                logging.info(" * * creating new Meeting for %s:%s", newt.getname(), oldm.datetime.strftime("%Y-%m-%d %H:%M"))
                newm = Meeting.getOrCreate(newt.key, oldm.name, oldm.datetime, oldm.duration, oldm.ishike)
                newm.attendingPersons = oldm.attendingPersons
                entities_to_put.append(newm)
            else:
                logging.info(" * * already has Meeting for %s:%s", newt.getname(), newt.datetime.strftime("%Y-%m-%d %H:%M"))

    logging.info("Putting %d entities first", len(entities_to_put_first))
    if commit: ndb.put_multi(entities_to_put_first)
    logging.info("Putting %d entities", len(entities_to_put))
    if commit: ndb.put_multi(entities_to_put)
    logging.info("Deleting %d keys", len(keys_to_delete))
    if commit: ndb.delete_multi(keys_to_delete)
    logging.info("clear memcache")
    if commit: ndb.get_context().clear_cache()
    logging.info("Done!")