class Organization(BaseOrganization): identifier = ModelType(Identifier, required=True) additionalIdentifiers = ListType(ModelType(Identifier))
class PluginInitResponse(Model): _metadata = ModelType(PluginMetadata, default=PluginMetadata, serialized_name='metadata')
class Course(Model): id = StringType(required=True, validators=[]) attending = ListType(ModelType(Person))
class Question(Model): id = StringType() resources = ModelType(QuestionResources)
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)
class Card(Model): id = IntType(default=1) users = ListType(ModelType(User), min_size=1, required=True)
class PlayerInfo(Model): categories = ListType(ModelType(CategoryStatsInfo), default=lambda: [], serialize_when_none=True)
class Award(BaseEUAward): """ESCO EU award model""" value = ModelType(ESCOValue)
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
class Contract(BaseEUContract): """ESCO EU contract model""" value = ModelType(ESCOValue)
class AllocateNssi(Model): attributeListIn = ModelType(SliceProfile)
class PerfReq(Model): perfReqEmbb = ModelType(PerfReqEmbb) # perfReqUrllc = ModelType(PerfReqUrllc) perfReqUrllc = DictType(BaseType)
class ProcuringEntity(BaseProcuringEntity): identifier = ModelType(Identifier, required=True) additionalIdentifiers = ListType(ModelType(Identifier))
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
class Group(Model): users = ListType(ModelType(User))
class QuestionPack(Model): question = ModelType(Question)
class PlayerInfo(Model): categories = ListType(ModelType(CategoryStatsInfo))
class Card(Model): user = ModelType(User)
class QuestionResources(Model): pictures = ListType(ModelType(QuestionResource))
class Player(Model): id = IntType() location = ModelType(Location)
class QuestionPack(Model): id = StringType() questions = ListType(ModelType(Question))
class PlacementSolution(OSDFModel): serviceResourceId = StringType(required=True) resourceModuleName = StringType(required=True) solution = ModelType(Candidates, required=True) assignmentInfo = ListType(ModelType(AssignmentInfo))
class PluginMetadata(Model): supported_resource_type = ListType(StringType, default=_SUPPORTED_RESOURCE_TYPE) reference_keys = ListType(ModelType(ReferenceKeyModel), default=[])
class Solution(OSDFModel): placementSolutions = ListType( ListType(ModelType(PlacementSolution), min_size=1)) licenseSolutions = ListType(ModelType(LicenseSolution), min_size=1)
class School(Model): name = StringType(required=True) headmaster = ModelType(Person, required=True)
class PlacementResponse(OSDFModel): transactionId = StringType(required=True) requestId = StringType(required=True) requestStatus = StringType(required=True) statusMessage = StringType() solutions = ModelType(Solution, required=True)
class School(Model): courses = ListType(ModelType(Course))
class FinantialOrganization(BaseOrganization): identifier = ModelType(Identifier, required=True) additionalIdentifiers = ListType(ModelType(Identifier), required=True, validators=[validate_ua_fin])