def validate_patch_tender_stage2_data(request):
    data = validate_json_data(request)
    if request.context.status == 'draft':
        default_statuses = ['active.tendering', STAGE2_STATUS]
        if data.get('status') not in default_statuses:
            raise_operation_error(request, 'Can\'t update tender in current ({0}) status'.format(data['status']))
        request.validated['data'] = {'status': data.get('status')}
        request.context.status = data.get('status')
        return
    if data:
        if 'items' in data:
            items = request.context.items
            cpv_group_lists = [i.classification.id[:3] for i in items]
            for item in data['items']:
                if 'classification' in item and 'id' in item['classification']:
                    cpv_group_lists.append(item['classification']['id'][:3])
            if len(set(cpv_group_lists)) != 1:
                request.errors.add('body', 'item', 'Can\'t change classification')
                request.errors.status = 403
                raise error_handler(request.errors)
        if 'enquiryPeriod' in data:
            if apply_data_patch(request.context.enquiryPeriod.serialize(), data['enquiryPeriod']):
                request.errors.add('body', 'item', 'Can\'t change enquiryPeriod')
                request.errors.status = 403
                raise error_handler(request.errors)
    if request.context.status == STAGE2_STATUS and data.get('status') == 'active.tendering':
        data = validate_data(request, type(request.tender), True, data)
        if data:  # if no error then add status to validate data
            request.context.status = 'active.tendering'
            data['status'] = 'active.tendering'
    else:
        data = validate_data(request, type(request.tender), True, data)

    return data
def validate_bid_status_update_not_to_pending_or_draft(request):
    if request.authenticated_role != 'Administrator':
        bid_status_to = request.validated['data'].get("status", request.context.status)
        if bid_status_to not in ['pending', 'draft']:
            request.errors.add('body', 'bid', 'Can\'t update bid to ({}) status'.format(bid_status_to))
            request.errors.status = 403
            raise error_handler(request.errors)
def validate_json_data(request):
    try:
        json = request.json_body
    except ValueError, e:
        request.errors.add('body', 'data', e.message)
        request.errors.status = 422
        raise error_handler(request.errors)
def factory(request):
    request.validated['tender_src'] = {}
    root = Root(request)
    if not request.matchdict or not request.matchdict.get('tender_id'):
        return root
    request.validated['tender_id'] = request.matchdict['tender_id']
    tender = Tender.load(root.db, request.matchdict['tender_id'])
    if not tender:
        request.errors.add('url', 'tender_id', 'Not Found')
        request.errors.status = 404
        raise error_handler(request.errors)
    tender.__parent__ = root
    request.validated['tender'] = tender
    request.validated['tender_status'] = tender.status
    if request.method != 'GET':
        request.validated['tender_src'] = tender.serialize('plain')
    if request.matchdict.get('award_id'):
        award = get_item(tender, 'award', request, root)
        if request.matchdict.get('complaint_id'):
            complaint = get_item(award, 'complaint', request, root)
            if request.matchdict.get('document_id'):
                return get_item(complaint, 'document', request, root)
            else:
                return complaint
        elif request.matchdict.get('document_id'):
            return get_item(award, 'document', request, root)
        else:
            return award
    elif request.matchdict.get('contract_id'):
        contract = get_item(tender, 'contract', request, root)
        if request.matchdict.get('document_id'):
            return get_item(contract, 'document', request, root)
        else:
            return contract
    elif request.matchdict.get('bid_id'):
        bid = get_item(tender, 'bid', request, root)
        if request.matchdict.get('document_id'):
            return get_item(bid, 'document', request, root)
        else:
            return bid
    elif request.matchdict.get('complaint_id'):
        complaint = get_item(tender, 'complaint', request, root)
        if request.matchdict.get('document_id'):
            return get_item(complaint, 'document', request, root)
        else:
            return complaint
    elif request.matchdict.get('cancellation_id'):
        cancellation = get_item(tender, 'cancellation', request, root)
        if request.matchdict.get('document_id'):
            return get_item(cancellation, 'document', request, root)
        else:
            return cancellation
    elif request.matchdict.get('document_id'):
        return get_item(tender, 'document', request, root)
    elif request.matchdict.get('question_id'):
        return get_item(tender, 'question', request, root)
    elif request.matchdict.get('lot_id'):
        return get_item(tender, 'lot', request, root)
    request.validated['id'] = request.matchdict['tender_id']
    return tender
