Skip to content

Commit

Permalink
Production deployment v1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
patelradhika committed Sep 10, 2024
1 parent 428dad7 commit 2751769
Show file tree
Hide file tree
Showing 18 changed files with 328 additions and 24 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/dev-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Build and Push Docker Image to Dev

on:
push:
branches:
- dev

env:
PROJECT_ID: spry-bricolage-298920
REGION: us
IMAGE_NAME: us-docker.pkg.dev/spry-bricolage-298920/gcr.io/dev/buildly-core

jobs:
build:
name: Build and Push to GCR
runs-on: ubuntu-latest
steps:
- name: "Checkout"
uses: actions/checkout@v3

- id: "auth"
uses: "google-github-actions/auth@v1"
with:
credentials_json: "${{ secrets.GCR_JSON_KEY }}"

- name: "Set up Cloud SDK"
uses: "google-github-actions/setup-gcloud@v1"

- name: "Use gcloud CLI"
run: "gcloud info"

- name: "Docker auth"
run: |-
gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev --quiet
- name: Build docker image
run: docker build -t $IMAGE_NAME:latest .

- name: Push to Google Artifact Registry
run: docker push $IMAGE_NAME:latest
12 changes: 6 additions & 6 deletions .github/workflows/unit_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ jobs:
unit_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v3

- name: Build the docker-compose stack
run: docker-compose build
- name: Build the docker compose stack
run: docker compose build

- name: Setup docker containers
run: docker-compose up -d
run: docker compose up -d

- name: Check running containers
run: docker ps -a

- name: Run unit test case
run: docker-compose run --entrypoint '/usr/bin/env' --rm buildly bash scripts/run-tests.sh --keepdb
run: docker compose run --entrypoint '/usr/bin/env' --rm buildly bash scripts/run-tests.sh --keepdb

- name: Stop docker container
run: docker-compose down
run: docker compose down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM --platform=linux/amd64 python:3.7-alpine3.10
FROM python:3.7-alpine3.10

# Do not buffer log messages in memory; some messages can be lost otherwise
ENV PYTHONUNBUFFERED 1
Expand All @@ -22,7 +22,7 @@ RUN ./scripts/collectstatic.sh
RUN apk del .build-deps

# Specify tag name to be created on github
LABEL version="1.3.0"
LABEL version="1.4.0"

EXPOSE 8080
ENTRYPOINT ["bash", "/code/scripts/docker-entrypoint.sh"]
2 changes: 1 addition & 1 deletion buildly/management/commands/loadinitialdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def _create_user(self):
su = CoreUser.objects.create_superuser(
first_name='System',
last_name='Admin',
username='67OAI8DD5I1O',
username='admin@example.com',
email='admin@example.com',
password=user_password,
organization=self._default_org,
Expand Down
2 changes: 2 additions & 0 deletions core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class CoreUserAdmin(UserAdmin):
'title',
'is_active',
'user_timezone',
'user_language',
)
display = 'Core User'
list_filter = ('is_staff', 'organization')
Expand All @@ -82,6 +83,7 @@ class CoreUserAdmin(UserAdmin):
'contact_info',
'organization',
'user_timezone',
'user_language',
)
},
),
Expand Down
12 changes: 10 additions & 2 deletions core/email_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@ def send_email(
context: dict,
template_name: str,
html_template_name: str = None,
attachments: list = [],
) -> int:
text_content = loader.render_to_string(template_name, context, using=None)
html_content = (
loader.render_to_string(html_template_name, context, using=None)
if html_template_name
else None
)
return send_email_body(email_address, subject, text_content, html_content)
return send_email_body(email_address, subject, text_content, html_content, attachments)


def send_email_body(
email_address: str, subject: str, text_content: str, html_content: str = None
email_address: str, subject: str, text_content: str, html_content: str = None, attachments: list = []
) -> int:
msg = EmailMultiAlternatives(
from_email=settings.DEFAULT_FROM_EMAIL,
Expand All @@ -32,4 +33,11 @@ def send_email_body(
msg.reply_to = [settings.DEFAULT_REPLYTO_EMAIL]
if html_content:
msg.attach_alternative(html_content, "text/html")
if len(attachments) > 0:
for attachment in attachments:
msg.attach(
attachment.get('name'),
attachment.get('file'),
'application/pdf'
)
return msg.send()
24 changes: 24 additions & 0 deletions core/migrations/0015_auto_20240520_0833.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 2.2.10 on 2024-05-20 08:33

import django.contrib.postgres.fields
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0014_auto_20240313_0822'),
]

operations = [
migrations.AddField(
model_name='organization',
name='is_reseller',
field=models.BooleanField(default=False, verbose_name='To mark as reseller'),
),
migrations.AddField(
model_name='organization',
name='reseller_customer_orgs',
field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=63), blank=True, help_text='All customer organizations associated with this reseller.', null=True, size=None),
),
]
18 changes: 18 additions & 0 deletions core/migrations/0016_coreuser_user_language.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.10 on 2024-05-27 08:54

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0015_auto_20240520_0833'),
]

operations = [
migrations.AddField(
model_name='coreuser',
name='user_language',
field=models.CharField(blank=True, max_length=255, null=True),
),
]
8 changes: 8 additions & 0 deletions core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,13 @@ class Organization(models.Model):
default=list,
)
enable_fujitsu_verification = models.BooleanField('Enable Fujitsu Integration for verification of shipment data', default=False)
is_reseller = models.BooleanField('To mark as reseller', default=False)
reseller_customer_orgs = ArrayField(
models.CharField(max_length=63),
blank=True,
null=True,
help_text="All customer organizations associated with this reseller.",
)

