class Encryption(Model):
    sha256 = StringType(deserialize_from='sha256')
    kmsKey_service_account = StringType(
        deserialize_from='kmsKeyServiceAccount')
    raw_key = StringType(deserialize_from='rawKey')
    kms_key_name = StringType(deserialize_from='kmsKeyName')
Example #2
0
class ContractModification(Model):
    class Options:
        roles = RolesFromCsv("ContractModification.csv", relative_to=__file__)

    itemId = StringType()
    contractId = StringType(required=True)
class DayOfWeek(Model):
    day = StringType(choices=('MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY',
                              'FRIDAY', 'SATURDAY', 'SUNDAY'))
    start_time = StringType(deserialize_from='startTime')
    duration = StringType()
class RetentionPolicy(Model):
    max_retention_days_display = StringType(serialize_when_none=False)
    max_retention_days = IntType(deserialize_from='maxRetentionDays',
                                 serialize_when_none=False)
    on_source_disk_delete = StringType(deserialize_from='onSourceDiskDelete',
                                       serialize_when_none=False)
class ScaleCapacity(Model):
    default = StringType(serialize_when_none=False)
    maximum = StringType(serialize_when_none=False)
    minimum = StringType(serialize_when_none=False)
Example #6
0
class Projects(Model):
    postcode = StringType(max_length=6, required=True)

    desc = StringType()
