0

I have an Order model which has a field status which has choices -> NEW (default), PENDING(PDG), DISPATCHED(DSP), COMPLETED(CMP), CANCELLED(CLD)

models.py

class Order(Address, TimeStampedUUIDModel):

    status = FSMField(
        max_length=25,
        choices=constants.STATUS_CHOICES,
        default=constants.NEW,
    )

    @transition(field=status, source=constants.NEW, target=constants.PDG)
    def to_pending(self):
        self.status = constants.PDG


    @transition(field=status, source=constants.PDG, target=constants.DSP)
    def to_dispatched(self):
        self.status = constants.DSP


    @transition(field=status, source=constants.DSP, target=constants.CMP)
    def to_completed(self):
        self.status = constants.CMP


    @transition(
        field=status,
        source=[constants.NEW, constants.PDG, constants.DSP],
        target=constants.CLD,
    )
    def to_cancel(self):
        self.status = constants.CLD

serializers.py

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Order
        fields = "__all__"
        read_only_fields = [--all fields except status--]

    def update(self, instance, validated_data):
        status = validated_data.pop("status", None)
        agent =  self.context['request'].user
        instance = services.status_function(status, instance, agent)
        return instance

In the below services file I'm simultaneously trying to create an order activity object to track changes in Order object. services.py

def status_function(status, instance, agent):
    if status is not None:
        switcher = {
            constants.PDG : instance.to_pending,
            constants.DSP : instance.to_dispatched,
            constants.CMP : instance.to_completed,
            constants.CLD : instance.to_cancel
        }
        func = switcher.get(status, None)
        try:
            func()
            models.OrderActivity.objects.create(
                event_name=status,
                order = instance,
                event = f"Order {status}",
                agent = agent,
                time = instance.modified_at
            )
        except TransitionNotAllowed :
            print("Exception Caught")
            raise exceptions.BadRequest([{"error": "Transition not allowed"}])

    return instance

constants.py

from extended_choices import Choices

## Order Status
NEW, NEW_ = "NEW", "NEW"
PDG, PDG_ = "PDG", "PENDING"
DSP, DSP_ = "DSP", "DISPATCHED"
CMP, CMP_ = "CMP", "COMPLETED"
CLD, CLD_ = "CLD", "CANCELLED"

STATUS_CHOICES = ( 
    (NEW, NEW_), 
    (PDG, PDG_), 
    (DSP, DSP_), 
    (CMP, CMP_),
    (CLD, CLD_),
)

My problem is that transitions other than NEW -> PDG, NEW -> CLD, and PDG -> CLD are raising an exception and also reverting the status of Order object to NEW which should not happen. Thanks in advance !!!!

Encrypto123
  • 129
  • 3
  • 9

1 Answers1

0

Remove assignment from every transition function

Change every transition function to:

    def to_completed(self):
            return

Since the states are changed by calling the function themselves. but not changed in database. So we only need to save the instance itself. Below func() in services.py put

instance.save()

Encrypto123
  • 129
  • 3
  • 9