Пример #1
0
class CertificateDescription(DescriptionMixin, TrackedModel):
    record_code = "205"
    subrecord_code = "10"

    period_record_code = "205"
    period_subrecord_code = "05"

    identifying_fields = ("sid", )

    sid = SignedIntSID(db_index=True)

    description = ShortDescription()
    described_certificate = models.ForeignKey(
        Certificate,
        related_name="descriptions",
        on_delete=models.PROTECT,
    )

    indirect_business_rules = (business_rules.CE6, )

    def save(self, *args, **kwargs):
        if getattr(self, "sid") is None:
            highest_sid = CertificateDescription.objects.aggregate(
                Max("sid"))["sid__max"]
            self.sid = highest_sid + 1

        return super().save(*args, **kwargs)

    class Meta:
        ordering = ("validity_start", )
Пример #2
0
class MeasurementUnit(TrackedModel, ValidityMixin):
    """The measurement unit refers to the ISO measurement unit code."""

    record_code = "210"
    subrecord_code = "00"

    description_record_code = "210"
    description_subrecord_code = "05"

    code = models.CharField(
        max_length=3,
        validators=[validators.measurement_unit_code_validator],
        db_index=True,
    )
    description = ShortDescription()
    abbreviation = models.CharField(max_length=32, blank=True)

    identifying_fields = ("code", )

    indirect_business_rules = (
        business_rules.ME51,
        business_rules.ME63,
    )

    business_rules = (UpdateValidity, )
Пример #3
0
class MeasureTypeSeries(TrackedModel, ValidityMixin):
    """
    Measure types may be grouped into series.

    The series can be used to determine how duties are applied, and the possible
    cumulative effect of other applicable measures.
    """

    record_code = "140"
    subrecord_code = "00"

    description_record_code = "140"
    description_subrecord_code = "05"

    identifying_fields = ("sid", )

    sid = models.CharField(
        max_length=2,
        validators=[validators.measure_type_series_id_validator],
        db_index=True,
    )
    measure_type_combination = models.PositiveSmallIntegerField(
        choices=validators.MeasureTypeCombination.choices, )
    description = ShortDescription()

    indirect_business_rules = (business_rules.MT10, )
    business_rules = (
        business_rules.MTS1,
        business_rules.MTS2,
        UpdateValidity,
    )
Пример #4
0
class CertificateDescription(DescriptionMixin, ValidityMixin, TrackedModel):
    record_code = "205"
    subrecord_code = "10"

    period_record_code = "205"
    period_subrecord_code = "05"

    sid = SignedIntSID(db_index=True)

    description = ShortDescription()
    described_certificate = models.ForeignKey(
        Certificate,
        related_name="descriptions",
        on_delete=models.PROTECT,
    )

    indirect_business_rules = (business_rules.CE6,)
    business_rules = (
        business_rules.NoOverlappingDescriptions,
        business_rules.ContiguousDescriptions,
    )

    def __str__(self):
        return self.identifying_fields_to_string(
            identifying_fields=("described_certificate", "valid_between"),
        )

    class Meta:
        ordering = ("valid_between",)
Пример #5
0
class MeasureConditionCode(TrackedModel, ValidityMixin):
    """A measure condition code identifies a broad area where conditions are
    required, for example "C" will have the description "required to present a
    certificate"."""

    record_code = "350"
    subrecord_code = "00"

    description_record_code = "350"
    description_subrecord_code = "05"

    code = models.CharField(
        max_length=2,
        validators=[validators.measure_condition_code_validator],
        db_index=True,
    )
    description = ShortDescription()

    identifying_fields = ("code",)

    business_rules = (
        business_rules.MC1,
        business_rules.MC4,
    )

    def used_in_component(self):
        return (
            MeasureConditionComponent.objects.filter(
                condition__condition_code__code=self.code,
            )
            .approved_up_to_transaction(self.transaction)
            .exists()
        )