def validate_data(request, model, partial=False, data=None):
    if data is None:
        data = validate_json_data(request)
    try:
        if partial and isinstance(request.context, model):
            initial_data = request.context.serialize()
            m = model(initial_data)
            new_patch = apply_data_patch(initial_data, data)
            if new_patch:
                m.import_data(new_patch, partial=True, strict=True)
            m.__parent__ = request.context.__parent__
            m.validate()
            role = request.context.get_role()
            method = m.to_patch
        else:
            m = model(data)
            m.__parent__ = request.context
            m.validate()
            method = m.serialize
            role = 'create'
    except (ModelValidationError, ModelConversionError), e:
        for i in e.message:
            request.errors.add('body', i, e.message[i])
        request.errors.status = 422
        raise error_handler(request.errors)
def validate_contract_data(request):
    update_logging_context(request, {'contract_id': '__new__'})
    data = request.validated['json_data'] = validate_json_data(request)
    model = request.contract_from_data(data, create=False)
    if hasattr(request, 'check_accreditation') and not request.check_accreditation(model.create_accreditation):
        request.errors.add('contract', 'accreditation', 'Broker Accreditation level does not permit contract creation')
        request.errors.status = 403
        raise error_handler(request.errors)
    return validate_data(request, model, data=data)
def tender_from_data(request, data, raise_error=True, create=True):
    procurementMethodType = data.get("procurementMethodType", "belowThreshold")
    model = request.registry.tender_procurementMethodTypes.get(procurementMethodType)
    if model is None and raise_error:
        request.errors.add("body", "procurementMethodType", "Not implemented")
        request.errors.status = 415
        raise error_handler(request)
    update_logging_context(request, {"tender_type": procurementMethodType})
    if model is not None and create:
        model = model(data)
    return model
def validate_bid_operation_not_in_tendering(request):
    if request.validated['tender_status'] != 'active.tendering':
        operation = 'add' if request.method == 'POST' else 'delete'
        if request.authenticated_role != 'Administrator' and request.method in (
                'PUT', 'PATCH'):
            operation = 'update'
        request.errors.add(
            'body', 'data',
            'Can\'t {} bid in current ({}) tender status'.format(
                operation, request.validated['tender_status']))
        request.errors.status = 403
        raise error_handler(request.errors)
def validate_update_contract_value(request):
    tender = request.validated['tender']
    data = request.validated['data']
    if data['value']:
        for ro_attr in ('valueAddedTaxIncluded', 'currency'):
            if data['value'][ro_attr] != getattr(request.context.value,
                                                 ro_attr):
                request.errors.add(
                    'body', 'data',
                    'Can\'t update {} for contract value'.format(ro_attr))
                request.errors.status = 403
                raise error_handler(request.errors)
        award = [a for a in tender.awards
                 if a.id == request.context.awardID][0]
        if data['value']['amount'] > award.value.amount:
            request.errors.add(
                'body', 'data',
                'Value amount should be less or equal to awarded amount ({})'.
                format(award.value.amount))
            request.errors.status = 403
            raise error_handler(request.errors)
Exemple #10
0
def validate_agreement_patch(request, **kwargs):
    data = validate_json_data(request)
    if data:
        if "features" in data:
            if apply_data_patch(
                [f.serialize() for f in request.context.features],
                    data["features"]):
                request.errors.add("body", "features", "Can't change features")
                request.errors.status = 403
                raise error_handler(request)

    return validate_data(request, type(request.agreement), True, data=data)
