target fix
This commit is contained in:
@@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -29,63 +30,88 @@ public class TargetingCampaignController {
|
|||||||
private final ABTestingService abTestingService;
|
private final ABTestingService abTestingService;
|
||||||
private final MarketingAnalysisV3Repository analysisRepository;
|
private final MarketingAnalysisV3Repository analysisRepository;
|
||||||
private final SocialMediaCredentialsService credentialsService;
|
private final SocialMediaCredentialsService credentialsService;
|
||||||
|
private final JwtService jwtService;
|
||||||
|
|
||||||
|
private String resolveUserId(String userIdHeader, String authHeader) {
|
||||||
|
if (StringUtils.hasText(userIdHeader)) {
|
||||||
|
return userIdHeader;
|
||||||
|
}
|
||||||
|
String userId = jwtService.extractUserIdFromHeader(authHeader);
|
||||||
|
if (userId == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot resolve user identity: X-User-Id header or valid Authorization token required");
|
||||||
|
}
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/campaigns")
|
@PostMapping("/campaigns")
|
||||||
public ResponseEntity<TargetingCampaign> createCampaign(
|
public ResponseEntity<TargetingCampaign> createCampaign(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@RequestBody TargetingCampaignRequest request) {
|
@RequestBody TargetingCampaignRequest request) {
|
||||||
|
String userId = resolveUserId(userIdHeader, authHeader);
|
||||||
log.info("[Targeting] Create campaign requested by {}", userId);
|
log.info("[Targeting] Create campaign requested by {}", userId);
|
||||||
return ResponseEntity.ok(campaignService.createCampaign(request, userId));
|
return ResponseEntity.ok(campaignService.createCampaign(request, userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/campaigns")
|
@GetMapping("/campaigns")
|
||||||
public ResponseEntity<Page<TargetingCampaign>> getUserCampaigns(
|
public ResponseEntity<Page<TargetingCampaign>> getUserCampaigns(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@RequestParam(defaultValue = "0") int page,
|
@RequestParam(defaultValue = "0") int page,
|
||||||
@RequestParam(defaultValue = "10") int size) {
|
@RequestParam(defaultValue = "10") int size) {
|
||||||
|
String userId = resolveUserId(userIdHeader, authHeader);
|
||||||
log.info("[Targeting] Get campaigns for {}", userId);
|
log.info("[Targeting] Get campaigns for {}", userId);
|
||||||
return ResponseEntity.ok(campaignService.getUserCampaigns(userId, page, size));
|
return ResponseEntity.ok(campaignService.getUserCampaigns(userId, page, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/campaigns/{id}")
|
@GetMapping("/campaigns/{id}")
|
||||||
public ResponseEntity<TargetingCampaign> getCampaign(
|
public ResponseEntity<TargetingCampaign> getCampaign(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@PathVariable String id) {
|
@PathVariable String id) {
|
||||||
|
String userId = resolveUserId(userIdHeader, authHeader);
|
||||||
log.info("[Targeting] Get campaign {} for {}", id, userId);
|
log.info("[Targeting] Get campaign {} for {}", id, userId);
|
||||||
return ResponseEntity.ok(campaignService.getCampaignById(id, userId));
|
return ResponseEntity.ok(campaignService.getCampaignById(id, userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/campaigns/{id}/pause")
|
@PostMapping("/campaigns/{id}/pause")
|
||||||
public ResponseEntity<TargetingCampaign> pauseCampaign(
|
public ResponseEntity<TargetingCampaign> pauseCampaign(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@PathVariable String id) {
|
@PathVariable String id) {
|
||||||
|
String userId = resolveUserId(userIdHeader, authHeader);
|
||||||
log.info("[Targeting] Pause campaign {}", id);
|
log.info("[Targeting] Pause campaign {}", id);
|
||||||
return ResponseEntity.ok(campaignService.pauseCampaign(id, userId));
|
return ResponseEntity.ok(campaignService.pauseCampaign(id, userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/campaigns/{id}/resume")
|
@PostMapping("/campaigns/{id}/resume")
|
||||||
public ResponseEntity<TargetingCampaign> resumeCampaign(
|
public ResponseEntity<TargetingCampaign> resumeCampaign(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@PathVariable String id) {
|
@PathVariable String id) {
|
||||||
|
String userId = resolveUserId(userIdHeader, authHeader);
|
||||||
log.info("[Targeting] Resume campaign {}", id);
|
log.info("[Targeting] Resume campaign {}", id);
|
||||||
return ResponseEntity.ok(campaignService.resumeCampaign(id, userId));
|
return ResponseEntity.ok(campaignService.resumeCampaign(id, userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/campaigns/{id}/insights")
|
@GetMapping("/campaigns/{id}/insights")
|
||||||
public ResponseEntity<TargetingPerformanceDto> getInsights(
|
public ResponseEntity<TargetingPerformanceDto> getInsights(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@PathVariable String id,
|
@PathVariable String id,
|
||||||
@RequestParam(defaultValue = "last_7d") String datePreset) {
|
@RequestParam(defaultValue = "last_7d") String datePreset) {
|
||||||
|
String userId = resolveUserId(userIdHeader, authHeader);
|
||||||
log.info("[Targeting] Get insights for campaign {}", id);
|
log.info("[Targeting] Get insights for campaign {}", id);
|
||||||
return ResponseEntity.ok(campaignService.getCampaignInsights(id, userId, datePreset));
|
return ResponseEntity.ok(campaignService.getCampaignInsights(id, userId, datePreset));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/campaigns/{id}/sync-insights")
|
@PostMapping("/campaigns/{id}/sync-insights")
|
||||||
public ResponseEntity<Void> syncInsights(
|
public ResponseEntity<Void> syncInsights(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@PathVariable String id) {
|
@PathVariable String id) {
|
||||||
|
String userId = resolveUserId(userIdHeader, authHeader);
|
||||||
log.info("[Targeting] Force sync insights for campaign {}", id);
|
log.info("[Targeting] Force sync insights for campaign {}", id);
|
||||||
// Authorize
|
|
||||||
campaignService.getCampaignById(id, userId);
|
campaignService.getCampaignById(id, userId);
|
||||||
campaignService.syncInsights(id);
|
campaignService.syncInsights(id);
|
||||||
return ResponseEntity.ok().build();
|
return ResponseEntity.ok().build();
|
||||||
@@ -93,8 +119,10 @@ public class TargetingCampaignController {
|
|||||||
|
|
||||||
@GetMapping("/campaigns/{id}/ab-test/evaluate")
|
@GetMapping("/campaigns/{id}/ab-test/evaluate")
|
||||||
public ResponseEntity<String> evaluateAbTest(
|
public ResponseEntity<String> evaluateAbTest(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@PathVariable String id) {
|
@PathVariable String id) {
|
||||||
|
String userId = resolveUserId(userIdHeader, authHeader);
|
||||||
log.info("[Targeting] Evaluate AB Test for {}", id);
|
log.info("[Targeting] Evaluate AB Test for {}", id);
|
||||||
TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
|
TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
|
||||||
return ResponseEntity.ok(abTestingService.evaluateABTest(campaign));
|
return ResponseEntity.ok(abTestingService.evaluateABTest(campaign));
|
||||||
@@ -104,7 +132,8 @@ public class TargetingCampaignController {
|
|||||||
|
|
||||||
@PostMapping("/audience/segment")
|
@PostMapping("/audience/segment")
|
||||||
public ResponseEntity<List<AudienceSegmentDto>> segmentAudience(
|
public ResponseEntity<List<AudienceSegmentDto>> segmentAudience(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@RequestBody Map<String, String> body) {
|
@RequestBody Map<String, String> body) {
|
||||||
String analysisId = body.get("analysisId");
|
String analysisId = body.get("analysisId");
|
||||||
log.info("[Targeting] Segment audience for analysis {}", analysisId);
|
log.info("[Targeting] Segment audience for analysis {}", analysisId);
|
||||||
@@ -114,7 +143,8 @@ public class TargetingCampaignController {
|
|||||||
|
|
||||||
@PostMapping("/audience/estimate")
|
@PostMapping("/audience/estimate")
|
||||||
public ResponseEntity<Map<String, Long>> estimateAudience(
|
public ResponseEntity<Map<String, Long>> estimateAudience(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@RequestParam String platform,
|
@RequestParam String platform,
|
||||||
@RequestBody TargetingAudienceProfile profile) {
|
@RequestBody TargetingAudienceProfile profile) {
|
||||||
log.info("[Targeting] Estimate audience for platform {}", platform);
|
log.info("[Targeting] Estimate audience for platform {}", platform);
|
||||||
@@ -125,8 +155,10 @@ public class TargetingCampaignController {
|
|||||||
|
|
||||||
@PostMapping("/budget/optimize")
|
@PostMapping("/budget/optimize")
|
||||||
public ResponseEntity<BudgetOptimizationDto> optimizeBudget(
|
public ResponseEntity<BudgetOptimizationDto> optimizeBudget(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@RequestBody Map<String, String> body) {
|
@RequestBody Map<String, String> body) {
|
||||||
|
String userId = resolveUserId(userIdHeader, authHeader);
|
||||||
String campaignId = body.get("campaignId");
|
String campaignId = body.get("campaignId");
|
||||||
log.info("[Targeting] Optimize budget for campaign {}", campaignId);
|
log.info("[Targeting] Optimize budget for campaign {}", campaignId);
|
||||||
TargetingCampaign campaign = campaignService.getCampaignById(campaignId, userId);
|
TargetingCampaign campaign = campaignService.getCampaignById(campaignId, userId);
|
||||||
@@ -138,14 +170,16 @@ public class TargetingCampaignController {
|
|||||||
|
|
||||||
@PostMapping("/account/select")
|
@PostMapping("/account/select")
|
||||||
public ResponseEntity<Void> selectAdAccount(
|
public ResponseEntity<Void> selectAdAccount(
|
||||||
@RequestHeader("X-User-Id") String userId,
|
@RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
|
||||||
|
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||||
@RequestBody Map<String, String> body) {
|
@RequestBody Map<String, String> body) {
|
||||||
|
String userId = resolveUserId(userIdHeader, authHeader);
|
||||||
String platform = body.get("platform");
|
String platform = body.get("platform");
|
||||||
String adAccountId = body.get("adAccountId");
|
String adAccountId = body.get("adAccountId");
|
||||||
|
|
||||||
log.info("[Targeting] Select ad account {} for platform {} by user {}", adAccountId, platform, userId);
|
log.info("[Targeting] Select ad account {} for platform {} by user {}", adAccountId, platform, userId);
|
||||||
credentialsService.updateAdAccountId(userId, platform, adAccountId);
|
credentialsService.updateAdAccountId(userId, platform, adAccountId);
|
||||||
|
|
||||||
return ResponseEntity.ok().build();
|
return ResponseEntity.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -410,25 +410,35 @@ public class TargetingCampaignService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return rawPlatforms.stream()
|
return rawPlatforms.stream()
|
||||||
.map(this::mapPlatform)
|
.flatMap(p -> expandPlatform(p).stream())
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.distinct()
|
.distinct()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private kz.konturai.parser.enums.TargetingPlatform mapPlatform(String platform) {
|
private List<kz.konturai.parser.enums.TargetingPlatform> expandPlatform(String platform) {
|
||||||
if (platform == null || platform.isBlank()) {
|
if (platform == null || platform.isBlank()) {
|
||||||
return null;
|
return List.of();
|
||||||
}
|
}
|
||||||
String normalized = platform.trim().toUpperCase(Locale.ROOT);
|
String normalized = platform.trim().toUpperCase(Locale.ROOT);
|
||||||
|
// FB_IG / META expand to both Facebook + Instagram
|
||||||
|
if ("FB_IG".equals(normalized) || "FB+IG".equals(normalized)) {
|
||||||
|
return List.of(
|
||||||
|
kz.konturai.parser.enums.TargetingPlatform.FACEBOOK,
|
||||||
|
kz.konturai.parser.enums.TargetingPlatform.INSTAGRAM
|
||||||
|
);
|
||||||
|
}
|
||||||
if ("META".equals(normalized)) {
|
if ("META".equals(normalized)) {
|
||||||
return kz.konturai.parser.enums.TargetingPlatform.FACEBOOK;
|
return List.of(
|
||||||
|
kz.konturai.parser.enums.TargetingPlatform.FACEBOOK,
|
||||||
|
kz.konturai.parser.enums.TargetingPlatform.INSTAGRAM
|
||||||
|
);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return kz.konturai.parser.enums.TargetingPlatform.valueOf(normalized);
|
return List.of(kz.konturai.parser.enums.TargetingPlatform.valueOf(normalized));
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
log.warn("Unknown targeting platform '{}', skipping", platform);
|
log.warn("Unknown targeting platform '{}', skipping", platform);
|
||||||
return null;
|
return List.of();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user