Reputation: 47
We have an invoice numbering rule, which we would like to modify a bit.
Inside user settings, there's a setting that sets the user invoice numbering format, we can let the user to change there anything he wants, but we have an invoice creation page, inside the page what we only want to allow is to let the user to change the number to a bit higher.
For example:
Inside settings the rule is set to CN-002/2021
. Inside the invoice creation page the user tries to change the rule to CN-001/2021
, in this case we will throw an error because we won't like to allow this. If the user tries to change the rule to CN-003/2021
, we allow it.
NOTE: The user can't change anything else, for example, CZ-003/2021
or CN-001/2022
.
if old_invoice_no != new_invoice_no
CN-001/2021
and the new number is CN-002/2021
. For this case, we will pass, because we only allow the number to be HIGHER and never LOWER. If the new number is CN-000/2021
we will throw an error, because the number is lower.How can I check if the number is not lower?
This is the whole code:
def update(self, instance, validated_data):
old_invoice_no = instance.number # Output CN-002/2021
new_invoice_no = validated_data.get("number") # CN-001/2021
if old_invoice_no != new_invoice_no:
# .. Now the number has changed, how can we find the new number which was changed?
# The number which has changed is 001 to 002
# If the number format didn't match we throw an error
return ValidationError("msg_error_malformed_invoice_number_pattern")
# Everything seems good, we can update the instance
validated_data = self._update_validated_data(validated_data)
instance = super().update(instance, validated_data)
self._update_customer(validated_data, instance)
return instance
Upvotes: 0
Views: 71
Reputation: 756
You can just check the number is higher or lower by doing str.split()
a couple of times if the format of your invoice number doesn't change...
def update(self, instance, validated_data):
old_invoice_no = instance.number # Output CN-002/2021
new_invoice_no = validated_data.get("number") # CN-001/2021
if old_invoice_no != new_invoice_no:
if(int((new_invoice_no.split('/')[0]).split('-')[1]) < int((old_invoice_no.split('/')[0]).split('-')[1]) or (new_invoice_no.split('/')[0]).split('-')[0] != (old_invoice_no.split('/')[0]).split('-')[0] or new_invoice_no.split('/')[1] != old_invoice_no.split('/')[1]):
# New number invalid
return ValidationError("msg_error_malformed_invoice_number_pattern")
# Everything seems good, we can update the instance
validated_data = self._update_validated_data(validated_data)
instance = super().update(instance, validated_data)
self._update_customer(validated_data, instance)
return instance
if you are using earlier versions of python then you need to use string.atoi()
instead of the int()
cast inside the if
.
also the above only checks for what you specifically asked. This splits the string the same way multiple times but assuming the changes are not quite often. Should not be a bottleneck in your application.
Upvotes: 1
Reputation: 5560
Here is a working solution
import re
def validate(old, new):
ost, omid, oend = re.split("[-/]", old)
nst, nmid, nend = re.split("[-/]", new)
if ost != nst or oend != nend:
return False
elif int(nmid) < int(omid):
return False
else:
return True
x = "CN-001/2021"
y = "CN-000/2021"
print(validate(x, y))
# False
x = "CN-001/2021"
y = "CN-002/2021"
print(validate(x, y))
# True
Here, we split the string at both -
and /
,so "CN-001/2021"
becomes ["CN", "001", "2021"]
. I called the variable names start, middle, and end here (ost
for "old start", omid
for "old mid", etc...). This code then returns False
if the customer has entered an invalid entry, and True
if their input is valid.
I would suggest validating the middle number further. For example, you could ensure that:
nmid
has the same number of characters as omid
nmid
is composed entirely of digitsYou also may want to return a message from the validate
function to report back what actually went wrong with the validation (eg. "It is illegal to change the start of the invoice number").
You might also consider correcting some changes. For example, if the user tries to modify "CN"
to become "CZ"
but the input is otherwise valid, you might want to just accept their changes, but replace nst
with ost
. Going further, I would suggest not even allowing the user to enter the start and end portions of the invoice number and instead, just ask them to enter a new number num
and then creating the new invoice number as f"{ost}-{num}/{oend}"
Upvotes: 1