Пример #6
0
class MeasurementUnitQualifier(TrackedModel, ValidityMixin):
    """
    The measurement unit qualifier is used to qualify a measurement unit.

    For example the measurement unit "kilogram" may be qualified as "net" or
    "gross".
    """

    record_code = "215"
    subrecord_code = "00"

    description_record_code = "215"
    description_subrecord_code = "05"

    code = models.CharField(
        max_length=1,
        validators=[validators.measurement_unit_qualifier_code_validator],
        db_index=True,
    )
    description = ShortDescription()
    abbreviation = models.CharField(max_length=32, blank=True)

    identifying_fields = ("code", )

    indirect_business_rules = (
        business_rules.ME52,
        business_rules.ME64,
        quotas_business_rules.QD11,
    )

    business_rules = (UpdateValidity, )
Пример #7
0
class GeographicalAreaDescription(DescriptionMixin, TrackedModel):
    record_code = "250"
    subrecord_code = "10"

    period_record_code = "250"
    period_subrecord_code = "05"

    identifying_fields = ("sid", )

    described_geographicalarea = models.ForeignKey(
        GeographicalArea,
        on_delete=models.CASCADE,
        related_name="descriptions",
    )
    description = ShortDescription()
    sid = SignedIntSID(db_index=True)

    def save(self, *args, **kwargs):
        if getattr(self, "sid") is None:
            highest_sid = GeographicalAreaDescription.objects.aggregate(
                Max("sid"))["sid__max"]
            self.sid = highest_sid + 1

        return super().save(*args, **kwargs)

    url_pattern_name_prefix = "geo_area_description"

    class Meta:
        ordering = ("validity_start", )
Пример #8
0
class CertificateType(TrackedModel, ValidityMixin):
    record_code = "110"
    subrecord_code = "00"

    description_record_code = "110"
    description_subrecord_code = "05"

    identifying_fields = ("sid", )

    sid = models.CharField(
        max_length=1,
        validators=[validators.certificate_type_sid_validator],
        db_index=True,
    )
    description = ShortDescription()

    indirect_business_rules = (business_rules.CE7, )
    business_rules = (
        business_rules.CET1,
        business_rules.CET2,
        UpdateValidity,
    )

    def __str__(self):
        return self.sid
Пример #9
0
class Group(TrackedModel, ValidityMixin):
    """
    A regulation group allows regulations to be grouped within the same logical
    unit. This allows the regulations covered by a certain regulation group to
    be identified. Consequently it is possible to identify the measure types
    and/or countries which relate to a regulation group. Only base regulations
    can be associated with a regulation group.

    Regulations can only belong to a single Regulation group.

    Regulations groups do not have end dates set.

    Regulation groups must not be modified.
    """

    record_code = "150"
    subrecord_code = "00"

    description_subrecord_code = "05"

    group_id = models.CharField(
        max_length=3,
        editable=False,
        validators=[RegexValidator(r"[A-Z][A-Z][A-Z]")],
        db_index=True,
    )
    description = ShortDescription()

    identifying_fields = ("group_id", )

    indirect_business_rules = (
        business_rules.ROIMB4,
        business_rules.ROIMB47,
    )
Пример #10
0
class CertificateType(TrackedModel, ValidityMixin):
    record_code = "110"
    subrecord_code = "00"

    description_record_code = "110"
    description_subrecord_code = "05"

    sid = models.CharField(
        max_length=1,
        validators=[validators.certificate_type_sid_validator],
        db_index=True,
    )
    description = ShortDescription()

    indirect_business_rules = (business_rules.CE7,)
    business_rules = (
        business_rules.CET1,
        business_rules.CET2,
    )

    def in_use(self):
        return (
            Certificate.objects.filter(certificate_type__sid=self.sid)
            .approved_up_to_transaction(self.transaction)
            .exists()
        )

    def __str__(self):
        return self.sid
Пример #11
0
class MonetaryUnit(TrackedModel, ValidityMixin):
    """The monetary unit identifies the currency code used in the system."""

    record_code = "225"
    subrecord_code = "00"

    description_record_code = "225"
    description_subrecord_code = "05"

    code = models.CharField(
        max_length=3,
        validators=[validators.monetary_unit_code_validator],
        db_index=True,
    )
    description = ShortDescription()

    identifying_fields = ("code", )

    indirect_business_rules = (
        business_rules.ME48,
        business_rules.ME49,
        business_rules.ME60,
        business_rules.ME61,
        quotas_business_rules.QD8,
    )

    business_rules = (UpdateValidity, )
