moco-ruby 0.1.2 → 1.0.0
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/.rubocop.yml +10 -3
- data/CHANGELOG.md +104 -5
- data/Gemfile +3 -1
- data/Gemfile.lock +72 -23
- data/README.md +225 -55
- data/examples/v2_api_example.rb +73 -0
- data/lib/moco/client.rb +47 -0
- data/lib/moco/collection_proxy.rb +200 -0
- data/lib/moco/connection.rb +68 -0
- data/lib/moco/entities/activity.rb +101 -0
- data/lib/moco/entities/base_entity.rb +312 -0
- data/lib/moco/entities/company.rb +28 -0
- data/lib/moco/entities/deal.rb +24 -0
- data/lib/moco/entities/expense.rb +37 -0
- data/lib/moco/entities/holiday.rb +25 -0
- data/lib/moco/entities/invoice.rb +53 -0
- data/lib/moco/entities/planning_entry.rb +26 -0
- data/lib/moco/entities/presence.rb +30 -0
- data/lib/moco/entities/project.rb +48 -0
- data/lib/moco/entities/schedule.rb +26 -0
- data/lib/moco/entities/task.rb +20 -0
- data/lib/moco/entities/user.rb +33 -0
- data/lib/moco/entities/web_hook.rb +27 -0
- data/lib/moco/entities.rb +11 -4
- data/lib/moco/entity_collection.rb +59 -0
- data/lib/moco/helpers.rb +1 -0
- data/lib/moco/nested_collection_proxy.rb +43 -0
- data/lib/moco/sync.rb +337 -62
- data/lib/moco/version.rb +1 -1
- data/lib/moco.rb +28 -2
- data/moco.gemspec +36 -0
- data/mocurl.rb +51 -34
- data/sync_activity.rb +12 -6
- metadata +42 -8
- data/lib/moco/api.rb +0 -194
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94fd15c735a242e23f7a1e20dd49408d12dbfbb21f1665ca64bfd85ba3251cae
|
4
|
+
data.tar.gz: 710f5ce6be51b2c363c6d2b3df871d755e5b21e90e9ad53cbb535ac249b46b6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 272eede87d5a02636ca02354ea0ef592f0d21662378fb6817b68cc6fa73e66922b43623f6ac5da5c4c76ac3db9c6ebaee12a340fcc9920df93104303f96668fd
|
7
|
+
data.tar.gz: 12f55e014641e51ecf2f666c04bff0a5f330ae68b91cf63e70060b6f85e5fc759eed517854060190651581a7ffba5bfa8345fdd25b8e2e59a96193a32cdece9a
|
data/.rubocop.yml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
AllCops:
|
2
|
-
TargetRubyVersion: 2
|
2
|
+
TargetRubyVersion: 3.2
|
3
3
|
SuggestExtensions: false
|
4
4
|
NewCops: enable
|
5
5
|
|
@@ -15,12 +15,19 @@ Naming/MethodParameterName:
|
|
15
15
|
AllowedNames:
|
16
16
|
- a
|
17
17
|
- b
|
18
|
+
- id
|
18
19
|
|
19
20
|
Layout/LineLength:
|
20
21
|
Max: 130
|
21
22
|
|
22
23
|
Metrics/BlockLength:
|
23
|
-
|
24
|
+
Enabled: false
|
24
25
|
|
25
26
|
Metrics/ClassLength:
|
26
|
-
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
Metrics/MethodLength:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
Metrics/AbcSize:
|
33
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,101 @@
|
|
1
|
-
# Changelog
|
1
|
+
# # Changelog
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [1.0.0] - 2025-10-08
|
6
|
+
|
7
|
+
### Fixed
|
8
|
+
- Fixed Project `leader` and `co_leader` associations to return User objects instead of Hashes
|
9
|
+
- Fixed Expense associations to use proper `association()` method for embedded objects
|
10
|
+
- Fixed nested resource proxy caching issue - tasks and expenses now always return fresh data
|
11
|
+
- Fixed `NestedCollectionProxy` path construction for expenses (was double-prefixing with "projects/")
|
12
|
+
- Fixed `entity_path` warnings by converting instance methods to class methods in Holiday and WebHook classes
|
13
|
+
- Fixed embedded entity conversion for leader, co_leader, and user associations in BaseEntity
|
14
|
+
|
15
|
+
### Added
|
16
|
+
- Added comprehensive test suite using test-unit framework:
|
17
|
+
- `test/test_comprehensive.rb` - 27 integration tests covering all CRUD operations
|
18
|
+
- `test/test_holidays_expenses.rb` - 9 tests for holidays and expenses (nested resources)
|
19
|
+
- `test/test_v2_api.rb` - 4 unit tests with mocked API responses
|
20
|
+
- `test/test_helper.rb` - Shared test configuration
|
21
|
+
- Added `Project#expenses` method for nested expense access
|
22
|
+
- Added proper entity type mappings for `:leader`, `:co_leader`, and `:user` in BaseEntity
|
23
|
+
- Added dotenv gem as development dependency for test environment configuration
|
24
|
+
|
25
|
+
### Changed
|
26
|
+
- Moved all `require_relative` statements out of methods and into file-level requires
|
27
|
+
- Improved load order in `lib/moco.rb` - core classes now load before entities
|
28
|
+
- Updated `Expense` entity to use `association()` method for project and user relationships
|
29
|
+
- Refactored nested resource access in Project class to return fresh proxies instead of cached ones
|
30
|
+
- Enhanced `NestedCollectionProxy` to properly handle nested resource paths without double-prefixing
|
31
|
+
|
32
|
+
### Removed
|
33
|
+
- Removed manual test scripts (converted to proper test-unit tests)
|
34
|
+
|
35
|
+
## [1.0.0.beta] - 2025-04-10
|
36
|
+
|
37
|
+
### Fixed
|
38
|
+
- Fixed activity synchronization to properly identify existing activities in target system
|
39
|
+
- Added remote_id accessor to Activity class to prevent duplicate activity creation
|
40
|
+
|
41
|
+
## [1.0.0.alpha] - 2025-04-10
|
42
|
+
|
43
|
+
### Added
|
44
|
+
- Added support for nested resources with `NestedCollectionProxy` class:
|
45
|
+
- Enables ActiveRecord-style operations on nested resources (e.g., `project.tasks.create`)
|
46
|
+
- Supports proper path construction for nested API endpoints
|
47
|
+
- Implements `destroy_all` method for bulk deletion of nested resources
|
48
|
+
|
49
|
+
## [1.0.0.alpha-initial] - 2025-04-10
|
50
|
+
|
51
|
+
### Added
|
52
|
+
- Implemented ActiveRecord-style query interface (`where`, `find`, `find_by`, `first`, `all`, `each`) via `CollectionProxy`.
|
53
|
+
- Added ActiveRecord-style persistence methods to `BaseEntity`:
|
54
|
+
- `save` - Persist changes to an entity
|
55
|
+
- `update` - Update attributes and save in one step
|
56
|
+
- `destroy` - Delete an entity
|
57
|
+
- `reload` - Refresh an entity from the API
|
58
|
+
- Added `has_many` method to `BaseEntity` for handling one-to-many associations, complementing the existing `association` method for one-to-one associations.
|
59
|
+
- Refactored entity association methods in `Project`, `User`, and `Company` classes to use the new `has_many` method.
|
60
|
+
- Added comprehensive project lifecycle test that creates a project, adds tasks and activities, then cleans up.
|
61
|
+
- Added support for nested resources with `NestedCollectionProxy` class:
|
62
|
+
- Enables ActiveRecord-style operations on nested resources (e.g., `project.tasks.create`)
|
63
|
+
- Supports proper path construction for nested API endpoints
|
64
|
+
- Implements `destroy_all` method for bulk deletion of nested resources
|
65
|
+
- Complete redesign with Ruby-esque API
|
66
|
+
- Chainable methods for fluent interface
|
67
|
+
- Dynamic entity creation with Rails-style inflection
|
68
|
+
- Comprehensive entity coverage for all MOCO API endpoints:
|
69
|
+
- Project
|
70
|
+
- Activity
|
71
|
+
- User
|
72
|
+
- Company
|
73
|
+
- Task
|
74
|
+
- Invoice
|
75
|
+
- Deal
|
76
|
+
- Expense
|
77
|
+
- WebHook
|
78
|
+
- Schedule
|
79
|
+
- Presence
|
80
|
+
- Holiday
|
81
|
+
- PlanningEntry
|
82
|
+
- Entity association methods for related entities
|
83
|
+
- Automatic entity creation from API responses
|
84
|
+
- Struct-based fallback for unknown entity types
|
85
|
+
- Generic association method for handling relationships between entities
|
86
|
+
|
87
|
+
### Changed
|
88
|
+
- Added ActiveSupport dependency for inflection methods
|
89
|
+
- Reorganized code structure for better maintainability
|
90
|
+
- Updated documentation with new API examples
|
91
|
+
- `MOCO::Activity#to_s` now uses `Helpers.decimal_hours_to_civil` for improved time display.
|
92
|
+
- Refined core components like `Client`, `CollectionProxy`, and `Connection`.
|
93
|
+
- Updated various entity classes (`Activity`, `BaseEntity`, `Presence`, `Project`) with internal improvements.
|
94
|
+
- Updated utility scripts (`mocurl.rb`, `sync_activity.rb`).
|
95
|
+
|
96
|
+
### Removed
|
97
|
+
- Legacy API (`lib/moco/api.rb`) as part of the transition to the new client.
|
98
|
+
|
5
99
|
## [0.1.2] - 2025-04-02
|
6
100
|
|
7
101
|
### Added
|
@@ -19,18 +113,23 @@
|
|
19
113
|
## [0.1.1] - 2024-02-27
|
20
114
|
|
21
115
|
### Added
|
22
|
-
|
23
116
|
- Prepared for Gem release
|
24
117
|
|
25
118
|
### Changed
|
26
|
-
|
27
119
|
- Changed target Ruby version to 2.6 (from 3.x)
|
28
120
|
- Applied Rubocop configuration and fixed style errors
|
29
121
|
|
30
122
|
### Security
|
31
|
-
|
32
123
|
- Bumped `uri` dependency to 0.13.0
|
33
124
|
|
34
125
|
## [0.1.0] - 2024-02-27
|
35
|
-
|
36
126
|
- Initial release
|
127
|
+
|
128
|
+
[Unreleased]: https://github.com/starsong-consulting/moco-ruby/compare/v1.0.0...HEAD
|
129
|
+
[1.0.0]: https://github.com/starsong-consulting/moco-ruby/compare/v1.0.0.beta...v1.0.0
|
130
|
+
[1.0.0.beta]: https://github.com/starsong-consulting/moco-ruby/compare/v1.0.0.alpha...v1.0.0.beta
|
131
|
+
[1.0.0.alpha]: https://github.com/starsong-consulting/moco-ruby/compare/v1.0.0.alpha-initial...v1.0.0.alpha
|
132
|
+
[1.0.0.alpha-initial]: https://github.com/starsong-consulting/moco-ruby/compare/v0.1.2...v1.0.0.alpha-initial
|
133
|
+
[0.1.2]: https://github.com/starsong-consulting/moco-ruby/compare/v0.1.1...v0.1.2
|
134
|
+
[0.1.1]: https://github.com/starsong-consulting/moco-ruby/compare/v0.1.0...v0.1.1
|
135
|
+
[0.1.0]: https://github.com/starsong-consulting/moco-ruby/releases/tag/v0.1.0
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,57 +1,106 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
moco-ruby (0.
|
4
|
+
moco-ruby (1.0.0)
|
5
|
+
activesupport (~> 7.0)
|
5
6
|
faraday (~> 2.9.0)
|
6
7
|
fuzzy_match (~> 2.1.0)
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: https://rubygems.org/
|
10
11
|
specs:
|
11
|
-
|
12
|
-
|
12
|
+
activesupport (7.2.2.1)
|
13
|
+
base64
|
14
|
+
benchmark (>= 0.3)
|
15
|
+
bigdecimal
|
16
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
17
|
+
connection_pool (>= 2.2.5)
|
18
|
+
drb
|
19
|
+
i18n (>= 1.6, < 2)
|
20
|
+
logger (>= 1.4.2)
|
21
|
+
minitest (>= 5.1)
|
22
|
+
securerandom (>= 0.3)
|
23
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
24
|
+
addressable (2.8.7)
|
25
|
+
public_suffix (>= 2.0.2, < 7.0)
|
26
|
+
ast (2.4.3)
|
27
|
+
base64 (0.2.0)
|
28
|
+
benchmark (0.4.0)
|
29
|
+
bigdecimal (3.1.9)
|
30
|
+
concurrent-ruby (1.3.5)
|
31
|
+
connection_pool (2.5.0)
|
32
|
+
crack (1.0.0)
|
33
|
+
bigdecimal
|
34
|
+
rexml
|
35
|
+
dotenv (2.8.1)
|
36
|
+
drb (2.2.1)
|
37
|
+
faraday (2.9.2)
|
13
38
|
faraday-net_http (>= 2.0, < 3.2)
|
14
|
-
faraday-net_http (3.1.
|
39
|
+
faraday-net_http (3.1.1)
|
15
40
|
net-http
|
16
41
|
fuzzy_match (2.1.0)
|
17
|
-
|
18
|
-
|
19
|
-
|
42
|
+
hashdiff (1.1.2)
|
43
|
+
i18n (1.14.7)
|
44
|
+
concurrent-ruby (~> 1.0)
|
45
|
+
json (2.10.2)
|
46
|
+
language_server-protocol (3.17.0.4)
|
47
|
+
lint_roller (1.1.0)
|
48
|
+
logger (1.7.0)
|
49
|
+
minitest (5.25.5)
|
50
|
+
net-http (0.6.0)
|
20
51
|
uri
|
21
|
-
parallel (1.
|
22
|
-
parser (3.3.
|
52
|
+
parallel (1.26.3)
|
53
|
+
parser (3.3.7.4)
|
23
54
|
ast (~> 2.4.1)
|
24
55
|
racc
|
25
|
-
|
56
|
+
power_assert (2.0.5)
|
57
|
+
prism (1.4.0)
|
58
|
+
public_suffix (6.0.1)
|
59
|
+
racc (1.8.1)
|
26
60
|
rainbow (3.1.1)
|
27
|
-
rake (13.1
|
28
|
-
regexp_parser (2.
|
29
|
-
rexml (3.
|
30
|
-
rubocop (1.
|
61
|
+
rake (13.2.1)
|
62
|
+
regexp_parser (2.10.0)
|
63
|
+
rexml (3.4.1)
|
64
|
+
rubocop (1.75.2)
|
31
65
|
json (~> 2.3)
|
32
|
-
language_server-protocol (
|
66
|
+
language_server-protocol (~> 3.17.0.2)
|
67
|
+
lint_roller (~> 1.1.0)
|
33
68
|
parallel (~> 1.10)
|
34
69
|
parser (>= 3.3.0.2)
|
35
70
|
rainbow (>= 2.2.2, < 4.0)
|
36
|
-
regexp_parser (>=
|
37
|
-
|
38
|
-
rubocop-ast (>= 1.30.0, < 2.0)
|
71
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
72
|
+
rubocop-ast (>= 1.44.0, < 2.0)
|
39
73
|
ruby-progressbar (~> 1.7)
|
40
|
-
unicode-display_width (>= 2.4.0, <
|
41
|
-
rubocop-ast (1.
|
42
|
-
parser (>= 3.
|
74
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
75
|
+
rubocop-ast (1.44.0)
|
76
|
+
parser (>= 3.3.7.2)
|
77
|
+
prism (~> 1.4)
|
43
78
|
ruby-progressbar (1.13.0)
|
44
|
-
|
45
|
-
|
79
|
+
securerandom (0.4.1)
|
80
|
+
test-unit (3.6.8)
|
81
|
+
power_assert
|
82
|
+
tzinfo (2.0.6)
|
83
|
+
concurrent-ruby (~> 1.0)
|
84
|
+
unicode-display_width (3.1.4)
|
85
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
86
|
+
unicode-emoji (4.0.4)
|
87
|
+
uri (1.0.3)
|
88
|
+
webmock (3.25.1)
|
89
|
+
addressable (>= 2.8.0)
|
90
|
+
crack (>= 0.3.2)
|
91
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
46
92
|
|
47
93
|
PLATFORMS
|
48
94
|
arm64-darwin-22
|
49
95
|
arm64-darwin-23
|
50
96
|
|
51
97
|
DEPENDENCIES
|
98
|
+
dotenv (~> 2.8)
|
52
99
|
moco-ruby!
|
53
100
|
rake (~> 13.0)
|
54
101
|
rubocop (~> 1.21)
|
102
|
+
test-unit (~> 3.5)
|
103
|
+
webmock (~> 3.18)
|
55
104
|
|
56
105
|
BUNDLED WITH
|
57
106
|
2.4.1
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# MOCO Ruby Gem
|
2
2
|
|
3
|
-
|
3
|
+
[](https://badge.fury.io/rb/moco-ruby)
|
4
|
+
|
5
|
+
A Ruby Gem to interact with the [MOCO API](https://hundertzehn.github.io/mocoapp-api-docs/). This gem provides a modern, Ruby-esque interface (`MOCO::Client`) for interacting with the MOCO API.
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
@@ -14,88 +16,256 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
14
16
|
|
15
17
|
## Usage
|
16
18
|
|
17
|
-
###
|
19
|
+
### Initialization
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
require 'moco'
|
23
|
+
|
24
|
+
moco = MOCO::Client.new(
|
25
|
+
subdomain: "your-subdomain", # Your MOCO subdomain
|
26
|
+
api_key: "your-api-key" # Your MOCO API key
|
27
|
+
)
|
28
|
+
```
|
29
|
+
|
30
|
+
### Accessing Collections
|
31
|
+
|
32
|
+
Collections are accessed dynamically using pluralized entity names (following Rails conventions):
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
projects = moco.projects
|
36
|
+
activities = moco.activities
|
37
|
+
users = moco.users
|
38
|
+
# ... and so on for all supported entities
|
39
|
+
```
|
40
|
+
|
41
|
+
### Fetching Entities
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
# Get all entities in a collection
|
45
|
+
all_projects = moco.projects.all
|
46
|
+
|
47
|
+
# Get entities matching specific criteria
|
48
|
+
active_projects = moco.projects.where(active: true)
|
49
|
+
recent_activities = moco.activities.where(date: ">=2024-01-01")
|
50
|
+
|
51
|
+
# Get a specific entity by ID
|
52
|
+
project = moco.projects.find(12345)
|
53
|
+
user = moco.users.find(678)
|
54
|
+
```
|
55
|
+
|
56
|
+
### Creating Entities
|
18
57
|
|
19
58
|
```ruby
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
59
|
+
# Create a new project
|
60
|
+
new_project = moco.projects.create(
|
61
|
+
name: "New Website Project",
|
62
|
+
customer_id: 987,
|
63
|
+
billable: true
|
64
|
+
)
|
65
|
+
puts "Created project: #{new_project.name} (ID: #{new_project.id})"
|
66
|
+
|
67
|
+
# Create a new time entry (activity)
|
68
|
+
new_activity = moco.activities.create(
|
69
|
+
date: "2024-04-10",
|
70
|
+
project_id: new_project.id,
|
71
|
+
task_id: new_project.tasks.first.id, # Assumes project has tasks
|
72
|
+
hours: 3.5,
|
73
|
+
description: "Implemented feature X"
|
74
|
+
)
|
75
|
+
puts "Created activity: #{new_activity.description} on #{new_activity.date}"
|
76
|
+
```
|
77
|
+
|
78
|
+
### Updating Entities
|
79
|
+
|
80
|
+
Modify attributes and call `save`:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
project = moco.projects.find(12345)
|
84
|
+
project.name = "Updated Project Name"
|
85
|
+
project.billable = false
|
86
|
+
|
87
|
+
if project.save
|
88
|
+
puts "Project updated successfully."
|
89
|
+
else
|
90
|
+
puts "Failed to update project: #{project.errors.full_messages.join(", ")}" # Assuming error handling exists
|
91
|
+
end
|
92
|
+
|
93
|
+
# You can also update directly via the collection
|
94
|
+
moco.projects.update(12345, name: "Another Update", active: false)
|
95
|
+
```
|
96
|
+
|
97
|
+
### Deleting Entities
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
# Delete by object
|
101
|
+
activity = moco.activities.find(9876)
|
102
|
+
if activity&.delete
|
103
|
+
puts "Activity deleted."
|
104
|
+
end
|
105
|
+
|
106
|
+
# Delete by ID via collection
|
107
|
+
if moco.activities.delete(9876)
|
108
|
+
puts "Activity deleted."
|
27
109
|
end
|
28
110
|
```
|
29
111
|
|
30
|
-
###
|
112
|
+
### Entity Associations
|
31
113
|
|
32
|
-
|
114
|
+
Entities provide methods to access related entities easily:
|
33
115
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
116
|
+
```ruby
|
117
|
+
project = moco.projects.find(12345)
|
118
|
+
|
119
|
+
# Get tasks associated with the project
|
120
|
+
tasks = project.tasks # Returns a collection proxy for tasks
|
121
|
+
puts "Tasks for project '#{project.name}': #{tasks.map(&:name).join(', ')}"
|
122
|
+
|
123
|
+
# Get activities for the project
|
124
|
+
project_activities = project.activities
|
125
|
+
puts "Activities count: #{project_activities.size}"
|
39
126
|
|
40
|
-
|
127
|
+
# Get the customer (company) for the project
|
128
|
+
customer = project.customer # Returns a MOCO::Company object
|
129
|
+
puts "Customer: #{customer.name}"
|
41
130
|
|
42
|
-
|
131
|
+
# ---
|
43
132
|
|
44
|
-
|
45
|
-
|
46
|
-
|
133
|
+
activity = moco.activities.find(9876)
|
134
|
+
|
135
|
+
# Get the associated project, task, and user
|
136
|
+
act_project = activity.project
|
137
|
+
act_task = activity.task
|
138
|
+
act_user = activity.user
|
139
|
+
puts "Activity by #{act_user.firstname} on project '#{act_project.name}' (Task: #{act_task.name})"
|
140
|
+
```
|
141
|
+
|
142
|
+
### Nested Resources
|
143
|
+
|
144
|
+
The gem supports ActiveRecord-style operations on nested resources:
|
47
145
|
|
48
146
|
```ruby
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
source: options.slice(:from, :to, :project_id, :company_id, :term),
|
59
|
-
target: options.slice(:from, :to)
|
60
|
-
},
|
61
|
-
dry_run: options[:dry_run]
|
147
|
+
project = moco.projects.find(12345)
|
148
|
+
|
149
|
+
# Create a new task for the project
|
150
|
+
new_task = project.tasks.create(
|
151
|
+
name: "New Feature Development",
|
152
|
+
billable: true,
|
153
|
+
active: true,
|
154
|
+
budget: 40,
|
155
|
+
hourly_rate: 120
|
62
156
|
)
|
157
|
+
puts "Created task: #{new_task.name} (ID: #{new_task.id})"
|
158
|
+
|
159
|
+
# Delete all tasks for a project
|
160
|
+
project.tasks.destroy_all
|
161
|
+
|
162
|
+
# Query tasks with conditions
|
163
|
+
billable_tasks = project.tasks.where(billable: true).all
|
164
|
+
puts "Billable tasks: #{billable_tasks.map(&:name).join(', ')}"
|
165
|
+
|
166
|
+
# Find a specific task
|
167
|
+
dev_task = project.tasks.find_by(name: "Development")
|
63
168
|
```
|
64
169
|
|
170
|
+
### Supported Entities
|
171
|
+
|
172
|
+
The gem supports all MOCO API entities with a Ruby-esque interface:
|
173
|
+
|
174
|
+
- `Project`
|
175
|
+
- `Activity`
|
176
|
+
- `User`
|
177
|
+
- `Company`
|
178
|
+
- `Task`
|
179
|
+
- `Invoice`
|
180
|
+
- `Deal`
|
181
|
+
- `Expense`
|
182
|
+
- `WebHook`
|
183
|
+
- `Schedule`
|
184
|
+
- `Presence`
|
185
|
+
- `Holiday`
|
186
|
+
- `PlanningEntry`
|
187
|
+
|
188
|
+
Access them via the moco using their plural, snake_case names (e.g., `moco.planning_entries`).
|
189
|
+
|
65
190
|
## Utilities
|
66
191
|
|
67
|
-
|
192
|
+
These command-line utilities provide helpful shortcuts. They can use credentials and configuration from a `config.yml` file (see `config.yml.sample`) in the current directory or accept parameters.
|
68
193
|
|
69
|
-
### mocurl
|
194
|
+
### `mocurl`
|
70
195
|
|
71
|
-
|
72
|
-
Use config.yml or specify api key with `-a`.
|
196
|
+
A wrapper around `curl` to easily make authenticated requests to your MOCO instance API. Useful for testing or exploring endpoints.
|
73
197
|
|
74
198
|
```
|
75
199
|
Usage: mocurl.rb [options] url
|
76
200
|
mocurl.rb [options] subdomain path
|
77
|
-
-X, --method METHOD Set HTTP method to use
|
78
|
-
-d, --data DATA Data to send to server
|
79
|
-
-a, --api-key API_KEY Manually specify MOCO API key
|
80
|
-
-n, --no-format Disable JSON pretty-printing
|
201
|
+
-X, --method METHOD Set HTTP method to use (GET, POST, PUT, DELETE)
|
202
|
+
-d, --data DATA Data to send to server (JSON format) for POST/PUT
|
203
|
+
-a, --api-key API_KEY Manually specify MOCO API key (overrides config.yml)
|
204
|
+
-n, --no-format Disable JSON pretty-printing of the response
|
81
205
|
-v, --verbose Show additional request and response information
|
82
206
|
-h, --help Show this message
|
83
207
|
```
|
208
|
+
**Example:** `mocurl.rb your-subdomain projects/12345`
|
209
|
+
|
210
|
+
### `sync_activity`
|
84
211
|
|
85
|
-
|
212
|
+
Syncs activity data (time entries) between two MOCO instances (source and target). It uses fuzzy matching to map projects and tasks between the instances.
|
86
213
|
|
87
|
-
|
88
|
-
|
214
|
+
**Important:**
|
215
|
+
* Always use `--dry-run` first to verify the matching and intended actions.
|
216
|
+
* Use date filters (`--from`, `--to`) to limit the scope.
|
89
217
|
|
90
218
|
```
|
91
|
-
Usage: sync_activity.rb [options]
|
92
|
-
-f, --from DATE Start date (YYYY-MM-DD)
|
93
|
-
-t, --to DATE End date (YYYY-MM-DD)
|
94
|
-
-p, --project PROJECT_ID Project ID to filter by
|
95
|
-
-c, --company COMPANY_ID Company ID to filter by
|
96
|
-
-g, --term TERM Term to filter
|
97
|
-
-n, --dry-run
|
219
|
+
Usage: sync_activity.rb [options] source_subdomain target_subdomain
|
220
|
+
-f, --from DATE Start date for sync (YYYY-MM-DD)
|
221
|
+
-t, --to DATE End date for sync (YYYY-MM-DD)
|
222
|
+
-p, --project PROJECT_ID Source Project ID to filter by (optional)
|
223
|
+
-c, --company COMPANY_ID Source Company ID to filter by (optional)
|
224
|
+
-g, --term TERM Term to filter source activities by (optional)
|
225
|
+
-n, --dry-run Perform matching and show planned actions, but do not modify target instance
|
98
226
|
--match-project-threshold VALUE
|
99
|
-
|
100
|
-
--match-task-threshold VALUE
|
227
|
+
Fuzzy match threshold for projects (0.0 - 1.0), default 0.8
|
228
|
+
--match-task-threshold VALUE Fuzzy match threshold for tasks (0.0 - 1.0), default 0.45
|
229
|
+
-h, --help Show this message
|
101
230
|
```
|
231
|
+
**Example:** `sync_activity.rb --from 2024-04-01 --to 2024-04-10 --dry-run source-instance target-instance`
|
232
|
+
|
233
|
+
## Development
|
234
|
+
|
235
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
236
|
+
|
237
|
+
### Running Tests
|
238
|
+
|
239
|
+
The gem includes a comprehensive test suite with both unit tests (mocked) and integration tests (live API):
|
240
|
+
|
241
|
+
```bash
|
242
|
+
# Run all tests
|
243
|
+
ruby test/test_v2_api.rb # Unit tests (mocked, fast)
|
244
|
+
ruby test/test_comprehensive.rb # Integration tests (requires .env)
|
245
|
+
ruby test/test_holidays_expenses.rb # Holidays & Expenses tests (requires .env)
|
246
|
+
|
247
|
+
# Or run individually
|
248
|
+
ruby test/test_v2_api.rb
|
249
|
+
```
|
250
|
+
|
251
|
+
For integration tests, create a `.env` file with your test instance credentials:
|
252
|
+
```
|
253
|
+
MOCO_API_TEST_SUBDOMAIN=your-test-subdomain
|
254
|
+
MOCO_API_TEST_API_KEY=your-test-api-key
|
255
|
+
```
|
256
|
+
|
257
|
+
**Note:** The MOCO API has rate limits (120 requests per 2 minutes on standard plans). Integration tests make real API calls.
|
258
|
+
|
259
|
+
### Installation
|
260
|
+
|
261
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
262
|
+
|
263
|
+
To release a new version, update the version number in `version.rb`, update the `CHANGELOG.md`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
264
|
+
|
265
|
+
## Contributing
|
266
|
+
|
267
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/starsong-consulting/moco-ruby.
|
268
|
+
|
269
|
+
## License
|
270
|
+
|
271
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|