-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cash register tracking #18
Cash register tracking #18
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #18 +/- ##
===========================================
+ Coverage 86.79% 87.69% +0.89%
===========================================
Files 71 73 +2
Lines 2204 2381 +177
Branches 114 125 +11
===========================================
+ Hits 1913 2088 +175
Misses 275 275
- Partials 16 18 +2
Continue to review full report at Codecov.
|
WalletCorrection model could have a |
src/wallet/api.py
Outdated
@@ -24,6 +24,16 @@ def get_balance(owner_id, currency): | |||
return wallet_obj, wallet_obj.balance | |||
|
|||
|
|||
def set_balance(owner_id, new_balance, reference=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function should probably be decorated with @transaction.atomic. We want to avoid possible race conditions (no other wallet transactions should be able to sneak in between get_balance
and withdraw
/deposit
).
src/foobar/admin.py
Outdated
def has_add_permission(self, request): | ||
return False | ||
|
||
def get_form(self, request, obj=None, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug code? Should be cleaned up.
src/foobar/api.py
Outdated
amount=-amount, | ||
reference=reference | ||
) | ||
trx = 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No hardcoded values. Should be replaced with fobar.enums.TrxType.WITHDRAW
. The same applies to the other occurrences of hardcoded values in this function.
src/foobar/forms.py
Outdated
data = self.cleaned_data['deposit_or_withdraw'] | ||
wallet, balance = api.get_balance(self.owner_id) | ||
if data.amount < 0 and -data > balance: | ||
raise forms.ValidationError("Not enough founds") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The string should be translated using following method: https://docs.djangoproject.com/en/1.10/topics/i18n/translation/#internationalization-in-python-code. Also, the convention in our codebase is to use single quotes for strings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
founds
is misspelled, should be funds
src/foobar/models.py
Outdated
@@ -86,3 +86,24 @@ def total(self): | |||
|
|||
def __str__(self): | |||
return str(self.id) | |||
|
|||
|
|||
class WalletCorrection(UUIDModel, TimeStampedModel): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name could probably be improved. What are we representing here actually? It seems that it can be both either correction or withdrawal/deposit. The name should reflect that.
{% csrf_token %} | ||
{{ form_class.as_p }} | ||
</div> | ||
<input type="submit" name="save_correction" action="" id="correction_save" style="float:right"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What function does "action" have on the input field?
src/foobar/tests/test_api.py
Outdated
) | ||
self.assertEqual(correction_obj.wallet.owner_id, wallet_obj.owner_id) | ||
self.assertEqual(correction_obj.trx_type.value, 0) | ||
self.assertEqual(correction_obj.post_balance.amount, 1000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really right? You set the balance of the wallet to 1200 in your call on row 211, but the post_balance
is 1000. Shouldn't be 1200?
src/foobar/tests/test_api.py
Outdated
) | ||
self.assertEqual(correction_obj.wallet.owner_id, wallet_obj.owner_id) | ||
self.assertEqual(correction_obj.trx_type.value, 1) | ||
self.assertEqual(correction_obj.post_balance.amount, 1000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your initial balance is 1000 SEK. You deposit 100 SEK. The post_balance
should be 1100 SEK.
src/foobar/tests/test_api.py
Outdated
owner_id=wallet_obj.owner_id | ||
) | ||
self.assertEqual(correction_obj.wallet.owner_id, wallet_obj.owner_id) | ||
self.assertEqual(correction_obj.trx_type.value, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those should not be hardcoded. Use enums.TrxType.DEPOSIT
instead,
src/foobar/enums.py
Outdated
class TrxType(enum.Enum): | ||
CORRECTION = 0 | ||
DEPOSIT = 1 | ||
WITHDRAW = 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we follow @kjagiello's idea of changing the name for WalletCorrection
the name here might be appropriate to change as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WITHDRAW
should probably be changed too from being a verb to a noun: WITHDRAWAL
.
import uuid | ||
|
||
|
||
class Migration(migrations.Migration): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens with old transactions that exist in the system?
I assume that each new transaction will generate a Correction/Log but should/can we generate an instance for the old ones?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are no old correction transactions, so no data migration is needed.
|
||
|
||
@transaction.atomic | ||
def calculate_correction(new_balance, owner_id, user, reference=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm the reference
should be saved only in WalletCorrection
. Then WalletCorrect.id
should be saved as reference in WalletTransaction
. That way, WalletTransactions can be traced back to specific WalletCorrections.
The code is not compatible with Django 1.9 anymore, but I don't think it is an issue. I've got some changes in workings that are not compatible with Django 1.9 and as we are the only ones using this project at the moment, I propose we drop the 1.9 compatibility. |
Codecov Report
@@ Coverage Diff @@
## develop #18 +/- ##
===========================================
+ Coverage 86.88% 87.71% +0.83%
===========================================
Files 71 73 +2
Lines 2218 2410 +192
Branches 115 126 +11
===========================================
+ Hits 1927 2114 +187
- Misses 275 278 +3
- Partials 16 18 +2
Continue to review full report at Codecov.
|
src/foobar/admin.py
Outdated
'pre_balance' | ||
) | ||
ordering = ('-date_created',) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add a Meta-class here and specify verbose_name
and verbose_name_plural
.
src/foobar/admin.py
Outdated
@@ -192,6 +192,25 @@ def changelist_view(self, request, extra_context=None): | |||
return response | |||
|
|||
|
|||
@admin.register(models.WalletLogEntry) | |||
class WalletLogEntryAdmin(admin.ModelAdmin): | |||
list_display = ('date_created', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -192,6 +192,25 @@ def changelist_view(self, request, extra_context=None): | |||
return response | |||
|
|||
|
|||
@admin.register(models.WalletLogEntry) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…anged so wallet_correction ID is saved in wallet transaction as reference
src/wallet/api.py
Outdated
@@ -29,10 +29,10 @@ def set_balance(owner_id, new_balance, reference=None): | |||
wallet, old_balance = get_balance(owner_id, new_balance.currency) | |||
difference = new_balance - old_balance | |||
if difference.amount < 0: | |||
withdraw(owner_id, -difference, reference) | |||
return withdraw(owner_id, -difference, reference), difference |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second return value should be -difference
to become identical to the object's amount
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is actually correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind. My mistake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is okay. No problem.
src/foobar/admin.py
Outdated
) | ||
readonly_fields = list_display |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should keep the comment
field writeable? To avoid cluttering the timeline by forcing any spelling mistakes or similar to updated by creating a new log entry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea 👍🏻
…redit wallet and added colors to wallet log entry change list
src/foobar/forms.py
Outdated
|
||
class CorrectionForm(forms.Form): | ||
balance = MoneyField(label='Balance', min_value=0) | ||
comment = forms.CharField(label='Comment', max_length=250, required=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The max length of the comment field should reflect the max length of the corresponding database field.
src/foobar/admin.py
Outdated
'amount', | ||
'post_balance' | ||
) | ||
readonly_fields = list_display |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍 |
src/foobar/models.py
Outdated
@@ -92,7 +92,7 @@ class WalletLogEntry(UUIDModel, TimeStampedModel): | |||
user = models.ForeignKey(User, null=True, blank=True) | |||
trx_type = EnumIntegerField(enums.TrxType, | |||
default=enums.TrxType.CORRECTION) | |||
wallet = models.ForeignKey('wallet.Wallet', related_name='log_entries') | |||
wallet = models.ForeignKey('wallet.Wallet', related_name='log_entries', editable=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a heads up, because settings editable=False
should trigger a migration. In case it does, we are missing a migration file, test running python manage.py makemigrations
to see if it generates a new migration file.
For the admin panel, if you haven't figured it out already, the same effect as setting editable=False
here would be applied by including the field in the ModelAdmins readonly_fields
.
No description provided.