From cc18786027019722961dc45374f8b719b0d8bf30 Mon Sep 17 00:00:00 2001 From: Aditya Anand M C Date: Wed, 20 May 2020 19:42:13 +0530 Subject: [PATCH] chore: bounty fulfilment changes (#6670) * chore: bounty fulfilment changes - remove fields which aren't needed from bounty submission UI - make fulfiller_email, fulfiller_name into a prop - remove fulfiller_github_username - update code references which use the removed db fields * create migrations * fix tests --- app/app/fixtures/dashboard.json | 55 +------------------ app/assets/v2/js/pages/change_bounty.js | 2 +- app/assets/v2/js/pages/fulfill_bounty/ETH.js | 2 - .../v2/js/pages/fulfill_bounty/index.js | 3 - .../v2/js/pages/fulfill_bounty/token.js | 2 - app/dashboard/admin.py | 4 +- app/dashboard/helpers.py | 12 +--- .../migrations/0111_auto_20200520_0457.py | 25 +++++++++ app/dashboard/models.py | 24 ++++---- app/dashboard/router.py | 10 ++-- app/dashboard/templates/bounty/details2.html | 3 +- app/dashboard/templates/bounty/fulfill.html | 9 +-- app/dashboard/templates/shared/reserved.html | 4 +- app/dashboard/tests/test_dashboard_models.py | 3 - app/dashboard/tests/test_users_list.py | 6 -- app/dashboard/views.py | 22 +++----- app/dataviz/d3_views.py | 6 +- .../commands/assemble_leaderboards.py | 4 +- .../commands/test_assemble_leaderboards.py | 11 +--- .../management/commands/test_expiration.py | 12 ++-- .../management/commands/test_sync_keywords.py | 26 ++++++--- ...c_pull_request_with_bounty_fulfillments.py | 12 ++-- .../tests/test_mail_funder_payout_reminder.py | 3 - app/retail/emails.py | 3 +- scripts/debug/hackathon_export.py | 2 +- 25 files changed, 100 insertions(+), 165 deletions(-) create mode 100644 app/dashboard/migrations/0111_auto_20200520_0457.py diff --git a/app/app/fixtures/dashboard.json b/app/app/fixtures/dashboard.json index 9a21a9b4754..c52fb2777ce 100644 --- a/app/app/fixtures/dashboard.json +++ b/app/app/fixtures/dashboard.json @@ -5803,9 +5803,6 @@ "created_on": "2019-06-09T18:31:03.534Z", "modified_on": "2019-06-09T18:31:03.536Z", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", - "fulfiller_email": "", - "fulfiller_github_username": "test3", - "fulfiller_name": "", "fulfiller_metadata": { "id": 0, "data": { @@ -5849,9 +5846,6 @@ "created_on": "2019-06-09T18:31:12.409Z", "modified_on": "2019-06-09T18:31:12.411Z", "fulfiller_address": "0xeDa95eD3e3436C689376889F9eD0a8f4bA23E866", - "fulfiller_email": "octavioamuchastegui@gmail.com", - "fulfiller_github_username": "octavioamu", - "fulfiller_name": "", "fulfiller_metadata": { "id": 0, "data": { @@ -5895,9 +5889,6 @@ "created_on": "2019-06-09T18:31:07.439Z", "modified_on": "2019-06-09T19:00:10.461Z", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", - "fulfiller_email": "", - "fulfiller_github_username": "test4", - "fulfiller_name": "", "fulfiller_metadata": { "id": 0, "data": { @@ -5941,9 +5932,6 @@ "created_on": "2019-06-09T18:31:07.446Z", "modified_on": "2019-06-09T19:00:10.479Z", "fulfiller_address": "0xCC4b3DE30576E161C8632786560Fa7DD3Fb33f77", - "fulfiller_email": "", - "fulfiller_github_username": "test5", - "fulfiller_name": "", "fulfiller_metadata": { "id": 1, "data": { @@ -5987,9 +5975,6 @@ "created_on": "2019-06-09T18:31:07.452Z", "modified_on": "2019-06-09T19:00:10.496Z", "fulfiller_address": "0x0B8C767a91DdbE99ABA14685d03B14D4265c1E5B", - "fulfiller_email": "", - "fulfiller_github_username": "owocki", - "fulfiller_name": "", "fulfiller_metadata": { "id": 2, "data": { @@ -6033,9 +6018,6 @@ "created_on": "2019-06-09T18:31:07Z", "modified_on": "2019-06-10T09:49:45.646Z", "fulfiller_address": "0xBcAfdD642118e5536024675e776d32413728dd08", - "fulfiller_email": "", - "fulfiller_github_username": "test3", - "fulfiller_name": "", "fulfiller_metadata": { "id": 3, "data": { @@ -6079,9 +6061,6 @@ "created_on": "2019-06-09T18:31:07Z", "modified_on": "2019-06-10T09:49:38.760Z", "fulfiller_address": "0xCC4b3DE30576E161C8632786560Fa7DD3Fb33f77", - "fulfiller_email": "", - "fulfiller_github_username": "test10", - "fulfiller_name": "", "fulfiller_metadata": { "id": 4, "data": { @@ -6125,9 +6104,6 @@ "created_on": "2019-06-10T09:41:33Z", "modified_on": "2019-06-10T09:42:42.114Z", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", - "fulfiller_email": "", - "fulfiller_github_username": "", - "fulfiller_name": "", "fulfiller_metadata": {}, "fulfillment_id": null, "fulfiller_hours_worked": null, @@ -6146,9 +6122,6 @@ "created_on": "2019-06-10T09:42:47Z", "modified_on": "2019-06-10T09:43:16.481Z", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", - "fulfiller_email": "", - "fulfiller_github_username": "", - "fulfiller_name": "", "fulfiller_metadata": {}, "fulfillment_id": null, "fulfiller_hours_worked": null, @@ -6167,9 +6140,6 @@ "created_on": "2019-06-10T09:43:34Z", "modified_on": "2019-06-10T09:44:16.848Z", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", - "fulfiller_email": "", - "fulfiller_github_username": "", - "fulfiller_name": "", "fulfiller_metadata": {}, "fulfillment_id": null, "fulfiller_hours_worked": null, @@ -6188,9 +6158,6 @@ "created_on": "2019-06-10T09:44:29Z", "modified_on": "2019-06-10T09:45:03.943Z", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", - "fulfiller_email": "", - "fulfiller_github_username": "", - "fulfiller_name": "", "fulfiller_metadata": {}, "fulfillment_id": null, "fulfiller_hours_worked": null, @@ -6209,9 +6176,6 @@ "created_on": "2019-06-10T09:52:43Z", "modified_on": "2019-06-10T09:53:12.807Z", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", - "fulfiller_email": "", - "fulfiller_github_username": "", - "fulfiller_name": "", "fulfiller_metadata": {}, "fulfillment_id": null, "fulfiller_hours_worked": null, @@ -6230,9 +6194,6 @@ "created_on": "2019-06-27T01:08:08.620Z", "modified_on": "2019-06-27T01:08:08.625Z", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", - "fulfiller_email": "", - "fulfiller_github_username": "test4", - "fulfiller_name": "", "fulfiller_metadata": { "id": 0, "data": { @@ -6276,9 +6237,6 @@ "created_on": "2019-06-27T01:08:08.635Z", "modified_on": "2019-06-27T01:08:08.640Z", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", - "fulfiller_email": "", - "fulfiller_github_username": "test4", - "fulfiller_name": "", "fulfiller_metadata": { "id": 1, "data": { @@ -6322,9 +6280,6 @@ "created_on": "2019-06-30T19:27:18.223Z", "modified_on": "2019-06-30T19:27:18.234Z", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", - "fulfiller_email": "", - "fulfiller_github_username": "test8", - "fulfiller_name": "", "fulfiller_metadata": { "id": 0, "data": { @@ -7321,9 +7276,7 @@ "id": 19, "accepted": false, "accepted_on": "None", - "fulfiller_name": "", "fulfillment_id": 1, - "fulfiller_email": "", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", "fulfiller_metadata": { "id": 1, @@ -7352,8 +7305,7 @@ "fulfiller": "0x27FC067c91f1bA562C7978920722B07B70122897" }, "fulfiller_github_url": "", - "fulfiller_hours_worked": "20.00", - "fulfiller_github_username": "test4" + "fulfiller_hours_worked": "20.00" } }, "needs_review": false @@ -7595,9 +7547,7 @@ "id": 20, "accepted": false, "accepted_on": "None", - "fulfiller_name": "", "fulfillment_id": 0, - "fulfiller_email": "", "fulfiller_address": "0x27FC067c91f1bA562C7978920722B07B70122897", "fulfiller_metadata": { "id": 0, @@ -7626,8 +7576,7 @@ "fulfiller": "0x27FC067c91f1bA562C7978920722B07B70122897" }, "fulfiller_github_url": "", - "fulfiller_hours_worked": "100.00", - "fulfiller_github_username": "test8" + "fulfiller_hours_worked": "100.00" } }, "needs_review": false diff --git a/app/assets/v2/js/pages/change_bounty.js b/app/assets/v2/js/pages/change_bounty.js index 1312ddb62ff..00db9e50a22 100644 --- a/app/assets/v2/js/pages/change_bounty.js +++ b/app/assets/v2/js/pages/change_bounty.js @@ -131,7 +131,7 @@ const getSuggestions = () => { } obj.children.forEach(children => { - children.text = children.fulfiller_github_username || children.user__profile__handle; + children.text = children.profile__handle || children.user__profile__handle; children.id = generalIndex; generalIndex++; }); diff --git a/app/assets/v2/js/pages/fulfill_bounty/ETH.js b/app/assets/v2/js/pages/fulfill_bounty/ETH.js index 1573ff7fba5..e4b2394109a 100644 --- a/app/assets/v2/js/pages/fulfill_bounty/ETH.js +++ b/app/assets/v2/js/pages/fulfill_bounty/ETH.js @@ -24,7 +24,6 @@ const ethFulfillBounty = data => { loading_button($('.js-submit')); const githubUsername = data.githubUsername; const issueURL = data.issueURL; - const notificationEmail = data.notificationEmail; const githubPRLink = data.githubPRLink; const hoursWorked = data.hoursWorked; const address = data.payoutAddress; @@ -46,7 +45,6 @@ const ethFulfillBounty = data => { fulfiller: { githubPRLink: githubPRLink, hoursWorked: hoursWorked, - email: notificationEmail, githubUsername: githubUsername, address: address }, diff --git a/app/assets/v2/js/pages/fulfill_bounty/index.js b/app/assets/v2/js/pages/fulfill_bounty/index.js index d516d60975a..937f604d2fb 100644 --- a/app/assets/v2/js/pages/fulfill_bounty/index.js +++ b/app/assets/v2/js/pages/fulfill_bounty/index.js @@ -17,9 +17,6 @@ window.onload = function() { $('input[name=githubUsername]').val(localStorage['githubUsername']); } } - if (typeof localStorage['notificationEmail'] != 'undefined') { - $('input[name=notificationEmail]').val(localStorage['notificationEmail']); - } if (getParam('source')) { $('input[name=issueURL]').val(getParam('source')); } diff --git a/app/assets/v2/js/pages/fulfill_bounty/token.js b/app/assets/v2/js/pages/fulfill_bounty/token.js index 3c62cbd3120..e6be061e14e 100644 --- a/app/assets/v2/js/pages/fulfill_bounty/token.js +++ b/app/assets/v2/js/pages/fulfill_bounty/token.js @@ -20,7 +20,6 @@ fulfillBounty = data => { 'data': { 'payload': { 'fulfiller': { - 'email': data.notificationEmail, 'address': data.payoutAddress, 'hoursWorked': data.hoursWorked, 'githubPRLink': data.githubPRLink @@ -33,7 +32,6 @@ fulfillBounty = data => { const params = { 'issueURL': data.issueURL, - 'email': data.notificationEmail, 'githubPRLink': data.githubPRLink, 'hoursWorked': data.hoursWorked, 'metadata': JSON.stringify(metadata), diff --git a/app/dashboard/admin.py b/app/dashboard/admin.py index d44b5953f62..1bdbce43a3b 100644 --- a/app/dashboard/admin.py +++ b/app/dashboard/admin.py @@ -39,10 +39,10 @@ class BountyEventAdmin(admin.ModelAdmin): class BountyFulfillmentAdmin(admin.ModelAdmin): raw_id_fields = ['bounty', 'profile'] + readonly_fields = ['fulfiller_github_username'] list_display = ['id', 'bounty', 'profile', 'fulfiller_github_url'] search_fields = [ - 'fulfiller_address', 'fulfiller_email', 'fulfiller_github_username', - 'fulfiller_name', 'fulfiller_metadata', 'fulfiller_github_url' + 'fulfiller_address', 'fulfiller_metadata', 'fulfiller_github_url' ] ordering = ['-id'] diff --git a/app/dashboard/helpers.py b/app/dashboard/helpers.py index 3fb65f7b90b..3e3e18d4a85 100644 --- a/app/dashboard/helpers.py +++ b/app/dashboard/helpers.py @@ -350,10 +350,6 @@ def handle_bounty_fulfillments(fulfillments, new_bounty, old_bounty): try: created_on = timezone.now() modified_on = timezone.now() - fulfiller_email = fulfillment.get('data', {}).get( - 'payload', {}).get('fulfiller', {}).get('email', '') - fulfiller_name = fulfillment.get('data', {}).get( - 'payload', {}).get('fulfiller', {}).get('name', '') fulfiller_github_url = fulfillment.get('data', {}).get( 'payload', {}).get('fulfiller', {}).get('githubPRLink', '') hours_worked = fulfillment.get('data', {}).get( @@ -372,9 +368,6 @@ def handle_bounty_fulfillments(fulfillments, new_bounty, old_bounty): tenant = 'ETH', token_name=new_bounty.token_name, fulfiller_address=fulfiller_address, - fulfiller_email=fulfiller_email, - fulfiller_github_username=github_username, - fulfiller_name=fulfiller_name, fulfiller_metadata=fulfillment, fulfillment_id=fulfillment.get('id'), fulfiller_github_url=fulfiller_github_url, @@ -767,7 +760,6 @@ def get_fulfillment_data_for_activity(fulfillment): 'fulfiller_address': fulfillment.fulfiller_address, 'fulfiller_email': fulfillment.fulfiller_email, 'fulfiller_github_username': fulfillment.fulfiller_github_username, - 'fulfiller_name': fulfillment.fulfiller_name, 'fulfiller_metadata': fulfillment.fulfiller_metadata, 'fulfillment_id': fulfillment.fulfillment_id, 'fulfiller_hours_worked': str(fulfillment.fulfiller_hours_worked), @@ -823,9 +815,9 @@ def record_bounty_activity(event_name, old_bounty, new_bounty, _fulfillment=None if event_name == 'work_done': fulfillment = new_bounty.fulfillments.filter(accepted=True).latest('fulfillment_id') if fulfillment: - user_profile = Profile.objects.filter(handle=fulfillment.fulfiller_github_username.lower()).first() + user_profile = Profile.objects.filter(handle=fulfillment.profile__handle.lower()).first() if not user_profile: - user_profile = sync_profile(fulfillment.fulfiller_github_username) + user_profile = sync_profile(fulfillment.profile__handle) except Exception as e: logger.error(f'{e} during record_bounty_activity for {new_bounty}') diff --git a/app/dashboard/migrations/0111_auto_20200520_0457.py b/app/dashboard/migrations/0111_auto_20200520_0457.py new file mode 100644 index 00000000000..d3d78437f73 --- /dev/null +++ b/app/dashboard/migrations/0111_auto_20200520_0457.py @@ -0,0 +1,25 @@ +# Generated by Django 2.2.4 on 2020-05-20 04:57 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('dashboard', '0110_auto_20200519_1417'), + ] + + operations = [ + migrations.RemoveField( + model_name='bountyfulfillment', + name='fulfiller_email', + ), + migrations.RemoveField( + model_name='bountyfulfillment', + name='fulfiller_github_username', + ), + migrations.RemoveField( + model_name='bountyfulfillment', + name='fulfiller_name', + ), + ] diff --git a/app/dashboard/models.py b/app/dashboard/models.py index d4c80ce3d42..9843e3a8089 100644 --- a/app/dashboard/models.py +++ b/app/dashboard/models.py @@ -745,7 +745,7 @@ def keywords_list(self): @property def fulfillers_handles(self): - bounty_fulfillers = self.fulfillments.filter(accepted=True).values_list('fulfiller_github_username', flat=True) + bounty_fulfillers = self.fulfillments.filter(accepted=True).values_list('profile__handle', flat=True) tip_fulfillers = self.tips.values_list('username', flat=True) return list(bounty_fulfillers) + list(tip_fulfillers) @@ -1362,12 +1362,6 @@ class BountyFulfillment(SuperModel): profile = models.ForeignKey('dashboard.Profile', related_name='fulfilled', on_delete=models.CASCADE, null=True, help_text="fulfillers's profile") funder_profile = models.ForeignKey('dashboard.Profile', null=True, on_delete=models.CASCADE, help_text="funder's profile") - # TODO: MAKE AS PROP - fulfiller_email = models.CharField(max_length=255, blank=True) - # TODO: MAKE AS PROP - fulfiller_github_username = models.CharField(max_length=255, blank=True) - # TODO: MAKE AS PROP - fulfiller_name = models.CharField(max_length=255, blank=True) # TODO: rename to hours_worked fulfiller_hours_worked = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=50) @@ -1398,17 +1392,22 @@ def __str__(self): """ return f'BountyFulfillment ID: ({self.pk}) - Bounty ID: ({self.bounty.pk})' - def save(self, *args, **kwargs): - """Define custom handling for saving bounty fulfillments.""" - if self.fulfiller_github_username: - self.fulfiller_github_username = self.fulfiller_github_username.lstrip('@') - super().save(*args, **kwargs) + + @property + def fulfiller_email(self): + return self.profile.email + + + @property + def fulfiller_github_username(self): + return self.profile.handle @property def should_hide(self): return self.fulfiller_github_username in settings.BLOCKED_USERS + @property def to_json(self): """Define the JSON representation of BountyFulfillment. @@ -1422,7 +1421,6 @@ def to_json(self): 'bounty_id': self.bounty.pk, 'email': self.fulfiller_email, 'githubUsername': self.fulfiller_github_username, - 'name': self.fulfiller_name, 'payout_status': self.payout_status, 'payout_amount': self.payout_amount, 'token_name': self.token_name, diff --git a/app/dashboard/router.py b/app/dashboard/router.py index 99732137121..ef08584c804 100644 --- a/app/dashboard/router.py +++ b/app/dashboard/router.py @@ -39,12 +39,14 @@ class BountyFulfillmentSerializer(serializers.ModelSerializer): """Handle serializing the BountyFulfillment object.""" profile = ProfileSerializer() + fulfiller_email = serializers.ReadOnlyField() + fulfiller_github_username = serializers.ReadOnlyField() class Meta: """Define the bounty fulfillment serializer metadata.""" model = BountyFulfillment - fields = ('pk', 'fulfiller_address', - 'fulfiller_github_username', 'fulfiller_name', 'fulfiller_metadata', + fields = ('pk', 'fulfiller_email', 'fulfiller_address', + 'fulfiller_github_username', 'fulfiller_metadata', 'fulfillment_id', 'accepted', 'profile', 'created_on', 'accepted_on', 'fulfiller_github_url', 'payout_tx_id', 'payout_amount', 'token_name', 'payout_status') @@ -349,13 +351,13 @@ def get_queryset(self): # Retrieve all fullfilled bounties by fulfiller_username if 'fulfiller_github_username' in param_keys: queryset = queryset.filter( - fulfillments__fulfiller_github_username__iexact=self.request.query_params.get('fulfiller_github_username') + fulfillments__profile__handle__iexact=self.request.query_params.get('fulfiller_github_username') ) # Retrieve all DONE fullfilled bounties by fulfiller_username if 'fulfiller_github_username_done' in param_keys: queryset = queryset.filter( - fulfillments__fulfiller_github_username__iexact=self.request.query_params.get('fulfiller_github_username'), + fulfillments__profile__handle__iexact=self.request.query_params.get('fulfiller_github_username'), fulfillments__accepted=True, ) diff --git a/app/dashboard/templates/bounty/details2.html b/app/dashboard/templates/bounty/details2.html index 171ab167915..5050a041cd3 100644 --- a/app/dashboard/templates/bounty/details2.html +++ b/app/dashboard/templates/bounty/details2.html @@ -368,8 +368,7 @@
{% trans "SUBMISSIONS" %}

- - + [[ fulfillment.fulfiller_github_username | capitalize ]]

diff --git a/app/dashboard/templates/bounty/fulfill.html b/app/dashboard/templates/bounty/fulfill.html index 3ccf5228bdf..c8632e050c5 100644 --- a/app/dashboard/templates/bounty/fulfill.html +++ b/app/dashboard/templates/bounty/fulfill.html @@ -96,19 +96,14 @@

{% trans "Submit Work" %}

-
+
-
- - +
{% if show_information_publicly_checkbox %} {% include "shared/show_information_publicly.html" with id="show_email_publicly" %} {% endif %} diff --git a/app/dashboard/templates/shared/reserved.html b/app/dashboard/templates/shared/reserved.html index 8fab9f4669a..4f3b7d7e305 100644 --- a/app/dashboard/templates/shared/reserved.html +++ b/app/dashboard/templates/shared/reserved.html @@ -51,8 +51,8 @@
{% for contributor in suggested_developers %}
  • - - {{ contributor.fulfiller_github_username }} + + {{ contributor.profile__handle }}
  • {% endfor %} diff --git a/app/dashboard/tests/test_dashboard_models.py b/app/dashboard/tests/test_dashboard_models.py index 50861b799e7..1598c02122f 100644 --- a/app/dashboard/tests/test_dashboard_models.py +++ b/app/dashboard/tests/test_dashboard_models.py @@ -75,9 +75,6 @@ def test_bounty(): ) bounty_fulfillment = BountyFulfillment.objects.create( fulfiller_address='0x0000000000000000000000000000000000000000', - fulfiller_email='', - fulfiller_github_username='fred', - fulfiller_name='Fred', bounty=bounty, profile=fulfiller_profile, ) diff --git a/app/dashboard/tests/test_users_list.py b/app/dashboard/tests/test_users_list.py index c04b1641d3d..8dae3d04f24 100644 --- a/app/dashboard/tests/test_users_list.py +++ b/app/dashboard/tests/test_users_list.py @@ -58,9 +58,6 @@ def setup_bounties(): BountyFulfillment.objects.create( fulfiller_address='0x0000000000000000000000000000000000000000', - fulfiller_email='fred@bar.com', - fulfiller_github_username='user1', - fulfiller_name='Fred', accepted=True, bounty=Bounty.objects.first(), profile=User.objects.filter(username='user1').first().profile @@ -68,9 +65,6 @@ def setup_bounties(): BountyFulfillment.objects.create( fulfiller_address='0x0000000000000000000000000000000000000000', - fulfiller_email='fred@bar.com', - fulfiller_github_username='user19', - fulfiller_name='Fred', accepted=True, bounty=Bounty.objects.last(), profile=User.objects.last().profile diff --git a/app/dashboard/views.py b/app/dashboard/views.py index d106aae2c6e..fa6283f14e3 100644 --- a/app/dashboard/views.py +++ b/app/dashboard/views.py @@ -1060,7 +1060,7 @@ def previous_worked(): filter=Q( bounties_funded__fulfillments__bounty__network=network, bounties_funded__fulfillments__accepted=True, - bounties_funded__fulfillments__fulfiller_github_username=current_user.profile.handle + bounties_funded__fulfillments__profile__handle=current_user.profile.handle ) ) @@ -1965,7 +1965,7 @@ def funder_payout_reminder(request, bounty_network, stdbounties_id): except Bounty.DoesNotExist: raise Http404 - has_fulfilled = bounty.fulfillments.filter(fulfiller_github_username=github_user_data['login']).count() + has_fulfilled = bounty.fulfillments.filter(profile__handle=github_user_data['login']).count() if has_fulfilled == 0: return JsonResponse({ 'success': False, @@ -3200,7 +3200,7 @@ def new_bounty(request): .filter( bounty__bounty_owner_github_username__iexact=request.user.profile.handle, bounty__idx_status='done' - ).values('fulfiller_github_username', 'profile__id').annotate(fulfillment_count=Count('bounty')) \ + ).values('profile__handle', 'profile__id').annotate(fulfillment_count=Count('bounty')) \ .order_by('-fulfillment_count')[:5] bounty_params = { 'newsletter_headline': _('Be the first to know about new funded issues.'), @@ -3252,7 +3252,7 @@ def get_suggested_contributors(request): .filter( bounty__bounty_owner_github_username__iexact=request.user.profile.handle, bounty__idx_status='done' - ).values('fulfiller_github_username', 'profile__id').annotate(fulfillment_count=Count('bounty')) \ + ).values('profile__handle', 'profile__id').annotate(fulfillment_count=Count('bounty')) \ .order_by('-fulfillment_count') keywords_filter = Q() @@ -3262,9 +3262,9 @@ def get_suggested_contributors(request): Q(bounty__issue_description__icontains=keyword) recommended_developers = BountyFulfillment.objects.prefetch_related('bounty', 'profile') \ - .filter(keywords_filter).values('fulfiller_github_username', 'profile__id') \ - .exclude(fulfiller_github_username__isnull=True) \ - .exclude(fulfiller_github_username__exact='').distinct()[:10] + .filter(keywords_filter).values('profile__handle', 'profile__id') \ + .exclude(profile__handle__isnull=True) \ + .exclude(profile__handle__exact='').distinct()[:10] verified_developers = UserVerificationModel.objects.filter(verified=True).values('user__profile__handle', 'user__profile__id') @@ -4909,11 +4909,6 @@ def fulfill_bounty_v1(request): response['message'] = 'error: missing fulfiller_address' return JsonResponse(response) - fulfiller_email = request.POST.get('email') - if not fulfiller_email: - response['message'] = 'error: missing email' - return JsonResponse(response) - hours_worked = request.POST.get('hoursWorked') if not hours_worked or not hours_worked.isdigit(): response['message'] = 'error: missing hoursWorked' @@ -4947,13 +4942,10 @@ def fulfill_bounty_v1(request): fulfillment.modified_on = now fulfillment.funder_last_notified_on = now fulfillment.token_name = bounty.token_name - fulfillment.fulfiller_github_username = profile.handle - # fulfillment.fulfiller_name ETC-TODO: REMOVE ? # fulfillment.fulfillment_id ETC-TODO: REMOVE ? fulfillment.fulfiller_address = fulfiller_address - fulfillment.fulfiller_email = fulfiller_email fulfillment.fulfiller_hours_worked = hours_worked fulfillment.fulfiller_github_url = fulfiller_github_url diff --git a/app/dataviz/d3_views.py b/app/dataviz/d3_views.py index d9c3c980d94..f1d0c6470ff 100644 --- a/app/dataviz/d3_views.py +++ b/app/dataviz/d3_views.py @@ -636,13 +636,13 @@ def viz_draggable(request, key='email_open'): bfs = BountyFulfillment.objects.filter(accepted=True) limit = 50 usernames = list( - bfs.exclude(fulfiller_github_username='' - ).distinct('fulfiller_github_username').values_list('fulfiller_github_username', flat=True) + bfs.exclude(profile__handle='' + ).distinct('profile__handle').values_list('profile__handle', flat=True) )[0:limit] if request.GET.get('data'): output = [] for username in usernames: - these_bounties = bfs.filter(fulfiller_github_username=username) + these_bounties = bfs.filter(profile__handle=username) start_date = timezone.now() - timezone.timedelta(days=180) income = [] lifeExpectancy = [] diff --git a/app/marketing/management/commands/assemble_leaderboards.py b/app/marketing/management/commands/assemble_leaderboards.py index 02d408c6701..e54df27845a 100644 --- a/app/marketing/management/commands/assemble_leaderboards.py +++ b/app/marketing/management/commands/assemble_leaderboards.py @@ -106,7 +106,7 @@ def profile_to_location_helper(handle): def bounty_to_location(bounty): locations = profile_to_location(bounty.bounty_owner_github_username) fulfiller_usernames = list( - bounty.fulfillments.filter(accepted=True).values_list('fulfiller_github_username', flat=True) + bounty.fulfillments.filter(accepted=True).values_list('profile__handle', flat=True) ) for username in fulfiller_usernames: locations = locations + profile_to_location(username) @@ -232,7 +232,7 @@ def add_element(key, index_term, amount): def sum_bounty_helper(b, time, index_term, val_usd): - fulfiller_index_terms = list(b.fulfillments.filter(accepted=True).values_list('fulfiller_github_username', flat=True)) + fulfiller_index_terms = list(b.fulfillments.filter(accepted=True).values_list('profile__handle', flat=True)) add_element(f'{time}_{ALL}', index_term, val_usd) add_element(f'{time}_{FULFILLED}', index_term, val_usd) if index_term == b.bounty_owner_github_username and index_term not in IGNORE_PAYERS: diff --git a/app/marketing/tests/management/commands/test_assemble_leaderboards.py b/app/marketing/tests/management/commands/test_assemble_leaderboards.py index bd32fd0a2dc..9b9429be921 100644 --- a/app/marketing/tests/management/commands/test_assemble_leaderboards.py +++ b/app/marketing/tests/management/commands/test_assemble_leaderboards.py @@ -39,7 +39,6 @@ def setUp(self): self.bounty_value = 3 self.bounty_payer_handle = 'flintstone' self.bounty_earner_handle = 'freddy' - self.fulfiller_handle = 'bambam' self.bounty_payer_profile = Profile.objects.create( data={}, @@ -89,17 +88,12 @@ def setUp(self): network='mainnet', metadata={"issueKeywords": "Python, Shell"}, ) - self.fulfiller_profile = Profile.objects.create( - data={}, - handle=self.fulfiller_handle, - hide_profile=False, - ) + BountyFulfillment.objects.create( fulfiller_address='0x0000000000000000000000000000000000000000', - fulfiller_github_username=self.bounty_earner_handle, bounty=self.bounty, accepted=True, - profile=self.fulfiller_profile, + profile=self.bounty_earner_profile, ) self.tip_value = 7 @@ -142,7 +136,6 @@ def setUp(self): def tearDown(self): self.bounty_payer_profile.delete() self.bounty_earner_profile.delete() - self.fulfiller_profile.delete() self.tip_username_profile.delete() self.tip_from_username_profile.delete() diff --git a/app/marketing/tests/management/commands/test_expiration.py b/app/marketing/tests/management/commands/test_expiration.py index a00969d8a95..05ba64513fc 100644 --- a/app/marketing/tests/management/commands/test_expiration.py +++ b/app/marketing/tests/management/commands/test_expiration.py @@ -62,9 +62,6 @@ def test_handle(self, mock_func): ) BountyFulfillment.objects.create( fulfiller_address='0x0000000000000000000000000000000000000000', - fulfiller_email='fred@bar.com', - fulfiller_github_username='fred', - fulfiller_name='Fred', bounty=bounty, profile=fulfiller_profile, ) @@ -97,13 +94,14 @@ def test_handle_no_users(self, mock_func): current_bounty=True, network='mainnet' ) + fulfiller_profile = Profile.objects.create( + data={}, + handle='fred' + ) BountyFulfillment.objects.create( fulfiller_address='0x0000000000000000000000000000000000000000', - fulfiller_email='', - fulfiller_github_username='fred', - fulfiller_name='Fred', bounty=bounty, - profile=None, + profile=fulfiller_profile, ) Command().handle() diff --git a/app/marketing/tests/management/commands/test_sync_keywords.py b/app/marketing/tests/management/commands/test_sync_keywords.py index a79684baec2..ba18d251f84 100644 --- a/app/marketing/tests/management/commands/test_sync_keywords.py +++ b/app/marketing/tests/management/commands/test_sync_keywords.py @@ -21,7 +21,7 @@ from django.utils import timezone -from dashboard.models import Bounty, BountyFulfillment +from dashboard.models import Bounty, BountyFulfillment, Profile from marketing.management.commands.sync_keywords import Command from marketing.models import Keyword from test_plus.test import TestCase @@ -109,20 +109,28 @@ def test_handle_complex(self): } ) + fulfiller_profile = Profile.objects.create( + data={}, + handle='fred', + email='fred@bar.com' + ) + BountyFulfillment.objects.create( fulfiller_address='0x0000000000000000000000000000000000000000', - fulfiller_email='fred@bar.com', - fulfiller_github_username='fred', - fulfiller_name='Fred', - bounty=bounty + bounty=bounty, + profile=fulfiller_profile + ) + + fulfiller_profile = Profile.objects.create( + data={}, + handle='', + email='david@bar.com' ) BountyFulfillment.objects.create( fulfiller_address='0x0000000000000000000000000000000000000000', - fulfiller_email='david@bar.com', - fulfiller_github_username='', - fulfiller_name='Fred', - bounty=bounty + bounty=bounty, + profile=fulfiller_profile ) Command().handle() diff --git a/app/marketing/tests/management/commands/test_sync_pull_request_with_bounty_fulfillments.py b/app/marketing/tests/management/commands/test_sync_pull_request_with_bounty_fulfillments.py index 544a30119bd..33aa4f1559a 100644 --- a/app/marketing/tests/management/commands/test_sync_pull_request_with_bounty_fulfillments.py +++ b/app/marketing/tests/management/commands/test_sync_pull_request_with_bounty_fulfillments.py @@ -27,7 +27,7 @@ import marketing import marketing.management.commands.sync_pull_request_with_bounty_fulfillments -from dashboard.models import Bounty, BountyFulfillment +from dashboard.models import Bounty, BountyFulfillment, Profile from test_plus.test import TestCase @@ -63,12 +63,16 @@ def setUp(self): current_bounty=True ) + fulfiller_profile = Profile.objects.create( + data={}, + handle='samplegitcoindeveloper1', + email='fred@bar.com' + ) + BountyFulfillment.objects.create( fulfiller_address='0x0000000000000000000000000000000000000000', - fulfiller_email='fred@bar.com', - fulfiller_github_username='samplegitcoindeveloper1', - fulfiller_name='Fred', accepted=False, + profile=fulfiller_profile, bounty=Bounty.objects.last() ) diff --git a/app/marketing/tests/test_mail_funder_payout_reminder.py b/app/marketing/tests/test_mail_funder_payout_reminder.py index deb5bb25d18..8e74bac961b 100644 --- a/app/marketing/tests/test_mail_funder_payout_reminder.py +++ b/app/marketing/tests/test_mail_funder_payout_reminder.py @@ -67,9 +67,6 @@ def setUp(self): ) BountyFulfillment.objects.create( fulfiller_address='0x0000000000000000000000000000000000000000', - fulfiller_email='fred@bar.com', - fulfiller_github_username='samplegitcoindeveloper1', - fulfiller_name='Fred', accepted=False, bounty=Bounty.objects.last() ) diff --git a/app/retail/emails.py b/app/retail/emails.py index 1d04339c5a2..25e82337960 100644 --- a/app/retail/emails.py +++ b/app/retail/emails.py @@ -351,7 +351,7 @@ def render_quarterly_stats(to_email, platform_wide_stats): def render_funder_payout_reminder(**kwargs): - kwargs['bounty_fulfillment'] = kwargs['bounty'].fulfillments.filter(fulfiller_github_username=kwargs['github_username']).last() + kwargs['bounty_fulfillment'] = kwargs['bounty'].fulfillments.filter(profile__handle=kwargs['github_username']).last() response_html = premailer_transform(render_to_string("emails/funder_payout_reminder.html", kwargs)) response_txt = '' return response_html, response_txt @@ -377,7 +377,6 @@ def render_no_applicant_reminder(bounty): def render_bounty_feedback(bounty, persona='submitter', previous_bounties=[]): - previous_bounties_str = ", ".join([bounty.github_url for bounty in previous_bounties]) if persona == 'fulfiller': accepted_fulfillments = bounty.fulfillments.filter(accepted=True) github_username = " @" + accepted_fulfillments.first().fulfiller_github_username if accepted_fulfillments.exists() and accepted_fulfillments.first().fulfiller_github_username else "" diff --git a/scripts/debug/hackathon_export.py b/scripts/debug/hackathon_export.py index daa6e8f1ba0..7770b53e6ed 100644 --- a/scripts/debug/hackathon_export.py +++ b/scripts/debug/hackathon_export.py @@ -1,7 +1,7 @@ from dashboard.models import Bounty, HackathonEvent # bounty data export script for electric capital -print("hackathon name, start date, end date, bounty_created, bounty url, bounty title, bounty amount, bounty token, contributors, github_issue, fulfiller_name, fulfiller_pr") +print("hackathon name, start date, end date, bounty_created, bounty url, bounty title, bounty amount, bounty token, contributors, github_issue, fulfiller_pr") for bounty in Bounty.objects.current().filter(idx_status='done'): for bf in bounty.fulfillments.all(): he = bounty.event