Skip to content

Commit

Permalink
Merge pull request #69 from sparc-software-hust/develop
Browse files Browse the repository at this point in the history
build test flight
  • Loading branch information
thaidmfinnick authored Jan 17, 2025
2 parents 0f091e9 + dd7377c commit d8b38d7
Show file tree
Hide file tree
Showing 23 changed files with 457 additions and 93 deletions.
4 changes: 2 additions & 2 deletions api/lib/cecr_unwomen/consumer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ defmodule CecrUnwomen.Consumer do
{:ok, obj} -> case obj["action"] do
"broadcast_remind_to_input" -> spawn(fn -> ScheduleWorker.schedule_to_send_noti_vi([obj["data"]]) end)
_ -> raise("not detect action #{obj}")

Basic.ack channel, tag
end
Basic.ack channel, tag

{:error, _} ->
Basic.reject channel, tag, requeue: false
end
Expand Down
10 changes: 10 additions & 0 deletions api/lib/cecr_unwomen/fcm/fcm_payload.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
defmodule CecrUnwomen.Fcm.FcmPayload do
def create_payload_with_data(:both, token, notification, data) do
%{
"message" => %{
"token" => token,
"notification" => notification,
"data" => data
},
}
end

def create_payload(:both, token, notification) do
%{
"message" => %{
Expand Down
21 changes: 21 additions & 0 deletions api/lib/cecr_unwomen/utils/helper.ex
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,25 @@ defmodule CecrUnwomen.Utils.Helper do
DateTime.now!(timezone)
|> Calendar.strftime("%d/%m/%Y")
end

def fold_fcm_token(map, extra_fields \\ %{}) do
map
|> Enum.reduce(%{}, fn item, acc ->
user_id = item["user_id"]
token = item["token"]

base_map = Map.merge(
%{
"user_id" => user_id,
"tokens" => [token]
},
extra_fields
)

Map.update(acc, user_id, base_map, fn existing ->
Map.update(existing, "tokens", [token], fn tokens -> tokens ++ [token] end)
end)
end)
|> Map.values()
end
end
10 changes: 8 additions & 2 deletions api/lib/cecr_unwomen/workers/fcm_worker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule CecrUnwomen.Workers.FcmWorker do

@url_firebase_messaging "https://fcm.googleapis.com/v1/projects/cecr-unwomen/messages:send"

def send_firebase_notification(firebase_tokens, notification_field) do
def send_firebase_notification(firebase_tokens, notification_field, data \\ %{}) do
server_firebase_token = GenServer.call(FcmStore, :get_token)
headers = [{"Authorization", "Bearer #{server_firebase_token}"}]

Expand All @@ -16,7 +16,13 @@ defmodule CecrUnwomen.Workers.FcmWorker do

Enum.each(firebase_tokens, fn t ->
token = t["token"]
payload = FcmPayload.create_payload(:both, token, notification_field)
# payload = FcmPayload.create_payload(:both, token, notification_field)
payload = cond do
data == %{} -> FcmPayload.create_payload(:both, token, notification_field)
true ->
data_valid = data |> Map.new(fn {k, v} -> {k, to_string(v)} end)
FcmPayload.create_payload_with_data(:both, token, notification_field, data_valid)
end
# payload = cond do
# t["platform"] == "android" -> FcmPayload.create_payload(:android, token, data_android_string)
# t["platform"] == "ios" && apns_custom_field != nil -> FcmPayload.create_payload(:ios_custom, token, data_ios_string, apns_custom_field)
Expand Down
4 changes: 4 additions & 0 deletions api/lib/cecr_unwomen/workers/schedule_worker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ defmodule CecrUnwomen.Workers.ScheduleWorker do
%{
"title" => "Nhập dữ liệu ngày #{local_time_string}",
"body" => "Bạn chưa nhập dữ liệu cho hôm nay. Ấn vào thông báo để tiến hành nhập liệu."
},
%{
"type" => "remind_to_contribute",
"role_id" => role_id
}
)
end
Expand Down
73 changes: 70 additions & 3 deletions api/lib/cecr_unwomen_web/controllers/contribution_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ defmodule CecrUnwomenWeb.ContributionController do

alias CecrUnwomenWeb.Models.{
User,
FirebaseToken,
ScraperContribution,
HouseholdContribution,
OverallScraperContribution,
OverallHouseholdContribution,
HouseholdConstantFactor,
ScrapConstantFactor
}


alias CecrUnwomen.Workers.FcmWorker
alias CecrUnwomen.{Utils.Helper, Repo}

def contribute_data(conn, params) do
Expand Down Expand Up @@ -58,7 +60,10 @@ defmodule CecrUnwomenWeb.ContributionController do
Helper.aggregate_with_fields(OverallScraperContribution, keys)
end)
|> case do
{:ok, overall_data} -> Helper.response_json_with_data(true, "Nhập thông tin thành công!", overall_data)
{:ok, overall_data} ->
send_noti_to_admin(user_id, overall_data, date)
Helper.response_json_with_data(true, "Nhập thông tin thành công!", overall_data)

_ -> Helper.response_json_message(false, "Có lỗi xảy ra", 406)
end

Expand Down Expand Up @@ -101,7 +106,9 @@ defmodule CecrUnwomenWeb.ContributionController do
Helper.aggregate_with_fields(OverallHouseholdContribution, keys)
end)
|> case do
{:ok, overall_data} -> Helper.response_json_with_data(true, "Nhập thông tin thành công!", overall_data)
{:ok, overall_data} ->
send_noti_to_admin(user_id, overall_data, date)
Helper.response_json_with_data(true, "Nhập thông tin thành công!", overall_data)
_ -> Helper.response_json_message(false, "Có lỗi xảy ra", 406)
end