class Meta:
ordering = ('name',)
Expand Down Expand Up @@ -298,6 +305,7 @@ class CoreUser(AbstractUser):
sms_number = models.CharField(blank=True, null=True, max_length=15)
whatsApp_number = models.CharField(blank=True, null=True, max_length=15)
user_timezone = models.CharField(blank=True, null=True, max_length=255)
user_language = models.CharField(blank=True, null=True, max_length=255)
last_gdpr_shown = models.DateTimeField(null=True, blank=True)

REQUIRED_FIELDS = []
Expand Down
29 changes: 25 additions & 4 deletions core/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ class Meta:
'whatsApp_number',
'user_timezone',
'last_gdpr_shown',
'user_language',
)
read_only_fields = ('core_user_uuid', 'organization')
depth = 1
Expand Down Expand Up @@ -192,8 +193,16 @@ def create(self, validated_data):
+ str(organization.organization_uuid)
+ '&unit_of_measure_for=Time%20Zone'
)
uom_language_url = (
settings.TP_SHIPMENT_URL
+ 'unit_of_measure/?organization_uuid='
+ str(organization.organization_uuid)
+ '&unit_of_measure_for=Language'
)
default_timezone = requests.get(uom_timezone_url).json()[0]
default_language = requests.get(uom_language_url).json()[0]
coreuser.user_timezone = default_timezone['unit_of_measure']
coreuser.user_language = default_language['unit_of_measure']

coreuser.core_groups.set(core_groups)
coreuser.save()
Expand Down Expand Up @@ -232,6 +241,7 @@ class CoreUserProfileSerializer(serializers.Serializer):
sms_number = serializers.CharField(required=False)
whatsApp_number = serializers.CharField(required=False)
user_timezone = serializers.CharField(required=False)
user_language = serializers.CharField(required=False)
last_gdpr_shown = serializers.DateTimeField(required=False)

class Meta:
Expand All @@ -249,6 +259,7 @@ class Meta:
'whatsApp_number',
'user_timezone',
'last_gdpr_shown',
'user_language',
)

def update(self, instance, validated_data):
Expand All @@ -274,9 +285,8 @@ def update(self, instance, validated_data):
)
instance.sms_number = validated_data.get('sms_number', instance.sms_number)
instance.whatsApp_number = validated_data.get('whatsApp_number', instance.whatsApp_number)
instance.user_timezone = validated_data.get(
'user_timezone', instance.user_timezone
)
instance.user_timezone = validated_data.get('user_timezone', instance.user_timezone)
instance.user_language = validated_data.get('user_language', instance.user_language)
instance.last_gdpr_shown = validated_data.get('last_gdpr_shown', instance.last_gdpr_shown)
password = validated_data.get('password', None)
if password is not None:
Expand All @@ -299,6 +309,7 @@ class CoreUserInvitationSerializer(serializers.Serializer):
temperature = serializers.CharField(required=False)
weight = serializers.CharField(required=False)
org_timezone = serializers.CharField(required=False)
org_language = serializers.CharField(required=False)
user_role = serializers.CharField(required=False)


Expand Down Expand Up @@ -461,13 +472,23 @@ class CoreUserEmailAlertSerializer(serializers.Serializer):

class CoreUserStatusBatteryAlertSerializer(serializers.Serializer):
"""
Serializer for email alert of shipment
Serializer for email status or battery alert of shipment
"""

organization_uuid = serializers.UUIDField()
message = serializers.JSONField()


class CoreUserEmailShipmentReporSerializer(serializers.Serializer):
"""
Serializer for email shipment report
"""

shipment_name = serializers.CharField()
user_email = serializers.CharField()
report_pdf = serializers.FileField()


class OrganizationTypeSerializer(serializers.ModelSerializer):
id = serializers.ReadOnlyField()

Expand Down
1 change: 1 addition & 0 deletions core/tests/test_coreuserview.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ class TestCoreUserRead(object):
'whatsApp_number',
'user_timezone',
'last_gdpr_shown',
'user_language',
}

def test_coreuser_list(self, request_factory, org_member):
Expand Down
3 changes: 3 additions & 0 deletions core/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ def test_org_serializer(request_factory, org):
'default_measurement_interval',
'enable_fujitsu_verification',
'alerts_to_suppress',
'is_reseller',
'reseller_customer_orgs',
]
assert set(data.keys()) == set(keys)

Expand Down Expand Up @@ -88,6 +90,7 @@ def test_core_user_serializer(request_factory, org_member):
'whatsApp_number',
'user_timezone',
'last_gdpr_shown',
'user_language',
]
assert set(data.keys()) == set(keys)
assert isinstance(data['organization'], dict)
14 changes: 12 additions & 2 deletions core/views/coregroup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from rest_framework import viewsets
from rest_framework.response import Response

from core.models import CoreGroup
from core.models import CoreGroup, Organization
from core.serializers import CoreGroupSerializer
from core.permissions import IsOrgMember

Expand All @@ -22,7 +22,17 @@ def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
if not request.user.is_global_admin:
q1 = queryset.filter(organization=None)
q2 = queryset.filter(organization_id=request.user.organization_id)
organization_id = request.user.organization_id
if request.user.is_org_admin:
reseller_orgs = [organization_id]
org = Organization.objects.get(pk=organization_id)
if org.is_reseller and org.reseller_customer_orgs is not None and len(org.reseller_customer_orgs) > 0:
for ro in org.reseller_customer_orgs:
reseller_orgs.append(ro)

q2 = queryset.filter(organization_id__in=reseller_orgs)
else:
q2 = queryset.filter(organization_id=organization_id)
queryset = q1.union(q2, all=True)
return Response(self.get_serializer(queryset, many=True).data)

Expand Down
Loading

0 comments on commit 2751769

Please sign in to comment.