Implement link groups
This commit is contained in:
parent
0723f14c53
commit
bbd25c7450
22
app/urls.py
22
app/urls.py
|
@ -25,6 +25,7 @@ from core.views import (
|
|||
aggregators,
|
||||
banks,
|
||||
base,
|
||||
linkgroups,
|
||||
notifications,
|
||||
platforms,
|
||||
profit,
|
||||
|
@ -230,4 +231,25 @@ urlpatterns = [
|
|||
wallets.WalletDelete.as_view(),
|
||||
name="wallet_delete",
|
||||
),
|
||||
# Link groups
|
||||
path(
|
||||
"links/<str:type>/",
|
||||
linkgroups.LinkGroupList.as_view(),
|
||||
name="linkgroups",
|
||||
),
|
||||
path(
|
||||
"links/<str:type>/create/",
|
||||
linkgroups.LinkGroupCreate.as_view(),
|
||||
name="linkgroup_create",
|
||||
),
|
||||
path(
|
||||
"links/<str:type>/update/<str:pk>/",
|
||||
linkgroups.LinkGroupUpdate.as_view(),
|
||||
name="linkgroup_update",
|
||||
),
|
||||
path(
|
||||
"links/<str:type>/delete/<str:pk>/",
|
||||
linkgroups.LinkGroupDelete.as_view(),
|
||||
name="linkgroup_delete",
|
||||
),
|
||||
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
|
|
106
core/forms.py
106
core/forms.py
|
@ -8,6 +8,7 @@ from .models import (
|
|||
Ad,
|
||||
Aggregator,
|
||||
Asset,
|
||||
LinkGroup,
|
||||
NotificationSettings,
|
||||
Platform,
|
||||
Provider,
|
||||
|
@ -73,6 +74,7 @@ class AggregatorForm(RestrictedFormMixin, ModelForm):
|
|||
"secret_id",
|
||||
"secret_key",
|
||||
"poll_interval",
|
||||
"link_group",
|
||||
"enabled",
|
||||
)
|
||||
help_texts = {
|
||||
|
@ -81,6 +83,7 @@ class AggregatorForm(RestrictedFormMixin, ModelForm):
|
|||
"secret_id": "The secret ID for the aggregator service.",
|
||||
"secret_key": "The secret key for the aggregator service.",
|
||||
"poll_interval": "The interval in seconds to poll the aggregator service.",
|
||||
"link_group": "The link group to use for this aggregator connection.",
|
||||
"enabled": "Whether or not the aggregator connection is enabled.",
|
||||
}
|
||||
|
||||
|
@ -120,6 +123,7 @@ class PlatformForm(RestrictedFormMixin, ModelForm):
|
|||
"base_usd",
|
||||
"withdrawal_trigger",
|
||||
"payees",
|
||||
"link_group",
|
||||
"enabled",
|
||||
)
|
||||
help_texts = {
|
||||
|
@ -143,6 +147,7 @@ class PlatformForm(RestrictedFormMixin, ModelForm):
|
|||
"base_usd": "The amount in USD to keep in the platform.",
|
||||
"withdrawal_trigger": "The amount above the base USD to trigger a withdrawal.",
|
||||
"payees": "The wallet addresses to send profit concerning this platform to.",
|
||||
"link_group": "The link group to use for this platform.",
|
||||
"enabled": "Whether or not the platform connection is enabled.",
|
||||
}
|
||||
|
||||
|
@ -169,11 +174,12 @@ class AdForm(RestrictedFormMixin, ModelForm):
|
|||
"dist_list",
|
||||
"asset_list",
|
||||
"provider_list",
|
||||
"platforms",
|
||||
"aggregators",
|
||||
# "platforms",
|
||||
# "aggregators",
|
||||
"account_whitelist",
|
||||
"send_reference",
|
||||
"visible",
|
||||
"link_group",
|
||||
"enabled",
|
||||
)
|
||||
help_texts = {
|
||||
|
@ -185,11 +191,12 @@ class AdForm(RestrictedFormMixin, ModelForm):
|
|||
"dist_list": "Currency and country, space separated, one pair per line.",
|
||||
"asset_list": "List of assets to distribute ads for.",
|
||||
"provider_list": "List of providers to distribute ads for.",
|
||||
"platforms": "Enabled platforms for this ad",
|
||||
"aggregators": "Enabled aggregators for this ad",
|
||||
# "platforms": "Enabled platforms for this ad",
|
||||
# "aggregators": "Enabled aggregators for this ad",
|
||||
"account_whitelist": "List of account IDs to use, one per line.",
|
||||
"send_reference": "Whether or not to send the reference on new trades.",
|
||||
"visible": "Whether or not this ad is visible.",
|
||||
"link_group": "The link group to use for this ad.",
|
||||
"enabled": "Whether or not this ad is enabled.",
|
||||
}
|
||||
|
||||
|
@ -205,18 +212,18 @@ class AdForm(RestrictedFormMixin, ModelForm):
|
|||
help_text=Meta.help_texts["provider_list"],
|
||||
required=True,
|
||||
)
|
||||
platforms = forms.ModelMultipleChoiceField(
|
||||
queryset=Platform.objects.all(),
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
help_text=Meta.help_texts["platforms"],
|
||||
required=True,
|
||||
)
|
||||
aggregators = forms.ModelMultipleChoiceField(
|
||||
queryset=Aggregator.objects.all(),
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
help_text=Meta.help_texts["aggregators"],
|
||||
required=True,
|
||||
)
|
||||
# platforms = forms.ModelMultipleChoiceField(
|
||||
# queryset=Platform.objects.all(),
|
||||
# widget=forms.CheckboxSelectMultiple,
|
||||
# help_text=Meta.help_texts["platforms"],
|
||||
# required=True,
|
||||
# )
|
||||
# aggregators = forms.ModelMultipleChoiceField(
|
||||
# queryset=Aggregator.objects.all(),
|
||||
# widget=forms.CheckboxSelectMultiple,
|
||||
# help_text=Meta.help_texts["aggregators"],
|
||||
# required=True,
|
||||
# )
|
||||
|
||||
|
||||
class RequisitionForm(RestrictedFormMixin, ModelForm):
|
||||
|
@ -254,3 +261,70 @@ class WalletForm(RestrictedFormMixin, ModelForm):
|
|||
"name": "The name of the wallet.",
|
||||
"address": "The XMR address to send funds to.",
|
||||
}
|
||||
|
||||
|
||||
class LinkGroupForm(RestrictedFormMixin, ModelForm):
|
||||
class Meta:
|
||||
model = LinkGroup
|
||||
fields = (
|
||||
"name",
|
||||
"aggregators",
|
||||
"platforms",
|
||||
"platform_owner_cut_percentage",
|
||||
"requisition_owner_cut_percentage",
|
||||
"operator_cut_percentage",
|
||||
"enabled",
|
||||
)
|
||||
|
||||
help_texts = {
|
||||
"name": "The name of the link group.",
|
||||
"aggregators": "The aggregators to use.",
|
||||
"platforms": "The platforms to use.",
|
||||
"platform_owner_cut_percentage": "The percentage of the total profit of this group to give to the platform owners.",
|
||||
"requisition_owner_cut_percentage": "The percentage of the total profit of this group to give to the requisition owners.",
|
||||
"operator_cut_percentage": "The percentage of the total profit of this group to give to the operator.",
|
||||
"enabled": "Whether or not this link group is enabled.",
|
||||
}
|
||||
|
||||
platforms = forms.ModelMultipleChoiceField(
|
||||
queryset=Platform.objects.all(),
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
help_text=Meta.help_texts["platforms"],
|
||||
required=True,
|
||||
)
|
||||
aggregators = forms.ModelMultipleChoiceField(
|
||||
queryset=Aggregator.objects.all(),
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
help_text=Meta.help_texts["aggregators"],
|
||||
required=True,
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super(LinkGroupForm, self).clean()
|
||||
platform_owner_cut_percentage = cleaned_data.get(
|
||||
"platform_owner_cut_percentage"
|
||||
)
|
||||
requisition_owner_cut_percentage = cleaned_data.get(
|
||||
"requisition_owner_cut_percentage"
|
||||
)
|
||||
operator_cut_percentage = cleaned_data.get("operator_cut_percentage")
|
||||
total_sum = (
|
||||
platform_owner_cut_percentage
|
||||
+ requisition_owner_cut_percentage
|
||||
+ operator_cut_percentage
|
||||
)
|
||||
if total_sum != 100:
|
||||
self.add_error(
|
||||
"platform_owner_cut_percentage",
|
||||
f"The sum of the percentages must be 100, not {total_sum}.",
|
||||
)
|
||||
self.add_error(
|
||||
"requisition_owner_cut_percentage",
|
||||
f"The sum of the percentages must be 100, not {total_sum}.",
|
||||
)
|
||||
self.add_error(
|
||||
"operator_cut_percentage",
|
||||
f"The sum of the percentages must be 100, not {total_sum}.",
|
||||
)
|
||||
return
|
||||
return cleaned_data
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# Generated by Django 4.1.7 on 2023-03-18 10:12
|
||||
|
||||
import uuid
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0029_alter_requisition_id_alter_wallet_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='LinkGroup',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=255)),
|
||||
('platform_owner_cut_percentage', models.FloatField(default=0)),
|
||||
('requisition_owner_cut_percentage', models.FloatField(default=0)),
|
||||
('operator_cut_percentage', models.FloatField(default=0)),
|
||||
('enabled', models.BooleanField(default=True)),
|
||||
('aggregators', models.ManyToManyField(to='core.aggregator')),
|
||||
('platforms', models.ManyToManyField(to='core.platform')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -0,0 +1,45 @@
|
|||
# Generated by Django 4.1.7 on 2023-03-18 10:38
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0030_linkgroup'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='ad',
|
||||
name='aggregators',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='ad',
|
||||
name='platforms',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='linkgroup',
|
||||
name='aggregators',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='linkgroup',
|
||||
name='platforms',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ad',
|
||||
name='link_group',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.linkgroup'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aggregator',
|
||||
name='link_group',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.linkgroup'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='link_group',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.linkgroup'),
|
||||
),
|
||||
]
|
143
core/models.py
143
core/models.py
|
@ -50,6 +50,26 @@ class NotificationSettings(models.Model):
|
|||
return f"Notification settings for {self.user}"
|
||||
|
||||
|
||||
class LinkGroup(models.Model):
|
||||
"""
|
||||
A group linking Aggregators, Platforms and defining a percentage split
|
||||
that the owners of each should receive.
|
||||
"""
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
platform_owner_cut_percentage = models.FloatField(default=0)
|
||||
requisition_owner_cut_percentage = models.FloatField(default=0)
|
||||
operator_cut_percentage = models.FloatField(default=0)
|
||||
|
||||
enabled = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Aggregator(models.Model):
|
||||
"""
|
||||
A connection to an API aggregator to pull transactions from bank accounts.
|
||||
|
@ -70,6 +90,10 @@ class Aggregator(models.Model):
|
|||
|
||||
fetch_accounts = models.BooleanField(default=True)
|
||||
|
||||
link_group = models.ForeignKey(
|
||||
LinkGroup, on_delete=models.CASCADE, null=True, blank=True
|
||||
)
|
||||
|
||||
enabled = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
|
@ -85,36 +109,41 @@ class Aggregator(models.Model):
|
|||
|
||||
@classmethod
|
||||
def get_for_platform(cls, platform):
|
||||
aggregators = []
|
||||
ads = Ad.objects.filter(
|
||||
platforms=platform,
|
||||
enabled=True,
|
||||
)
|
||||
for ad in ads:
|
||||
for aggregator in ad.aggregators.all():
|
||||
if aggregator not in aggregators:
|
||||
aggregators.append(aggregator)
|
||||
# aggregators = []
|
||||
# linkgroups = LinkGroup.objects.filter(
|
||||
# platforms=platform,
|
||||
# enabled=True,
|
||||
# )
|
||||
# for link in linkgroups:
|
||||
# for aggregator in link.aggregators.all():
|
||||
# if aggregator not in aggregators:
|
||||
# aggregators.append(aggregator)
|
||||
platform_link = platform.link_group
|
||||
|
||||
return aggregators
|
||||
# return aggregators
|
||||
return cls.objects.filter(
|
||||
link_group=platform_link,
|
||||
)
|
||||
|
||||
@property
|
||||
def platforms(self):
|
||||
"""
|
||||
Get platforms for this aggregator.
|
||||
Do this by looking up Ads with the aggregator.
|
||||
Do this by looking up LinkGroups with the aggregator.
|
||||
Then, join them all together.
|
||||
"""
|
||||
platforms = []
|
||||
ads = Ad.objects.filter(
|
||||
aggregators=self,
|
||||
enabled=True,
|
||||
)
|
||||
for ad in ads:
|
||||
for platform in ad.platforms.all():
|
||||
if platform not in platforms:
|
||||
platforms.append(platform)
|
||||
return Platform.objects.filter(link_group=self.link_group)
|
||||
# platforms = []
|
||||
# linkgroups = LinkGroup.objects.filter(
|
||||
# aggregators=self,
|
||||
# enabled=True,
|
||||
# )
|
||||
# for link in linkgroups:
|
||||
# for platform in link.platforms.all():
|
||||
# if platform not in platforms:
|
||||
# platforms.append(platform)
|
||||
|
||||
return platforms
|
||||
# return platforms
|
||||
|
||||
@classmethod
|
||||
def get_currencies_for_platform(cls, platform):
|
||||
|
@ -168,6 +197,9 @@ class Wallet(models.Model):
|
|||
name = models.CharField(max_length=255)
|
||||
address = models.CharField(max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Platform(models.Model):
|
||||
"""
|
||||
|
@ -205,6 +237,10 @@ class Platform(models.Model):
|
|||
|
||||
payees = models.ManyToManyField(Wallet, blank=True)
|
||||
|
||||
link_group = models.ForeignKey(
|
||||
LinkGroup, on_delete=models.CASCADE, null=True, blank=True
|
||||
)
|
||||
|
||||
enabled = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
|
@ -214,7 +250,9 @@ class Platform(models.Model):
|
|||
ad_id = self.platform_ad_ids.get(platform_ad_id, None)
|
||||
if not ad_id:
|
||||
return None
|
||||
ad_object = Ad.objects.filter(id=ad_id, user=self.user, enabled=True).first()
|
||||
ad_object = Ad.objects.filter(
|
||||
id=ad_id, user=self.user, link_group=self.link_group, enabled=True
|
||||
).first()
|
||||
return ad_object
|
||||
|
||||
@classmethod
|
||||
|
@ -234,7 +272,9 @@ class Platform(models.Model):
|
|||
"""
|
||||
Get all ads linked to this platform.
|
||||
"""
|
||||
return Ad.objects.filter(user=self.user, enabled=True, platforms=self)
|
||||
return Ad.objects.filter(
|
||||
user=self.user, enabled=True, link_group=self.link_group
|
||||
)
|
||||
|
||||
@property
|
||||
def ads_assets(self):
|
||||
|
@ -343,36 +383,45 @@ class Platform(models.Model):
|
|||
|
||||
@classmethod
|
||||
def get_for_aggregator(cls, aggregator):
|
||||
platforms = []
|
||||
ads = Ad.objects.filter(
|
||||
aggregators=aggregator,
|
||||
enabled=True,
|
||||
)
|
||||
for ad in ads:
|
||||
for platform in ad.platforms.all():
|
||||
if platform not in platforms:
|
||||
platforms.append(platform)
|
||||
# platforms = []
|
||||
# linkgroups = LinkGroup.objects.filter(
|
||||
# aggregators=aggregator,
|
||||
# enabled=True,
|
||||
# )
|
||||
# for link in linkgroups:
|
||||
# for platform in link.platforms.all():
|
||||
# if platform not in platforms:
|
||||
# platforms.append(platform)
|
||||
|
||||
return platforms
|
||||
# return platforms
|
||||
|
||||
aggregator_link = aggregator.link_group
|
||||
return cls.objects.filter(
|
||||
link_group=aggregator_link,
|
||||
)
|
||||
|
||||
@property
|
||||
def aggregators(self):
|
||||
"""
|
||||
Get aggregators for this platform.
|
||||
Do this by looking up Ads with the platform.
|
||||
Do this by looking up LinkGroups with the platform.
|
||||
Then, join them all together.
|
||||
"""
|
||||
aggregators = []
|
||||
ads = Ad.objects.filter(
|
||||
platforms=self,
|
||||
enabled=True,
|
||||
)
|
||||
for ad in ads:
|
||||
for aggregator in ad.aggregators.all():
|
||||
if aggregator not in aggregators:
|
||||
aggregators.append(aggregator)
|
||||
# aggregators = []
|
||||
# linkgroups = LinkGroup.objects.filter(
|
||||
# platforms=self,
|
||||
# enabled=True,
|
||||
# )
|
||||
# for link in linkgroups:
|
||||
# for aggregator in link.aggregators.all():
|
||||
# if aggregator not in aggregators:
|
||||
# aggregators.append(aggregator)
|
||||
|
||||
return aggregators
|
||||
# return aggregators
|
||||
|
||||
return Aggregator.objects.filter(
|
||||
link_group=self.link_group,
|
||||
)
|
||||
|
||||
def get_requisition(self, aggregator_id, requisition_id):
|
||||
"""
|
||||
|
@ -425,15 +474,15 @@ class Ad(models.Model):
|
|||
asset_list = models.ManyToManyField(Asset)
|
||||
provider_list = models.ManyToManyField(Provider)
|
||||
|
||||
platforms = models.ManyToManyField(Platform)
|
||||
aggregators = models.ManyToManyField(Aggregator)
|
||||
|
||||
account_map = models.JSONField(default=dict)
|
||||
account_whitelist = models.TextField(null=True, blank=True)
|
||||
|
||||
send_reference = models.BooleanField(default=True)
|
||||
|
||||
visible = models.BooleanField(default=True)
|
||||
link_group = models.ForeignKey(
|
||||
LinkGroup, on_delete=models.CASCADE, null=True, blank=True
|
||||
)
|
||||
enabled = models.BooleanField(default=True)
|
||||
|
||||
@property
|
||||
|
|
|
@ -272,7 +272,10 @@
|
|||
Platform Connections
|
||||
</a>
|
||||
<a class="navbar-item" href="{% url 'wallets' type='page' %}">
|
||||
Wallets
|
||||
Profit Wallets
|
||||
</a>
|
||||
<a class="navbar-item" href="{% url 'linkgroups' type='page' %}">
|
||||
Link Groups
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -28,6 +28,19 @@
|
|||
<td>{{ item.accounts|length }}</td>
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<button
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-get="{% url 'requisition_update' type=type aggregator_id=pk req_id=item.id %}"
|
||||
hx-trigger="click"
|
||||
hx-target="#modals-here"
|
||||
hx-swap="innerHTML"
|
||||
class="button">
|
||||
<span class="icon-text">
|
||||
<span class="icon has-text-black" data-tooltip="Configure">
|
||||
<i class="fa-solid fa-wrench"></i>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-delete="{% url 'req_delete' type=type pk=pk req_id=item.id %}"
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
{% load cache %}
|
||||
{% load cachalot cache %}
|
||||
{% get_last_invalidation 'core.LinkGroup' as last %}
|
||||
{% include 'mixins/partials/notify.html' %}
|
||||
{# cache 600 objects_linkgroups request.user.id object_list type last #}
|
||||
<table
|
||||
class="table is-fullwidth is-hoverable"
|
||||
hx-target="#{{ context_object_name }}-table"
|
||||
id="{{ context_object_name }}-table"
|
||||
hx-swap="outerHTML"
|
||||
hx-trigger="{{ context_object_name_singular }}Event from:body"
|
||||
hx-get="{{ list_url }}">
|
||||
<thead>
|
||||
<th>id</th>
|
||||
<th>user</th>
|
||||
<th>name</th>
|
||||
<th>platform</th>
|
||||
<th>requisition</th>
|
||||
<th>operator</th>
|
||||
<th>enabled</th>
|
||||
<th>actions</th>
|
||||
</thead>
|
||||
{% for item in object_list %}
|
||||
<tr>
|
||||
<td>
|
||||
<a
|
||||
class="has-text-grey"
|
||||
onclick="window.prompt('Copy to clipboard: Ctrl+C, Enter', '{{ item.id }}');">
|
||||
<span class="icon" data-tooltip="Copy to clipboard">
|
||||
<i class="fa-solid fa-copy" aria-hidden="true"></i>
|
||||
</span>
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ item.user }}</td>
|
||||
<td>{{ item.name }}</td>
|
||||
<td>{{ item.platform_owner_cut_percentage }}</td>
|
||||
<td>{{ item.requisition_owner_cut_percentage }}</td>
|
||||
<td>{{ item.operator_cut_percentage }}</td>
|
||||
<td>
|
||||
{% if item.enabled %}
|
||||
<span class="icon">
|
||||
<i class="fa-solid fa-check"></i>
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="icon">
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<button
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-get="{% url 'linkgroup_update' type=type pk=item.id %}"
|
||||
hx-trigger="click"
|
||||
hx-target="#{{ type }}s-here"
|
||||
hx-swap="innerHTML"
|
||||
class="button">
|
||||
<span class="icon-text">
|
||||
<span class="icon">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-delete="{% url 'linkgroup_delete' type=type pk=item.id %}"
|
||||
hx-trigger="click"
|
||||
hx-target="#modals-here"
|
||||
hx-swap="innerHTML"
|
||||
hx-confirm="Are you sure you wish to delete {{ item.name }}?"
|
||||
class="button">
|
||||
<span class="icon-text">
|
||||
<span class="icon">
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
{# endcache #}
|
|
@ -1,6 +1,6 @@
|
|||
{% load cache %}
|
||||
{% load cachalot cache %}
|
||||
{% get_last_invalidation 'core.Platform' as last %}
|
||||
{% get_last_invalidation 'core.Trade' as last %}
|
||||
{% include 'mixins/partials/notify.html' %}
|
||||
{# cache 600 objects_platform_trades request.user.id object_list type last #}
|
||||
{% for platform_name, trade_map in object_list.items %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{% load cache %}
|
||||
{% load cachalot cache %}
|
||||
{% get_last_invalidation 'core.Ad' as last %}
|
||||
{% get_last_invalidation 'core.Wallet' as last %}
|
||||
{% include 'mixins/partials/notify.html' %}
|
||||
{# cache 600 objects_ads request.user.id object_list type last #}
|
||||
{# cache 600 objects_wallets request.user.id object_list type last #}
|
||||
<table
|
||||
class="table is-fullwidth is-hoverable"
|
||||
hx-target="#{{ context_object_name }}-table"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.test import TransactionTestCase
|
||||
|
||||
from core.clients.platform import LocalPlatformClient
|
||||
from core.models import Ad, Asset, Provider, Requisition
|
||||
from core.models import Ad, Asset, LinkGroup, Provider, Requisition
|
||||
from core.tests.helpers import AggregatorPlatformMixin
|
||||
|
||||
|
||||
|
@ -93,11 +93,22 @@ class TestPlatform(AggregatorPlatformMixin, TransactionTestCase):
|
|||
|
||||
self.ad.asset_list.set([asset])
|
||||
self.ad.provider_list.set([provider])
|
||||
self.ad.platforms.set([self.platform])
|
||||
self.ad.aggregators.set([self.aggregator])
|
||||
# self.ad.platforms.set([self.platform])
|
||||
# self.ad.aggregators.set([self.aggregator])
|
||||
|
||||
self.ad.save()
|
||||
|
||||
self.linkgroup = LinkGroup.objects.create(
|
||||
user=self.user,
|
||||
name="Test",
|
||||
)
|
||||
|
||||
self.aggregator.link_group = self.linkgroup
|
||||
self.aggregator.save()
|
||||
|
||||
self.platform.link_group = self.linkgroup
|
||||
self.platform.save()
|
||||
|
||||
self.req = Requisition.objects.create(
|
||||
user=self.user,
|
||||
aggregator=self.aggregator,
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from mixins.views import ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate
|
||||
from two_factor.views.mixins import OTPRequiredMixin
|
||||
|
||||
from core.forms import LinkGroupForm
|
||||
from core.models import LinkGroup
|
||||
|
||||
|
||||
class LinkGroupList(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
|
||||
list_template = "partials/linkgroup-list.html"
|
||||
model = LinkGroup
|
||||
page_title = "List of link groups"
|
||||
page_subtitle = "Link groups are used to link aggregators and platforms"
|
||||
|
||||
list_url_name = "linkgroups"
|
||||
list_url_args = ["type"]
|
||||
|
||||
submit_url_name = "linkgroup_create"
|
||||
|
||||
|
||||
class LinkGroupCreate(LoginRequiredMixin, OTPRequiredMixin, ObjectCreate):
|
||||
model = LinkGroup
|
||||
form_class = LinkGroupForm
|
||||
|
||||
submit_url_name = "linkgroup_create"
|
||||
|
||||
|
||||
class LinkGroupUpdate(LoginRequiredMixin, OTPRequiredMixin, ObjectUpdate):
|
||||
model = LinkGroup
|
||||
form_class = LinkGroupForm
|
||||
|
||||
submit_url_name = "linkgroup_update"
|
||||
|
||||
|
||||
class LinkGroupDelete(LoginRequiredMixin, OTPRequiredMixin, ObjectDelete):
|
||||
model = LinkGroup
|
|
@ -9,7 +9,7 @@ from core.models import Wallet
|
|||
class WalletList(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
|
||||
list_template = "partials/wallet-list.html"
|
||||
model = Wallet
|
||||
page_title = "List of wallets"
|
||||
page_title = "List of wallets to send profit to"
|
||||
|
||||
list_url_name = "wallets"
|
||||
list_url_args = ["type"]
|
||||
|
|
Loading…
Reference in New Issue