Example #7
0
class Tender(BaseTender):
    """Data regarding tender process - publicly inviting prospective contractors
    to submit bids for evaluation and selecting a winner or winners.
    """
    class Options:
        namespace = "Tender"
        _core_roles = BaseTender.Options.roles
        # without _serializable_fields they won't be calculated (even though serialized_name is in the role)
        _serializable_fields = whitelist("tender_guarantee", "tender_value",
                                         "tender_minimalStep")
        _edit_fields = _serializable_fields + whitelist(
            "enquiryPeriod",
            "next_check",
            "numberOfBidders",
            "hasEnquiries",
            "features",
            "items",
            "tenderPeriod",
            "procuringEntity",
            "guarantee",
            "value",
            "minimalStep",
        )
        _edit_role = _core_roles["edit"] + _edit_fields + whitelist(
            "contracts", "numberOfBids")
        _view_tendering_role = (_core_roles["view"] + _edit_fields + whitelist(
            "auctionUrl",
            "awards",
            "awardPeriod",
            "questions",
            "lots",
            "cancellations",
            "complaints",
            "contracts",
            "auctionPeriod",
        ))
        _view_role = _view_tendering_role + whitelist("bids", "numberOfBids")
        _all_forbidden = whitelist()
        roles = {
            "create": _core_roles["create"] + _edit_role + whitelist("lots"),
            "edit": _edit_role,
            "edit_draft": _core_roles["edit_draft"],
            "edit_active.enquiries": _edit_role,
            "edit_active.tendering": _all_forbidden,
            "edit_active.auction": _all_forbidden,
            "edit_active.qualification": _all_forbidden,
            "edit_active.awarded": _all_forbidden,
            "edit_complete": _all_forbidden,
            "edit_unsuccessful": _all_forbidden,
            "edit_cancelled": _all_forbidden,
            "draft": _view_tendering_role,
            "active.enquiries": _view_tendering_role,
            "active.tendering": _view_tendering_role,
            "active.auction": _view_tendering_role,
            "view": _view_role,
            "active.qualification": _view_role,
            "active.awarded": _view_role,
            "complete": _view_role,
            "unsuccessful": _view_role,
            "cancelled": _view_role,
            "auction_view": _core_roles["auction_view"],
            "auction_post": _core_roles["auction_post"],
            "auction_patch": _core_roles["auction_patch"],
            "chronograph": _core_roles["chronograph"],
            "chronograph_view": _core_roles["chronograph_view"],
            "Administrator": _core_roles["Administrator"],
            "plain": _core_roles["plain"],
            "listing": _core_roles["listing"],
            "contracting": _core_roles["contracting"],
            "default": _core_roles["default"],
        }

    items = ListType(
        ModelType(Item, required=True),
        required=True,
        min_size=1,
        validators=[validate_items_uniq, validate_classification_id],
    )  # The goods and services to be purchased, broken into line items wherever possible. Items should not be duplicated, but a quantity of 2 specified instead.
    value = ModelType(
        Value, required=True)  # The total estimated value of the procurement.
    enquiryPeriod = ModelType(
        PeriodEndRequired, required=True
    )  # The period during which enquiries may be made and will be answered.
    tenderPeriod = ModelType(
        PeriodEndRequired, required=True
    )  # The period when the tender is open for submissions. The end date is the closing date for tender submissions.
    hasEnquiries = BooleanType(
    )  # A Yes/No field as to whether enquiries were part of tender process.
    awardPeriod = ModelType(
        Period
    )  # The date or period on which an award is anticipated to be made.
    numberOfBidders = IntType(
    )  # The number of unique tenderers who participated in the tender
    bids = ListType(ModelType(Bid, required=True), default=list(
    ))  # A list of all the companies who entered submissions for the tender.
    procuringEntity = ModelType(
        ProcuringEntity, required=True
    )  # The entity managing the procurement, which may be different from the buyer who is paying / using the items being procured.
    awards = ListType(ModelType(Award, required=True), default=list())
    contracts = ListType(ModelType(Contract, required=True), default=list())
    auctionPeriod = ModelType(TenderAuctionPeriod, default={})
    minimalStep = ModelType(Value, required=True)
    questions = ListType(ModelType(Question, required=True), default=list())
    complaints = ListType(ComplaintModelType(Complaint, required=True),
                          default=list())
    auctionUrl = URLType()
    cancellations = ListType(ModelType(Cancellation, required=True),
                             default=list())
    features = ListType(ModelType(Feature, required=True),
                        validators=[validate_features_uniq])
    lots = ListType(ModelType(Lot, required=True),
                    default=list(),
                    validators=[validate_lots_uniq])
    guarantee = ModelType(Guarantee)

    procurementMethodType = StringType(default="belowThreshold")

    procuring_entity_kinds = [
        "general", "special", "defense", "central", "other"
    ]
    block_complaint_status = ["answered", "pending"]

    def __local_roles__(self):
        roles = dict([("{}_{}".format(self.owner,
                                      self.owner_token), "tender_owner")])
        for i in self.bids:
            roles["{}_{}".format(i.owner, i.owner_token)] = "bid_owner"
        return roles

    def __acl__(self):
        acl = super(Tender, self).__acl__()
        acl.extend([(Allow, "g:brokers", "create_cancellation_complaint")])
        return acl

    @serializable(serialize_when_none=False)
    def next_check(self):
        now = get_now()
        checks = []
        if self.status == "active.enquiries" and self.tenderPeriod.startDate:
            checks.append(self.tenderPeriod.startDate.astimezone(TZ))
        elif self.status == "active.enquiries" and self.enquiryPeriod.endDate:
            checks.append(self.enquiryPeriod.endDate.astimezone(TZ))
        elif self.status == "active.tendering" and self.tenderPeriod.endDate:
            checks.append(self.tenderPeriod.endDate.astimezone(TZ))
        elif (not self.lots and self.status == "active.auction"
              and self.auctionPeriod and self.auctionPeriod.startDate
              and not self.auctionPeriod.endDate):
            if now < self.auctionPeriod.startDate:
                checks.append(self.auctionPeriod.startDate.astimezone(TZ))
            elif now < calc_auction_end_time(
                    self.numberOfBids,
                    self.auctionPeriod.startDate).astimezone(TZ):
                checks.append(
                    calc_auction_end_time(
                        self.numberOfBids,
                        self.auctionPeriod.startDate).astimezone(TZ))
        elif self.lots and self.status == "active.auction":
            for lot in self.lots:
                if (lot.status != "active" or not lot.auctionPeriod
                        or not lot.auctionPeriod.startDate
                        or lot.auctionPeriod.endDate):
                    continue
                if now < lot.auctionPeriod.startDate:
                    checks.append(lot.auctionPeriod.startDate.astimezone(TZ))
                elif now < calc_auction_end_time(
                        lot.numberOfBids,
                        lot.auctionPeriod.startDate).astimezone(TZ):
                    checks.append(
                        calc_auction_end_time(
                            lot.numberOfBids,
                            lot.auctionPeriod.startDate).astimezone(TZ))
        elif (not self.lots and self.status == "active.awarded" and not any(
            [i.status in self.block_complaint_status for i in self.complaints])
              and not any([
                  i.status in self.block_complaint_status for a in self.awards
                  for i in a.complaints
              ])):
            standStillEnds = [
                a.complaintPeriod.endDate.astimezone(TZ) for a in self.awards
                if a.complaintPeriod.endDate
            ]
            last_award_status = self.awards[-1].status if self.awards else ""
            if standStillEnds and last_award_status == "unsuccessful":
                checks.append(max(standStillEnds))
        elif (self.lots
              and self.status in ["active.qualification", "active.awarded"]
              and not any([
                  i.status in self.block_complaint_status
                  and i.relatedLot is None for i in self.complaints
              ])):
            for lot in self.lots:
                if lot["status"] != "active":
                    continue
                lot_awards = [i for i in self.awards if i.lotID == lot.id]
                pending_complaints = any([
                    i["status"] in self.block_complaint_status
                    and i.relatedLot == lot.id for i in self.complaints
                ])
                pending_awards_complaints = any([
                    i.status in self.block_complaint_status for a in lot_awards
                    for i in a.complaints
                ])
                standStillEnds = [
                    a.complaintPeriod.endDate.astimezone(TZ)
                    for a in lot_awards if a.complaintPeriod.endDate
                ]
                last_award_status = lot_awards[-1].status if lot_awards else ""
                if (not pending_complaints and not pending_awards_complaints
                        and standStillEnds
                        and last_award_status == "unsuccessful"):
                    checks.append(max(standStillEnds))
        if self.status.startswith("active"):
            from openprocurement.tender.core.utils import calculate_tender_business_date

            for complaint in self.complaints:
                if complaint.status == "answered" and complaint.dateAnswered:
                    checks.append(
                        calculate_tender_business_date(
                            complaint.dateAnswered, COMPLAINT_STAND_STILL_TIME,
                            self))
                elif complaint.status == "pending":
                    checks.append(self.dateModified)
            for award in self.awards:
                if award.status == "active" and not any(
                    [i.awardID == award.id for i in self.contracts]):
                    checks.append(award.date)
                for complaint in award.complaints:
                    if complaint.status == "answered" and complaint.dateAnswered:
                        checks.append(
                            calculate_tender_business_date(
                                complaint.dateAnswered,
                                COMPLAINT_STAND_STILL_TIME, self))
                    elif complaint.status == "pending":
                        checks.append(self.dateModified)
        return min(checks).isoformat() if checks else None

    @serializable
    def numberOfBids(self):
        """A property that is serialized by schematics exports."""
        return len(self.bids)

    @serializable(serialized_name="value", type=ModelType(Value))
    def tender_value(self):
        return (Value(
            dict(
                amount=sum([i.value.amount for i in self.lots]),
                currency=self.value.currency,
                valueAddedTaxIncluded=self.value.valueAddedTaxIncluded,
            )) if self.lots else self.value)

    @serializable(serialized_name="guarantee",
                  serialize_when_none=False,
                  type=ModelType(Guarantee))
    def tender_guarantee(self):
        if self.lots:
            lots_amount = [
                i.guarantee.amount for i in self.lots if i.guarantee
            ]
            if not lots_amount:
                return self.guarantee
            guarantee = {"amount": sum(lots_amount)}
            lots_currency = [
                i.guarantee.currency for i in self.lots if i.guarantee
            ]
            guarantee["currency"] = lots_currency[0] if lots_currency else None
            if self.guarantee:
                guarantee["currency"] = self.guarantee.currency
            return Guarantee(guarantee)
        else:
            return self.guarantee

    @serializable(serialized_name="minimalStep", type=ModelType(Value))
    def tender_minimalStep(self):
        return (Value(
            dict(
                amount=min([i.minimalStep.amount for i in self.lots]),
                currency=self.minimalStep.currency,
                valueAddedTaxIncluded=self.minimalStep.valueAddedTaxIncluded,
            )) if self.lots else self.minimalStep)

    def validate_items(self, data, items):
        cpv_336_group = items[
            0].classification.id[:3] == "336" if items else False
        if (not cpv_336_group
                and (data.get("revisions")[0].date if data.get("revisions")
                     else get_now()) > CPV_ITEMS_CLASS_FROM and items
                and len(set([i.classification.id[:4] for i in items])) != 1):
            raise ValidationError(u"CPV class of items should be identical")
        else:
            validate_cpv_group(items)

    def validate_features(self, data, features):
        if (features and data["lots"] and any([
                round(
                    vnmax([
                        i for i in features if i.featureOf == "tenderer"
                        or i.featureOf == "lot" and i.relatedItem == lot["id"]
                        or i.featureOf == "item" and i.relatedItem in [
                            j.id
                            for j in data["items"] if j.relatedLot == lot["id"]
                        ]
                    ]),
                    15,
                ) > 0.3 for lot in data["lots"]
        ])):
            raise ValidationError(
                u"Sum of max value of all features for lot should be less then or equal to 30%"
            )
        elif features and not data["lots"] and round(vnmax(features),
                                                     15) > 0.3:
            raise ValidationError(
                u"Sum of max value of all features should be less then or equal to 30%"
            )

    def validate_auctionUrl(self, data, url):
        if url and data["lots"]:
            raise ValidationError(u"url should be posted for each lot")

    def validate_minimalStep(self, data, value):
        validate_minimalstep(data, value)

    def validate_enquiryPeriod(self, data, period):
        active_validation = get_first_revision_date(
            data, default=get_now()) > RELEASE_2020_04_19

        if (active_validation and period and period.startDate
                and period.endDate
                and period.endDate < calculate_tender_business_date(
                    period.startDate, timedelta(days=3), data, True)):
            raise ValidationError(
                u"the enquiryPeriod cannot end earlier than 3 business days after the start"
            )

    def validate_tenderPeriod(self, data, period):
        if (period and period.startDate and data.get("enquiryPeriod")
                and data.get("enquiryPeriod").endDate
                and period.startDate < data.get("enquiryPeriod").endDate):
            raise ValidationError(u"period should begin after enquiryPeriod")

        active_validation = get_first_revision_date(
            data, default=get_now()) > RELEASE_2020_04_19
        if (active_validation and period and period.startDate
                and period.endDate
                and period.endDate < calculate_tender_business_date(
                    period.startDate, timedelta(days=2), data, True)):
            raise ValidationError(
                u"the tenderPeriod cannot end earlier than 2 business days after the start"
            )

    def validate_awardPeriod(self, data, period):
        if (period and period.startDate and data.get("auctionPeriod")
                and data.get("auctionPeriod").endDate
                and period.startDate < data.get("auctionPeriod").endDate):
            raise ValidationError(u"period should begin after auctionPeriod")
        if (period and period.startDate and data.get("tenderPeriod")
                and data.get("tenderPeriod").endDate
                and period.startDate < data.get("tenderPeriod").endDate):
            raise ValidationError(u"period should begin after tenderPeriod")

    def validate_lots(self, data, value):
        if len(set([lot.guarantee.currency
                    for lot in value if lot.guarantee])) > 1:
            raise ValidationError(
                u"lot guarantee currency should be identical to tender guarantee currency"
            )