Пример #12
0
class QuotaSuspension(TrackedModel, ValidityMixin):
    """Defines a suspension period for a quota."""

    record_code = "370"
    subrecord_code = "15"

    sid = SignedIntSID(db_index=True)
    quota_definition = models.ForeignKey(QuotaDefinition,
                                         on_delete=models.PROTECT)
    description = ShortDescription()

    business_rules = (business_rules.QSP2, )
Пример #13
0
class QuotaBlocking(TrackedModel, ValidityMixin):
    """Defines a blocking period for a (sub-)quota."""

    record_code = "370"
    subrecord_code = "10"

    sid = SignedIntSID(db_index=True)
    quota_definition = models.ForeignKey(QuotaDefinition,
                                         on_delete=models.PROTECT)
    blocking_period_type = models.PositiveSmallIntegerField(
        choices=validators.BlockingPeriodType.choices, )
    description = ShortDescription()

    business_rules = (business_rules.QBP2, )
Пример #14
0
class TestModelDescription1(DescriptionMixin, TrackedModel):
    __test__ = False
    record_code = "01"
    subrecord_code = "02"

    identifying_fields = (
        "described_record__sid",
        "validity_start",
    )

    described_record = models.ForeignKey(
        TestModel1,
        on_delete=models.PROTECT,
        related_name="descriptions",
    )
    description = ShortDescription()
Пример #15
0
class FootnoteType(TrackedModel, ValidityMixin):
    """
    The footnote type record allows all footnotes to be classified according to
    type.

    It will be used to check if a given footnote can be associated with a
    specific entity. For example, footnote type "CN" will be used to group all
    CN-related footnotes.
    """

    record_code = "100"
    subrecord_code = "00"

    description_record_code = "100"
    description_subrecord_code = "05"

    identifying_fields = ("footnote_type_id",)

    footnote_type_id = models.CharField(
        max_length=3,
        validators=[validators.footnote_type_id_validator],
        db_index=True,
    )
    application_code = models.PositiveIntegerField(
        choices=validators.ApplicationCode.choices,
    )
    description = ShortDescription()

    indirect_business_rules = (business_rules.FO17,)
    business_rules = (
        business_rules.FOT1,
        business_rules.FOT2,
    )

    def __str__(self):
        return self.footnote_type_id

    def in_use(self):
        return (
            Footnote.objects.filter(
                footnote_type__footnote_type_id=self.footnote_type_id,
            )
            .approved_up_to_transaction(self.transaction)
            .exists()
        )
Пример #16
0
class GeographicalAreaDescription(TrackedModel, ValidityMixin):
    record_code = "250"
    subrecord_code = "10"

    period_record_code = "250"
    period_subrecord_code = "05"

    area = models.ForeignKey(
        GeographicalArea,
        on_delete=models.CASCADE,
        related_name="descriptions",
    )
    description = ShortDescription()
    sid = SignedIntSID(db_index=True)

    def __str__(self):
        return f'description ({self.sid}) - "{self.description}" for {self.area}'

    class Meta:
        ordering = ("valid_between", )
Пример #17
0
class DutyExpression(TrackedModel, ValidityMixin):
    """
    The duty expression identifies the type of duty which must be applied for a
    given measure component.

    It will also control how the duty will be expressed, for example whether an
    amount is "permitted" or "mandatory".
    """

    record_code = "230"
    subrecord_code = "00"

    description_record_code = "230"
    description_subrecord_code = "05"

    identifying_fields = ("sid", )

    sid = models.IntegerField(
        choices=validators.DutyExpressionId.choices,
        db_index=True,
    )
    prefix = models.CharField(max_length=14, blank=True)
    duty_amount_applicability_code = ApplicabilityCode()
    measurement_unit_applicability_code = ApplicabilityCode()
    monetary_unit_applicability_code = ApplicabilityCode()
    description = ShortDescription()

    indirect_business_rules = (
        business_rules.ME40,
        business_rules.ME42,
        business_rules.ME45,
        business_rules.ME46,
        business_rules.ME47,
        business_rules.ME105,
        business_rules.ME106,
        business_rules.ME109,
        business_rules.ME110,
        business_rules.ME111,
    )

    business_rules = (UniqueIdentifyingFields, UpdateValidity)
