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 !!!!
Remove assignment from every transition function
Change every transition function to:
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()