Skip to content

Commit 2bb4d8d

Browse files
Merge pull request #388 from MySecondLanguage/fixed-invoice-logo-upload
Fixed invoice logo upload
2 parents f392208 + e4c026a commit 2bb4d8d

File tree

14 files changed

+213
-23
lines changed

14 files changed

+213
-23
lines changed

nxtbn/core/admin_mutation.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
from nxtbn.core import CurrencyTypes
55
from nxtbn.core.admin_permissions import gql_required_perm
6-
from nxtbn.core.admin_types import CurrencyExchangeType
7-
from nxtbn.core.models import CurrencyExchange
6+
from nxtbn.core.admin_types import CurrencyExchangeType, InvoiceSettingsInput, InvoiceSettingsType
7+
from nxtbn.core.models import CurrencyExchange, InvoiceSettings
88
from nxtbn.users import UserRole
99

1010
class CurrencyExchangeInput(graphene.InputObjectType):
@@ -77,9 +77,33 @@ def mutate(root, info, id):
7777

7878
currency_exchange.delete() # Delete the record
7979
return DeleteCurrencyExchange(success=True) # Return success
80+
81+
82+
83+
class CreateInvoiceSettings(graphene.Mutation):
84+
class Arguments:
85+
input = InvoiceSettingsInput()
86+
87+
invoice_settings = graphene.Field(InvoiceSettingsType)
88+
89+
@gql_required_perm(InvoiceSettings, 'add_invoicesettings')
90+
@staticmethod
91+
def mutate(root, info, input):
92+
invoice_settings = InvoiceSettings.objects.create(
93+
store_name=input.store_name,
94+
store_address=input.store_address,
95+
city=input.city,
96+
country=input.country,
97+
postal_code=input.postal_code,
98+
contact_email=input.contact_email,
99+
contact_phone=input.contact_phone,
100+
is_default=input.is_default,
101+
)
102+
return CreateInvoiceSettings(invoice_settings=invoice_settings)
80103

81104

82105
class CoreMutation(graphene.ObjectType):
83106
update_exchange_rate = UpdateCurrencyExchange.Field()
84107
create_exchange_rate = CreateCurrencyExchange.Field()
85-
delete_exchange_rate = DeleteCurrencyExchange.Field()
108+
delete_exchange_rate = DeleteCurrencyExchange.Field()
109+
create_invoice_settings = CreateInvoiceSettings.Field()

nxtbn/core/admin_queries.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ class AdminCoreQuery(graphene.ObjectType):
1313
currency_exchanges = DjangoFilterConnectionField(CurrencyExchangeType)
1414
currency_exchange = graphene.Field(CurrencyExchangeType, id=graphene.ID(required=True))
1515
allowed_currency_list = graphene.List(AdminCurrencyTypesEnum)
16-
default_invoice_settings = graphene.Field(InvoiceSettingsType)
16+
invoice_setting = graphene.Field(InvoiceSettingsType, invoice_settings_id=graphene.ID(required=False))
17+
invoice_settings = DjangoFilterConnectionField(InvoiceSettingsType)
1718

1819
@gql_store_admin_required
1920
def resolve_currency_exchanges(self, info, **kwargs):
@@ -39,6 +40,11 @@ def resolve_allowed_currency_list(self, info):
3940
]
4041

4142
@gql_store_admin_required
42-
def resolve_default_invoice_settings(self, info):
43-
site_id = getattr(settings, 'SITE_ID', 1)
44-
return InvoiceSettings.objects.get(site__id=site_id)
43+
def resolve_invoice_setting(self, info, invoice_settings_id=None, **kwargs):
44+
if not invoice_settings_id:
45+
return InvoiceSettings.objects.get(is_default=True)
46+
return InvoiceSettings.objects.get(id=invoice_settings_id)
47+
48+
@gql_store_admin_required
49+
def resolve_invoice_settings(self, info, **kwargs):
50+
return InvoiceSettings.objects.all()

nxtbn/core/admin_types.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,31 @@ class Meta:
2020

2121
class InvoiceSettingsType(DjangoObjectType):
2222
db_id = graphene.ID(source='id')
23+
logo = graphene.String()
24+
25+
def resolve_logo(self, info):
26+
if self.logo:
27+
return info.context.build_absolute_uri(self.logo.url)
28+
return None
2329
class Meta:
2430
model = InvoiceSettings
2531
fields = "__all__"
32+
interfaces = (relay.Node,)
33+
filter_fields = {
34+
'store_name': ['exact', 'icontains'],
35+
}
36+
37+
38+
class InvoiceSettingsInput(graphene.InputObjectType):
39+
store_name = graphene.String()
40+
store_address = graphene.String()
41+
city = graphene.String()
42+
country = graphene.String()
43+
postal_code = graphene.String()
44+
contact_email = graphene.String()
45+
contact_phone = graphene.String()
46+
is_default = graphene.Boolean()
47+
2648

2749
class AdminCurrencyTypesEnum(graphene.ObjectType):
2850
value = graphene.String()

nxtbn/core/api/dashboard/serializers.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ class Meta:
2323
'country',
2424
'postal_code',
2525
'contact_email',
26+
'is_default',
2627
]
2728

