Git Product home page Git Product logo

django-logic's Issues

Accessing transitions checks their permissions despite user not being available

Accessing transition from a process like

model.process.transition()

Results in a call to Process.get_available_transitions, which accepts a user object, which it passes to permissions to check them. However, in this case user will be None, because all we're doing is accessing a transition.
Essentially what this means is that all permission functions have to check whether they were passed an empty user and return True in this case, otherwise transitions using them cannot be called.

Implement Celery command

It needs to implement a command which executes all provided functions as celery chain tasks.
During the execution, it should change the state to the in-progress state.
Once, the execution is finished, it should change to the target state.
If a failure occurs, it should change to the failure state and run a failure handler.
Provide acks_late=True by default

`getattr` on Process instances raises TransitionNotAllowed on failure

getattr(tracking_event.tracking_event_process, 'gfdgdfg')

Traceback (most recent call last):
  File "/home/vagrant/env/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 3326, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-6-ebad20b256f2>", line 1, in <module>
    getattr(tracking_event.tracking_event_process, 'gfdgdfg')
  File "/home/vagrant/env/lib/python3.6/site-packages/django_logic/process.py", line 51, in __getattr__
    raise TransitionNotAllowed('Transition not allowed')
django_logic.exceptions.TransitionNotAllowed: Transition not allowed

Seems like a bug, attribute user's attempting to get might not even be a transition

Update readme

Define clearly what is:

  • state
  • command: Condition, Permission, Side-Effects and Callbacks
  • Transition
  • Process
  • ProcessManager and why it should work as a mixin

It needs to provide more information on these questions:

  • What does this project do?
  • Why is this project useful?
  • How do I get started?
  • Where can I get more help, if I need it?

Also:

  • Code of Conduct

`get_db_state` assumes default queryset

 @staticmethod
    def get_db_state(instance, field_name):
        """
        Fetches state directly from db instead of model instance.
        """
        return instance._meta.model.objects.values_list(field_name, flat=True).get(pk=instance.id)

This code assumes that the model is currently contained within the default queryset, which is not always the case. For instance, default queryset could be configured to exclude models with state=deleted, in which case transitions would stop working for it.

Implement change state method

It should support the execution of side-effects and callbacks as:

  • Function
  • Celery Command
  • Failure Command

During the execution, the object should be locked and the state should be changed to in_progress

Draw method enhancements

  • support in progress states
  • highlight begin
  • fix bug with process name
  • fix bug which duplicated condition on the graph, e.g. has_no_sales_invoices duplicated.
  • cover by tests
class InvoiceProcess(Process):
    transitions = [
        Transition(action_name='approve',
                   sources=[states.draft],
                   target=states.approved),
        Transition(action_name='void',
                   sources=[states.draft, states.approved],
                   target=states.void,
                   conditions=[has_no_sales_invoices],
                   ),
    ]

Screenshot 2019-12-09 at 10 28 13 PM

Implement StateField & remove ProcessManager

Implement StateField which shouldn't be possible to update via the save method without explicitly defining so. Currently, it's implemented via mixin django_logic.process.ProcessManager which can be deleted after.
However, it looks more like a workaround rather than a solution.
Try to avoid extra models.

Once it's done it should be possible to assign Process class explicitly to the model.

`ProcessManager.bind_state_fields` doesn't work with multiple states

Currently there is a bug with ProcessManager.bind_state_fields method as it utilizes closures incorrectly:

for state_field, process_class in kwargs.items():
    if not issubclass(process_class, Process):
        raise TypeError('Must be a sub class of Process')
    parameters[process_class.get_process_name()] = property(lambda self: process_class(
        field_name=state_field,
        instance=self))
    parameters['state_fields'].append(state_field)

With this code, value of the process_class variable inside the lambda function will always be the last class passed in kwargs to bind_state_fields method.

How to call transition from 2 statefields

Hello, love the design of this package thinking of integrating it with our exisitng app.

I tried following your example of having 2 state fields in a model

process.py

class ApprovalProc(BaseProcess):
    transitions = [
        Transition(action_name='approve', sources=['pending', 'awaiting_seller'], target='approved'),
        Transition(action_name='schedule', sources=['approved'], target='scheduled'),
        Transition(action_name='reject', sources=['pending', 'awaiting_seller'], target='rejected'),
        Transition(action_name='await_seller', sources=['pending'], target='awaiting_seller'),
        Transition(action_name='cancel', sources=['pending', 'approved'], target='cancelled'),
        # Action(action_name='update', side_effects=[]),
    ]
class AuctionProc(BaseProcess):
     transitions = [
        Transition(action_name='start', sources=['not_started', 'on_hold'], target='ongoing'),
        Transition(action_name='pause', sources=['ongoing',], target='on_hold'),
        Transition(action_name='end', sources=['ongoing',], target='ended'),
        Transition(action_name='void', sources=['not_started', 'on_hold', 'ongoing', 'ended'], target='voided'),

        # Action(action_name='update', side_effects=[update_data]),
    ]
ListingProcess = ProcessManager.bind_state_fields(listing_status=ApprovalProc,auction_status=AuctionProc )

class Listing(ListingProcess, models.Model):
    listing_status = models.CharField(choices=ApprovalProc.states, default='pending', max_length=100, blank=True)
    auction_status = models.CharField(choices=AuctionProc.states, default='not_started', max_length=100, blank=True)

When i try to play around with in the shell

l = Listing.objects.first()
l.process.approve()

I get this error

django_logic.exceptions.TransitionNotAllowed: Process class <class 'listings.process.AuctionProc'> has no transition with action name approve

transitions from the AuctionProc get called without any errors. So how do I call the other process?

Improve hash function

An object should be locked only for a particular state field.

It needs to make hash function more generic and avoid collisions with the same app, model and state field names. Also, take into considerations Proxy Models.
django_logic.transition.Transition._get_hash

Process and ProcessManager enhancements

  • default process name should be process, and could be overwritten.
  • e.g. s.process raises an exception django_logic.exceptions.TransitionNotAllowed: Transition not allowed

Add support for failure handlers

At the moment failure handlers are not implemented at all

  • Execute if a side effect task raises an exception
  • Multiple execution types (synchronous, asynchronous (Celery), etc

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.