Exemple #1
0
class Period(Model):
    startDate = IsoDateTimeType()  # The state date for the period.
    endDate = IsoDateTimeType()  # The end date for the period.

    def validate_startDate(self, data, value):
        if value and data.get('endDate') and data.get('endDate') < value:
            raise ValidationError(u"period should begin before its end")
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.")
Exemple #3
0
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
Exemple #4
0
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 Decision(Report):
    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.")
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 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 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)
Exemple #9
0
class Document(Model):
    class Options:
        roles = {
            'create':
            blacklist('id', 'datePublished', 'dateModified', 'author',
                      'download_url'),
            'edit':
            blacklist('id', 'url', 'datePublished', 'dateModified', 'author',
                      'hash', 'download_url'),
            'embedded':
            (blacklist('url', 'download_url') + schematics_embedded_role),
            'default':
            blacklist("__parent__"),
            'view': (blacklist('revisions') + schematics_default_role),
            'revisions':
            whitelist('url', 'dateModified'),
        }

    id = MD5Type(required=True, default=lambda: uuid4().hex)
    hash = HashType()
    title = StringType(required=True)  # A title of the document.
    title_en = StringType()
    title_ru = StringType()
    description = StringType()  # A description of the document.
    description_en = StringType()
    description_ru = StringType()
    format = StringType(required=True, regex='^[-\w]+/[-\.\w\+]+$')
    url = StringType(required=True)  # Link to the document or attachment.
    datePublished = IsoDateTimeType(default=get_now)
    dateModified = IsoDateTimeType(
        default=get_now)  # Date that the document was last dateModified
    language = StringType()
    relatedItem = MD5Type()
    author = StringType()
    documentType = StringType(choices=[
        "tenderNotice",
        "awardNotice",
        "contractNotice",
        "notice",
        "biddingDocuments",
        "technicalSpecifications",
        "evaluationCriteria",
        "clarifications",
        "shortlistedFirms",
        "riskProvisions",
        "billOfQuantity",
        "bidders",
        "conflictOfInterest",
        "debarments",
        "evaluationReports",
        "winningBid",
        "complaints",
        "contractSigned",
        "contractArrangements",
        "contractSchedule",
        "contractAnnexe",
        "contractGuarantees",
        "subContract",
        "eligibilityCriteria",
        "contractProforma",
        "commercialProposal",
        "qualificationDocuments",
        "eligibilityDocuments",
        "registerExtract",
        "registerFiscal",
    ])

    @serializable(serialized_name="url")
    def download_url(self):
        url = self.url
        if not url or '?download=' not in url:
            return url
        doc_id = parse_qs(urlparse(url).query)['download'][-1]
        root = self.__parent__
        parents = []
        while root.__parent__ is not None:
            parents[0:0] = [root]
            root = root.__parent__
        request = root.request
        if not request.registry.docservice_url:
            return url
        if 'status' in parents[0] and parents[0].status in type(
                parents[0])._options.roles:
            role = parents[0].status
            for index, obj in enumerate(parents):
                if obj.id != url.split('/')[(index - len(parents)) * 2 - 1]:
                    break
                field = url.split('/')[(index - len(parents)) * 2]
                if "_" in field:
                    field = field[0] + field.title().replace("_", "")[1:]
                roles = type(obj)._options.roles
                if roles[role if role in roles else 'default'](field, []):
                    return url
        from openprocurement.audit.api.utils import generate_docservice_url
        if not self.hash:
            path = [
                i for i in urlparse(url).path.split('/')
                if len(i) == 32 and not set(i).difference(hexdigits)
            ]
            return generate_docservice_url(request, doc_id, False,
                                           '{}/{}'.format(path[0], path[-1]))
        return generate_docservice_url(request, doc_id, False)

    def import_data(self, raw_data, **kw):
        """
        Converts and imports the raw data into the instance of the model
        according to the fields in the model.
        :param raw_data:
            The data to be imported.
        """
        data = self.convert(raw_data, **kw)
        del_keys = [k for k in data.keys() if data[k] == getattr(self, k)]
        for k in del_keys:
            del data[k]

        self._data.update(data)
        return self
Exemple #10
0
class Revision(Model):
    author = StringType()
    date = IsoDateTimeType(default=get_now)
    changes = ListType(DictType(BaseType), default=list())
    rev = StringType()
Exemple #11
0
class Report(Model):
    description = StringType(required=True)
    documents = ListType(ModelType(Document), default=[])
    dateCreated = IsoDateTimeType(default=get_now)
    datePublished = IsoDateTimeType()
Exemple #12
0
class Proceeding(Model):
    dateProceedings = IsoDateTimeType(required=True)
    proceedingNumber = StringType(required=True)
Exemple #13
0
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.")