Expand All @@ -110,6 +117,66 @@ defmodule CecrUnwomenWeb.ContributionController do

json(conn, res)
end

defp send_noti_to_admin(user_id, data, date) do
user_info = from(
u in User,
where: u.id == ^user_id,
select: %{
"first_name" => u.first_name,
"last_name" => u.last_name,
"role_id" => u.role_id,
"avatar_url" => u.avatar_url
}
)
|> Repo.one

admin_fcm_tokens = from(
u in User,
join: ft in FirebaseToken,
on: u.id == ft.user_id,
where: u.role_id == 1,
select: %{
"user_id" => u.id,
"token" => ft.token,
}
)
|> Repo.all
# fold cac token thuoc cung 1 user lai ve 1 map
|> Helper.fold_fcm_token()

Enum.each(admin_fcm_tokens, fn t ->
tokens = t["tokens"]
date_string = Calendar.strftime(date, "%d/%m/%Y")
user_name = "#{user_info["first_name"]} #{user_info["last_name"]}"
role_name = if (user_info["role_id"] == 2), do: "hộ gia đình", else: "người thu gom"
role_id = user_info["role_id"]
avatar_url = user_info["avatar_url"]

FcmWorker.send_firebase_notification(
Enum.map(tokens, fn t -> %{"token" => t} end),
%{
"title" => "#{user_name} (#{role_name}) vừa nhập dữ liệu ngày #{date_string}",
"body" => "Có dữ liệu đóng góp mới. Ấn vào thông báo để xem thông tin"
},
%{
"type" => "user_contribute_data",
"date" => date,
"formatted_date" => date_string,
"name" => user_name,
"role_id" => role_id,
"user_id" => user_id,
"avatar_url" => avatar_url,
"kg_co2e_reduced" => Map.get(data,:kg_co2e_reduced),
"kg_collected" => Map.get(data,:kg_collected),
"expense_reduced" => Map.get(data,:expense_reduced),
"kg_co2e_plastic_reduced" => Map.get(data, :kg_co2e_plastic_reduced),
"kg_co2e_recycle_reduced" => Map.get(data, :kg_co2e_recycle_reduced),
"kg_recycle_collected" => Map.get(data,:kg_recycle_collected),
}
)
end)
end