def validate_patch_tender_data(request):
    data = validate_json_data(request)
    if request.context.status != 'draft':
        return validate_data(request, type(request.tender), True, data)
    default_status = type(request.tender).fields['status'].default
    if data.get('status') != default_status:
        request.errors.add('body', 'data',
                           'Can\'t update tender in current (draft) status')
        request.errors.status = 403
        raise error_handler(request.errors)
    request.validated['data'] = {'status': default_status}
    request.context.status = default_status
def validate_access_to_award_document_upload(request, **kwargs):
    document = request.validated.get('document')

    # bid_owner in some cases has permission to change award
    if request.authenticated_role == 'bid_owner':
        # bid_owner(winner) can`t upload rejection protocol to award
        if document and document.documentType == 'rejectionProtocol':
            err_msg = 'You can\'t upload rejection protocol to award'
            request.errors.add('body', 'data', err_msg)
            request.errors.status = 403
            raise error_handler(request)
    return True
def validate_json_data(request, allow_bulk=False):
    try:
        json = request.json
    except JSONDecodeError as e:
        request.errors.add("body", "data", str(e))
        # request.errors.add("body", "data", "No JSON object could be decoded")  # Expecting value: line 1 column 1 (char 0)
        request.errors.status = 422
        raise error_handler(request)
    data = json.get("data") if isinstance(json, dict) else None
    allowed_types = (list, dict) if allow_bulk else dict
    if any([
            not isinstance(data, allowed_types),
            isinstance(data, list) and not data,
            isinstance(data, list)
            and not all(isinstance(i, dict) for i in data)
    ]):
        request.errors.add("body", "data", "Data not available")
        request.errors.status = 422
        raise error_handler(request)
    request.validated["json_data"] = data
    return json["data"]
Exemple #14
0
def validate_bid_data(request):
    if not request.check_accreditation(request.tender.edit_accreditation):
        request.errors.add('procurementMethodType', 'accreditation', 'Broker Accreditation level does not permit bid creation')
        request.errors.status = 403
        raise error_handler(request.errors)
    if request.tender.get('mode', None) is None and request.check_accreditation('t'):
        request.errors.add('procurementMethodType', 'mode', 'Broker Accreditation level does not permit bid creation')
        request.errors.status = 403
        raise error_handler(request.errors)
    update_logging_context(request, {'bid_id': '__new__'})
    model = type(request.tender).bids.model_class
    bid = validate_data(request, model)
    validated_bid = request.validated.get('bid')
    if validated_bid:
        if any([key == 'documents' or 'Documents' in key for key in validated_bid.keys()]):
            bid_documents = validate_bid_documents(request)
            if not bid_documents:
                return
            for documents_type, documents in bid_documents.items():
                validated_bid[documents_type] = documents
    return bid
Exemple #15
0
def validate_patch_tender_stage2_data(request):
    data = validate_json_data(request)
    if request.context.status == "draft":
        default_statuses = ["active.tendering", STAGE2_STATUS]
        if "status" in data and data.get("status") not in default_statuses:
            raise_operation_error(
                request, "Can't update tender in current ({0}) status".format(
                    data["status"]))
        request.validated["data"] = {"status": data.get("status")}
        request.context.status = data.get("status")
        return
    if data:
        if "items" in data:
            items = request.context.items
            cpv_group_lists = [i.classification.id[:3] for i in items]
            for item in data["items"]:
                if "classification" in item and "id" in item["classification"]:
                    cpv_group_lists.append(item["classification"]["id"][:3])
            if len(set(cpv_group_lists)) != 1:
                request.errors.add("body", "item",
                                   "Can't change classification")
                request.errors.status = 403
                raise error_handler(request.errors)
        if "enquiryPeriod" in data:
            if apply_data_patch(request.context.enquiryPeriod.serialize(),
                                data["enquiryPeriod"]):
                request.errors.add("body", "item",
                                   "Can't change enquiryPeriod")
                request.errors.status = 403
                raise error_handler(request.errors)
    if request.context.status == STAGE2_STATUS and data.get(
            "status") == "active.tendering":
        data = validate_data(request, type(request.tender), True, data)
        if data:  # if no error then add status to validate data
            request.context.status = "active.tendering"
            data["status"] = "active.tendering"
    else:
        data = validate_data(request, type(request.tender), True, data)

    return data
