23 Commits

Author SHA1 Message Date
a14bc4e73a Add cityID in creation and update and edit some graphics in the map 2025-08-19 09:24:29 +03:00
50c6a2ef5b cloudsystem column added 2025-08-19 07:36:45 +03:00
d4e40f5a6b just pushing this to resolve merge conflict i have no changes made in this commit 2025-08-19 07:33:53 +03:00
bbb0976aa1 added the cloudsystem column 2025-08-19 07:16:17 +03:00
085a417016 Fix dropdown selection overflow while scrolling 2025-08-19 06:51:50 +03:00
edd8feb4d2 Add optimization to show data faster using Memo 2025-08-19 06:43:22 +03:00
2d39883b7f filtering raw data page 2025-08-19 06:17:37 +03:00
21b757cf77 Fix small translation in Map 2025-08-19 05:39:16 +03:00
8bd6d94174 Fix the DataCenterOverview tab display by removing project relation 2025-08-19 05:39:02 +03:00
Ali Sadeghi
b5901a049c Merge: Add city to datacenter, cloudsystem to summary, fix listener 2025-08-19 04:43:53 +03:00
82f86a62ca Fix issue in updating datacenter
Found a hibernate cascade issue and was fixed by reuse the existing collection instaed of creating a new one in updating the datacenter entity
2025-08-19 00:15:51 +03:00
47959fb35f Make the datacenter creation modal mobile friendly 2025-08-19 00:08:42 +03:00
2257ec79f6 Make creation of default area nested in city initialization 2025-08-19 00:08:01 +03:00
17d77fcda7 Fix message queue data misnaming 2025-08-19 00:07:20 +03:00
92d88df213 Fix Backend error:
Error loading data: Exception while fetching data (/vmEmissionSummary) : org.hibernate.exception.SQLGrammarException: could not extract ResultSet
2025-08-18 08:03:40 +03:00
a66b01334d Small bug fix 2025-08-18 08:02:34 +03:00
c7e60c25eb Add datacenter with multiple emission source and inputs 2025-08-18 06:12:19 +03:00
ebd997a33d Fix the datacenter query according to the changes in backend 2025-08-18 05:38:51 +03:00
dd04a057b1 Comment not needed orgnization code 2025-08-18 05:38:39 +03:00
d224905ba0 Make the Datacenter module structure following the whole code structure 2025-08-18 05:38:20 +03:00
b5ceb1591e Merge Backend Updates 2025-08-18 04:28:45 +03:00
89b4644983 few translation edits and changing it to use vmEmission query 2025-08-09 20:08:56 +03:00
39fffadbd2 fixed issue GUI and Datacenter tab related 2025-08-07 19:28:56 +03:00
60 changed files with 3921 additions and 2084 deletions

39
docker-compose.yml Normal file
View File

