diff --git a/src/main/java/com/pump/PumpApplication.java b/src/main/java/com/pump/PumpApplication.java
index b85855e517255a38004dd21f122cc96ba1fe2810..9173ce063ffb52cffac3ef56e980fb7d27513c6a 100644
--- a/src/main/java/com/pump/PumpApplication.java
+++ b/src/main/java/com/pump/PumpApplication.java
@@ -29,7 +29,7 @@ public class PumpApplication {
         return _ -> {
             log.info("Starting application");
 
-            gitPump.run();
+            jiraPump.run();
 
             log.info("Application ended");
         };
diff --git a/src/main/java/com/pump/jira/JiraPump.java b/src/main/java/com/pump/jira/JiraPump.java
index 89a8f3c72182df1a3784ee5f0d04c5110d6d7398..7499af4ffef0b8b90dc42063fd08f202740750be 100644
--- a/src/main/java/com/pump/jira/JiraPump.java
+++ b/src/main/java/com/pump/jira/JiraPump.java
@@ -8,12 +8,22 @@ import com.atlassian.jira.rest.client.api.domain.SearchResult;
 import com.atlassian.jira.rest.client.auth.AnonymousAuthenticationHandler;
 import com.atlassian.jira.rest.client.auth.BasicHttpAuthenticationHandler;
 import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory;
+import com.pump.jira.service.AttachmentService;
+import com.pump.jira.service.IssueService;
+import com.pump.jira.service.ProjectService;
+import com.pump.jira.service.UserService;
+import com.pump.jira.service.VersionService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -21,6 +31,7 @@ import java.util.stream.StreamSupport;
 
 @Slf4j
 @Service
+@RequiredArgsConstructor
 public class JiraPump {
 
     @Value("${jira.url}")
@@ -41,19 +52,34 @@ public class JiraPump {
     @Value("${jira.timeout.seconds}")
     private int timeoutSeconds;
 
+    private final UserService userService;
+    private final VersionService versionService;
+    private final IssueService issueService;
+    private final ProjectService projectService;
+    private final AttachmentService attachmentService;
+
+    ///
     public void run() {
         log.info("Starting JiraPump for project {}...", projectKey);
         JiraRestClient restClient = null;
 
         try {
             restClient = createJiraRestClient();
-            Project project = fetchProjectDetails(restClient);
-            fetchProjectVersions(project);
-            fetchProjectComponents(project);
-            fetchProjectIssues(restClient);
-            fetchRecentActivity(restClient);
-            fetchAssignedIssues(restClient);
-            fetchCriticalIssues(restClient);
+            attachmentService.fetchAttachments(restClient);
+
+//            TODO these methods will be moved into separate services
+//            Project project = fetchProjectDetails(restClient);
+//            fetchProjectVersions(project);
+//            fetchProjectComponents(project);
+//            fetchProjectIssues(restClient);
+//            fetchRecentActivity(restClient);
+//            fetchAssignedIssues(restClient);
+//            fetchCriticalIssues(restClient);
+//            fetchUserInformation(restClient);
+//            fetchIssueTypeStatistics(restClient);
+//            fetchWorkflowInformation(restClient);
+//            fetchProjectRoles(restClient);
+            fetchCustomFieldValues(restClient, "Story Points");
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
             log.error("Interrupted while fetching data from Jira", e);
@@ -198,4 +224,119 @@ public class JiraPump {
             }
         }
     }
+
+    private void fetchUserInformation(JiraRestClient restClient)
+        throws InterruptedException, ExecutionException, TimeoutException {
+        log.info("Fetching active contributors in project");
+
+        String jqlActive = "project = " + projectKey + " ORDER BY updated DESC";
+        SearchResult result = restClient.getSearchClient().searchJql(jqlActive, 50, 0, null)
+                                        .get(timeoutSeconds, TimeUnit.SECONDS);
+
+        Set<String> usernames = new HashSet<>();
+        result.getIssues().forEach(issue -> {
+            if (issue.getReporter() != null) {
+                usernames.add(issue.getReporter().getName());
+            }
+            if (issue.getAssignee() != null) {
+                usernames.add(issue.getAssignee().getName());
+            }
+        });
+
+        log.info("Found {} active contributors", usernames.size());
+        for (String username : usernames) {
+            try {
+                com.atlassian.jira.rest.client.api.domain.User user =
+                    restClient.getUserClient().getUser(username)
+                              .get(timeoutSeconds, TimeUnit.SECONDS);
+                log.info("  User: {} ({}), Email: {}, Active: {}",
+                    user.getDisplayName(),
+                    user.getName(),
+                    user.getEmailAddress(),
+                    user.isActive());
+            } catch (Exception e) {
+                log.warn("Could not fetch details for user: {}", username);
+            }
+        }
+    }
+
+    private void fetchIssueTypeStatistics(JiraRestClient restClient)
+        throws InterruptedException, ExecutionException, TimeoutException {
+        log.info("Fetching issue type statistics");
+
+        Project project = restClient.getProjectClient().getProject(projectKey)
+                                    .get(timeoutSeconds, TimeUnit.SECONDS);
+
+        project.getIssueTypes().forEach(issueType -> {
+            try {
+                String jql = "project = " + projectKey + " AND issuetype = \"" + issueType.getName() + "\"";
+                SearchResult result = restClient.getSearchClient().searchJql(jql, 0, 0, null)
+                                                .get(timeoutSeconds, TimeUnit.SECONDS);
+
+                log.info("  {} - {} issues", issueType.getName(), result.getTotal());
+            } catch (Exception e) {
+                log.warn("Error counting issues of type {}: {}", issueType.getName(), e.getMessage());
+            }
+        });
+    }
+
+    private void fetchWorkflowInformation(JiraRestClient restClient)
+        throws InterruptedException, ExecutionException, TimeoutException {
+        log.info("Fetching workflow status information");
+
+        String jql = "project = " + projectKey + " ORDER BY created DESC";
+        SearchResult result = restClient.getSearchClient().searchJql(jql, 1, 0, null)
+                                        .get(timeoutSeconds, TimeUnit.SECONDS);
+
+        if (result.getTotal() > 0) {
+            Issue sampleIssue = result.getIssues().iterator().next();
+
+            log.info("Status categories in workflow:");
+            Map<String, Integer> statusCounts = new HashMap<>();
+
+            // Now get all issues and count by status
+            String jqlAll = "project = " + projectKey;
+            SearchResult allResult = restClient.getSearchClient().searchJql(jqlAll, maxIssues, 0, null)
+                                               .get(timeoutSeconds, TimeUnit.SECONDS);
+
+            allResult.getIssues().forEach(issue -> {
+                String status = issue.getStatus().getName();
+                statusCounts.put(status, statusCounts.getOrDefault(status, 0) + 1);
+            });
+
+            statusCounts.forEach((status, count) ->
+                log.info("  {} - {} issues", status, count)
+            );
+        }
+    }
+
+    private void fetchProjectRoles(JiraRestClient restClient)
+        throws InterruptedException, ExecutionException, TimeoutException {
+        log.info("Fetching project roles");
+
+        final String roleEndpoint = jiraApiUrl + "/rest/api/2/project/" + projectKey + "/role";
+
+        log.info("Note: Project role details require custom REST API implementation");
+    }
+
+    private void fetchCustomFieldValues(JiraRestClient restClient, String customFieldName)
+        throws InterruptedException, ExecutionException, TimeoutException {
+        log.info("Fetching values for custom field: {}", customFieldName);
+
+        String jql = "project = " + projectKey;
+        SearchResult result = restClient.getSearchClient().searchJql(jql, maxIssues, 0, null)
+                                        .get(timeoutSeconds, TimeUnit.SECONDS);
+
+        result.getIssues().forEach(issue -> {
+            issue.getFields().forEach(field -> {
+                if (field.getName().equals(customFieldName)) {
+                    log.info("  [{}] {} - {}: {}",
+                        issue.getKey(),
+                        issue.getSummary(),
+                        customFieldName,
+                        field.getValue() != null ? field.getValue().toString() : "null");
+                }
+            });
+        });
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/com/pump/jira/service/AttachmentService.java b/src/main/java/com/pump/jira/service/AttachmentService.java
new file mode 100644
index 0000000000000000000000000000000000000000..691bfd92842f90e461771a2d01e4b91becee85cd
--- /dev/null
+++ b/src/main/java/com/pump/jira/service/AttachmentService.java
@@ -0,0 +1,90 @@
+package com.pump.jira.service;
+
+
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.domain.Attachment;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.SearchResult;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.StreamSupport;
+
+@Slf4j
+@Service
+public class AttachmentService {
+
+    @Value("${jira.project.key}")
+    private String projectKey;
+
+    @Value("${jira.max.issues:100}")
+    private int maxIssues;
+
+    @Value("${jira.timeout.seconds:30}")
+    private int timeoutSeconds;
+
+    /// id -> Artifact.externalId -> TODO NOT EXISTING
+    /// fileName -> Artifact.name
+    /// properties -> Artifact.description
+    /// created -> Artifact.created
+    /// authorObject -> Artifact.author
+    /// "File" -> Artifact.artifactClass
+    /// mimeType -> Artifact.mimeType
+    /// fileSize -> Artifact.size
+    public void fetchAttachments(JiraRestClient restClient)
+        throws InterruptedException, ExecutionException, TimeoutException {
+        log.info("Fetching attachments for project: {}", projectKey);
+
+        // First find issues with attachments
+        String jql = "project = " + projectKey + " AND attachments IS NOT EMPTY ORDER BY updated DESC";
+        SearchResult result = restClient.getSearchClient().searchJql(jql, maxIssues, 0, null)
+                                        .get(timeoutSeconds, TimeUnit.SECONDS);
+
+        log.info("Found {} issues with attachments", result.getTotal());
+        int totalAttachments = 0;
+
+        // For each issue in the search results, fetch the complete issue with all fields
+        for (Issue basicIssue : result.getIssues()) {
+
+            // Get the full issue with all fields including attachments
+            Issue completeIssue = restClient.getIssueClient().getIssue(basicIssue.getKey())
+                                            .get(timeoutSeconds, TimeUnit.SECONDS);
+
+            Iterable<Attachment> attachments = completeIssue.getAttachments();
+
+            if (attachments != null) {
+                int count = (int) StreamSupport.stream(attachments.spliterator(), false).count();
+
+                if (count > 0) {
+                    log.info("Issue [{}] - {} has {} attachment(s)",
+                        completeIssue.getKey(), completeIssue.getSummary(), count);
+
+                    // Data that we want to save
+                    for (Attachment attachment : attachments) {
+                        log.info("ID: {}, Filename: {}, Properties: {}, Created: {}, AuthorObject: {}, " +
+                            "\"File\": {}, MimeType: {}, FileSize: {}",
+                            0,  // TODO WE HAVE NOT ID
+                            attachment.getFilename(),
+                            "NO PROPERTIES", // TODO we have no properties
+                            attachment.getCreationDate(),
+                            attachment.getAuthor().getDisplayName(),
+                            attachment.getSelf(), // TODO we have no file yet
+                            // TODO it's request to API so we will most likely have to fetch it additionally
+                            attachment.getMimeType(),
+                            attachment.getSize()
+                            );
+                        totalAttachments++;
+                    }
+                }
+            } else {
+                log.debug("Issue [{}] reports having attachments but returned null", basicIssue.getKey());
+            }
+        }
+
+        log.info("Total attachments found: {}", totalAttachments);
+    }
+}
diff --git a/src/main/java/com/pump/jira/service/IssueService.java b/src/main/java/com/pump/jira/service/IssueService.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f4829327ab7f7f53ee456716ee4056f567aa3e7
--- /dev/null
+++ b/src/main/java/com/pump/jira/service/IssueService.java
@@ -0,0 +1,10 @@
+package com.pump.jira.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class IssueService {
+
+}
diff --git a/src/main/java/com/pump/jira/service/ProjectService.java b/src/main/java/com/pump/jira/service/ProjectService.java
new file mode 100644
index 0000000000000000000000000000000000000000..474af4c0f1ad7319907969b2733666273e867b87
--- /dev/null
+++ b/src/main/java/com/pump/jira/service/ProjectService.java
@@ -0,0 +1,10 @@
+package com.pump.jira.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class ProjectService {
+
+}
diff --git a/src/main/java/com/pump/jira/service/UserService.java b/src/main/java/com/pump/jira/service/UserService.java
new file mode 100644
index 0000000000000000000000000000000000000000..5055c922a2d400c5d55dfcd25970f79ef7d44a22
--- /dev/null
+++ b/src/main/java/com/pump/jira/service/UserService.java
@@ -0,0 +1,13 @@
+package com.pump.jira.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class UserService {
+
+    public void run() {
+        log.info("Running user service");
+    }
+}
diff --git a/src/main/java/com/pump/jira/service/VersionService.java b/src/main/java/com/pump/jira/service/VersionService.java
new file mode 100644
index 0000000000000000000000000000000000000000..de0d30ab35a4aecef6ab3cd4f1a2f9544cede629
--- /dev/null
+++ b/src/main/java/com/pump/jira/service/VersionService.java
@@ -0,0 +1,10 @@
+package com.pump.jira.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class VersionService {
+
+}