begin implementation of teamsnap syncing
This commit is contained in:
72
teamsnap/migrations/0019_auto_20211216_1851.py
Normal file
72
teamsnap/migrations/0019_auto_20211216_1851.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# Generated by Django 3.2.6 on 2021-12-16 18:51
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('events', '0004_delete_availability'),
|
||||
('teamsnap', '0018_user_managed_teams'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='availability',
|
||||
old_name='team',
|
||||
new_name='managed_by_team',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='event',
|
||||
old_name='team',
|
||||
new_name='managed_by_team',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='member',
|
||||
old_name='team',
|
||||
new_name='managed_by_team',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='team',
|
||||
old_name='bencoach_team',
|
||||
new_name='benchcoach_object',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='lineupentry',
|
||||
name='managed_by_team',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='teamsnap.team'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='location',
|
||||
name='managed_by_team',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='teamsnap.team'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='team',
|
||||
name='managed_by_team',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='teamsnap.team'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='benchcoach_object',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='teamsnap_event', to='events.event'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Opponent',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('teamsnap_id', models.CharField(max_length=10, unique=True)),
|
||||
('name', models.CharField(max_length=50, null=True)),
|
||||
('managed_by_team', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='teamsnap.team')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='opponent',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opponent', to='teamsnap.opponent'),
|
||||
),
|
||||
]
|
||||
41
teamsnap/migrations/0020_auto_20211216_1903.py
Normal file
41
teamsnap/migrations/0020_auto_20211216_1903.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# Generated by Django 3.2.6 on 2021-12-16 19:03
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teamsnap', '0019_auto_20211216_1851'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='availability',
|
||||
name='teamsnap_id',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='event',
|
||||
name='teamsnap_id',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='location',
|
||||
name='teamsnap_id',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='member',
|
||||
name='teamsnap_id',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='opponent',
|
||||
name='teamsnap_id',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='team',
|
||||
name='teamsnap_id',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='user',
|
||||
name='teamsnap_id',
|
||||
),
|
||||
]
|
||||
53
teamsnap/migrations/0021_auto_20211216_1905.py
Normal file
53
teamsnap/migrations/0021_auto_20211216_1905.py
Normal file
@@ -0,0 +1,53 @@
|
||||
# Generated by Django 3.2.6 on 2021-12-16 19:05
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teamsnap', '0020_auto_20211216_1903'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='availability',
|
||||
name='id',
|
||||
field=models.CharField(max_length=10, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='id',
|
||||
field=models.CharField(max_length=10, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='lineupentry',
|
||||
name='id',
|
||||
field=models.CharField(max_length=10, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='location',
|
||||
name='id',
|
||||
field=models.CharField(max_length=10, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='member',
|
||||
name='id',
|
||||
field=models.CharField(max_length=10, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='opponent',
|
||||
name='id',
|
||||
field=models.CharField(max_length=10, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='id',
|
||||
field=models.CharField(max_length=10, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='id',
|
||||
field=models.CharField(max_length=10, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
]
|
||||
53
teamsnap/migrations/0022_auto_20211216_1909.py
Normal file
53
teamsnap/migrations/0022_auto_20211216_1909.py
Normal file
@@ -0,0 +1,53 @@
|
||||
# Generated by Django 3.2.6 on 2021-12-16 19:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teamsnap', '0021_auto_20211216_1905'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='availability',
|
||||
name='id',
|
||||
field=models.CharField(max_length=50, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='id',
|
||||
field=models.CharField(max_length=50, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='lineupentry',
|
||||
name='id',
|
||||
field=models.CharField(max_length=50, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='location',
|
||||
name='id',
|
||||
field=models.CharField(max_length=50, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='member',
|
||||
name='id',
|
||||
field=models.CharField(max_length=50, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='opponent',
|
||||
name='id',
|
||||
field=models.CharField(max_length=50, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='id',
|
||||
field=models.CharField(max_length=50, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='id',
|
||||
field=models.CharField(max_length=50, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
]
|
||||
21
teamsnap/migrations/0023_auto_20211216_1951.py
Normal file
21
teamsnap/migrations/0023_auto_20211216_1951.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 3.2.6 on 2021-12-16 19:51
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teamsnap', '0022_auto_20211216_1909'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='lineupentry',
|
||||
name='teamsnap_id',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='team',
|
||||
name='managed_by_team',
|
||||
),
|
||||
]
|
||||
109
teamsnap/migrations/0024_auto_20211216_1703.py
Normal file
109
teamsnap/migrations/0024_auto_20211216_1703.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# Generated by Django 3.2.6 on 2021-12-16 23:03
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teamsnap', '0023_auto_20211216_1951'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='availability',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='availability',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='lineupentry',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='lineupentry',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='location',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='location',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='member',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='member',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='opponent',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='opponent',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='team',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='team',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(default='2000-10-31T01:30:00.000-05:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
20
teamsnap/migrations/0025_opponent_benchcoach_object.py
Normal file
20
teamsnap/migrations/0025_opponent_benchcoach_object.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 3.2.6 on 2021-12-16 23:31
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teams', '0001_initial'),
|
||||
('teamsnap', '0024_auto_20211216_1703'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='opponent',
|
||||
name='benchcoach_object',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='teams.team'),
|
||||
),
|
||||
]
|
||||
100
teamsnap/migrations/0026_auto_20211216_2003.py
Normal file
100
teamsnap/migrations/0026_auto_20211216_2003.py
Normal file
@@ -0,0 +1,100 @@
|
||||
# Generated by Django 3.2.6 on 2021-12-17 02:03
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('teams', '0001_initial'),
|
||||
('teamsnap', '0025_opponent_benchcoach_object'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='availability',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='availability',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='lineupentry',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='lineupentry',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='location',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='location',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='member',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='member',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='opponent',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='opponent',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='benchcoach_object',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='teamsnapteam', to='teams.team'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
]
|
||||
@@ -7,104 +7,114 @@ import players.models
|
||||
import events.models
|
||||
|
||||
class TeamsnapBaseModel(models.Model):
|
||||
teamsnap_id = models.CharField(max_length=10, unique=True)
|
||||
type = None
|
||||
id = models.CharField(max_length=50, unique=True, primary_key=True)
|
||||
name = models.CharField(max_length=50, null=True)
|
||||
created_at = models.DateTimeField(null=True)
|
||||
updated_at = models.DateTimeField(null=True)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def __str__(self):
|
||||
return f"TeamSnap {self.__class__.__name__} Object ({self.teamsnap_id})"
|
||||
return f"TeamSnap {self.__class__.__name__} Object ({self.id})"
|
||||
|
||||
@property
|
||||
def api_url(self):
|
||||
return "https://api.teamsnap.com/v3/{type}/{id}".format(type=self.type, id=self.id)
|
||||
|
||||
class Team(TeamsnapBaseModel):
|
||||
bencoach_team = models.ForeignKey(teams.models.Team, null=True, on_delete=models.CASCADE)
|
||||
type = 'team'
|
||||
managed_by_team = None
|
||||
benchcoach_object = models.ForeignKey(teams.models.Team, null=True, on_delete=models.CASCADE,related_name="teamsnapteam")
|
||||
|
||||
class User(TeamsnapBaseModel):
|
||||
type = 'user'
|
||||
name = None
|
||||
first_name = models.CharField(max_length=50, null=True)
|
||||
last_name = models.CharField(max_length = 50, null=True)
|
||||
email = models.EmailField(null=True)
|
||||
managed_teams = models.ManyToManyField(Team)
|
||||
|
||||
class TeamsnapManagedObjectModel(TeamsnapBaseModel):
|
||||
managed_by_team = models.ForeignKey(Team, null=True, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
@property
|
||||
def view_url(self):
|
||||
return f"https://go.teamsnap.com/{self.team.teamsnap_id}/team/view/{self.teamsnap_id}"
|
||||
def url(self, endpoint='view'):
|
||||
return f"https://go.teamsnap.com/{self.managed_by_team.id}/{self.type}/{endpoint}/{self.id}"
|
||||
|
||||
@property
|
||||
def edit_url(self):
|
||||
return f"https://go.teamsnap.com/{self.team.teamsnap_id}/team/edit/{self.teamsnap_id}"
|
||||
class Opponent(TeamsnapManagedObjectModel):
|
||||
type = 'opponent'
|
||||
benchcoach_object = models.ForeignKey(teams.models.Team, null=True, on_delete=models.CASCADE)
|
||||
|
||||
class Location(TeamsnapBaseModel):
|
||||
class Location(TeamsnapManagedObjectModel):
|
||||
benchcoach_object = models.ForeignKey(venues.models.Venue, null=True, on_delete=models.CASCADE)
|
||||
|
||||
@property
|
||||
def view_url(self):
|
||||
return f"https://go.teamsnap.com/{self.team.teamsnap_id}/location/view/{self.teamsnap_id}"
|
||||
|
||||
@property
|
||||
def edit_url(self):
|
||||
return f"https://go.teamsnap.com/{self.team.teamsnap_id}/location/edit/{self.teamsnap_id}"
|
||||
|
||||
class Member(TeamsnapBaseModel):
|
||||
name = None
|
||||
class Member(TeamsnapManagedObjectModel):
|
||||
# url format is
|
||||
# f"https://go.teamsnap.com/{self.team.teamsnap_id}/roster/player/{self.teamsnap_id}"
|
||||
# f"https://go.teamsnap.com/{self.team.teamsnap_id}/roster/edit/{self.teamsnap_id}"
|
||||
type = 'member'
|
||||
benchcoach_object = models.ForeignKey(players.models.Player, null=True, on_delete=models.CASCADE)
|
||||
team = models.ForeignKey(Team, null=True, on_delete=models.CASCADE)
|
||||
first_name = models.CharField(max_length = 50, null=True)
|
||||
last_name = models.CharField(max_length = 50, null=True)
|
||||
jersey_number = models.IntegerField(null=True)
|
||||
is_non_player = models.BooleanField()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.last_name}, {self.first_name} ({self.teamsnap_id})"
|
||||
return f"{self.last_name}, {self.first_name} ({self.id})"
|
||||
|
||||
@property
|
||||
def view_url(self):
|
||||
return f"https://go.teamsnap.com/{self.team.teamsnap_id}/roster/player/{self.teamsnap_id}"
|
||||
def name(self):
|
||||
return f"{self.first_name} {self.last_name}"
|
||||
|
||||
@property
|
||||
def edit_url(self):
|
||||
return f"https://go.teamsnap.com/{self.team.teamsnap_id}/roster/edit/{self.teamsnap_id}"
|
||||
|
||||
class Event(TeamsnapBaseModel):
|
||||
class Event(TeamsnapManagedObjectModel):
|
||||
# url is
|
||||
# f"https://go.teamsnap.com/{self.team.teamsnap_id}/schedule/view_game/{self.teamsnap_id}"
|
||||
# f"https://go.teamsnap.com/{self.team.teamsnap_id}/schedule/edit_game/{self.teamsnap_id}"
|
||||
type = 'event'
|
||||
name = None
|
||||
benchcoach_object = models.ForeignKey(events.models.Event, null=True, on_delete=models.CASCADE)
|
||||
benchcoach_object = models.ForeignKey(events.models.Event, null=True, on_delete=models.CASCADE, related_name ='teamsnap_event')
|
||||
label = models.CharField(max_length = 50, null=True)
|
||||
start_date = models.DateTimeField(null=True)
|
||||
opponent = models.ForeignKey(Team, null=True, on_delete=models.CASCADE, related_name="opponent")
|
||||
team = models.ForeignKey(Team, null=True, on_delete=models.CASCADE)
|
||||
opponent = models.ForeignKey(Opponent, null=True, on_delete=models.CASCADE, related_name="opponent")
|
||||
location = models.ForeignKey(Location, null=True, on_delete=models.CASCADE)
|
||||
formatted_title = models.CharField(max_length = 50, null=True)
|
||||
points_for_opponent = models.PositiveSmallIntegerField(null=True)
|
||||
points_for_team = models.PositiveSmallIntegerField(null=True)
|
||||
is_game = models.BooleanField()
|
||||
|
||||
@property
|
||||
def view_url(self):
|
||||
return f"https://go.teamsnap.com/{self.team.teamsnap_id}/schedule/view_game/{self.teamsnap_id}"
|
||||
|
||||
@property
|
||||
def edit_url(self):
|
||||
return f"https://go.teamsnap.com/{self.team.teamsnap_id}/schedule/edit_game/{self.teamsnap_id}"
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.formatted_title} ({self.teamsnap_id})"
|
||||
return f"{self.formatted_title} ({self.id})"
|
||||
|
||||
class Availability(TeamsnapBaseModel):
|
||||
class Availability(TeamsnapManagedObjectModel):
|
||||
YES = 1
|
||||
NO = 0
|
||||
MAYBE = 2
|
||||
UNKNOWN = None
|
||||
status_codes = [
|
||||
(1, 'Yes'),
|
||||
(0, 'No'),
|
||||
(2, 'Maybe'),
|
||||
(None, 'Unknown')
|
||||
(YES, 'Yes'),
|
||||
(NO, 'No'),
|
||||
(MAYBE, 'Maybe'),
|
||||
(UNKNOWN, 'Unknown')
|
||||
]
|
||||
name = None
|
||||
team = models.ForeignKey(Team, null=True, on_delete=models.CASCADE)
|
||||
event = models.ForeignKey(Event, null=True, on_delete=models.CASCADE)
|
||||
member = models.ForeignKey(Member, null=True, on_delete=models.CASCADE)
|
||||
benchcoach_object = models.ForeignKey(lineups.models.Availability, null=True, on_delete=models.CASCADE)
|
||||
status_code = models.SmallIntegerField(null=True, choices=status_codes, default=None)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.member} - {self.event} ({self.teamsnap_id})"
|
||||
return f"{self.member} - {self.event} ({self.id})"
|
||||
|
||||
class Meta:
|
||||
verbose_name_plural = "availabilities"
|
||||
|
||||
class LineupEntry(TeamsnapBaseModel):
|
||||
class LineupEntry(TeamsnapManagedObjectModel):
|
||||
name = None
|
||||
teamsnap_id = models.CharField(max_length=10, unique=True, null=True, blank=True)
|
||||
member = models.ForeignKey(Member, on_delete=models.CASCADE)
|
||||
event = models.ForeignKey(Event, on_delete=models.CASCADE)
|
||||
positions = [
|
||||
@@ -125,10 +135,3 @@ class LineupEntry(TeamsnapBaseModel):
|
||||
|
||||
class Meta:
|
||||
unique_together = ('member', 'event',)
|
||||
|
||||
class User(TeamsnapBaseModel):
|
||||
name = None
|
||||
first_name = models.CharField(max_length=50, null=True)
|
||||
last_name = models.CharField(max_length = 50, null=True)
|
||||
email = models.EmailField(null=True)
|
||||
managed_teams = models.ManyToManyField(Team)
|
||||
@@ -1,3 +1,3 @@
|
||||
from .api import TeamSnap
|
||||
|
||||
__all__ = ['TeamSnap']
|
||||
# from .utils import TeamSnap
|
||||
#
|
||||
# __all__ = ['TeamSnap']
|
||||
@@ -6,5 +6,44 @@
|
||||
<h1>Currently Logged in as</h1>
|
||||
<p><b>BenchCoach: </b>{{ user }} ({{ user.email }})</p>
|
||||
<p><b>TeamSnap: </b>{{ teamsnap_user.email }}</p>
|
||||
<p><b>TeamSnap Managed Team: </b>{{ teamsnap_team.name }}</p>
|
||||
|
||||
<button type="button" class="btn btn-primary m-1" onclick="sync_teamsnap_db()">
|
||||
Sync TeamSnap DB
|
||||
<div id="teamsnap-sync-spinner" class="spinner-border spinner-border-sm d-none" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<textarea id="output_box" name="comment" disabled class="w-100 m" style="min-height: 400px"></textarea>
|
||||
<button type="button" class="btn btn-outline-secondary m-1" onclick="clear_output_box()">Clear</button>
|
||||
<script>
|
||||
const output_box = document.getElementById("output_box");
|
||||
const progress_spinner = document.getElementById("teamsnap-sync-spinner")
|
||||
function sync_teamsnap_db(){
|
||||
const Http = new XMLHttpRequest();
|
||||
const url='{% url 'sync teamsnap' %}';
|
||||
console.log(progress_spinner)
|
||||
progress_spinner.classList.remove("d-none");
|
||||
fetch(url)
|
||||
.then((response) => {
|
||||
progress_spinner.classList.add("d-none")
|
||||
return response.json();
|
||||
})
|
||||
.then((myJson) => {
|
||||
var s = 'Number of objects updated: '
|
||||
for (i in myJson) {
|
||||
s += myJson[i]
|
||||
{#s += myJson[i].name +" ("+ myJson[i].id+")" + "\r\n"#}
|
||||
}
|
||||
output_box.value = s;
|
||||
});
|
||||
}
|
||||
|
||||
function clear_output_box(){
|
||||
progress_spinner.classList.add('d-none')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
@@ -10,5 +10,6 @@ urlpatterns = [
|
||||
path('events', views.EventsListView.as_view(), name="teamsnap list events"),
|
||||
path('events-table', views.EventsTableView.as_view(), name="teamsnap table events"),
|
||||
path('edit/event/<int:id>', views.edit_event, name='teamsnap edit event'),
|
||||
path('edit/lineup/<int:event_id>', views.edit_lineup, name='teamsnap edit lineup')
|
||||
path('from_teamsnap', views.sync_teamsnap, name="sync teamsnap"),
|
||||
# path('import_teamsnap', views.import_teamsnap, name="import teamsnap"),
|
||||
]
|
||||
0
teamsnap/utils/__init__.py
Normal file
0
teamsnap/utils/__init__.py
Normal file
197
teamsnap/utils/import_teamsnap.py
Normal file
197
teamsnap/utils/import_teamsnap.py
Normal file
@@ -0,0 +1,197 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "benchcoach.settings")
|
||||
os.environ["DJANGO_SETTINGS_MODULE"] = "benchcoach.settings"
|
||||
import django
|
||||
django.setup()
|
||||
|
||||
from teamsnap.teamsnap.api import TeamSnap
|
||||
import teamsnap.teamsnap.api
|
||||
from teamsnap.models import User, Member, Team, Event, Location, Availability, Opponent
|
||||
from typing import List
|
||||
from benchcoach.models import Profile as BenchcoachUser
|
||||
from teams.models import Team as BenchcoachTeam
|
||||
from events.models import Event as BenchcoachEvent
|
||||
import pytz
|
||||
|
||||
def update_object_from_teamsnap(
|
||||
TeamsnapApiObject: teamsnap.teamsnap.api.ApiObject,
|
||||
TeamsnapDbModelClass: teamsnap.models.TeamsnapBaseModel,
|
||||
TeamsnapClient: teamsnap.teamsnap.api.TeamSnap,
|
||||
teamsnap_search_kwargs: dict,
|
||||
fetching_keys: List[tuple] = ['id'],
|
||||
default_keys: List[tuple] = ['name']
|
||||
):
|
||||
|
||||
"""
|
||||
Import or Update database objects from TeamSnap API
|
||||
|
||||
additional_fetching_keys (key,) or (api_key, db_field_name) or (api_key, db_field_name, callable)
|
||||
Additional kwargs used to fetch an object from the database. ('id', 'teamsnap_id') are already included
|
||||
Callable will be run with the retrieved value as an argument. Example uses for this callable are to sanitize the value
|
||||
such as for a date, or to retrieve another database object
|
||||
|
||||
additional_default_keys
|
||||
Additional Keys used to update the object (key,) or (api_key, db_field_name) or (api_key, db_field_name, callable)
|
||||
('name',) is already included
|
||||
Callable will be run with the retrieved value as an argument. Example uses for this callable are to sanitize the value
|
||||
such as for a date, or to retrieve another database object
|
||||
|
||||
:rtype: object
|
||||
"""
|
||||
api_response = TeamsnapApiObject.search(client=TeamsnapClient, **teamsnap_search_kwargs)
|
||||
|
||||
# This routine allows, for convenience, simplers tuples in which the additional detail is not needed
|
||||
# for example [('key', 'key', None)] can be passed as ['key'] if the TeamsnapApi key is the same as the TeamsnapDb field/key
|
||||
# and doesn't need to be sanitized
|
||||
for d in [fetching_keys, fetching_keys, default_keys]:
|
||||
for i, key in enumerate(d):
|
||||
if isinstance(key, tuple):
|
||||
if len(key) == 1:
|
||||
d[i] = (key[0], key[0], None)
|
||||
if len(key) == 2:
|
||||
d[i] = (key[0], key[1], None)
|
||||
elif isinstance(key, str):
|
||||
d[i] = (key, key, None)
|
||||
|
||||
r = []
|
||||
for data in [items.data for items in api_response]:
|
||||
kwargs, defaults = {}, {}
|
||||
for api_key, db_field_name, callable_function in fetching_keys:
|
||||
if api_key in data.keys():
|
||||
kwargs[db_field_name] = callable_function(data[api_key]) if callable_function else data[api_key]
|
||||
for api_key, db_field_name, callable_function in default_keys:
|
||||
if api_key in data.keys():
|
||||
defaults[db_field_name] = callable_function(data[api_key]) if callable_function else data[api_key]
|
||||
defaults ={k:v for k,v in defaults.items() if v is not None}
|
||||
obj, created = TeamsnapDbModelClass.objects.update_or_create(**kwargs, defaults=defaults)
|
||||
r.append((obj,created))
|
||||
return r
|
||||
|
||||
def update_locations (client, **kwargs):
|
||||
return update_object_from_teamsnap(
|
||||
teamsnap.teamsnap.api.Location,
|
||||
Location,
|
||||
TeamsnapClient=client,
|
||||
teamsnap_search_kwargs=kwargs,
|
||||
default_keys=[
|
||||
'name', 'created_at', 'updated_at',
|
||||
('team_id', 'managed_by_team_id')
|
||||
]
|
||||
)
|
||||
|
||||
def update_teams (client, **kwargs):
|
||||
teams = update_object_from_teamsnap(
|
||||
teamsnap.teamsnap.api.Team,
|
||||
Team,
|
||||
TeamsnapClient=client,
|
||||
teamsnap_search_kwargs=kwargs,
|
||||
default_keys=[
|
||||
'name', 'created_at', 'updated_at',
|
||||
('team_id', 'managed_by_team_id')
|
||||
]
|
||||
)
|
||||
opponents = update_object_from_teamsnap(
|
||||
teamsnap.teamsnap.api.Opponent,
|
||||
Opponent,
|
||||
TeamsnapClient=client,
|
||||
teamsnap_search_kwargs=kwargs,
|
||||
default_keys= [
|
||||
'name', 'created_at', 'updated_at',
|
||||
('team_id', 'managed_by_team_id')
|
||||
]
|
||||
)
|
||||
return teams + opponents
|
||||
|
||||
def update_members (client, **kwargs):
|
||||
return update_object_from_teamsnap(
|
||||
TeamsnapApiObject=teamsnap.teamsnap.api.Member,
|
||||
TeamsnapDbModelClass=Member,
|
||||
TeamsnapClient=client,
|
||||
teamsnap_search_kwargs=kwargs,
|
||||
default_keys=['first_name','last_name','jersey_number','is_non_player', 'created_at', 'updated_at',
|
||||
('team_id', 'managed_by_team_id'),
|
||||
]
|
||||
)
|
||||
pass
|
||||
|
||||
def update_availabilities(client, **kwargs):
|
||||
return update_object_from_teamsnap(
|
||||
TeamsnapApiObject=teamsnap.teamsnap.api.Availability,
|
||||
TeamsnapDbModelClass=Availability,
|
||||
TeamsnapClient=client,
|
||||
teamsnap_search_kwargs=kwargs,
|
||||
default_keys=[ 'status_code',
|
||||
'member_id',
|
||||
'event_id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
('team_id', 'managed_by_team_id')
|
||||
]
|
||||
)
|
||||
|
||||
def update_events(client, **kwargs):
|
||||
return update_object_from_teamsnap(
|
||||
TeamsnapApiObject=teamsnap.teamsnap.api.Event,
|
||||
TeamsnapDbModelClass=Event,
|
||||
TeamsnapClient=client,
|
||||
teamsnap_search_kwargs=kwargs,
|
||||
default_keys=['formatted_title','label','points_for_opponent','points_for_team','is_game','opponent_id','location_id',
|
||||
'start_date', 'created_at', 'updated_at',
|
||||
('team_id', 'managed_by_team_id')
|
||||
]
|
||||
)
|
||||
|
||||
def update_users(client, **kwargs):
|
||||
return update_object_from_teamsnap(
|
||||
TeamsnapApiObject=teamsnap.teamsnap.api.User,
|
||||
TeamsnapDbModelClass=User,
|
||||
TeamsnapClient=client,
|
||||
teamsnap_search_kwargs=kwargs,
|
||||
default_keys=['first_name', 'last_name', 'email', 'created_at', 'updated_at',]
|
||||
)
|
||||
|
||||
def import_teamsnap():
|
||||
user = BenchcoachUser.objects.get(id=1)
|
||||
TOKEN = user.teamsnap_access_token
|
||||
USER_ID = user.teamsnap_user.id
|
||||
TEAM_ID = user.teamsnapsettings.managed_team.id
|
||||
CLIENT = TeamSnap(token=TOKEN)
|
||||
update_users(CLIENT, id=USER_ID)
|
||||
|
||||
l = []
|
||||
for team in Opponent.objects.filter(managed_by_team_id=TEAM_ID):
|
||||
d = {
|
||||
'name': team.name,
|
||||
}
|
||||
obj, created = BenchcoachTeam.objects.update_or_create(opponent=team, defaults=d)
|
||||
team.benchcoach_object = obj
|
||||
team.save()
|
||||
l.append((obj,created))
|
||||
|
||||
for team in Team.objects.filter(id=TEAM_ID):
|
||||
d = {
|
||||
'name': team.name,
|
||||
}
|
||||
obj_id = BenchcoachTeam.objects.filter(id=team.benchcoach_object.id).update(**d)
|
||||
team.benchcoach_object = BenchcoachTeam.objects.get(id=obj_id)
|
||||
team.save()
|
||||
l.append((obj,created))
|
||||
|
||||
for event in Event.objects.filter(managed_by_team_id=TEAM_ID):
|
||||
d = {
|
||||
'start':event.start_date,
|
||||
}
|
||||
obj, created = BenchcoachEvent.objects.update_or_create(teamsnap_event=event, defaults=d)
|
||||
# event.benchcoach_object = obj
|
||||
|
||||
pass
|
||||
# l += update_teams(CLIENT, team_id=TEAM_ID)
|
||||
# l += update_members(CLIENT, team_id=TEAM_ID)
|
||||
# l += update_locations(CLIENT, team_id=TEAM_ID)
|
||||
# l += update_events(CLIENT, team_id=TEAM_ID)
|
||||
# l += update_availabilities(CLIENT, team_id=TEAM_ID)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import_teamsnap()
|
||||
@@ -1,6 +1,7 @@
|
||||
from django.shortcuts import render, redirect
|
||||
|
||||
# from .teamsnap.api import TeamSnap, Team, Event, Availability
|
||||
from .teamsnap.api import Event as TsApiEvent
|
||||
from .teamsnap.api import TeamSnap
|
||||
from .models import User, Member, Team, Event, Location, LineupEntry
|
||||
from django.views.generic.list import ListView
|
||||
from lib.views import BenchcoachListView
|
||||
@@ -11,6 +12,11 @@ from django.db.models import Case, When
|
||||
from django.views import View
|
||||
from django.http import HttpResponse
|
||||
from benchcoach.models import Profile as BenchcoachUser
|
||||
from events.models import Event as BenchcoachEvent
|
||||
import teamsnap.teamsnap.api
|
||||
import json
|
||||
from django.http import JsonResponse
|
||||
from .utils.import_teamsnap import update_users, update_teams, update_events, update_members, update_locations, update_availabilities
|
||||
|
||||
def queryset_from_ids(Model, id_list):
|
||||
#https://stackoverflow.com/questions/4916851/django-get-a-queryset-from-array-of-ids-in-specific-order
|
||||
@@ -70,65 +76,40 @@ class LocationListView(BenchcoachListView):
|
||||
list_url = 'teamsnap list locations'
|
||||
page_title = "TeamSnap Locations"
|
||||
|
||||
def edit_lineup(request, event_id):
|
||||
def update_from_teamsnap_event(request):
|
||||
TOKEN = BenchcoachUser.objects.get(id=1).teamsnap_access_token
|
||||
CLIENT = TeamSnap(token=TOKEN)
|
||||
teamsnap_event_id=request.POST.get('teamsnap event')
|
||||
benchcoach_event_id=request.POST.get('teamsnap event')
|
||||
if teamsnap_event_id:
|
||||
benchcoach_event = BenchcoachEvent.objects.get(id=benchcoach_event_id)
|
||||
teamsnap_object = Event.objects.get(id=teamsnap_event_id)
|
||||
teamsnap_id = teamsnap_object.teamsnap_id
|
||||
teamsnap_response = TsApiEvent.search(client=CLIENT, id=teamsnap_id)
|
||||
if teamsnap_response[0]:
|
||||
data = teamsnap_response[0].data
|
||||
location = Location.objects.get(teamsnap_id=data['location_id'])
|
||||
opponent = Team.objects.get(teamsnap_id=data['opponent_id'])
|
||||
|
||||
if request.method == 'POST':
|
||||
# create a form instance and populate it with data from the request:
|
||||
formset = LineupEntryFormSet(request.POST)
|
||||
for form in formset:
|
||||
if form.is_valid():
|
||||
# process the data in form.cleaned_data as required
|
||||
# ...
|
||||
# redirect to a new URL:
|
||||
return HttpResponse(f'Success, {data}')
|
||||
|
||||
if isinstance(form.cleaned_data['id'], LineupEntry):
|
||||
positioning_id = form.cleaned_data.pop('id').id #FIXME this is a workaround, not sure why it is necessary
|
||||
positioning = LineupEntry.objects.filter(id=positioning_id)
|
||||
positioning.update(**form.cleaned_data)
|
||||
did_create = False
|
||||
else:
|
||||
positioning = LineupEntry.objects.create(**form.cleaned_data, event_id=event_id)
|
||||
did_create = True
|
||||
else:
|
||||
pass
|
||||
return render(request, 'success.html', {'call_back':'teamsnap edit lineup','id':event_id, 'errors':[error for error in formset.errors if error]}, status=200)
|
||||
# return render(request, 'success.html', {'call_back':'schedule'})
|
||||
event = Event.objects.get(id=event_id)
|
||||
members = Member.objects.filter(is_non_player=False).prefetch_related('availability_set', 'lineupentry_set')
|
||||
# players_d.sort(key=lambda d: (-d['availability'].available, d['last_name']))
|
||||
def sync_teamsnap(request):
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
USER_ID = request.user.profile.teamsnap_user.id
|
||||
TEAM_ID = request.user.profile.teamsnapsettings.managed_team.id
|
||||
CLIENT = TeamSnap(token=TOKEN)
|
||||
l = []
|
||||
l += update_users(CLIENT, id=USER_ID)
|
||||
l += update_teams(CLIENT, team_id=TEAM_ID)
|
||||
l += update_members(CLIENT, team_id=TEAM_ID)
|
||||
l += update_locations(CLIENT, team_id=TEAM_ID)
|
||||
l += update_events(CLIENT, team_id=TEAM_ID)
|
||||
l += update_availabilities(CLIENT, team_id=TEAM_ID)
|
||||
|
||||
for member in members:
|
||||
LineupEntry.objects.get_or_create(member_id=member.id, event_id=event_id)
|
||||
return JsonResponse({'number of objects updated':len(l)})
|
||||
|
||||
qs_starting_lineup = LineupEntry.objects.filter(event_id=event_id, sequence__isnull=False, sequence__gt=0).order_by('sequence')
|
||||
qs_bench = LineupEntry.objects.filter(event_id=event_id, sequence=0).prefetch_related('member__availability_set').order_by('member__last_name')
|
||||
|
||||
# This is all a compromise to get the sorting just the way I wanted. THERE'S GOT TO BE A BETTER WAY
|
||||
ids_starting_lineup = [item.id for item in qs_starting_lineup]
|
||||
ids_bench_available = [item.id for item in qs_bench
|
||||
if item.member.availability_set.get(event_id=event_id).status_code == 1]
|
||||
ids_bench_maybe = [item.id for item in qs_bench
|
||||
if item.member.availability_set.get(event_id=event_id).status_code == 2]
|
||||
ids_bench_no = [item.id for item in qs_bench
|
||||
if item.member.availability_set.get(event_id=event_id).status_code == 0]
|
||||
ids_bench_unknown = [item.id for item in qs_bench
|
||||
if item.member.availability_set.get(event_id=event_id).status_code is None]
|
||||
qset = queryset_from_ids(LineupEntry, ids_starting_lineup + ids_bench_available + ids_bench_maybe + ids_bench_no + ids_bench_unknown)
|
||||
|
||||
formset = LineupEntryFormSet(queryset=qset)
|
||||
|
||||
for f in formset:
|
||||
if f.instance.member_id:
|
||||
f.availability = f.instance.member.availability_set.get(event_id=event_id)
|
||||
# f.statline = f.instance.member.statline_set.get()
|
||||
|
||||
formset_lineup = [f for f in formset if f.instance.sequence]
|
||||
formset_bench = [f for f in formset if f not in formset_lineup]
|
||||
formset_dhd = [f for f in formset if not f.instance.sequence and f.instance.label]
|
||||
|
||||
return render(request, 'teamsnap/lineup.html', {'title': 'Lineup',
|
||||
'event': event,
|
||||
'formset_lineup': formset_lineup,
|
||||
'formset_bench':formset_bench,
|
||||
'formset_dhd':formset_dhd
|
||||
})
|
||||
Reference in New Issue
Block a user