@@ -0,0 +1,39 @@
services:
backend:
build:
context: ./sge-backend
dockerfile: Dockerfile
ports:
- "8080:8080"
env_file:
- ./config.conf
environment:
SPRING_PROFILES_ACTIVE: docker
depends_on:
- database
restart: unless-stopped
frontend:
build:
context: ./sge-frontend
dockerfile: Dockerfile
ports:
- "80:80"
env_file:
- ./config.conf
restart: unless-stopped
database:
image: postgres:15
environment:
POSTGRES_DB: sge
POSTGRES_USER: sge
POSTGRES_PASSWORD: 147
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
postgres_data:

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,8 @@ package com.sgs;
import com.sgs.graphql.activitySubUnit.domain.ActivitySubUnit;
import com.sgs.graphql.activitySubUnit.service.ActivitySubUnitService;
import com.sgs.graphql.area.domain.Area;
import com.sgs.graphql.area.service.AreaService;
import com.sgs.graphql.city.domain.City;
import com.sgs.graphql.city.repo.CityRepo;
import com.sgs.graphql.city.service.CityService;
@@ -73,6 +75,7 @@ public class SgsApplication implements CommandLineRunner {
private final PermissionService permissionService;
private final RoleService roleService;
private final RoleRepo roleRepo;
private final AreaService areaService;
private final NeighborhoodRepo neighborhoodRepo;
private final NeighborhoodService neighborhoodService;
private final CityService cityService;
@@ -118,7 +121,8 @@ public class SgsApplication implements CommandLineRunner {
@Autowired
public SgsApplication(RoleService roleService, PermissionService permissionService, RoleRepo roleRepo,
NeighborhoodRepo neighborhoodRepo, NeighborhoodService neighborhoodService, CityService cityService,
AreaService areaService, NeighborhoodRepo neighborhoodRepo, NeighborhoodService neighborhoodService,
CityService cityService,
CityRepo cityRepo, DistrictRepo districtRepo, DistrictService districtService, CountryRepo countryRepo,
CountryService countryService, OrganizationService organizationService, UserService userService,
PasswordEncoder passwordEncoder, SectorService sectorService, SubSectorService subSectorService,
@@ -133,6 +137,7 @@ public class SgsApplication implements CommandLineRunner {
this.roleService = roleService;
this.permissionService = permissionService;
this.roleRepo = roleRepo;
this.areaService = areaService;
this.neighborhoodRepo = neighborhoodRepo;
this.neighborhoodService = neighborhoodService;
this.cityService = cityService;
@@ -426,6 +431,10 @@ public class SgsApplication implements CommandLineRunner {
data_center_read.setTag(PermissionName.DATA_CENTER_READ);
data_center_read.setDescription(PermissionDescription.DATA_CENTER_READ);
Permission paginate_datacenters_get = new Permission();
paginate_datacenters_get.setTag(PermissionName.PAGINATE_DATACENTERS_GET);
paginate_datacenters_get.setDescription(PermissionDescription.PAGINATE_DATACENTERS_GET);
permissionService.saveAll(List.of(
show_graphics, activities_get, paginate_user_histories, activity_sub_units_get, sub_sectors_get,
sectors_get, deleted_items, undelete_items, user_create, user_update, user_delete, paginate_users_get,
@@ -442,7 +451,7 @@ public class SgsApplication implements CommandLineRunner {
question_create, question_delete, question_update, paginate_questions_get,
published_survey_create, surveys_get, paginate_surveys_get,
survey_add, survey_delete, survey_update, settings_access, data_center_create, data_center_delete,
data_center_update, data_center_read));
data_center_update, data_center_read, paginate_datacenters_get));
}
public void createDefaultRole() {
@@ -771,6 +780,27 @@ public class SgsApplication implements CommandLineRunner {
mailInfoService.save(mailInfo);
}
public void ensureMissingPermissions() {
// Check if paginate_datacenters_get permission exists
Optional<Permission> datacenterPermission = permissionService.findByTag("paginate_datacenters_get");
if (!datacenterPermission.isPresent()) {
// Create the missing permission
Permission paginate_datacenters_get = new Permission();
paginate_datacenters_get.setTag(PermissionName.PAGINATE_DATACENTERS_GET);
paginate_datacenters_get.setDescription(PermissionDescription.PAGINATE_DATACENTERS_GET);
permissionService.save(paginate_datacenters_get);
}
// Ensure SUPER_ADMIN has all permissions
Optional<Role> superAdminRole = roleRepo.findByTag("SUPER_ADMIN");
if (superAdminRole.isPresent()) {
Role role = superAdminRole.get();
List<Permission> allPermissions = permissionService.findAll();
role.setPermissions(allPermissions);
roleService.save(role);
}
}
@Override
public void run(String... args) throws Exception {
if (mailInfoService.findAll().isEmpty()) {
@@ -816,6 +846,8 @@ public class SgsApplication implements CommandLineRunner {
if (roleService.findAll().isEmpty()) {
createDefaultRole();
}
// Ensure all permissions are created and assigned to SUPER_ADMIN
ensureMissingPermissions();
if (organizationService.findAll().isEmpty()) {
createDefaultOrganization();
}
@@ -827,6 +859,7 @@ public class SgsApplication implements CommandLineRunner {
}
if (cityService.findAll().isEmpty()) {
createCitiesFromJson();
createDefaultArea();
}
if (districtService.findAll().isEmpty()) {
createDistrictFromJson();
@@ -834,18 +867,31 @@ public class SgsApplication implements CommandLineRunner {
if (neighborhoodService.findAll().isEmpty()) {
createNeighborhoodsFromJson();
}
// Add new permission if it doesn't exist
// [Remove Later]
if (permissionService.findAll().stream().noneMatch(p -> PermissionName.SETTINGS_ACCESS.equals(p.getTag()))) {
Permission settingsAccess = new Permission();
settingsAccess.setTag(PermissionName.SETTINGS_ACCESS);
settingsAccess.setDescription(PermissionDescription.SETTINGS_ACCESS);
settingsAccess.setDefault_permission(false);
settingsAccess.setDeleted(false);
permissionService.save(settingsAccess);
}
void createDefaultArea() {
// Check if default area already exists
List<Area> existingAreas = areaService.findAll();
boolean defaultAreaExists = existingAreas.stream()
.anyMatch(area -> "Turkiye".equals(area.getTag()) && area.isDefaultArea());
if (!defaultAreaExists) {
Area defaultArea = new Area();
defaultArea.setTag("Turkiye");
defaultArea.setDefaultArea(true);
defaultArea.setDeleted(false);
// Get all cities to add to the default area
List<City> allCities = cityService.findAll();
defaultArea.setCities(allCities);
// Get the Turkey country to add to the default area
List<Country> countries = countryService.findAll();
if (!countries.isEmpty()) {
defaultArea.setCountries(countries);
}
areaService.save(defaultArea);
}
Permission settings_access = new Permission();
settings_access.setTag(PermissionName.SETTINGS_ACCESS);
settings_access.setDescription(PermissionDescription.SETTINGS_ACCESS);
}
}

View File

@@ -1,12 +1,12 @@
package com.sgs.graphql.dataCenter.domain;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.sgs.graphql.area.domain.Area;
import com.sgs.graphql.city.domain.City;
import com.sgs.graphql.sector.domain.Sector;
import com.sgs.graphql.subSector.domain.SubSector;
import com.sgs.graphql.emissionSource.domain.EmissionSource;
import com.sgs.graphql.emissionScope.domain.EmissionScope;
import com.sgs.graphql.consuptionUnit.domain.ConsuptionUnit;
import com.sgs.graphql.activitySubUnit.domain.ActivitySubUnit;
import com.sgs.lib.dao.domain.BaseDomain;
@@ -14,7 +14,8 @@ import javax.persistence.*;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.springframework.transaction.annotation.Transactional;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import java.util.ArrayList;
import java.util.List;
@@ -26,28 +27,26 @@ public class DataCenter extends BaseDomain {
@Column(unique = true)
private Integer externalId;
private Integer number;
private Area area;
private City city;
private List<Project> projects = new ArrayList<>();
private List<PhysicalMachine> physicalMachines = new ArrayList<>();
private List<DataCenterEmissionSource> dataCenterEmissionSources = new ArrayList<>();
private Sector sector;
private SubSector subSector;
private EmissionSource emissionSource;
private EmissionScope emissionScope;
private Double consuptionAmount;
private ConsuptionUnit consuptionUnit;
private ActivitySubUnit activitySubUnit;
// New attributes
private String ayposURL;
private String address;
private Double latitude;
private Double longitude;
@Column(name = "data_center_name")
@Transactional
public String getDataCenter() {
return dataCenter;
}
@@ -63,12 +62,23 @@ public class DataCenter extends BaseDomain {
@OneToMany(mappedBy = "dataCenter", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@JsonManagedReference
public List<Project> getProjects() {
return projects;
public List<PhysicalMachine> getPhysicalMachines() {
return physicalMachines;
}
public void setProjects(List<Project> projects) {
this.projects = projects;
public void setPhysicalMachines(List<PhysicalMachine> physicalMachines) {
this.physicalMachines = physicalMachines;
}
@OneToMany(mappedBy = "dataCenter", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@Fetch(FetchMode.SUBSELECT)
@JsonManagedReference
public List<DataCenterEmissionSource> getDataCenterEmissionSources() {
return dataCenterEmissionSources;
}
public void setDataCenterEmissionSources(List<DataCenterEmissionSource> dataCenterEmissionSources) {
this.dataCenterEmissionSources = dataCenterEmissionSources;
}
public void setExternalId(Integer externalId) {
@@ -84,7 +94,6 @@ public class DataCenter extends BaseDomain {
this.number = number;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "sector_id")
public Sector getSector() {
@@ -114,16 +123,6 @@ public class DataCenter extends BaseDomain {
this.consuptionAmount = consuptionAmount;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "consuption_unit_id")
public ConsuptionUnit getConsuptionUnit() {
return consuptionUnit;
}
public void setConsuptionUnit(ConsuptionUnit consuptionUnit) {
this.consuptionUnit = consuptionUnit;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "area_id")
public Area getArea() {
@@ -134,6 +133,16 @@ public class DataCenter extends BaseDomain {
this.area = area;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "city_id")
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "sub_sector_id")
public SubSector getSubSector() {
@@ -144,16 +153,6 @@ public class DataCenter extends BaseDomain {
this.subSector = subSector;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "emission_source_id")
public EmissionSource getEmissionSource() {
return emissionSource;
}
public void setEmissionSource(EmissionSource emissionSource) {
this.emissionSource = emissionSource;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "activity_sub_unit_id")
public ActivitySubUnit getActivitySubUnit() {

View File

@@ -0,0 +1,68 @@
package com.sgs.graphql.dataCenter.domain;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.sgs.graphql.emissionSource.domain.EmissionSource;
import com.sgs.graphql.consuptionUnit.domain.ConsuptionUnit;
import com.sgs.lib.dao.domain.BaseDomain;
import javax.persistence.*;
@Entity
@Table(name = "data_center_emission_source")
public class DataCenterEmissionSource extends BaseDomain {
private DataCenter dataCenter;
private EmissionSource emissionSource;
private ConsuptionUnit consuptionUnit;
private Boolean isDefault = false; // To mark which one is the default emission source
private Double percentage; // Percentage allocation for this emission source (optional)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "data_center_id", nullable = false)
@JsonBackReference
public DataCenter getDataCenter() {
return dataCenter;
}
public void setDataCenter(DataCenter dataCenter) {
this.dataCenter = dataCenter;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "emission_source_id", nullable = false)
public EmissionSource getEmissionSource() {
return emissionSource;
}
public void setEmissionSource(EmissionSource emissionSource) {
this.emissionSource = emissionSource;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "consuption_unit_id", nullable = false)
public ConsuptionUnit getConsuptionUnit() {
return consuptionUnit;
}
public void setConsuptionUnit(ConsuptionUnit consuptionUnit) {
this.consuptionUnit = consuptionUnit;
}
@Column(name = "is_default")
public Boolean getIsDefault() {
return isDefault;
}
public void setIsDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
@Column(name = "percentage")
public Double getPercentage() {
return percentage;
}
public void setPercentage(Double percentage) {
this.percentage = percentage;
}
}

View File

@@ -14,9 +14,10 @@ public class PhysicalMachine extends BaseDomain {
private String name;
private String ip;
private String tag;
private String cloudSystem;
private Double power;
private List<VM> vms = new ArrayList<>();
private Project project;
private DataCenter dataCenter;
@Column(name = "name")
public String getName() {
@@ -45,6 +46,15 @@ public class PhysicalMachine extends BaseDomain {
this.tag = tag;
}
@Column(name = "cloud_system")
public String getCloudSystem() {
return cloudSystem;
}
public void setCloudSystem(String cloudSystem) {
this.cloudSystem = cloudSystem;
}
@Column(name = "power")
public Double getPower() {
return power;
@@ -65,13 +75,13 @@ public class PhysicalMachine extends BaseDomain {
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "project_id")
@JoinColumn(name = "data_center_id")
@JsonBackReference
public Project getProject() {
return project;
public DataCenter getDataCenter() {
return dataCenter;
}
public void setProject(Project project) {
this.project = project;
public void setDataCenter(DataCenter dataCenter) {
this.dataCenter = dataCenter;
}
}

View File

@@ -1,50 +0,0 @@
package com.sgs.graphql.dataCenter.domain;
import java.util.List;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.sgs.lib.dao.domain.BaseDomain;
@Entity
@Table(name = "project")
public class Project extends BaseDomain{
private String name;
private List<PhysicalMachine> physicalMachines;
@OneToMany(mappedBy = "project", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
public List<PhysicalMachine> getPhysicalMachines() {
return physicalMachines;
}
public void setPhysicalMachines(List<PhysicalMachine> physicalMachines) {
this.physicalMachines = physicalMachines;
}
// This creates a foreign key in the `project` table
private DataCenter dataCenter;
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne
@JoinColumn(name = "data_center_id")
@JsonBackReference
public DataCenter getDataCenter() {
return dataCenter;
}
public void setDataCenter(DataCenter dataCenter) {
this.dataCenter = dataCenter;
}
}

View File

@@ -23,6 +23,7 @@ public class VM extends BaseDomain {
private String host;
private String flavorName;
private String tag;
private String project; // UUID of the project this VM belongs to
private String emissionSourceData; // JSON string to store emission source map
private Config config;
private PhysicalMachine physicalMachine;
@@ -100,6 +101,15 @@ public class VM extends BaseDomain {
this.tag = tag;
}
@Column(name = "project")
public String getProject() {
return project;
}
public void setProject(String project) {
this.project = project;
}
@Column(name = "ip")
public String getIp() {
return ip;

View File

@@ -17,8 +17,10 @@ public class DataCenterDto {
private Integer externalId;
private Integer number;
private AreaDto area;
private Map<String, ProjectDto> projects;
@JsonProperty("physical_machines")
private Map<String, PhysicalMachineDto> physicalMachine;
// Emission calculation fields
private SectorDto sector;
private SubSectorDto subSector;
@@ -60,20 +62,20 @@ public class DataCenterDto {
this.number = number;
}
public AreaDto getArea() {
return area;
}
public void setArea(AreaDto area) {
this.area = area;
public AreaDto getArea() {
return area;
}
public Map<String, ProjectDto> getProjects() {
return projects;
public void setArea(AreaDto area) {
this.area = area;
}
public void setProjects(Map<String, ProjectDto> projects) {
this.projects = projects;
public Map<String, PhysicalMachineDto> getPhysicalMachine() {
return physicalMachine;
}
public void setPhysicalMachine(Map<String, PhysicalMachineDto> physicalMachine) {
this.physicalMachine = physicalMachine;
}
public SectorDto getSector() {

View File

@@ -0,0 +1,50 @@
package com.sgs.graphql.dataCenter.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
public class DataCenterEmissionSourceDto {
@JsonProperty("emission_source_id")
private String emissionSourceId;
@JsonProperty("consuption_unit_id")
private String consuptionUnitId;
@JsonProperty("is_default")
private Boolean isDefault = false;
@JsonProperty("percentage")
private Double percentage;
public String getEmissionSourceId() {
return emissionSourceId;
}
public void setEmissionSourceId(String emissionSourceId) {
this.emissionSourceId = emissionSourceId;
}
public String getConsuptionUnitId() {
return consuptionUnitId;
}
public void setConsuptionUnitId(String consuptionUnitId) {
this.consuptionUnitId = consuptionUnitId;
}
public Boolean getIsDefault() {
return isDefault;
}
public void setIsDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
public Double getPercentage() {
return percentage;
}
public void setPercentage(Double percentage) {
this.percentage = percentage;
}
}

View File

@@ -1,24 +0,0 @@
package com.sgs.graphql.dataCenter.dto;
import java.util.Map;
public class MainOptimizationSpaceDto {
private Map<String, VMDto> vms;
private Map<String, PhysicalMachineDto> pms;
public Map<String, VMDto> getVms() {
return vms;
}
public void setVms(Map<String, VMDto> vms) {
this.vms = vms;
}
public Map<String, PhysicalMachineDto> getPms() {
return pms;
}
public void setPms(Map<String, PhysicalMachineDto> pms) {
this.pms = pms;
}
}

View File

@@ -2,6 +2,7 @@ package com.sgs.graphql.dataCenter.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.Map;
public class PhysicalMachineDto {
@JsonProperty("name")
@@ -10,11 +11,17 @@ public class PhysicalMachineDto {
@JsonProperty("tag")
private String tag;
@JsonProperty("cloud_system")
private String cloudSystem;
@JsonProperty("power")
private double power;
@JsonProperty("confg") // Note: keeping the typo from JSON
private List<Object> confg;
@JsonProperty("vms")
private Map<String, VMDto> vms;
private String ip; // IP address from the message key
@@ -34,6 +41,14 @@ public class PhysicalMachineDto {
this.tag = tag;
}
public String getCloudSystem() {
return cloudSystem;
}
public void setCloudSystem(String cloudSystem) {
this.cloudSystem = cloudSystem;
}
public double getPower() {
return power;
}
@@ -57,4 +72,12 @@ public class PhysicalMachineDto {
public void setIp(String ip) {
this.ip = ip;
}
public Map<String, VMDto> getVms() {
return vms;
}
public void setVms(Map<String, VMDto> vms) {
this.vms = vms;
}
}

View File

@@ -1,61 +0,0 @@
package com.sgs.graphql.dataCenter.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
public class ProjectDto {
@JsonProperty("main_optimization_space")
private MainOptimizationSpaceDto mainOptimizationSpace;
@JsonProperty("sub_optimization_space")
private SubOptimizationSpaceDto subOptimizationSpace;
// Legacy field - kept for backward compatibility with older message formats
@JsonProperty("physical_machines")
private List<PhysicalMachineDto> physicalMachines;
// These fields are derived from the map key and entity relationships, not from the message
private String id; // This will be set from the map key
private String name; // This will be derived or set separately
public MainOptimizationSpaceDto getMainOptimizationSpace() {
return mainOptimizationSpace;
}
public void setMainOptimizationSpace(MainOptimizationSpaceDto mainOptimizationSpace) {
this.mainOptimizationSpace = mainOptimizationSpace;
}
public SubOptimizationSpaceDto getSubOptimizationSpace() {
return subOptimizationSpace;
}
public void setSubOptimizationSpace(SubOptimizationSpaceDto subOptimizationSpace) {
this.subOptimizationSpace = subOptimizationSpace;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<PhysicalMachineDto> getPhysicalMachines() {
return physicalMachines;
}
public void setPhysicalMachines(List<PhysicalMachineDto> physicalMachines) {
this.physicalMachines = physicalMachines;
}
}

View File

@@ -1,24 +0,0 @@
package com.sgs.graphql.dataCenter.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* DTO for sub_optimization_space in the message format.
* Currently appears to be empty in the message structure.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class SubOptimizationSpaceDto {
// Currently empty based on the message format
// Can be extended if needed in the future
// Add a placeholder field to make Jackson happy
private boolean isEmpty = true;
public boolean isEmpty() {
return isEmpty;
}
public void setEmpty(boolean empty) {
this.isEmpty = empty;
}
}

View File

@@ -26,6 +26,9 @@ public class VMDto {
@JsonProperty("tag")
private String tag;
@JsonProperty("project")
private String project;
@JsonProperty("confg") // Note: keeping the typo from JSON
private List<Object> confg;
@@ -101,6 +104,14 @@ public class VMDto {
this.tag = tag;
}
public String getProject() {
return project;
}
public void setProject(String project) {
this.project = project;
}
public List<Object> getConfg() {
return confg;
}

View File

@@ -1,18 +1,26 @@
package com.sgs.graphql.dataCenter.mutation;
import com.sgs.exception.GraphQLCustomException;
import com.sgs.graphql.dataCenter.mutation.mapper.DataCenterMapper;
import com.sgs.graphql.dataCenter.service.DataCenterService;
import com.sgs.graphql.dataCenter.domain.DataCenter;
import com.sgs.graphql.dataCenter.mutation.input.DataCenterCreateInput;
import com.sgs.graphql.dataCenter.mutation.input.DataCenterUpdateInput;
import com.sgs.graphql.permission.domain.PermissionName;
import com.sgs.graphql.systemHistory.enums.LogType;
import com.sgs.graphql.systemHistory.mutation.SystemLogger;
import com.sgs.graphql.userHistory.mutation.UserLogger;
import com.sgs.graphql.userNotification.mutation.UserNotificationMutation;
import graphql.kickstart.tools.GraphQLMutationResolver;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.transaction.Transactional;
import javax.validation.Valid;
import java.util.NoSuchElementException;
import java.util.UUID;
@Validated
@@ -21,57 +29,128 @@ public class DataCenterMutation implements GraphQLMutationResolver {
private final DataCenterService dataCenterService;
private final DataCenterMapper dataCenterMapper;
private final SystemLogger systemLogger;
private final UserLogger userLogger;
private final UserNotificationMutation notificationMutation;
@Autowired
public DataCenterMutation(DataCenterService dataCenterService, DataCenterMapper dataCenterMapper) {
public DataCenterMutation(DataCenterService dataCenterService, DataCenterMapper dataCenterMapper,
SystemLogger systemLogger, UserLogger userLogger,
UserNotificationMutation notificationMutation) {
this.dataCenterService = dataCenterService;
this.dataCenterMapper = dataCenterMapper;
this.systemLogger = systemLogger;
this.userLogger = userLogger;
this.notificationMutation = notificationMutation;
}
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_CREATE + "')")
public DataCenter createDataCenter(@Valid DataCenterCreateInput input) {
// Check for duplicate externalId
if (input.getExternalId() != null && dataCenterService.existsByExternalId(input.getExternalId())) {
throw new RuntimeException("This external id already exists: " + input.getExternalId());
@Transactional
public DataCenter createDataCenter(@Valid DataCenterCreateInput input, DataFetchingEnvironment environment) {
try {
// Check for duplicate externalId
if (input.getExternalId() != null && dataCenterService.existsByExternalId(input.getExternalId())) {
throw new GraphQLCustomException("2010", input.getExternalId().toString());
}
DataCenter dataCenter = dataCenterMapper.toEntity(input);
// Set auto-generated number if not provided
if (dataCenter.getNumber() == null) {
Integer maxNumber = dataCenterService.findMaxNumber();
dataCenter.setNumber((maxNumber == null) ? 1 : maxNumber + 1);
}
DataCenter savedDataCenter = dataCenterService.save(dataCenter);
// Log and notify
String dataCenterName = savedDataCenter.getDataCenter() != null ? savedDataCenter.getDataCenter()
: "DataCenter #" + savedDataCenter.getNumber();
systemLogger.createSystemLog(LogType.INFO, dataCenterName + " adlı veri merkezi oluşturuldu");
userLogger.createUserLog(LogType.INFO, dataCenterName + " adlı veri merkezi oluşturuldu", environment);
notificationMutation.createNotification(environment, "Veri Merkezi",
dataCenterName + " adlı veri merkezi oluşturuldu", "Yeni kayıt");
return savedDataCenter;
} catch (GraphQLCustomException e) {
throw e;
} catch (Exception e) {
systemLogger.createSystemLog(LogType.ERROR,
"Yeni veri merkezi oluşturulurken hata oluştu: " + e.getMessage());
throw e;
}
DataCenter dataCenter = dataCenterMapper.toEntity(input);
// Set auto-generated number if not provided
if (dataCenter.getNumber() == null) {
Integer maxNumber = dataCenterService.getRepository().findMaxNumber();
dataCenter.setNumber((maxNumber == null) ? 1 : maxNumber + 1);
}
return dataCenterService.save(dataCenter);
}
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_UPDATE + "')")
public DataCenter updateDataCenter(UUID id, @Valid DataCenterUpdateInput input) {
return dataCenterService.findById(id)
.map(dataCenter -> {
// Check for duplicate externalId if it's being updated
if (input.getExternalId() != null &&
!input.getExternalId().equals(dataCenter.getExternalId()) &&
dataCenterService.existsByExternalId(input.getExternalId())) {
throw new RuntimeException("This external id already exists: " + input.getExternalId());
}
return dataCenterService.update(dataCenterMapper.updateEntity(dataCenter, input));
})
.orElseThrow(() -> new RuntimeException("Data center not found with ID: " + id));
@Transactional
public DataCenter updateDataCenter(UUID id, @Valid DataCenterUpdateInput input,
DataFetchingEnvironment environment) {
try {
DataCenter dataCenter = dataCenterService.findById(id)
.orElseThrow(() -> new NoSuchElementException("Data center not found with ID: " + id));
// Check for duplicate externalId if it's being updated
if (input.getExternalId() != null &&
!input.getExternalId().equals(dataCenter.getExternalId()) &&
dataCenterService.existsByExternalId(input.getExternalId())) {
throw new GraphQLCustomException("2010", input.getExternalId().toString());
}
DataCenter updatedDataCenter = dataCenterService.update(dataCenterMapper.updateEntity(dataCenter, input));
// Log and notify
String dataCenterName = updatedDataCenter.getDataCenter() != null ? updatedDataCenter.getDataCenter()
: "DataCenter #" + updatedDataCenter.getNumber();
systemLogger.createSystemLog(LogType.INFO, dataCenterName + " adlı veri merkezi güncellendi");
userLogger.createUserLog(LogType.INFO, dataCenterName + " adlı veri merkezi güncellendi", environment);
notificationMutation.createNotification(environment, "Veri Merkezi",
dataCenterName + " adlı veri merkezi güncellendi", "Güncelleme");
return updatedDataCenter;
} catch (GraphQLCustomException e) {
throw e;
} catch (NoSuchElementException e) {
systemLogger.createSystemLog(LogType.ERROR, "Veri merkezi bulunamadı: " + id);
throw e;
} catch (Exception e) {
systemLogger.createSystemLog(LogType.ERROR, "Veri merkezi güncellenirken hata oluştu: " + e.getMessage());
throw e;
}
}
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_DELETE + "')")
public Boolean deleteDataCenter(UUID id) {
@Transactional
public String deleteDataCenter(UUID id, DataFetchingEnvironment environment) {
String dataCenterName = "";
try {
DataCenter dataCenter = dataCenterService.findById(id)
.orElseThrow(() -> new RuntimeException("Data center not found with ID: " + id));
.orElseThrow(() -> new NoSuchElementException("Data center not found with ID: " + id));
dataCenterName = dataCenter.getDataCenter() != null ? dataCenter.getDataCenter()
: "DataCenter #" + dataCenter.getNumber();
// Check if data center has physical machines or other dependencies
if (dataCenter.getPhysicalMachines() != null && !dataCenter.getPhysicalMachines().isEmpty()) {
String message = "Silinmeye çalışılan veri merkezinin fiziksel makineleri olduğu için silinememektedir";
systemLogger.createSystemLog(LogType.WARN, dataCenterName + ": " + message);
return message;
}
dataCenterService.delete(dataCenter);
return true;
// Log and notify
systemLogger.createSystemLog(LogType.INFO, dataCenterName + " adlı veri merkezi silindi");
userLogger.createUserLog(LogType.INFO, dataCenterName + " adlı veri merkezi silindi", environment);
notificationMutation.createNotification(environment, "Veri Merkezi",
dataCenterName + " adlı veri merkezi silindi", "Silme");
return "true";
} catch (NoSuchElementException e) {
systemLogger.createSystemLog(LogType.ERROR, "Veri merkezi bulunamadı: " + id);
return "false";
} catch (Exception e) {
System.out.println("DataCenter deletion error: " + e.getMessage());
return false;
systemLogger.createSystemLog(LogType.ERROR, "Veri merkezi silinirken hata oluştu: " + e.getMessage());
return "false";
}
}
}

View File

@@ -5,6 +5,7 @@ import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Min;
import java.util.UUID;
import java.util.List;
public class DataCenterCreateInput extends BaseCreateInput {
@NotBlank(message = "Data center adı gereklidir")
@@ -15,18 +16,20 @@ public class DataCenterCreateInput extends BaseCreateInput {
private Integer number;
private Double consuptionAmount;
@NotNull(message = "Alan ID gereklidir")
private UUID areaId;
private UUID cityId;
@NotNull(message = "Sektör ID gereklidir")
private UUID sectorId;
private UUID subSectorId;
private UUID emissionSourceId;
private UUID emissionScopeId;
private UUID consuptionUnitId;
private UUID activitySubUnitId;
// Multiple emission sources support - each with exactly one unit
private List<DataCenterEmissionSourceInput> dataCenterEmissionSources;
// New attributes
private String ayposURL;
private String address;
@@ -49,24 +52,24 @@ public class DataCenterCreateInput extends BaseCreateInput {
public UUID getAreaId() { return areaId; }
public void setAreaId(UUID areaId) { this.areaId = areaId; }
public UUID getCityId() { return cityId; }
public void setCityId(UUID cityId) { this.cityId = cityId; }
public UUID getSectorId() { return sectorId; }
public void setSectorId(UUID sectorId) { this.sectorId = sectorId; }
public UUID getSubSectorId() { return subSectorId; }
public void setSubSectorId(UUID subSectorId) { this.subSectorId = subSectorId; }
public UUID getEmissionSourceId() { return emissionSourceId; }
public void setEmissionSourceId(UUID emissionSourceId) { this.emissionSourceId = emissionSourceId; }
public UUID getEmissionScopeId() { return emissionScopeId; }
public void setEmissionScopeId(UUID emissionScopeId) { this.emissionScopeId = emissionScopeId; }
public UUID getConsuptionUnitId() { return consuptionUnitId; }
public void setConsuptionUnitId(UUID consuptionUnitId) { this.consuptionUnitId = consuptionUnitId; }
public UUID getActivitySubUnitId() { return activitySubUnitId; }
public void setActivitySubUnitId(UUID activitySubUnitId) { this.activitySubUnitId = activitySubUnitId; }
public List<DataCenterEmissionSourceInput> getDataCenterEmissionSources() { return dataCenterEmissionSources; }
public void setDataCenterEmissionSources(List<DataCenterEmissionSourceInput> dataCenterEmissionSources) { this.dataCenterEmissionSources = dataCenterEmissionSources; }
// New attribute getters and setters
public String getAyposURL() { return ayposURL; }
public void setAyposURL(String ayposURL) { this.ayposURL = ayposURL; }

View File

@@ -0,0 +1,40 @@
package com.sgs.graphql.dataCenter.mutation.input;
public class DataCenterEmissionSourceInput {
private String emissionSourceId;
private String consuptionUnitId;
private Boolean isDefault = false;
private Double percentage;
public String getEmissionSourceId() {
return emissionSourceId;
}
public void setEmissionSourceId(String emissionSourceId) {
this.emissionSourceId = emissionSourceId;
}
public String getConsuptionUnitId() {
return consuptionUnitId;
}
public void setConsuptionUnitId(String consuptionUnitId) {
this.consuptionUnitId = consuptionUnitId;
}
public Boolean getIsDefault() {
return isDefault;
}
public void setIsDefault(Boolean isDefault) {
this.isDefault = isDefault;
}
public Double getPercentage() {
return percentage;
}
public void setPercentage(Double percentage) {
this.percentage = percentage;
}
}

View File

@@ -1,8 +1,11 @@
package com.sgs.graphql.dataCenter.mutation.input;
import com.sgs.lib.dao.mutation.input.BaseUpdateInput;
import java.util.List;
import java.util.UUID;
import javax.validation.constraints.NotNull;
public class DataCenterUpdateInput extends BaseUpdateInput {
private String dataCenter;
private Integer externalId;
@@ -10,13 +13,16 @@ public class DataCenterUpdateInput extends BaseUpdateInput {
private Double consuptionAmount;
private UUID areaId;
private UUID cityId;
@NotNull(message = "Sektör ID gereklidir")
private UUID sectorId;
private UUID subSectorId;
private UUID emissionSourceId;
private UUID emissionScopeId;
private UUID consuptionUnitId;
private UUID activitySubUnitId;
// Multiple emission sources with units
private List<DataCenterEmissionSourceInput> dataCenterEmissionSources;
// New attributes
private String ayposURL;
private String address;
@@ -39,24 +45,28 @@ public class DataCenterUpdateInput extends BaseUpdateInput {
public UUID getAreaId() { return areaId; }
public void setAreaId(UUID areaId) { this.areaId = areaId; }
public UUID getCityId() { return cityId; }
public void setCityId(UUID cityId) { this.cityId = cityId; }
public UUID getSectorId() { return sectorId; }
public void setSectorId(UUID sectorId) { this.sectorId = sectorId; }
public UUID getSubSectorId() { return subSectorId; }
public void setSubSectorId(UUID subSectorId) { this.subSectorId = subSectorId; }
public UUID getEmissionSourceId() { return emissionSourceId; }
public void setEmissionSourceId(UUID emissionSourceId) { this.emissionSourceId = emissionSourceId; }
public UUID getEmissionScopeId() { return emissionScopeId; }
public void setEmissionScopeId(UUID emissionScopeId) { this.emissionScopeId = emissionScopeId; }
public UUID getConsuptionUnitId() { return consuptionUnitId; }
public void setConsuptionUnitId(UUID consuptionUnitId) { this.consuptionUnitId = consuptionUnitId; }
public UUID getActivitySubUnitId() { return activitySubUnitId; }
public void setActivitySubUnitId(UUID activitySubUnitId) { this.activitySubUnitId = activitySubUnitId; }
public List<DataCenterEmissionSourceInput> getDataCenterEmissionSources() {
return dataCenterEmissionSources;
}
public void setDataCenterEmissionSources(List<DataCenterEmissionSourceInput> dataCenterEmissionSources) {
this.dataCenterEmissionSources = dataCenterEmissionSources;
}
// New attribute getters and setters
public String getAyposURL() { return ayposURL; }
public void setAyposURL(String ayposURL) { this.ayposURL = ayposURL; }

View File

@@ -1,8 +1,10 @@
package com.sgs.graphql.dataCenter.mutation.mapper;
import com.sgs.graphql.dataCenter.domain.DataCenter;
import com.sgs.graphql.dataCenter.domain.DataCenterEmissionSource;
import com.sgs.graphql.dataCenter.mutation.input.DataCenterCreateInput;
import com.sgs.graphql.dataCenter.mutation.input.DataCenterUpdateInput;
import com.sgs.graphql.dataCenter.mutation.input.DataCenterEmissionSourceInput;
import com.sgs.graphql.area.service.AreaService;
import com.sgs.graphql.sector.service.SectorService;
import com.sgs.graphql.subSector.service.SubSectorService;
@@ -10,9 +12,13 @@ import com.sgs.graphql.emissionSource.service.EmissionSourceService;
import com.sgs.graphql.emissionScope.service.EmissionScopeService;
import com.sgs.graphql.consuptionUnit.service.ConsuptionUnitService;
import com.sgs.graphql.activitySubUnit.service.ActivitySubUnitService;
import com.sgs.graphql.city.service.CityService;
import com.sgs.lib.dao.mutation.mapper.BaseCreateUpdateMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.ArrayList;
import java.util.UUID;
@Component
public class DataCenterMapper extends BaseCreateUpdateMapper<DataCenter, DataCenterCreateInput, DataCenterUpdateInput> {
@@ -24,12 +30,13 @@ public class DataCenterMapper extends BaseCreateUpdateMapper<DataCenter, DataCen
private final EmissionScopeService emissionScopeService;
private final ConsuptionUnitService consuptionUnitService;
private final ActivitySubUnitService activitySubUnitService;
private final CityService cityService;
@Autowired
public DataCenterMapper(AreaService areaService, SectorService sectorService,
SubSectorService subSectorService, EmissionSourceService emissionSourceService,
EmissionScopeService emissionScopeService, ConsuptionUnitService consuptionUnitService,
ActivitySubUnitService activitySubUnitService) {
ActivitySubUnitService activitySubUnitService, CityService cityService) {
this.areaService = areaService;
this.sectorService = sectorService;
this.subSectorService = subSectorService;
@@ -37,53 +44,80 @@ public class DataCenterMapper extends BaseCreateUpdateMapper<DataCenter, DataCen
this.emissionScopeService = emissionScopeService;
this.consuptionUnitService = consuptionUnitService;
this.activitySubUnitService = activitySubUnitService;
this.cityService = cityService;
}
@Override
public DataCenter toEntity(DataCenterCreateInput input) {
DataCenter entity = new DataCenter();
// Basic fields
entity.setDataCenter(input.getDataCenter());
entity.setExternalId(input.getExternalId());
entity.setNumber(input.getNumber());
entity.setConsuptionAmount(input.getConsuptionAmount());
// Convert ID references to entities
if (input.getAreaId() != null) {
entity.setArea(areaService.findById(input.getAreaId()).orElse(null));
}
if (input.getCityId() != null) {
entity.setCity(cityService.findById(input.getCityId()).orElse(null));
}
if (input.getSectorId() != null) {
entity.setSector(sectorService.findById(input.getSectorId()).orElse(null));
}
if (input.getSubSectorId() != null) {
entity.setSubSector(subSectorService.findById(input.getSubSectorId()).orElse(null));
}
if (input.getEmissionSourceId() != null) {
entity.setEmissionSource(emissionSourceService.findById(input.getEmissionSourceId()).orElse(null));
}
if (input.getEmissionScopeId() != null) {
entity.setEmissionScope(emissionScopeService.findById(input.getEmissionScopeId()).orElse(null));
}
if (input.getConsuptionUnitId() != null) {
entity.setConsuptionUnit(consuptionUnitService.findById(input.getConsuptionUnitId()).orElse(null));
}
if (input.getActivitySubUnitId() != null) {
entity.setActivitySubUnit(activitySubUnitService.findById(input.getActivitySubUnitId()).orElse(null));
}
// New attributes
entity.setAyposURL(input.getAyposURL());
entity.setAddress(input.getAddress());
entity.setLatitude(input.getLatitude());
entity.setLongitude(input.getLongitude());
// Handle multiple emission sources if provided
if (input.getDataCenterEmissionSources() != null && !input.getDataCenterEmissionSources().isEmpty()) {
List<DataCenterEmissionSource> dataCenterEmissionSources = new ArrayList<>();
for (DataCenterEmissionSourceInput emissionSourceInput : input.getDataCenterEmissionSources()) {
DataCenterEmissionSource dcEmissionSource = new DataCenterEmissionSource();
dcEmissionSource.setDataCenter(entity);
// Set EmissionSource
if (emissionSourceInput.getEmissionSourceId() != null) {
dcEmissionSource.setEmissionSource(emissionSourceService
.findById(UUID.fromString(emissionSourceInput.getEmissionSourceId())).orElse(null));
}
// Set ConsuptionUnit
if (emissionSourceInput.getConsuptionUnitId() != null) {
dcEmissionSource.setConsuptionUnit(consuptionUnitService
.findById(UUID.fromString(emissionSourceInput.getConsuptionUnitId())).orElse(null));
}
// Set optional fields
dcEmissionSource.setIsDefault(
emissionSourceInput.getIsDefault() != null ? emissionSourceInput.getIsDefault() : false);
dcEmissionSource.setPercentage(emissionSourceInput.getPercentage());
dataCenterEmissionSources.add(dcEmissionSource);
}
entity.setDataCenterEmissionSources(dataCenterEmissionSources);
}
return entity;
}
@@ -93,65 +127,89 @@ public class DataCenterMapper extends BaseCreateUpdateMapper<DataCenter, DataCen
if (input.getDataCenter() != null) {
entity.setDataCenter(input.getDataCenter());
}
if (input.getExternalId() != null) {
entity.setExternalId(input.getExternalId());
}
if (input.getNumber() != null) {
entity.setNumber(input.getNumber());
}
if (input.getConsuptionAmount() != null) {
entity.setConsuptionAmount(input.getConsuptionAmount());
}
// Update relationships only if provided
if (input.getAreaId() != null) {
entity.setArea(areaService.findById(input.getAreaId()).orElse(null));
}
if (input.getCityId() != null) {
entity.setCity(cityService.findById(input.getCityId()).orElse(null));
}
if (input.getSectorId() != null) {
entity.setSector(sectorService.findById(input.getSectorId()).orElse(null));
}
if (input.getSubSectorId() != null) {
entity.setSubSector(subSectorService.findById(input.getSubSectorId()).orElse(null));
}
if (input.getEmissionSourceId() != null) {
entity.setEmissionSource(emissionSourceService.findById(input.getEmissionSourceId()).orElse(null));
}
if (input.getEmissionScopeId() != null) {
entity.setEmissionScope(emissionScopeService.findById(input.getEmissionScopeId()).orElse(null));
}
if (input.getConsuptionUnitId() != null) {
entity.setConsuptionUnit(consuptionUnitService.findById(input.getConsuptionUnitId()).orElse(null));
}
if (input.getActivitySubUnitId() != null) {
entity.setActivitySubUnit(activitySubUnitService.findById(input.getActivitySubUnitId()).orElse(null));
}
// Handle multiple emission sources update if provided
if (input.getDataCenterEmissionSources() != null) {
// Clear existing emission sources from the managed collection
entity.getDataCenterEmissionSources().clear();
// Add new emission sources to the same managed collection
for (DataCenterEmissionSourceInput emissionSourceInput : input.getDataCenterEmissionSources()) {
DataCenterEmissionSource dcEmissionSource = new DataCenterEmissionSource();
dcEmissionSource.setDataCenter(entity);
if (emissionSourceInput.getEmissionSourceId() != null) {
dcEmissionSource.setEmissionSource(emissionSourceService
.findById(UUID.fromString(emissionSourceInput.getEmissionSourceId())).orElse(null));
}
if (emissionSourceInput.getConsuptionUnitId() != null) {
dcEmissionSource.setConsuptionUnit(consuptionUnitService
.findById(UUID.fromString(emissionSourceInput.getConsuptionUnitId())).orElse(null));
}
dcEmissionSource.setIsDefault(
emissionSourceInput.getIsDefault() != null ? emissionSourceInput.getIsDefault() : false);
dcEmissionSource.setPercentage(emissionSourceInput.getPercentage());
// Add to the existing managed collection instead of creating a new one
entity.getDataCenterEmissionSources().add(dcEmissionSource);
}
}
// New attributes (partial update - only if provided)
if (input.getAyposURL() != null) {
entity.setAyposURL(input.getAyposURL());
}
if (input.getAddress() != null) {
entity.setAddress(input.getAddress());
}
if (input.getLatitude() != null) {
entity.setLatitude(input.getLatitude());
}
if (input.getLongitude() != null) {
entity.setLongitude(input.getLongitude());
}
return entity;
}
}

View File

@@ -11,15 +11,16 @@ import javax.transaction.Transactional;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import com.sgs.graphql.auth.service.AuthorizationService;
import com.sgs.graphql.dataCenter.domain.DataCenter;
import com.sgs.graphql.dataCenter.domain.PhysicalMachine;
import com.sgs.graphql.dataCenter.query.pagination.DataCenterPageable;
import com.sgs.graphql.dataCenter.repo.DataCenterRepo;
import com.sgs.graphql.dataCenter.repo.criteria.DataCenterCriteria;
import com.sgs.graphql.dataCenter.service.DataCenterService;
import com.sgs.graphql.systemHistory.mutation.SystemLogger;
import com.sgs.graphql.dataCenter.service.PhysicalMachineService;
import com.sgs.graphql.permission.domain.PermissionName;
import com.sgs.lib.dao.query.pagination.Pagination;
import com.sgs.lib.dao.query.sort.SortBy;
@@ -28,42 +29,46 @@ import graphql.kickstart.tools.GraphQLQueryResolver;
@Component
public class DataCenterQueryResolver implements GraphQLQueryResolver {
private final DataCenterService DataCenterService;
private final DataCenterRepo dataCenterRepo;
private final AuthorizationService authorizationService;
private final SystemLogger systemLogger;
private final DataCenterService dataCenterService;
private final PhysicalMachineService physicalMachineService;
@Autowired
public DataCenterQueryResolver(AuthorizationService authorizationService, SystemLogger systemLogger, DataCenterService DataCenterService, DataCenterRepo dataCenterRepo) {
this.DataCenterService = DataCenterService;
this.dataCenterRepo = dataCenterRepo;
this.authorizationService = authorizationService;
this.systemLogger = systemLogger;
public DataCenterQueryResolver(DataCenterService dataCenterService, PhysicalMachineService physicalMachineService) {
this.dataCenterService = dataCenterService;
this.physicalMachineService = physicalMachineService;
}
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_READ + "')")
public DataCenter dataCenter(UUID id) {
return DataCenterService.findById(id).orElse(null);
return dataCenterService.findById(id).orElse(null);
}
@Transactional
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_READ + "')")
public List<DataCenter> dataCenters(DataCenterCriteria criteria, List<SortBy> sortBy) {
List<DataCenter> dataCenters = DataCenterService.filterWithSort(ObjectUtils.defaultIfNull(criteria, new DataCenterCriteria()),
return dataCenterService.filterWithSort(ObjectUtils.defaultIfNull(criteria, new DataCenterCriteria()),
Sort.by(ObjectUtils.defaultIfNull(sortBy, new ArrayList<SortBy>())
.stream()
.map(SortBy::toOrder)
.collect(Collectors.toList())));
return dataCenters;
}
public DataCenterPageable paginateDataCenters(Pagination pagination, DataCenterCriteria criteria, List<SortBy> sortBy) {
return new DataCenterPageable(DataCenterService.filterWithPaginate(ObjectUtils.defaultIfNull(criteria, new DataCenterCriteria()),
Pagination.toPageRequest(pagination, sortBy)));
@PreAuthorize("hasAuthority('" + PermissionName.PAGINATE_DATACENTERS_GET + "')")
public DataCenterPageable paginateDataCenters(Pagination pagination, DataCenterCriteria criteria,
List<SortBy> sortBy) {
return new DataCenterPageable(
dataCenterService.filterWithPaginate(ObjectUtils.defaultIfNull(criteria, new DataCenterCriteria()),
Pagination.toPageRequest(pagination, sortBy)));
}
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_READ + "')")
public Optional<DataCenter> getByNumber(Integer number) {
return dataCenterService.findByNumber(number);
}
public Optional<DataCenter> getByNumber(Integer id) {
return dataCenterRepo.findByNumber(id).stream().findFirst();
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_READ + "')")
public List<PhysicalMachine> physicalMachines(UUID datacenterId) {
return physicalMachineService.findByDatacenterId(datacenterId);
}
}

View File

@@ -0,0 +1,25 @@
package com.sgs.graphql.dataCenter.repo;
import com.sgs.graphql.dataCenter.domain.DataCenter;
import com.sgs.graphql.dataCenter.domain.DataCenterEmissionSource;
import com.sgs.lib.dao.repo.BaseRepo;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface DataCenterEmissionSourceRepo extends BaseRepo<DataCenterEmissionSource> {
List<DataCenterEmissionSource> findByDataCenter(DataCenter dataCenter);
Optional<DataCenterEmissionSource> findByDataCenterAndIsDefaultTrue(DataCenter dataCenter);
@Query("SELECT dces FROM DataCenterEmissionSource dces WHERE dces.dataCenter.id = :dataCenterId")
List<DataCenterEmissionSource> findByDataCenterId(@Param("dataCenterId") String dataCenterId);
void deleteByDataCenter(DataCenter dataCenter);
}

View File

@@ -0,0 +1,22 @@
package com.sgs.graphql.dataCenter.repo;
import com.sgs.graphql.dataCenter.domain.PhysicalMachine;
import com.sgs.lib.dao.repo.BaseRepo;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.UUID;
@Repository
public interface PhysicalMachineRepo extends BaseRepo<PhysicalMachine> {
/**
* Find all physical machines by datacenter ID
* @param datacenterId Datacenter ID
* @return List of physical machines
*/
@Query("SELECT pm FROM PhysicalMachine pm WHERE pm.dataCenter.id = :datacenterId")
List<PhysicalMachine> findByDatacenterId(@Param("datacenterId") UUID datacenterId);
}

View File

@@ -0,0 +1,6 @@
package com.sgs.graphql.dataCenter.repo.criteria;
import com.sgs.lib.dao.repo.criteria.BaseCriteria;
public class DataCenterEmissionSourceCriteria extends BaseCriteria {
}

View File

@@ -0,0 +1,6 @@
package com.sgs.graphql.dataCenter.repo.criteria;
import com.sgs.lib.dao.repo.criteria.BaseCriteria;
public class PhysicalMachineCriteria extends BaseCriteria {
}

View File

@@ -0,0 +1,6 @@
package com.sgs.graphql.dataCenter.repo.criteria;
import com.sgs.lib.dao.repo.criteria.BaseCriteria;
public class VMCriteria extends BaseCriteria {
}

View File

@@ -0,0 +1,17 @@
package com.sgs.graphql.dataCenter.repo.criteria.spec;
import com.sgs.graphql.dataCenter.domain.DataCenterEmissionSource;
import com.sgs.graphql.dataCenter.repo.criteria.DataCenterEmissionSourceCriteria;
import com.sgs.lib.dao.repo.criteria.spec.BaseCriteriaSpec;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
@Component
public class DataCenterEmissionSourceCriteriaSpec
extends BaseCriteriaSpec<DataCenterEmissionSource, DataCenterEmissionSourceCriteria> {
@Override
public Specification<DataCenterEmissionSource> createForAll(DataCenterEmissionSourceCriteria criteria) {
return null;
}
}

View File

@@ -0,0 +1,16 @@
package com.sgs.graphql.dataCenter.repo.criteria.spec;
import com.sgs.graphql.dataCenter.domain.PhysicalMachine;
import com.sgs.graphql.dataCenter.repo.criteria.PhysicalMachineCriteria;
import com.sgs.lib.dao.repo.criteria.spec.BaseCriteriaSpec;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
@Component
public class PhysicalMachineCriteriaSpec extends BaseCriteriaSpec<PhysicalMachine, PhysicalMachineCriteria> {
@Override
public Specification<PhysicalMachine> createForAll(PhysicalMachineCriteria criteria) {
return null;
}
}

View File

@@ -0,0 +1,16 @@
package com.sgs.graphql.dataCenter.repo.criteria.spec;
import com.sgs.graphql.dataCenter.domain.VM;
import com.sgs.graphql.dataCenter.repo.criteria.VMCriteria;
import com.sgs.lib.dao.repo.criteria.spec.BaseCriteriaSpec;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
@Component
public class VMCriteriaSpec extends BaseCriteriaSpec<VM, VMCriteria> {
@Override
public Specification<VM> createForAll(VMCriteria criteria) {
return null;
}
}

View File

@@ -0,0 +1,40 @@
package com.sgs.graphql.dataCenter.service;
import com.sgs.graphql.dataCenter.domain.DataCenter;
import com.sgs.graphql.dataCenter.domain.DataCenterEmissionSource;
import com.sgs.graphql.dataCenter.repo.DataCenterEmissionSourceRepo;
import com.sgs.graphql.dataCenter.repo.criteria.DataCenterEmissionSourceCriteria;
import com.sgs.graphql.dataCenter.repo.criteria.spec.DataCenterEmissionSourceCriteriaSpec;
import com.sgs.lib.dao.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class DataCenterEmissionSourceService extends
BaseService<DataCenterEmissionSource, DataCenterEmissionSourceRepo, DataCenterEmissionSourceCriteria, DataCenterEmissionSourceCriteriaSpec> {
@Autowired
public DataCenterEmissionSourceService(DataCenterEmissionSourceRepo repository,
DataCenterEmissionSourceCriteriaSpec criteriaSpec) {
super(repository, criteriaSpec);
}
public List<DataCenterEmissionSource> findByDataCenter(DataCenter dataCenter) {
return getRepository().findByDataCenter(dataCenter);
}
public Optional<DataCenterEmissionSource> findByDataCenterAndIsDefaultTrue(DataCenter dataCenter) {
return getRepository().findByDataCenterAndIsDefaultTrue(dataCenter);
}
public List<DataCenterEmissionSource> findByDataCenterId(String dataCenterId) {
return getRepository().findByDataCenterId(dataCenterId);
}
public void deleteByDataCenter(DataCenter dataCenter) {
getRepository().deleteByDataCenter(dataCenter);
}
}

View File

@@ -8,15 +8,26 @@ import com.sgs.lib.dao.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
public class DataCenterService extends BaseService<DataCenter, DataCenterRepo, DataCenterCriteria, DataCenterCriteriaSpec> {
public class DataCenterService
extends BaseService<DataCenter, DataCenterRepo, DataCenterCriteria, DataCenterCriteriaSpec> {
@Autowired
public DataCenterService(DataCenterRepo repository, DataCenterCriteriaSpec criteriaSpec) {
super(repository, criteriaSpec);
}
public boolean existsByExternalId(Integer externalId) {
return getRepository().existsByExternalId(externalId);
}
public Optional<DataCenter> findByNumber(Integer number) {
return getRepository().findByNumber(number);
}
public Integer findMaxNumber() {
return getRepository().findMaxNumber();
}
}

View File

@@ -0,0 +1,26 @@
package com.sgs.graphql.dataCenter.service;
import com.sgs.graphql.dataCenter.domain.PhysicalMachine;
import com.sgs.graphql.dataCenter.repo.PhysicalMachineRepo;
import com.sgs.graphql.dataCenter.repo.criteria.PhysicalMachineCriteria;
import com.sgs.graphql.dataCenter.repo.criteria.spec.PhysicalMachineCriteriaSpec;
import com.sgs.lib.dao.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
@Service
public class PhysicalMachineService extends
BaseService<PhysicalMachine, PhysicalMachineRepo, PhysicalMachineCriteria, PhysicalMachineCriteriaSpec> {
@Autowired
public PhysicalMachineService(PhysicalMachineRepo repository, PhysicalMachineCriteriaSpec criteriaSpec) {
super(repository, criteriaSpec);
}
public List<PhysicalMachine> findByDatacenterId(UUID datacenterId) {
return getRepository().findByDatacenterId(datacenterId);
}
}

View File

@@ -0,0 +1,29 @@
package com.sgs.graphql.dataCenter.service;
import com.sgs.graphql.dataCenter.domain.VM;
import com.sgs.graphql.dataCenter.repo.VMRepo;
import com.sgs.graphql.dataCenter.repo.criteria.VMCriteria;
import com.sgs.graphql.dataCenter.repo.criteria.spec.VMCriteriaSpec;
import com.sgs.lib.dao.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class VMService extends BaseService<VM, VMRepo, VMCriteria, VMCriteriaSpec> {
@Autowired
public VMService(VMRepo repository, VMCriteriaSpec criteriaSpec) {
super(repository, criteriaSpec);
}
public List<VM> findAllByVmName(String vmName) {
return getRepository().findAllByVmName(vmName);
}
public Optional<VM> findFirstByVmNameOrderByIdDesc(String vmName) {
return getRepository().findFirstByVmNameOrderByIdDesc(vmName);
}
}

View File

@@ -15,7 +15,7 @@ public class VMEmissionSummary {
private Double totalEmission; // Individual record's total emission
private LocalDateTime createdDate; // When this specific record was created
private String physicalMachine;
private String project;
private String cloudSystem; // From physical machine
private String dataCenter;
// Individual emission values for this specific record
@@ -31,7 +31,7 @@ public class VMEmissionSummary {
public VMEmissionSummary(UUID vmId, String vmName, Double vmPower, String vmStatus,
Double totalEmission, LocalDateTime createdDate,
String physicalMachine, String project, String dataCenter,
String physicalMachine, String cloudSystem, String dataCenter,
Double co2, Double ch4, Double n2o) {
this.vmId = vmId;
this.vmName = vmName;
@@ -40,7 +40,7 @@ public class VMEmissionSummary {
this.totalEmission = totalEmission;
this.createdDate = createdDate;
this.physicalMachine = physicalMachine;
this.project = project;
this.cloudSystem = cloudSystem;
this.dataCenter = dataCenter;
this.co2 = co2;
this.ch4 = ch4;
@@ -70,8 +70,8 @@ public class VMEmissionSummary {
public String getPhysicalMachine() { return physicalMachine; }
public void setPhysicalMachine(String physicalMachine) { this.physicalMachine = physicalMachine; }
public String getProject() { return project; }
public void setProject(String project) { this.project = project; }
public String getCloudSystem() { return cloudSystem; }
public void setCloudSystem(String cloudSystem) { this.cloudSystem = cloudSystem; }
public String getDataCenter() { return dataCenter; }
public void setDataCenter(String dataCenter) { this.dataCenter = dataCenter; }

View File

@@ -51,9 +51,11 @@ public class MainDataTableQueryResolver implements GraphQLQueryResolver {
/**
* GraphQL query to get VM emission summaries with hierarchy information
* @param datacenterId Optional datacenter ID to filter VMs by datacenter
* @param projectId Optional project ID to filter VMs by project
* @return List of VM emission summaries including datacenter, project, aggregate, and physical machine info
*/
public List<VMEmissionSummary> vmEmissionSummary() {
return mainDataTableService.getVMEmissionSummaries();
public List<VMEmissionSummary> vmEmissionSummary(UUID datacenterId) {
return mainDataTableService.getVMEmissionSummaries(datacenterId);
}
}

View File

@@ -9,6 +9,7 @@ import com.sgs.lib.dao.service.BaseService;
import com.sgs.graphql.mainDataTable.dto.VMEmissionSummary;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -21,7 +22,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MainDataTableService extends BaseService<MainDataTable, MainDataTableRepo, MainDataTableCriteria, MainDataTableCriteriaSpec> {
public class MainDataTableService
extends BaseService<MainDataTable, MainDataTableRepo, MainDataTableCriteria, MainDataTableCriteriaSpec> {
@PersistenceContext
private EntityManager entityManager;
@@ -32,68 +34,86 @@ public class MainDataTableService extends BaseService<MainDataTable, MainDataTab
}
public List<VMEmissionSummary> getVMEmissionSummaries() {
return getVMEmissionSummaries(null);
}
public List<VMEmissionSummary> getVMEmissionSummaries(UUID datacenterId) {
List<String> whereConditions = new ArrayList<>();
if (datacenterId != null) {
whereConditions.add("dc.id = decode(replace(:datacenterId, '-', ''), 'hex')");
}
String whereClause = whereConditions.isEmpty() ? "" :
"WHERE " + String.join(" AND ", whereConditions) + " ";
String sql = """
SELECT
CAST(v.id AS VARCHAR) as vm_id,
v.name as vm_name,
v.vm_name as vm_name,
v.power as vm_power,
v.status as vm_status,
v.state as vm_status,
mdt.total_emission,
mdt.created_date,
pm.name as physical_machine_name,
p.name as project_name,
pm.cloud_system as cloud_system,
dc.data_center_name as datacenter_name,
mdt.co2,
mdt.ch4,
mdt.n2o
FROM main_data_table mdt
JOIN vm v ON mdt.vm_id = v.id
LEFT JOIN vms vms_active ON v.active_vms_id = vms_active.id
LEFT JOIN vms vms_inactive ON v.inactive_vms_id = vms_inactive.id
LEFT JOIN physical_machine pm ON (pm.vms_id = vms_active.id OR pm.vms_id = vms_inactive.id)
LEFT JOIN project p ON pm.project_id = p.id
LEFT JOIN data_center dc ON p.data_center_id = dc.id
ORDER BY mdt.created_date DESC, v.name
LEFT JOIN physical_machine pm ON v.physical_machine_id = pm.id
LEFT JOIN data_center dc ON pm.data_center_id = dc.id
""" + whereClause + """
ORDER BY mdt.created_date DESC, v.vm_name
""";
Query query = entityManager.createNativeQuery(sql);
// Add parameters if provided
if (datacenterId != null) {
query.setParameter("datacenterId", datacenterId.toString());
}
@SuppressWarnings("unchecked")
List<Object[]> results = query.getResultList();
return results.stream().map(row -> {
VMEmissionSummary summary = new VMEmissionSummary();
// Handle UUID conversion from hex format
String uuidStr = (String) row[0];
UUID vmId = convertHexToUUID(uuidStr);
summary.setVmId(vmId);
summary.setVmName((String) row[1]);
summary.setVmPower((Double) row[2]);
summary.setVmStatus((String) row[3]);
summary.setTotalEmission((Double) row[4]);
// Convert Timestamp to LocalDateTime for created_date
Timestamp timestamp = (Timestamp) row[5];
if (timestamp != null) {
summary.setCreatedDate(timestamp.toLocalDateTime());
}
summary.setPhysicalMachine((String) row[6]);
summary.setProject((String) row[7]);
summary.setCloudSystem((String) row[7]);
summary.setDataCenter((String) row[8]);
// Individual emission values
summary.setCo2((Double) row[9]);
summary.setCh4((Double) row[10]);
summary.setN2o((Double) row[11]);
return summary;
}).collect(Collectors.toList());
}
/**
* Converts PostgreSQL hex format UUID to proper UUID format
*
* @param hexUuid UUID in hex format (e.g., \x6205c18b8d1e4f0fa5154212fb44050b)
* @return UUID object
*/
@@ -103,11 +123,11 @@ public class MainDataTableService extends BaseService<MainDataTable, MainDataTab
String hex = hexUuid.substring(2);
// Insert hyphens to make it a proper UUID format
// UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
String formatted = hex.substring(0, 8) + "-" +
hex.substring(8, 12) + "-" +
hex.substring(12, 16) + "-" +
hex.substring(16, 20) + "-" +
hex.substring(20);
String formatted = hex.substring(0, 8) + "-" +
hex.substring(8, 12) + "-" +
hex.substring(12, 16) + "-" +
hex.substring(16, 20) + "-" +
hex.substring(20);
return UUID.fromString(formatted);
} else {
// If it's already in proper format, parse directly

View File

@@ -74,4 +74,5 @@ public class PermissionDescription {
public static final String DATA_CENTER_DELETE = "Veri Merkezi Silme";
public static final String DATA_CENTER_UPDATE = "Veri Merkezi Güncelleme";
public static final String DATA_CENTER_READ = "Veri Merkezi Görüntüleme";
public static final String PAGINATE_DATACENTERS_GET = "Veri Merkezleri Listesi Görüntüleme";
}

View File

@@ -84,5 +84,6 @@ public class PermissionName {
public static final String DATA_CENTER_DELETE = "data_center_delete";
public static final String DATA_CENTER_UPDATE = "data_center_update";
public static final String DATA_CENTER_READ = "data_center_read";
public static final String PAGINATE_DATACENTERS_GET = "paginate_datacenters_get";
}

View File

@@ -9,6 +9,8 @@ import com.sgs.lib.dao.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
public class PermissionService extends BaseService<Permission, PermissionRepo, PermissionCriteria, PermissionCriteriaSpec> {
@@ -16,4 +18,8 @@ public class PermissionService extends BaseService<Permission, PermissionRepo, P
public PermissionService(PermissionRepo repository, PermissionCriteriaSpec criteriaSpec) {
super(repository, criteriaSpec);
}
public Optional<Permission> findByTag(String tag) {
return getRepository().findByTag(tag);
}
}

View File

@@ -74,19 +74,16 @@ public class MessageListener {
System.out.println(" External ID: " + dto.getId());
System.out.println(" Number: " + dto.getNumber());
System.out.println(" Consumption Amount: " + dto.getConsuptionAmount());
System.out.println(" Projects Count: " + (dto.getProjects() != null ? dto.getProjects().size() : 0));
System.out.println(" Physical Machines Count: " + (dto.getPhysicalMachine() != null ? dto.getPhysicalMachine().size() : 0));
// Log MainOptimizationSpace info for each project
if (dto.getProjects() != null) {
for (Map.Entry<String, ProjectDto> projectEntry : dto.getProjects().entrySet()) {
String projectId = projectEntry.getKey();
ProjectDto project = projectEntry.getValue();
if (project.getMainOptimizationSpace() != null) {
MainOptimizationSpaceDto mainOpt = project.getMainOptimizationSpace();
System.out.println(" Project " + projectId + ":");
System.out.println(" PMs: " + (mainOpt.getPms() != null ? mainOpt.getPms().size() : 0));
System.out.println(" VMs: " + (mainOpt.getVms() != null ? mainOpt.getVms().size() : 0));
}
// Log Physical Machine info
if (dto.getPhysicalMachine() != null) {
for (Map.Entry<String, PhysicalMachineDto> pmEntry : dto.getPhysicalMachine().entrySet()) {
String pmIp = pmEntry.getKey();
PhysicalMachineDto pm = pmEntry.getValue();
System.out.println(" Physical Machine " + pm.getName() + " (IP: " + pmIp + "):");
System.out.println(" Power: " + pm.getPower());
System.out.println(" VMs: " + (pm.getVms() != null ? pm.getVms().size() : 0));
}
}
@@ -103,18 +100,18 @@ public class MessageListener {
// System.out.println(entity.toString());
System.out.println("✅ Raw JSON message:\n" + message);
System.out.println("✅ DTO parsed:\n" + objectMapper.writeValueAsString(dto));
//System.out.println("✅ DTO parsed:\n" + objectMapper.writeValueAsString(dto));
//System.out.println("✅ Entity:\n" + objectMapper.writeValueAsString(entity));
System.out.println("🚨 DataCenter name: " + dataCenter.getDataCenter());
System.out.println("🚨 External ID: " + dataCenter.getExternalId());
System.out.println("🚨 Projects count: " + (dataCenter.getProjects() != null ? dataCenter.getProjects().size() : 0));
if (dataCenter.getProjects() != null && !dataCenter.getProjects().isEmpty()) {
Project firstProject = dataCenter.getProjects().get(0);
System.out.println("🚨 PMs in first project: " + firstProject.getPhysicalMachines().size());
System.out.println("🚨 Physical Machines count: " + (dataCenter.getPhysicalMachines() != null ? dataCenter.getPhysicalMachines().size() : 0));
if (dataCenter.getPhysicalMachines() != null && !dataCenter.getPhysicalMachines().isEmpty()) {
PhysicalMachine firstPM = dataCenter.getPhysicalMachines().get(0);
System.out.println("🚨 VMs in first PM: " + firstPM.getVms().size());
// Show VM assignment summary
int totalVMs = 0;
for (PhysicalMachine pm : firstProject.getPhysicalMachines()) {
for (PhysicalMachine pm : dataCenter.getPhysicalMachines()) {
int vmCount = pm.getVms() != null ? pm.getVms().size() : 0;
totalVMs += vmCount;
System.out.println(" PM " + pm.getName() + " (IP: " + pm.getIp() + "): " + vmCount + " VMs");
@@ -157,6 +154,7 @@ public class MessageListener {
entity.setHost(dto.getHost());
entity.setFlavorName(dto.getFlavorName());
entity.setTag(dto.getTag());
entity.setProject(dto.getProject());
// Set calcOn - you may want to derive this from state or other logic
entity.setCalcOn(dto.isCalcOn());
@@ -168,7 +166,7 @@ public class MessageListener {
entity.setEmissionSource(dto.getEmissionSource());
// Debug logging
System.out.println("🔍 VM Entity Created: " + dto.getVmName() + " - state = " + dto.getState() + " - calcOn = " + dto.isCalcOn());
System.out.println("🔍 VM Entity Created: " + dto.getVmName() + " - state = " + dto.getState() + " - calcOn = " + dto.isCalcOn() + " - project = " + dto.getProject());
if (dto.getEmissionSource() != null && !dto.getEmissionSource().isEmpty()) {
System.out.println(" Emission Sources: " + dto.getEmissionSource());
}
@@ -184,6 +182,7 @@ public class MessageListener {
entity.setName(dto.getName());
entity.setIp(dto.getIp());
entity.setTag(dto.getTag());
entity.setCloudSystem(dto.getCloudSystem());
entity.setPower(dto.getPower());
// VMs are now processed separately from the new message format
@@ -207,112 +206,43 @@ public class MessageListener {
// ConsuptionUnit, and ActivitySubUnit are no longer received in the message
// These will need to be set via the DataCenter CRUD operations
// Convert Projects
if (dto.getProjects() != null) {
List<Project> projects = new ArrayList<>();
for (Map.Entry<String, ProjectDto> projectEntry : dto.getProjects().entrySet()) {
String projectId = projectEntry.getKey();
ProjectDto projectDto = projectEntry.getValue();
// Convert Physical Machines directly
if (dto.getPhysicalMachine() != null) {
List<PhysicalMachine> physicalMachines = new ArrayList<>();
for (Map.Entry<String, PhysicalMachineDto> pmEntry : dto.getPhysicalMachine().entrySet()) {
String pmIp = pmEntry.getKey();
PhysicalMachineDto pmDto = pmEntry.getValue();
// Set the project ID and a default name if not provided
projectDto.setId(projectId);
if (projectDto.getName() == null || projectDto.getName().isEmpty()) {
projectDto.setName("Project-" + projectId.substring(0, 8)); // Use first 8 chars of ID as name
PhysicalMachine pm = new PhysicalMachine();
pm.setName(pmDto.getName());
pm.setIp(pmIp); // Use the IP from the map key
pm.setTag(pmDto.getTag());
pm.setCloudSystem(pmDto.getCloudSystem());
pm.setPower(pmDto.getPower());
pm.setDataCenter(entity);
// Process VMs for this PM
if (pmDto.getVms() != null) {
List<VM> vms = new ArrayList<>();
for (Map.Entry<String, VMDto> vmEntry : pmDto.getVms().entrySet()) {
String vmIp = vmEntry.getKey();
VMDto vmDto = vmEntry.getValue();
VM vm = toVMEntity(vmDto);
vm.setIp(vmIp); // Use the IP from the map key
vm.setPhysicalMachine(pm);
vms.add(vm);
}
pm.setVms(vms);
}
Project project = toProjectEntity(projectDto);
project.setDataCenter(entity);
projects.add(project);
physicalMachines.add(pm);
}
entity.setProjects(projects);
}
return entity;
}
public Project toProjectEntity(ProjectDto dto){
if (dto == null)
return null;
Project entity = new Project();
entity.setName(dto.getName());
// Process MainOptimizationSpace instead of physical machines list
if (dto.getMainOptimizationSpace() != null) {
List<PhysicalMachine> physicalMachines = processMainOptimizationSpace(dto.getMainOptimizationSpace());
// Set project reference for each PM
physicalMachines.forEach(pm -> pm.setProject(entity));
entity.setPhysicalMachines(physicalMachines);
}
return entity;
}
/**
* Process MainOptimizationSpaceDto and assign VMs to their hosting PMs
*/
private List<PhysicalMachine> processMainOptimizationSpace(MainOptimizationSpaceDto mainOptSpace) {
List<PhysicalMachine> physicalMachines = new ArrayList<>();
if (mainOptSpace.getPms() == null || mainOptSpace.getVms() == null) {
System.out.println("⚠️ MainOptimizationSpace has null PMs or VMs");
return physicalMachines;
}
System.out.println("🔍 Processing MainOptimizationSpace with " +
mainOptSpace.getPms().size() + " PMs and " +
mainOptSpace.getVms().size() + " VMs");
// Convert PMs from DTO to Entity
for (Map.Entry<String, PhysicalMachineDto> pmEntry : mainOptSpace.getPms().entrySet()) {
String pmIp = pmEntry.getKey();
PhysicalMachineDto pmDto = pmEntry.getValue();
// Set the IP from the map key
pmDto.setIp(pmIp);
PhysicalMachine pm = toPhysicalMachineEntity(pmDto);
physicalMachines.add(pm);
System.out.println("✅ Created PM: " + pm.getName() + " (IP: " + pm.getIp() + ")");
}
// Assign VMs to their hosting PMs
for (Map.Entry<String, VMDto> vmEntry : mainOptSpace.getVms().entrySet()) {
String vmIp = vmEntry.getKey();
VMDto vmDto = vmEntry.getValue();
// Set the IP from the map key
vmDto.setIp(vmIp);
VM vm = toVMEntity(vmDto);
// Find the hosting PM by IP
String hostingPmIp = vmDto.getHostingPm();
PhysicalMachine hostingPm = physicalMachines.stream()
.filter(pm -> pm.getIp().equals(hostingPmIp))
.findFirst()
.orElse(null);
if (hostingPm != null) {
// Assign VM to PM
vm.setPhysicalMachine(hostingPm);
if (hostingPm.getVms() == null) {
hostingPm.setVms(new ArrayList<>());
}
hostingPm.getVms().add(vm);
System.out.println("✅ Assigned VM: " + vm.getVmName() + " (IP: " + vm.getIp() +
") to PM: " + hostingPm.getName() + " (IP: " + hostingPm.getIp() + ")");
} else {
System.err.println("❌ Could not find hosting PM with IP: " + hostingPmIp +
" for VM: " + vm.getVmName());
}
}
return physicalMachines;
}
@Transactional
public DataCenter createDataCenter(DataCenter newDc) {
@@ -335,123 +265,117 @@ public class MessageListener {
// Note: DataCenter name and emission-related fields are no longer updated from the message
// These are now managed via DataCenter CRUD operations
for (Project newProject : newDc.getProjects()) {
Optional<Project> existingProjOpt = dc.getProjects().stream()
.filter(p -> p.getName().equalsIgnoreCase(newProject.getName()))
.findFirst();
// Ensure datacenter has initialized physical machines list
if (dc.getPhysicalMachines() == null) {
dc.setPhysicalMachines(new ArrayList<>());
}
Project project;
if (existingProjOpt.isPresent()) {
project = existingProjOpt.get();
project.setName(newProject.getName());
System.out.println("✅ Updated existing project: " + project.getName());
} else {
project = newProject;
project.setDataCenter(dc);
dc.getProjects().add(project);
System.out.println("✅ Created new project: " + project.getName());
// Process Physical Machines directly from the message structure
for (PhysicalMachine newPm : newDc.getPhysicalMachines()) {
Optional<PhysicalMachine> existingPmOpt = dc.getPhysicalMachines().stream()
.filter(pm -> pm.getIp().equals(newPm.getIp())) // Match by IP instead of name
.findFirst();
PhysicalMachine pm;
if (existingPmOpt.isPresent()) {
// Update existing PM
pm = existingPmOpt.get();
pm.setName(newPm.getName());
pm.setIp(newPm.getIp());
pm.setTag(newPm.getTag());
pm.setCloudSystem(newPm.getCloudSystem());
pm.setPower(newPm.getPower());
System.out.println("✅ Updated existing PM: " + pm.getName() + " (IP: " + pm.getIp() + ") - CloudSystem: " + pm.getCloudSystem());
} else {
// Create new PM
pm = newPm;
pm.setDataCenter(dc);
dc.getPhysicalMachines().add(pm);
System.out.println("✅ Created new PM: " + pm.getName() + " (IP: " + pm.getIp() + ") - CloudSystem: " + pm.getCloudSystem());
}
// Process VMs that are already assigned to this PM
if (newPm.getVms() != null && !newPm.getVms().isEmpty()) {
System.out.println("🔍 Processing " + newPm.getVms().size() + " VMs for PM: " + newPm.getName());
// Ensure PM has VM list initialized
if (pm.getVms() == null) {
pm.setVms(new ArrayList<>());
}
// Ensure project has initialized physical machines list
if (project.getPhysicalMachines() == null) {
project.setPhysicalMachines(new ArrayList<>());
}
// Process Physical Machines (VMs are already assigned to PMs from MainOptimizationSpace)
for (PhysicalMachine newPm : newProject.getPhysicalMachines()) {
Optional<PhysicalMachine> existingPmOpt = project.getPhysicalMachines().stream()
.filter(pm -> pm.getIp().equals(newPm.getIp())) // Match by IP instead of name
.findFirst();
PhysicalMachine pm;
if (existingPmOpt.isPresent()) {
// Update existing PM
pm = existingPmOpt.get();
pm.setName(newPm.getName());
pm.setIp(newPm.getIp());
pm.setTag(newPm.getTag());
pm.setPower(newPm.getPower());
System.out.println("✅ Updated existing PM: " + pm.getName() + " (IP: " + pm.getIp() + ")");
} else {
// Create new PM
pm = newPm;
pm.setProject(project);
project.getPhysicalMachines().add(pm);
System.out.println("✅ Created new PM: " + pm.getName() + " (IP: " + pm.getIp() + ")");
// Clear existing VMs to replace with new ones
pm.getVms().clear();
// Process each VM that's already assigned to this PM
for (VM newVm : newPm.getVms()) {
if (newVm == null) continue;
// Find existing VM by vmName
Optional<VM> existingVmOpt = Optional.empty();
String vmLookupName = newVm.getVmName();
if (vmLookupName != null) {
existingVmOpt = vmRepo.findFirstByVmNameOrderByIdDesc(vmLookupName);
}
// Process VMs that are already assigned to this PM
if (newPm.getVms() != null && !newPm.getVms().isEmpty()) {
System.out.println("🔍 Processing " + newPm.getVms().size() + " VMs for PM: " + newPm.getName());
VM vm;
if (existingVmOpt.isPresent()) {
// Update existing VM
vm = existingVmOpt.get();
// Ensure PM has VM list initialized
if (pm.getVms() == null) {
pm.setVms(new ArrayList<>());
// IMPORTANT: Remove VM from its current Physical Machine first
if (vm.getPhysicalMachine() != null) {
PhysicalMachine currentPM = vm.getPhysicalMachine();
if (currentPM.getVms() != null) {
currentPM.getVms().remove(vm);
System.out.println("🔄 Removed VM " + vm.getVmName() + " from previous PM: " + currentPM.getName());
}
}
// Clear existing VMs to replace with new ones
pm.getVms().clear();
vm.setState(newVm.getState());
vm.setVmName(newVm.getVmName());
vm.setIp(newVm.getIp());
vm.setPower(newVm.getPower());
vm.setCalcOn(newVm.getCalcOn());
vm.setHostingPm(newVm.getHostingPm());
vm.setHost(newVm.getHost());
vm.setFlavorName(newVm.getFlavorName());
vm.setTag(newVm.getTag());
vm.setEmissionSource(newVm.getEmissionSource());
vm.setProject(newVm.getProject());
// Process each VM that's already assigned to this PM
for (VM newVm : newPm.getVms()) {
if (newVm == null) continue;
// Find existing VM by vmName
Optional<VM> existingVmOpt = Optional.empty();
String vmLookupName = newVm.getVmName();
if (vmLookupName != null) {
existingVmOpt = vmRepo.findFirstByVmNameOrderByIdDesc(vmLookupName);
}
VM vm;
if (existingVmOpt.isPresent()) {
// Update existing VM
vm = existingVmOpt.get();
vm.setState(newVm.getState());
vm.setVmName(newVm.getVmName());
vm.setIp(newVm.getIp());
vm.setPower(newVm.getPower());
vm.setCalcOn(newVm.getCalcOn());
vm.setHostingPm(newVm.getHostingPm());
vm.setHost(newVm.getHost());
vm.setFlavorName(newVm.getFlavorName());
vm.setTag(newVm.getTag());
vm.setEmissionSource(newVm.getEmissionSource());
System.out.println("✅ Updated existing VM: " + vm.getVmName() + " (IP: " + vm.getIp() + ") - calcOn = " + vm.getCalcOn());
} else {
// Use new VM
vm = newVm;
System.out.println("✅ Created new VM: " + vm.getVmName() + " (IP: " + vm.getIp() + ") - calcOn = " + vm.getCalcOn());
}
// Set physical machine relationship
vm.setPhysicalMachine(pm);
pm.getVms().add(vm);
System.out.println("✅ Updated existing VM: " + vm.getVmName() + " (IP: " + vm.getIp() + ") - calcOn = " + vm.getCalcOn());
} else {
// Use new VM
vm = newVm;
System.out.println("✅ Created new VM: " + vm.getVmName() + " (IP: " + vm.getIp() + ") - calcOn = " + vm.getCalcOn());
}
// Set physical machine relationship
vm.setPhysicalMachine(pm);
pm.getVms().add(vm);
// Update config
if (newVm.getConfig() != null) {
if (vm.getConfig() == null) {
vm.setConfig(newVm.getConfig());
vm.getConfig().setVm(vm);
} else {
vm.getConfig().setCpu(newVm.getConfig().getCpu());
vm.getConfig().setRam(newVm.getConfig().getRam());
vm.getConfig().setDisk(newVm.getConfig().getDisk());
}
}
// Update config
if (newVm.getConfig() != null) {
if (vm.getConfig() == null) {
vm.setConfig(newVm.getConfig());
vm.getConfig().setVm(vm);
} else {
vm.getConfig().setCpu(newVm.getConfig().getCpu());
vm.getConfig().setRam(newVm.getConfig().getRam());
vm.getConfig().setDisk(newVm.getConfig().getDisk());
}
}
}
}
}
System.out.println("Before Save: DataCenter=" + dc.getDataCenter());
System.out.println("External ID=" + dc.getExternalId());
System.out.println("Number=" + dc.getNumber());
System.out.println("Projects=" + (dc.getProjects() != null ? dc.getProjects().size() : 0));
System.out.println("Physical Machines=" + (dc.getPhysicalMachines() != null ? dc.getPhysicalMachines().size() : 0));
DataCenter saved = dataCenterService.save(dc);
System.out.println("✅ Saved: ID=" + saved.getId());
@@ -525,41 +449,29 @@ public class MessageListener {
int failedCalculations = 0;
int totalEmissionSources = 0;
for (Project project : dataCenter.getProjects()) {
for (PhysicalMachine pm : project.getPhysicalMachines()) {
if (pm.getVms() != null) {
// Calculate for all VMs (only those with calcOn = true)
for (VM vm : pm.getVms()) {
totalVMs++;
if (vm.getCalcOn() != null && vm.getCalcOn()) {
eligibleVMs++;
if (vm.getPower() != null && vm.getPower() > 0) {
System.out.println("✅ Processing VM " + vm.getVmName() + " (calcOn = true)");
processedVMs++;
// Check if VM has emission sources
Map<String, Integer> emissionSources = vm.getEmissionSource();
if (emissionSources != null && !emissionSources.isEmpty()) {
// Create separate emission record for each emission source
System.out.println("🔍 VM has " + emissionSources.size() + " emission sources");
totalEmissionSources += emissionSources.size();
for (Map.Entry<String, Integer> sourceEntry : emissionSources.entrySet()) {
String sourceName = sourceEntry.getKey();
Integer percentage = sourceEntry.getValue();
System.out.println(" - " + sourceName + ": " + percentage + "%");
boolean success = createVMEmissionRecordForSource(dataCenter, vm, project, pm, sourceName, percentage);
if (success) {
successfulCalculations++;
} else {
failedCalculations++;
}
}
} else {
// Fallback to default emission source if VM has no emission sources
System.out.println("⚠️ VM has no emission sources, using default");
totalEmissionSources++;
boolean success = createVMEmissionRecord(dataCenter, vm, project, pm);
for (PhysicalMachine pm : dataCenter.getPhysicalMachines()) {
if (pm.getVms() != null) {
// Calculate for all VMs (only those with calcOn = true)
for (VM vm : pm.getVms()) {
totalVMs++;
if (vm.getCalcOn() != null && vm.getCalcOn()) {
eligibleVMs++;
if (vm.getPower() != null && vm.getPower() > 0) {
System.out.println("✅ Processing VM " + vm.getVmName() + " (calcOn = true)");
processedVMs++;
// Check if VM has emission sources
Map<String, Integer> emissionSources = vm.getEmissionSource();
if (emissionSources != null && !emissionSources.isEmpty()) {
// Create separate emission record for each emission source
System.out.println("🔍 VM has " + emissionSources.size() + " emission sources");
totalEmissionSources += emissionSources.size();
for (Map.Entry<String, Integer> sourceEntry : emissionSources.entrySet()) {
String sourceName = sourceEntry.getKey();
Integer percentage = sourceEntry.getValue();
System.out.println(" - " + sourceName + ": " + percentage + "%");
boolean success = createVMEmissionRecordForSource(dataCenter, vm, pm, sourceName, percentage);
if (success) {
successfulCalculations++;
} else {
@@ -567,16 +479,26 @@ public class MessageListener {
}
}
} else {
System.out.println("⚠️ Skipping VM " + vm.getVmName() + " (calcOn = true) - no power consumption data");
// Fallback to default emission source if VM has no emission sources
System.out.println("⚠️ VM has no emission sources, using default");
totalEmissionSources++;
boolean success = createVMEmissionRecord(dataCenter, vm, pm);
if (success) {
successfulCalculations++;
} else {
failedCalculations++;
}
}
} else {
System.out.println(" Skipping VM " + vm.getVmName() + " - calcOn = " + vm.getCalcOn());
System.out.println(" Skipping VM " + vm.getVmName() + " (calcOn = true) - no power consumption data");
}
} else {
System.out.println("⏭️ Skipping VM " + vm.getVmName() + " - calcOn = " + vm.getCalcOn());
}
}
}
}
System.out.println("🎯 VM Emission Calculation Summary:");
System.out.println(" Total VMs found: " + totalVMs);
System.out.println(" VMs with calcOn = true: " + eligibleVMs);
@@ -587,7 +509,7 @@ public class MessageListener {
System.out.println(" Failed emission calculations: " + failedCalculations);
}
private boolean createVMEmissionRecord(DataCenter dataCenter, VM vm, Project project, PhysicalMachine pm) {
private boolean createVMEmissionRecord(DataCenter dataCenter, VM vm, PhysicalMachine pm) {
try {
// Check if VM has an ID (is persisted)
if (vm.getId() == null) {
@@ -595,7 +517,7 @@ public class MessageListener {
return false;
}
MainDataTableCreateInput input = createVMMainDataTableInput(dataCenter, vm, project, pm);
MainDataTableCreateInput input = createVMMainDataTableInput(dataCenter, vm, pm);
System.out.println("🔍 Creating emission record for VM: " + vm.getVmName() + " (Power: " + vm.getPower() + "W)");
MainDataTable result = callMainDataTableMutation(input);
@@ -619,7 +541,7 @@ public class MessageListener {
}
}
private boolean createVMEmissionRecordForSource(DataCenter dataCenter, VM vm, Project project, PhysicalMachine pm, String emissionSourceName, Integer percentage) {
private boolean createVMEmissionRecordForSource(DataCenter dataCenter, VM vm, PhysicalMachine pm, String emissionSourceName, Integer percentage) {
try {
// Check if VM has an ID (is persisted)
if (vm.getId() == null) {
@@ -627,19 +549,56 @@ public class MessageListener {
return false;
}
// Find the emission source by name/tag
List<EmissionSource> emissionSources = emissionSourceRepo.findByTag(emissionSourceName);
if (emissionSources.isEmpty()) {
// Find the emission source by name/tag from datacenter's configured emission sources
EmissionSource emissionSource = null;
// First, try to find the emission source from datacenter's configured sources
if (dataCenter.getDataCenterEmissionSources() != null && !dataCenter.getDataCenterEmissionSources().isEmpty()) {
for (DataCenterEmissionSource dces : dataCenter.getDataCenterEmissionSources()) {
if (dces.getEmissionSource() != null &&
emissionSourceName.equalsIgnoreCase(dces.getEmissionSource().getTag())) {
emissionSource = dces.getEmissionSource();
System.out.println("✅ Found emission source '" + emissionSourceName +
"' in datacenter's configured sources (ID: " + emissionSource.getId() + ")");
break;
}
}
}
// If not found in datacenter's sources, fall back to subsector-specific search
if (emissionSource == null && dataCenter.getSubSector() != null) {
emissionSource = emissionSourceRepo.findByTagAndSubSectorIgnoreCase(emissionSourceName, dataCenter.getSubSector());
if (emissionSource != null) {
System.out.println("⚠️ Using subsector fallback for emission source '" + emissionSourceName +
"' (ID: " + emissionSource.getId() + ") - Consider configuring it for datacenter");
}
}
// Last resort: global search
if (emissionSource == null) {
List<EmissionSource> emissionSources = emissionSourceRepo.findByTag(emissionSourceName);
if (!emissionSources.isEmpty()) {
emissionSource = emissionSources.get(0);
System.out.println("⚠️ Using global fallback for emission source '" + emissionSourceName +
"' (ID: " + emissionSource.getId() + ") - This may cause incorrect calculations!");
}
}
if (emissionSource == null) {
System.err.println("❌ Could not find emission source: " + emissionSourceName);
return false;
}
EmissionSource emissionSource = emissionSources.get(0);
// Calculate power consumption for this emission source (percentage of total VM power)
double sourceSpecificPower = vm.getPower() * (percentage / 100.0);
MainDataTableCreateInput input = createVMMainDataTableInputForSource(dataCenter, vm, project, pm, emissionSource, sourceSpecificPower, percentage);
MainDataTableCreateInput input = createVMMainDataTableInputForSource(dataCenter, vm, pm, emissionSource, sourceSpecificPower, percentage);
if (input == null) {
System.err.println("❌ Failed to create input for VM emission calculation - skipping");
return false;
}
System.out.println("🔍 Creating emission record for VM: " + vm.getVmName() +
" - Source: " + emissionSourceName + " (" + percentage + "%) - Power: " + sourceSpecificPower + "W");
@@ -665,7 +624,7 @@ public class MessageListener {
}
}
private MainDataTableCreateInput createVMMainDataTableInput(DataCenter dataCenter, VM vm, Project project, PhysicalMachine pm) {
private MainDataTableCreateInput createVMMainDataTableInput(DataCenter dataCenter, VM vm, PhysicalMachine pm) {
MainDataTableCreateInput input = new MainDataTableCreateInput();
// Copy datacenter-level information (if available)
@@ -692,8 +651,15 @@ public class MessageListener {
input.setSubSector(dataCenter.getSubSector().getId());
}
if (dataCenter.getEmissionSource() != null) {
input.setEmissionSource(dataCenter.getEmissionSource().getId());
// Handle multiple emission sources - use the default one for emission calculations
if (dataCenter.getDataCenterEmissionSources() != null && !dataCenter.getDataCenterEmissionSources().isEmpty()) {
// Find the default emission source or use the first one
DataCenterEmissionSource defaultEmissionSource = dataCenter.getDataCenterEmissionSources().stream()
.filter(DataCenterEmissionSource::getIsDefault)
.findFirst()
.orElse(dataCenter.getDataCenterEmissionSources().get(0));
input.setEmissionSource(defaultEmissionSource.getEmissionSource().getId());
} else {
// Fallback to default emission source for electricity
try {
@@ -711,8 +677,16 @@ public class MessageListener {
input.setActivitySubUnit(dataCenter.getActivitySubUnit().getId());
}
if (dataCenter.getConsuptionUnit() != null) {
input.setConsuptionUnit(dataCenter.getConsuptionUnit().getId());
// Handle consumption unit from emission sources - use the default one for VM calculations
if (dataCenter.getDataCenterEmissionSources() != null && !dataCenter.getDataCenterEmissionSources().isEmpty()) {
DataCenterEmissionSource defaultEmissionSource = dataCenter.getDataCenterEmissionSources().stream()
.filter(DataCenterEmissionSource::getIsDefault)
.findFirst()
.orElse(dataCenter.getDataCenterEmissionSources().get(0));
if (defaultEmissionSource.getConsuptionUnit() != null) {
input.setConsuptionUnit(defaultEmissionSource.getConsuptionUnit().getId());
}
}
// Default to Kapsam-3 if no emission scope is set
@@ -739,69 +713,144 @@ public class MessageListener {
System.out.println(" VM Name: " + vm.getVmName());
System.out.println(" Power: " + vm.getPower() + "W");
System.out.println(" Physical Machine: " + pm.getName());
System.out.println(" Project: " + project.getName());
System.out.println(" DataCenter Sector: " + (dataCenter.getSector() != null ? dataCenter.getSector().getTag() : "NOT SET"));
return input;
}
private MainDataTableCreateInput createVMMainDataTableInputForSource(DataCenter dataCenter, VM vm, Project project, PhysicalMachine pm, EmissionSource emissionSource, double sourceSpecificPower, Integer percentage) {
private MainDataTableCreateInput createVMMainDataTableInputForSource(DataCenter dataCenter, VM vm, PhysicalMachine pm, EmissionSource emissionSource, double sourceSpecificPower, Integer percentage) {
MainDataTableCreateInput input = new MainDataTableCreateInput();
// Copy datacenter-level information (if available)
input.setYear("2025");
input.setMonth("07");
// Validate required fields
if (dataCenter == null) {
System.err.println("❌ DataCenter is null - cannot create emission record");
return null;
}
if (vm == null) {
System.err.println("❌ VM is null - cannot create emission record");
return null;
}
if (emissionSource == null) {
System.err.println("❌ EmissionSource is null - cannot create emission record");
return null;
}
// Note: These fields are no longer received in the message
// They need to be set via DataCenter CRUD operations first
if (dataCenter.getArea() != null && !dataCenter.getArea().getCities().isEmpty()) {
input.setCity(dataCenter.getArea().getCities().get(0).getId());
System.out.println("🔍 Setting City: " + dataCenter.getArea().getCities().get(0).getId());
} else {
System.out.println("⚠️ Warning: No city available for DataCenter");
}
if (dataCenter.getArea() != null && !dataCenter.getArea().getDistricts().isEmpty()) {
input.setDistrict(dataCenter.getArea().getDistricts().get(0).getId());
System.out.println("🔍 Setting District: " + dataCenter.getArea().getDistricts().get(0).getId());
} else {
System.out.println("⚠️ Warning: No district available for DataCenter");
}
if (dataCenter.getSector() != null) {
input.setSector(dataCenter.getSector().getId());
System.out.println("🔍 Setting Sector: " + dataCenter.getSector().getId() + " (" + dataCenter.getSector().getTag() + ")");
} else {
System.out.println("⚠️ Warning: DataCenter has no sector set - emission calculation may fail");
System.err.println("❌ Error: DataCenter has no sector set - this is required for emission calculation");
return null;
}
if (dataCenter.getSubSector() != null) {
input.setSubSector(dataCenter.getSubSector().getId());
System.out.println("🔍 Setting SubSector: " + dataCenter.getSubSector().getId());
} else {
System.out.println("⚠️ Warning: DataCenter has no subsector set");
}
// Use the specific emission source for this calculation
input.setEmissionSource(emissionSource.getId());
System.out.println("🔍 Setting EmissionSource: " + emissionSource.getId() + " (" + emissionSource.getTag() + ")");
if (dataCenter.getActivitySubUnit() != null) {
input.setActivitySubUnit(dataCenter.getActivitySubUnit().getId());
System.out.println("🔍 Setting ActivitySubUnit: " + dataCenter.getActivitySubUnit().getId());
} else {
System.out.println("⚠️ Warning: DataCenter has no activity sub unit set");
}
if (dataCenter.getConsuptionUnit() != null) {
input.setConsuptionUnit(dataCenter.getConsuptionUnit().getId());
// Handle consumption unit from emission sources - use the emission source's unit
if (emissionSource != null) {
// Find the DataCenterEmissionSource that matches this emissionSource
System.out.println("🔍 Looking for consumption unit for emission source: " + emissionSource.getTag());
if (dataCenter.getDataCenterEmissionSources() == null || dataCenter.getDataCenterEmissionSources().isEmpty()) {
System.err.println("❌ Error: DataCenter has no emission sources configured - cannot find consumption unit");
return null;
}
boolean foundUnit = false;
for (DataCenterEmissionSource dces : dataCenter.getDataCenterEmissionSources()) {
if (dces.getEmissionSource() != null && dces.getEmissionSource().getId().equals(emissionSource.getId())) {
if (dces.getConsuptionUnit() != null) {
input.setConsuptionUnit(dces.getConsuptionUnit().getId());
System.out.println("🔍 Setting ConsumptionUnit: " + dces.getConsuptionUnit().getId() + " (" + dces.getConsuptionUnit().getTag() + ")");
foundUnit = true;
break;
} else {
System.err.println("❌ Error: DataCenterEmissionSource has no consumption unit set for emission source: " + emissionSource.getTag());
return null;
}
}
}
if (!foundUnit) {
System.err.println("❌ Error: Could not find matching DataCenterEmissionSource for emission source: " + emissionSource.getTag());
return null;
}
}
// Default to Kapsam-3 if no emission scope is set
input.setScope(dataCenter.getEmissionScope() != null ?
dataCenter.getEmissionScope().getTag().equals("Kapsam-3") : true);
System.out.println("🔍 Setting Scope: " + (dataCenter.getEmissionScope() != null ?
dataCenter.getEmissionScope().getTag() : "Kapsam-3 (default)"));
try {
List<Organization> organizations = organizationRepo.findAll();
if (!organizations.isEmpty()) {
input.setOrganization(organizations.get(0).getId());
System.out.println("🔍 Setting Organization: " + organizations.get(0).getId());
} else {
System.err.println("❌ Error: No organizations found in database - this is required");
return null;
}
} catch (Exception e) {
System.err.println("❌ Error finding organization: " + e.getMessage());
return null;
}
// Set VM-specific fields
input.setVmId(vm.getId());
System.out.println("🔍 Setting VM ID: " + vm.getId());
// Use the source-specific power consumption (percentage of total VM power)
input.setConsuptionAmount(String.valueOf(sourceSpecificPower));
// Use the source-specific power consumption (percentage of total VM power)
// Format to 6 decimal places to avoid very long strings
String formattedPower = String.format("%.6f", sourceSpecificPower);
input.setConsuptionAmount(formattedPower);
System.out.println("🔍 Setting Consumption Amount: " + formattedPower + "W");
// Validate field lengths to prevent database errors
System.out.println("🔍 Field length validation:");
System.out.println(" Year: " + (input.getYear() != null ? input.getYear().length() : "null"));
System.out.println(" Month: " + (input.getMonth() != null ? input.getMonth().length() : "null"));
System.out.println(" ConsuptionAmount: " + (input.getConsuptionAmount() != null ? input.getConsuptionAmount().length() : "null"));
System.out.println("🔍 VM Emission Input for Source:");
System.out.println(" VM ID: " + vm.getId());
System.out.println(" VM Name: " + vm.getVmName());
@@ -809,7 +858,6 @@ public class MessageListener {
System.out.println(" Percentage: " + percentage + "%");
System.out.println(" Source Power: " + sourceSpecificPower + "W");
System.out.println(" Physical Machine: " + pm.getName());
System.out.println(" Project: " + project.getName());
System.out.println(" DataCenter Sector: " + (dataCenter.getSector() != null ? dataCenter.getSector().getTag() : "NOT SET"));
return input;
@@ -828,6 +876,34 @@ public class MessageListener {
try {
System.out.println("🔄 Calling mainDataTableMutation.createMainDataTable...");
// Validate input fields before making the call
if (input.getSector() == null) {
System.err.println("❌ Sector is null - cannot create emission record");
return null;
}
if (input.getEmissionSource() == null) {
System.err.println("❌ EmissionSource is null - cannot create emission record");
return null;
}
if (input.getConsuptionUnit() == null) {
System.err.println("❌ ConsumptionUnit is null - cannot create emission record");
return null;
}
if (input.getOrganization() == null) {
System.err.println("❌ Organization is null - cannot create emission record");
return null;
}
if (input.getVmId() == null) {
System.err.println("❌ VM ID is null - cannot create emission record");
return null;
}
System.out.println("🔍 Input validation passed - proceeding with mutation call");
// Call the mutation method - pass null environment since we've already patched the logging
MainDataTable result = mainDataTableMutation.createMainDataTable(input, null);

View File

@@ -17,16 +17,10 @@ security.jwt.token.secret-key=secret
app.survey.base-url=http://localhost.com
# spring.rabbitmq.host=188.132.198.145
# spring.rabbitmq.port=5672
# spring.rabbitmq.username=testuser
# spring.rabbitmq.password=JGasF24561AZv2894De
spring.rabbitmq.host=rabbitmq
#spring.rabbitmq.host=localhost
spring.rabbitmq.host=188.132.198.145
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.username=testuser
spring.rabbitmq.password=JGasF24561AZv2894De
spring.rabbitmq.virtual-host=/
spring.rabbitmq.connection-timeout=20000
spring.rabbitmq.template.retry.enabled=true
@@ -34,3 +28,6 @@ spring.rabbitmq.template.retry.max-attempts=3
spring.rabbitmq.template.retry.initial-interval=1000ms
logging.level.org.springframework.amqp=DEBUG
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

View File

@@ -5,10 +5,13 @@ input DataCenterCreateInput {
sectorId: ID
subSectorId: ID
activitySubUnitId: ID
emissionSourceId: ID
consuptionUnitId: ID
# Multiple emission sources support - each with exactly one unit
dataCenterEmissionSources: [DataCenterEmissionSourceInput!]
consuptionAmount: Float
areaId: ID
cityId: ID
number: Int
ayposURL: String
address: String
@@ -23,13 +26,23 @@ input DataCenterUpdateInput {
sectorId: ID
subSectorId: ID
activitySubUnitId: ID
emissionSourceId: ID
consuptionUnitId: ID
# Multiple emission sources support - each with exactly one unit
dataCenterEmissionSources: [DataCenterEmissionSourceInput!]
consuptionAmount: Float
areaId: ID
cityId: ID
number: Int
ayposURL: String
address: String
latitude: Float
longitude: Float
}
input DataCenterEmissionSourceInput {
emissionSourceId: ID!
consuptionUnitId: ID!
isDefault: Boolean
percentage: Float
}

View File

@@ -3,4 +3,5 @@ extend type Query{
dataCenters(criteria: DataCenterCriteria, sortBy: [SortBy!]): [DataCenter!]
paginateDataCenters(pagination : Pagination!, criteria: DataCenterCriteria, sortBy:[SortBy!] ) : DataCenterPageable!
getByNumber(number: Int!): DataCenter
physicalMachines(datacenterId: ID!): [PhysicalMachine!]!
}

View File

@@ -7,12 +7,15 @@ type DataCenter {
sector: Sector
subSector: SubSector
activitySubUnit: ActivitySubUnit
emissionSource: EmissionSource
consuptionUnit: ConsuptionUnit
# Multiple emission sources support - each with exactly one unit
dataCenterEmissionSources: [DataCenterEmissionSource]
consuptionAmount: Float
projects: [Project]
physicalMachines: [PhysicalMachine]
area: Area
city: City
number: Int
ayposURL: String
@@ -21,10 +24,12 @@ type DataCenter {
longitude: Float
}
type Project {
type DataCenterEmissionSource {
id: ID
name: String
physicalMachines: [PhysicalMachine]
emissionSource: EmissionSource
consuptionUnit: ConsuptionUnit
isDefault: Boolean
percentage: Float
}
type PhysicalMachine {
@@ -32,11 +37,13 @@ type PhysicalMachine {
name: String
ip: String
tag: String
cloudSystem: String
power: Float
vms: [Vm]
vms: [VM]
dataCenter: DataCenter
}
type Vm {
type VM {
id: ID
state: String
vmName: String
@@ -47,8 +54,10 @@ type Vm {
host: String
flavorName: String
tag: String
project: String
emissionSource: EmissionSourceMap
config: Config
physicalMachine: PhysicalMachine
}
scalar EmissionSourceMap

View File

@@ -2,5 +2,5 @@ extend type Query{
mainDataTable(id: ID!): MainDataTable!
mainDataTables(criteria: MainDataTableCriteria, sortBy: [SortBy!]): [MainDataTable!]
paginateMainDataTables(pagination : Pagination!, criteria: MainDataTableCriteria, sortBy:[SortBy!] ) : MainDataTablePageable!
vmEmissionSummary: [VMEmissionSummary!]!
vmEmissionSummary(datacenterId: ID): [VMEmissionSummary!]!
}

View File

@@ -26,11 +26,11 @@ type MainDataTable {
proteinAmount:Float
burnOrOpenBurn:Boolean
scopeCheck:Boolean
vm: Vm
vm: VM
}
type Vm {
type VM {
id: ID
state: String
vmName: String
@@ -41,6 +41,7 @@ type Vm {
host: String
flavorName: String
tag: String
project: String
config: Config
}
@@ -51,22 +52,22 @@ type Config {
disk: Int
}
type VMEmissionSummary {
vmId: ID!
vmName: String!
vmPower: Float
vmStatus: String
totalEmission: Float!
createdDate: LocalDateTime!
physicalMachine: String
project: String
dataCenter: String
# Individual emission values per record
co2: Float!
ch4: Float!
n2o: Float!
reportGeneratedTime: LocalDateTime
}
type VMEmissionSummary {
vmId: ID!
vmName: String
vmPower: Float
vmStatus: String
totalEmission: Float!
createdDate: LocalDateTime!
physicalMachine: String
cloudSystem: String
dataCenter: String
# Individual emission values per record
co2: Float!
ch4: Float!
n2o: Float!
reportGeneratedTime: LocalDateTime
}
type SolidWasteSupplement {
id: ID!

View File

@@ -67,7 +67,11 @@
"Common": {
"save": "Save",
"cancel": "Cancel"
"cancel": "Cancel",
"yes": "Yes",
"no": "No",
"areYouSure": "Are you sure?",
"cantRevert": "This action cannot be undone!"
},
"DataInput": {

View File

@@ -1,311 +1,315 @@
{
"Actions": "Aksiyonlar",
"Active": "Aktif",
"ByName": "İsme Göre",
"CreatedTime": "Oluşturulma Zamanı",
"Description": " Açıklaması",
"Filter": "Filtrele",
"Management": "Yönetim",
"Passive": "Pasif",
"Show": "Göster",
"Status": "Durum",
"Time": "Zaman ",
"Activities": {
"activity": "Aktivite ",
"activities": "Aktiviteler ",
"type": "Log Tipi",
"message": "Log Mesajı"
},
"Areas": {
"addArea": "Alan Ekle",
"area": "Alan ",
"areas": "Alanlar ",
"areaName": "Alan Adı ",
"city": "Şehir ",
"cities": "Şehirler ",
"cityName": "Şehir Adı ",
"country": "Ülke ",
"countries": "Ülkeler ",
"countryName": "Ülke Adı ",
"countryCode": "Ülke Kodu ",
"district": "İlçe ",
"districts": "İlçeler",
"districtName": "İlçe Adı",
"neighborhood": "Mahalle ",
"neighborhoods": "Mahalleler ",
"neighborhoodName": "Mahalle Adı",
"addNeighborhood": "Mahalle Ekle",
"latitude": "Enlem",
"longitude": "Boylam"
},
"Auth": {
"authorized": "Devam etmek için yetkilendirilmiş kullanıcı bilgilerinizi giriniz.",
"didUForgotPassword": "Şifrenizi mi unuttunuz?",
"logout": ıkış Yap",
"logoutMessage": " Çıkış yaptınız. Yönlendiriliyorsunuz...",
"login": "Giriş Yap",
"loginMessage": " Giriş başarılı yönlendiriliyorsunuz...",
"password": "Şifre ",
"welcome": "Hoşgeldiniz",
"incorrectForm": "Kullanıcı bilgileri hatalıdır. Lütfen tekrar deneyiniz."
},
"Cruds": {
"add": " Ekle",
"cancel": " İptal",
"delete": "Sil",
"edit": "Düzenle",
"reactive": "Aktif Et",
"save": "Kaydet",
"saving": "Kaydediliyor..",
"update": "Güncelle"
},
"Common": {
"save": "Kaydet",
"cancel": " İptal"
},
"DataInput": {
"area": "Bölge ",
"report": "Rapor ",
"reports": "Raw Data",
"data": "Veri ",
"datas": "Veriler ",
"dataInput": "Veri Girişi",
"year": "Yıl",
"month": "Ay",
"consumptionAmount": "Tüketim Miktarı",
"consumptionUnit": "Tüketim Birimi",
"gpcReference": "GPC Referans",
"total": "Toplam ",
"save": "Veriyi Kaydet",
"update": "Veriyi Güncelle",
"showDeleted": "Silinen Raporları Göster",
"result": "Sonuç",
"directToAllDatas": "Tüm Verileri Gör",
"addNewData": "Yeni Veri Ekle",
"failUploadExcel": "Dosya yüklenirken hata oluştu!"
},
"Graphics": {
"graphics": "Raporlar",
"reports": "Raporlar"
},
"EmissionSources": {
"dataSet": "Veri Seti",
"emissionSource": "Emisyon Kaynağı ",
"emissionSources": "Emisyon Kaynakları ",
"emissionSourceName": "Emisyon Kaynağı Adı",
"addEmissionSource": "Emisyon Kaynağı Ekle",
"existingEmissionName": "Bu isimde bir emisyon kaynağı mevcuttur!",
"sector": "Veri Sektörü ",
"sectors": "Veri Sektörleri ",
"subSector": "Sektör Alt Birimi ",
"subSectors": "Sektör Alt Birimleri ",
"subUnit": "Faaliyet Alt Birimi ",
"subUnits": "Faaliyet Alt Birimleri ",
"emissionScopes": "Emisyon Kapsamı ",
"emissionFactors": "Emisyon Faktörleri ",
"showDeletedEmissionSource": "Silinen Emisyon Kaynaklarını Göster"
},
"Map": {
"map": "Harita",
"goBack": "Geri dön",
"reference": "Referans",
"title": "Harita"
},
"Months": {
"1": "Ocak",
"2": "Şubat",
"3": "Mart",
"4": "Nisan",
"5": "Mayıs",
"6": "Haziran",
"7": "Temmuz",
"8": "Ağustos",
"9": "Eylül",
"10": "Ekim",
"11": "Kasım",
"12": "Aralık",
"null": "Yıl Geneli",
"0": "Yıl Geneli"
},
"Notifications": {
"content": "İçerik ",
"notification": "Bildirim ",
"notifications": "Bildirimler ",
"showAll": "Tüm Bildirimleri Göster",
"title": "Başlık ",
"notificationType": "Bildirim Tipi "
},
"Organizations": {
"organization": "Organizasyon ",
"organizations": "Organizasyonlar",
"organizationName": "Organizasyon Adı",
"parentOrganization": "Bağlı Olduğu Organizasyon",
"childOrganization": "Alt Organizasyonu",
"addOrganization": "Organizasyon Ekle",
"existingName": "Bu isimde bir organizasyon mevcuttur!.",
"showDeletedOrganizations": "Silinen Organizasyonları Göster"
},
"PasswordLabel": {
"passwordLabel": "Şifre",
"confirmPassword": "Şifre Tekrar",
"oldPassword": "Eski Şifre",
"newPassword": "Yeni Şifre",
"newConfirmPassword": "Yeni Şifre Tekrar",
"verificationCode": "Doğrulama Kodu",
"cannotbeleftblank": " Boş Bırakılamaz ",
"passwordNotSame": "Şifreler aynı değil",
"passwordValidation": "Şifre 6-20 karakter uzunluğunda, en az 1 sayı, 1 büyük harf ve 1 küçük harf içermelidir!",
"forgotPassword": "Şifremi Unuttum",
"enterEmail": "Geçerli bir email giriniz.",
"send": "Gönder",
"redirectToReset": "Şifre sıfırlama ekranına yönlendiriliyorsunuz..",
"resetPassword": "Şifre Sıfırlama",
"resend": "Doğrulama Kodunu Tekrar Gönder",
"invalidVerificationCode": "Geçersiz doğrulama kodu!",
"redirectToLogin": "Giriş ekranına yönlendiriliyorsunuz.."
},
"Roles": {
"role": "Rol ",
"roles": "Roller",
"roleName": "Rol Adı",
"addRole": "Rol Ekle",
"permissions": "Yetkiler",
"existingRole": "Bu rol zaten mevcuttur."
},
"Survey": {
"addAnswer": "Cevap Ekle",
"addSurvey": "Anket Ekle",
"addQuestion": "Soru Ekle",
"answer": "Cevap ",
"answers": "Cevaplar",
"survey": "Anket",
"surveys": "Anketler ",
"surveyName": "Anket Adı",
"question": "Soru ",
"questions": "Sorular",
"tag": "Etiket",
"value": "Değer"
},
"Contact": {
"contact": "İletişim",
"contactInfo": "İletişim Bilgileri",
"contactEmail": "E-posta Adresi",
"contactPhoneNumber": "Telefon Numarası",
"contactAddress": "Adres"
},
"MailSettings": {
"mailSettings": "E-posta Ayarları",
"editMailInfo": "E-posta Bilgilerini Düzenle",
"hostName": "Sunucu Adı",
"smtpPort": "SMTP Portu",
"emailAddress": "E-posta Adresi",
"emailPassword": "E-posta Şifresi",
"leaveBlankNote": "(Mevcut şifreyi korumak için boş bırakın)",
"mainMail": "Ana e-posta yapılandırması olarak ayarla",
"saveSettings": "Ayarları Kaydet",
"notConfigured": "E-posta yapılandırılmamış",
"noMailsRegistered": "Kayıtlı e-posta bulunamadı"
},
"Timer": {
"continue": "Devam Et ",
"expire": "Oturum süreniz dolmak üzeredir.."
},
"Users": {
"user": "Kullanıcı ",
"users": "Kullanıcılar ",
"userName": "Kullanıcı Adı ",
"addUser": "Kullanıcı Ekle",
"existingEmail": "Bu e-mail zaten mevcuttur.",
"existingPhoneNumber": "Bu telefon numarası zaten mevcuttur.",
"showDeletedUsers": "Silinen Kullanıcıları Göster"
},
"UserProfile": {
"myProfile": "Profilim",
"firstName": "Ad",
"lastName": "Soyad",
"phoneNumber": "Telefon Numarası",
"avatar": "Profil Fotoğrafı",
"status": "Durum",
"changePassword": "Şifre Değiştir",
"communicationPreferences": "İletişim Tercihleri",
"updateAvatar": "Profil Resmini Güncelle"
},
"Warnings": {
"addedFail": " Eklenirken hata meydana geldi, lütfen tekrar deneyiniz.",
"addedSuccessfully": " Başarıyla Eklendi!",
"updatedSuccessfully": " Başarıyla Güncellendi!",
"updatedFail": " Güncellenirken hata meydana geldi, lütfen tekrar deneyiniz.",
"deletedSuccessfully": " Başarıyla Silindi!",
"deletedFail": " Silinirken hata meydana geldi, lütfen tekrar deneyiniz.",
"genericUpdateFailed": "Güncelleme başarısız oldu. Lütfen tekrar deneyiniz.",
"notFound": "Bulunamadı",
"notUndone": "Bu işlem geri alınamaz!",
"required": "Tüm Alanlar Zorunludur!",
"sureForDelete": " Silmek İstediğinize Emin Misiniz?",
"uniqueName": " Benzersiz bir isim veriniz! "
},
"UserActivities": {
"title": "Kullanıcı Aktiviteleri"
},
"SystemActivities": {
"title": "Sistem Aktiviteleri"
},
"DataCenter": {
"title": "Veri Merkezleri",
"create": "Veri Merkezi Ekle",
"name": "İsim",
"namePlaceholder": "Veri merkezi ismini girin",
"externalId": "Harici ID",
"externalIdPlaceholder": "Harici ID girin",
"number": "Numara",
"numberPlaceholder": "Numara girin",
"url": "URL",
"urlPlaceholder": "URL girin",
"createSuccess": "Veri merkezi başarıyla oluşturuldu",
"deleteSuccess": "Veri merkezi başarıyla silindi",
"searchPlaceholder": "Veri merkezlerinde ara..."
},
"DataCenters": {
"title": "Veri Merkezleri",
"create": "Veri Merkezi Ekle",
"name": "İsim",
"namePlaceholder": "Veri merkezi ismini girin",
"externalId": "Harici ID",
"externalIdPlaceholder": "Harici ID girin",
"number": "Numara",
"numberPlaceholder": "Numara girin",
"url": "URL",
"urlPlaceholder": "URL girin",
"createSuccess": "Veri merkezi başarıyla oluşturuldu",
"deleteSuccess": "Veri merkezi başarıyla silindi",
"searchPlaceholder": "Veri merkezlerinde ara..."
}
}
{
"Actions": "Aksiyonlar",
"Active": "Aktif",
"ByName": "İsme Göre",
"CreatedTime": "Oluşturulma Zamanı",
"Description": " Açıklaması",
"Filter": "Filtrele",
"Management": "Yönetim",
"Passive": "Pasif",
"Show": "Göster",
"Status": "Durum",
"Time": "Zaman ",
"Activities": {
"activity": "Aktivite ",
"activities": "Aktiviteler ",
"type": "Log Tipi",
"message": "Log Mesajı"
},
"Areas": {
"addArea": "Alan Ekle",
"area": "Alan ",
"areas": "Alanlar ",
"areaName": "Alan Adı ",
"city": "Şehir ",
"cities": "Şehirler ",
"cityName": "Şehir Adı ",
"country": "Ülke ",
"countries": "Ülkeler ",
"countryName": "Ülke Adı ",
"countryCode": "Ülke Kodu ",
"district": "İlçe ",
"districts": "İlçeler",
"districtName": "İlçe Adı",
"neighborhood": "Mahalle ",
"neighborhoods": "Mahalleler ",
"neighborhoodName": "Mahalle Adı",
"addNeighborhood": "Mahalle Ekle",
"latitude": "Enlem",
"longitude": "Boylam"
},
"Auth": {
"authorized": "Devam etmek için yetkilendirilmiş kullanıcı bilgilerinizi giriniz.",
"didUForgotPassword": "Şifrenizi mi unuttunuz?",
"logout": ıkış Yap",
"logoutMessage": " Çıkış yaptınız. Yönlendiriliyorsunuz...",
"login": "Giriş Yap",
"loginMessage": " Giriş başarılı yönlendiriliyorsunuz...",
"password": "Şifre ",
"welcome": "Hoşgeldiniz",
"incorrectForm": "Kullanıcı bilgileri hatalıdır. Lütfen tekrar deneyiniz."
},
"Cruds": {
"add": " Ekle",
"cancel": " İptal",
"delete": "Sil",
"edit": "Düzenle",
"reactive": "Aktif Et",
"save": "Kaydet",
"saving": "Kaydediliyor..",
"update": "Güncelle"
},
"Common": {
"save": "Kaydet",
"cancel": "İptal",
"yes": "Evet",
"no": "Hayır",
"areYouSure": "Emin misiniz?",
"cantRevert": "Bu işlem geri alınamaz!"
},
"DataInput": {
"area": "Bölge ",
"report": "Rapor ",
"reports": "Raw Data",
"data": "Veri ",
"datas": "Veriler ",
"dataInput": "Veri Girişi",
"year": "Yıl",
"month": "Ay",
"consumptionAmount": "Tüketim Miktarı",
"consumptionUnit": "Tüketim Birimi",
"gpcReference": "GPC Referans",
"total": "Toplam ",
"save": "Veriyi Kaydet",
"update": "Veriyi Güncelle",
"showDeleted": "Silinen Raporları Göster",
"result": "Sonuç",
"directToAllDatas": "Tüm Verileri Gör",
"addNewData": "Yeni Veri Ekle",
"failUploadExcel": "Dosya yüklenirken hata oluştu!"
},
"Graphics": {
"graphics": "Raporlar",
"reports": "Raporlar"
},
"EmissionSources": {
"dataSet": "Veri Seti",
"emissionSource": "Emisyon Kaynağı ",
"emissionSources": "Emisyon Kaynakları ",
"emissionSourceName": "Emisyon Kaynağı Adı",
"addEmissionSource": "Emisyon Kaynağı Ekle",
"existingEmissionName": "Bu isimde bir emisyon kaynağı mevcuttur!",
"sector": "Veri Sektörü ",
"sectors": "Veri Sektörleri ",
"subSector": "Sektör Alt Birimi ",
"subSectors": "Sektör Alt Birimleri ",
"subUnit": "Faaliyet Alt Birimi ",
"subUnits": "Faaliyet Alt Birimleri ",
"emissionScopes": "Emisyon Kapsamı ",
"emissionFactors": "Emisyon Faktörleri ",
"showDeletedEmissionSource": "Silinen Emisyon Kaynaklarını Göster"
},
"Map": {
"map": "Harita",
"goBack": "Geri dön",
"reference": "Referans",
"title": "Harita"
},
"Months": {
"1": "Ocak",
"2": "Şubat",
"3": "Mart",
"4": "Nisan",
"5": "Mayıs",
"6": "Haziran",
"7": "Temmuz",
"8": "Ağustos",
"9": "Eylül",
"10": "Ekim",
"11": "Kasım",
"12": "Aralık",
"null": "Yıl Geneli",
"0": "Yıl Geneli"
},
"Notifications": {
"content": "İçerik ",
"notification": "Bildirim ",
"notifications": "Bildirimler ",
"showAll": "Tüm Bildirimleri Göster",
"title": "Başlık ",
"notificationType": "Bildirim Tipi "
},
"Organizations": {
"organization": "Organizasyon ",
"organizations": "Organizasyonlar",
"organizationName": "Organizasyon Adı",
"parentOrganization": "Bağlı Olduğu Organizasyon",
"childOrganization": "Alt Organizasyonu",
"addOrganization": "Organizasyon Ekle",
"existingName": "Bu isimde bir organizasyon mevcuttur!.",
"showDeletedOrganizations": "Silinen Organizasyonları Göster"
},
"PasswordLabel": {
"passwordLabel": "Şifre",
"confirmPassword": "Şifre Tekrar",
"oldPassword": "Eski Şifre",
"newPassword": "Yeni Şifre",
"newConfirmPassword": "Yeni Şifre Tekrar",
"verificationCode": "Doğrulama Kodu",
"cannotbeleftblank": " Boş Bırakılamaz ",
"passwordNotSame": "Şifreler aynı değil",
"passwordValidation": "Şifre 6-20 karakter uzunluğunda, en az 1 sayı, 1 büyük harf ve 1 küçük harf içermelidir!",
"forgotPassword": "Şifremi Unuttum",
"enterEmail": "Geçerli bir email giriniz.",
"send": "Gönder",
"redirectToReset": "Şifre sıfırlama ekranına yönlendiriliyorsunuz..",
"resetPassword": "Şifre Sıfırlama",
"resend": "Doğrulama Kodunu Tekrar Gönder",
"invalidVerificationCode": "Geçersiz doğrulama kodu!",
"redirectToLogin": "Giriş ekranına yönlendiriliyorsunuz.."
},
"Roles": {
"role": "Rol ",
"roles": "Roller",
"roleName": "Rol Adı",
"addRole": "Rol Ekle",
"permissions": "Yetkiler",
"existingRole": "Bu rol zaten mevcuttur."
},
"Survey": {
"addAnswer": "Cevap Ekle",
"addSurvey": "Anket Ekle",
"addQuestion": "Soru Ekle",
"answer": "Cevap ",
"answers": "Cevaplar",
"survey": "Anket",
"surveys": "Anketler ",
"surveyName": "Anket Adı",
"question": "Soru ",
"questions": "Sorular",
"tag": "Etiket",
"value": "Değer"
},
"Contact": {
"contact": "İletişim",
"contactInfo": "İletişim Bilgileri",
"contactEmail": "E-posta Adresi",
"contactPhoneNumber": "Telefon Numarası",
"contactAddress": "Adres"
},
"MailSettings": {
"mailSettings": "E-posta Ayarları",
"editMailInfo": "E-posta Bilgilerini Düzenle",
"hostName": "Sunucu Adı",
"smtpPort": "SMTP Portu",
"emailAddress": "E-posta Adresi",
"emailPassword": "E-posta Şifresi",
"leaveBlankNote": "(Mevcut şifreyi korumak için boş bırakın)",
"mainMail": "Ana e-posta yapılandırması olarak ayarla",
"saveSettings": "Ayarları Kaydet",
"notConfigured": "E-posta yapılandırılmamış",
"noMailsRegistered": "Kayıtlı e-posta bulunamadı"
},
"Timer": {
"continue": "Devam Et ",
"expire": "Oturum süreniz dolmak üzeredir.."
},
"Users": {
"user": "Kullanıcı ",
"users": "Kullanıcılar ",
"userName": "Kullanıcı Adı ",
"addUser": "Kullanıcı Ekle",
"existingEmail": "Bu e-mail zaten mevcuttur.",
"existingPhoneNumber": "Bu telefon numarası zaten mevcuttur.",
"showDeletedUsers": "Silinen Kullanıcıları Göster"
},
"UserProfile": {
"myProfile": "Profilim",
"firstName": "Ad",
"lastName": "Soyad",
"phoneNumber": "Telefon Numarası",
"avatar": "Profil Fotoğrafı",
"status": "Durum",
"changePassword": "Şifre Değiştir",
"communicationPreferences": "İletişim Tercihleri",
"updateAvatar": "Profil Resmini Güncelle"
},
"Warnings": {
"addedFail": " Eklenirken hata meydana geldi, lütfen tekrar deneyiniz.",
"addedSuccessfully": " Başarıyla Eklendi!",
"updatedSuccessfully": " Başarıyla Güncellendi!",
"updatedFail": " Güncellenirken hata meydana geldi, lütfen tekrar deneyiniz.",
"deletedSuccessfully": " Başarıyla Silindi!",
"deletedFail": " Silinirken hata meydana geldi, lütfen tekrar deneyiniz.",
"genericUpdateFailed": "Güncelleme başarısız oldu. Lütfen tekrar deneyiniz.",
"notFound": "Bulunamadı",
"notUndone": "Bu işlem geri alınamaz!",
"required": "Tüm Alanlar Zorunludur!",
"sureForDelete": " Silmek İstediğinize Emin Misiniz?",
"uniqueName": " Benzersiz bir isim veriniz! "
},
"UserActivities": {
"title": "Kullanıcı Aktiviteleri"
},
"SystemActivities": {
"title": "Sistem Aktiviteleri"
},
"DataCenter": {
"title": "Veri Merkezleri",
"create": "Veri Merkezi Ekle",
"name": "İsim",
"namePlaceholder": "Veri merkezi ismini girin",
"externalId": "Harici ID",
"externalIdPlaceholder": "Harici ID girin",
"number": "Numara",
"numberPlaceholder": "Numara girin",
"url": "URL",
"urlPlaceholder": "URL girin",
"createSuccess": "Veri merkezi başarıyla oluşturuldu",
"deleteSuccess": "Veri merkezi başarıyla silindi",
"searchPlaceholder": "Veri merkezlerinde ara..."
},
"DataCenters": {
"title": "Veri Merkezleri",
"create": "Veri Merkezi Ekle",
"name": "İsim",
"namePlaceholder": "Veri merkezi ismini girin",
"externalId": "Harici ID",
"externalIdPlaceholder": "Harici ID girin",
"number": "Numara",
"numberPlaceholder": "Numara girin",
"url": "URL",
"urlPlaceholder": "URL girin",
"createSuccess": "Veri merkezi başarıyla oluşturuldu",
"deleteSuccess": "Veri merkezi başarıyla silindi",
"searchPlaceholder": "Veri merkezlerinde ara..."
}
}

View File

@@ -49,9 +49,9 @@ export default [
permissionCheck("paginate_roles_get")) && [
{
id: "Organizations",
title: "DataCenters.title",
title: "Data Center Management",
icon: <Home size={20} />,
navLink: "/organizasyonlar",
navLink: "/veri-merkezi-yonetimi",
display: (permissionCheck("paginate_datacenters_get") ||
permissionCheck("data_center_create") ||
permissionCheck("data_center_update") ||
@@ -142,9 +142,63 @@ export default [
},
{
id: "DataCenter",
title: "Data Centers",
title: "Data Center Overview",
icon: <Zap size={20} />,
navLink: "/verimerkezi",
navLink: "/veri-merkezi-genel",
},
{
id: "Areas",
title: "Areas.areas",
icon: <Map size={20} />,
display:
permissionCheck("paginate_areas_get") ||
permissionCheck("paginate_countries_get") ||
permissionCheck("paginate_cities_get") ||
permissionCheck("paginate_districts_get") ||
permissionCheck("paginate_neighborhoods_get")
? ""
: "none",
children: (permissionCheck("paginate_areas_get") ||
permissionCheck("paginate_countries_get") ||
permissionCheck("paginate_cities_get") ||
permissionCheck("paginate_districts_get") ||
permissionCheck("paginate_neighborhoods_get")) && [
{
id: "AreasManagement",
title: "Areas.areas",
icon: <ArrowRight size={20} />,
navLink: "/alanlar",
display: permissionCheck("paginate_areas_get") ? "" : "none",
},
{
id: "Countries",
title: "Areas.countries",
icon: <ArrowRight size={20} />,
navLink: "/ulkeler",
display: permissionCheck("paginate_countries_get") ? "" : "none",
},
{
id: "Cities",
title: "Areas.cities",
icon: <ArrowRight size={20} />,
navLink: "/iller",
display: permissionCheck("paginate_cities_get") ? "" : "none",
},
{
id: "Districts",
title: "Areas.districts",
icon: <ArrowRight size={20} />,
navLink: "/ilceler",
display: permissionCheck("paginate_districts_get") ? "" : "none",
},
{
id: "Neighborhoods",
title: "Areas.neighborhoods",
icon: <ArrowRight size={20} />,
navLink: "/mahalleler",
display: permissionCheck("paginate_neighborhoods_get") ? "" : "none",
},
],
},
{
id: "Survey",

View File

@@ -49,9 +49,9 @@ export default [
permissionCheck("paginate_roles_get")) && [
{
id: "DataCenters",
title: "DataCenters.title",
title: "Data Center Management",
icon: <Zap size={20} />,
navLink: "/organizasyonlar",
navLink: "/veri-merkezi-yonetimi",
display: (permissionCheck("paginate_datacenters_get") ||
permissionCheck("data_center_create") ||
permissionCheck("data_center_update") ||
@@ -142,9 +142,63 @@ export default [
},
{
id: "DataCenter",
title: "DataCenters",
title: "Data Center Overview",
icon: <Zap size={20} />,
navLink: "/verimerkezi",
navLink: "/veri-merkezi-genel",
},
{
id: "Areas",
title: "Areas.areas",
icon: <Map size={20} />,
display:
permissionCheck("paginate_areas_get") ||
permissionCheck("paginate_countries_get") ||
permissionCheck("paginate_cities_get") ||
permissionCheck("paginate_districts_get") ||
permissionCheck("paginate_neighborhoods_get")
? ""
: "none",
children: (permissionCheck("paginate_areas_get") ||
permissionCheck("paginate_countries_get") ||
permissionCheck("paginate_cities_get") ||
permissionCheck("paginate_districts_get") ||
permissionCheck("paginate_neighborhoods_get")) && [
{
id: "AreasManagement",
title: "Areas.areas",
icon: <ArrowRight size={20} />,
navLink: "/alanlar",
display: permissionCheck("paginate_areas_get") ? "" : "none",
},
{
id: "Countries",
title: "Areas.countries",
icon: <ArrowRight size={20} />,
navLink: "/ulkeler",
display: permissionCheck("paginate_countries_get") ? "" : "none",
},
{
id: "Cities",
title: "Areas.cities",
icon: <ArrowRight size={20} />,
navLink: "/iller",
display: permissionCheck("paginate_cities_get") ? "" : "none",
},
{
id: "Districts",
title: "Areas.districts",
icon: <ArrowRight size={20} />,
navLink: "/ilceler",
display: permissionCheck("paginate_districts_get") ? "" : "none",
},
{
id: "Neighborhoods",
title: "Areas.neighborhoods",
icon: <ArrowRight size={20} />,
navLink: "/mahalleler",
display: permissionCheck("paginate_neighborhoods_get") ? "" : "none",
},
],
},
{
id: "Survey",

View File

@@ -12,6 +12,15 @@ export const getAreas = () => {
id
tag
isDeleted
cities {
id
name
coordinates
country {
id
name
}
}
}
}
`,

View File

@@ -34,30 +34,69 @@ export const getDataCenters = () => {
latitude
longitude
area {
tag
name
cityId
districtId
}
projects {
id
name
physicalMachines {
tag
cities {
id
name
vms {
active {
id
status
name
power
config {
id
cpu
ram
disk
}
}
}
districts {
id
name
}
}
city {
id
name
}
emissionScope {
id
tag
description
}
sector {
id
tag
}
subSector {
id
tag
}
dataCenterEmissionSources {
id
emissionSource {
id
tag
}
consuptionUnit {
id
description
}
isDefault
percentage
}
activitySubUnit {
id
tag
}
physicalMachines {
id
name
vms {
id
vmName
state
power
calcOn
hostingPm
host
flavorName
tag
config {
id
cpu
ram
disk
}
}
}
@@ -77,7 +116,7 @@ export const getDataCenters = () => {
console.log("GraphQL Response:", {
status: response.status,
data: response.data,
errors: response.data?.errors
errors: response.data?.errors,
});
// Check for GraphQL errors
@@ -91,7 +130,7 @@ export const getDataCenters = () => {
}
const dataCenters = response.data.data.dataCenters;
// Validate dataCenters is an array
if (!Array.isArray(dataCenters)) {
throw new Error("Invalid response: dataCenters is not an array");
@@ -110,7 +149,7 @@ export const getDataCenters = () => {
message: error.message,
response: error.response?.data,
status: error.response?.status,
stack: error.stack
stack: error.stack,
});
// Check for specific error types
@@ -155,10 +194,50 @@ export const createDataCenter = (dataCenterData) => {
latitude
longitude
area {
id
tag
cities {
id
name
}
districts {
id
name
}
}
city {
id
name
cityId
districtId
}
emissionScope {
id
tag
description
}
sector {
id
tag
}
subSector {
id
tag
}
dataCenterEmissionSources {
id
emissionSource {
id
tag
}
consuptionUnit {
id
description
}
isDefault
percentage
}
activitySubUnit {
id
tag
}
}
}
@@ -169,13 +248,23 @@ export const createDataCenter = (dataCenterData) => {
externalId: parseInt(dataCenterData.externalId),
ayposURL: dataCenterData.ayposURL || "",
number: parseInt(dataCenterData.number) || 1,
areaId: dataCenterData.areaId,
areaId: dataCenterData.areaId || null,
cityId: dataCenterData.cityId || null,
address: dataCenterData.address || "",
latitude: dataCenterData.latitude ? parseFloat(dataCenterData.latitude) : null,
longitude: dataCenterData.longitude ? parseFloat(dataCenterData.longitude) : null,
city: dataCenterData.city
}
}
latitude: dataCenterData.latitude
? parseFloat(dataCenterData.latitude)
: null,
longitude: dataCenterData.longitude
? parseFloat(dataCenterData.longitude)
: null,
emissionScopeId: dataCenterData.emissionScopeId || null,
sectorId: dataCenterData.sectorId || null,
subSectorId: dataCenterData.subSectorId || null,
dataCenterEmissionSources:
dataCenterData.dataCenterEmissionSources || [],
activitySubUnitId: dataCenterData.activitySubUnitId || null,
},
},
},
{
headers: {
@@ -188,7 +277,7 @@ export const createDataCenter = (dataCenterData) => {
console.log("Create Response:", {
status: response.status,
data: response.data,
errors: response.data?.errors
errors: response.data?.errors,
});
if (response.data?.errors) {
@@ -240,10 +329,50 @@ export const updateDataCenter = (id, dataCenterData) => {
latitude
longitude
area {
id
tag
cities {
id
name
}
districts {
id
name
}
}
city {
id
name
cityId
districtId
}
emissionScope {
id
tag
description
}
sector {
id
tag
}
subSector {
id
tag
}
dataCenterEmissionSources {
id
emissionSource {
id
tag
}
consuptionUnit {
id
description
}
isDefault
percentage
}
activitySubUnit {
id
tag
}
}
}
@@ -255,13 +384,23 @@ export const updateDataCenter = (id, dataCenterData) => {
externalId: parseInt(dataCenterData.externalId),
ayposURL: dataCenterData.ayposURL || "",
number: parseInt(dataCenterData.number) || 1,
areaId: dataCenterData.areaId,
areaId: dataCenterData.areaId || null,
cityId: dataCenterData.cityId || null,
address: dataCenterData.address || "",
latitude: dataCenterData.latitude ? parseFloat(dataCenterData.latitude) : null,
longitude: dataCenterData.longitude ? parseFloat(dataCenterData.longitude) : null,
city: dataCenterData.city
}
}
latitude: dataCenterData.latitude
? parseFloat(dataCenterData.latitude)
: null,
longitude: dataCenterData.longitude
? parseFloat(dataCenterData.longitude)
: null,
emissionScopeId: dataCenterData.emissionScopeId || null,
sectorId: dataCenterData.sectorId || null,
subSectorId: dataCenterData.subSectorId || null,
dataCenterEmissionSources:
dataCenterData.dataCenterEmissionSources || [],
activitySubUnitId: dataCenterData.activitySubUnitId || null,
},
},
},
{
headers: {
@@ -276,7 +415,7 @@ export const updateDataCenter = (id, dataCenterData) => {
dispatch({
type: "UPDATE_DATA_CENTER_SUCCESS",
payload: response.data.data.updateDataCenter
payload: response.data.data.updateDataCenter,
});
return response.data.data.updateDataCenter;
@@ -309,8 +448,8 @@ export const deleteDataCenter = (id) => {
}
`,
variables: {
id: id
}
id: id,
},
},
{
headers: {
@@ -325,7 +464,7 @@ export const deleteDataCenter = (id) => {
dispatch({
type: "DELETE_DATA_CENTER_SUCCESS",
payload: id
payload: id,
});
return true;
@@ -342,69 +481,113 @@ export const deleteDataCenter = (id) => {
};
};
export const getEmissionScopes = () => {
return async (dispatch) => {
dispatch({
type: "GET_EMISSION_SCOPES_LOADING",
});
try {
const response = await ApplicationService.http().post(
"/graphql",
{
query: `
query GetEmissionScopes {
emissionScopes {
id
tag
description
}
}
`,
},
{
headers: {
Authorization: "Bearer " + localStorage.getItem("accessToken"),
},
}
);
if (response.data?.errors) {
throw new Error(response.data.errors[0].message);
}
dispatch({
type: "GET_EMISSION_SCOPES_SUCCESS",
payload: response.data.data.emissionScopes,
});
return response.data.data.emissionScopes;
} catch (error) {
console.error("Error fetching emission scopes:", error);
dispatch({
type: "GET_EMISSION_SCOPES_ERROR",
payload: {
error: error.message || "Failed to fetch emission scopes",
},
});
throw error;
}
};
};
export const getDataCenterVMs = (dataCenterId) => {
return new Promise(async (resolve, reject) => {
// Don't make the request if dataCenterId is undefined, null, or empty
if (!dataCenterId || dataCenterId === "undefined") {
console.log('getDataCenterVMs: No dataCenterId provided');
console.log("getDataCenterVMs: No dataCenterId provided");
resolve([]);
return;
}
try {
console.log('getDataCenterVMs: Fetching VMs for data center:', dataCenterId);
const response = await ApplicationService.http()
.post(
"/graphql",
{
query: `
console.log(
"getDataCenterVMs: Fetching VMs for data center:",
dataCenterId
);
const response = await ApplicationService.http().post(
"/graphql",
{
query: `
{
dataCenter(id: "${dataCenterId}") {
id
dataCenter
projects {
physicalMachines {
id
name
physicalMachines {
vms {
id
name
vms {
id
name
status
power
}
vmName
state
power
}
}
}
}
`,
},
{
headers: {
Authorization: "Bearer " + localStorage.getItem("accessToken"),
},
{
headers: {
Authorization: "Bearer " + localStorage.getItem("accessToken"),
},
}
);
}
);
const dataCenter = response?.data?.data?.dataCenter;
console.log('getDataCenterVMs: Data center response:', dataCenter);
console.log("getDataCenterVMs: Data center response:", dataCenter);
let allVMs = [];
if (dataCenter && dataCenter.projects) {
dataCenter.projects.forEach(project => {
if (project.physicalMachines) {
project.physicalMachines.forEach(pm => {
if (pm.vms) {
allVMs = allVMs.concat(pm.vms);
}
});
if (dataCenter && dataCenter.physicalMachines) {
dataCenter.physicalMachines.forEach((pm) => {
if (pm.vms) {
allVMs = allVMs.concat(pm.vms);
}
});
}
console.log('getDataCenterVMs: Found VMs:', allVMs);
console.log("getDataCenterVMs: Found VMs:", allVMs);
resolve(allVMs);
} catch (error) {
console.error("Error fetching VMs by data center:", error);

View File

@@ -1,6 +1,6 @@
import ApplicationService from "../../../services/ApplicationService";
export const getVMEmissionSummary = () => {
export const getVMEmissionSummary = (datacenterId) => {
return async (dispatch) => {
try {
const response = await ApplicationService.http()
@@ -8,8 +8,8 @@ export const getVMEmissionSummary = () => {
"/graphql",
{
query: `
{
vmEmissionSummary {
query GetVMEmissions($datacenterId: ID) {
vmEmissionSummary(datacenterId: $datacenterId) {
vmId
vmName
vmPower
@@ -17,7 +17,7 @@ export const getVMEmissionSummary = () => {
totalEmission
createdDate
physicalMachine
project
cloudSystem
dataCenter
co2
ch4
@@ -25,7 +25,10 @@ export const getVMEmissionSummary = () => {
reportGeneratedTime
}
}
`
`,
variables: {
datacenterId: datacenterId
}
},
{
headers: {
@@ -125,11 +128,12 @@ export const getMainDataTablesWithPaginate = (data) => {
{
paginateMainDataTables(
pagination: { page: 0, rowsPerPage: 100 }
criteria: { deleted: false }
criteria: { deleted: false, hasVm: true }
sortBy: [{ field: "createdDate", direction: DESC }]
) {
content {
id
year
sector {
id
tag
@@ -138,11 +142,40 @@ export const getMainDataTablesWithPaginate = (data) => {
id
tag
}
activitySubUnit {
id
tag
}
emissionSource {
id
tag
}
emissionScope {
id
tag
}
co2
ch4
n2o
totalEmission
createdDate
vm {
id
vmName
state
power
calcOn
hostingPm
host
flavorName
tag
config {
id
cpu
ram
disk
}
}
}
pageInfo {
totalElements

View File

@@ -0,0 +1,33 @@
const initialState = {
emissionScopes: [],
loading: false,
error: null,
};
const emissionScopeReducer = (state = initialState, action) => {
switch (action.type) {
case "GET_EMISSION_SCOPES_LOADING":
return {
...state,
loading: true,
error: null,
};
case "GET_EMISSION_SCOPES_SUCCESS":
return {
...state,
loading: false,
emissionScopes: action.payload,
error: null,
};
case "GET_EMISSION_SCOPES_ERROR":
return {
...state,
loading: false,
error: action.payload.error,
};
default:
return state;
}
};
export default emissionScopeReducer;

View File

@@ -27,6 +27,7 @@ import surveys from "./surveys";
import uploads from "./upload";
import mailSettings from "./mailSettings";
import dataCenter from "./dataCenter";
import emissionScope from "./emissionScope";
const rootReducer = combineReducers({
accessToken,
@@ -57,6 +58,7 @@ const rootReducer = combineReducers({
uploads,
mailSettings,
dataCenter,
emissionScope,
});
export default rootReducer;

View File

@@ -25,7 +25,7 @@ const Routes = [
display: permissionCheck("paginate_users_get"),
},
{
path: "/organizasyonlar",
path: "/veri-merkezi-yonetimi",
component: lazy(() => import("../../views/DataCenterManagement")),
display: permissionCheck("paginate_datacenters_get") ||
permissionCheck("data_center_create") ||
@@ -74,7 +74,7 @@ const Routes = [
display: permissionCheck("activity_sub_units_get"),
},
{
path: "/verimerkezi",
path: "/veri-merkezi-genel",
component: lazy(() => import("../../views/DataCenter")),
},
{

View File

@@ -18,17 +18,16 @@ const DataCenter = () => {
const [refreshInterval, setRefreshInterval] = useState(null);
const getAllPhysicalMachines = (dataCenter) => {
if (!dataCenter.projects) return [];
return dataCenter.projects.flatMap(project =>
project.physicalMachines || []
);
// Physical machines are directly in the dataCenter object, not in projects
const pms = dataCenter.physicalMachines || [];
return pms;
};
// Table columns following your pattern
const initialColumns = [
{
name: "Number",
selector: (row) => row.number,
name: "External ID",
selector: (row) => row.externalId,
sortable: true,
minWidth: "100px",
},
@@ -38,19 +37,33 @@ const DataCenter = () => {
sortable: true,
minWidth: "200px",
},
// Projects
{
name: "Projects",
selector: (row) =>
(row.projects || []).map((p) => p.name).join(", "),
sortable: false,
minWidth: "200px",
cell: (row) => (
<span>
{(row.projects || []).map((p) => p.name).join(", ") || "-"}
</span>
),
},
// Projects - Based on API response, this field might not exist or be structured differently
// {
// name: "Projects",
// selector: (row) => row.projects?.length || 0,
// sortable: true,
// minWidth: "200px",
// cell: (row) => (
// <div>
// {row.projects && row.projects.length > 0 ? (
// <div className="d-flex flex-column">
// {row.projects.map((project, index) => (
// <div
// key={project.id}
// className={`badge badge-light-primary ${
// index > 0 ? "mt-1" : ""
// }`}
// >
// {project.name}
// </div>
// ))}
// </div>
// ) : (
// <span className="text-muted">-</span>
// )}
// </div>
// ),
// },
// Physical Machines
{
name: "Physical Machines",
@@ -68,26 +81,55 @@ const DataCenter = () => {
},
},
{
name: "Total Active VMs",
name: "Virtual Machines",
selector: (row) => {
const pms = getAllPhysicalMachines(row);
return pms.reduce(
(total, pm) => total + (pm.vms?.active?.length || 0),
0
const vms = pms.reduce(
(acc, pm) => {
if (!pm.vms) return acc;
return {
active:
acc.active +
pm.vms.filter((vm) => vm.state?.toLowerCase() === "active")
.length,
total: acc.total + pm.vms.length,
};
},
{ active: 0, total: 0 }
);
return vms.total;
},
sortable: true,
minWidth: "150px",
minWidth: "200px",
cell: (row) => {
const pms = getAllPhysicalMachines(row);
const totalVMs = pms.reduce(
(total, pm) => total + (pm.vms?.active?.length || 0),
0
const vms = pms.reduce(
(acc, pm) => {
if (!pm.vms) return acc;
return {
active:
acc.active +
pm.vms.filter((vm) => vm.state?.toLowerCase() === "active")
.length,
total: acc.total + pm.vms.length,
};
},
{ active: 0, total: 0 }
);
return (
<div className="d-flex align-items-center">
<Monitor size={16} className="mr-1" />
<span>{totalVMs}</span>
<Monitor size={16} className="mr-2" />
<div>
<div className="font-weight-bold">{vms.total} Total</div>
<div className="small">
<span className="text-success">{vms.active} Active</span>
<span className="text-muted mx-1"></span>
<span className="text-warning">
{vms.total - vms.active} Inactive
</span>
</div>
</div>
</div>
);
},
@@ -138,76 +180,112 @@ const DataCenter = () => {
<div key={pm.id} className="mb-3 border rounded p-3">
<h6 className="text-primary">{pm.name}</h6>
{/* Active VMs */}
<p className="mb-2">
<strong>Active VMs ({pm.vms?.active?.length || 0}):</strong>
</p>
{pm.vms?.active?.length > 0 ? (
<div className="ml-3">
{pm.vms.active.map((vm) => (
<div
key={vm.id}
className="mb-2 p-2 border-left border-success"
>
<div className="row">
<div className="col-md-3">
<strong>Name:</strong> {vm.name}
</div>
<div className="col-md-2">
<strong>Status:</strong>
<span className="badge badge-success ml-1">
{vm.status}
</span>
</div>
<div className="col-md-2">
<strong>Power:</strong> {vm.power}
</div>
<div className="col-md-5">
<strong>Config:</strong> CPU: {vm.config?.cpu}, RAM:{" "}
{vm.config?.ram}, Disk: {vm.config?.disk}
</div>
</div>
</div>
))}
{/* All VMs */}
<div className="mb-2 d-flex justify-content-between align-items-center">
<h6 className="mb-0">
<Monitor size={16} className="mr-1" />
Virtual Machines ({pm.vms?.length || 0})
</h6>
</div>
{pm.vms?.length > 0 ? (
<div className="table-responsive mt-2">
<table className="table table-bordered table-hover">
<thead className="thead-light">
<tr>
<th>Name</th>
<th>Status</th>
<th>Power (W)</th>
<th>Configuration</th>
<th>Host</th>
</tr>
</thead>
<tbody>
{pm.vms.map((vm) => {
const isActive =
vm.state && ["ACTIVE", "active"].includes(vm.state);
return (
<tr key={vm.id}>
<td>
<span className="font-weight-bold">
{vm.vmName || vm.vm_name}
</span>
</td>
<td>
<div
className={`d-inline-block px-2 py-1 rounded-pill ${
isActive
? "bg-light-success text-success"
: "bg-light-warning text-warning"
}`}
>
{vm.state}
</div>
</td>
<td>
{vm.power ? (
<span>{vm.power.toFixed(2)}</span>
) : (
<span className="text-muted">-</span>
)}
</td>
<td>
<div className="d-flex align-items-center">
<div className="mr-3">
<small className="text-muted d-block">
CPU
</small>
<span>
{vm.config?.cpu ||
(vm.confg && vm.confg[1]) ||
"-"}
</span>
</div>
<div className="mr-3">
<small className="text-muted d-block">
RAM
</small>
<span>
{vm.config?.ram ||
(vm.confg && vm.confg[2]) ||
"-"}{" "}
GB
</span>
</div>
<div>
<small className="text-muted d-block">
Disk
</small>
<span>
{vm.config?.disk ||
(vm.confg && vm.confg[3]) ||
"-"}{" "}
GB
</span>
</div>
</div>
</td>
<td>
<div className="d-flex align-items-center">
<Server size={14} className="mr-1" />
<span>
{vm.host ||
vm.hostingPm ||
(vm.confg && vm.confg[4]) ||
"-"}
</span>
</div>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
) : (
<p className="text-muted ml-3">No active VMs</p>
)}
{/* Inactive VMs */}
<p className="mb-2 mt-3">
<strong>Inactive VMs ({pm.vms?.inactive?.length || 0}):</strong>
</p>
{pm.vms?.inactive?.length > 0 ? (
<div className="ml-3">
{pm.vms.inactive.map((vm) => (
<div
key={vm.id}
className="mb-2 p-2 border-left border-warning"
>
<div className="row">
<div className="col-md-3">
<strong>Name:</strong> {vm.name}
</div>
<div className="col-md-2">
<strong>Status:</strong>
<span className="badge badge-warning ml-1">
{vm.status}
</span>
</div>
<div className="col-md-2">
<strong>Power:</strong> {vm.power}
</div>
<div className="col-md-5">
<strong>Config:</strong> CPU: {vm.config?.cpu}, RAM:{" "}
{vm.config?.ram}, Disk: {vm.config?.disk}
</div>
</div>
</div>
))}
<div className="text-center p-3 bg-light-secondary rounded">
<Monitor size={24} className="text-muted mb-1" />
<p className="text-muted mb-0">No virtual machines found</p>
</div>
) : (
<p className="text-muted ml-3">No inactive VMs</p>
)}
</div>
))}
@@ -215,8 +293,6 @@ const DataCenter = () => {
);
};
return (
<div style={{ marginTop: "2%" }}>
<Card>

File diff suppressed because it is too large Load Diff

View File

@@ -1,101 +1,157 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useMemo } from "react";
import { MaterialReactTable } from "material-react-table";
import { useDispatch, useSelector } from "react-redux";
import { useTranslation } from "react-i18next";
import { Card, CardHeader, CardTitle, Alert } from "reactstrap";
import {
Card,
CardHeader,
CardTitle,
Alert,
Row,
Col,
Label,
} from "reactstrap";
import { getVMEmissionSummary } from "../../redux/actions/mainDataTables/index";
import { getDataCenters } from "../../redux/actions/dataCenter";
import { editNumbers } from "../../components/edit-numbers";
import Select from "react-select";
function MainDataTables() {
const { t } = useTranslation();
const dispatch = useDispatch();
const mainDataTablesStore = useSelector((state) => state.mainDataTables);
const dataCenterStore = useSelector((state) => state.dataCenter);
const [error, setError] = useState(null);
const [selectedDataCenter, setSelectedDataCenter] = useState(null);
const [dataCenterOptions, setDataCenterOptions] = useState([]);
const [loading, setLoading] = useState(false);
// Fetch datacenters on component mount
useEffect(() => {
try {
// Fetch VM emission data
dispatch(getVMEmissionSummary());
} catch (err) {
console.error('Error in MainDataTables:', err);
setError(err.message);
}
dispatch(getDataCenters());
}, [dispatch]);
// Debug log for store data
// Update datacenter options when datacenters are loaded
useEffect(() => {
console.log('Current store data:', mainDataTablesStore);
}, [mainDataTablesStore]);
if (dataCenterStore?.dataCenters?.length > 0) {
const options = dataCenterStore.dataCenters.map((dataCenter) => ({
value: dataCenter.id,
label: dataCenter.dataCenter,
externalId: dataCenter.externalId,
}));
setDataCenterOptions(options);
}
}, [dataCenterStore?.dataCenters]);
const columns = [
{
header: "VM ID",
accessorKey: "vmId",
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "Data Center",
accessorKey: "dataCenter",
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "Project",
accessorKey: "project",
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "Physical Machine",
accessorKey: "physicalMachine",
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "Virtual Machine",
accessorKey: "vmName",
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "VM Power (W)",
accessorKey: "vmPower",
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "VM Status",
accessorKey: "vmStatus",
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "Total Emissions",
accessorKey: "totalEmission",
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "CO2",
accessorKey: "co2",
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "CH4",
accessorKey: "ch4",
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "N2O",
accessorKey: "n2o",
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "Created Date",
accessorKey: "createdDate",
Cell: ({ cell }) => (
<span>
{cell.getValue() ? new Date(cell.getValue()).toLocaleString() : "-"}
</span>
),
},
];
// Fetch VM emission data when datacenter is selected
useEffect(() => {
if (selectedDataCenter?.value) {
const fetchData = async () => {
try {
setLoading(true);
setError(null);
await dispatch(getVMEmissionSummary(selectedDataCenter.value));
} catch (err) {
console.error("Error in MainDataTables:", err);
setError(err.message);
} finally {
setLoading(false);
}
};
fetchData();
}
}, [selectedDataCenter, dispatch]);
const tableData = mainDataTablesStore?.vmEmissionSummary || [];
console.log('VM Emission data:', tableData);
// Memoize columns to prevent re-renders
const columns = useMemo(
() => [
{
header: t("VM ID"),
accessorKey: "vmId",
size: 150,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: t("VM Name"),
accessorKey: "vmName",
size: 200,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: t("VM Power"),
accessorKey: "vmPower",
size: 120,
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: t("VM Status"),
accessorKey: "vmStatus",
size: 100,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: t("Total Emission"),
accessorKey: "totalEmission",
size: 150,
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: t("Physical Machine"),
accessorKey: "physicalMachine",
size: 150,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: t("Cloud System"),
accessorKey: "cloudSystem",
size: 150,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: t("Data Center"),
accessorKey: "dataCenter",
size: 150,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "CO2",
accessorKey: "co2",
size: 100,
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "CH4",
accessorKey: "ch4",
size: 100,
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "N2O",
accessorKey: "n2o",
size: 100,
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: t("Created Date"),
accessorKey: "createdDate",
size: 180,
Cell: ({ cell }) => (
<span>
{cell.getValue() ? new Date(cell.getValue()).toLocaleString() : "-"}
</span>
),
sortable: true,
},
],
[t]
);
// Memoize table data to prevent unnecessary re-renders
const tableData = useMemo(() => {
const data = mainDataTablesStore?.vmEmissionSummary || [];
console.log("VM Emission data count:", data.length);
return data;
}, [mainDataTablesStore?.vmEmissionSummary]);
if (error) {
return (
@@ -109,37 +165,109 @@ function MainDataTables() {
<div style={{ marginTop: "2%" }}>
<Card>
<CardHeader className="border-bottom">
<CardTitle tag="h4">{t("Carbon Emission Data")}</CardTitle>
<CardTitle tag="h4">{t("Raw Data")}</CardTitle>
{tableData.length > 0 && (
<small className="text-muted">
{tableData.length} records loaded
</small>
)}
</CardHeader>
<MaterialReactTable
columns={columns}
data={tableData}
enableColumnFilters={true}
enableFilters={true}
enableGlobalFilter={true}
enablePagination={true}
enableColumnResizing={true}
enableStickyHeader={true}
muiTableContainerProps={{ sx: { maxHeight: 'calc(100vh - 180px)' } }}
muiTableProps={{
sx: {
tableLayout: 'auto',
},
}}
initialState={{
pagination: {
pageSize: 100,
pageIndex: 0
},
sorting: [
{ id: 'dataCenter', desc: false }
],
density: 'compact'
}}
state={{
isLoading: !mainDataTablesStore?.vmEmissionSummary
}}
/>
{/* Datacenter Selection */}
<div className="p-3 border-bottom">
<Row>
<Col md="6">
<Label for="datacenter-select">{t("Data Center")}</Label>
<Select
id="datacenter-select"
value={selectedDataCenter}
onChange={setSelectedDataCenter}
options={dataCenterOptions}
placeholder={t("Select a data center...")}
isClearable
isSearchable
isLoading={dataCenterStore?.loading}
noOptionsMessage={() => t("No data centers available")}
styles={{
menu: (provided) => ({
...provided,
zIndex: 9999, // Ensure dropdown appears above other elements
}),
}}
menuPortalTarget={document.body} // Render dropdown in body to avoid container overflow
/>
</Col>
</Row>
</div>
{selectedDataCenter ? (
<MaterialReactTable
columns={columns}
data={tableData}
// Performance optimizations for large datasets
enableColumnFilters={true}
enableFilters={true}
enableGlobalFilter={true}
enablePagination={true}
enableColumnResizing={true} // Disable resizing for better performance
enableStickyHeader={true}
enableRowVirtualization={true} // Enable virtualization for large datasets
enableColumnVirtualization={false} // Keep columns visible
// Pagination settings for large datasets
initialState={{
pagination: {
pageSize: 100, // Reduce page size for better performance
pageIndex: 0,
},
sorting: [{ id: "createdDate", desc: true }],
density: "compact",
}}
// Performance-optimized table props
muiTableContainerProps={{
sx: {
maxHeight: "calc(100vh - 250px)",
minHeight: "400px",
},
}}
muiTableProps={{
sx: {
tableLayout: "fixed", // Better performance with fixed layout
},
}}
// Pagination options
muiTablePaginationProps={{
rowsPerPageOptions: [10, 25, 50, 100],
showFirstButton: true,
showLastButton: true,
}}
// Loading and error states
state={{
isLoading: loading || mainDataTablesStore?.loading,
showProgressBars: loading || mainDataTablesStore?.loading,
showSkeletons: loading || mainDataTablesStore?.loading,
}}
// Disable features that can slow down large tables
enableRowSelection={false}
enableColumnOrdering={true}
enableColumnDragging={false}
enableDensityToggle={false}
enableFullScreenToggle={false}
// Custom loading overlay
renderProgressBarCell={({ cell }) => (
<div
style={{
width: "100%",
height: "20px",
backgroundColor: "#f0f0f0",
}}
/>
)}
/>
) : (
<div className="p-4 text-center text-muted">
{t("Please select a data center to view raw data")}
</div>
)}
</Card>
</div>
);

View File

@@ -32,15 +32,87 @@ import { getCities } from "../redux/actions/cities";
import { v4 as uuidv4 } from "uuid";
import { getCity } from "../redux/actions/city";
import { getDistrict } from "../redux/actions/district";
import {
getOrganisations,
getOrganisationById,
} from "../redux/actions/organisations";
// import {
// getOrganisations,
// getOrganisationById,
// } from "../redux/actions/organisations";
import { getAreasWithCriteria } from "../redux/actions/areas";
import { ChromePicker } from "react-color";
import { customFilterForSelect } from "../utility/Utils";
import { permissionCheck } from "../components/permission-check";
import { getDataCenters } from "../redux/actions/dataCenter";
import L from "leaflet";
// Custom data center icon
const dataCenterIcon = new L.Icon({
iconUrl:
"data:image/svg+xml;base64," +
btoa(`
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<defs>
<linearGradient id="serverGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#4A90E2;stop-opacity:1" />
<stop offset="100%" style="stop-color:#2E5BBA;stop-opacity:1" />
</linearGradient>
<linearGradient id="rackGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#F5F5F5;stop-opacity:1" />
<stop offset="100%" style="stop-color:#E0E0E0;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Main server rack -->
<rect x="8" y="4" width="32" height="40" rx="2" ry="2" fill="url(#rackGradient)" stroke="#B0B0B0" stroke-width="1"/>
<!-- Server units -->
<rect x="10" y="6" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<rect x="10" y="12" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<rect x="10" y="18" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<rect x="10" y="24" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<rect x="10" y="30" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<rect x="10" y="36" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<!-- LED indicators -->
<circle cx="13" cy="8" r="0.8" fill="#00FF00"/>
<circle cx="13" cy="14" r="0.8" fill="#00FF00"/>
<circle cx="13" cy="20" r="0.8" fill="#FFFF00"/>
<circle cx="13" cy="26" r="0.8" fill="#00FF00"/>
<circle cx="13" cy="32" r="0.8" fill="#FF0000"/>
<circle cx="13" cy="38" r="0.8" fill="#00FF00"/>
<!-- Power indicators -->
<circle cx="35" cy="8" r="0.6" fill="#0080FF"/>
<circle cx="35" cy="14" r="0.6" fill="#0080FF"/>
<circle cx="35" cy="20" r="0.6" fill="#0080FF"/>
<circle cx="35" cy="26" r="0.6" fill="#0080FF"/>
<circle cx="35" cy="32" r="0.6" fill="#0080FF"/>
<circle cx="35" cy="38" r="0.6" fill="#0080FF"/>
<!-- Ventilation grilles -->
<rect x="16" y="7" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="8.5" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="13" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="14.5" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="19" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="20.5" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="25" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="26.5" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="31" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="32.5" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="37" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="38.5" width="16" height="0.5" fill="#1A4A8A"/>
<!-- Base/feet -->
<rect x="6" y="42" width="4" height="2" rx="1" fill="#808080"/>
<rect x="38" y="42" width="4" height="2" rx="1" fill="#808080"/>
<!-- Shadow -->
<ellipse cx="24" cy="45" rx="18" ry="2" fill="#000000" opacity="0.2"/>
</svg>
`),
iconSize: [48, 48],
iconAnchor: [18, 36],
popupAnchor: [0, -36],
});
const ColorPicker = ({ selectedColors, setSelectedColors, index }) => {
const [showColorPicker, setShowColorPicker] = useState(false);
@@ -117,20 +189,20 @@ const Map = () => {
const citiesStore = useSelector((state) => state.cities);
const cityStore = useSelector((state) => state.city);
const districtStore = useSelector((state) => state.district);
const OrganisationsStore = useSelector((state) => state.organizations);
// const OrganisationsStore = useSelector((state) => state.organizations);
const areasStore = useSelector((state) => state.areas);
const dataCenterStore = useSelector((state) => state.dataCenter);
const [cities, setCities] = useState([]);
const [districts, setDistricts] = useState([]);
const [neighborhoods, setNeighborhoods] = useState([]);
const [organizationOptions, setOrganizationOptions] = useState([]);
const organizationId = localStorage.getItem("organizationId");
const roleTag = localStorage.getItem("roleTag");
const [selectedOrganization, setSelectedOrganization] = useState({
label: localStorage.getItem("organizationName"),
value: organizationId,
});
// const [organizationOptions, setOrganizationOptions] = useState([]);
// const organizationId = localStorage.getItem("organizationId");
// const roleTag = localStorage.getItem("roleTag");
// const [selectedOrganization, setSelectedOrganization] = useState({
// label: localStorage.getItem("organizationName"),
// value: organizationId,
// });
const [areasOptions, setAreasOptions] = useState([]);
const [done, setDone] = useState(false);
@@ -146,7 +218,7 @@ const Map = () => {
const [showDataInputModal, setShowDataInputModal] = useState(false);
const [inputData, setInputData] = useState({
organization: selectedOrganization,
// organization: selectedOrganization,
});
const [referance, setReferance] = useState(
Number(localStorage.getItem("referance")) || 1000
@@ -176,15 +248,17 @@ const Map = () => {
dispatch(getDataCenters());
}, []);
useEffect(() => {
if (selectedOrganization?.value != "undefined") {
dispatch(getAreasWithCriteria(selectedOrganization.value));
}
}, [selectedOrganization]);
// useEffect(() => {
// if (selectedOrganization?.value != "undefined") {
// dispatch(getAreasWithCriteria(selectedOrganization.value));
// }
// }, [selectedOrganization]);
useEffect(() => {
setAreasOptions([]);
// Load all areas without organization filter for now
// You may want to add organization filtering back later if needed
const citiesOptions =
areasStore?.areasWithCriteria
?.map((area) =>
@@ -235,13 +309,13 @@ const Map = () => {
]);
}, [areasStore]);
useEffect(() => {
if (roleTag === "SUPER_ADMIN") {
dispatch(getOrganisations());
} else {
dispatch(getOrganisationById(organizationId));
}
}, []);
// useEffect(() => {
// if (roleTag === "SUPER_ADMIN") {
// dispatch(getOrganisations());
// } else {
// dispatch(getOrganisationById(organizationId));
// }
// }, []);
const handleDataInputButtonPressed = ({ area, type }) => {
const areaName =
@@ -348,38 +422,38 @@ const Map = () => {
});
}, [selectedDistrict, districtStore?.district, year.value]);
useEffect(() => {
let organizationOptions = [];
// useEffect(() => {
// let organizationOptions = [];
if (
OrganisationsStore.organization &&
OrganisationsStore.organization.length !== 0
) {
organizationOptions.push({
value: OrganisationsStore.organization.id,
label: OrganisationsStore.organization.tag,
});
// if (
// OrganisationsStore.organization &&
// OrganisationsStore.organization.length !== 0
// ) {
// organizationOptions.push({
// value: OrganisationsStore.organization.id,
// label: OrganisationsStore.organization.tag,
// });
if (OrganisationsStore.organization.children) {
organizationOptions = [
...organizationOptions,
...OrganisationsStore.organization.children.map((organization) => ({
value: organization.child.id,
label: organization.child.tag,
})),
];
}
} else {
organizationOptions = OrganisationsStore.dataOrganization.map(
(organization) => ({
value: organization.id,
label: organization.tag,
})
);
}
// if (OrganisationsStore.organization.children) {
// organizationOptions = [
// ...organizationOptions,
// ...OrganisationsStore.organization.children.map((organization) => ({
// value: organization.child.id,
// label: organization.child.tag,
// })),
// ];
// }
// } else {
// organizationOptions = OrganisationsStore.dataOrganization.map(
// (organization) => ({
// value: organization.id,
// label: organization.tag,
// })
// );
// }
setOrganizationOptions(organizationOptions);
}, [OrganisationsStore]);
// setOrganizationOptions(organizationOptions);
// }, [OrganisationsStore]);
const renderDataInputModal = () => {
return (
@@ -623,29 +697,60 @@ const Map = () => {
<LayerGroup>
{dataCenterStore.dataCenters.map((dc) => {
if (!dc.latitude || !dc.longitude) return null;
return (
<Marker
key={dc.id}
<Marker
key={dc.id}
position={[dc.latitude, dc.longitude]}
icon={dataCenterIcon}
>
<Popup>
<div className="data-center-popup">
<h5 className="mb-2">{dc.dataCenter}</h5>
<p className="mb-1"><strong>{t('DataCenter.number')}:</strong> {dc.number}</p>
<p className="mb-1"><strong>{t('DataCenter.externalId')}:</strong> {dc.externalId}</p>
<p className="mb-1"><strong>{t('DataCenter.city')}:</strong> {dc.area?.cities?.map(city => city.name).join(', ') || "-"}</p>
{dc.area && <p className="mb-1"><strong>{t('Area')}:</strong> {dc.area.tag}</p>}
{dc.projects?.length > 0 && (
<h5 className="mb-2 text-primary">{dc.dataCenter}</h5>
<div className="mb-2">
<p className="mb-1">
<strong>{t('Projects')}:</strong> {dc.projects.length}
<strong>{t("DataCenter.city")}:</strong>{" "}
<span>{dc.city?.name || "-"}</span>
</p>
{dc.address && (
<p className="mb-1 small text-muted">
<strong>{t("Address")}:</strong> {dc.address}
</p>
)}
</div>
<p className="mb-1">
<strong>{t("DataCenter.number")}:</strong> {dc.number}
</p>
<p className="mb-1">
<strong>{t("DataCenter.externalId")}:</strong>{" "}
{dc.externalId}
</p>
{dc.area && (
<p className="mb-1">
<strong>{t("Area")}:</strong> {dc.area.tag}
</p>
)}
{dc.physicalMachines?.length > 0 && (
<p className="mb-1">
<strong>{t("Physical Machines")}:</strong>{" "}
<span className="badge badge-secondary">
{dc.physicalMachines.length}
</span>
</p>
)}
{dc.dataCenterEmissionSources?.length > 0 && (
<p className="mb-1">
<strong>{t("EmissionSources.emissionSources")}:</strong>{" "}
<span className="badge badge-info">
{dc.dataCenterEmissionSources.length}
</span>
</p>
)}
{dc.ayposURL && (
<Button
className="w-100 mb-1"
color="primary"
onClick={() => window.open(dc.ayposURL, '_blank')}
onClick={() => window.open(dc.ayposURL, "_blank")}
>
Dashboard
</Button>
@@ -699,7 +804,9 @@ const Map = () => {
setDistrictView(true);
setZoom(8.0);
let convertCordinates = convertCoordinates(city.coordinates);
let convertCordinates = convertCoordinates(
city.coordinates
);
let length = convertCordinates[0][0][0].length;
let mlength = ((length + 1) / 2).toFixed(0);
let lat1 = convertCordinates[0][0][0][0];
@@ -710,7 +817,7 @@ const Map = () => {
lat: ((lat1 + lat2) / 2).toFixed(2),
lng: ((lng1 + lng2) / 2).toFixed(2),
});
}
},
}}
>
<Tooltip permanent direction="center">