Пример #18
0
class MeasureAction(TrackedModel, ValidityMixin):
    """
    The measure action identifies the action to take when a given condition is
    met.

    For example, the description of "01" will be "apply ACTION AMOUNT".
    """

    record_code = "355"
    subrecord_code = "00"

    description_record_code = "355"
    description_subrecord_code = "05"

    code = models.CharField(
        max_length=3,
        validators=[validators.validate_action_code],
        db_index=True,
    )
    description = ShortDescription()

    identifying_fields = ("code",)

    indirect_business_rules = (
        business_rules.MA4,
        business_rules.ME59,
    )
    business_rules = (
        business_rules.MA1,
        business_rules.MA2,
    )

    def in_use(self):
        return (
            MeasureConditionComponent.objects.filter(
                condition__action__code=self.code,
            )
            .approved_up_to_transaction(self.transaction)
            .exists()
        )
Пример #19
0
class MeasureAction(TrackedModel, ValidityMixin):
    """
    The measure action identifies the action to take when a given condition is
    met.

    For example, the description of "01" will be "apply ACTION AMOUNT".
    """

    record_code = "355"
    subrecord_code = "00"

    description_record_code = "355"
    description_subrecord_code = "05"

    code = models.CharField(
        max_length=3,
        validators=[validators.validate_action_code],
        db_index=True,
    )
    description = ShortDescription()
    requires_duty = models.BooleanField(default=False)

    identifying_fields = ("code", )

    indirect_business_rules = (
        business_rules.MA4,
        business_rules.ME59,
    )
    business_rules = (
        business_rules.MA1,
        business_rules.MA2,
        UpdateValidity,
    )

    class Meta:
        ordering = ["code"]

    def __str__(self):
        return f"{self.code} - {self.description}"
Пример #20
0
class AdditionalCodeType(TrackedModel, ValidityMixin):
    """
    The additional code type allows all additional codes to be classified
    according to type.

    It will be used to check if a given additional code can be associated with
    other data. For example, additional code types for export refund purposes
    are grouped together and can only be used within that area (nomenclature,
    measures).
    """

    record_code = "120"
    subrecord_code = "00"

    description_record_code = "120"
    description_subrecord_code = "05"

    identifying_fields = ("sid", )

    sid = models.CharField(
        max_length=1,
        validators=[validators.additional_code_type_sid_validator],
        db_index=True,
    )
    description = ShortDescription()

    # Code which indicates to which data type the additional code type applies.
    application_code = models.PositiveSmallIntegerField(
        choices=validators.ApplicationCode.choices, )

    indirect_business_rules = (
        business_rules.ACN2,
        business_rules.ACN17,
        measures_business_rules.ME12,
    )
    business_rules = (business_rules.CT1, UpdateValidity)

    def __str__(self):
        return f"AdditionalcodeType {self.sid}: {self.description}"
Пример #21
0
class MeasureTypeSeries(TrackedModel, ValidityMixin):
    """
    Measure types may be grouped into series.

    The series can be used to determine how duties are applied, and the possible
    cumulative effect of other applicable measures.
    """

    record_code = "140"
    subrecord_code = "00"

    description_record_code = "140"
    description_subrecord_code = "05"

    sid = models.CharField(
        max_length=2,
        validators=[validators.measure_type_series_id_validator],
        db_index=True,
    )
    measure_type_combination = models.PositiveSmallIntegerField(
        choices=validators.MeasureTypeCombination.choices,
    )
    description = ShortDescription()

    indirect_business_rules = (business_rules.MT10,)
    business_rules = (
        business_rules.MTS1,
        business_rules.MTS2,
    )

    def in_use(self):
        return (
            MeasureType.objects.filter(
                measure_type_series__sid=self.sid,
            )
            .approved_up_to_transaction(self.transaction)
            .exists()
        )
