Class: HarvestTimeOff::WorkEntryCLI
- Inherits:
-
Object
- Object
- HarvestTimeOff::WorkEntryCLI
- Defined in:
- lib/harvest_time_off/work_entry_cli.rb
Constant Summary collapse
- EXISTING_ENTRY =
2- LOCKED_ENTRY =
3
Class Method Summary collapse
- .option_parser(options) ⇒ Object
- .run(arguments, output: $stdout, error: $stderr, client: nil) ⇒ Object
- .validate!(dates, options) ⇒ Object
Class Method Details
.option_parser(options) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/harvest_time_off/work_entry_cli.rb', line 57 def self.option_parser() OptionParser.new do |opts| opts. = "Usage: harvest-work-entry DATE --project NAME --task NAME --hours HOURS --notes NOTES [--dry-run]" opts.on("--project NAME", "Harvest project name") { |value| [:project] = value } opts.on("--task NAME", "Harvest task name") { |value| [:task] = value } opts.on("--project-id ID", Integer, "Harvest project ID") { |value| [:project_id] = value } opts.on("--task-id ID", Integer, "Harvest task ID") { |value| [:task_id] = value } opts.on("--hours HOURS", Float, "Hours for this entry") { |value| [:hours] = value } opts.on("--notes NOTES", "Entry description") { |value| [:notes] = value } opts.on("--dry-run", "Check for existing entries without writing") { [:dry_run] = true } opts.on("-h", "--help", "Show this help") do puts opts exit 0 end end end |
.run(arguments, output: $stdout, error: $stderr, client: nil) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/harvest_time_off/work_entry_cli.rb', line 8 def self.run(arguments, output: $stdout, error: $stderr, client: nil) = { dry_run: false } parser = option_parser() dates = parser.parse(arguments) validate!(dates, ) spent_date = Date.iso8601(dates.first) client ||= Marlens::HarvestApiV2::Client.from_environment project_id, task_id = if [:project_id] [[:project_id], [:task_id]] else CLI.resolve_assignment(client, [:project], [:task]) end existing_entries = client.request( :get, "/v2/time_entries", params: { project_id:, task_id:, from: spent_date.iso8601, to: spent_date.iso8601 } ).fetch("time_entries") if existing_entries.any? { |entry| entry["is_locked"] } output.puts "Locked existing Harvest entry on #{spent_date.iso8601}; skipped" return LOCKED_ENTRY end if existing_entries.any? output.puts "Existing Harvest entry on #{spent_date.iso8601}; skipped" return EXISTING_ENTRY end if [:dry_run] output.puts "Would create #{spent_date.iso8601}: #{HarvestTimeOff.display_hours([:hours])}h on #{[:project]} / #{[:task]}; #{[:notes]}" return 0 end entry = client.create_time_entry( project_id:, task_id:, spent_date:, hours: [:hours], notes: [:notes] ) output.puts "Created #{spent_date.iso8601}: #{HarvestTimeOff.display_hours([:hours])}h (entry ##{entry.fetch("id")})" 0 rescue Error, Marlens::HarvestApiV2::Error, OptionParser::ParseError, Date::Error => e error.puts "Error: #{e.}" error.puts parser if parser 1 end |
.validate!(dates, options) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/harvest_time_off/work_entry_cli.rb', line 74 def self.validate!(dates, ) raise Error, "DATE is required" unless dates.length == 1 raise Error, "--hours must be a positive finite number" unless [:hours]&.positive? && [:hours].finite? raise Error, "--notes is required" unless [:notes] && ![:notes].empty? names_provided = [:project] || [:task] ids_provided = [:project_id] || [:task_id] valid_names = [:project] && [:task] valid_ids = [:project_id] && [:task_id] raise Error, "supply --project and --task, or --project-id and --task-id" unless valid_names || valid_ids raise Error, "do not combine project/task names with IDs" if names_provided && ids_provided end |