Example #8
0
 def test_string_type_accepts_none(self):
     field = StringType()
     field.validate(None)
class ScaleAction(Model):
    direction = StringType(choices=('Decrease', 'Increase', 'None'), serialize_when_none=False)
    type = StringType(choices=('ChangeCount', 'ExactCount', 'PercentChangeCount'), serialize_when_none=False)
    value = StringType(serialize_when_none=False)
    cooldown = TimedeltaType(serialize_when_none=False)
class AutoscaleProfile(Model):
    capacity = ModelType(ScaleCapacity, serialize_when_none=False)
    fixed_date = ModelType(TimeWindow, serialize_when_none=False)
    name = StringType(serialize_when_none=False)
    recurrence = ModelType(Recurrence, serialize_when_none=False)
    rules = ListType(ModelType(ScaleRule), serialize_when_none=False)
class Recurrence(Model):
    frequency = StringType(choices= ('Day', 'Hour', 'Minute', 'Month', 'None', 'Second', 'Week', 'Year'), serialize_when_none=False)
    schedule = ModelType(RecurrentSchedule)
class RecurrentSchedule(Model):
    days = ListType(StringType, serialize_when_none=False)
    hours = ListType(IntType, serialize_when_none=False)
    minutes = ListType(IntType, serialize_when_none=False)
    time_zone = StringType(serialize_when_none=False)