28-
29+
30+
31+
class InvoiceSettingsLogoSerializer(serializers.ModelSerializer):
32+
class Meta:
33+
model = InvoiceSettings
34+
fields = ['id', 'logo']
35+
read_only_fields = ['id']

nxtbn/core/api/dashboard/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
urlpatterns = [
66
path('site-settings/', core_views.SiteSettingsView.as_view(), name='site-settings'),
7-
path('invoice-settings/', core_views.InvoiceSettingsView.as_view(), name='invoice-settings'),
7+
path('invoice-settings/<int:pk>/', core_views.InvoiceSettingsView.as_view(), name='invoice-settings'),
8+
path('invoice-settings/upload-logo/<int:id>/', core_views.InvoiceSettingsLogoUploadAPIView.as_view(), name='upload-logo'),
9+
810
path('system-status/', status_views.SystemStatusAPIView.as_view(), name='system-status'),
911
path('db-tables-details/', status_views.DatabaseTableInfoAPIView.as_view(), name='db-details'),
1012
path('language-list/', core_views.LanguageChoicesAPIView.as_view(), name='language-list'),

nxtbn/core/api/dashboard/views.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
from nxtbn.core import LanguageChoices
2929
from nxtbn.core.admin_permissions import GranularPermission, IsStoreAdmin, IsStoreStaff
30-
from nxtbn.core.api.dashboard.serializers import InvoiceSettingsSerializer, SiteSettingsSerializer
30+
from nxtbn.core.api.dashboard.serializers import InvoiceSettingsLogoSerializer, InvoiceSettingsSerializer, SiteSettingsSerializer
3131
from nxtbn.core.models import InvoiceSettings, SiteSettings
3232
from nxtbn.users import UserRole
3333

@@ -54,16 +54,19 @@ class InvoiceSettingsView(generics.RetrieveUpdateAPIView):
5454
permission_classes = (IsStoreAdmin,)
5555
queryset = InvoiceSettings.objects.all()
5656
serializer_class = InvoiceSettingsSerializer
57+
lookup_field = 'pk'
58+
5759

5860

61+
class InvoiceSettingsLogoUploadAPIView(generics.UpdateAPIView):
62+
permission_classes = (IsStoreAdmin,)
63+
queryset = InvoiceSettings.objects.all()
64+
serializer_class = InvoiceSettingsLogoSerializer
65+
lookup_field = 'id'
5966

60-
def get_object(self):
61-
current_site = get_current_site(self.request)
62-
try:
63-
return InvoiceSettings.objects.get(site=current_site)
64-
except InvoiceSettings.DoesNotExist:
65-
raise NotFound("Site settings for the current site do not exist.")
66-
67+
def partial_update(self, request, *args, **kwargs):
68+
kwargs['partial'] = True
69+
return self.update(request, *args, **kwargs)
6770

6871

6972
class LanguageChoicesAPIView(APIView):
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 4.2.11 on 2025-02-14 07:57
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("core", "0003_alter_currencyexchange_base_currency_and_more"),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name="invoicesettings",
15+
name="site",
16+
),
17+
]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Generated by Django 4.2.11 on 2025-02-14 08:04
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("core", "0004_remove_invoicesettings_site"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="invoicesettings",
15+
name="is_default",
16+
field=models.BooleanField(
17+
default=False, help_text="If this is the default invoice settings."
18+
),
19+
),
20+
]

nxtbn/core/models.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ class Meta:
162162
verbose_name_plural = "Site Settings"
163163

164164
class InvoiceSettings(models.Model): # This info will be seen in the invoice
165-
site = models.OneToOneField(Site, on_delete=models.CASCADE, null=True, blank=True, help_text="The site this configuration applies to.")
166165
store_name = models.CharField(max_length=100, blank=True, null=True, help_text="Name of the store.")
167166
store_address = models.TextField(blank=True, null=True, help_text="Physical address of the store.")
168167
city = models.CharField(max_length=100, blank=True, null=True, help_text="City of the store.")
@@ -171,6 +170,15 @@ class InvoiceSettings(models.Model): # This info will be seen in the invoice
171170
logo = models.ImageField(upload_to='logos/', blank=True, null=True, help_text="Logo of the site.")
172171
contact_email = models.EmailField(blank=True, null=True, help_text="Contact email for site administrators.")
173172
contact_phone = models.CharField(max_length=20, blank=True, null=True, help_text="Contact phone number for site administrators.")
173+
is_default = models.BooleanField(default=False, help_text="If this is the default invoice settings.")
174+
175+
def save(self, *args, **kwargs):
176+
if self.is_default:
177+
InvoiceSettings.objects.filter(is_default=True).update(is_default=False)
178+
else:
179+
if not InvoiceSettings.objects.filter(is_default=True).exists():
180+
raise ValidationError("There must be at least one default invoice setting.")
181+
super().save(*args, **kwargs)
174182

175183

176184

nxtbn/core/receivers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ def create_default_site_settings(sender, **kwargs):
3131
)
3232

3333
InvoiceSettings.objects.create(
34-
site=site,
3534
store_name="nxtbn commerce",
3635
store_address="Default Store Address",
3736
city="Default City",
3837
country="Default Country",
3938
postal_code="123456",
4039
contact_email="[email protected]",
40+
is_default=True,
4141
)
4242

4343
if Warehouse.objects.count() == 0:

0 commit comments

Comments
 (0)