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_firm_to_create_bid(request): tender = request.validated['tender'] bid = request.validated['bid'] firm_keys = prepare_shortlistedFirms(tender.shortlistedFirms) bid_keys = prepare_bid_identifier(bid) if not (bid_keys <= firm_keys): raise_operation_error(request, 'Firm can\'t create bid')
def validate_update_tender(self): """ TODO move validators This class is inherited from openua package, but validate_update_tender function has different validators (check using working days). For now, we have no way to use different validators on methods according to procedure type. """ if self.request.validated['tender_status'] == 'active.tendering' and calculate_business_date(get_now(), TENDERING_EXTRA_PERIOD, self.request.validated['tender'], True) > self.request.validated['tender'].tenderPeriod.endDate: raise_operation_error(self.request, 'tenderPeriod should be extended by {0.days} working days'.format(TENDERING_EXTRA_PERIOD)) return True
def patch_as_complaint_owner(self, data): tender = self.request.validated["tender"] data = self.request.validated["data"] status = self.context.status new_status = data.get("status", status) is_qualificationPeriod = tender.qualificationPeriod.startDate < get_now( ) and (not tender.qualificationPeriod.endDate or tender.qualificationPeriod.endDate > get_now()) new_rules = get_first_revision_date(tender, get_now()) > RELEASE_2020_04_19 if (status in ["draft", "claim", "answered"] and new_status == "cancelled"): apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateCanceled = get_now() elif (new_rules and status == "draft" and self.context.type == "complaint" and new_status == "mistaken"): self.context.rejectReason = "cancelledByComplainant" apply_patch(self.request, save=False, src=self.context.serialize()) elif (status in ["pending", "accepted"] and new_status == "stopping"): apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateCanceled = get_now() elif (is_qualificationPeriod and status == "draft" and new_status == status): apply_patch(self.request, save=False, src=self.context.serialize()) elif (is_qualificationPeriod and status == "draft" and new_status == "claim"): if (self.request.validated["qualification"].status == "unsuccessful" and self.request.validated["qualification"].bidID != self.context.bid_id): raise_operation_error( self.request, "Can add claim only on unsuccessful qualification of your bid" ) apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif (is_qualificationPeriod and status == "draft" and new_status == "pending" and not new_rules): apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = "complaint" self.context.dateSubmitted = get_now() elif (status == "answered" and new_status == status): apply_patch(self.request, save=False, src=self.context.serialize()) else: raise_operation_error( self.request, "Can't update complaint from {} to {} status".format( status, new_status))
def patch_as_abovethresholdreviewers(self, data): tender = self.request.validated["tender"] data = self.request.validated["data"] status = self.context.status new_status = data.get("status", status) new_rules = get_first_revision_date(tender, get_now()) > RELEASE_2020_04_19 if (self.request.authenticated_role == "aboveThresholdReviewers" and status in ["pending", "accepted", "stopping"] and new_status == status): apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "aboveThresholdReviewers" and status in ["pending", "stopping"] and ((not new_rules and new_status in ["invalid", "mistaken"]) or (new_status == "invalid"))): apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() self.context.acceptance = False elif (self.request.authenticated_role == "aboveThresholdReviewers" and status == "pending" and new_status == "accepted"): apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateAccepted = get_now() self.context.acceptance = True elif (self.request.authenticated_role == "aboveThresholdReviewers" and status in ["accepted", "stopping"] and new_status == "declined"): apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() elif (self.request.authenticated_role == "aboveThresholdReviewers" and status in ["accepted", "stopping"] and new_status == "satisfied"): apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() tender.status = "active.pre-qualification" if tender.qualificationPeriod.endDate: tender.qualificationPeriod.endDate = None elif ( self.request.authenticated_role == "aboveThresholdReviewers" and ((not new_rules and status in ["pending", "accepted", "stopping"]) or (new_rules and status in ["accepted", "stopping"])) and new_status == "stopped"): apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() self.context.dateCanceled = self.context.dateCanceled or get_now() else: raise_operation_error( self.request, "Can't update complaint from {} to {} status".format( status, new_status))
def validate_document_operation_in_not_allowed_tender_status(request, **kwargs): if ( request.authenticated_role != "auction" and request.validated["tender_status"] not in ("draft", "draft.pending", "active.enquiries") or request.authenticated_role == "auction" and request.validated["tender_status"] not in ("active.auction", "active.qualification") ): raise_operation_error( request, "Can't {} document in current ({}) tender status".format( OPERATIONS.get(request.method), request.validated["tender_status"] ), )
def validate_patch_submission_data(request, **kwargs): data = validate_json_data(request) data = validate_data(request, type(request.submission), True, data) submission = request.validated["submission"] framework_id = data.get("frameworkID", submission["frameworkID"]) framework = get_framework_by_id(request, framework_id) if not framework: raise_operation_error( request, "frameworkID must be one of exists frameworks", ) request.validated["framework"] = framework return data
def validate_patch_milestone_status(request, **kwargs): milestone = request.context curr_status = milestone.status new_status = request.validated["data"].get("status", curr_status) if curr_status == new_status: return if new_status != "met": raise_operation_error( request, f"Can't switch milestone status from `{curr_status}` to `{new_status}`" )
def validate_update_tender(self): """ TODO move validators This class is inherited in openua package, but validate_update_tender function has different validators. For now, we have no way to use different validators on methods according to procedure type. """ if self.request.authenticated_role != 'auction' and self.request.validated['tender_status'] not in ['active.tendering', STAGE2_STATUS] or \ self.request.authenticated_role == 'auction' and self.request.validated['tender_status'] not in ['active.auction', 'active.qualification']: raise_operation_error(self.request, 'Can\'t {} document in current ({}) tender status'.format(OPERATIONS.get(self.request.method), self.request.validated['tender_status'])) if self.request.validated['tender_status'] == 'active.tendering' and calculate_business_date(get_now(), TENDERING_EXTRA_PERIOD, self.request.validated['tender']) > self.request.validated['tender'].tenderPeriod.endDate: raise_operation_error(self.request, 'tenderPeriod should be extended by {0.days} days'.format(TENDERING_EXTRA_PERIOD)) if self.request.method in ['PUT', 'PATCH']: validate_tender_document_update_not_by_author_or_tender_owner(self.request) return True
def validate_update_complaint_not_in_allowed_tender_status(request): tender = request.validated["tender"] if tender.status not in [ "active.enquiries", "active.tendering", "active.auction", "active.qualification", "active.awarded", ]: raise_operation_error( request, "Can't update complaint in current ({}) tender status".format( tender.status))
def validate_update_contracting_value_identical(request): if requested_fields_changes(request, ("amountPaid",)): value = request.validated["data"].get("value") paid_data = request.validated["json_data"].get("amountPaid") for attr in ("valueAddedTaxIncluded", "currency"): if value and paid_data and paid_data.get(attr) is not None: paid = ContractValue(paid_data) if value.get(attr) != paid.get(attr): raise_operation_error( request, "{} of {} should be identical to {} of value of contract".format(attr, "amountPaid", attr), name="amountPaid", )
def validate_json_data_in_active_enquiries(request, **kwargs): source = request.validated["data"] tender = request.validated["tender_src"] data = source if "tenderPeriod" in source and "endDate" in source["tenderPeriod"]: data["tenderPeriod"] = {"endDate": source["tenderPeriod"]["endDate"]} if len(source["items"]) != len(tender["items"]): raise_operation_error(request, "Can't update tender items. Items count mismatch") if [item["id"] for item in source["items"]] != [item["id"] for item in tender["items"]]: raise_operation_error(request, "Can't update tender items. Items order mismatch") request.validated["data"] = data
def validate_update_milestone_value(request): milestone = request.context changes = milestone.__parent__.changes pending_change = True if len( changes) > 0 and changes[-1].status == 'pending' else False if not pending_change and milestone.status in ['pending', 'scheduled']: value = request.validated['data']['value'] for k in value.keys(): v = getattr(milestone.value, k) if v != value[k]: raise_operation_error( request, "Contract doesn't have any change in 'pending' status.")
def validate_update_contract_value(request, name="value", attrs=("currency", )): data = request.validated["data"] value = data.get(name) if value: for ro_attr in attrs: field = getattr(request.context, name) if field and value.get(ro_attr) != field.to_native().get(ro_attr): raise_operation_error(request, "Can't update {} for contract {}".format( ro_attr, name), name=name)
def validate_update_contracting_paid_amount(request): data = request.validated["data"] value = data.get("value") paid = data.get("amountPaid") if paid: validate_update_contracting_value_amount(request, name="amountPaid") for attr in ("amount", "amountNet"): paid_amount = paid.get(attr) value_amount = value.get(attr) if value_amount and paid_amount > value_amount: raise_operation_error( request, "AmountPaid {} can`t be greater than value {}".format(attr, attr), name="amountPaid" )
def validate_submission_data(request, **kwargs): update_logging_context(request, {"submission_id": "__new__"}) data = validate_json_data(request) model = request.submission_from_data(data, create=False) data = validate_data(request, model, data=data) framework = get_framework_by_id(request, data["frameworkID"]) if not framework: raise_operation_error( request, "frameworkID must be one of exists frameworks", ) request.validated["framework"] = framework return data
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): raise_operation_error( request, '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()))
def validate_patch_asset_data(request, error_handler, **kwargs): data = validate_json_data(request) editing_roles = request.content_configurator.available_statuses[ request.context.status]['editing_permissions'] if request.authenticated_role not in editing_roles: msg = 'Can\'t update {} in current ({}) status'.format( request.validated['resource_type'], request.context.status) raise_operation_error(request, error_handler, msg) default_status = type(request.asset).fields['status'].default if data.get('status') == default_status and data.get( 'status') != request.context.status: raise_operation_error( request, error_handler, 'Can\'t switch asset to {} status'.format(default_status))
def validate_activate_submission(request, **kwargs): db = request.registry.db submission = request.validated["submission"] old_status = submission.status new_status = request.validated["data"].get("status", old_status) if new_status != "active" or old_status == new_status: return key = [submission.frameworkID, submission.tenderers[0].identifier.id] res = submissions_active_by_framework_id_count_view(db, key=key) if res: raise_operation_error( request, "Tenderer already have active submission for framework {}".format( submission.frameworkID))
def patch_as_tender_owner(self, data): context = self.context status = context.status new_status = data.get("status", status) if status in ["pending", "accepted"] or new_status == status and status in ["claim", "satisfied"]: apply_patch(self.request, save=False, src=context.serialize()) elif status == "claim" and new_status == "answered": if not data.get("resolution", context.resolution) or not data.get("resolutionType", context.resolutionType): raise_operation_error(self.request, "Can't update complaint: resolution and resolutionType required") if len(data.get("resolution", context.resolution)) < 20: raise_operation_error(self.request, "Can't update complaint: resolution too short") apply_patch(self.request, save=False, src=context.serialize()) context.dateAnswered = get_now() elif status == "satisfied" and new_status == "resolved": if not data.get("tendererAction", context.tendererAction): raise_operation_error(self.request, "Can't update complaint: tendererAction required") apply_patch(self.request, save=False, src=context.serialize()) else: raise_operation_error(self.request, "Can't update complaint from {} to {} status".format(status, new_status))
def patch_draft_as_complaint_owner(self, data): context = self.context status = context.status new_status = data.get("status", self.context.status) if new_status == self.context.status: apply_patch(self.request, save=False, src=context.serialize()) elif status == "draft" and new_status == "mistaken": apply_patch(self.request, save=False, src=context.serialize()) elif new_status == "pending": apply_patch(self.request, save=False, src=context.serialize()) context.dateSubmitted = get_now() else: raise_operation_error(self.request, "Can't update draft complaint into {} status".format(new_status))
def validate_change_data(request, **kwargs): update_logging_context(request, {"change_id": "__new__"}) data = validate_json_data(request) if not "rationaleType" in data: raise_operation_error(request, "Can't add change without rationaleType") model = queryUtility(IChange, data["rationaleType"]) if not model: raise_operation_error( request, "rationaleType should be one of {}".format( ["taxRate", "itemPriceVariation", "thirdParty", "partyWithdrawal"] ), ) return validate_data(request, model, data=data)
def validate_view_financial_bid_documents_allowed_in_tender_status(request): tender_status = request.validated["tender_status"] view_forbidden_states = ( "active.tendering", "active.pre-qualification", "active.pre-qualification.stand-still", "active.auction", ) if tender_status in view_forbidden_states and request.authenticated_role != "bid_owner": raise_operation_error( request, "Can't view bid documents in current ({}) tender status".format( tender_status), )
def validate_question(self, operation): """ TODO move validators This class is inherited from below package, but validate_question function has different validators. For now, we have no way to use different validators on methods according to procedure type. """ tender = self.request.validated["tender"] now = get_now() if operation == "add" and (now < tender.enquiryPeriod.startDate or now > tender.enquiryPeriod.endDate): raise_operation_error(self.request, "Can add question only in enquiryPeriod") if operation == "update" and tender.status != "active.tendering": raise_operation_error( self.request, "Can't update question in current ({}) tender status".format( tender.status)) question = self.request.validated["question"] items_dict = {i.id: i.relatedLot for i in tender.items} if any([ i.status != "active" for i in tender.lots if question.questionOf == "lot" and i.id == question.relatedItem or question.questionOf == "item" and i.id == items_dict[question.relatedItem] ]): raise_operation_error( self.request, "Can {} question only in active lot status".format(operation)) if operation == "update" and now > tender.enquiryPeriod.clarificationsUntil: raise_operation_error( self.request, "Can update question only before enquiryPeriod.clarificationsUntil" ) return True
def validate_patch_qualification_data(request, **kwargs): data = validate_json_data(request) qualification = request.validated["qualification"] framework_id = data.get("frameworkID", qualification["frameworkID"]) framework = get_framework_by_id(request.registry.db, framework_id) if not framework: raise_operation_error( request, "frameworkID must be one of existing frameworks", ) request.validated["framework_src"] = framework request.validated["framework"] = Framework(framework) request.validated["framework"].__parent__ = qualification.__parent__ return validate_data(request, type(request.qualification), True, data)
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
def _validate_plan_availability(request): data = request.validated["data"] procurement_method_type = data.get("tender", {}).get("procurementMethodType", "") now = get_now() if ((now >= RELEASE_SIMPLE_DEFENSE_FROM and procurement_method_type == "aboveThresholdUA.defense") or (now < RELEASE_SIMPLE_DEFENSE_FROM and procurement_method_type == "simple.defense")): raise_operation_error( request, "procedure with procurementMethodType = {} is not available". format(procurement_method_type), )
def validate_submission_status(request, **kwargs): status_map = { "draft": ("draft", "active", "deleted"), } curr_status = request.validated["submission_src"]["status"] new_status = request.validated["data"].get("status", curr_status) available_statuses = status_map.get(curr_status, []) if new_status not in available_statuses: raise_operation_error( request, "Can't update submission from current ({}) to new ({}) status". format(curr_status, new_status))
def validate_contract_document_operation(request, **kwargs): operation = OPERATIONS.get(request.method) if request.validated["tender_status"] not in\ ["active.qualification", "active.awarded"]: raise_operation_error( request, "Can't {} document in current ({}) tender status".format( operation, request.validated["tender_status"]), ) if request.validated["contract"].status not in ["pending", "active"]: raise_operation_error( request, "Can't {} document in current contract status".format(operation)) return True
def validate_agreement_data(request, **kwargs): update_logging_context(request, {"agreement_id": "__new__"}) data = validate_json_data(request) model = request.agreement_from_data(data, create=False) _validate_agreement_accreditation_level(request, model) if data.get("frameworkID"): framework = get_framework_by_id(request, data["frameworkID"]) if not framework: raise_operation_error( request, "frameworkID must be one of exists frameworks", ) request.validated["framework"] = framework return validate_data(request, model, data=data)
def validate_complaint_document_operation_not_in_allowed_status(request): if request.validated["tender_status"] not in [ "active.enquiries", "active.tendering", "active.auction", "active.qualification", "active.awarded", ]: raise_operation_error( request, "Can't {} document in current ({}) tender status".format( OPERATIONS.get(request.method), request.validated["tender_status"]), )
def validate_download_bid_document(request): tender = request.validated["tender"] bid = request.validated["bid"] acc_token = extract_access_token(request) auth_user_id = request.authenticated_userid if request.params.get("download"): document = request.validated["document"] is_owner = (auth_user_id == bid.owner and acc_token == bid.owner_token) is_tender_owner = (auth_user_id == tender.owner and acc_token == tender.owner_token) if document.confidentiality == "buyerOnly" and not is_owner and not is_tender_owner: raise_operation_error(request, "Document download forbidden.")
def patch_as_complaint_owner(self, data): status = self.context.status new_status = data.get("status", status) if status in ["draft", "claim", "answered"] and new_status == "cancelled": apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateCanceled = get_now() elif status == "draft": complaint_period = self.request.validated["award"].complaintPeriod is_complaint_period = ( complaint_period.startDate < get_now() < complaint_period.endDate if complaint_period.endDate else complaint_period.startDate < get_now() ) if not is_complaint_period: raise_operation_error(self.request, "Can't update draft complaint not in complaintPeriod") if new_status == status: apply_patch(self.request, save=False, src=self.context.serialize()) elif new_status == "claim": apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() else: raise_operation_error(self.request, "Can't update draft complaint to {} status".format(new_status)) elif status == "answered" and new_status == status: apply_patch(self.request, save=False, src=self.context.serialize()) elif status == "answered" and new_status == "resolved": if not isinstance(data.get("satisfied", self.context.satisfied), bool): raise_operation_error(self.request, "Can't resolve answered claim: satisfied required") apply_patch(self.request, save=False, src=self.context.serialize()) else: raise_operation_error(self.request, "Can't update complaint from {} to {}".format(status, new_status))
def collection_post(self): """Post a complaint """ tender = self.request.validated["tender"] old_rules = get_first_revision_date(tender) < RELEASE_2020_04_19 complaint = self.request.validated["complaint"] complaint.relatedLot = self.context.lotID complaint.date = get_now() complaint.bid_id = get_bid_id(self.request) if complaint.status == "claim" and complaint.type == "claim": complaint.dateSubmitted = get_now() elif old_rules and complaint.status == "pending": complaint.type = "complaint" complaint.dateSubmitted = get_now() else: complaint.status = "draft" if (self.context.status == "unsuccessful" and complaint.status == "claim" and self.context.bidID != complaint.bid_id): raise_operation_error( self.request, "Can add claim only on unsuccessful qualification of your bid") complaint.complaintID = "{}.{}{}".format( tender.tenderID, self.server_id, calculate_total_complaints(tender) + 1, ) access = set_ownership(complaint, self.request) self.context.complaints.append(complaint) if save_tender(self.request): self.LOGGER.info( "Created tender qualification complaint {}".format( complaint.id), extra=context_unpack( self.request, {"MESSAGE_ID": "tender_qualification_complaint_create"}, {"complaint_id": complaint.id}, ), ) self.request.response.status = 201 self.request.response.headers["Location"] = self.request.route_url( "{}:Tender Qualification Complaints".format( tender.procurementMethodType), tender_id=tender.id, qualification_id=self.request.validated["qualification_id"], complaint_id=complaint["id"], ) return {"data": complaint.serialize("view"), "access": access}
def stage2_bid_post(self): tender = self.request.validated['tender'] bid = self.request.validated['bid'] # TODO can't move validator because of self.allowed_bid_status_on_create if bid.status not in self.allowed_bid_status_on_create: raise_operation_error(self.request, 'Bid can be added only with status: {}.'.format(self.allowed_bid_status_on_create)) tender.modified = False api_set_ownership(bid, self.request) tender.bids.append(bid) if save_tender(self.request): self.LOGGER.info('Created tender bid {}'.format(bid.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_bid_create'}, {'bid_id': bid.id})) self.request.response.status = 201 self.request.response.headers['Location'] = self.request.route_url('{}:Tender Bids'.format(tender.procurementMethodType), tender_id=tender.id, bid_id=bid['id']) return { 'data': bid.serialize('view'), 'access': { 'token': bid.owner_token } }
def validate_credentials_generate(request): contract = request.validated['contract'] if contract.status != "active": raise_operation_error(request, 'Can\'t generate credentials in current ({}) contract status'.format(contract.status))
def validate_terminate_contract_without_amountPaid(request): contract = request.validated['contract'] if contract.status == 'terminated' and not contract.amountPaid: raise_operation_error(request, 'Can\'t terminate contract while \'amountPaid\' is not set')
def validate_contract_update_not_in_allowed_status(request): contract = request.validated['contract'] if request.authenticated_role != 'Administrator' and contract.status != 'active': raise_operation_error(request, 'Can\'t update contract in current ({}) status'.format(contract.status))
def validate_update_contract_change_status(request): data = request.validated['data'] if not data.get("dateSigned", ''): raise_operation_error(request, 'Can\'t update contract change status. \'dateSigned\' is required.')
def validate_contract_change_update_not_in_allowed_change_status(request): change = request.validated['change'] if change.status == 'active': raise_operation_error(request, 'Can\'t update contract change in current ({}) status'.format(change.status))
def validate_create_contract_change(request): contract = request.validated['contract'] if contract.changes and contract.changes[-1].status == 'pending': raise_operation_error(request, 'Can\'t create new contract change while any (pending) change exists')
def validate_contract_change_add_not_in_allowed_contract_status(request): contract = request.validated['contract'] if contract.status != 'active': raise_operation_error(request, 'Can\'t add contract change in current ({}) contract status'.format(contract.status))
def validate_submit_claim_time(request): tender = request.context claim_submit_time = request.content_configurator.tender_claim_submit_time if get_now() > calculate_business_date(tender.tenderPeriod.endDate, -claim_submit_time, tender, True): raise_operation_error(request,'Can submit claim not later than {0.days} days before tenderPeriod end'.format(claim_submit_time))
def patch(self): """Post a complaint resolution """ tender = self.request.validated['tender'] data = self.request.validated['data'] # complaint_owner if self.request.authenticated_role == 'complaint_owner' and self.context.status in ['draft', 'claim', 'answered'] and data.get('status', self.context.status) == 'cancelled': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateCanceled = get_now() elif self.request.authenticated_role == 'complaint_owner' and self.context.status in ['pending', 'accepted'] and data.get('status', self.context.status) == 'stopping': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateCanceled = get_now() elif self.request.authenticated_role == 'complaint_owner' and tender.status == 'active.tendering' and self.context.status == 'draft' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and tender.status == 'active.tendering' and self.context.status == 'draft' and data.get('status', self.context.status) == 'claim': if get_now() > calculate_business_date(tender.tenderPeriod.endDate, -CLAIM_SUBMIT_TIME, tender, True): raise_operation_error(self.request, 'Can submit claim not later than {0.days} days before tenderPeriod end'.format(CLAIM_SUBMIT_TIME)) apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif self.request.authenticated_role == 'complaint_owner' and tender.status == 'active.tendering' and self.context.status in ['draft', 'claim'] and data.get('status', self.context.status) == 'pending': if get_now() > tender.complaintPeriod.endDate: raise_operation_error(self.request, 'Can submit complaint not later than {0.days} days before tenderPeriod end'.format(COMPLAINT_SUBMIT_TIME)) apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = 'complaint' self.context.dateSubmitted = get_now() elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is True and data.get('status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is False and data.get('status', self.context.status) == 'pending': if get_now() > tender.complaintPeriod.endDate: raise_operation_error(self.request, 'Can submit complaint not later than {0.days} days before tenderPeriod end'.format(COMPLAINT_SUBMIT_TIME)) apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = 'complaint' self.context.dateEscalated = get_now() # tender_owner elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get('status', self.context.status) == self.context.status: now = get_now() if now > tender.enquiryPeriod.clarificationsUntil: raise_operation_error(self.request, 'Can update claim only before enquiryPeriod.clarificationsUntil') apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'satisfied' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get('resolution', self.context.resolution) and data.get('resolutionType', self.context.resolutionType) and data.get('status', self.context.status) == 'answered': now = get_now() if now > tender.enquiryPeriod.clarificationsUntil: raise_operation_error(self.request, 'Can update claim only before enquiryPeriod.clarificationsUntil') if len(data.get('resolution', self.context.resolution)) < 20: raise_operation_error(self.request, 'Can\'t update complaint: resolution too short') apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateAnswered = get_now() elif self.request.authenticated_role == 'tender_owner' and self.context.status in ['pending', 'accepted']: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'satisfied' and data.get('tendererAction', self.context.tendererAction) and data.get('status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) # aboveThresholdReviewers elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in ['pending', 'accepted', 'stopping'] and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in ['pending', 'stopping'] and data.get('status', self.context.status) in ['invalid', 'mistaken']: apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() self.context.acceptance = False elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status == 'pending' and data.get('status', self.context.status) == 'accepted': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateAccepted = get_now() self.context.acceptance = True elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in ['accepted', 'stopping'] and data.get('status', self.context.status) in ['declined', 'satisfied']: apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in ['pending', 'accepted', 'stopping'] and data.get('status', self.context.status) == 'stopped': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() self.context.dateCanceled = self.context.dateCanceled or get_now() else: raise_operation_error(self.request, 'Can\'t update complaint') if self.context.tendererAction and not self.context.tendererActionDate: self.context.tendererActionDate = get_now() if self.context.status not in ['draft', 'claim', 'answered', 'pending', 'accepted', 'stopping'] and tender.status in ['active.qualification', 'active.awarded']: check_tender_status(self.request) if save_tender(self.request): self.LOGGER.info('Updated tender complaint {}'.format(self.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_complaint_patch'})) return {'data': self.context.serialize("view")}
def validate_tender_period_extension_with_working_days(request): tender = request.context extra_period = request.content_configurator.tendering_period_extra if calculate_business_date(get_now(), extra_period, tender, True) > request.validated['tender'].tenderPeriod.endDate: raise_operation_error(request,'tenderPeriod should be extended by {0.days} working days'.format(extra_period))
def patch(self): """Tender Edit (partial) For example here is how procuring entity can change number of items to be procured and total Value of a tender: .. sourcecode:: http PATCH /tenders/4879d3f8ee2443169b5fbbc9f89fa607 HTTP/1.1 Host: example.com Accept: application/json { "data": { "value": { "amount": 600 }, "itemsToBeProcured": [ { "quantity": 6 } ] } } And here is the response to be expected: .. sourcecode:: http HTTP/1.0 200 OK Content-Type: application/json { "data": { "id": "4879d3f8ee2443169b5fbbc9f89fa607", "tenderID": "UA-64e93250be76435397e8c992ed4214d1", "dateModified": "2014-10-27T08:12:34.956Z", "value": { "amount": 600 }, "itemsToBeProcured": [ { "quantity": 6 } ] } } """ tender = self.context data = self.request.validated['data'] if self.request.authenticated_role == 'tender_owner' and \ self.request.validated['tender_status'] in ['active.tendering', STAGE2_STATUS]: if 'tenderPeriod' in data and 'endDate' in data['tenderPeriod']: self.request.validated['tender'].tenderPeriod.import_data(data['tenderPeriod']) validate_tender_period_extension(self.request) self.request.registry.notify(TenderInitializeEvent(self.request.validated['tender'])) self.request.validated['data']["enquiryPeriod"] = self.request.validated['tender'].enquiryPeriod.serialize() apply_patch(self.request, save=False, src=self.request.validated['tender_src']) if self.request.authenticated_role == 'chronograph': check_status_eu(self.request) elif self.request.authenticated_role == 'tender_owner' and tender.status == 'active.tendering': tender.invalidate_bids_data() elif self.request.authenticated_role == 'tender_owner' and \ self.request.validated['tender_status'] == 'active.pre-qualification' and \ tender.status == "active.pre-qualification.stand-still": if all_bids_are_reviewed(self.request): tender.qualificationPeriod.endDate = calculate_business_date(get_now(), COMPLAINT_STAND_STILL, self.request.validated['tender']) tender.check_auction_time() else: raise_operation_error(self.request, 'Can\'t switch to \'active.pre-qualification.stand-still\' while not all bids are qualified') save_tender(self.request) self.LOGGER.info('Updated tender {}'.format(tender.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_patch'})) return {'data': tender.serialize(tender.status)}
def validate_update_tender(self): tender = self.request.validated['tender'] if calculate_business_date(get_now(), TENDERING_EXTRA_PERIOD, tender, True) > tender.tenderPeriod.endDate: raise_operation_error(self.request, 'tenderPeriod should be extended by {0.days} working days'.format(TENDERING_EXTRA_PERIOD)) return True
def validate_credentials_generation(request): if request.validated['tender'].status != "draft.stage2": raise_operation_error(request, 'Can\'t generate credentials in current ({}) contract status'.format(request.validated['tender'].status))
def validate_tender_update(request): tender = request.context data = request.validated['data'] if request.authenticated_role == 'tender_owner' and 'status' in data and \ data['status'] not in ['active.pre-qualification.stand-still', 'active.stage2.waiting', tender.status]: raise_operation_error(request, 'Can\'t update tender status')
def validate_contract_document_operation_not_in_allowed_contract_status(request): if request.validated['contract'].status != 'active': raise_operation_error(request, 'Can\'t {} document in current ({}) contract status'.format(OPERATIONS.get(request.method), request.validated['contract'].status))
def validate_add_document_to_active_change(request): data = request.validated['data'] if "relatedItem" in data and data.get('documentOf') == 'change': if not [1 for c in request.validated['contract'].changes if c.id == data['relatedItem'] and c.status == 'pending']: raise_operation_error(request, 'Can\'t add document to \'active\' change')
def validate_lot_operation_for_stage2(request): operations = {"POST": "create", "PATCH": "update", "DELETE": "delete"} raise_operation_error(request, 'Can\'t {} lot for tender stage2'.format(operations.get(request.method)))