class TimeWindow(Model):
    end = StringType(serialize_when_none=False)
    start = StringType(serialize_when_none=False)
    time_zone = StringType(serialize_when_none=False)
Example #14
0
def test_string_type_required():
    field = StringType(required=True)
    with pytest.raises(ValidationError):
        field.validate(None)
Example #15
0
class RequestGithubToken(Model):
    authorizationCode = StringType(required=True)
 def test_string_required_doesnt_accept_empty_string(self):
     field = StringType(required=True)
     with self.assertRaises(ValidationError):
         field.validate('')
Example #17
0
class RequestGithubAuthorization(Model):
    username = StringType(required=True)
    password = StringType(required=True)
    otp_code = StringType()
Example #18
0
 def test_string_min_length_doesnt_accept_empty_string(self):
     field = StringType(min_length=1)
     with self.assertRaises(ValidationError):
         field.validate('')
class AutoScalingResource(CloudServiceResource):
    cloud_service_group = StringType(default='EC2')
Example #20
0
class RequestData(Model):
    text = StringType(required=True)
class AutoScalingGroupResource(AutoScalingResource):
    cloud_service_type = StringType(default='AutoScalingGroup')
    data = ModelType(AutoScalingGroup)
    _metadata = ModelType(CloudServiceMeta,
                          default=asg_meta,
                          serialized_name='metadata')
class DailySchedule(Model):
    days_in_cycle = IntType(deserialize_from='daysInCycle')
    start_time = StringType(deserialize_from='startTime')
    duration = StringType()
class LaunchConfigurationResource(AutoScalingResource):
    cloud_service_type = StringType(default='LaunchConfiguration')
    data = ModelType(LaunchConfiguration)
    _metadata = ModelType(CloudServiceMeta,
                          default=lc_meta,
                          serialized_name='metadata')
class Labels(Model):
    key = StringType()
    value = StringType()
class LaunchTemplateResource(AutoScalingResource):
    cloud_service_type = StringType(default='LaunchTemplate')
    data = ModelType(LaunchTemplateDetail)
    _metadata = ModelType(CloudServiceMeta,
                          default=lt_meta,
                          serialized_name='metadata')
class Disk(Model):
    source_disk = StringType()
    source_disk_display = StringType()
    source_disk_id = StringType()
    disk_size = FloatType()
    storage_bytes = IntType()
Example #27
0
class Bid(BaseBid):
    class Options:
        roles = {
            "Administrator":
            Administrator_bid_role,
            "embedded":
            view_bid_role,
            "view":
            view_bid_role,
            "create":
            whitelist(
                "value",
                "tenderers",
                "parameters",
                "lotValues",
                "status",
                "selfQualified",
                "selfEligible",
                "subcontractingDetails",
                "documents",
            ),
            "edit":
            whitelist("value", "tenderers", "parameters", "lotValues",
                      "status", "subcontractingDetails"),
            "auction_view":
            whitelist("value", "lotValues", "id", "date", "parameters",
                      "participationUrl", "status"),
            "auction_post":
            whitelist("value", "lotValues", "id", "date"),
            "auction_patch":
            whitelist("id", "lotValues", "participationUrl"),
            "active.enquiries":
            whitelist(),
            "active.tendering":
            whitelist(),
            "active.auction":
            whitelist(),
            "active.qualification":
            view_bid_role,
            "active.awarded":
            view_bid_role,
            "complete":
            view_bid_role,
            "unsuccessful":
            view_bid_role,
            "cancelled":
            view_bid_role,
            "invalid":
            whitelist("id", "status"),
            "deleted":
            whitelist("id", "status"),
        }

    lotValues = ListType(ModelType(LotValue, required=True), default=list())
    subcontractingDetails = StringType()
    status = StringType(choices=["draft", "active", "invalid", "deleted"],
                        default="active")
    selfQualified = BooleanType(required=True, choices=[True])
    selfEligible = BooleanType(required=True, choices=[True])
    parameters = ListType(ModelType(Parameter, required=True),
                          default=list(),
                          validators=[validate_parameters_uniq])
    documents = ListType(ConfidentialDocumentModelType(ConfidentialDocument,
                                                       required=True),
                         default=list())

    def serialize(self, role=None):
        if role and self.status in ["invalid", "deleted"]:
            role = self.status
        return super(Bid, self).serialize(role)

    @bids_validation_wrapper
    def validate_value(self, data, value):
        BaseBid._validator_functions["value"](self, data, value)

    @bids_validation_wrapper
    def validate_lotValues(self, data, lotValues):
        BaseBid._validator_functions["lotValues"](self, data, lotValues)

    @bids_validation_wrapper
    def validate_participationUrl(self, data, participationUrl):
        BaseBid._validator_functions["participationUrl"](self, data,
                                                         participationUrl)

    @bids_validation_wrapper
    def validate_parameters(self, data, parameters):
        BaseBid._validator_functions["parameters"](self, data, parameters)
