Ejemplo n.º 1
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")
Ejemplo n.º 2
0
def adminUpdateUpdatePersonIds():
    user = UserPrefs.current()
    if not user.isAdmin():
        return "denied", 403

    section_title = u'Hem'
    baselink = '/'
    breadcrumbs = [{'link':baselink, 'text':section_title}]

    section_title = u'Admin'
    baselink += 'admin/'
    breadcrumbs.append({'link':baselink, 'text':section_title})

    section_title = u'Update Person Ids'
    baselink += 'update_person_ids/'
    breadcrumbs.append({'link':baselink, 'text':section_title})

    if request.method == 'POST':
        sgroup_key = None
        if len(request.form.get('groupaccess')) != 0:
            sgroup_key = ndb.Key(urlsafe=request.form.get('groupaccess'))

        commit = request.form.get('commit') == 'on'
        return startAsyncUpdatePersonIds(commit, sgroup_key)
    else:
        return render_template('update_person_ids.html',
            heading=section_title,
            baselink=baselink,
            breadcrumbs=breadcrumbs,
            scoutgroups=ScoutGroup.query().fetch())
Ejemplo n.º 3
0
    def GetOrCreateGroup(self, name, scoutnetID):
        if len(name) == 0:
            return None
        group = ScoutGroup.get_by_id(ScoutGroup.getid(name), use_memcache=True)
        if group == None:
            self.result.append(u"Ny kår %s, id=%s" % (name, str(scoutnetID)))
            group = ScoutGroup.create(name, scoutnetID)
            group.scoutnetID = scoutnetID
            if self.commit:
                group.put()

        if group.scoutnetID != scoutnetID:
            group.scoutnetID = scoutnetID
            if self.commit:
                group.put()

        self.importedScoutGroup_key = group.key
        return group
Ejemplo n.º 4
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
Ejemplo n.º 5
0
def adminaccess(userprefs_url=None):
    user = UserPrefs.current()
    if not user.isAdmin():
        return "denied", 403

    section_title = u'Hem'
    baselink = '/'
    breadcrumbs = [{'link':baselink, 'text':section_title}]

    section_title = u'Admin'
    baselink += 'admin/'
    breadcrumbs.append({'link':baselink, 'text':section_title})

    section_title = u'Access'
    baselink += 'access/'
    breadcrumbs.append({'link':baselink, 'text':section_title})

    if userprefs_url != None:
        userprefs = ndb.Key(urlsafe=userprefs_url).get()
        if request.method == 'POST':
            userprefs.hasaccess = request.form.get('hasAccess') == 'on'
            userprefs.hasadminaccess = request.form.get('hasAdminAccess') == 'on'
            userprefs.groupadmin = request.form.get('groupadmin') == 'on'
            userprefs.canimport = request.form.get('canImport') == 'on'
            sgroup_key = None
            if len(request.form.get('groupaccess')) != 0:
                sgroup_key = ndb.Key(urlsafe=request.form.get('groupaccess'))
            userprefs.groupaccess = sgroup_key
            userprefs.put()
        else:
            section_title = userprefs.getname()
            baselink += userprefs_url + '/'
            breadcrumbs.append({'link':baselink, 'text':section_title})
            return render_template('userprefs.html',
                heading=section_title,
                baselink=baselink,
                userprefs=userprefs,
                breadcrumbs=breadcrumbs,
                scoutgroups=ScoutGroup.query().fetch())

    users = UserPrefs().query().fetch()
    return render_template('userlist.html',
        heading=section_title,
        baselink=baselink,
        users=users,
        breadcrumbs=breadcrumbs)
Ejemplo n.º 6
0
def getaccess():
    user = UserPrefs.current()
    breadcrumbs = [{'link': '/', 'text': 'Hem'}]
    baselink = "/getaccess/"
    section_title = "Access"
    breadcrumbs.append({'link': baselink, 'text': section_title})
    if request.method == "POST":

        # anti-spam protection, the user can only ask once.
        user_request_access_key = "request_access_" + user.getemail()
        if memcache.get(user_request_access_key) is not None:
            logging.warning("User is spamming req-access:" + user.getemail())
            return "denied", 403
        memcache.add(user_request_access_key, True)

        sgroup = None
        if len(request.form.get('scoutgroup')) != 0:
            sgroup = ndb.Key(urlsafe=request.form.get('scoutgroup')).get()

        if sgroup is not None:
            groupAdminEmails = UserPrefs.getAllGroupAdminEmails(sgroup.key)
            if len(groupAdminEmails) > 0:
                mail.send_mail(
                    sender="*****@*****.**",
                    to=','.join(groupAdminEmails),
                    subject=
                    u"""Användaren: {} vill ha access till närvaroregistrering i Skojjt
                    för scoutkåren {}""".format(user.getemail(),
                                                sgroup.getname()),
                    body=u"""Gå till {} för att lägga till {}""".format(
                        request.host_url + "groupaccess/", user.getname()))
        return redirect('/')
    else:
        return render_template('getaccess.html',
                               baselink=baselink,
                               breadcrumbs=breadcrumbs,
                               scoutgroups=ScoutGroup.query().fetch())
