diff --git a/.github/workflows/deploy_api.yml b/.github/workflows/deploy_api.yml index 3e2e3c59..9df543c0 100644 --- a/.github/workflows/deploy_api.yml +++ b/.github/workflows/deploy_api.yml @@ -49,7 +49,7 @@ jobs: echo "Starting redis service..." sudo systemctl start redis echo "Starting gunicorn..." - nohup sh -c 'gunicorn -w 4 marketplace.wsgi:application > gunicorn.out 2>&1' & + nohup sh -c 'gunicorn -w 4 --access-logfile - --error-logfile - --timeout 300 marketplace.wsgi:application > gunicorn.out 2>&1' & echo "Gunicorn started." echo "Starting celery worker..." nohup sh -c 'celery -A marketplace worker -l info > celery_worker.out 2>&1' & diff --git a/.github/workflows/deploy_prod_api.yml b/.github/workflows/deploy_prod_api.yml index edbdf38b..e5b4bf3c 100644 --- a/.github/workflows/deploy_prod_api.yml +++ b/.github/workflows/deploy_prod_api.yml @@ -51,7 +51,7 @@ jobs: echo "Starting redis service..." sudo systemctl start redis echo "Starting gunicorn..." - nohup sh -c 'gunicorn -w 4 marketplace.wsgi:application > gunicorn.out 2>&1' & + nohup sh -c 'gunicorn -w 4 --access-logfile - --error-logfile - --timeout 300 marketplace.wsgi:application > gunicorn.out 2>&1' & echo "Gunicorn started." echo "Starting celery worker..." nohup sh -c 'celery -A marketplace worker -l info > celery_worker.out 2>&1' & diff --git a/.github/workflows/deploy_ui.yml b/.github/workflows/deploy_ui.yml index b3f86279..c6146860 100644 --- a/.github/workflows/deploy_ui.yml +++ b/.github/workflows/deploy_ui.yml @@ -42,7 +42,7 @@ jobs: npm install npm run build sudo systemctl restart nginx - pm2 stop marketplace + pm2 delete marketplace pm2 start npm --name marketplace -- start - name: Remove Github Actions IP from security group diff --git a/src/api/marketplace/accounts/serializers.py b/src/api/marketplace/accounts/serializers.py index 394d9494..2bc6f3b5 100644 --- a/src/api/marketplace/accounts/serializers.py +++ b/src/api/marketplace/accounts/serializers.py @@ -25,46 +25,6 @@ from django.shortcuts import get_object_or_404 from django.db.models import Avg - -class BusinessAccountMetaDataSerializer(serializers.ModelSerializer): - influencer_ids = serializers.SerializerMethodField(read_only=True) - is_twitter_connected = serializers.SerializerMethodField(read_only=True) - is_wallet_connected = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = BusinessAccountMetaData - fields = "__all__" - - def get_influencer_ids(self, business_meta_data): - completed_orders = Order.objects.filter( - buyer=business_meta_data.user_account, status="completed" - ) - influencer_ids = set() - - for completed_order in completed_orders: - completed_order_items = OrderItem.objects.filter(order_id=completed_order) - package_ids = completed_order_items.values_list("package_id", flat=True) - influencers = Package.objects.filter(id__in=package_ids).values_list( - "influencer_id", flat=True - ) - influencer_ids.update(influencers) - - return list(influencer_ids) - - def get_is_twitter_connected(self, business_meta_data): - userAccount = business_meta_data.user_account - if userAccount.twitter_account: - return True - return False - - - def get_is_wallet_connected(self, business_meta_data): - user_wallet = Wallet.objects.filter(user_id = business_meta_data.user_account) - if(user_wallet): - return True - return False - - class CategoryMasterSerializer(serializers.ModelSerializer): class Meta: model = CategoryMaster @@ -125,7 +85,7 @@ def get_user_id(self, twitter_account): def get_service_types(self, twitter_account): services = Service.objects.filter( - package__influencer__twitter_account=twitter_account + package__influencer__twitter_account=twitter_account, deleted_at=None ) # Extract service types and prices @@ -268,6 +228,52 @@ def update(self, instance, validated_data): return instance +class BusinessAccountMetaDataSerializer(serializers.ModelSerializer): + influencer_ids = serializers.SerializerMethodField(read_only=True) + is_twitter_connected = serializers.SerializerMethodField(read_only=True) + is_wallet_connected = serializers.SerializerMethodField(read_only=True) + user_twitter_profile_image = serializers.SerializerMethodField(read_only=True) + user_account = UserSerializer(read_only=True) + + class Meta: + model = BusinessAccountMetaData + fields = "__all__" + + def get_influencer_ids(self, business_meta_data): + completed_orders = Order.objects.filter( + buyer=business_meta_data.user_account, status="completed" + ) + influencer_ids = set() + + for completed_order in completed_orders: + completed_order_items = OrderItem.objects.filter(order_id=completed_order) + package_ids = completed_order_items.values_list("package_id", flat=True) + influencers = Package.objects.filter(id__in=package_ids).values_list( + "influencer_id", flat=True + ) + influencer_ids.update(influencers) + + return list(influencer_ids) + + def get_is_twitter_connected(self, business_meta_data): + userAccount = business_meta_data.user_account + if userAccount.twitter_account: + return True + return False + + + def get_is_wallet_connected(self, business_meta_data): + user_wallet = Wallet.objects.filter(user_id = business_meta_data.user_account) + if(user_wallet): + return True + return False + + def get_user_twitter_profile_image(self, business_meta_data): + userAccount = business_meta_data.user_account + try: + return userAccount.twitter_account.profile_image_url + except Exception as e: + return "" class TwitterReadSerializer(serializers.ModelSerializer): class Meta: diff --git a/src/api/marketplace/core/apps.py b/src/api/marketplace/core/apps.py index 8115ae60..1ded3d15 100644 --- a/src/api/marketplace/core/apps.py +++ b/src/api/marketplace/core/apps.py @@ -4,3 +4,7 @@ class CoreConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'core' + + def ready(self) -> None: + import core.signals + super().ready() diff --git a/src/api/marketplace/core/services.py b/src/api/marketplace/core/services.py index c7503049..6a604df1 100644 --- a/src/api/marketplace/core/services.py +++ b/src/api/marketplace/core/services.py @@ -2,7 +2,8 @@ import requests from decouple import config - +from packages.models import Service +from .models import Configuration def get_twitter_usage(): url = "https://api.twitter.com/2/usage/tweets" @@ -10,3 +11,10 @@ def get_twitter_usage(): response = requests.get(url, headers=headers) response.raise_for_status() return response.json() + + +def update_priority_fees(): + services = Service.objects.all() + current_platform_fees = int( + Configuration.objects.get(key="platform_fees").value) + services.update(platform_fees=current_platform_fees) diff --git a/src/api/marketplace/core/signals.py b/src/api/marketplace/core/signals.py new file mode 100644 index 00000000..ae7e02bd --- /dev/null +++ b/src/api/marketplace/core/signals.py @@ -0,0 +1,14 @@ +# From the configuration model, whenever the key "priority_fees" is updated, I want to run a function +# that will update the priority fees in the database. + +from django.db.models.signals import post_save +from django.dispatch import receiver + +from .models import Configuration +from .services import update_priority_fees + + +@receiver(post_save, sender=Configuration) +def post_save_update_priority_fees(sender, instance, created, **kwargs): + if instance.key == "platform_fees" and not created: + update_priority_fees() diff --git a/src/ui/app/business/components/influencersContainer/influencersCards/index.tsx b/src/ui/app/business/components/influencersContainer/influencersCards/index.tsx index 507f5690..d2f4ad6b 100644 --- a/src/ui/app/business/components/influencersContainer/influencersCards/index.tsx +++ b/src/ui/app/business/components/influencersContainer/influencersCards/index.tsx @@ -286,18 +286,18 @@ export default function InfluencersCards({ justifyContent={"center"} alignItems={"center"} > - + Followers: {influencer?.followers} - + {`${influencer?.minPrice} - ${influencer?.maxPrice}`} diff --git a/src/ui/app/business/explore/page.tsx b/src/ui/app/business/explore/page.tsx index 17410970..73c5e91c 100644 --- a/src/ui/app/business/explore/page.tsx +++ b/src/ui/app/business/explore/page.tsx @@ -192,7 +192,7 @@ export default function Explore({}: Props) { {pagination?.total_data_count ?? 0} Results {/* The step should be in the database with the corresponding route */} - {/* */} + 0) { + if (data?.pagination?.total_data_count > 0) { setHasAMessage(true); } } diff --git a/src/ui/app/business/profile-preview/[id]/page.tsx b/src/ui/app/business/profile-preview/[id]/page.tsx index f6d360a4..7eedbec9 100644 --- a/src/ui/app/business/profile-preview/[id]/page.tsx +++ b/src/ui/app/business/profile-preview/[id]/page.tsx @@ -27,6 +27,7 @@ import Image from "next/image"; import NotFound from "@/public/svg/not_found.svg"; import { stringToColor } from "@/src/utils/helper"; import { BADGES } from "@/src/utils/consts"; +import { getProfileCompletedStatus } from "@/src/services/profileCompletion"; type Props = { params: { @@ -48,22 +49,6 @@ const styles = { }, }; -const getProfileCompletedStatus: (businessDetails: any) => string = ( - businessDetails -) => { - if (businessDetails) { - let count = 0; - if (businessDetails?.isTwitterAccountConnected) count += 5; - if (businessDetails?.isWalletConnected) count += 5; - count += - Object.values(businessDetails).filter( - (value) => value !== "" && value !== null - ).length - 7; - return `${count} / ${10 + Object.keys(businessDetails).length - 7}`; - } - return "-"; -}; - const formatTwitterFollowers = (followersCount: any) => { if (followersCount >= 1000000) { // Convert to millions format @@ -80,8 +65,7 @@ const formatTwitterFollowers = (followersCount: any) => { export default function BusinessProfilePreview({ params }: Props) { const [isProfileComplete, setIsProfileComplete] = useState(false); const [collaborations, setCollaborations] = useState([]); - const [businessDetails, setBusinessDetails] = - useState(); + const [businessDetails, setBusinessDetails] = useState(); const user = useAppSelector((state) => state.user?.user); const router = useRouter(); @@ -104,6 +88,8 @@ export default function BusinessProfilePreview({ params }: Props) { .replace(/\s/g, "") .split("/"); + console.log(completionStringArr); + return ( (parseInt(completionStringArr[0]) / parseInt(completionStringArr[1])) * 100 @@ -160,8 +146,6 @@ export default function BusinessProfilePreview({ params }: Props) { if (isSuccess) { setBusinessDetails({ ...data?.data, - isTwitterAccountConnected: !!user?.twitter_account, - isWalletConnected: !!user?.wallets?.length, }); getCollaborators(data?.data?.influencer_ids); } @@ -211,10 +195,10 @@ export default function BusinessProfilePreview({ params }: Props) { alignItems: "center", }} > - {user?.twitter_account?.profile_image_url ? ( + {!!businessDetails?.user_twitter_profile_image ? ( ) : ( )} @@ -412,7 +398,7 @@ export default function BusinessProfilePreview({ params }: Props) { margin: "20px", }} > - {user?.role?.name === "business_owner" ? ( + {user?.id == params?.id ? (