Exemple #16
0
def factory(request):
    request.validated['tender_src'] = {}
    root = Root(request)
    if not request.matchdict or not request.matchdict.get('tender_id'):
        return root
    request.validated['tender_id'] = request.matchdict['tender_id']
    tender = Tender.load(root.db, request.matchdict['tender_id'])
    if not tender:
        request.errors.add('url', 'tender_id', 'Not Found')
        request.errors.status = 404
        raise error_handler(request.errors)
    tender.__parent__ = root
    request.validated['tender'] = tender
    request.validated['tender_status'] = tender.status
    if request.method != 'GET':
        request.validated['tender_src'] = tender.serialize('plain')
    if request.matchdict.get('award_id'):
        award = get_item(tender, 'award', request, root)
        if request.matchdict.get('complaint_id'):
            complaint = get_item(award, 'complaint', request, root)
            if request.matchdict.get('document_id'):
                return get_item(complaint, 'document', request, root)
            else:
                return complaint
        elif request.matchdict.get('contract_id'):
            contract = get_item(award, 'contract', request, root)
            if request.matchdict.get('document_id'):
                return get_item(contract, 'document', request, root)
            else:
                return contract
        elif request.matchdict.get('document_id'):
            return get_item(award, 'document', request, root)
        else:
            return award
    elif request.matchdict.get('bid_id'):
        bid = get_item(tender, 'bid', request, root)
        if request.matchdict.get('document_id'):
            return get_item(bid, 'document', request, root)
        else:
            return bid
    elif request.matchdict.get('complaint_id'):
        complaint = get_item(tender, 'complaint', request, root)
        if request.matchdict.get('document_id'):
            return get_item(complaint, 'document', request, root)
        else:
            return complaint
    elif request.matchdict.get('document_id'):
        return get_item(tender, 'document', request, root)
    elif request.matchdict.get('question_id'):
        return get_item(tender, 'question', request, root)
    request.validated['id'] = request.matchdict['tender_id']
    return tender
def validate_plan_data(request):
    update_logging_context(request, {'plan_id': '__new__'})
    data = validate_json_data(request)
    if data is None:
        return
    model = request.plan_from_data(data, create=False)
    if hasattr(request, 'check_accreditation') \
            and not any([request.check_accreditation(acc) for acc in model.create_accreditations]):
        request.errors.add(
            'plan', 'accreditation',
            'Broker Accreditation level does not permit plan creation')
        request.errors.status = 403
        raise error_handler(request.errors)
    data = validate_data(request, model, data=data)
    if data and data.get('mode',
                         None) is None and request.check_accreditation('t'):
        request.errors.add(
            'plan', 'mode',
            'Broker Accreditation level does not permit plan creation')
        request.errors.status = 403
        raise error_handler(request.errors)
    return data
Exemple #18
0
def validate_patch_tender_ua_data(request, **kwargs):
    data = validate_json_data(request)
    if request.context.status == "draft":
        validate_patch_tender_data_draft(request)
    if data:
        if "items" in data:
            items = request.context.items
            cpv_group_lists = [i.classification.id[:3] for i in items]
            for item in data["items"]:
                if "classification" in item and "id" in item["classification"]:
                    cpv_group_lists.append(item["classification"]["id"][:3])
            if len(set(cpv_group_lists)) != 1:
                request.errors.add("body", "item", "Can't change classification")
                request.errors.status = 403
                raise error_handler(request)
        if "enquiryPeriod" in data:
            if apply_data_patch(request.context.enquiryPeriod.serialize(), data["enquiryPeriod"]):
                request.errors.add("body", "item", "Can't change enquiryPeriod")
                request.errors.status = 403
                raise error_handler(request)

    return validate_data(request, type(request.tender), True, data)
