class Party(Model): id = MD5Type(required=True, default=lambda: uuid4().hex) name = StringType(required=True, min_length=1) identifier = ModelType(Identifier) additionalIdentifiers = ListType(ModelType(Identifier)) address = ModelType(Address) contactPoint = ModelType(ContactPoint) roles = ListType(StringType(choices=[]), default=[]) datePublished = IsoDateTimeType(default=get_now)
class Liability(Model): class Options: roles = { 'create': whitelist('reportNumber', 'documents', 'legislation'), 'edit': whitelist('proceeding'), 'view': schematics_default_role, } id = MD5Type(required=True, default=lambda: uuid4().hex) reportNumber = StringType(required=True, min_length=1) datePublished = IsoDateTimeType(default=get_now) documents = ListType(ModelType(Document), default=[]) proceeding = ModelType(Proceeding) legislation = ModelType(Legislation, required=True) def get_role(self): return 'edit' @serializable(serialized_name="legislation", serialize_when_none=False) def fill_legislation(self): legislation = { 'version': '2020-11-21', 'type': 'NATIONAL_LEGISLATION', 'article': self.legislation.article, 'identifier': { 'id': '8073-X', 'legalName': 'Кодекс України про адміністративні правопорушення', 'uri': 'https://zakon.rada.gov.ua/laws/show/80731-10#Text', } } return legislation
class Conclusion(Report): violationOccurred = BooleanType(required=True) violationType = ListType(StringType(choices=VIOLATION_TYPE_CHOICES), default=[]) otherViolationType = StringType() auditFinding = StringType() stringsAttached = StringType() description = StringType(required=False) date = IsoDateTimeType(required=False) relatedParty = StringType() def validate_relatedParty(self, data, value): parent = data['__parent__'] if value and isinstance( parent, Model) and value not in [i.id for i in parent.parties]: raise ValidationError(u"relatedParty should be one of parties.") def validate_violationType(self, data, value): if data["violationOccurred"] and not value: raise ValidationError(u"This field is required.") if value and OTHER_VIOLATION not in value: # drop other type description data["otherViolationType"] = None def validate_otherViolationType(self, data, value): if OTHER_VIOLATION in data["violationType"] and not value: raise ValidationError(u"This field is required.")
class Party(Model): class Options: roles = { 'create': blacklist('id') + schematics_embedded_role, 'edit': blacklist('id') + schematics_embedded_role, 'embedded': schematics_embedded_role, 'view': schematics_default_role, } id = MD5Type(required=True, default=lambda: uuid4().hex) name = StringType(required=True) identifier = ModelType(Identifier, required=True) additionalIdentifiers = ListType(ModelType(Identifier)) address = ModelType(Address, required=True) contactPoint = ModelType(ContactPoint, required=True) roles = ListType(StringType(choices=PARTY_ROLES_CHOICES), default=[]) datePublished = IsoDateTimeType(default=get_now)
class Post(Model): class Options: roles = { 'create': whitelist('title', 'description', 'documents', 'relatedParty', 'relatedPost'), '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() postOf = StringType(choices=DIALOGUE_TYPE_CHOICES, default=DECISION_OBJECT_TYPE) datePublished = IsoDateTimeType(default=get_now) dateOverdue = IsoDateTimeType() relatedPost = StringType() relatedParty = StringType() def validate_relatedParty(self, data, value): parent = data['__parent__'] if value and isinstance(parent, Model) and value not in [i.id for i in parent.parties]: raise ValidationError(u"relatedParty should be one of parties.") def validate_relatedPost(self, data, value): parent = data['__parent__'] 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(u"relatedPost should be one of posts of current monitoring.") # 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(u"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(u"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(u"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(u"relatedPost can't be have relatedPost defined.")
class Inspection(BaseModel): class Options: roles = { 'plain': blacklist('_attachments', 'revisions') + schematics_embedded_role, 'revision': whitelist('revisions'), 'create': blacklist('revisions', 'dateModified', 'dateCreated', 'doc_id', '_attachments', 'inspection_id') + schematics_embedded_role, 'edit': whitelist("description", "monitoring_ids"), 'view': blacklist( '_attachments', 'revisions', ) + schematics_embedded_role, 'listing': whitelist('dateModified', 'doc_id'), 'default': schematics_default_role, } monitoring_ids = ListType(MD5Type, required=True, min_size=1) description = StringType(required=True) documents = ListType(ModelType(Document), default=list()) inspection_id = StringType() dateModified = IsoDateTimeType() dateCreated = IsoDateTimeType(default=get_now) revisions = ListType(ModelType(Revision), default=list()) _attachments = DictType(DictType(BaseType), default=dict()) def __repr__(self): return '<%s:%r-%r@%r>' % (type(self).__name__, self.inspection_id, self.id, self.rev)
class MonitoringParty(Party): class Options: namespace = "Party" roles = { 'create': blacklist('id') + schematics_embedded_role, 'edit': blacklist('id') + schematics_embedded_role, 'embedded': schematics_embedded_role, 'view': schematics_default_role, } identifier = ModelType(Identifier, required=True) address = ModelType(MonitoringAddress, required=True) contactPoint = ModelType(MonitoringContactPoint, required=True) roles = ListType(StringType(choices=PARTY_ROLES_CHOICES), default=[])
class RequestParty(Party): class Options: namespace = "Party" roles = { "view": blacklist( "address", "contactPoint", "identifier", "additionalIdentifiers", ) + schematics_embedded_role, "view_%s" % SAS_ROLE: schematics_embedded_role, } address = ModelType(RequestAddress, required=True) contactPoint = ModelType(RequestContactPoint, required=True) roles = ListType( StringType(choices=REQUEST_PARTY_ROLES_CHOICES), default=[PUBLIC_ROLE], required=True, )
class Revision(Model): author = StringType() date = IsoDateTimeType(default=get_now) changes = ListType(DictType(BaseType), default=list()) rev = StringType()
class Report(Model): description = StringType(required=True) documents = ListType(ModelType(Document), default=[]) dateCreated = IsoDateTimeType(default=get_now) datePublished = IsoDateTimeType()
class Legislation(Model): version = StringType() identifier = ModelType(LegislationIdentifier) type = StringType(choices=LEGISLATION_CHOICES, default=NATIONAL_LEGISLATION_TYPE) article = ListType(StringType, min_size=1, required=True)
class Monitoring(BaseModel): class Options: _perm_edit_whitelist = whitelist('status', 'reasons', 'procuringStages') roles = { 'plain': blacklist('_attachments', 'revisions') + schematics_embedded_role, 'revision': whitelist('revisions'), 'create': whitelist( "tender_id", "reasons", "procuringStages", "status", "mode", "monitoringDetails", "parties", "decision", "riskIndicators", "riskIndicatorsTotalImpact", "riskIndicatorsRegion", ), 'edit_draft': whitelist('decision', 'cancellation') + _perm_edit_whitelist, 'edit_active': whitelist('conclusion', 'cancellation') + _perm_edit_whitelist, 'edit_addressed': whitelist('eliminationResolution', 'cancellation') + _perm_edit_whitelist, 'edit_declined': whitelist('cancellation') + _perm_edit_whitelist, 'edit_completed': whitelist('documents'), 'edit_closed': whitelist('documents'), 'edit_stopped': whitelist('documents'), 'edit_cancelled': whitelist('documents'), 'view': blacklist('tender_owner_token', '_attachments', 'revisions', 'decision', 'conclusion', 'cancellation') + schematics_embedded_role, 'listing': whitelist('dateModified', 'doc_id'), 'default': schematics_default_role, } tender_id = MD5Type(required=True) monitoring_id = StringType() status = StringType(choices=MONITORING_STATUS_CHOICES, default=DRAFT_STATUS) reasons = ListType(StringType(choices=MONITORING_REASON_CHOICES), required=True) procuringStages = ListType(StringType(choices=MONITORING_PROCURING_STAGES), required=True) monitoringPeriod = ModelType(Period) documents = ListType(ModelType(Document), default=[]) riskIndicators = ListType(StringType(), default=[]) riskIndicatorsTotalImpact = FloatType() riskIndicatorsRegion = StringType() decision = ModelType(Decision) conclusion = ModelType(Conclusion) eliminationReport = ModelType(EliminationReport) eliminationResolution = ModelType(EliminationResolution) eliminationPeriod = ModelType(Period) posts = ListType(ModelType(Post), default=[]) cancellation = ModelType(Cancellation) appeal = ModelType(Appeal) liabilities = ListType(ModelType(Liability), default=list()) parties = ListType(ModelType(MonitoringParty), default=[]) dateModified = IsoDateTimeType() endDate = IsoDateTimeType() dateCreated = IsoDateTimeType(default=get_now) tender_owner = StringType() tender_owner_token = StringType() revisions = ListType(ModelType(Revision), default=[]) _attachments = DictType(DictType(BaseType), default=dict()) mode = StringType(choices=['test']) if SANDBOX_MODE: monitoringDetails = StringType() @serializable(serialized_name='decision', serialize_when_none=False, type=ModelType(Decision)) def monitoring_decision(self): role = self.__parent__.request.authenticated_role if self.decision and self.decision.datePublished or role == 'sas': return self.decision @serializable(serialized_name='conclusion', serialize_when_none=False, type=ModelType(Conclusion)) def monitoring_conclusion(self): role = self.__parent__.request.authenticated_role if self.conclusion and self.conclusion.datePublished or role == 'sas': return self.conclusion @serializable(serialized_name='cancellation', serialize_when_none=False, type=ModelType(Cancellation)) def monitoring_cancellation(self): role = self.__parent__.request.authenticated_role if self.cancellation and self.cancellation.datePublished or role == 'sas': return self.cancellation def get_role(self): role = super(Monitoring, self).get_role() status = self.__parent__.request.context.status return 'edit_{}'.format(status) if role == 'edit' else role def __acl__(self): return [ (Allow, '{}_{}'.format(self.tender_owner, self.tender_owner_token), 'create_post'), (Allow, '{}_{}'.format(self.tender_owner, self.tender_owner_token), 'create_elimination_report'), (Allow, '{}_{}'.format(self.tender_owner, self.tender_owner_token), 'create_appeal'), ] def __repr__(self): return '<%s:%r-%r@%r>' % (type(self).__name__, self.tender_id, self.id, self.rev)
class Request(BaseModel): class Options: namespace = "Request" roles = { "plain": blacklist("revisions") + schematics_embedded_role, "revision": whitelist("revisions"), "create": whitelist("description", "violationType", "documents", "parties", "tenderId", "mode"), "edit": whitelist("answer", "reason"), "view": blacklist("revisions") + schematics_embedded_role, "view_%s" % SAS_ROLE: blacklist("revisions") + schematics_embedded_role, "view_%s" % PUBLIC_ROLE: blacklist("revisions") + schematics_embedded_role, "listing": whitelist("dateModified", "doc_id"), "default": schematics_default_role, } description = StringType(required=True, min_length=1) violationType = ListType(StringType(choices=VIOLATION_TYPE_CHOICES), required=True, min_size=1) dateAnswered = IsoDateTimeType() dateModified = IsoDateTimeType() dateCreated = IsoDateTimeType(default=get_now) requestId = StringType() tenderId = MD5Type(required=True) documents = ListType(ModelType(Document, required=True), required=True, min_size=1) parties = ListType(ModelType(RequestParty, required=True), required=True, min_size=1) revisions = ListType(ModelType(Revision), default=list()) reason = StringType() answer = StringType(choices=[ "monitoringCreated", "noViolations", "plannedInspection", "lawEnforcement", "inspectionCreated", "plannedMonitoring", "noCompetency", "tenderCancelled", "violationRemoved" ]) def __repr__(self): return "<%s:%r-%r@%r>" % ( type(self).__name__, self.requestId, self.id, self.rev, ) def validate_answer(self, data, value): if data.get("reason") and not value: raise ValidationError("This field is required.") def validate_reason(self, data, value): if data.get("answer") and not value: raise ValidationError("This field is required.")