Пример #22
0
class MeasureConditionCode(TrackedModel, ValidityMixin):
    """A measure condition code identifies a broad area where conditions are
    required, for example "C" will have the description "required to present a
    certificate"."""

    record_code = "350"
    subrecord_code = "00"

    description_record_code = "350"
    description_subrecord_code = "05"

    code = models.CharField(
        max_length=2,
        validators=[validators.measure_condition_code_validator],
        db_index=True,
    )
    description = ShortDescription()
    # A measure condition code must be created with one or both of
    # accepts_certificate and accepts_price set to True,
    # though a condition should only ever have one of either required_certificate or duty_amount set.
    accepts_certificate = models.BooleanField(default=False)
    accepts_price = models.BooleanField(default=False)

    identifying_fields = ("code", )

    business_rules = (
        business_rules.MC1,
        business_rules.MC4,
        UpdateValidity,
    )

    class Meta:
        ordering = ["code"]

    def __str__(self):
        return f"{self.code} - {self.description}"
Пример #23
0
class Regulation(TrackedModel, ValidityMixin):
    """
    The main legal acts at the basis of the Union tariff and commercial
    legislation are regulations and decisions.

    They can have one or several roles: base, provisional or definitive
    antidumping, modification, complete abrogation, explicit abrogation,
    prorogation (extension), Full Temporary Stop (FTS), Partial Temporary Stop
    (PTS)
    """

    identifying_fields = ("role_type", "regulation_id")

    record_code = "285"
    subrecord_code = "00"

    role_type = models.PositiveIntegerField(
        choices=validators.RoleType.choices,
        default=validators.RoleType.BASE,
        editable=False,
        db_index=True,
    )
    regulation_id = models.CharField(
        max_length=8,
        editable=False,
        validators=[validators.regulation_id_validator],
        help_text="The regulation number",
        db_index=True,
    )
    official_journal_number = models.CharField(
        max_length=5,
        null=True,
        blank=True,
        editable=False,
        default="1",
    )
    official_journal_page = models.PositiveSmallIntegerField(
        blank=True,
        null=True,
        validators=[MaxValueValidator(9999)],
        editable=False,
        default=1,
    )
    published_at = models.DateField(
        blank=True,
        null=True,
    )
    information_text = ShortDescription(
        validators=[validators.no_information_text_delimiters], )
    public_identifier = models.CharField(
        max_length=50,
        null=True,
        blank=True,
        help_text=
        "This is the name of the regulation as it would appear on (for example) legislation.gov.uk",
        validators=[validators.no_information_text_delimiters],
    )
    url = models.URLField(
        blank=True,
        null=True,
        help_text="Please enter the absolute URL of the regulation",
        validators=[validators.no_information_text_delimiters],
    )

    # Indicates if a (draft) regulation is approved.
    # Measures associated with an unapproved draft regulation are only for information and
    # do not apply.
    # If the draft regulation is rejected, all associated measures are deleted.
    # If approved, all measures apply.
    # Once the actual regulation is known, it replaces the draft regulation and all
    # measures are moved from the draft to the actual regulation.
    # It is possible for a draft regulation to be replaced by multiple actual regulations,
    # each one partially replacing the draft.
    approved = models.BooleanField(default=False, )
    """The code which indicates whether or not a regulation has been replaced."""
    replacement_indicator = models.PositiveIntegerField(
        choices=validators.ReplacementIndicator.choices,
        default=validators.ReplacementIndicator.NOT_REPLACED,
        editable=False,
    )

    # Complete Abrogation, Explicit Abrogation and Prorogation regulations have no
    # validity period
    if settings.SQLITE:
        validity_start = DateField(db_index=True, null=True, blank=True)
        validity_end = DateField(db_index=True, null=True, blank=True)
    else:
        valid_between = TaricDateRangeField(blank=True, null=True)

    # Base, Modification and FTS regulations have an effective end date
    effective_end_date = models.DateField(blank=True,
                                          null=True,
                                          editable=False)

    # XXX do we need to store this? - i think it is already captured by
    #     self.terminations.count() > 0
    stopped = models.BooleanField(default=False)

    # Base regulations have community_code and regulation_group
    community_code = models.PositiveIntegerField(
        choices=validators.CommunityCode.choices,
        blank=True,
        null=True,
        default=validators.CommunityCode.ECONOMIC,
    )
    regulation_group = models.ForeignKey(
        Group,
        on_delete=models.PROTECT,
        blank=True,
        null=True,
    )

    amends = models.ManyToManyField(
        "Regulation",
        through="Amendment",
        related_name="+",
        through_fields=("enacting_regulation", "target_regulation"),
    )

    extends = models.ManyToManyField(
        "Regulation",
        through="Extension",
        related_name="+",
        through_fields=("enacting_regulation", "target_regulation"),
    )

    suspends = models.ManyToManyField(
        "Regulation",
        through="Suspension",
        related_name="+",
        through_fields=("enacting_regulation", "target_regulation"),
    )

    terminates = models.ManyToManyField(
        "Regulation",
        through="Termination",
        related_name="+",
        through_fields=("enacting_regulation", "target_regulation"),
    )

    replaces = models.ManyToManyField(
        "Regulation",
        through="Replacement",
        related_name="+",
        through_fields=("enacting_regulation", "target_regulation"),
    )

    business_rules = (
        business_rules.ROIMB1,
        business_rules.ROIMB4,
        business_rules.ROIMB8,
        business_rules.ROIMB44,
        business_rules.ROIMB46,
        business_rules.ROIMB47,
        UpdateValidity,
    )

    indirect_business_rules = (measure_business_rules.ME27, )

    @property
    def structure_description(self):
        return self.information_text

    @classmethod
    def from_db(cls, db, field_names, values):
        instance = super().from_db(db, field_names, values)
        # store db values to detect changes
        instance.values_from_db = dict(zip(field_names, values))
        return instance

    @property
    def is_draft_regulation(self):
        return self.regulation_id.startswith("C")

    def __str__(self):
        return str(self.regulation_id)

    @property
    def autocomplete_label(self):
        return f"{self} - {self.information_text}"

    def used_as_terminating_regulation_or_draft_generating_and_terminating_regulation(
        self,
        transaction,
    ):
        if self.role_type != validators.RoleType.BASE:
            return

        return (self.measure_set.model.objects.filter(
            terminating_regulation__regulation_id=self.regulation_id,
            terminating_regulation__role_type=self.role_type,
        ).exclude(
            generating_regulation__regulation_id__startswith="C",
            generating_regulation__regulation_id=self.regulation_id,
            generating_regulation__role_type=self.role_type,
        ).approved_up_to_transaction(transaction).exists())
