moco-ruby 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -2
- data/Gemfile.lock +1 -0
- data/lib/moco/api.rb +65 -0
- data/lib/moco/entities.rb +3 -1
- data/lib/moco/helpers.rb +12 -0
- data/lib/moco/sync.rb +21 -7
- data/lib/moco/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 781b3fd8aed069892a3c387056616917556da295b17878e23e3ec3b8aa8dd8fb
|
4
|
+
data.tar.gz: 1a818a32e9910e7ab30fd978e4e39348dcb7e970717b60e3f2f2b7dd755c6fbb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa1352b7183998b30397668eca16ca9eefbb99659f72fb60812eb14585f284789808defa0e8dfb147e6327a4d540bccf1e0531c3c3946f6753447bee347e3942
|
7
|
+
data.tar.gz: 367888eed8cb0a9bc91d2301a28e9f57ab1cc57f9226e5bd09a91fb71fe52c4220ff65bcb0e2fd7aae903fc12107be37f46e5df7ce27636451a1e7d3800e6807
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,21 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
4
|
-
|
5
3
|
## [Unreleased]
|
6
4
|
|
5
|
+
## [0.1.2] - 2025-04-02
|
6
|
+
|
7
|
+
### Added
|
8
|
+
- Complete Activities API implementation:
|
9
|
+
- Single activity retrieval
|
10
|
+
- Bulk activity creation
|
11
|
+
- Activity timer control (start/stop)
|
12
|
+
- Activity disregard endpoint
|
13
|
+
- Activity deletion
|
14
|
+
- Project management API endpoints:
|
15
|
+
- Archive/unarchive projects
|
16
|
+
- Project report operations
|
17
|
+
- Project group assignment
|
18
|
+
|
7
19
|
## [0.1.1] - 2024-02-27
|
8
20
|
|
9
21
|
### Added
|
data/Gemfile.lock
CHANGED
data/lib/moco/api.rb
CHANGED
@@ -38,6 +38,21 @@ module MOCO
|
|
38
38
|
parse_activities_response(response.body)
|
39
39
|
end
|
40
40
|
|
41
|
+
def get_activity(id)
|
42
|
+
response = @conn.get("activities/#{id}")
|
43
|
+
parse_activities_response([response.body]).first
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_activities_bulk(activities)
|
47
|
+
api_entities = activities.map do |activity|
|
48
|
+
activity.to_h.except(:id, :project, :user, :customer).tap do |h|
|
49
|
+
h[:project_id] = activity.project.id
|
50
|
+
h[:task_id] = activity.task.id
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@conn.post("activities/bulk", { activities: api_entities })
|
54
|
+
end
|
55
|
+
|
41
56
|
def create_activity(activity)
|
42
57
|
api_entity = activity.to_h.except(:id, :project, :user, :customer).tap do |h|
|
43
58
|
h[:project_id] = activity.project.id
|
@@ -54,6 +69,56 @@ module MOCO
|
|
54
69
|
@conn.put("activities/#{activity.id}", api_entity)
|
55
70
|
end
|
56
71
|
|
72
|
+
def start_activity_timer(activity_id)
|
73
|
+
@conn.patch("activities/#{activity_id}/start_timer")
|
74
|
+
end
|
75
|
+
|
76
|
+
def stop_activity_timer(activity_id)
|
77
|
+
@conn.patch("activities/#{activity_id}/stop_timer")
|
78
|
+
end
|
79
|
+
|
80
|
+
def disregard_activities(reason:, activity_ids:, company_id:, project_id: nil)
|
81
|
+
payload = {
|
82
|
+
reason: reason,
|
83
|
+
activity_ids: activity_ids,
|
84
|
+
company_id: company_id
|
85
|
+
}
|
86
|
+
payload[:project_id] = project_id if project_id
|
87
|
+
@conn.post("activities/disregard", payload)
|
88
|
+
end
|
89
|
+
|
90
|
+
def delete_activity(activity_id)
|
91
|
+
@conn.delete("activities/#{activity_id}")
|
92
|
+
end
|
93
|
+
|
94
|
+
def archive_project(project_id)
|
95
|
+
@conn.put("projects/#{project_id}/archive")
|
96
|
+
end
|
97
|
+
|
98
|
+
def unarchive_project(project_id)
|
99
|
+
@conn.put("projects/#{project_id}/unarchive")
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_project_report(project_id)
|
103
|
+
@conn.get("projects/#{project_id}/report")
|
104
|
+
end
|
105
|
+
|
106
|
+
def share_project_report(project_id)
|
107
|
+
@conn.put("projects/#{project_id}/share")
|
108
|
+
end
|
109
|
+
|
110
|
+
def disable_project_report_sharing(project_id)
|
111
|
+
@conn.put("projects/#{project_id}/disable_share")
|
112
|
+
end
|
113
|
+
|
114
|
+
def assign_project_to_group(project_id, project_group_id)
|
115
|
+
@conn.put("projects/#{project_id}/assign_project_group", { project_group_id: project_group_id })
|
116
|
+
end
|
117
|
+
|
118
|
+
def unassign_project_from_group(project_id)
|
119
|
+
@conn.put("projects/#{project_id}/unassign_project_group")
|
120
|
+
end
|
121
|
+
|
57
122
|
private
|
58
123
|
|
59
124
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
data/lib/moco/entities.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "helpers"
|
4
|
+
|
3
5
|
module MOCO
|
4
6
|
# Base entity class others inherit from, providing comparison, to_h, to_json
|
5
7
|
class BaseEntity
|
@@ -67,7 +69,7 @@ module MOCO
|
|
67
69
|
:customer, :tag
|
68
70
|
|
69
71
|
def to_s
|
70
|
-
"#{date} - #{hours}h (#{seconds}s) - #{project&.name} - #{task&.name}#{description.empty? ? "" : " (#{description})"} " \
|
72
|
+
"#{date} - #{Helpers.decimal_hours_to_civil(hours)}h (#{seconds}s) - #{project&.name} - #{task&.name}#{description.empty? ? "" : " (#{description})"} " \
|
71
73
|
"(#{%i[billable billed].map { |x| (send(x) ? "" : "not ") + x.to_s }.join(", ")})"
|
72
74
|
end
|
73
75
|
end
|
data/lib/moco/helpers.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MOCO
|
4
|
+
class Helpers
|
5
|
+
def self.decimal_hours_to_civil(decimal_hours)
|
6
|
+
hours = decimal_hours.floor
|
7
|
+
fractional_hours = decimal_hours - hours
|
8
|
+
minutes = (fractional_hours * 60).round
|
9
|
+
"#{hours}:#{format("%02d", minutes)}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/moco/sync.rb
CHANGED
@@ -8,7 +8,7 @@ module MOCO
|
|
8
8
|
class Sync
|
9
9
|
attr_reader :project_mapping, :task_mapping, :source_projects, :target_projects
|
10
10
|
attr_accessor :project_match_threshold, :task_match_threshold, :dry_run
|
11
|
-
|
11
|
+
|
12
12
|
def initialize(source_instance_api, target_instance_api, **args)
|
13
13
|
@source_api = source_instance_api
|
14
14
|
@target_api = target_instance_api
|
@@ -16,14 +16,14 @@ module MOCO
|
|
16
16
|
@task_match_threshold = args.fetch(:task_match_threshold, 0.45)
|
17
17
|
@filters = args.fetch(:filters, {})
|
18
18
|
@dry_run = args.fetch(:dry_run, false)
|
19
|
-
|
19
|
+
|
20
20
|
@project_mapping = {}
|
21
21
|
@task_mapping = {}
|
22
|
-
|
22
|
+
|
23
23
|
fetch_assigned_projects
|
24
24
|
build_initial_mappings
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
# rubocop:todo Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
28
28
|
def sync(&callbacks)
|
29
29
|
results = []
|
@@ -38,6 +38,9 @@ module MOCO
|
|
38
38
|
activities.group_by(&:project)
|
39
39
|
end
|
40
40
|
|
41
|
+
used_source_activities = []
|
42
|
+
used_target_activities = []
|
43
|
+
|
41
44
|
source_activities_grouped.each do |date, activities_by_project|
|
42
45
|
activities_by_project.each do |project, source_activities|
|
43
46
|
target_activities = target_activities_grouped.fetch(date, {}).fetch(@project_mapping[project.id], [])
|
@@ -46,9 +49,6 @@ module MOCO
|
|
46
49
|
matches = calculate_matches(source_activities, target_activities)
|
47
50
|
matches.sort_by! { |match| -match[:score] }
|
48
51
|
|
49
|
-
used_source_activities = []
|
50
|
-
used_target_activities = []
|
51
|
-
|
52
52
|
matches.each do |match|
|
53
53
|
source_activity, target_activity = match[:activity]
|
54
54
|
score = match[:score]
|
@@ -87,6 +87,20 @@ module MOCO
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
90
|
+
|
91
|
+
source_activities_r.each do |source_activity|
|
92
|
+
unless used_source_activities.include?(source_activity)
|
93
|
+
next unless @project_mapping[source_activity.project.id]
|
94
|
+
|
95
|
+
expected_target_activity = get_expected_target_activity(source_activity)
|
96
|
+
callbacks&.call(:create, source_activity, expected_target_activity)
|
97
|
+
unless @dry_run
|
98
|
+
results << @target_api.create_activity(expected_target_activity)
|
99
|
+
callbacks&.call(:created, source_activity, expected_target_activity, results.last)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
90
104
|
results
|
91
105
|
end
|
92
106
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
data/lib/moco/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moco-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Teal Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- lib/moco.rb
|
59
59
|
- lib/moco/api.rb
|
60
60
|
- lib/moco/entities.rb
|
61
|
+
- lib/moco/helpers.rb
|
61
62
|
- lib/moco/sync.rb
|
62
63
|
- lib/moco/version.rb
|
63
64
|
- mocurl.rb
|