Skip to content
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

Added command to export reviewer's votes #650

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a383ac2
Python 3.5 type strings
the-xperimentalist Mar 22, 2020
b4ddc51
Added command to export as excel file
the-xperimentalist Mar 22, 2020
300ed87
Merge branch 'master' of https://github.com/prasoonmayank/junction
the-xperimentalist Mar 22, 2020
3822dd3
Change export to csv
the-xperimentalist Mar 22, 2020
75dce2e
Remove unused import
the-xperimentalist Mar 22, 2020
bc5a473
Message text change
the-xperimentalist Mar 22, 2020
2280969
Working command
the-xperimentalist Mar 24, 2020
b44eb7a
Converted from usage to csv
the-xperimentalist Mar 24, 2020
4e48be2
Remove pandas from requirements
the-xperimentalist Mar 24, 2020
664f133
Remove env file
the-xperimentalist Mar 25, 2020
5ad9437
Resolved comments and run linter
the-xperimentalist Apr 4, 2020
e7f2495
Removed return
the-xperimentalist Apr 4, 2020
dc85222
Merge branch 'master' of https://github.com/pythonindia/junction
the-xperimentalist Apr 4, 2020
fc3cb1c
Lint code based upon latest changes
the-xperimentalist Apr 5, 2020
9d87dba
Merge branch 'master' into master
the-xperimentalist Apr 15, 2020
ba50508
Fix lint issues
the-xperimentalist Apr 19, 2020
625637c
Merge branch 'master' of https://github.com/prasoonmayank/junction
the-xperimentalist Apr 19, 2020
99076ae
Resolved comments
the-xperimentalist Apr 24, 2020
b3470b5
Merge branch 'master' into master
the-xperimentalist May 2, 2020
79c0fbe
Merge branch 'master' into master
the-xperimentalist May 4, 2020
c8790fb
Merge branch 'master' into master
the-xperimentalist May 30, 2020
3bcc98f
Resolved some comments
the-xperimentalist May 30, 2020
13bf0c1
Merge branch 'master' into master
the-xperimentalist Aug 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,6 @@ qr_files/
.vscode/

tmp/

# generated by command to create csv
csvs/
Empty file.
105 changes: 105 additions & 0 deletions junction/proposals/management/commands/export_conf_proposals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
import csv
import os
import sys

from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from settings.common import ROOT_DIR

from junction.base.constants import ProposalStatus
from junction.conferences.models import Conference
from junction.proposals.models import Proposal, ProposalSectionReviewerVoteValue
from junction.proposals.permissions import is_conference_moderator


class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument(
"--conference_slug",
default=None,
help="Enter the conference whose reviewer votes are to be exported from",
)

parser.add_argument("--user_id", default=None, help="Enter your user id")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the need of userid ? The command is supposed to be used by the admin from the console so the admin must be logged in to the application server.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, but there are multiple admin users, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes whoever has login access can use this command. No need to check for user id. Usually whoever is managing junction is also the one managing the server. Also user id's are not user friendly


def handle(self, *args, **options):

try:
conference = Conference.objects.get(slug=options.get("conference_slug"))
user = User.objects.get(id=options.get("user_id"))
except User.DoesNotExist:
self.stdout.write("Invalid user")
sys.exit(1)
except Conference.DoesNotExist:
the-xperimentalist marked this conversation as resolved.
Show resolved Hide resolved
self.stdout.write("Invalid conference")
sys.exit(1)

if not is_conference_moderator(user=user, conference=conference):
self.stdout.write("The user id is not a conference moderator")
sys.exit(1)

proposal_sections = conference.proposal_sections.all()
proposals_qs = Proposal.objects.select_related(
"proposal_type", "proposal_section", "conference", "author"
).filter(conference=conference, status=ProposalStatus.PUBLIC)
proposals_qs = sorted(
proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), reverse=True
)
proposal_vote_values = ProposalSectionReviewerVoteValue.objects.order_by(
"-vote_value"
)
vote_values_list = [v.vote_value for v in proposal_vote_values]
vote_values_desc = tuple(i.description for i in proposal_vote_values)
header = ("Proposal Type", "Title", "Sum of reviewer votes", "No. of reviewer votes")
+ ("Public votes count", "Vote comments")
+ tuple(vote_values_desc)

csv_contents = []

for section in proposal_sections:
section_proposals = [
p for p in proposals_qs if p.proposal_section == section
]

for index, p in enumerate(section_proposals, 1):
vote_details = tuple(
p.get_reviewer_votes_count_by_value(v) for v in vote_values_list
)
vote_comment = "\n".join(
[
comment.comment
for comment in p.proposalcomment_set.filter(
vote=True, deleted=False
)
]
)
row = {
header[0]: p.proposal_type.name,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of csv.DictWriter you should simply use csv.writer and use lists to write each row. This reduces this complexity of creating a dictionary in each iteration and makes the code simpler. e.g.

row = (p.proposal_type.name, p.title, p.get_reviewer_votes_sum(),

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using dictwriter would be a lot more accurate, right? Always ensuring which values go for which fields? Probably, never creating confusion for future devs on which key belongs to which key?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename the vote_details variable to reviewer_votes_count in that case

header[1]: p.title,
header[2]: p.get_reviewer_votes_sum(),
header[3]: p.get_reviewer_votes_count(),
header[4]: p.get_votes_count(),
header[5]: vote_comment,
}
for i in range(len(tuple(vote_values_desc))):
row[tuple(vote_values_desc)[i]] = vote_details[i]

csv_contents.append(row)

csv_file_name = "%s-%s.csv" % (user.username, conference.name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no section name in the filename. This will overwrite the file each time as it is opened in w mode.

csv_base_dir = os.path.join(ROOT_DIR, "csvs")

if not os.path.exists(csv_base_dir):
os.makedirs(csv_base_dir)

csv_file_location = os.path.join(ROOT_DIR, "csvs", csv_file_name)

with open(csv_file_location, "w") as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=header)

writer.writeheader()
for row in csv_contents:
writer.writerow(row)

self.stdout.write("Successfully created the csv file")