Exemple #19
0
def agreement_from_data(request, data, raise_error=True, create=True):
    if request.authenticated_role == "agreements":
        data["agreementType"] = "cfaua"
    if not data.get("agreementType") and raise_error:
        request.errors.add("data", "agreementType", "This field is required")
        request.errors.status = 422
        raise error_handler(request)

    return object_from_data(request,
                            data,
                            "agreement",
                            raise_error=raise_error,
                            create=create)
Exemple #20
0
def validate_contract_data(request):
    update_logging_context(request, {'contract_id': '__new__'})
    data = request.validated['json_data'] = validate_json_data(request)
    model = request.contract_from_data(data, create=False)
    if hasattr(request,
               'check_accreditation') and not request.check_accreditation(
                   model.create_accreditation):
        request.errors.add(
            'contract', 'accreditation',
            'Broker Accreditation level does not permit contract creation')
        request.errors.status = 403
        raise error_handler(request.errors)
    return validate_data(request, model, data=data)
Exemple #21
0
def object_from_data(request, data, obj_name, raise_error=True, create=True):
    objType = data.get("%sType" % obj_name, "electronicCatalogue")
    model_types = getattr(request.registry,
                          "%s_%sTypes" % (obj_name, obj_name))
    model = model_types.get(objType)
    if model is None and raise_error:
        request.errors.add("body", "%sType" % obj_name, "Not implemented")
        request.errors.status = 415
        raise error_handler(request)
    update_logging_context(request, {"%s_type" % obj_name: objType})
    if model is not None and create:
        model = model(data)
    return model
Exemple #22
0
def validate_tender_data(request):
    update_logging_context(request, {'tender_id': '__new__'})

    data = validate_json_data(request)

    model = request.tender_from_data(data, create=False)
    #if not request.check_accreditation(model.create_accreditation):
    #if not any([request.check_accreditation(acc) for acc in getattr(model, 'create_accreditations', [getattr(model, 'create_accreditation', '')])]):
    if not any([request.check_accreditation(acc) for acc in iter(str(model.create_accreditation))]):
        request.errors.add('procurementMethodType', 'accreditation', 'Broker Accreditation level does not permit tender creation')
        request.errors.status = 403
        raise error_handler(request.errors)
    data = validate_data(request, model, data=data)
    if data and data.get('mode', None) is None and request.check_accreditation('t'):
        request.errors.add('procurementMethodType', 'mode', 'Broker Accreditation level does not permit tender creation')
        request.errors.status = 403
        raise error_handler(request.errors)
    if data and data.get('procuringEntity', {}).get('kind', '') not in model.procuring_entity_kinds:
        request.errors.add('procuringEntity',
                           'kind',
                           '{kind!r} procuringEntity cannot publish this type of procedure. '
                           'Only {kinds} are allowed.'.format(kind=data.get('procuringEntity', {}).get('kind', ''), kinds=', '.join(model.procuring_entity_kinds)))
        request.errors.status = 403
def validate_milestone_author(request, **kwargs):
    milestone = request.validated["milestone"]
    plan = request.validated["plan"]
    author = milestone.author

    plan_identifier = plan.procuringEntity.identifier
    milestone_identifier = author.identifier
    if (plan_identifier.scheme, plan_identifier.id) != (
            milestone_identifier.scheme, milestone_identifier.id):
        request.errors.add("body", "author",
                           "Should match plan.procuringEntity")
        request.errors.status = 422
        raise error_handler(request)

    if any((m.author.identifier.scheme,
            m.author.identifier.id) == (author.identifier.scheme,
                                        author.identifier.id)
           for m in plan.milestones if m.status in Milestone.ACTIVE_STATUSES):
        request.errors.add(
            "body", "author",
            "An active milestone already exists for this author")
        request.errors.status = 422
        raise error_handler(request)
