Ejemplo n.º 1
0
class Organization(BaseOrganization):
    identifier = ModelType(Identifier, required=True)
    additionalIdentifiers = ListType(ModelType(Identifier))
Ejemplo n.º 2
0
class PluginInitResponse(Model):
    _metadata = ModelType(PluginMetadata,
                          default=PluginMetadata,
                          serialized_name='metadata')
Ejemplo n.º 3
0
 class Course(Model):
     id = StringType(required=True, validators=[])
     attending = ListType(ModelType(Person))
Ejemplo n.º 4
0
 class Question(Model):
     id = StringType()
     resources = ModelType(QuestionResources)
Ejemplo n.º 5
0
class CFASelectionUATender(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
        _not_implemented = whitelist("mainProcurementCategory", "milestones")
        _base_edit = (_core_roles["edit"] - _not_implemented + whitelist(
            "procuringEntity",
            "numberOfBidders",
            "guarantee",
            "items",
            "next_check",
            "tender_guarantee",
            "numberOfBids",
            "agreements",
            "hasEnquiries",
        ))
        _edit_role = _base_edit + whitelist(
            "enquiryPeriod", "tender_minimalStep", "contracts", "tenderPeriod",
            "features", "minimalStep")
        _draft_view_role = (_core_roles["view"] - _not_implemented + whitelist(
            "tender_guarantee",
            "awardPeriod",
            "auctionUrl",
            "auctionPeriod",
            "next_check",
            "procuringEntity",
            "questions",
            "complaints",
            "lots",
            "items",
            "cancellations",
            "contracts",
            "agreements",
            "numberOfBidders",
            "awards",
            "guarantee",
            "hasEnquiries",
        ))
        _view_tendering_role = _draft_view_role + whitelist(
            "tender_value",
            "tenderPeriod",
            "features",
            "enquiryPeriod",
            "tender_minimalStep",
            "value",
            "minimalStep",
        )
        _view_role = _view_tendering_role + whitelist("bids", "numberOfBids")
        _procurement_method_details = whitelist("procurementMethodDetails")
        roles = {
            "create":
            _base_edit + whitelist("lots", "procurementMethodType", "mode"),
            "edit_draft":
            _core_roles["edit_draft"] + _procurement_method_details,
            "edit_draft.pending":
            whitelist("agreements", "unsuccessfulReason") +
            _procurement_method_details,
            "edit_cancelled":
            _procurement_method_details,
            "edit_complete":
            _procurement_method_details,
            "edit_unsuccessful":
            _procurement_method_details,
            "edit_active.awarded":
            _procurement_method_details,
            "edit_active.auction":
            _procurement_method_details,
            "edit_active.tendering":
            _procurement_method_details,
            "edit_active.qualification":
            _procurement_method_details,
            "edit_active.enquiries":
            whitelist(
                "description",
                "description_en",
                "description_ru",
                "documents",
                "items",
                "lots",
                "procurementMethodDetails",
                "guarantee",
                "tenderPeriod",
                "tender_guarantee",
                "title",
                "title_en",
                "title_ru",
            ),
            "edit":
            _edit_role,
            "edit_agreement_selection":
            whitelist("agreements", "procurementMethodDetails", "status"),
            "active.tendering":
            _view_tendering_role,
            "active.enquiries":
            _view_tendering_role,
            "active.auction":
            _view_tendering_role,
            "draft":
            _draft_view_role,
            "draft.pending":
            _draft_view_role + whitelist("features"),
            "draft.unsuccessful":
            _draft_view_role + whitelist("features", "unsuccessfulReason"),
            "active.awarded":
            _view_role,
            "unsuccessful":
            _view_role,
            "cancelled":
            _view_role,
            "view":
            _view_role,
            "active.qualification":
            _view_role,
            "complete":
            _view_role,
            "chronograph":
            _core_roles["chronograph"] + _procurement_method_details,
            "chronograph_view":
            _core_roles["chronograph_view"] + whitelist("agreements") +
            _procurement_method_details,
            "Administrator":
            _core_roles["Administrator"] + _procurement_method_details,
            "contracting":
            _core_roles["contracting"] + _procurement_method_details,
            "auction_post":
            _core_roles["auction_post"] + _procurement_method_details,
            "auction_patch":
            _core_roles["auction_patch"] + _procurement_method_details,
            "auction_view":
            _core_roles["auction_view"] + whitelist("minimalStep") +
            whitelist("tender_minimalStep") + _procurement_method_details,
            "listing":
            _core_roles["listing"] + _procurement_method_details,
            "embedded":
            _core_roles["embedded"],
            "plain":
            _core_roles["plain"],
            "default":
            _core_roles["default"],
        }

    items = ListType(
        ModelType(Item, required=True),
        min_size=1,
        validators=[validate_items_uniq]
    )  # 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)  # The total estimated value of the procurement.
    enquiryPeriod = ModelType(
        PeriodEndRequired, required=False
    )  # The period during which enquiries may be made and will be answered.
    tenderPeriod = ModelType(
        PeriodEndRequired, required=False
    )  # 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=False)
    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],
                    min_size=1,
                    max_size=1)
    guarantee = ModelType(Guarantee)
    status = StringType(
        choices=[
            "draft",
            "draft.pending",
            "draft.unsuccessful",
            "active.enquiries",
            "active.tendering",
            "active.auction",
            "active.qualification",
            "active.awarded",
            "complete",
            "cancelled",
            "unsuccessful",
        ],
        default="draft",
    )  # TODO Refactoring status
    agreements = ListType(ModelType(Agreement, required=True),
                          default=list(),
                          min_size=1,
                          max_size=1)

    procurementMethod = StringType(choices=["open", "selective", "limited"],
                                   default="selective")
    procurementMethodType = StringType(
        default="closeFrameworkAgreementSelectionUA")
    unsuccessfulReason = ListType(StringType, serialize_when_none=False)
    procuring_entity_kinds = [
        "authority", "central", "defense", "general", "other", "social",
        "special"
    ]

    def get_role(self):
        root = self.__parent__
        request = root.request
        if request.authenticated_role == "Administrator":
            role = "Administrator"
        elif request.authenticated_role == "chronograph":
            role = "chronograph"
        elif request.authenticated_role == "auction":
            role = "auction_{}".format(request.method.lower())
        elif request.authenticated_role == "contracting":
            role = "contracting"
        elif request.authenticated_role == "agreement_selection":
            role = "edit_{}".format(request.authenticated_role)
        else:
            role = "edit_{}".format(request.context.status)
        return role

    def __acl__(self):
        acl = [(Allow, "{}_{}".format(i.owner,
                                      i.owner_token), "create_award_complaint")
               for i in self.bids]
        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"),
            (Allow, "g:agreement_selection", "edit_agreement_selection"),
            (Allow, "g:agreement_selection", "edit_tender"),
            (Allow, "g:brokers", "create_cancellation_complaint")
        ])
        self._acl_cancellation(acl)
        return acl

    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

    # Non-required mainProcurementCategory
    def validate_mainProcurementCategory(self, data, value):
        pass

    # Not required milestones
    def validate_milestones(self, data, value):
        pass

    @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
            guarantee_class = self._fields["guarantee"]
            return guarantee_class(guarantee)
        else:
            return self.guarantee

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

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

    @serializable(serialize_when_none=False)
    def next_check(self):
        now = get_now()
        checks = []
        if self.status == "active.enquiries" and self.enquiryPeriod and self.enquiryPeriod.endDate:
            checks.append(self.enquiryPeriod.endDate.astimezone(TZ))
        elif self.status == "active.tendering" and self.tenderPeriod 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))
            else:
                auction_end_time = calc_auction_end_time(
                    self.numberOfBids,
                    self.auctionPeriod.startDate).astimezone(TZ)
                if now < auction_end_time:
                    checks.append(auction_end_time)
        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))
                else:
                    auction_end_time = calc_auction_end_time(
                        lot.numberOfBids,
                        lot.auctionPeriod.startDate).astimezone(TZ)
                    if now < auction_end_time:
                        checks.append(auction_end_time)
        elif self.lots and self.status in [
                "active.qualification", "active.awarded"
        ]:
            for lot in self.lots:
                if lot["status"] != "active":
                    continue
        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)
        return min(checks).isoformat() if checks else None

    @serializable
    def numberOfBids(self):
        return len(self.bids)

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

    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("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("period should begin after tenderPeriod")

    def validate_features(self, data, features):
        validate_features_custom_weight(data, features, Decimal("0.3"))

    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 items and len(
                set([i.classification.id[:4] for i in items])) != 1:
            raise ValidationError("CPV class of items should be identical")
        else:
            validate_cpv_group(items)

    def validate_lots(self, data, lots):
        if len(set([lot.guarantee.currency
                    for lot in lots if lot.guarantee])) > 1:
            raise ValidationError(
                "lot guarantee currency should be identical to tender guarantee currency"
            )

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

    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("period should begin after enquiryPeriod")
        if (period and period.startDate and period.endDate):
            _validate_tender_period_duration(data, period, TENDERING_DURATION)
Ejemplo n.º 6
0
 class Card(Model):
     id = IntType(default=1)
     users = ListType(ModelType(User), min_size=1, required=True)
Ejemplo n.º 7
0
 class PlayerInfo(Model):
     categories = ListType(ModelType(CategoryStatsInfo),
                           default=lambda: [],
                           serialize_when_none=True)
Ejemplo n.º 8
0
class Award(BaseEUAward):
    """ESCO EU award model"""

    value = ModelType(ESCOValue)
Ejemplo n.º 9
0
class Tender(BaseTender):
    """ ESCO EU Tender model """
    class Options:
        roles = {
            'plain': plain_role,
            'create': create_role_eu + blacklist('minValue', 'tender_minValue'),
            'edit': edit_role_eu + blacklist('minValue', 'tender_minValue'),
            'edit_draft': edit_role_eu + blacklist('minValue', 'tender_minValue'),
            'edit_active.tendering': edit_role_eu + blacklist('minValue', 'tender_minValue'),
            'edit_active.pre-qualification': whitelist('status'),
            'edit_active.pre-qualification.stand-still': whitelist(),
            'edit_active.auction': whitelist(),
            'edit_active.qualification': whitelist(),
            'edit_active.awarded': whitelist(),
            'edit_complete': whitelist(),
            'edit_unsuccessful': whitelist(),
            'edit_cancelled': whitelist(),
            'view': view_role,
            'listing': listing_role,
            'auction_view': auction_view_role + whitelist('NBUdiscountRate'),
            'auction_post': auction_post_role,
            'auction_patch': auction_patch_role,
            'draft': enquiries_role,
            'active.tendering': enquiries_role,
            'active.pre-qualification': pre_qualifications_role,
            'active.pre-qualification.stand-still': pre_qualifications_role,
            'active.auction': pre_qualifications_role,
            'active.qualification': view_role,
            'active.awarded': view_role,
            'complete': view_role,
            'unsuccessful': view_role,
            'cancelled': view_role,
            'chronograph': chronograph_role,
            'chronograph_view': chronograph_view_role,
            'Administrator': Administrator_role,
            'default': schematics_default_role,
            'contracting': whitelist('doc_id', 'owner'),
        }

    procurementMethodType = StringType(default="esco.EU")
    title_en = StringType(required=True, min_length=1)

    items = ListType(ModelType(Item), required=True, min_size=1, validators=[validate_cpv_group, validate_items_uniq])  # 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.
    minValue = ModelType(Value, required=False, default={'amount': 0, 'currency': 'UAH', 'valueAddedTaxIncluded': True})  # The total estimated value of the procurement.

    enquiryPeriod = ModelType(EnquiryPeriod, required=False)
    tenderPeriod = ModelType(PeriodStartEndRequired, required=True)
    auctionPeriod = ModelType(TenderAuctionPeriod, default={})
    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 = SifterListType(BidModelType(Bid), default=list(), filter_by='status', filter_in_values=['invalid', 'invalid.pre-qualification', 'deleted'])  # 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), default=list())
    contracts = ListType(ModelType(Contract), default=list())
    minimalStep = ModelType(Value, required=True)
    questions = ListType(ModelType(Question), default=list())
    complaints = ListType(ComplaintModelType(Complaint), default=list())
    auctionUrl = URLType()
    cancellations = ListType(ModelType(Cancellation), default=list())
    features = ListType(ModelType(Feature), validators=[validate_features_uniq])
    lots = ListType(ModelType(Lot), default=list(), validators=[validate_lots_uniq])
    guarantee = ModelType(Guarantee)
    documents = ListType(ModelType(Document), default=list())  # All documents and attachments related to the tender.
    qualifications = ListType(ModelType(Qualification), default=list())
    qualificationPeriod = ModelType(Period)
    status = StringType(choices=['draft', 'active.tendering', 'active.pre-qualification', 'active.pre-qualification.stand-still', 'active.auction',
                                 'active.qualification', 'active.awarded', 'complete', 'cancelled', 'unsuccessful'], default='active.tendering')
    NBUdiscountRate = FloatType(required=True, min_value=0, max_value=0.99)
    submissionMethodDetails = StringType(default="quick(mode:no-auction)")  # TODO: temporary decision, while esco auction is not ready. Remove after adding auction. Remove function "check_submission_method_details" in openprocurement.tender.esco.subscribers

    create_accreditation = 3
    edit_accreditation = 4
    procuring_entity_kinds = ['general', 'special', 'defense']
    block_tender_complaint_status = OpenUATender.block_tender_complaint_status
    block_complaint_status = OpenUATender.block_complaint_status

    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 = [
            (Allow, '{}_{}'.format(i.owner, i.owner_token), 'create_qualification_complaint')
            for i in self.bids
            if i.status in ['active', 'unsuccessful']
        ]
        acl.extend([
            (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_tender'),
            (Allow, '{}_{}'.format(self.owner, self.owner_token), 'upload_tender_documents'),
            (Allow, '{}_{}'.format(self.owner, self.owner_token), 'edit_complaint'),
        ])
        return acl

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

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

    @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 self.status == 'active.pre-qualification.stand-still' and self.qualificationPeriod and self.qualificationPeriod.endDate:
            active_lots = [lot.id for lot in self.lots if lot.status == 'active'] if self.lots else [None]
            if not any([
                i.status in self.block_complaint_status
                for q in self.qualifications
                for i in q.complaints
                if q.lotID in active_lots
            ]):
                checks.append(self.qualificationPeriod.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'):
            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)
        return min(checks).isoformat() if checks else None

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

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

    @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):
        if value and value.amount and data.get('minValue'):
            if data.get('minValue').currency != value.currency:
                raise ValidationError(u"currency should be identical to currency of minValue of tender")
            if data.get('minValue').valueAddedTaxIncluded != value.valueAddedTaxIncluded:
                raise ValidationError(u"valueAddedTaxIncluded should be identical to valueAddedTaxIncluded of minValue of tender")

    def validate_tenderPeriod(self, data, period):
        # if data['_rev'] is None when tender was created just now
        if not data['_rev'] and calculate_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_business_date(period.startDate, TENDERING_DURATION, data) > period.endDate:
            raise ValidationError(u"tenderPeriod should be greater than {} days".format(TENDERING_DAYS))

    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")


    def check_auction_time(self):
        if self.auctionPeriod and self.auctionPeriod.startDate and self.auctionPeriod.shouldStartAfter \
                and self.auctionPeriod.startDate > calculate_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_business_date(parse_date(lot.auctionPeriod.shouldStartAfter), AUCTION_PERIOD_TIME, self, True):
                lot.auctionPeriod.startDate = None

    def invalidate_bids_data(self):
        self.check_auction_time()
        self.enquiryPeriod.invalidationDate = get_now()
        for bid in self.bids:
            if bid.status not in ["deleted", "draft"]:
                bid.status = "invalid"
class Lot(BaseLot):
    class Options:
        roles = lot_roles

    title = StringType()
    status = StringType(choices=LOT_STATUSES, default='draft')
    description = StringType()
    lotType = StringType(default="loki")
    rectificationPeriod = ModelType(Period)
    lotCustodian = ModelType(AssetCustodian, serialize_when_none=False)
    lotHolder = ModelType(AssetHolder, serialize_when_none=False)
    officialRegistrationID = StringType(serialize_when_none=False)
    items = ListType(ModelType(Item), default=list())
    documents = ListType(ModelType(Document), default=list())
    decisions = ListType(ModelType(Decision),
                         default=list(),
                         min_size=1,
                         max_size=2,
                         required=True)
    assets = ListType(MD5Type(), required=True, min_size=1, max_size=1)
    auctions = ListType(ModelType(Auction), default=list(), max_size=3)
    _internal_type = 'loki'

    def get_role(self):
        root = self.__parent__
        request = root.request
        if request.authenticated_role == 'Administrator':
            role = 'Administrator'
        elif request.authenticated_role == 'concierge':
            role = 'concierge'
        elif request.authenticated_role == 'convoy':
            role = 'convoy'
        elif request.authenticated_role == 'chronograph':
            role = 'chronograph'
        else:
            after_rectificationPeriod = bool(
                request.context.rectificationPeriod
                and request.context.rectificationPeriod.endDate < get_now())
            if request.context.status == 'pending' and after_rectificationPeriod:
                return 'edit_pendingAfterRectificationPeriod'
            role = 'edit_{}'.format(request.context.status)
        return role

    @serializable(serialize_when_none=False, type=IsoDateTimeType())
    def next_check(self):
        checks = []
        if self.rectificationPeriod and self.status == 'pending':
            checks.append(self.rectificationPeriod.endDate)
        return min(checks) if checks else None

    def __acl__(self):
        acl = [
            (Allow, '{}_{}'.format(self.owner, self.owner_token), 'edit_lot'),
            (Allow, '{}_{}'.format(self.owner,
                                   self.owner_token), 'upload_lot_documents'),
            (Allow, '{}_{}'.format(self.owner,
                                   self.owner_token), 'upload_lot_items'),
            (Allow, '{}_{}'.format(self.owner,
                                   self.owner_token), 'upload_lot_auctions'),
            (Allow, '{}_{}'.format(self.owner, self.owner_token),
             'upload_lot_auction_documents'),
        ]
        return acl
Ejemplo n.º 11
0
class Contract(BaseEUContract):
    """ESCO EU contract model"""

    value = ModelType(ESCOValue)
Ejemplo n.º 12
0
class AllocateNssi(Model):
    attributeListIn = ModelType(SliceProfile)
Ejemplo n.º 13
0
class PerfReq(Model):
    perfReqEmbb = ModelType(PerfReqEmbb)
    # perfReqUrllc = ModelType(PerfReqUrllc)
    perfReqUrllc = DictType(BaseType)
Ejemplo n.º 14
0
class ProcuringEntity(BaseProcuringEntity):
    identifier = ModelType(Identifier, required=True)
    additionalIdentifiers = ListType(ModelType(Identifier))
Ejemplo n.º 15
0
 class Card(Model):
     users = ListType(ModelType(User), min_size=1, required=True)
class UnitPrice(Model):
    relatedItem = StringType()
    value = ModelType(Value)

    def validate_relatedItem(self, data, relatedItem):
        pass
Ejemplo n.º 17
0
 class Group(Model):
     users = ListType(ModelType(User))
Ejemplo n.º 18
0
        class QuestionPack(Model):

            question = ModelType(Question)
Ejemplo n.º 19
0
 class PlayerInfo(Model):
     categories = ListType(ModelType(CategoryStatsInfo))
Ejemplo n.º 20
0
 class Card(Model):
     user = ModelType(User)
Ejemplo n.º 21
0
 class QuestionResources(Model):
     pictures = ListType(ModelType(QuestionResource))
Ejemplo n.º 22
0
 class Player(Model):
     id = IntType()
     location = ModelType(Location)
Ejemplo n.º 23
0
 class QuestionPack(Model):
     id = StringType()
     questions = ListType(ModelType(Question))
Ejemplo n.º 24
0
class PlacementSolution(OSDFModel):
    serviceResourceId = StringType(required=True)
    resourceModuleName = StringType(required=True)
    solution = ModelType(Candidates, required=True)
    assignmentInfo = ListType(ModelType(AssignmentInfo))
Ejemplo n.º 25
0
class PluginMetadata(Model):
    supported_resource_type = ListType(StringType,
                                       default=_SUPPORTED_RESOURCE_TYPE)
    reference_keys = ListType(ModelType(ReferenceKeyModel), default=[])
Ejemplo n.º 26
0
class Solution(OSDFModel):
    placementSolutions = ListType(
        ListType(ModelType(PlacementSolution), min_size=1))
    licenseSolutions = ListType(ModelType(LicenseSolution), min_size=1)
Ejemplo n.º 27
0
 class School(Model):
     name = StringType(required=True)
     headmaster = ModelType(Person, required=True)
Ejemplo n.º 28
0
class PlacementResponse(OSDFModel):
    transactionId = StringType(required=True)
    requestId = StringType(required=True)
    requestStatus = StringType(required=True)
    statusMessage = StringType()
    solutions = ModelType(Solution, required=True)
Ejemplo n.º 29
0
 class School(Model):
     courses = ListType(ModelType(Course))
Ejemplo n.º 30
0
class FinantialOrganization(BaseOrganization):
    identifier = ModelType(Identifier, required=True)
    additionalIdentifiers = ListType(ModelType(Identifier),
                                     required=True,
                                     validators=[validate_ua_fin])