Ejemplo n.º 7
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))
Ejemplo n.º 8
0
def show(sgroup_url=None, person_url=None, action=None):
    user = UserPrefs.current()
    if not user.hasAccess():
        return "denied", 403

    breadcrumbs = [{'link':'/', 'text':'Hem'}]

    section_title = u'Personer'
    breadcrumbs.append({'link': '/persons', 'text': section_title})
    baselink = '/persons/'

    sgroup_key = None  # type: ndb.Key
    scoutgroup = None  # type: ScoutGroup
    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()})

    if scoutgroup is None:
        return render_template(
            'index.html',
            heading=section_title,
            baselink=baselink,
            items=ScoutGroup.getgroupsforuser(user),
            breadcrumbs=breadcrumbs,
            username=user.getname())

    person_key = None  # type: ndb.Key
    person = None  # type: Person
    if person_url is not None:
        person_key = ndb.Key(urlsafe=person_url)
        person = person_key.get()
        baselink += person_url+"/"
        section_title = person.getname()
        breadcrumbs.append({'link': baselink, 'text': section_title})

    if person is None:
        if not user.hasGroupKeyAccess(sgroup_key):
            return "denied", 403
        section_title = 'Personer'
        return render_template(
            'persons.html',
            heading=section_title,
            baselink=baselink,
            # TODO: memcache
            persons=Person.query(Person.scoutgroup == sgroup_key).order(Person.firstname, Person.lastname).fetch(),
            breadcrumbs=breadcrumbs,
            username=user.getname())

    if person.scoutgroup != sgroup_key:
        return "denied", 403

    if not user.hasPersonAccess(person):
        return "denied", 403

    if action is not None:
        if action == "deleteperson" or action == "addbackperson":
            person.removed = action == "deleteperson"
            person.put() # we only mark the person as removed
            if person.removed:
                tps = TroopPerson.query(TroopPerson.person == person.key).fetch()
                for tp in tps:
                    tp.delete()
            return redirect(breadcrumbs[-1]['link'])
        elif action == "removefromtroop" or action == "setasleader" or action == "removeasleader":
            troop_key = ndb.Key(urlsafe=request.args["troop"])
            tps = TroopPerson.query(TroopPerson.person == person.key, TroopPerson.troop == troop_key).fetch(1)
            if len(tps) == 1:
                tp = tps[0]
                if action == "removefromtroop":
                    tp.delete()
                else:
                    tp.leader = (action == "setasleader")
                    tp.put()
        elif action == "addtowaitinglist":
            scoutgroup = person.scoutgroup.get()
            troop = None
            tps = TroopPerson.query(TroopPerson.person == person.key).fetch(1)
            if len(tps) == 1:
                troop = tps[0].troop.get()
            scoutgroup = person.scoutgroup.get()
            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,
                            "",
                            "",
                            "",
                            "",
                            "",
                            "",
                            "",
                            ""
                    ):
                        person.notInScoutnet = False
                        person.put()
                except scoutnet.ScoutnetException as e:
                    return render_template('error.html', error=str(e))
        else:
            logging.error('unknown action=' + action)
            abort(404)
            return ""

    trooppersons = TroopPerson.query(TroopPerson.person == person.key).fetch() # TODO: memcache

    # render main pages
    return render_template(
        'person.html',
        heading=section_title,
        baselink='/persons/' + scoutgroup.key.urlsafe() + '/',
		trooppersons=sorted(trooppersons, semester_sort),
        ep=person,
        scoutgroup=scoutgroup,
        breadcrumbs=breadcrumbs)
