moco-ruby 1.1.0 → 1.2.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/CHANGELOG.md +36 -1
- data/Gemfile.lock +44 -40
- data/README.md +53 -24
- data/lib/moco/client.rb +58 -0
- data/lib/moco/connection.rb +45 -22
- data/lib/moco/entities/activity.rb +31 -1
- data/lib/moco/entities/catalog_service.rb +54 -0
- data/lib/moco/entities/comment.rb +61 -0
- data/lib/moco/entities/company.rb +57 -2
- data/lib/moco/entities/contact.rb +56 -0
- data/lib/moco/entities/custom_property.rb +49 -0
- data/lib/moco/entities/deal.rb +38 -2
- data/lib/moco/entities/deal_category.rb +27 -0
- data/lib/moco/entities/employment.rb +55 -0
- data/lib/moco/entities/expense.rb +37 -2
- data/lib/moco/entities/expense_template.rb +39 -0
- data/lib/moco/entities/fixed_cost.rb +30 -0
- data/lib/moco/entities/holiday.rb +33 -2
- data/lib/moco/entities/hourly_rate.rb +33 -0
- data/lib/moco/entities/internal_hourly_rate.rb +32 -0
- data/lib/moco/entities/invoice.rb +81 -1
- data/lib/moco/entities/invoice_bookkeeping_export.rb +33 -0
- data/lib/moco/entities/invoice_payment.rb +51 -0
- data/lib/moco/entities/invoice_reminder.rb +51 -0
- data/lib/moco/entities/offer.rb +122 -0
- data/lib/moco/entities/offer_approval.rb +42 -0
- data/lib/moco/entities/payment_schedule.rb +48 -0
- data/lib/moco/entities/planning_entry.rb +43 -2
- data/lib/moco/entities/presence.rb +34 -2
- data/lib/moco/entities/profile.rb +24 -0
- data/lib/moco/entities/project.rb +76 -10
- data/lib/moco/entities/project_contract.rb +50 -0
- data/lib/moco/entities/project_group.rb +38 -0
- data/lib/moco/entities/purchase.rb +90 -0
- data/lib/moco/entities/purchase_bookkeeping_export.rb +34 -0
- data/lib/moco/entities/purchase_budget.rb +47 -0
- data/lib/moco/entities/purchase_category.rb +38 -0
- data/lib/moco/entities/purchase_draft.rb +25 -0
- data/lib/moco/entities/purchase_payment.rb +51 -0
- data/lib/moco/entities/receipt.rb +55 -0
- data/lib/moco/entities/recurring_expense.rb +55 -0
- data/lib/moco/entities/reports/absences.rb +16 -0
- data/lib/moco/entities/reports/cashflow.rb +16 -0
- data/lib/moco/entities/reports/finance.rb +16 -0
- data/lib/moco/entities/reports/utilization.rb +16 -0
- data/lib/moco/entities/schedule.rb +39 -2
- data/lib/moco/entities/tag.rb +30 -0
- data/lib/moco/entities/tagging.rb +27 -0
- data/lib/moco/entities/task.rb +25 -2
- data/lib/moco/entities/task_template.rb +38 -0
- data/lib/moco/entities/unit.rb +36 -0
- data/lib/moco/entities/user.rb +50 -2
- data/lib/moco/entities/user_role.rb +29 -0
- data/lib/moco/entities/vat_code_purchase.rb +29 -0
- data/lib/moco/entities/vat_code_sale.rb +29 -0
- data/lib/moco/entities/web_hook.rb +32 -2
- data/lib/moco/entities/work_time_adjustment.rb +51 -0
- data/lib/moco/version.rb +1 -1
- data/lib/moco.rb +51 -1
- data/moco.gemspec +38 -0
- metadata +47 -8
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO purchase/expense (Ausgaben)
|
|
5
|
+
#
|
|
6
|
+
# == Required attributes for create:
|
|
7
|
+
# date - String, "YYYY-MM-DD" format
|
|
8
|
+
# currency - String, valid currency code (e.g., "EUR", "CHF", "USD")
|
|
9
|
+
# payment_method - String, one of:
|
|
10
|
+
# "bank_transfer", "direct_debit", "credit_card",
|
|
11
|
+
# "paypal", "cash", "bank_transfer_swiss_qr_esr"
|
|
12
|
+
# items - Array of item hashes (at least one required):
|
|
13
|
+
# { title: "Item", total: 100.0, tax: 7.7, tax_included: true }
|
|
14
|
+
#
|
|
15
|
+
# == Optional attributes:
|
|
16
|
+
# title - String, purchase title (auto-generated from items if omitted)
|
|
17
|
+
# due_date - String, "YYYY-MM-DD" payment due date
|
|
18
|
+
# service_period_from - String, "YYYY-MM-DD" service period start
|
|
19
|
+
# service_period_to - String, "YYYY-MM-DD" service period end
|
|
20
|
+
# status - String, "pending" (Inbox) or "archived" (Archive)
|
|
21
|
+
# company_id - Integer, supplier company ID
|
|
22
|
+
# user_id - Integer, responsible user ID
|
|
23
|
+
# receipt_identifier - String, supplier's invoice number
|
|
24
|
+
# info - String, free text notes
|
|
25
|
+
# iban - String, bank account for payment
|
|
26
|
+
# reference - String, payment reference
|
|
27
|
+
# custom_property_values - Hash, custom field values
|
|
28
|
+
# tags - Array of Strings, labels
|
|
29
|
+
# file - Hash, { filename: "doc.pdf", base64: "..." }
|
|
30
|
+
#
|
|
31
|
+
# == Item attributes:
|
|
32
|
+
# title - String, item description
|
|
33
|
+
# total - Float, item total amount
|
|
34
|
+
# tax - Float, tax percentage (e.g., 7.7)
|
|
35
|
+
# tax_included - Boolean, whether total includes tax
|
|
36
|
+
# category_id - Integer, purchase category ID
|
|
37
|
+
#
|
|
38
|
+
# == Read-only attributes:
|
|
39
|
+
# id, identifier, net_total, gross_total, payments (Array),
|
|
40
|
+
# approval_status, file_url, company (Hash), user (Hash),
|
|
41
|
+
# created_at, updated_at
|
|
42
|
+
#
|
|
43
|
+
# == Example:
|
|
44
|
+
# moco.purchases.create(
|
|
45
|
+
# date: "2024-01-15",
|
|
46
|
+
# currency: "EUR",
|
|
47
|
+
# payment_method: "bank_transfer",
|
|
48
|
+
# company_id: 456,
|
|
49
|
+
# items: [
|
|
50
|
+
# { title: "Office supplies", total: 119.0, tax: 19.0, tax_included: true }
|
|
51
|
+
# ],
|
|
52
|
+
# tags: ["Office"]
|
|
53
|
+
# )
|
|
54
|
+
#
|
|
55
|
+
class Purchase < BaseEntity
|
|
56
|
+
# Assign purchase to a project expense
|
|
57
|
+
def assign_to_project(project_id:, project_expense_id: nil)
|
|
58
|
+
payload = { project_id: }
|
|
59
|
+
payload[:project_expense_id] = project_expense_id if project_expense_id
|
|
60
|
+
|
|
61
|
+
client.post("purchases/#{id}/assign_to_project", payload)
|
|
62
|
+
reload
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Update purchase status (pending/archived)
|
|
66
|
+
def update_status(status)
|
|
67
|
+
client.patch("purchases/#{id}/update_status", { status: })
|
|
68
|
+
reload
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Store/upload a document for this purchase
|
|
72
|
+
def store_document(file_data)
|
|
73
|
+
client.patch("purchases/#{id}/store_document", file_data)
|
|
74
|
+
self
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Associations
|
|
78
|
+
def company
|
|
79
|
+
association(:company)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def user
|
|
83
|
+
association(:user)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def to_s
|
|
87
|
+
"#{title} (#{date})"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO purchase bookkeeping export
|
|
5
|
+
# (Ausgaben / Buchhaltungsexporte)
|
|
6
|
+
# Exports purchase data for accounting systems
|
|
7
|
+
#
|
|
8
|
+
# == Read-only attributes:
|
|
9
|
+
# id, from, to, file_url, user (Hash),
|
|
10
|
+
# created_at, updated_at
|
|
11
|
+
#
|
|
12
|
+
# == Filtering:
|
|
13
|
+
# moco.purchase_bookkeeping_exports.all
|
|
14
|
+
# moco.purchase_bookkeeping_exports.where(from: "2024-01-01", to: "2024-01-31")
|
|
15
|
+
#
|
|
16
|
+
# == Note:
|
|
17
|
+
# Bookkeeping exports are generated via MOCO's finance interface.
|
|
18
|
+
# This endpoint provides read-only access to export records.
|
|
19
|
+
#
|
|
20
|
+
class PurchaseBookkeepingExport < BaseEntity
|
|
21
|
+
# Custom path since it's nested under purchases
|
|
22
|
+
def self.entity_path
|
|
23
|
+
"purchases/bookkeeping_exports"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def user
|
|
27
|
+
association(:user, "User")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_s
|
|
31
|
+
"PurchaseBookkeepingExport #{id} (#{from} - #{to})"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO purchase budget (Ausgaben – Budgets)
|
|
5
|
+
# Read-only budget tracking for expense categories
|
|
6
|
+
#
|
|
7
|
+
# == Read-only attributes:
|
|
8
|
+
# id, title, year, target, exhausted, remaining,
|
|
9
|
+
# created_at, updated_at
|
|
10
|
+
#
|
|
11
|
+
# == Helper methods:
|
|
12
|
+
# remaining_percentage - Percentage of budget remaining
|
|
13
|
+
# exhausted_percentage - Percentage of budget used
|
|
14
|
+
#
|
|
15
|
+
# == Example:
|
|
16
|
+
# budgets = moco.purchase_budgets.all
|
|
17
|
+
# budgets.each do |budget|
|
|
18
|
+
# puts "#{budget.title}: #{budget.remaining_percentage}% remaining"
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# == Note:
|
|
22
|
+
# Purchase budgets are configured in MOCO's admin interface.
|
|
23
|
+
# This endpoint provides read-only access for tracking.
|
|
24
|
+
#
|
|
25
|
+
class PurchaseBudget < BaseEntity
|
|
26
|
+
# Custom path since it's nested under purchases
|
|
27
|
+
def self.entity_path
|
|
28
|
+
"purchases/budgets"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_s
|
|
32
|
+
"PurchaseBudget #{id}: #{title} (#{year})"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def remaining_percentage
|
|
36
|
+
return 0 if target.to_f.zero?
|
|
37
|
+
|
|
38
|
+
(remaining.to_f / target.to_f * 100).round(1)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def exhausted_percentage
|
|
42
|
+
return 0 if target.to_f.zero?
|
|
43
|
+
|
|
44
|
+
(exhaused.to_f / target.to_f * 100).round(1)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO purchase category (Ausgaben – Kategorien)
|
|
5
|
+
# Read-only expense categories for organizing purchases
|
|
6
|
+
#
|
|
7
|
+
# == Read-only attributes:
|
|
8
|
+
# id, name, credit_account, active, created_at, updated_at
|
|
9
|
+
#
|
|
10
|
+
# == Example:
|
|
11
|
+
# # List all categories
|
|
12
|
+
# moco.purchase_categories.all
|
|
13
|
+
#
|
|
14
|
+
# # Use category when creating purchase
|
|
15
|
+
# moco.purchases.create(
|
|
16
|
+
# # ... other fields ...
|
|
17
|
+
# items: [{
|
|
18
|
+
# title: "Travel",
|
|
19
|
+
# total: 250.0,
|
|
20
|
+
# tax: 7.7,
|
|
21
|
+
# category_id: 123 # from purchase_categories
|
|
22
|
+
# }]
|
|
23
|
+
# )
|
|
24
|
+
#
|
|
25
|
+
# == Note:
|
|
26
|
+
# Purchase categories are configured in MOCO's admin interface.
|
|
27
|
+
# This endpoint provides read-only access.
|
|
28
|
+
#
|
|
29
|
+
class PurchaseCategory < BaseEntity
|
|
30
|
+
def self.entity_path
|
|
31
|
+
"purchases/categories"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_s
|
|
35
|
+
name.to_s
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO purchase draft
|
|
5
|
+
# Auto-created draft purchases from document scanning
|
|
6
|
+
#
|
|
7
|
+
# == Read-only attributes:
|
|
8
|
+
# id, title, date, company (Hash), file_url,
|
|
9
|
+
# items (Array), created_at, updated_at
|
|
10
|
+
#
|
|
11
|
+
# == Note:
|
|
12
|
+
# Purchase drafts are created automatically when documents
|
|
13
|
+
# are uploaded/scanned in MOCO's inbox.
|
|
14
|
+
# Convert to actual purchases via the MOCO interface.
|
|
15
|
+
#
|
|
16
|
+
class PurchaseDraft < BaseEntity
|
|
17
|
+
def self.entity_path
|
|
18
|
+
"purchases/drafts"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
"Draft ##{id}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO purchase payment record (Ausgaben / Zahlungen)
|
|
5
|
+
# For tracking payments made for purchases
|
|
6
|
+
#
|
|
7
|
+
# == Required attributes for create:
|
|
8
|
+
# date - String, "YYYY-MM-DD" payment date
|
|
9
|
+
# total - Float, payment amount
|
|
10
|
+
#
|
|
11
|
+
# == Optional attributes:
|
|
12
|
+
# purchase_id - Integer, purchase being paid (required unless description set)
|
|
13
|
+
# description - String, payment description (required if no purchase_id)
|
|
14
|
+
#
|
|
15
|
+
# == Read-only attributes:
|
|
16
|
+
# id, purchase (Hash), created_at, updated_at
|
|
17
|
+
#
|
|
18
|
+
# == Example:
|
|
19
|
+
# moco.purchase_payments.create(
|
|
20
|
+
# date: "2024-01-20",
|
|
21
|
+
# purchase_id: 456,
|
|
22
|
+
# total: 1500.0
|
|
23
|
+
# )
|
|
24
|
+
#
|
|
25
|
+
# == Bulk create:
|
|
26
|
+
# moco.post("purchases/payments/bulk", {
|
|
27
|
+
# bulk_data: [
|
|
28
|
+
# { date: "2024-01-20", purchase_id: 123, total: 500 },
|
|
29
|
+
# { date: "2024-01-21", description: "Salaries", total: 10000 }
|
|
30
|
+
# ]
|
|
31
|
+
# })
|
|
32
|
+
#
|
|
33
|
+
# == Filtering:
|
|
34
|
+
# moco.purchase_payments.where(purchase_id: 456)
|
|
35
|
+
# moco.purchase_payments.where(date_from: "2024-01-01", date_to: "2024-01-31")
|
|
36
|
+
#
|
|
37
|
+
class PurchasePayment < BaseEntity
|
|
38
|
+
# Custom path since it's nested under purchases
|
|
39
|
+
def self.entity_path
|
|
40
|
+
"purchases/payments"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def purchase
|
|
44
|
+
association(:purchase, "Purchase")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def to_s
|
|
48
|
+
"PurchasePayment #{id}: #{total} on #{date}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO receipt/expense claim (Spesen)
|
|
5
|
+
#
|
|
6
|
+
# == Required attributes for create:
|
|
7
|
+
# date - String, "YYYY-MM-DD" format
|
|
8
|
+
# title - String, receipt description (e.g., "Team lunch")
|
|
9
|
+
# currency - String, valid currency code (e.g., "EUR", "CHF")
|
|
10
|
+
# items - Array of item hashes (at least one required):
|
|
11
|
+
# { vat_code_id: 186, gross_total: 99.90 }
|
|
12
|
+
#
|
|
13
|
+
# == Optional attributes:
|
|
14
|
+
# project_id - Integer, project to associate with
|
|
15
|
+
# info - String, additional notes
|
|
16
|
+
# billable - Boolean, whether expense is billable to customer
|
|
17
|
+
# attachment - Hash, { filename: "receipt.pdf", base64: "..." }
|
|
18
|
+
#
|
|
19
|
+
# == Item attributes:
|
|
20
|
+
# vat_code_id - Integer, VAT code ID (required)
|
|
21
|
+
# gross_total - Float, total amount including tax (required)
|
|
22
|
+
# purchase_category_id - Integer, expense category
|
|
23
|
+
#
|
|
24
|
+
# == Read-only attributes:
|
|
25
|
+
# id, pending, user (Hash), project (Hash), refund_request (Hash),
|
|
26
|
+
# attachment_url, created_at, updated_at
|
|
27
|
+
#
|
|
28
|
+
# == Example:
|
|
29
|
+
# moco.receipts.create(
|
|
30
|
+
# date: "2024-01-15",
|
|
31
|
+
# title: "Client lunch",
|
|
32
|
+
# currency: "EUR",
|
|
33
|
+
# project_id: 123,
|
|
34
|
+
# billable: true,
|
|
35
|
+
# items: [
|
|
36
|
+
# { vat_code_id: 186, gross_total: 85.50 }
|
|
37
|
+
# ]
|
|
38
|
+
# )
|
|
39
|
+
#
|
|
40
|
+
# == Filtering:
|
|
41
|
+
# moco.receipts.where(from: "2024-01-01", to: "2024-01-31")
|
|
42
|
+
# moco.receipts.where(project_id: 123)
|
|
43
|
+
# moco.receipts.where(user_id: 456)
|
|
44
|
+
#
|
|
45
|
+
class Receipt < BaseEntity
|
|
46
|
+
# Associations
|
|
47
|
+
def user
|
|
48
|
+
association(:user)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def to_s
|
|
52
|
+
"#{title} (#{date})"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO project recurring expense
|
|
5
|
+
# (Wiederkehrende Zusatzleistungen) for ongoing services like hosting
|
|
6
|
+
#
|
|
7
|
+
# == Required attributes for create:
|
|
8
|
+
# start_date - String, "YYYY-MM-DD" when recurring starts
|
|
9
|
+
# period - String, recurrence interval:
|
|
10
|
+
# "weekly", "biweekly", "monthly", "quarterly",
|
|
11
|
+
# "biannual", "annual"
|
|
12
|
+
# title - String, expense name (e.g., "Monthly Hosting")
|
|
13
|
+
# quantity - Float, number of units per period
|
|
14
|
+
# unit - String, unit type (e.g., "Server", "License")
|
|
15
|
+
# unit_price - Float, price per unit
|
|
16
|
+
# unit_cost - Float, internal cost per unit
|
|
17
|
+
#
|
|
18
|
+
# == Optional attributes:
|
|
19
|
+
# finish_date - String, "YYYY-MM-DD" when to stop (null = unlimited)
|
|
20
|
+
# description - String, detailed description
|
|
21
|
+
# billable - Boolean, whether to invoice (default: true)
|
|
22
|
+
# budget_relevant - Boolean, count toward budget (default: false)
|
|
23
|
+
# service_period_direction - String, "none", "forward", "backward"
|
|
24
|
+
# custom_properties - Hash, custom field values
|
|
25
|
+
#
|
|
26
|
+
# == Read-only attributes:
|
|
27
|
+
# id, price, cost, currency, recur_next_date, project (Hash),
|
|
28
|
+
# revenue_category (Hash), created_at, updated_at
|
|
29
|
+
#
|
|
30
|
+
# == Example:
|
|
31
|
+
# moco.post("projects/123/recurring_expenses", {
|
|
32
|
+
# start_date: "2024-01-01",
|
|
33
|
+
# period: "monthly",
|
|
34
|
+
# title: "Web Hosting",
|
|
35
|
+
# quantity: 1,
|
|
36
|
+
# unit: "Server",
|
|
37
|
+
# unit_price: 99.0,
|
|
38
|
+
# unit_cost: 50.0,
|
|
39
|
+
# billable: true
|
|
40
|
+
# })
|
|
41
|
+
#
|
|
42
|
+
# == Note:
|
|
43
|
+
# start_date and period cannot be modified after creation.
|
|
44
|
+
#
|
|
45
|
+
class RecurringExpense < BaseEntity
|
|
46
|
+
# Associations
|
|
47
|
+
def project
|
|
48
|
+
association(:project)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def to_s
|
|
52
|
+
"RecurringExpense ##{id} - #{title}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
module Reports
|
|
5
|
+
# Represents a MOCO absences report (read-only)
|
|
6
|
+
class Absences < BaseEntity
|
|
7
|
+
def self.entity_path
|
|
8
|
+
"report/absences"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
"AbsencesReport"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
module Reports
|
|
5
|
+
# Represents a MOCO cashflow report (read-only)
|
|
6
|
+
class Cashflow < BaseEntity
|
|
7
|
+
def self.entity_path
|
|
8
|
+
"report/cashflow"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
"CashflowReport"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
module Reports
|
|
5
|
+
# Represents a MOCO finance report (read-only)
|
|
6
|
+
class Finance < BaseEntity
|
|
7
|
+
def self.entity_path
|
|
8
|
+
"report/finance"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
"FinanceReport"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
module Reports
|
|
5
|
+
# Represents a MOCO utilization report (read-only)
|
|
6
|
+
class Utilization < BaseEntity
|
|
7
|
+
def self.entity_path
|
|
8
|
+
"report/utilization"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
"UtilizationReport"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -1,8 +1,45 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MOCO
|
|
4
|
-
# Represents a MOCO schedule entry
|
|
5
|
-
#
|
|
4
|
+
# Represents a MOCO schedule entry (absence/time-off)
|
|
5
|
+
# Note: For project planning, use PlanningEntry instead
|
|
6
|
+
#
|
|
7
|
+
# == Required attributes for create:
|
|
8
|
+
# date - String, "YYYY-MM-DD" date of absence
|
|
9
|
+
# absence_code - Integer, type of absence:
|
|
10
|
+
# 1 = unplannable absence
|
|
11
|
+
# 2 = public holiday
|
|
12
|
+
# 3 = sick day
|
|
13
|
+
# 4 = holiday/vacation
|
|
14
|
+
# 5 = other absence
|
|
15
|
+
#
|
|
16
|
+
# == Optional attributes:
|
|
17
|
+
# user_id - Integer, user ID (default: current user)
|
|
18
|
+
# am - Boolean, morning absence (default: true)
|
|
19
|
+
# pm - Boolean, afternoon absence (default: true)
|
|
20
|
+
# comment - String, comment/note
|
|
21
|
+
# symbol - Integer, 1-6 for half day visualization
|
|
22
|
+
#
|
|
23
|
+
# == Read-only attributes:
|
|
24
|
+
# id, assignment (Hash), user (Hash), created_at, updated_at
|
|
25
|
+
#
|
|
26
|
+
# == Example:
|
|
27
|
+
# # Full day vacation
|
|
28
|
+
# moco.schedules.create(
|
|
29
|
+
# date: "2024-01-15",
|
|
30
|
+
# absence_code: 4,
|
|
31
|
+
# user_id: 123,
|
|
32
|
+
# comment: "Annual leave"
|
|
33
|
+
# )
|
|
34
|
+
#
|
|
35
|
+
# # Half day sick (morning only)
|
|
36
|
+
# moco.schedules.create(
|
|
37
|
+
# date: "2024-01-16",
|
|
38
|
+
# absence_code: 3,
|
|
39
|
+
# am: true,
|
|
40
|
+
# pm: false
|
|
41
|
+
# )
|
|
42
|
+
#
|
|
6
43
|
class Schedule < BaseEntity
|
|
7
44
|
# Associations
|
|
8
45
|
def user
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO tag/label
|
|
5
|
+
#
|
|
6
|
+
# == Required attributes for create:
|
|
7
|
+
# name - String, tag name (e.g., "Important")
|
|
8
|
+
# context - String, entity type this tag applies to:
|
|
9
|
+
# "Project", "Contact", "Company", "Deal", "Offer",
|
|
10
|
+
# "Invoice", "Purchase", "User"
|
|
11
|
+
#
|
|
12
|
+
# == Read-only attributes:
|
|
13
|
+
# id, created_at, updated_at
|
|
14
|
+
#
|
|
15
|
+
# == Example:
|
|
16
|
+
# moco.tags.create(
|
|
17
|
+
# name: "Priority",
|
|
18
|
+
# context: "Project"
|
|
19
|
+
# )
|
|
20
|
+
#
|
|
21
|
+
# == Note:
|
|
22
|
+
# To apply tags to entities, use the `tags` attribute when
|
|
23
|
+
# creating/updating the entity: { tags: ["Tag1", "Tag2"] }
|
|
24
|
+
#
|
|
25
|
+
class Tag < BaseEntity
|
|
26
|
+
def to_s
|
|
27
|
+
name.to_s
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO tagging (association between a tag and an entity)
|
|
5
|
+
# This is a read-only entity representing tag assignments.
|
|
6
|
+
#
|
|
7
|
+
# == Read-only attributes:
|
|
8
|
+
# id, entity_id, entity_type, tag (Hash), created_at, updated_at
|
|
9
|
+
#
|
|
10
|
+
# == Note:
|
|
11
|
+
# To apply tags to entities, use the `tags` attribute when
|
|
12
|
+
# creating/updating the entity directly:
|
|
13
|
+
# moco.projects.update(123, tags: ["Priority", "Important"])
|
|
14
|
+
#
|
|
15
|
+
# See also: Tag entity for managing available tags.
|
|
16
|
+
#
|
|
17
|
+
class Tagging < BaseEntity
|
|
18
|
+
# Associations
|
|
19
|
+
def tag
|
|
20
|
+
association(:tag)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_s
|
|
24
|
+
"Tagging ##{id}"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/moco/entities/task.rb
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MOCO
|
|
4
|
-
# Represents a MOCO task
|
|
5
|
-
#
|
|
4
|
+
# Represents a MOCO task (project service/activity type)
|
|
5
|
+
# Tasks are nested under projects: project.tasks.create(...)
|
|
6
|
+
#
|
|
7
|
+
# == Required attributes for create:
|
|
8
|
+
# name - String, task name (e.g., "Development", "Design / UX")
|
|
9
|
+
#
|
|
10
|
+
# == Optional attributes:
|
|
11
|
+
# billable - Boolean, whether time on this task is billable
|
|
12
|
+
# active - Boolean, whether task is active
|
|
13
|
+
# budget - Float/Integer, budget in hours or currency
|
|
14
|
+
# hourly_rate - Float/Integer, rate for this task (used if project billing_variant is "task")
|
|
15
|
+
# description - String, task description
|
|
16
|
+
#
|
|
17
|
+
# == Read-only attributes (returned by API):
|
|
18
|
+
# id, created_at, updated_at
|
|
19
|
+
#
|
|
20
|
+
# == Example:
|
|
21
|
+
# project = moco.projects.find(123)
|
|
22
|
+
# project.tasks.create(
|
|
23
|
+
# name: "Development",
|
|
24
|
+
# billable: true,
|
|
25
|
+
# hourly_rate: 150,
|
|
26
|
+
# budget: 100
|
|
27
|
+
# )
|
|
28
|
+
#
|
|
6
29
|
class Task < BaseEntity
|
|
7
30
|
# Associations
|
|
8
31
|
def project
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO task template (Standardleistungen)
|
|
5
|
+
# Pre-defined task types for projects
|
|
6
|
+
#
|
|
7
|
+
# == Required attributes for create:
|
|
8
|
+
# name - String, task name (e.g., "Development", "Design")
|
|
9
|
+
#
|
|
10
|
+
# == Optional attributes:
|
|
11
|
+
# description - String, task description
|
|
12
|
+
# revenue_category_id - Integer, revenue category for invoicing
|
|
13
|
+
# billable - Boolean, whether tasks are billable by default
|
|
14
|
+
# project_default - Boolean, auto-add to new projects
|
|
15
|
+
# index - Integer, display order (e.g., 10, 20, 30)
|
|
16
|
+
#
|
|
17
|
+
# == Read-only attributes:
|
|
18
|
+
# id, revenue_category (Hash), created_at, updated_at
|
|
19
|
+
#
|
|
20
|
+
# == Example:
|
|
21
|
+
# moco.task_templates.create(
|
|
22
|
+
# name: "Backend Development",
|
|
23
|
+
# description: "Server-side programming",
|
|
24
|
+
# billable: true,
|
|
25
|
+
# project_default: true,
|
|
26
|
+
# index: 10
|
|
27
|
+
# )
|
|
28
|
+
#
|
|
29
|
+
class TaskTemplate < BaseEntity
|
|
30
|
+
def self.entity_path
|
|
31
|
+
"account/task_templates"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_s
|
|
35
|
+
name.to_s
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MOCO
|
|
4
|
+
# Represents a MOCO unit/team (Teams)
|
|
5
|
+
#
|
|
6
|
+
# == Required attributes for create:
|
|
7
|
+
# name - String, team name (e.g., "Development Team")
|
|
8
|
+
#
|
|
9
|
+
# == Read-only attributes:
|
|
10
|
+
# id, users (Array of user hashes), created_at, updated_at
|
|
11
|
+
#
|
|
12
|
+
# == Example:
|
|
13
|
+
# # Create a new team
|
|
14
|
+
# moco.units.create(name: "Marketing Team")
|
|
15
|
+
#
|
|
16
|
+
# # Get users in a team
|
|
17
|
+
# team = moco.units.find(123)
|
|
18
|
+
# team.users # => Array of User objects
|
|
19
|
+
#
|
|
20
|
+
# == Note:
|
|
21
|
+
# To assign users to a team, update the user with unit_id:
|
|
22
|
+
# moco.users.update(user_id, unit_id: team.id)
|
|
23
|
+
#
|
|
24
|
+
# Deleting a unit is only possible if no users are assigned to it.
|
|
25
|
+
#
|
|
26
|
+
class Unit < BaseEntity
|
|
27
|
+
# Get users belonging to this unit
|
|
28
|
+
def users
|
|
29
|
+
has_many(:users, :unit_id)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_s
|
|
33
|
+
name.to_s
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|