Exemple #24
0
 def patch(self):
     """Tender Document Update"""
     if not self.validate_update_tender():
         raise error_handler(self.request.errors)
     if self.request.authenticated_role == 'tender_owner' and self.request.validated[
             'tender_status'] == 'active.tendering':
         self.request.validated['tender'].invalidate_bids_data()
     if apply_patch(self.request, src=self.request.context.serialize()):
         update_file_content_type(self.request)
         self.LOGGER.info(
             'Updated tender document {}'.format(self.request.context.id),
             extra=context_unpack(self.request,
                                  {'MESSAGE_ID': 'tender_document_patch'}))
         return {'data': self.request.context.serialize("view")}
Exemple #25
0
 def validate_award_document(self, operation):
     """ TODO move validators
     This class is inherited in openua package, but validate_award_document function has different validators.
     For now, we have no way to use different validators on methods according to procedure type.
     """
     if self.request.validated['tender_status'] != 'active.qualification':
         raise_operation_error(self.request, 'Can\'t {} document in current ({}) tender status'.format(operation, self.request.validated['tender_status']))
     if any([i.status != 'active' for i in self.request.validated['tender'].lots if i.id == self.request.validated['award'].lotID]):
         raise_operation_error(self.request, 'Can {} document only in active lot status'.format(operation))
     if operation == 'update' and self.request.authenticated_role != (self.context.author or 'tender_owner'):
         self.request.errors.add('url', 'role', 'Can update document only author')
         self.request.errors.status = 403
         raise error_handler(self.request.errors)
     return True
Exemple #26
0
def validate_plan_with_tender(request):
    plan = request.validated["plan"]
    if plan.tender_id:
        json_data = request.validated["json_data"]
        names = []
        if "procuringEntity" in json_data:
            names.append("procuringEntity")
        if "budget" in json_data and "breakdown" in json_data["budget"]:
            names.append("budget.breakdown")
        for name in names:
            request.errors.add("data", name, "Changing this field is not allowed after tender creation")
        if request.errors:
            request.errors.status = 422
            raise error_handler(request.errors)
def lot_from_data(request, data, raise_error=True, create=True):
    lotType = data.get('lotType')
    if not lotType:
        lot_types = get_lot_types(request.registry, (DEFAULT_LOT_TYPE, ))
        lotType = lot_types[0] if lot_types else DEFAULT_LOT_TYPE
    model = request.registry.lotTypes.get(lotType)
    if model is None and raise_error:
        request.errors.add('body', 'lotType', 'Not implemented')
        request.errors.status = 415
        raise error_handler(request)
    update_logging_context(request, {'lot_type': lotType})
    if model is not None and create:
        model = model(data)
    return model
Exemple #28
0
 def put(self):
     """Tender Document Update"""
     if not self.validate_update_tender():
         raise error_handler(self.request.errors)
     document = upload_file(self.request)
     self.request.validated['tender'].documents.append(document)
     if self.request.authenticated_role == 'tender_owner' and self.request.validated[
             'tender_status'] == 'active.tendering':
         self.request.validated['tender'].invalidate_bids_data()
     if save_tender(self.request):
         self.LOGGER.info(
             'Updated tender document {}'.format(self.request.context.id),
             extra=context_unpack(self.request,
                                  {'MESSAGE_ID': 'tender_document_put'}))
         return {'data': document.serialize("view")}
def validate_tender_plan_procurement_method_type(request):
    plan = request.validated["plan"]
    tender = request.validated["tender"]

    if plan.tender.procurementMethodType not in (tender.procurementMethodType,
                                                 "centralizedProcurement"):
        request.errors.add(
            "data",
            "procurementMethodType",
            u"procurementMethodType doesn't match: {} != {}".format(
                plan.tender.procurementMethodType,
                tender.procurementMethodType),
        )
        request.errors.status = 422
        raise error_handler(request.errors)