class HourlySchedule(Model):
    hours_in_cycle = IntType(deserialize_from='hoursInCycle')
    start_time = StringType(deserialize_from='startTime')
    duration = StringType()
Example #29
0
class ComplaintPost(Model):
    class Options:
        namespace = "post"
        roles = {
            "create":
            whitelist("title", "description", "documents", "relatedParty",
                      "relatedPost", "recipient"),
            "edit":
            whitelist(),
            "view":
            schematics_default_role,
            "default":
            schematics_default_role,
            "embedded":
            schematics_embedded_role,
        }

    id = MD5Type(required=True, default=lambda: uuid4().hex)

    title = StringType(required=True)
    description = StringType(required=True)
    documents = ListType(ModelType(Document), default=list())
    author = StringType(
        choices=["complaint_owner", "tender_owner", "aboveThresholdReviewers"])
    recipient = StringType(
        required=True,
        choices=["complaint_owner", "tender_owner", "aboveThresholdReviewers"])
    datePublished = IsoDateTimeType(default=get_now)
    relatedPost = StringType()

    reviewer_roles = ["aboveThresholdReviewers"]
    recipient_roles = ["complaint_owner", "tender_owner"]

    def validate_relatedPost(self, data, value):
        parent = data["__parent__"]

        if data["author"] in self.recipient_roles and not value:
            raise ValidationError(BaseType.MESSAGES["required"])

        if value and isinstance(parent, Model):

            # check that another post with "id"
            # that equals "relatedPost" of current post exists
            if value not in [i.id for i in parent.posts]:
                raise ValidationError("relatedPost should be one of posts.")

            # check that another posts with `relatedPost`
            # that equals `relatedPost` of current post does not exist
            if len([i for i in parent.posts if i.relatedPost == value]) > 1:
                raise ValidationError("relatedPost must be unique.")

            related_posts = [i for i in parent.posts if i.id == value]

            # check that there are no multiple related posts,
            # that should never happen coz `id` is unique
            if len(related_posts) > 1:
                raise ValidationError(
                    "relatedPost can't be a link to more than one post.")

            # check that related post have another author
            if len(related_posts
                   ) == 1 and data["author"] == related_posts[0]["author"]:
                raise ValidationError(
                    "relatedPost can't have the same author.")

            # check that related post is not an answer to another post
            if len(related_posts) == 1 and related_posts[0]["relatedPost"]:
                raise ValidationError(
                    "relatedPost can't have relatedPost defined.")

            # check that answer author matches related post recipient
            if data["author"] and data["author"] != related_posts[0][
                    "recipient"]:
                raise ValidationError("relatedPost invalid recipient.")

    def validate_recipient(self, data, value):
        # validate for aboveThresholdReviewers role
        if data["author"] in self.reviewer_roles and value not in self.recipient_roles:
            raise ValidationError("Value must be one of {}.".format(
                self.recipient_roles))

        # validate for complaint_owner and tender_owner roles
        elif data[
                "author"] in self.recipient_roles and value not in self.reviewer_roles:
            raise ValidationError("Value must be one of {}.".format(
                self.reviewer_roles))
Example #30
0
 def test_string_type_doesnt_accept_none(self):
     field = StringType()
     with self.assertRaises(ValidationError):
         field.validate(None)