Ejemplo n.º 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)
Ejemplo n.º 10
0
def show(sgroup_url=None, badge_url=None, troop_url=None, person_url=None, action=None, template_url=None):
    # logging.info("badges.py: sgroup_url=%s, badge_url=%s, troop_url=%s, person_url=%s, action=%s",
    #             sgroup_url, badge_url, troop_url, person_url, action)
    user = UserPrefs.current()  # TODO. Check right scout_group + troop_admin
    if not user.hasAccess():
        return "denied badges", 403

    breadcrumbs = [{'link': '/', 'text': 'Hem'}]
    section_title = u'Märken'
    breadcrumbs.append({'link': '/badges', 'text': section_title})
    baselink = '/badges/'

    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()})

    if scoutgroup is None:
        return render_template(
            'index.html',
            heading=section_title,
            baselink=baselink,
            items=ScoutGroup.getgroupsforuser(user),
            breadcrumbs=breadcrumbs,
            username=user.getname())

    if troop_url is None and person_url is None:  # scoutgroup level
        if badge_url is None:
            # logging.info("Render list of all badges for scout_group")
            section_title = 'Märken för kår'
            badges = Badge.get_badges(sgroup_key)
            counts = []
            for badge in badges:
                counts.append(BadgeCompleted.query(BadgeCompleted.badge_key == badge.key).count())

            return render_template('badgelist.html',
                                   heading=section_title,
                                   baselink=baselink,
                                   badges=badges,
                                   counts=counts,
                                   breadcrumbs=breadcrumbs,
                                   user=user)
        # Specific badge or new badge
        if request.method == "GET":
            if template_url is not None:
                template = ndb.Key(urlsafe=template_url).get()
            else:
                template = None
            if badge_url == "newbadge":  # Get form for or create new
                section_title = "Nytt märke"
                badge = None
                if template:
                    name = template.name
                    description = template.description
                else:
                    name = "Nytt"
                    description = ""
            else:
                section_title = "Märke"
                badge_key = ndb.Key(urlsafe=badge_url)
                badge = badge_key.get()
                name = badge.name
                description = badge.description

            baselink += 'badge/' + badge_url + "/"
            if action is not None:
                baselink += action + '/'

            breadcrumbs.append({'link': baselink, 'text': name})

            if action == "showcompleted":
                badgeCompleted = BadgeCompleted.query(BadgeCompleted.badge_key == badge_key).fetch()
                Compl = namedtuple("Compl", "name date examiner")
                completed = [Compl(bc.person_key.get().getname(),
                                   bc.date.strftime("%Y-%m-%d"),
                                   bc.examiner) for bc in badgeCompleted]
                # logging.info("Completed: %s" % completed)
                return render_template('badge_completed_list.html',
                                       breadcrumbs=breadcrumbs,
                                       badge=badge,
                                       badge_completed=completed)
            other_badges = Badge.get_badges(sgroup_key)
            parts_scout = []
            parts_admin = []
            img_url = DEFAULT_IMG_URL
            if badge:
                parts_scout = zip(badge.parts_scout_short, badge.parts_scout_long)
                parts_admin = zip(badge.parts_admin_short, badge.parts_admin_long)
                other_badges = filter(lambda bdg: bdg.name != badge.name, other_badges)
                if badge.img_url:
                    img_url = badge.img_url
            elif template:
                parts_scout = zip(template.parts_scout_short, template.parts_scout_long)
                parts_admin = zip(template.parts_admin_short, template.parts_admin_long)
                if template.img_url:
                    img_url = template.img_url
            other_badge_names = ",".join([bdg.name for bdg in other_badges])
            # logging.info(other_badge_names)
            # logging.info(img_url)
            return render_template('badge.html',
                                   name=name,
                                   heading=section_title,
                                   baselink=baselink,
                                   breadcrumbs=breadcrumbs,
                                   description=description,
                                   parts_scout=parts_scout,
                                   parts_admin=parts_admin,
                                   img_url=img_url,
                                   action=action,
                                   other_badge_names=other_badge_names,
                                   scoutgroup=scoutgroup)
        if request.method == "POST":
            name = request.form['name']
            description = request.form['description']
            parts_scout = request.form['parts_scout'].split("::")
            parts_scout = [p.split("|") for p in parts_scout]
            parts_admin = request.form['parts_admin'].split("::")
            parts_admin = [p.split("|") for p in parts_admin]
            img_url = request.form['img_url']
            # logging.info('img_data=%s' % img_data[:32])
            # logging.info('description=%s' % description)
            # logging.info("name: %s, parts: %s", name, parts)
            if badge_url == "newbadge":
                badge = Badge.create(name, sgroup_key, description, parts_scout, parts_admin, img_url)
                return "ok"  # TODO add render_template
            else:  # Update an existing badge
                badge_key = ndb.Key(urlsafe=badge_url)
                badge = badge_key.get()
                badge.update(name, description, parts_scout, parts_admin, img_url)
                return "ok" # TODO add render_template
        else:
            return "Unsupported method %s" % request.method, 500

    if troop_url is not None and badge_url is None:
        # logging.info("TROOP_URL without BADGE_URL")
        troop_key = ndb.Key(urlsafe=troop_url)
        troop = troop_key.get()
        if request.method == "GET":
            # Since we come from /start/... instead of /badges/... replace part links
            for bc in breadcrumbs:
                bc['link'] = bc['link'].replace('badges', 'start')
                bc['text'] = bc['text'].replace('Märken', 'Kårer')
            baselink += "troop/" + troop_url + "/"
            badges = Badge.get_badges(sgroup_key)
            semester_key = troop.semester_key
            semester = semester_key.get()
            semester_name = semester.getname()
            section_title = "Märken för %s %s" % (troop.name, semester_name)
            breadcrumbs.append({'link': baselink, 'text': "Märken %s" % troop.name})
            troop_badges = TroopBadge.get_badges_for_troop(troop)
            # logging.info("Nr troop_badges is %d" % len(troop_badges))
            troop_badge_names = [tb.name for tb in troop_badges]
            return render_template('badges_for_troop.html',
                                   name=troop.name,
                                   heading=section_title,
                                   baselink=baselink,
                                   breadcrumbs=breadcrumbs,
                                   badges=badges,
                                   troop_badge_names=troop_badge_names,
                                   scoutgroup=scoutgroup)
        # POST
        new_badge_names = request.form['badges'].split("|")
        new_badge_names = [n for n in new_badge_names if n != ""]
        # logging.info(new_badge_names)
        TroopBadge.update_for_troop(troop, new_badge_names)
        return "ok"  # TODO add render_template

    if troop_url is not None and badge_url is not None:
        troop_key = ndb.Key(urlsafe=troop_url)
        troop = troop_key.get()
        badge_key = ndb.Key(urlsafe=badge_url)
        badge = badge_key.get()
        if request.method == "POST":
            if person_url is not None:
                return render_badge_for_user(request, person_url, badge_url, baselink, breadcrumbs)
            # logging.info("POST %s %s" % (troop.name, badge.name))
            update_scout = request.form['update_scout']
            update_admin = request.form['update_admin']
            if update_scout == "" and update_admin == "":
                return "ok"  # Return ok to Ajax call
            progress_scout = []
            if update_scout != "":
                progress_scout = update_scout.split(",")
            progress_admin = []
            if update_admin != "":
                progress_admin = update_admin.split(",")
            examiner_name = UserPrefs.current().name
            # logging.info("progress_scout: %s" % progress_scout)
            # logging.info("progress_admin: %s" % progress_admin)
            update_badge_progress(badge, progress_scout, "scout", examiner_name)
            update_badge_progress(badge, progress_admin, "admin", examiner_name)
            return "ok"  # Return ok to Ajax call # TODO add render_template
        if request.method == "GET":
            # logging.info("GET %s %s" % (troop.name, badge.name))
            # Since we come from /start/... instead of /badges/... replace part links
            for bc in breadcrumbs:
                bc['link'] = bc['link'].replace('badges', 'start')
                bc['text'] = bc['text'].replace('Märken', 'Kårer')
            baselink += "troop/" + troop_url + "/" + badge_url + "/"
            breadcrumbs.append({'link': baselink, 'text': "%s %s" % (troop.name, badge.name)})
            if person_url is not None:
                baselink += person_url + '/'
                person_key = ndb.Key(urlsafe=person_url)
                person = person_key.get()
                breadcrumbs.append({'link': baselink, 'text': person.getname()})
                return render_badge_for_user(request, person_url, badge_url, baselink, breadcrumbs)
            return render_badge_for_troop(sgroup_url, badge_key, badge, troop_key, troop, baselink, breadcrumbs)

    if person_url is not None:
        person_key = ndb.Key(urlsafe=person_url)
        person = person_key.get()
        baselink = "/badges/" + sgroup_url + '/person/' + person_url + '/'
        breadcrumbs.append({'link': baselink, 'text': "%s" % person.getname()})
        if badge_url is None:
            # logging.info("Badges for %s" % person.getname())
            badge_parts_done = BadgePartDone.query(BadgePartDone.person_key == person_key).fetch()
            badge_keys = {part.badge_key for part in badge_parts_done}
            badges = [bkey.get() for bkey in badge_keys]
            badges.sort(key=lambda x: x.name)
            badges_completed = BadgeCompleted.query(BadgeCompleted.person_key == person_key).fetch()
            # logging.info(badges_completed)
            completed_keys = {bc.badge_key for bc in badges_completed}
            completed = [b.key in completed_keys for b in badges]
            # logging.info("badges %s completed %s" % ([b.name for b in badges], completed))

            return render_template('badgelist_person.html',
                                   heading="Märken för %s" % person.getname(),
                                   baselink=baselink,
                                   breadcrumbs=breadcrumbs,
                                   badges=badges,
                                   completed=completed,
                                   badge_parts_done=badge_parts_done)
        # badge_url is not none

    if person_url is not None and badge_url is not None:
        baselink += badge_url + "/"
        badge_key = ndb.Key(urlsafe=badge_url)
        badge = badge_key.get()
        breadcrumbs.append({'link': baselink, 'text': "%s" % badge.name})
        return render_badge_for_user(request, person_url, badge_url, baselink, breadcrumbs)

    # note that we set the 404 status explicitly
    return "Page not found", 404
Ejemplo n.º 11
0
Archivo: main.py Proyecto: kesse/skojjt
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!")