Exemple #30
0
def validate_rectification_period_editing(request):
    if request.context.status == 'active.tendering' and request.authenticated_role not in [
            'chronograph', 'Administrator'
    ]:
        auction = request.validated['auction']
        rectificationPeriod = auction.rectificationPeriod or generate_rectificationPeriod(
            auction)
        if rectificationPeriod.endDate.astimezone(TZ) < get_now():
            request.errors.add(
                'body', 'data',
                'Auction can be edited only during the rectification period: from ({}) to ({}).'
                .format(rectificationPeriod.startDate.isoformat(),
                        rectificationPeriod.endDate.isoformat()))
            request.errors.status = 403
            raise error_handler(request.errors)
def validate_award_data_post_common(request, **kwargs):
    auction = request.validated['auction']
    award = request.validated['award']
    if auction.status != 'active.qualification':
        request.errors.add(
            'body', 'data', 'Can\'t create award in current ({})'
            ' auction status'.format(auction.status))
    elif any(
        [i.status != 'active' for i in auction.lots if i.id == award.lotID]):
        request.errors.add('body', 'data',
                           'Can create award only in active lot status')
    else:
        return
    request.errors.status = 403
    raise error_handler(request)
Exemple #32
0
def validate_tender(request):
    tender = request.validated["tender"]
    if tender.status in [
        "complete",
        "unsuccessful",
        "cancelled",
        "active.stage2.waiting",
        "draft.pending",
        "draft.unsuccessful",
    ]:
        request.errors.add(
            "body", "data", "Can't update credentials in current ({}) tender status".format(tender.status)
        )
        request.errors.status = 403
        raise error_handler(request.errors)
def validate_document_upload_contract_not_terminal_status(request, **kwargs):
    contract = request.context

    document_of = request.validated['document'].documentOf
    if not document_of == 'contract':
        return

    forbidden_statuses = CONTRACT_TERMINAL_STATUSES + CONTRACT_PRE_TERMINAL_STATUSES

    if contract.status in forbidden_statuses:
        request.errors.add(
            'body', 'status',
            "Can\'t attach document to contract in current ({0}) status".
            format(contract.status))
        request.errors.status = 403
        raise error_handler(request)
def validate_patch_award_access(request, **kwargs):
    auction = request.validated['auction']
    award = request.context
    next_status = request.validated['json_data'].get('status')

    # bid_owner in some cases has permission to change award
    if request.authenticated_role == 'bid_owner':
        # bid_owner(winner) can switch award form status 'pending.waiting' to cancelled
        if award.status == 'pending.waiting' and next_status == 'cancelled':
            return True
        else:
            err_msg = 'Bidder is not allowed to switch award from pending to active.'
            request.errors.add('body', 'data', err_msg)
            request.errors.status = 403
            raise error_handler(request)
    return True
def extract_transfer(request, transfer_id=None):
    """ Extract transfer from db
    :param request:
    :param transfer_id: uuid4
    :return: transfer as Transfer instance or raise 404
    """
    db = request.registry.db
    if not transfer_id:
        transfer_id = request.matchdict['transfer_id']
    doc = db.get(transfer_id)
    if doc is None or doc.get('doc_type') != 'Transfer':
        request.errors.add('url', 'transfer_id', 'Not Found')
        request.errors.status = 404
        raise error_handler(request.errors)

    return request.transfer_from_data(doc)
def validate_bid_document_operation_period(request):
    tender = request.validated['tender']
    if request.validated['tender_status'] == 'active.tendering' and (
            tender.tenderPeriod.startDate
            and get_now() < tender.tenderPeriod.startDate
            or get_now() > tender.tenderPeriod.endDate):
        request.errors.add(
            'body', 'data',
            'Document can be {} only during the tendering period: from ({}) to ({}).'
            .format(
                'added' if request.method == 'POST' else 'updated',
                tender.tenderPeriod.startDate
                and tender.tenderPeriod.startDate.isoformat(),
                tender.tenderPeriod.endDate.isoformat()))
        request.errors.status = 403
        raise error_handler(request.errors)