Example #31
0
class Complaint(BaseComplaint):
    class Options:
        _base_roles = BaseComplaint.Options.roles
        roles = {
            "create":
            _base_roles["create"],  # TODO inherit the rest of the roles
            "draft":
            whitelist("author", "title", "description", "status"),
            "bot":
            whitelist("rejectReason", "status"),
            "cancellation":
            whitelist("cancellationReason", "status"),
            "satisfy":
            whitelist("satisfied", "status"),
            "escalate":
            whitelist("status"),
            "resolve":
            whitelist("status", "tendererAction"),
            "answer":
            whitelist("resolution", "resolutionType", "status",
                      "tendererAction"),
            "action":
            whitelist("tendererAction"),
            "review":
            whitelist("decision", "status", "rejectReason",
                      "rejectReasonDescription", "reviewDate", "reviewPlace"),
            "embedded":
            (blacklist("owner_token", "owner", "transfer_token", "bid_id") +
             schematics_embedded_role),
            "view":
            (blacklist("owner_token", "owner", "transfer_token", "bid_id") +
             schematics_default_role),
        }

    status = StringType(
        choices=[
            "draft",
            "claim",
            "answered",
            "pending",
            "accepted",
            "invalid",
            "resolved",
            "declined",
            "cancelled",
            "satisfied",
            "stopping",
            "stopped",
            "mistaken",
        ],
        default="draft",
    )
    acceptance = BooleanType()
    dateAccepted = IsoDateTimeType()
    rejectReasonDescription = StringType()
    reviewDate = IsoDateTimeType()
    reviewPlace = StringType()
    bid_id = StringType()
    posts = ListType(ModelType(ComplaintPost), default=list())

    def __acl__(self):
        return [
            (Allow, "g:bots", "edit_complaint"),
            (Allow, "g:aboveThresholdReviewers", "edit_complaint"),
            (Allow, "{}_{}".format(self.owner,
                                   self.owner_token), "edit_complaint"),
            (Allow, "{}_{}".format(self.owner, self.owner_token),
             "upload_complaint_documents"),
        ]

    def get_role(self):
        root = self.get_root()
        request = root.request
        data = request.json_body["data"]
        auth_role = request.authenticated_role
        status = data.get("status", self.status)
        if auth_role == "Administrator":
            role = auth_role
        elif auth_role == "complaint_owner" and self.status != "mistaken" and status == "cancelled":
            role = "cancellation"
        elif auth_role == "complaint_owner" and self.status in [
                "pending", "accepted"
        ] and status == "stopping":
            role = "cancellation"
        elif auth_role == "complaint_owner" and self.status == "draft":
            role = "draft"
        elif auth_role == "complaint_owner" and self.status == "claim":
            role = "escalate"
        elif auth_role == "bots" and self.status == "draft":
            role = "bot"
        elif auth_role == "tender_owner" and self.status == "claim":
            role = "answer"
        elif auth_role == "tender_owner" and self.status in [
                "pending", "accepted"
        ]:
            role = "action"
        elif auth_role == "tender_owner" and self.status == "satisfied":
            role = "resolve"
        elif auth_role == "complaint_owner" and self.status == "answered":
            role = "satisfy"
        elif auth_role == "aboveThresholdReviewers" and self.status in [
                "pending", "accepted", "stopping"
        ]:
            role = "review"
        else:
            role = "invalid"
        return role

    def validate_cancellationReason(self, data, cancellationReason):
        if not cancellationReason and data.get("status") in [
                "cancelled", "stopping"
        ]:
            raise ValidationError(u"This field is required.")

    def validate_rejectReason(self, data, rejectReason):
        tender_date = get_first_revision_date(get_tender(data["__parent__"]),
                                              default=get_now())
        if tender_date < RELEASE_2020_04_19:
            return
        if not rejectReason and data.get("status") in [
                "invalid", "stopped"
        ] and data.get("type") == "complaint":
            raise ValidationError(u"This field is required.")

    def validate_reviewDate(self, data, reviewDate):
        tender_date = get_first_revision_date(get_tender(data["__parent__"]),
                                              default=get_now())
        if tender_date < RELEASE_2020_04_19:
            return
        if not reviewDate and data.get("status") == "accepted":
            raise ValidationError(u"This field is required.")

    def validate_reviewPlace(self, data, reviewPlace):
        tender_date = get_first_revision_date(get_tender(data["__parent__"]),
                                              default=get_now())
        if tender_date < RELEASE_2020_04_19:
            return
        if not reviewPlace and data.get("status") == "accepted":
            raise ValidationError(u"This field is required.")
Example #32
0
def test_string_min_length_doesnt_accept_empty_string():
    field = StringType(min_length=1)
    with pytest.raises(ValidationError):
        field.validate('')
Example #33
0
class CancellationComplaint(Complaint):
    class Options:
        _base_roles = Complaint.Options.roles
        namespace = "Complaint"
        roles = {
            "create": whitelist("author", "title", "description",
                                "relatedLot"),
            "draft": _base_roles["draft"],
            "bot": _base_roles["bot"],
            "cancellation": _base_roles["cancellation"],
            "satisfy": _base_roles["satisfy"],
            "resolve": _base_roles["resolve"],
            "action": _base_roles["action"],
            # "pending": whitelist("decision", "status", "rejectReason", "rejectReasonDescription"),
            "review": _base_roles["review"],
            "embedded": _base_roles["embedded"],
            "view": _base_roles["view"],
        }

    def get_role(self):
        root = self.get_root()
        request = root.request
        data = request.json_body["data"]
        auth_role = request.authenticated_role
        status = data.get("status", self.status)

        if auth_role == "Administrator":
            role = auth_role
        elif auth_role == "complaint_owner" and self.status != "mistaken" and status == "cancelled":
            role = "cancellation"
        elif auth_role == "complaint_owner" and self.status in [
                "pending", "accepted"
        ] and status == "stopping":
            role = "cancellation"
        elif auth_role == "complaint_owner" and self.status == "draft":
            role = "draft"
        elif auth_role == "bots" and self.status == "draft":
            role = "bot"
        elif auth_role == "tender_owner" and self.status == "pending":
            role = "action"
        elif auth_role == "tender_owner" and self.status == "satisfied":
            role = "resolve"
        elif auth_role == "aboveThresholdReviewers" and self.status in [
                "pending", "accepted", "stopping"
        ]:
            role = "review"
        else:
            role = "invalid"
        return role

    def __acl__(self):
        return [
            (Allow, "g:bots", "edit_complaint"),
            (Allow, "g:aboveThresholdReviewers", "edit_complaint"),
            (Allow, "{}_{}".format(self.owner,
                                   self.owner_token), "edit_complaint"),
            (Allow, "{}_{}".format(self.owner, self.owner_token),
             "upload_complaint_documents"),
        ]

    status = StringType(
        choices=[
            "draft",
            "pending",
            "accepted",
            "invalid",
            "resolved",
            "declined",
            "satisfied",
            "stopped",
            "mistaken",
        ],
        default="draft",
    )
    type = StringType(
        choices=["claim", "complaint"],
        default="complaint",
    )
Example #34
0
 def test_string_type_required(self):
     field = StringType(required=True)
     with self.assertRaises(ValidationError):
         field.validate(None)