def edit_factor_quantity(conn, params) do
user_id = conn.assigns.user.user_id
Expand Down
4 changes: 2 additions & 2 deletions mobile/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ if (keystorePropertiesFile.exists()) {

android {
namespace = "vn.sparc.waznet"
compileSdk = flutter.compileSdkVersion
compileSdk = 34
ndkVersion = flutter.ndkVersion

compileOptions {
Expand All @@ -40,7 +40,7 @@ android {
ndk {
debugSymbolLevel 'FULL'
}

multiDexEnabled true
}

signingConfigs {
Expand Down
9 changes: 8 additions & 1 deletion mobile/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ import UIKit
import Firebase
import FirebaseCore
import FirebaseMessaging
import flutter_local_notifications

@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
GeneratedPluginRegistrant.register(with: registry)
}
FirebaseApp.configure()
// UNUserNotificationCenter.current().delegate = self
//
// let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
Expand All @@ -21,6 +25,9 @@ import FirebaseMessaging
//
// application.registerForRemoteNotifications()
GeneratedPluginRegistrant.register(with: self)
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

Expand Down
23 changes: 20 additions & 3 deletions mobile/lib/features/firebase/bloc/firebase_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'dart:convert';

import 'package:bloc/bloc.dart';
import 'package:cecr_unwomen/features/firebase/bloc/firebase_event.dart';
import 'package:cecr_unwomen/features/firebase/bloc/firebase_state.dart';
import 'package:cecr_unwomen/features/firebase/repository/firebase_repository.dart';
import 'package:cecr_unwomen/service/notification_service.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

class FirebaseBloc extends Bloc<FirebaseEvent, FirebaseState>{
Expand Down Expand Up @@ -33,7 +36,12 @@ class FirebaseBloc extends Bloc<FirebaseEvent, FirebaseState>{
await emit.onEach(FirebaseMessaging.onMessage,
onData: (RemoteMessage message) async {
if (message.notification == null) return;
print('Message foreground also contained a notification: ${message.notification}');
if (message.data.isNotEmpty && message.data["type"] != null) {
NotificationService.showNotification(message.notification!.title ?? "", message.notification!.body ?? "", jsonEncode(message.data));
}
else {
NotificationService.showNotification(message.notification!.title ?? "", message.notification!.body ?? "", null);
}
},
onError: (e, t) => emit(state.copyWith(FirebaseStatus.noToken))
);
Expand All @@ -42,7 +50,10 @@ class FirebaseBloc extends Bloc<FirebaseEvent, FirebaseState>{
Future<void> _onOpenMessageBackground(OpenMessageBackground event, Emitter emit) async {
await emit.onEach(FirebaseMessaging.onMessageOpenedApp,
onData: (RemoteMessage message) async {
print('_onOpenMessageBackground:${message.notification?.body}');
if (message.notification == null) return;
if (message.data.isNotEmpty && message.data["type"] != null) {
notificationTapBackground(message.data);
}
// emit(state.copyWith(FirebaseStatus.haveToken));
},
onError: (e, t) => emit(state.copyWith(FirebaseStatus.noToken))
Expand All @@ -51,6 +62,12 @@ class FirebaseBloc extends Bloc<FirebaseEvent, FirebaseState>{

Future<void> _onOpenMessageTerminated(OpenMessageTerminated event, Emitter emit) async {
RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) print('terminated noti:$initialMessage');

if (initialMessage != null) {
if (initialMessage.notification == null) return;
if (initialMessage.data.isNotEmpty && initialMessage.data["type"] != null) {
notificationTapBackground(initialMessage.data);
}
}
}
}
Loading

0 comments on commit d8b38d7

Please sign in to comment.