target fix

This commit is contained in:
arys
2026-04-03 00:31:46 +05:00
parent 891f9ce3db
commit 1cbca9ecfc
2 changed files with 65 additions and 21 deletions
@@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Map;
@@ -29,63 +30,88 @@ public class TargetingCampaignController {
private final ABTestingService abTestingService;
private final MarketingAnalysisV3Repository analysisRepository;
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")
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) {
String userId = resolveUserId(userIdHeader, authHeader);
log.info("[Targeting] Create campaign requested by {}", userId);
return ResponseEntity.ok(campaignService.createCampaign(request, userId));
}
@GetMapping("/campaigns")
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 = "10") int size) {
String userId = resolveUserId(userIdHeader, authHeader);
log.info("[Targeting] Get campaigns for {}", userId);
return ResponseEntity.ok(campaignService.getUserCampaigns(userId, page, size));
}
@GetMapping("/campaigns/{id}")
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) {
String userId = resolveUserId(userIdHeader, authHeader);
log.info("[Targeting] Get campaign {} for {}", id, userId);
return ResponseEntity.ok(campaignService.getCampaignById(id, userId));
}
@PostMapping("/campaigns/{id}/pause")
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) {
String userId = resolveUserId(userIdHeader, authHeader);
log.info("[Targeting] Pause campaign {}", id);
return ResponseEntity.ok(campaignService.pauseCampaign(id, userId));
}
@PostMapping("/campaigns/{id}/resume")
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) {
String userId = resolveUserId(userIdHeader, authHeader);
log.info("[Targeting] Resume campaign {}", id);
return ResponseEntity.ok(campaignService.resumeCampaign(id, userId));
}
@GetMapping("/campaigns/{id}/insights")
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,
@RequestParam(defaultValue = "last_7d") String datePreset) {
String userId = resolveUserId(userIdHeader, authHeader);
log.info("[Targeting] Get insights for campaign {}", id);
return ResponseEntity.ok(campaignService.getCampaignInsights(id, userId, datePreset));
}
@PostMapping("/campaigns/{id}/sync-insights")
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) {
String userId = resolveUserId(userIdHeader, authHeader);
log.info("[Targeting] Force sync insights for campaign {}", id);
// Authorize
campaignService.getCampaignById(id, userId);
campaignService.syncInsights(id);
return ResponseEntity.ok().build();
@@ -93,8 +119,10 @@ public class TargetingCampaignController {
@GetMapping("/campaigns/{id}/ab-test/evaluate")
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) {
String userId = resolveUserId(userIdHeader, authHeader);
log.info("[Targeting] Evaluate AB Test for {}", id);
TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
return ResponseEntity.ok(abTestingService.evaluateABTest(campaign));
@@ -104,7 +132,8 @@ public class TargetingCampaignController {
@PostMapping("/audience/segment")
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) {
String analysisId = body.get("analysisId");
log.info("[Targeting] Segment audience for analysis {}", analysisId);
@@ -114,7 +143,8 @@ public class TargetingCampaignController {
@PostMapping("/audience/estimate")
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,
@RequestBody TargetingAudienceProfile profile) {
log.info("[Targeting] Estimate audience for platform {}", platform);
@@ -125,8 +155,10 @@ public class TargetingCampaignController {
@PostMapping("/budget/optimize")
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) {
String userId = resolveUserId(userIdHeader, authHeader);
String campaignId = body.get("campaignId");
log.info("[Targeting] Optimize budget for campaign {}", campaignId);
TargetingCampaign campaign = campaignService.getCampaignById(campaignId, userId);
@@ -138,14 +170,16 @@ public class TargetingCampaignController {
@PostMapping("/account/select")
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) {
String userId = resolveUserId(userIdHeader, authHeader);
String platform = body.get("platform");
String adAccountId = body.get("adAccountId");
log.info("[Targeting] Select ad account {} for platform {} by user {}", adAccountId, platform, userId);
credentialsService.updateAdAccountId(userId, platform, adAccountId);
return ResponseEntity.ok().build();
}
@@ -410,25 +410,35 @@ public class TargetingCampaignService {
}
return rawPlatforms.stream()
.map(this::mapPlatform)
.flatMap(p -> expandPlatform(p).stream())
.filter(Objects::nonNull)
.distinct()
.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()) {
return null;
return List.of();
}
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)) {
return kz.konturai.parser.enums.TargetingPlatform.FACEBOOK;
return List.of(
kz.konturai.parser.enums.TargetingPlatform.FACEBOOK,
kz.konturai.parser.enums.TargetingPlatform.INSTAGRAM
);
}
try {
return kz.konturai.parser.enums.TargetingPlatform.valueOf(normalized);
return List.of(kz.konturai.parser.enums.TargetingPlatform.valueOf(normalized));
} catch (IllegalArgumentException ex) {
log.warn("Unknown targeting platform '{}', skipping", platform);
return null;
return List.of();
}
}