def get_resource(self, resource_id, resource_uri):
     if resource_id:
         return current_app.db_session.query(
             Resource
         ).filter(Resource.id == resource_id).one()
     if resource_uri:
         return get_resource_for_uri("/%s" % resource_uri)
    def post(self):
        data = request.get_json()

        person_uri = data["person"]["uri"]
        text = data["text"]

        resource_uri = data["resource"]["uri"]
        resource = get_resource_for_uri(resource_uri)

        settings = SettingsResource().get()

        if not (resource.auto_approval_allowed and settings["strotime_booking_allowed"]):
            abort(403, __error__=[u"Strøtimer ikke tillatt"])

        person = get_person_for_uri(person_uri)
        application = Application(person, None, text, None, resource)

        datetime_now = datetime.now()

        slots = [self.parse_slot_request(d, application) for d in data["slots"]]

        for slot in slots:
            start_date = slot.start_time.date()
            end_date = slot.end_time.date()
            week_day = slot.start_time.isoweekday()
            start_time = slot.start_time.time()
            end_time = slot.end_time.time()
            self.validate_start_and_end_times(start_date, end_date, start_time, end_time)

            if slot.start_time < nearest_hour(datetime_now):
                abort(400, __error__=[u"Du kan ikke søke om en time tilbake i tid"])

            if self.is_conflict_slot_time(
                resource, start_date, end_date, week_day, start_time, end_time
            ) or self.is_conflict_rammetid(resource, start_date, end_date, week_day, start_time, end_time):
                abort(400, __error__=[u"Tiden du har søkt på er ikke tilgjengelig"])
            if self.is_conflict_blocked_time(resource, start_date, end_date, week_day, start_time, end_time):
                abort(400, __error__=[u"Tiden du har søkt på er blokkert"])

            # The start time must be in the range 3-21 days (inclusive)
            days = (slot.start_time.date() - datetime_now.date()).days
            if days >= 3 and days <= 21:
                application.add_strotime_slot(slot)
            else:
                abort(400, __error__=[u"Tiden må være innenfor 3-21 dager fra dagens dato"])

        application.status = "Granted"
        current_app.db_session.add(application)
        current_app.db_session.commit()
        current_app.db_session.refresh(application)

        send_email_strotime_granted(application)
        send_email_to_resource(application)

        return application, 201
    def put(self, rammetid_id):
        data = request.get_json()

        rammetid = self.get_object_by_id(rammetid_id)

        status = data.get("status", None)

        resource_data = data.get("resource", None)
        if resource_data:
            resource_uri = resource_data["uri"]
            resource = get_resource_for_uri(resource_uri)
            if not resource:
                abort(403, __error__=[u'Ressursen ble ikke funnet.'])
        else:
            abort(403, __error__=[u'Data om ressursen mangler.'])

        # The rammetid might have been
        # moved to a different resource
        rammetid.resource = resource

        # The rammtid status might
        # have been changed
        rammetid.status = status

        rammetid_slots_data = data.get("rammetid_slots", None)
        if rammetid_slots_data:
            for rammetid_slot in rammetid_slots_data:
                rammetid_slot_parsed = parse_repeating_slot(rammetid_slot)
                if BaseApplicationResource.is_conflict_rammetid(resource, rammetid_slot_parsed.start_date, rammetid_slot_parsed.end_date, rammetid_slot_parsed.week_day,
                                                                rammetid_slot_parsed.start_time, rammetid_slot_parsed.end_time):
                    abort(
                        400,
                        __error__=[u'Tiden er ikke tilgjengelig']
                    )
                if BaseApplicationResource.is_conflict_blocked_time(resource, rammetid_slot_parsed.start_date, rammetid_slot_parsed.end_date, rammetid_slot_parsed.week_day,
                                                                    rammetid_slot_parsed.start_time, rammetid_slot_parsed.end_time):
                    abort(
                        400,
                        __error__=[u'Tiden er blokkert']
                    )

                rammetid.add_rammetid_slot(rammetid_slot_parsed)

        current_app.db_session.add(rammetid)
        current_app.db_session.commit()
        current_app.db_session.refresh(rammetid)

        return marshal(rammetid, rammetid_fields)
    def post(self):
        data = request.get_json()

        resource_data = data.get("resource", None)
        if resource_data:
            resource_uri = resource_data["uri"]
            resource = get_resource_for_uri(resource_uri)
            if not resource:
                abort(403, __error__=[u'Ressursen ble ikke funnet.'])
        else:
            abort(403, __error__=[u'Data om ressursen mangler.'])

        umbrella_organisation_data = data.get("umbrella_organisation", None)
        if umbrella_organisation_data:
            umbrella_organisation_uri = umbrella_organisation_data["uri"]
            umbrella_organisation = get_umbrella_organisation_for_uri(umbrella_organisation_uri)
            if not umbrella_organisation:
                abort(403, __error__=[u'Paraplyorganisasjonen ble ikke funnet.'])
        else:
            abort(403, __error__=[u'Data om paraplyorganisasjonen mangler.'])

        rammetid = Rammetid(umbrella_organisation, resource)

        rammetid_slots_data = data.get("rammetid_slots", None)
        if rammetid_slots_data:
            for rammetid_slot in rammetid_slots_data:
                rammetid_slot_parsed = parse_repeating_slot(rammetid_slot)
                if BaseApplicationResource.is_conflict_rammetid(resource, rammetid_slot_parsed.start_date, rammetid_slot_parsed.end_date, rammetid_slot_parsed.week_day,
                                                                rammetid_slot_parsed.start_time, rammetid_slot_parsed.end_time):
                    abort(
                        400,
                        __error__=[u'Tiden er ikke tilgjengelig']
                    )
                if BaseApplicationResource.is_conflict_blocked_time(resource, rammetid_slot_parsed.start_date, rammetid_slot_parsed.end_date, rammetid_slot_parsed.week_day,
                                                                    rammetid_slot_parsed.start_time, rammetid_slot_parsed.end_time):
                    abort(
                        400,
                        __error__=[u'Tiden er blokkert']
                    )
                rammetid.add_rammetid_slot(rammetid_slot_parsed)

        current_app.db_session.add(rammetid)
        current_app.db_session.commit()
        current_app.db_session.refresh(rammetid)

        return marshal(rammetid, rammetid_fields), 201
    def post(self):
        data = request.get_json()

        is_arrangement = data.get("isArrangement", False)
        person = data.get('person', None)
        if not person or not person.get('uri', None):
            abort(400)
        person_uri = person["uri"]
        text = data["text"]
        facilitation = data["facilitation"]

        resource_uri = data["resource"]["uri"]
        resource = get_resource_for_uri(resource_uri)

        settings = SettingsResource().get()
        user = get_user(request.cookies)

        # Check that the resource allows the type of application
        if not settings["single_booking_allowed"] and not (has_role(user, 'flod_brukere') or has_role(user, 'flod_saksbehandlere')) or \
                not resource.single_booking_allowed:
            abort(403, __error__=[u'Engangslån ikke tillatt'])

        organisation_data = data.get("organisation", None)
        if organisation_data:
            organisation_uri = organisation_data["uri"]
            organisation = get_organisation_for_uri(organisation_uri)
        else:
            organisation = None

        person = get_person_for_uri(person_uri)
        application = Application(
            person,
            organisation,
            text,
            facilitation,
            resource,
            amenities=data.get('amenities'),
            accessibility=data.get('accessibility'),
            equipment=data.get('equipment'),
            suitability=data.get('suitability'),
            facilitators=data.get('facilitators')
        )
        application.is_arrangement = is_arrangement

        slots = [self.parse_slot_request(d) for d in data["slots"]]
        if not slots:
            abort(400, __error__=[u'Tidspunkt mangler'])

        for slot in slots:
            start_date = slot.start_time.date()
            end_date = slot.end_time.date()
            week_day = slot.start_time.isoweekday()
            start_time = slot.start_time.time()
            end_time = slot.end_time.time()

            self.validate_end_date_of_slot(settings["single_booking_enddate"], end_date.isoformat(), u'engangslån')
            self.validate_start_and_end_times(start_date, end_date, start_time, end_time)

            if not is_arrangement:
                if self.is_conflict_slot_time(resource, start_date, end_date, week_day, start_time, end_time) or \
                        self.is_conflict_rammetid(resource, start_date, end_date, week_day, start_time, end_time):
                    abort(
                        400,
                        __error__=[u'Tiden du har søkt på er ikke tilgjengelig']
                    )

            if self.is_conflict_blocked_time(resource, start_date, end_date, week_day, start_time, end_time):
                abort(
                    400,
                    __error__=[u'Tiden du har søkt på er blokkert']
                )

            application.request_single_slot(slot)

        current_app.db_session.add(application)
        current_app.db_session.commit()
        current_app.db_session.refresh(application)
        send_email_to_resource(application)
        send_email_to_applicant(application)
        return application, 201
    def put(self, application_id):
        data = request.get_json()

        application = self.get_object_by_id(application_id)
        ensure(PUT, application)

        status = data.get("status", None)
        resource_uri = data["resource"]["uri"]
        application_message = data.get("message", "")
        to_be_invoiced = data.get("to_be_invoiced", None)
        invoice_amount = data.get("invoice_amount") or None
        if invoice_amount is not None and type(invoice_amount) is not int \
                and not invoice_amount.isdigit():
            abort(400, __error__=[u'Fakturabeløp må være heltall'])
        resource = get_resource_for_uri(resource_uri)
        if not resource:
            abort(404)
        resource_details = get_resource_from_web(application.resource.uri)
        if not resource_details:
            abort(404)

        settings = SettingsResource().get()

        user = get_user(request.cookies)

        # Check that the resource allows the type of application
        if application.get_type() == "single" and not resource.single_booking_allowed:
            abort(403, __error__=[u'Det er ikke mulig å behandle en søknad om engangslån fordi type utlån er deaktivert for lokalet'])

        if application.get_type() == "repeating" and (not resource.repeating_booking_allowed or \
                                                              (resource.repeating_booking_allowed and not settings["repeating_booking_allowed"] and not has_role(user,
                                                                                                                                                                 'flod_saksbehandlere'))):
            abort(403, __error__=[u'Det er ikke mulig å behandle en søknad om fast lån fordi type utlån er deaktivert for lokalet'])

        # The application might have been moved to a different resource.
        application.resource = resource
        if status == "Pending":
            application.amenities = application.requested_amenities
            application.accessibility = application.requested_accessibility
            application.equipment = application.requested_equipment
            application.suitability = application.requested_suitability
            application.facilitators = application.requested_facilitators
        else:
            application.amenities = data.get('amenities')
            application.accessibility = data.get('accessibility')
            application.equipment = data.get('equipment')
            application.suitability = data.get('suitability')
            application.facilitators = data.get('facilitators')

        slot_data = data.get("slots", None)
        if status == "Granted" and not slot_data:
            abort(403, __error__=[u'Tildelt tid mangler'])

        if application.get_type() == "single":
            slots = [parse_single_slot(slot, application) for slot in slot_data]
            application.single_slots = slots
        elif application.get_type() == "repeating":
            slots = [parse_repeating_slot(slot, application) for slot in slot_data]
            application.repeating_slots = slots

        # Check if there are any conflicts
        for slot in slots:
            if application.get_type() == "single":
                start_date = slot.start_time.date()
                end_date = slot.end_time.date()
                week_day = slot.start_time.isoweekday()
                start_time = slot.start_time.time()
                end_time = slot.end_time.time()
            elif application.get_type() == "repeating":
                start_date = slot.start_date
                end_date = slot.end_date
                week_day = slot.week_day
                start_time = slot.start_time
                end_time = slot.end_time

            if application.get_type() == "single":
                self.validate_end_date_of_slot(settings["single_booking_enddate"], end_date.isoformat(), u'engangslån')
            elif application.get_type() == "repeating":
                self.validate_end_date_of_slot(settings["repeating_booking_enddate"], end_date.isoformat(), u'fast lån')

            self.validate_start_and_end_times(start_date, end_date, start_time, end_time)
            if application.is_arrangement or status == "Denied":
                # NOTE: Arrangements trumph all other applications. If we reject an application, we dont nede to
                # check if the time is available...
                pass
            else:
                if self.is_conflict_slot_time(resource, start_date, end_date, week_day, start_time, end_time) or \
                        self.is_conflict_rammetid(resource, start_date, end_date, week_day, start_time, end_time):
                    abort(
                        400,
                        __error__=[u'Tiden du har søkt på er ikke tilgjengelig']
                    )

            if status != "Denied":
                if self.is_conflict_blocked_time(resource, start_date, end_date, week_day, start_time, end_time):
                    abort(
                        400,
                        __error__=[u'Tiden du har søkt på er blokkert']
                    )

        if status == "Granted" or status == "Denied" or (status == "Pending" and len(slots) == 0):
            application.status = status
        else:
            application.status = "Processing"

        application.message = application_message
        application.invoice_amount = invoice_amount
        application.to_be_invoiced = to_be_invoiced
        application.comment = data.get('comment')

        current_app.db_session.add(application)
        current_app.db_session.commit()
        current_app.db_session.refresh(application)

        document = ''
        if status == "Granted" or status == "Denied":
            document = send_email_application_processed(application)

        # Create erv code
        if invoice_amount is not None and status == "Granted":
            invoice_amount = int(invoice_amount)
            org_number = None
            if application.organisation is not None:
                organisation = get_organisation_from_web(
                    application.organisation.uri)
                org_number = organisation.get('org_number', None)

            if org_number is None:
                person = get_person_from_web(application.person.uri)
                erv_code = erv_person(application, invoice_amount,
                                      person['national_identity_number'])
            else:
                erv_code = erv_organisation(application, invoice_amount,
                                            org_number)

            print 'erv: "{}"'.format(erv_code)
            # Skip sending mail for now
            # send_erv_code_mail("{},".format(erv_code))

        application_dict = {}
        if application.get_type() == "single":
            application_dict = marshal(application, single_application_fields)
        elif application.get_type() == "repeating":
            # Authentication is not implemented for all resources yet, so we
            # skip creating sak/journalpost if no auth_token exists
            if status == 'Granted' and 'auth_token' in request.cookies:
                arkiver(application, document)

            application_dict = marshal(application, repeating_application_fields)

        # Include emails in response, if requested
        if data.get("include_emails", False):
            _, granted_message = render_email_template(application, "Granted")
            _, denied_message = render_email_template(application, "Denied")
            application_dict['emails'] = dict(
                granted_message=granted_message,
                denied_message=denied_message
            )

        return application_dict
    def post(self):
        data = request.get_json()

        rammetid_to_application = RammetidToApplication(data.get('umbrella_organisation').get('uri'))
        ensure(POST, rammetid_to_application)

        resource = data.get("resource", None)
        if not resource:
            abort(403, __error__=[u'Ressurs er ikke angitt.'])

        resource = get_resource_for_uri(resource['uri'])
        if not resource:
            abort(404, __error__=[u'Ressursen finnes ikke.'])

        if not resource.repeating_booking_allowed:
            abort(403, __error__=[u'Gjentakende lån ikke tillatt'])

        user = get_user(request.cookies)
        person_uri = '/persons/{}'.format(user['person_id'])
        person = get_person_for_uri(person_uri)
        if not person:
            abort(404, __error__=[u'Personen finnes ikke.'])

        # get umbrella member orgs from organisations backend
        umbrella_member_organisations = get_umbrella_organisation_from_web(data.get('umbrella_organisation').get('uri')).get('organisations', [])

        # get local umbrella organisation object
        umbrella_organisation = get_umbrella_organisation_for_uri(data.get('umbrella_organisation').get('uri'))

        text = "Rammetid fordeling"

        applications = []
        organisations = data.get('organisations', None)
        for organisation in organisations:
            organisation_data = organisations[organisation]
            # have to be superuser if the organisation is not public and not copied to booking already
            organisation = get_organisation_for_uri(organisation_data['uri'], cookies=make_superuser_auth_cookie())

            if not organisation:
                abort(404, __error__=[u'Organisasjonen finnes ikke.'])

            if not any(org.get('uri') == organisation_data['uri'] for org in umbrella_member_organisations):
                abort(403, __error__=[u'Organisasjonen hører ikke til paraplyorganisasjonen'])

            application = Application(person, organisation, text, None, resource)
            application.status = 'Granted'

            slots = organisation_data["slots"]
            for slot_data in slots:

                slot = self.parse_slot(slot_data, application)
                slot_request = self.parse_slot_request(slot_data)

                start_date = slot.start_date
                end_date = slot.end_date
                week_day = slot.week_day
                start_time = slot.start_time
                end_time = slot.end_time

                self.validate_start_and_end_times(start_date, end_date, start_time, end_time)

                if not self.has_matching_rammetid(umbrella_organisation.id, start_date, end_date, week_day, start_time, end_time):
                    abort(400, __error__=[u'Ingen rammetid passer'])

                if self.is_conflict_slot_time(resource, start_date, end_date, week_day, start_time, end_time):
                    abort(400, __error__=[u'Tiden du har søkt på er ikke tilgjengelig'])

                if self.is_conflict_blocked_time(resource, start_date, end_date, week_day, start_time, end_time):
                    abort(400, __error__=[u'Tiden du har søkt på er blokkert'])

                application.request_repeating_slot(slot_request)
                application.add_repeating_slot(slot)
            applications.append(application)

        for application in applications:
            current_app.db_session.add(application)
            current_app.db_session.commit()
            current_app.db_session.refresh(application)

        return applications, 201
