diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index d476aa7..8ab19ff 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -8,6 +8,7 @@
+
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index f978135..bdaa3ea 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -10,6 +10,7 @@
+
diff --git a/settings.gradle b/settings.gradle
index ad90f3f..e9d201e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -10,4 +10,5 @@ rootProject.name = 'VegaHRM.Backend'
include 'vega-hrm-auth'
include 'vega-hrm-core'
+include 'vega-hrm-report'
diff --git a/vega-hrm-auth/build.gradle b/vega-hrm-auth/build.gradle
index 20d1ffd..a21570f 100644
--- a/vega-hrm-auth/build.gradle
+++ b/vega-hrm-auth/build.gradle
@@ -11,9 +11,6 @@ repositories {
mavenCentral()
}
-dependencies {
-
-}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.4.0'
implementation 'org.springframework.boot:spring-boot-starter-web:3.4.0'
@@ -24,6 +21,20 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-log4j2:3.4.0'
implementation 'org.springframework.boot:spring-boot-starter-validation:3.4.0'
implementation 'de.mkammerer:argon2-jvm:2.1'
+ implementation "com.google.apis:google-api-services-youtube:v3-rev182-1.22.0"
+ implementation("com.google.collections:google-collections:1.0")
+ implementation("com.google.guava:guava:20.0")
+ implementation("com.google.apis:google-api-services-youtubeAnalytics:v2-rev272-1.25.0")
+ implementation "com.google.http-client:google-http-client-jackson2:1.20.0"
+
+ // OAuth Client
+ implementation "com.google.oauth-client:google-oauth-client-jetty:1.20.0"
+ implementation 'com.google.apis:google-api-services-oauth2:v2-rev157-1.25.0'
+ implementation 'com.google.oauth-client:google-oauth-client-jetty:1.34.1'
+ implementation 'com.google.api-client:google-api-client:2.3.0'
+ // Google Collections
+ implementation "com.google.collections:google-collections:1.0"
+ implementation 'com.google.code.gson:gson:2.11.0'
annotationProcessor 'org.projectlombok:lombok:1.18.38'
implementation project(":vega-hrm-core")
implementation 'jakarta.annotation:jakarta.annotation-api:2.1.1'
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/controller/GoogleController.java b/vega-hrm-auth/src/main/java/com/vega/hrm/controller/GoogleController.java
new file mode 100644
index 0000000..923caab
--- /dev/null
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/controller/GoogleController.java
@@ -0,0 +1,29 @@
+package com.vega.hrm.controller;
+
+import com.vega.hrm.core.models.responses.BaseResponse;
+import com.vega.hrm.service.GoogleService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("api/google/user")
+@RequiredArgsConstructor
+public class GoogleController {
+
+ private final GoogleService googleService;
+
+ @GetMapping("/get-auth-url")
+ public ResponseEntity> getGoogleAuthUrl(){
+ return ResponseEntity.ok(googleService.getGoogleAuthUrl());
+ }
+
+ @GetMapping("callback")
+ public ResponseEntity> googleCallback(@RequestParam("code") String code){
+ return ResponseEntity.ok(googleService.googleCallback(code));
+ }
+
+}
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/controller/UserController.java b/vega-hrm-auth/src/main/java/com/vega/hrm/controller/UserController.java
index b8259d9..8868c88 100644
--- a/vega-hrm-auth/src/main/java/com/vega/hrm/controller/UserController.java
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/controller/UserController.java
@@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
-@RequestMapping("/auth/user")
+@RequestMapping("api/auth/user")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/service/GoogleService.java b/vega-hrm-auth/src/main/java/com/vega/hrm/service/GoogleService.java
new file mode 100644
index 0000000..36ae600
--- /dev/null
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/service/GoogleService.java
@@ -0,0 +1,100 @@
+package com.vega.hrm.service;
+
+import static com.vega.hrm.core.constants.CommonConst.SCOPES;
+
+import com.google.api.client.auth.oauth2.AuthorizationCodeFlow;
+import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl;
+import com.google.api.client.auth.oauth2.BearerToken;
+import com.google.api.client.auth.oauth2.Credential;
+import com.google.api.client.auth.oauth2.TokenResponse;
+import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
+import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
+import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
+import com.google.api.client.http.javanet.NetHttpTransport;
+import com.google.api.client.json.JsonFactory;
+import com.google.api.client.json.jackson2.JacksonFactory;
+import com.google.api.services.oauth2.Oauth2;
+import com.vega.hrm.core.component.TokenStore;
+import com.vega.hrm.core.models.responses.BaseResponse;
+import com.vega.hrm.core.dto.GoogleOAuthConfig;
+import com.google.api.services.oauth2.model.Userinfo;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.Objects;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class GoogleService {
+ private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
+ private final TokenStore tokenStore;
+
+ public BaseResponse getGoogleAuthUrl() {
+ var googleOAuthConfig = GoogleOAuthConfig.builder().build();
+ NetHttpTransport httpTransport = null;
+ try {
+ httpTransport = GoogleNetHttpTransport.newTrustedTransport();
+ } catch (GeneralSecurityException | IOException e) {
+ return BaseResponse.invalid(e.getMessage());
+ }
+
+ GoogleClientSecrets.Details details = new GoogleClientSecrets.Details();
+ details.setClientId(googleOAuthConfig.clientId);
+ details.setClientSecret(googleOAuthConfig.clientSecret);
+ GoogleClientSecrets clientSecrets = new GoogleClientSecrets().setInstalled(details);
+ AuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
+ httpTransport, JSON_FACTORY, clientSecrets, SCOPES)
+ .setAccessType("offline")
+ .setApprovalPrompt("force")
+ .build();
+ AuthorizationCodeRequestUrl authorizationUrl = flow.newAuthorizationUrl().setRedirectUri(googleOAuthConfig.redirectUri);
+ return BaseResponse.success("00",authorizationUrl.toString());
+ }
+
+ public BaseResponse googleCallback(String code) {
+ var googleOAuthConfig = GoogleOAuthConfig.builder().build();
+ NetHttpTransport httpTransport = null;
+
+ try {
+ httpTransport = GoogleNetHttpTransport.newTrustedTransport();
+ } catch (GeneralSecurityException | IOException e) {
+ BaseResponse.invalid(e.getMessage());
+ }
+
+ GoogleClientSecrets.Details details = new GoogleClientSecrets.Details();
+ details.setClientId(googleOAuthConfig.clientId);
+ details.setClientSecret(googleOAuthConfig.clientSecret);
+ GoogleClientSecrets clientSecrets = new GoogleClientSecrets().setInstalled(details);
+ AuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
+ httpTransport, JSON_FACTORY, clientSecrets, SCOPES)
+ .setAccessType("offline")
+ .setApprovalPrompt("force")
+ .build();
+ TokenResponse tokenResponse = null;
+ try {
+ tokenResponse = flow.newTokenRequest(code).setRedirectUri(googleOAuthConfig.redirectUri).execute();
+ } catch (IOException e) {
+ return BaseResponse.invalid(e.getMessage());
+ }
+ Credential credential = new Credential(BearerToken.authorizationHeaderAccessMethod())
+ .setAccessToken(tokenResponse.getAccessToken());
+
+ Oauth2 oauth2 = new Oauth2.Builder(
+ Objects.requireNonNull(httpTransport), JSON_FACTORY, credential)
+ .setApplicationName("VEGA_HRM")
+ .build();
+
+ Userinfo userInfo = null;
+ try {
+ userInfo = oauth2.userinfo().get().execute();
+ } catch (IOException e) {
+ return BaseResponse.invalid(e.getMessage());
+ }
+ String email = userInfo.getEmail();
+ tokenStore.storeToken(email, tokenResponse);
+ return BaseResponse.success("00",true);
+ }
+
+}
diff --git a/vega-hrm-core/build.gradle b/vega-hrm-core/build.gradle
index 7201eec..ebd3673 100644
--- a/vega-hrm-core/build.gradle
+++ b/vega-hrm-core/build.gradle
@@ -44,6 +44,19 @@ dependencies {
implementation 'org.bouncycastle:bcpkix-jdk18on:1.80'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
+ implementation "com.google.apis:google-api-services-youtube:v3-rev182-1.22.0"
+ implementation("com.google.collections:google-collections:1.0")
+ implementation("com.google.guava:guava:20.0")
+ implementation("com.google.apis:google-api-services-youtubeAnalytics:v2-rev272-1.25.0")
+ implementation "com.google.http-client:google-http-client-jackson2:1.20.0"
+
+ // OAuth Client
+ implementation "com.google.oauth-client:google-oauth-client-jetty:1.20.0"
+
+ // Google Collections
+ implementation "com.google.collections:google-collections:1.0"
+ implementation 'com.google.code.gson:gson:2.11.0'
+
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-orgjson
runtimeOnly 'io.jsonwebtoken:jjwt-orgjson:0.12.6'
}
diff --git a/vega-hrm-core/src/main/java/com/vega/hrm/core/component/TokenStore.java b/vega-hrm-core/src/main/java/com/vega/hrm/core/component/TokenStore.java
new file mode 100644
index 0000000..cd2a423
--- /dev/null
+++ b/vega-hrm-core/src/main/java/com/vega/hrm/core/component/TokenStore.java
@@ -0,0 +1,36 @@
+package com.vega.hrm.core.component;
+
+import com.google.api.client.auth.oauth2.Credential;
+import com.google.api.client.auth.oauth2.TokenResponse;
+import com.google.api.client.http.HttpTransport;
+import com.google.api.client.json.JsonFactory;
+import java.util.concurrent.ConcurrentHashMap;
+import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TokenStore {
+ private final ConcurrentHashMap tokenMap = new ConcurrentHashMap<>();
+
+ public void storeToken(String userId, TokenResponse tokenResponse) {
+ tokenMap.put(userId, tokenResponse);
+ }
+
+ public TokenResponse getTokenResponse(String userId) {
+ return tokenMap.get(userId);
+ }
+
+ public Credential buildCredential(HttpTransport transport, JsonFactory jsonFactory, String userId, String clientId, String clientSecret) {
+ TokenResponse tokenResponse = tokenMap.get(userId);
+ if (tokenResponse == null) {
+ return null;
+ }
+
+ return new GoogleCredential.Builder()
+ .setTransport(transport)
+ .setJsonFactory(jsonFactory)
+ .setClientSecrets(clientId, clientSecret)
+ .build()
+ .setFromTokenResponse(tokenResponse);
+ }
+}
diff --git a/vega-hrm-core/src/main/java/com/vega/hrm/core/constants/CommonConst.java b/vega-hrm-core/src/main/java/com/vega/hrm/core/constants/CommonConst.java
index b85683a..eb6de18 100644
--- a/vega-hrm-core/src/main/java/com/vega/hrm/core/constants/CommonConst.java
+++ b/vega-hrm-core/src/main/java/com/vega/hrm/core/constants/CommonConst.java
@@ -1,6 +1,14 @@
package com.vega.hrm.core.constants;
+import java.util.Arrays;
+import java.util.List;
+
public class CommonConst {
public static final String USER_ID = "user_id";
public static final String TOKEN = "token";
+ public static final List SCOPES = Arrays.asList(
+ "https://www.googleapis.com/auth/youtube.readonly",
+ "https://www.googleapis.com/auth/yt-analytics.readonly",
+ "https://www.googleapis.com/auth/yt-analytics-monetary.readonly"
+ );
}
diff --git a/vega-hrm-core/src/main/java/com/vega/hrm/core/dto/GoogleOAuthConfig.java b/vega-hrm-core/src/main/java/com/vega/hrm/core/dto/GoogleOAuthConfig.java
new file mode 100644
index 0000000..7cfb1be
--- /dev/null
+++ b/vega-hrm-core/src/main/java/com/vega/hrm/core/dto/GoogleOAuthConfig.java
@@ -0,0 +1,14 @@
+package com.vega.hrm.core.dto;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Builder
+public class GoogleOAuthConfig {
+ public String clientId;
+ public String clientSecret;
+ public String redirectUri;
+}
diff --git a/vega-hrm-core/src/main/java/com/vega/hrm/core/filters/AuthorizationFilter.java b/vega-hrm-core/src/main/java/com/vega/hrm/core/filters/AuthorizationFilter.java
index 7f74f6f..03fa057 100644
--- a/vega-hrm-core/src/main/java/com/vega/hrm/core/filters/AuthorizationFilter.java
+++ b/vega-hrm-core/src/main/java/com/vega/hrm/core/filters/AuthorizationFilter.java
@@ -28,7 +28,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
@RequiredArgsConstructor
public class AuthorizationFilter extends OncePerRequestFilter {
- private static final List EXCLUDE_URIS = List.of("/auth/user/login");
+ private static final List EXCLUDE_URIS = List.of("api/auth/user/login","api/google/user/callback");
private final RedisService redisService;
@Override
diff --git a/vega-hrm-core/src/main/java/com/vega/hrm/core/models/responses/BaseResponse.java b/vega-hrm-core/src/main/java/com/vega/hrm/core/models/responses/BaseResponse.java
index fa3550f..97a7851 100644
--- a/vega-hrm-core/src/main/java/com/vega/hrm/core/models/responses/BaseResponse.java
+++ b/vega-hrm-core/src/main/java/com/vega/hrm/core/models/responses/BaseResponse.java
@@ -28,6 +28,14 @@ public class BaseResponse {
private T data;
+ public static BaseResponse success(String msg, T data) {
+ return BaseResponse.builder()
+ .code(ResponseCodeConst.SUCCESS)
+ .message(msg)
+ .data(data)
+ .build();
+ }
+
public static BaseResponse success(String msg) {
return BaseResponse.builder()
.code(ResponseCodeConst.SUCCESS)
diff --git a/vega-hrm-report/src/main/java/com/vega/hrm/report/controller/ReportGoogleController.java b/vega-hrm-report/src/main/java/com/vega/hrm/report/controller/ReportGoogleController.java
new file mode 100644
index 0000000..a7b6876
--- /dev/null
+++ b/vega-hrm-report/src/main/java/com/vega/hrm/report/controller/ReportGoogleController.java
@@ -0,0 +1,47 @@
+package com.vega.hrm.report.controller;
+
+import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
+import com.google.api.client.json.jackson2.JacksonFactory;
+import com.vega.hrm.core.component.TokenStore;
+import com.vega.hrm.core.dto.GoogleOAuthConfig;
+import com.vega.hrm.core.models.responses.BaseResponse;
+import com.vega.hrm.report.request.GetDragRevenueRequest;
+import com.vega.hrm.report.serivce.CreateReportingJobService;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("api/report/google")
+@RequiredArgsConstructor
+public class ReportGoogleController {
+
+ private final CreateReportingJobService createReportingJob;
+ @GetMapping("/youtube/demo")
+ public ResponseEntity> getRevenue(GetDragRevenueRequest getDragRevenueRequest)
+ throws GeneralSecurityException, IOException {
+
+ var googleOAuthConfig = GoogleOAuthConfig.builder().build();
+ var tokenStore = new TokenStore();
+ createReportingJob.createJobWithStoredCredential(
+ tokenStore,
+ googleOAuthConfig,
+ GoogleNetHttpTransport.newTrustedTransport(),
+ JacksonFactory.getDefaultInstance(),
+ "default",
+ "channel_monetized_playback_a1", // report type
+ "vega-monetization-daily" // job name
+ );
+
+ return ResponseEntity.ok(
+ BaseResponse.builder()
+ .code("00")
+ .data(true)
+ .build()
+ );
+ }
+}
diff --git a/vega-hrm-report/src/main/java/com/vega/hrm/report/request/GetDragRevenueRequest.java b/vega-hrm-report/src/main/java/com/vega/hrm/report/request/GetDragRevenueRequest.java
new file mode 100644
index 0000000..bc330e1
--- /dev/null
+++ b/vega-hrm-report/src/main/java/com/vega/hrm/report/request/GetDragRevenueRequest.java
@@ -0,0 +1,8 @@
+package com.vega.hrm.report.request;
+
+import lombok.Getter;
+
+@Getter
+public class GetDragRevenueRequest {
+ public String email;
+}
diff --git a/vega-hrm-report/src/main/java/com/vega/hrm/report/serivce/CreateReportingJobService.java b/vega-hrm-report/src/main/java/com/vega/hrm/report/serivce/CreateReportingJobService.java
new file mode 100644
index 0000000..aefd108
--- /dev/null
+++ b/vega-hrm-report/src/main/java/com/vega/hrm/report/serivce/CreateReportingJobService.java
@@ -0,0 +1,159 @@
+package com.vega.hrm.report.serivce;
+
+import com.google.api.client.auth.oauth2.Credential;
+import com.google.api.client.googleapis.json.GoogleJsonResponseException;
+import com.google.api.client.http.GenericUrl;
+import com.google.api.services.youtubeAnalytics.v2.YouTubeAnalytics;
+import com.google.api.services.youtubeAnalytics.v2.model.QueryResponse;
+import com.google.api.services.youtubereporting.YouTubeReporting;
+import com.google.api.services.youtubereporting.YouTubeReporting.Media.Download;
+import com.google.api.services.youtubereporting.model.Job;
+import com.google.api.services.youtubereporting.model.ListReportTypesResponse;
+import com.google.api.services.youtubereporting.model.ListReportsResponse;
+import com.google.api.services.youtubereporting.model.Report;
+import com.google.api.services.youtubereporting.model.ReportType;
+import com.vega.hrm.core.component.TokenStore;
+import com.vega.hrm.core.dto.GoogleOAuthConfig;
+import com.vega.hrm.core.helpers.LogHelper;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class CreateReportingJobService {
+ private static YouTubeReporting youtubeReporting;
+ private static final String APPLICATION_NAME = "vega-report";
+
+ public void createJobWithStoredCredential(
+ TokenStore tokenStore,
+ GoogleOAuthConfig googleOAuthConfig,
+ com.google.api.client.http.HttpTransport httpTransport,
+ com.google.api.client.json.JsonFactory jsonFactory,
+ String userId,
+ String reportTypeId,
+ String jobName
+ ) {
+ try {
+ Credential credential = tokenStore.buildCredential(
+ httpTransport,
+ jsonFactory,
+ userId,
+ googleOAuthConfig.clientId,
+ googleOAuthConfig.clientSecret
+ );
+ if (credential == null) {
+ throw new IllegalStateException("No stored token for userId=" + userId);
+ }
+
+ youtubeReporting = new YouTubeReporting.Builder(httpTransport, jsonFactory, credential)
+ .setApplicationName(APPLICATION_NAME)
+ .build();
+ YouTubeAnalytics youtubeAnalytics = new YouTubeAnalytics.Builder(httpTransport, jsonFactory, credential)
+ .setApplicationName(APPLICATION_NAME)
+ .build();
+
+ QueryResponse resReport = youtubeAnalytics.reports().query().setIds("channel==MINE")
+ .setStartDate("2025-01-01")
+ .setEndDate("2025-09-30")
+ .setMetrics("estimatedRevenue")
+ .setDimensions("day").execute();
+
+ LogHelper.info("resReport: " + resReport.toPrettyString());
+
+ //TODO tam fix cứng
+ if (listReportTypes()) {
+ createReportingJob(reportTypeId, "test_job");
+ }
+ } catch (GoogleJsonResponseException e) {
+ LogHelper.error("GoogleJsonResponseException code: " + e.getDetails().getCode()
+ + " : " + e.getDetails().getMessage());
+
+ } catch (IOException e) {
+ LogHelper.error("IOException: " + e.getMessage());
+
+ } catch (Throwable t) {
+ LogHelper.error("Throwable: " + t.getMessage());
+
+ }
+ }
+
+ private static boolean listReportTypes() throws IOException {
+ ListReportTypesResponse reportTypesListResponse = youtubeReporting.reportTypes().list()
+ .execute();
+ List reportTypeList = reportTypesListResponse.getReportTypes();
+
+ if (reportTypeList == null || reportTypeList.isEmpty()) {
+ LogHelper.info("No report types found.");
+ return false;
+ } else {
+ // Print information from the API response.
+ LogHelper.info("\n================== Report Types ==================\n");
+ for (ReportType reportType : reportTypeList) {
+ LogHelper.info(" - Id: " + reportType.getId());
+ LogHelper.info(" - Name: " + reportType.getName());
+ LogHelper.info("\n-------------------------------------------------------------\n");
+ }
+ }
+ return true;
+ }
+
+ private static boolean retrieveReports(String jobId)
+ throws IOException {
+ ListReportsResponse reportsListResponse = youtubeReporting.jobs().reports().list(jobId).execute();
+ List reportslist = reportsListResponse.getReports();
+
+ if (reportslist == null || reportslist.isEmpty()) {
+ LogHelper.info("No reports found.");
+ return false;
+ } else {
+ LogHelper.info("\n============= Reports for the job " + jobId + " =============\n");
+
+ for (Report report : reportslist) {
+ LogHelper.info(" - Id: " + report.getId());
+ LogHelper.info(" - From: " + report.getStartTime());
+ LogHelper.info(" - To: " + report.getEndTime());
+ LogHelper.info(" - Download Url: " + report.getDownloadUrl());
+ downloadReport(report.getDownloadUrl());
+ LogHelper.info("\n-------------------------------------------------------------\n");
+ }
+ }
+ return true;
+ }
+
+ private static boolean downloadReport(String reportUrl) throws IOException {
+ // Tạo request download
+ Download request = youtubeReporting.media().download(
+ String.valueOf(new GenericUrl(reportUrl)));
+
+ // Tạo output file
+ try (FileOutputStream fop = new FileOutputStream(new File("report.csv"))) {
+ request.getMediaHttpDownloader().download(new GenericUrl(reportUrl), fop);
+ }
+
+ return true;
+ }
+
+ private static void createReportingJob(String reportTypeId, String name)
+ throws IOException {
+
+ Job job = new Job();
+ job.setReportTypeId(reportTypeId);
+ job.setName(name);
+
+ Job createdJob = youtubeReporting.jobs().create(job).execute();
+ retrieveReports(createdJob.getId());
+
+ LogHelper.info("\n================== Created reporting job ==================\n");
+ LogHelper.info(" - ID: " + createdJob.getId());
+ LogHelper.info(" - Name: " + createdJob.getName());
+ LogHelper.info(" - Report Type Id: " + createdJob.getReportTypeId());
+ LogHelper.info(" - Create Time: " + createdJob.getCreateTime());
+ LogHelper.info("\n-------------------------------------------------------------\n");
+ }
+}
diff --git a/vega-hrm-report/src/main/resources/application.properties b/vega-hrm-report/src/main/resources/application.properties
new file mode 100644
index 0000000..39a3324
--- /dev/null
+++ b/vega-hrm-report/src/main/resources/application.properties
@@ -0,0 +1,9 @@
+spring.application.name=vega-hrm-report
+spring.jpa.open-in-view=false
+server.port=8090
+vega.hrm.postgre.enabled=true
+vega.jpa.repository.basePackage=com.vega.hrm.core.repositories
+vega.jpa.entity.basePackage=com.vega.hrm.core.entities
+spring.config.import=file:config/shared.properties
+logging.config=file:config/log4j2.properties
+