Пример #1
0
 def approved_query_filter(self, prefix=""):
     return Q(
         **{
             f"{prefix}transaction__workbasket__status__in": WorkflowStatus.approved_statuses(),
             f"{prefix}transaction__workbasket__approver__isnull": False,
         }
     )
Пример #2
0
    def handle(self, *args: Any, **options: Any) -> Optional[str]:
        workbaskets = WorkBasket.objects.order_by("updated_at").all()

        workbasket_statuses = set()
        if options["status"]:
            workbasket_statuses.update(options["status"])

        if options.get("approved_statuses"):
            workbasket_statuses.update(WorkflowStatus.approved_statuses())

        if workbasket_statuses:
            workbaskets = workbaskets.filter(status__in=options["status"])

        if options.get("workbasket_ids"):
            workbaskets = workbaskets.filter(id__in=options["workbasket_ids"])

        output_format = (WorkBasketOutputFormat.COMPACT if options["compact"]
                         else WorkBasketOutputFormat.READABLE)

        show_transaction_info = options["transactions"]

        self.output_workbaskets(
            workbaskets,
            show_transaction_info,
            output_format=output_format,
        )
Пример #3
0
def infer_draft_transaction_partitions(apps, schemaeditor):
    """Infer the partition of Transactions to DRAFT if they are in an unapproved
    workbasket that isn't the first (seed) Workbasket."""
    from common.models.transactions import TransactionPartition
    from workbaskets.validators import WorkflowStatus

    non_seed_transactions(apps).exclude(
        workbasket__status__in=WorkflowStatus.approved_statuses(), ).update(
            partition=TransactionPartition.DRAFT.value)
Пример #4
0
    def get_partition(self, status: WorkflowStatus) -> TransactionPartition:
        """
        :param status:  Workbasket status
        :return:  TransactionPartition that maps to the workbasket status.
        """
        if status not in WorkflowStatus.approved_statuses():
            # Bail out early if not approved and avoid query in the next if block.
            return TransactionPartition.DRAFT

        return self.get_approved_partition()
Пример #5
0
def infer_revision_transaction_partitions(apps, schemaeditor):
    """Infer the partition of Transactions to REVISION if they are not in the
    first workbasket and their workbasket status is approved."""
    from common.models.transactions import TransactionPartition
    from workbaskets.validators import WorkflowStatus

    apps.get_model("common", "Transaction")
    apps.get_model("workbaskets", "Workbasket")

    non_seed_transactions(apps).filter(
        workbasket__status__in=WorkflowStatus.approved_statuses(), ).update(
            partition=TransactionPartition.REVISION.value)
Пример #6
0
    def get_approved_partition(self) -> TransactionPartition:
        """
        :return REVISION: if any approved workbaskets exist otherwise SEED_FILE.

        Implements the policy where approved transactions in the first workbasket are from the seed file
        and the rest of the approved transactions are revisions.

        Usage note:   This must to be called before workbasket status is changed otherwise it will only
                      ever return REVISION.
        """
        if WorkBasket.objects.filter(
                status__in=WorkflowStatus.approved_statuses(), ).exists():
            return TransactionPartition.REVISION
        return TransactionPartition.SEED_FILE
Пример #7
0
    def save(self, *args, force_write=False, **kwargs):
        if not force_write and not self._can_write():
            raise IllegalSaveError(
                "TrackedModels cannot be updated once written and approved. "
                "If writing a new row, use `.new_draft` instead",
            )

        if not hasattr(self, "version_group"):
            self.version_group = self._get_version_group()

        return_value = super().save(*args, **kwargs)

        if self.transaction.workbasket.status in WorkflowStatus.approved_statuses():
            self.version_group.current_version = self
            self.version_group.save()

        return return_value
Пример #8
0
    def add_arguments(self, parser: CommandParser) -> None:
        statuses = [str(w) for w in WorkflowStatus]
        parser.add_argument(
            "--status",
            nargs="+",
            help=("Only list WorkBaskets with the given STATUS. The default, "
                  "without use of this flag, is to list all WorkBaskets."
                  f"STATUS can be any of {', '.join(statuses)}"),
        )

        approved_statuses = [
            status.name for status in WorkflowStatus.approved_statuses()
        ]
        parser.add_argument(
            "-a",
            "--approved-statuses",
            dest="approved",
            action="store_true",
            help=
            f"List workbaskets with ANY of the approved statuses, equivalent to: [{', '.join(approved_statuses)}]",
        )

        parser.add_argument(
            "-c",
            "--compact",
            action="store_true",
            help="Output one workbasket per line.",
        )

        parser.add_argument(
            "-t",
            "--transactions",
            action="store_true",
            help="Output first / last transactions.",
        )

        parser.add_argument(
            "workbasket_ids",
            help=("Comma-separated list of workbasket ids to filter to"),
            type=ast.literal_eval,
        )
Пример #9
0
    def save(self, *args, force_write=False, **kwargs):
        """
        Save the model to the database.

        :param force_write bool: Ignore append-only restrictions and write to
            the database even if the model already exists
        """
        if not force_write and not self._can_write():
            raise IllegalSaveError(
                "TrackedModels cannot be updated once written and approved. "
                "If writing a new row, use `.new_draft` instead", )

        if not hasattr(self, "version_group"):
            self.version_group = self._get_version_group()

        return_value = super().save(*args, **kwargs)

        if self.transaction.workbasket.status in WorkflowStatus.approved_statuses(
        ):
            self.version_group.current_version = self
            self.version_group.save()

        auto_fields = {
            field
            for field in self.auto_value_fields
            if field.attname in self.__dict__
            and isinstance(self.__dict__.get(field.attname), (Expression, F))
        }

        # If the model contains any fields that are built in the database, the
        # fields will still contain the expression objects. So remove them now
        # and Django will lazy fetch the real values if they are accessed.
        for field in auto_fields:
            delattr(self, field.name)

        return return_value
Пример #10
0
 def approved(self):
     return self.status in WorkflowStatus.approved_statuses()
Пример #11
0
 def is_not_approved(self):
     return self.exclude(
         status__in=WorkflowStatus.approved_statuses(),
         approver__isnull=False,
     )
Пример #12
0
 def is_approved(self):
     return self.filter(
         status__in=WorkflowStatus.approved_statuses(),
         approver__isnull=False,
     )
Пример #13
0
 def _can_write(self):
     return not (self.pk and self.transaction.workbasket.status
                 in WorkflowStatus.approved_statuses())
Пример #14
0

@pytest.mark.parametrize("status",
                         [WorkflowStatus.EDITING, WorkflowStatus.PROPOSED])
def test_draft_status_as_transaction_partition_draft_no_first_seed(status, ):
    """When first_partition_is_seed is False, draft workbaskets should generate
    a DRAFT transaction partition value."""
    partition_scheme = SEED_FIRST
    assert isinstance(partition_scheme, TransactionPartitionScheme)

    partition = partition_scheme.get_partition(status)

    assert partition == TransactionPartition.DRAFT


@pytest.mark.parametrize("status", WorkflowStatus.approved_statuses())
@pytest.mark.parametrize(
    "partition_scheme,expected_partition",
    [
        (
            UserTransactionPartitionScheme(TransactionPartition.SEED_FILE,
                                           "test text"),
            TransactionPartition.SEED_FILE,
        ),
        (
            UserTransactionPartitionScheme(TransactionPartition.REVISION,
                                           "test text"),
            TransactionPartition.REVISION,
        ),
    ],
)