Example #35
0
class Tender(BaseTender):
    """
    Data regarding tender process - publicly inviting
    prospective contractors to submit bids for evaluation and selecting a winner or winners.
    """
    class Options:
        namespace = "Tender"
        _parent_roles = BaseTender.Options.roles

        _edit_role = _parent_roles["edit"]
        _above_fields = whitelist("complaintPeriod")
        _tendering_role = _parent_roles["active.tendering"] + _above_fields
        _view_role = _parent_roles["view"] + _above_fields
        _all_forbidden = whitelist()
        roles = {
            "create": _parent_roles["create"],
            "edit_draft": _parent_roles["edit_draft"],
            "edit": _edit_role,
            "edit_active.tendering": _edit_role,
            "edit_active.auction": _all_forbidden,
            "edit_active.qualification": _all_forbidden,
            "edit_active.awarded": _all_forbidden,
            "edit_complete": _all_forbidden,
            "edit_unsuccessful": _all_forbidden,
            "edit_cancelled": _all_forbidden,
            "draft": _tendering_role,
            "active.tendering": _tendering_role,
            "active.auction": _tendering_role,
            "view": _view_role,
            "active.qualification": _view_role,
            "active.awarded": _view_role,
            "complete": _view_role,
            "unsuccessful": _view_role,
            "cancelled": _view_role,
            "chronograph": _parent_roles["chronograph"],
            "chronograph_view": _parent_roles["chronograph_view"],
            "Administrator": _parent_roles["Administrator"],
            "default": _parent_roles["default"],
            "plain": _parent_roles["plain"],
            "listing": _parent_roles["listing"],
            "auction_view": _parent_roles["auction_view"],
            "auction_post": _parent_roles["auction_post"],
            "auction_patch": _parent_roles["auction_patch"],
            "contracting": _parent_roles["contracting"],
        }

    __name__ = ""

    enquiryPeriod = ModelType(EnquiryPeriod, required=False)
    tenderPeriod = ModelType(PeriodStartEndRequired, required=True)
    auctionPeriod = ModelType(TenderAuctionPeriod, default={})
    bids = SifterListType(
        ModelType(Bid, required=True),
        default=list(),
        filter_by="status",
        filter_in_values=["invalid", "deleted"]
    )  # A list of all the companies who entered submissions for the tender.
    awards = ListType(ModelType(Award, required=True), default=list())
    contracts = ListType(ModelType(Contract, required=True), default=list())
    complaints = ListType(ComplaintModelType(Complaint, required=True),
                          default=list())
    procurementMethodType = StringType(default="aboveThresholdUA")
    lots = ListType(ModelType(Lot, required=True),
                    default=list(),
                    validators=[validate_lots_uniq])
    status = StringType(
        choices=[
            "draft",
            "active.tendering",
            "active.auction",
            "active.qualification",
            "active.awarded",
            "complete",
            "cancelled",
            "unsuccessful",
        ],
        default="active.tendering",
    )
    items = ListType(
        ModelType(Item, required=True),
        required=True,
        min_size=1,
        validators=[
            validate_cpv_group, validate_items_uniq, validate_classification_id
        ],
    )  # The goods and services to be purchased, broken into line items wherever possible. Items should not be duplicated, but a quantity of 2 specified instead.
    cancellations = ListType(ModelType(Cancellation, required=True),
                             default=list())

    create_accreditations = (ACCR_3, ACCR_5)
    central_accreditations = (ACCR_5, )
    edit_accreditations = (ACCR_4, )

    procuring_entity_kinds = [
        "authority", "central", "defense", "general", "social", "special"
    ]

    block_tender_complaint_status = [
        "claim", "pending", "accepted", "satisfied", "stopping"
    ]
    block_complaint_status = ["pending", "accepted", "satisfied", "stopping"]

    def __acl__(self):
        acl = [(Allow, "{}_{}".format(i.owner,
                                      i.owner_token), "create_award_complaint")
               for i in self.bids if i.status == "active"]
        acl.extend([
            (Allow, "{}_{}".format(self.owner,
                                   self.owner_token), "edit_complaint"),
            (Allow, "{}_{}".format(self.owner,
                                   self.owner_token), "edit_contract"),
            (Allow, "{}_{}".format(self.owner, self.owner_token),
             "upload_contract_documents"),
        ])

        self._acl_cancellation_complaint(acl)
        return acl

    def validate_enquiryPeriod(self, data, period):
        # for deactivate validation to enquiryPeriod from parent tender
        return

    def validate_tenderPeriod(self, data, period):
        # data['_rev'] is None when tender was created just now
        if not data["_rev"] and calculate_tender_business_date(
                get_now(), -timedelta(minutes=10)) >= period.startDate:
            raise ValidationError(
                u"tenderPeriod.startDate should be in greater than current date"
            )
        if period and calculate_tender_business_date(
                period.startDate, TENDER_PERIOD, data) > period.endDate:
            raise ValidationError(
                u"tenderPeriod should be greater than 15 days")

    @serializable(serialized_name="enquiryPeriod",
                  type=ModelType(EnquiryPeriod))
    def tender_enquiryPeriod(self):
        endDate = calculate_tender_business_date(self.tenderPeriod.endDate,
                                                 -ENQUIRY_PERIOD_TIME, self)
        clarificationsUntil = calculate_clarifications_business_date(
            endDate, ENQUIRY_STAND_STILL_TIME, self, True)
        return EnquiryPeriod(
            dict(
                startDate=self.tenderPeriod.startDate,
                endDate=endDate,
                invalidationDate=self.enquiryPeriod
                and self.enquiryPeriod.invalidationDate,
                clarificationsUntil=clarificationsUntil,
            ))

    @serializable(type=ModelType(Period))
    def complaintPeriod(self):
        endDate = calculate_complaint_business_date(self.tenderPeriod.endDate,
                                                    -COMPLAINT_SUBMIT_TIME,
                                                    self)
        return Period(
            dict(startDate=self.tenderPeriod.startDate, endDate=endDate))

    @serializable
    def numberOfBids(self):
        """A property that is serialized by schematics exports."""
        return len([bid for bid in self.bids if bid.status == "active"])

    @serializable(serialize_when_none=False)
    def next_check(self):
        now = get_now()
        checks = []
        if (self.status == "active.tendering" and self.tenderPeriod.endDate
                and not has_unanswered_complaints(self)
                and not has_unanswered_questions(self)):
            checks.append(self.tenderPeriod.endDate.astimezone(TZ))
        elif (not self.lots and self.status == "active.auction"
              and self.auctionPeriod and self.auctionPeriod.startDate
              and not self.auctionPeriod.endDate):
            if now < self.auctionPeriod.startDate:
                checks.append(self.auctionPeriod.startDate.astimezone(TZ))
            elif now < calc_auction_end_time(
                    self.numberOfBids,
                    self.auctionPeriod.startDate).astimezone(TZ):
                checks.append(
                    calc_auction_end_time(
                        self.numberOfBids,
                        self.auctionPeriod.startDate).astimezone(TZ))
        elif self.lots and self.status == "active.auction":
            for lot in self.lots:
                if (lot.status != "active" or not lot.auctionPeriod
                        or not lot.auctionPeriod.startDate
                        or lot.auctionPeriod.endDate):
                    continue
                if now < lot.auctionPeriod.startDate:
                    checks.append(lot.auctionPeriod.startDate.astimezone(TZ))
                elif now < calc_auction_end_time(
                        lot.numberOfBids,
                        lot.auctionPeriod.startDate).astimezone(TZ):
                    checks.append(
                        calc_auction_end_time(
                            lot.numberOfBids,
                            lot.auctionPeriod.startDate).astimezone(TZ))
        elif (not self.lots and self.status == "active.awarded" and not any(
            [i.status in self.block_complaint_status for i in self.complaints])
              and not any([
                  i.status in self.block_complaint_status for a in self.awards
                  for i in a.complaints
              ])):
            standStillEnds = [
                a.complaintPeriod.endDate.astimezone(TZ) for a in self.awards
                if a.complaintPeriod and a.complaintPeriod.endDate
            ]
            last_award_status = self.awards[-1].status if self.awards else ""
            if standStillEnds and last_award_status == "unsuccessful":
                checks.append(max(standStillEnds))
        elif (self.lots
              and self.status in ["active.qualification", "active.awarded"]
              and not any([
                  i.status in self.block_complaint_status
                  and i.relatedLot is None for i in self.complaints
              ])):
            for lot in self.lots:
                if lot["status"] != "active":
                    continue
                lot_awards = [i for i in self.awards if i.lotID == lot.id]
                pending_complaints = any([
                    i["status"] in self.block_complaint_status
                    and i.relatedLot == lot.id for i in self.complaints
                ])
                pending_awards_complaints = any([
                    i.status in self.block_complaint_status for a in lot_awards
                    for i in a.complaints
                ])
                standStillEnds = [
                    a.complaintPeriod.endDate.astimezone(TZ)
                    for a in lot_awards
                    if a.complaintPeriod and a.complaintPeriod.endDate
                ]
                last_award_status = lot_awards[-1].status if lot_awards else ""
                if (not pending_complaints and not pending_awards_complaints
                        and standStillEnds
                        and last_award_status == "unsuccessful"):
                    checks.append(max(standStillEnds))
        if self.status.startswith("active"):
            for award in self.awards:
                if award.status == "active" and not any(
                    [i.awardID == award.id for i in self.contracts]):
                    checks.append(award.date)

        extend_next_check_by_complaint_period_ends(self, checks)

        return min(checks).isoformat() if checks else None

    def invalidate_bids_data(self):
        if (self.auctionPeriod and self.auctionPeriod.startDate
                and self.auctionPeriod.shouldStartAfter and
                self.auctionPeriod.startDate > calculate_tender_business_date(
                    parse_date(self.auctionPeriod.shouldStartAfter),
                    AUCTION_PERIOD_TIME, self, True)):
            self.auctionPeriod.startDate = None
        for lot in self.lots:
            if (lot.auctionPeriod and lot.auctionPeriod.startDate
                    and lot.auctionPeriod.shouldStartAfter
                    and lot.auctionPeriod.startDate >
                    calculate_tender_business_date(
                        parse_date(lot.auctionPeriod.shouldStartAfter),
                        AUCTION_PERIOD_TIME, self, True)):
                lot.auctionPeriod.startDate = None
        self.enquiryPeriod.invalidationDate = get_now()
        for bid in self.bids:
            if bid.status not in ["deleted", "draft"]:
                bid.status = "invalid"
Example #36
0
 def test_string_required_accepts_empty_string(self):
     field = StringType(required=True)
     field.validate('')
Example #37
0
class VNet(Model):
    vnet_id = StringType()
    vnet_name = StringType()
    cidr = StringType()
Example #38
0
def validate_string():
    st = StringType(max_length=10)
    print(st.to_native('this is longer than 10'))
    st.validate('this is longer than 10')
class VirtualMachineAgentInstanceView(Model):
    statuses = ListType(ModelType(InstanceViewStatus), serialize_when_none=False)
    vm_agent_version = StringType(serialize_when_none=False)
    display_status = StringType(serialize_when_none=False)  # #