Пример #24
0
class QuotaDefinition(TrackedModel, ValidityMixin):
    """
    Defines the validity period and quantity for which a quota is applicable.
    This model also represents sub-quotas, via a parent-child recursive relation
    through QuotaAssociation.

    The monetary unit code and the measurement unit code (with its optional unit
    qualifier code) are mutually exclusive – each quota definition must have one
    and only one of monetary or measurement unit.

    The pair of measurement and measurement unit qualifier must appear as a
    valid measurement in the measurements table.
    """

    record_code = "370"
    subrecord_code = "00"

    identifying_fields = ("sid", )

    sid = SignedIntSID(db_index=True)
    order_number = models.ForeignKey(QuotaOrderNumber,
                                     on_delete=models.PROTECT)
    volume = models.DecimalField(max_digits=14, decimal_places=3)
    initial_volume = models.DecimalField(max_digits=14, decimal_places=3)
    monetary_unit = models.ForeignKey(
        "measures.MonetaryUnit",
        on_delete=models.PROTECT,
        null=True,
        blank=True,
    )
    measurement_unit = models.ForeignKey(
        "measures.MeasurementUnit",
        on_delete=models.PROTECT,
        null=True,
        blank=True,
    )
    measurement_unit_qualifier = models.ForeignKey(
        "measures.MeasurementUnitQualifier",
        on_delete=models.PROTECT,
        null=True,
        blank=True,
    )
    maximum_precision = models.PositiveSmallIntegerField(
        validators=[validators.validate_max_precision], )
    quota_critical = models.BooleanField(default=False)
    # the percentage at which the quota becomes critical
    quota_critical_threshold = models.PositiveSmallIntegerField(
        validators=[validators.validate_percentage], )
    description = ShortDescription()

    sub_quotas = models.ManyToManyField(
        "self",
        through="QuotaAssociation",
        through_fields=("main_quota", "sub_quota"),
    )

    indirect_business_rules = (
        business_rules.QA2,
        business_rules.QA3,
        business_rules.QA5,
        business_rules.QSP2,
    )
    business_rules = (
        business_rules.ON8,
        business_rules.QD1,
        business_rules.QD7,
        business_rules.QD8,
        business_rules.QD10,
        business_rules.QD11,
        business_rules.PreventQuotaDefinitionDeletion,
        business_rules.QuotaAssociationMustReferToANonDeletedSubQuota,
        business_rules.QuotaSuspensionMustReferToANonDeletedQuotaDefinition,
        business_rules.
        QuotaBlockingPeriodMustReferToANonDeletedQuotaDefinition,
        business_rules.OverlappingQuotaDefinition,
        business_rules.VolumeAndInitialVolumeMustMatch,
        UniqueIdentifyingFields,
        UpdateValidity,
    )

    class Meta:
        constraints = [
            models.CheckConstraint(
                check=(models.Q(
                    monetary_unit__isnull=False,
                    measurement_unit__isnull=True,
                )
                       | models.Q(
                           monetary_unit__isnull=True,
                           measurement_unit__isnull=False,
                       )),
                name="quota_definition_must_have_one_unit",
            ),
        ]

    def __str__(self):
        return str(self.sid)