def get_resource_statistic(facility_id, start_date, end_date):
    resource_uri = "/facilities/%s" % facility_id
    resource = get_resource_for_uri(resource_uri)
    resource_details = get_resource_from_web(resource_uri)
    resource_area = resource_details['area']

    statuses = ["Granted"]

    resource_id = resource.id
    single_booking = current_app.db_session.query(Organisation.uri.label("organisation_uri"), func.sum(Slot.end_time - Slot.start_time).label("time")) \
        .outerjoin(Application.organisation) \
        .filter(Application.resource_id == resource_id,
                Slot.application_id == Application.id,
                Application.to_be_invoiced != True,  # != True to include both False and None
                Application.status.in_(statuses),
                # Get all slots between start and end date
                cast(Slot.start_time, Date).between(start_date, end_date),
                cast(Slot.end_time, Date).between(start_date, end_date),
                ) \
        .group_by(Organisation.uri)

    strotime_booking = current_app.db_session.query(Organisation.uri.label("organisation_uri"), func.sum(StrotimeSlot.end_time - StrotimeSlot.start_time).label("time")) \
        .outerjoin(Application.organisation) \
        .filter(Application.resource_id == resource_id,
                StrotimeSlot.application_id == Application.id,
                Application.to_be_invoiced != True,  # != True to include both False and None
                Application.status.in_(statuses),
                # Get all slots between start and end date
                cast(StrotimeSlot.start_time, Date).between(start_date, end_date),
                cast(StrotimeSlot.end_time, Date).between(start_date, end_date),
                ) \
        .group_by(Organisation.uri)

    repeating_booking = current_app.db_session.query(Organisation.uri.label("organisation_uri"), RepeatingSlot.start_date, RepeatingSlot.end_date, RepeatingSlot.start_time,
                                                     RepeatingSlot.end_time, RepeatingSlot.week_day) \
        .outerjoin(Application.organisation) \
        .filter(Application.resource_id == resource_id,
                RepeatingSlot.application_id == Application.id,
                Application.to_be_invoiced != True,  # != True to include both False and None
                Application.status.in_(statuses),
                # Get all slots between start and end date
                cast(RepeatingSlot.start_date, Date) <= end_date,
                cast(RepeatingSlot.end_date, Date) >= start_date,
                )

    results = []
    for single in single_booking.all():
        add_hours(results, single, resource_area)

    for strotime in strotime_booking.all():
        add_hours(results, strotime, resource_area)

    for repeating in repeating_booking.all():
        start = repeating.start_date
        if start < start_date:
            start = start_date

        end = repeating.end_date
        if end > end_date:
            end = end_date

        weeks = (end - start).days / 7

        starthours = datetime.combine(date.min, repeating.start_time)
        endhours = datetime.combine(date.min, repeating.end_time)

        hours = (endhours - starthours).total_seconds() / 3600.0
        total_hours = hours * weeks
        if ((end == start and start.isoweekday() == repeating.week_day)  # exact day
            or ((end - start).days % 7 != 0  # remaining week
                # repeating weekday after start and before end. I.E start is tuesday, repeating is wednesday, end is friday
                and ((start.isoweekday() <= repeating.week_day <= end.isoweekday())
                     # repeating weekday before start and before end, and start is after end. I.E start is friday, repeating is tuesday and end is wednesday
                     or (end.isoweekday() <= start.isoweekday() >= repeating.week_day <= end.isoweekday())))):
            total_hours += hours

        if total_hours > 0:
            item = find_organisation(results, repeating.organisation_uri)
            item['hours'] += total_hours
            item['area_time'] += total_hours * resource_area

    return marshal(results, resource_statistic_fields)
    def post(self):
        data = request.get_json()

        person = data.get('person', None)
        if not person or not person.get('uri', None):
            abort(400)
        person_uri = person["uri"]
        text = data["text"]
        facilitation = data['facilitation']

        resource_uri = data["resource"]["uri"]
        resource = get_resource_for_uri(resource_uri)

        settings = SettingsResource().get()
        user = get_user(request.cookies)

        # Check that the resource allows the type of application
        if (resource.repeating_booking_allowed and not settings["repeating_booking_allowed"] and not has_role(user, 'flod_saksbehandlere')) or \
                (not settings["repeating_booking_allowed"] and not (has_role(user, 'flod_brukere') or has_role(user, 'flod_saksbehandlere'))) or \
                not resource.repeating_booking_allowed:
            abort(403, __error__=[u'Gjentakende lån ikke tillatt'])

        organisation_data = data.get("organisation", None)
        if organisation_data:
            organisation_uri = organisation_data["uri"]
            organisation = get_organisation_for_uri(organisation_uri)
        else:
            organisation = None
        if not organisation:
            abort(
                403,
                __error__=[u'Du kan ikke søke gjentakende lån som privatperson']
            )

        person = get_person_for_uri(person_uri)
        application = Application(
            person,
            organisation,
            text,
            facilitation,
            resource,
            amenities=data.get('amenities'),
            accessibility=data.get('accessibility'),
            equipment=data.get('equipment'),
            suitability=data.get('suitability'),
            facilitators=data.get('facilitators')
        )

        slots = None
        try:
            slots = [self.parse_slot_request(d) for d in data["slots"]]
        except BookingDomainException as e:
            abort(400, __error__=[e.message])

        if not slots:
            abort(400, __error__=[u'Tidspunkt mangler'])

        for slot in slots:
            start_date = slot.start_date
            end_date = slot.end_date
            week_day = slot.week_day
            start_time = slot.start_time
            end_time = slot.end_time

            self.validate_end_date_of_slot(settings["repeating_booking_enddate"], end_date.isoformat(), u'fast lån')
            self.validate_start_and_end_times(start_date, end_date, start_time, end_time)

            if self.is_conflict_slot_time(resource, start_date, end_date, week_day, start_time, end_time) or \
                    self.is_conflict_rammetid(resource, start_date, end_date, week_day, start_time, end_time):
                abort(
                    400,
                    __error__=[u'Tiden du har søkt på er ikke tilgjengelig']
                )
            if self.is_conflict_blocked_time(resource, start_date, end_date, week_day, start_time, end_time):
                abort(
                    400,
                    __error__=[u'Tiden du har søkt på er blokkert']
                )

            application.request_repeating_slot(slot)

        current_app.db_session.add(application)
        current_app.db_session.commit()
        current_app.db_session.refresh(application)
        send_email_to_resource(application)

        return application, 201