Пример #25
0
class MeasureType(TrackedModel, ValidityMixin):
    """
    The measure type identifies a customs measure.

    TARIC customs measures cover a wide range of information, including tariff
    measures (such as levies and anti-dumping duties), and non-tariff measures
    (such as quantitative restrictions and prohibitions).
    """

    record_code = "235"
    subrecord_code = "00"

    description_record_code = "235"
    description_subrecord_code = "05"

    identifying_fields = ("sid", )

    sid = models.CharField(
        max_length=6,
        validators=[validators.measure_type_id_validator],
        db_index=True,
    )
    trade_movement_code = models.PositiveSmallIntegerField(
        choices=validators.ImportExportCode.choices, )
    priority_code = models.PositiveSmallIntegerField(
        validators=[validators.validate_priority_code], )
    measure_component_applicability_code = ApplicabilityCode()
    origin_destination_code = models.PositiveSmallIntegerField(
        choices=validators.ImportExportCode.choices, )
    order_number_capture_code = models.PositiveSmallIntegerField(
        choices=validators.OrderNumberCaptureCode.choices, )
    measure_explosion_level = models.PositiveSmallIntegerField(
        choices=validators.MeasureExplosionLevel.choices,
        validators=[validators.validate_measure_explosion_level],
    )
    description = ShortDescription()
    measure_type_series = models.ForeignKey(MeasureTypeSeries,
                                            on_delete=models.PROTECT)

    additional_code_types = models.ManyToManyField(
        "additional_codes.AdditionalCodeType",
        through="AdditionalCodeTypeMeasureType",
    )

    indirect_business_rules = (
        business_rules.ME1,
        business_rules.ME10,
        business_rules.ME88,
    )
    business_rules = (
        business_rules.MT1,
        business_rules.MT3,
        business_rules.MT4,
        business_rules.MT7,
        business_rules.MT10,
        UpdateValidity,
    )

    def __str__(self):
        return str(self.sid)

    @property
    def autocomplete_label(self):
        return f"{self} - {self.description}"

    @property
    def components_mandatory(self):
        return (self.measure_component_applicability_code ==
                validators.ApplicabilityCode.MANDATORY)

    @property
    def components_not_permitted(self):
        return (self.measure_component_applicability_code ==
                validators.ApplicabilityCode.NOT_PERMITTED)

    @property
    def order_number_mandatory(self):
        return self.order_number_capture_code == validators.ApplicabilityCode.MANDATORY

    @property
    def order_number_not_permitted(self):
        return (self.order_number_capture_code ==
                validators.ApplicabilityCode.NOT_PERMITTED)