instance_accountant 0.0.1
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 +7 -0
 - data/LICENSE.txt +12 -0
 - data/README.md +76 -0
 - data/Rakefile +6 -0
 - data/bin/instance_accountant +10 -0
 - data/instance_accountant.gemspec +43 -0
 - data/lib/instance_accountant/cli.rb +123 -0
 - data/lib/instance_accountant/filer.rb +37 -0
 - data/lib/instance_accountant/hour.rb +28 -0
 - data/lib/instance_accountant/journal_entry.rb +116 -0
 - data/lib/instance_accountant/poster.rb +52 -0
 - data/lib/instance_accountant.rb +8 -0
 - data/spec/helpers/minitest.rb +83 -0
 - data/spec/helpers/rspec.rb +25 -0
 - data/spec/helpers.rb +9 -0
 - data/spec/instance_accountant/cli_spec.rb +7 -0
 - data/spec/instance_accountant/filer_spec.rb +72 -0
 - data/spec/instance_accountant/hour_spec.rb +136 -0
 - data/spec/instance_accountant/journal_entry_spec.rb +178 -0
 - data/spec/instance_accountant/poster_spec.rb +109 -0
 - metadata +226 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 659797969092d787410c4789f8379c33b9b10ccb
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 0c858e6a0c0a6ae6f7bec5877cbbf450f6de665c
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: a442d471310a881effe735f4b7d6ff5118af02e238e20e908178e5e845409cc51a4c123e08e9f0acebac655badec7cc0fbd4278a7e8a21d20c95d03132015af6
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: cb5df07e2c58e9905134bf3d1683846f1ddeaa41cffb503b68e6dc6c99d5fb36a7119693c31e86553cf64a0e2b71ac3093636bf527a796528a68c17e0141f872
         
     | 
    
        data/LICENSE.txt
    ADDED
    
    | 
         @@ -0,0 +1,12 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2014, Subledger, Inc.
         
     | 
| 
      
 2 
     | 
    
         
            +
            All rights reserved.
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Subledger instance accountant Ruby gem
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Installation:
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                gem install instance_accountant
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Gemfile:
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                gem 'instance_accountant'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            The gem provides an executable that can be invoked two ways:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            If you want to account for the hourly cost of instances, use this form:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                instance_accountant account                                          \
         
     | 
| 
      
 16 
     | 
    
         
            +
                  --description       'instance usage for: %s'                       \
         
     | 
| 
      
 17 
     | 
    
         
            +
                  --reference         'http://test.com/journal_entry'                \
         
     | 
| 
      
 18 
     | 
    
         
            +
                  --cost              0.1                                            \
         
     | 
| 
      
 19 
     | 
    
         
            +
                  --cost_description  'cost for: %s'                                 \
         
     | 
| 
      
 20 
     | 
    
         
            +
                  --cost_reference    'http://test.com/cost'                         \
         
     | 
| 
      
 21 
     | 
    
         
            +
                  --expense_acct      subledger_account_id                           \
         
     | 
| 
      
 22 
     | 
    
         
            +
                  --payable_acct      subledger_account_id                           \
         
     | 
| 
      
 23 
     | 
    
         
            +
                  --key_id            subledger_key_id                               \
         
     | 
| 
      
 24 
     | 
    
         
            +
                  --secret            subledger_secret                               \
         
     | 
| 
      
 25 
     | 
    
         
            +
                  --org_id            subledger_org_id                               \
         
     | 
| 
      
 26 
     | 
    
         
            +
                  --book_id           subledger_book_id                              \
         
     | 
| 
      
 27 
     | 
    
         
            +
                  --daemon
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            If you want to account for both the hourly cost of instances, and hourly income instances, use this form:
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                instance_accountant account                                          \
         
     | 
| 
      
 32 
     | 
    
         
            +
                  --description       'instance usage for: %s'                       \
         
     | 
| 
      
 33 
     | 
    
         
            +
                  --reference         'http://test.com/journal_entry'                \
         
     | 
| 
      
 34 
     | 
    
         
            +
                  --cost              0.1                                            \
         
     | 
| 
      
 35 
     | 
    
         
            +
                  --cost_description  'cost for: %s'                                 \
         
     | 
| 
      
 36 
     | 
    
         
            +
                  --cost_reference    'http://test.com/cost'                         \
         
     | 
| 
      
 37 
     | 
    
         
            +
                  --expense_acct      subledger_account_id                           \
         
     | 
| 
      
 38 
     | 
    
         
            +
                  --payable_acct      subledger_account_id                           \
         
     | 
| 
      
 39 
     | 
    
         
            +
                  --price             0.2                                            \
         
     | 
| 
      
 40 
     | 
    
         
            +
                  --price_description 'price for: %s'                                \
         
     | 
| 
      
 41 
     | 
    
         
            +
                  --price_reference   'http://test.com/price'                        \
         
     | 
| 
      
 42 
     | 
    
         
            +
                  --receivable_acct   subledger_account_id                           \
         
     | 
| 
      
 43 
     | 
    
         
            +
                  --income_acct       subledger_account_id                           \
         
     | 
| 
      
 44 
     | 
    
         
            +
                  --key_id            subledger_key_id                               \
         
     | 
| 
      
 45 
     | 
    
         
            +
                  --secret            subledger_secret                               \
         
     | 
| 
      
 46 
     | 
    
         
            +
                  --org_id            subledger_org_id                               \
         
     | 
| 
      
 47 
     | 
    
         
            +
                  --book_id           subledger_book_id                              \
         
     | 
| 
      
 48 
     | 
    
         
            +
                  --daemon
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            Note: %s in descriptions will be replaced by the ISO 8601 of the hour in UTC
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            Here's a complete set of options:
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                Options:
         
     | 
| 
      
 55 
     | 
    
         
            +
                  f, [--filepath=FILEPATH]
         
     | 
| 
      
 56 
     | 
    
         
            +
                                                               # Default: ~/.instance_accountant
         
     | 
| 
      
 57 
     | 
    
         
            +
                  d, --description=DESCRIPTION
         
     | 
| 
      
 58 
     | 
    
         
            +
                                                               # Default: instance usage for
         
     | 
| 
      
 59 
     | 
    
         
            +
                      [--reference=REFERENCE]
         
     | 
| 
      
 60 
     | 
    
         
            +
                  c, --cost=COST
         
     | 
| 
      
 61 
     | 
    
         
            +
                      [--cost-description=COST_DESCRIPTION]
         
     | 
| 
      
 62 
     | 
    
         
            +
                                                               # Default: cost for
         
     | 
| 
      
 63 
     | 
    
         
            +
                      [--cost-reference=COST_REFERENCE]
         
     | 
| 
      
 64 
     | 
    
         
            +
                  e, --expense-acct=EXPENSE_ACCT
         
     | 
| 
      
 65 
     | 
    
         
            +
                  p, --payable-acct=PAYABLE_ACCT
         
     | 
| 
      
 66 
     | 
    
         
            +
                  p, [--price=PRICE]
         
     | 
| 
      
 67 
     | 
    
         
            +
                      [--price-description=PRICE_DESCRIPTION]
         
     | 
| 
      
 68 
     | 
    
         
            +
                                                               # Default: price for
         
     | 
| 
      
 69 
     | 
    
         
            +
                      [--price-reference=PRICE_REFERENCE]
         
     | 
| 
      
 70 
     | 
    
         
            +
                  i, [--income-acct=INCOME_ACCT]
         
     | 
| 
      
 71 
     | 
    
         
            +
                  r, [--receivable-acct=RECEIVABLE_ACCT]
         
     | 
| 
      
 72 
     | 
    
         
            +
                  k, --key-id=KEY_ID
         
     | 
| 
      
 73 
     | 
    
         
            +
                  s, --secret=SECRET
         
     | 
| 
      
 74 
     | 
    
         
            +
                  o, --org-id=ORG_ID
         
     | 
| 
      
 75 
     | 
    
         
            +
                  b, --book-id=BOOK_ID
         
     | 
| 
      
 76 
     | 
    
         
            +
                      [--daemon], [--no-daemon]
         
     | 
    
        data/Rakefile
    ADDED
    
    
| 
         @@ -0,0 +1,43 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            $LOAD_PATH.unshift 'lib'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require 'instance_accountant'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Gem::Specification.new do |gem|
         
     | 
| 
      
 8 
     | 
    
         
            +
              gem.authors       = [ 'Tom Mornini', 'John McKee' ]
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              gem.files         = Dir.glob( 'lib/**/*.rb' )
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              gem.files        << 'instance_accountant.gemspec'
         
     | 
| 
      
 13 
     | 
    
         
            +
              gem.files        << 'LICENSE.txt'
         
     | 
| 
      
 14 
     | 
    
         
            +
              gem.files        << 'Rakefile'
         
     | 
| 
      
 15 
     | 
    
         
            +
              gem.files        << 'README.md'
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              gem.test_files    = Dir.glob( 'spec/**/*.rb' )
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              gem.name          = 'instance_accountant'
         
     | 
| 
      
 20 
     | 
    
         
            +
              gem.description   = 'account for hourly instance usage using Subledger'
         
     | 
| 
      
 21 
     | 
    
         
            +
              gem.summary       = 'account for hourly instance usage using Subledger'
         
     | 
| 
      
 22 
     | 
    
         
            +
              gem.version       = InstanceAccountant::VERSION
         
     | 
| 
      
 23 
     | 
    
         
            +
              gem.email         = 'admin@subledger.com'
         
     | 
| 
      
 24 
     | 
    
         
            +
              gem.licenses      = ['BSD 3-Clause']
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              gem.homepage      = 'https://github.com/subledger/instance_accountant'
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              gem.bindir        = 'bin'
         
     | 
| 
      
 29 
     | 
    
         
            +
              gem.executables   = 'instance_accountant'
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              gem.add_runtime_dependency     'subledger',          '~> 0.7'
         
     | 
| 
      
 32 
     | 
    
         
            +
              gem.add_runtime_dependency     'thor',               '~> 0.19'
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              gem.add_development_dependency 'guard',              '~> 2.8'
         
     | 
| 
      
 35 
     | 
    
         
            +
              gem.add_development_dependency 'guard-minitest',     '~> 2.3'
         
     | 
| 
      
 36 
     | 
    
         
            +
              gem.add_development_dependency 'guard-rubocop',      '~> 1.1'
         
     | 
| 
      
 37 
     | 
    
         
            +
              gem.add_development_dependency 'minitest',           '~> 5.4'
         
     | 
| 
      
 38 
     | 
    
         
            +
              gem.add_development_dependency 'rake',               '~> 10.3'
         
     | 
| 
      
 39 
     | 
    
         
            +
              gem.add_development_dependency 'rb-fsevent',         '~> 0.9'
         
     | 
| 
      
 40 
     | 
    
         
            +
              gem.add_development_dependency 'rspec-expectations', '~> 3.1'
         
     | 
| 
      
 41 
     | 
    
         
            +
              gem.add_development_dependency 'rspec-mocks',        '~> 3.1'
         
     | 
| 
      
 42 
     | 
    
         
            +
              gem.add_development_dependency 'rubocop',            '~> 0.27'
         
     | 
| 
      
 43 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,123 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'thor'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'instance_accountant'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module InstanceAccountant
         
     | 
| 
      
 7 
     | 
    
         
            +
              class CLI < Thor
         
     | 
| 
      
 8 
     | 
    
         
            +
                desc 'account', 'Accounts for hours in Subledger'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                method_option :filepath,
         
     | 
| 
      
 11 
     | 
    
         
            +
                              aliases: :f,
         
     | 
| 
      
 12 
     | 
    
         
            +
                              default: '~/.instance_accountant'
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                method_option :description,
         
     | 
| 
      
 15 
     | 
    
         
            +
                              aliases:  :d,
         
     | 
| 
      
 16 
     | 
    
         
            +
                              required: true,
         
     | 
| 
      
 17 
     | 
    
         
            +
                              default:  'instance usage for'
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                method_option :reference
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                method_option :cost,
         
     | 
| 
      
 22 
     | 
    
         
            +
                              aliases:  :c,
         
     | 
| 
      
 23 
     | 
    
         
            +
                              required: true
         
     | 
| 
      
 24 
     | 
    
         
            +
                method_option :cost_description,
         
     | 
| 
      
 25 
     | 
    
         
            +
                              default: 'cost for'
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                method_option :cost_reference
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                method_option :expense_acct,
         
     | 
| 
      
 30 
     | 
    
         
            +
                              aliases:  :e,
         
     | 
| 
      
 31 
     | 
    
         
            +
                              required: true
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                method_option :payable_acct,
         
     | 
| 
      
 34 
     | 
    
         
            +
                              aliases:  :p,
         
     | 
| 
      
 35 
     | 
    
         
            +
                              required: true
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                method_option :price,
         
     | 
| 
      
 38 
     | 
    
         
            +
                              aliases: :p
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                method_option :price_description,
         
     | 
| 
      
 41 
     | 
    
         
            +
                              default: 'price for'
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                method_option :price_reference
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                method_option :income_acct,
         
     | 
| 
      
 46 
     | 
    
         
            +
                              aliases: :i
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                method_option :receivable_acct,
         
     | 
| 
      
 49 
     | 
    
         
            +
                              aliases: :r
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                method_option :key_id,
         
     | 
| 
      
 52 
     | 
    
         
            +
                              aliases:  :k,
         
     | 
| 
      
 53 
     | 
    
         
            +
                              required: true
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                method_option :secret,
         
     | 
| 
      
 56 
     | 
    
         
            +
                              aliases:  :s,
         
     | 
| 
      
 57 
     | 
    
         
            +
                              required: true
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                method_option :org_id,
         
     | 
| 
      
 60 
     | 
    
         
            +
                              aliases:  :o,
         
     | 
| 
      
 61 
     | 
    
         
            +
                              required: true
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                method_option :book_id,
         
     | 
| 
      
 64 
     | 
    
         
            +
                              aliases:  :b,
         
     | 
| 
      
 65 
     | 
    
         
            +
                              required: true
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                method_option :daemon, type: :boolean
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                SIGNALS = []
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                TWENTY_MINUTES = 20 * 60
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                %w(ABRT ALRM HUP INT STOP TERM QUIT).each do |signal|
         
     | 
| 
      
 74 
     | 
    
         
            +
                  Signal.trap signal do
         
     | 
| 
      
 75 
     | 
    
         
            +
                    SIGNALS << signal
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                def account
         
     | 
| 
      
 80 
     | 
    
         
            +
                  if price_but_not_income_and_receivable options
         
     | 
| 
      
 81 
     | 
    
         
            +
                    STDERR.puts '--price requires --income_acct and --receivable_acct'
         
     | 
| 
      
 82 
     | 
    
         
            +
                    exit 0
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  i = 0
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 88 
     | 
    
         
            +
                    consider_posting i, options
         
     | 
| 
      
 89 
     | 
    
         
            +
                    consider_exiting
         
     | 
| 
      
 90 
     | 
    
         
            +
                    sleep 1
         
     | 
| 
      
 91 
     | 
    
         
            +
                    i += 1
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                private
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                def consider_posting i, options
         
     | 
| 
      
 98 
     | 
    
         
            +
                  Poster.new(options).post(Hour.new, Time.now) if posting_required? i
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                def posting_required? i
         
     | 
| 
      
 102 
     | 
    
         
            +
                  (i % TWENTY_MINUTES).zero? or signal?
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                def consider_exiting
         
     | 
| 
      
 106 
     | 
    
         
            +
                  exit 1 if signal?
         
     | 
| 
      
 107 
     | 
    
         
            +
                  exit 0 if not_daemon?
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                def signal?
         
     | 
| 
      
 111 
     | 
    
         
            +
                  SIGNALS.length > 0
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                def not_daemon?
         
     | 
| 
      
 115 
     | 
    
         
            +
                  options[:daemon].nil?
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                def price_but_not_income_and_receivable options
         
     | 
| 
      
 119 
     | 
    
         
            +
                  options[:price] and
         
     | 
| 
      
 120 
     | 
    
         
            +
                    ! (options[:income_acct] and options[:receivable_acct])
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
              end
         
     | 
| 
      
 123 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module InstanceAccountant
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Filer
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize options = { }
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @file_klass = options[:file_klass] || File
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @time_klass = options[:time_klass] || Time
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  @filepath = @file_klass.expand_path options[:filepath]
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def read
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @time_klass.parse @file_klass.open( @filepath,
         
     | 
| 
      
 14 
     | 
    
         
            +
                                                      File::RDWR | File::CREAT,
         
     | 
| 
      
 15 
     | 
    
         
            +
                                                      0644 ) do |file|
         
     | 
| 
      
 16 
     | 
    
         
            +
                    file.flock File::LOCK_EX
         
     | 
| 
      
 17 
     | 
    
         
            +
                    file.read
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                rescue
         
     | 
| 
      
 20 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def write hour
         
     | 
| 
      
 24 
     | 
    
         
            +
                  hour_string = hour.to_s
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  @file_klass.open( @filepath,
         
     | 
| 
      
 27 
     | 
    
         
            +
                                    File::RDWR | File::CREAT,
         
     | 
| 
      
 28 
     | 
    
         
            +
                                    0644 ) do |file|
         
     | 
| 
      
 29 
     | 
    
         
            +
                    file.flock File::LOCK_EX
         
     | 
| 
      
 30 
     | 
    
         
            +
                    file.rewind
         
     | 
| 
      
 31 
     | 
    
         
            +
                    file.write hour_string
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  hour_string
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'time'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module InstanceAccountant
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Hour
         
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize options = { }
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @time = options[:time] ? options[:time].utc : now(options)
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def == other
         
     | 
| 
      
 11 
     | 
    
         
            +
                  hour_string == other.hour_string
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @time.iso8601
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def hour_string
         
     | 
| 
      
 19 
     | 
    
         
            +
                  to_s[0..12] + ':00:00Z'
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                private
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def now options
         
     | 
| 
      
 25 
     | 
    
         
            +
                  (options[:time_klass] || ::Time).now.utc
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,116 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'subledger'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module InstanceAccountant
         
     | 
| 
      
 5 
     | 
    
         
            +
              class JournalEntry
         
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize options = { }
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @options = options
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  @subledger = options[:subledger] || Subledger.new(@options.dup)
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def hash_for hour, now
         
     | 
| 
      
 13 
     | 
    
         
            +
                  hour_string = hour.hour_string
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  lines = cost_lines hour_string
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  lines += price_lines(hour_string) if include_price_lines?
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  hash = {
         
     | 
| 
      
 20 
     | 
    
         
            +
                    effective_at: now,
         
     | 
| 
      
 21 
     | 
    
         
            +
                    description:  description(hour_string),
         
     | 
| 
      
 22 
     | 
    
         
            +
                    lines:        lines
         
     | 
| 
      
 23 
     | 
    
         
            +
                  }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  hash.merge!(reference: @options[:reference]) if @options[:reference]
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  hash
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                private
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def include_price_lines?
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @options[:receivable_acct]     and
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @options[:income_acct]       and
         
     | 
| 
      
 35 
     | 
    
         
            +
                    @options[:price]
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def description hour_string
         
     | 
| 
      
 39 
     | 
    
         
            +
                  format @options[:description], hour_string
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def cost_lines hour_string
         
     | 
| 
      
 43 
     | 
    
         
            +
                  lines = [ ]
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  common = { description: @options[:cost_description],
         
     | 
| 
      
 46 
     | 
    
         
            +
                             reference:   @options[:cost_reference] }
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  lines << complete(
         
     | 
| 
      
 49 
     | 
    
         
            +
                             hour_string,
         
     | 
| 
      
 50 
     | 
    
         
            +
                             common.merge( account: expense_acct,
         
     | 
| 
      
 51 
     | 
    
         
            +
                                           value:   @subledger.debit(@options[:cost]) ) )
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  lines << complete(
         
     | 
| 
      
 54 
     | 
    
         
            +
                             hour_string,
         
     | 
| 
      
 55 
     | 
    
         
            +
                             common.merge( account: payable_acct,
         
     | 
| 
      
 56 
     | 
    
         
            +
                                           value:   @subledger.credit(@options[:cost]) ) )
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  lines
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def price_lines hour_string
         
     | 
| 
      
 62 
     | 
    
         
            +
                  lines = [ ]
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  common = { description: @options[:price_description],
         
     | 
| 
      
 65 
     | 
    
         
            +
                             reference:   @options[:price_reference] }
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  lines << complete(
         
     | 
| 
      
 68 
     | 
    
         
            +
                             hour_string,
         
     | 
| 
      
 69 
     | 
    
         
            +
                             common.merge( account: receivable_acct,
         
     | 
| 
      
 70 
     | 
    
         
            +
                                           value:   @subledger.debit(@options[:price]) ) )
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  lines << complete(
         
     | 
| 
      
 73 
     | 
    
         
            +
                             hour_string,
         
     | 
| 
      
 74 
     | 
    
         
            +
                             common.merge( account: income_acct,
         
     | 
| 
      
 75 
     | 
    
         
            +
                                           value:   @subledger.credit(@options[:price]) ) )
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  lines
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def complete hour_string, args
         
     | 
| 
      
 81 
     | 
    
         
            +
                  description = args[:description].nil? ? nil : description(hour_string)
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  if description
         
     | 
| 
      
 84 
     | 
    
         
            +
                    args.merge! description: description
         
     | 
| 
      
 85 
     | 
    
         
            +
                  else
         
     | 
| 
      
 86 
     | 
    
         
            +
                    args.delete :description
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                  reference = args[:reference]
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  if reference
         
     | 
| 
      
 92 
     | 
    
         
            +
                    args.merge! reference: reference
         
     | 
| 
      
 93 
     | 
    
         
            +
                  else
         
     | 
| 
      
 94 
     | 
    
         
            +
                    args.delete :reference
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  args
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                def expense_acct
         
     | 
| 
      
 101 
     | 
    
         
            +
                  @subledger.account id: @options[:expense_acct]
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                def payable_acct
         
     | 
| 
      
 105 
     | 
    
         
            +
                  @subledger.account id: @options[:payable_acct]
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                def receivable_acct
         
     | 
| 
      
 109 
     | 
    
         
            +
                  @subledger.account id: @options[:receivable_acct]
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                def income_acct
         
     | 
| 
      
 113 
     | 
    
         
            +
                  @subledger.account id: @options[:income_acct]
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,52 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'subledger'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'time'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            require 'instance_accountant/filer'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'instance_accountant/hour'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'instance_accountant/journal_entry'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            module InstanceAccountant
         
     | 
| 
      
 11 
     | 
    
         
            +
              class Poster
         
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize options = { }
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @options = options
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  @time_klass = @options[:time_klass] || Time
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @hour_klass = @options[:hour_klass] || Hour
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  @subledger     = @options[:subledger]     || Subledger.new(@options.dup)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @filer         = @options[:filer]         || Filer.new(@options)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @journal_entry = @options[:journal_entry] || JournalEntry.new(@options)
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def post hour, now
         
     | 
| 
      
 24 
     | 
    
         
            +
                  if posted? hour
         
     | 
| 
      
 25 
     | 
    
         
            +
                    false
         
     | 
| 
      
 26 
     | 
    
         
            +
                  else
         
     | 
| 
      
 27 
     | 
    
         
            +
                    write hour, now
         
     | 
| 
      
 28 
     | 
    
         
            +
                    true
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                private
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def posted? hour
         
     | 
| 
      
 35 
     | 
    
         
            +
                  file_time = @filer.read
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  if file_time.nil?
         
     | 
| 
      
 38 
     | 
    
         
            +
                    false
         
     | 
| 
      
 39 
     | 
    
         
            +
                  else
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @hour_klass.new( time: file_time ) == hour
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def write hour, now
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @subledger
         
     | 
| 
      
 46 
     | 
    
         
            +
                    .journal_entry
         
     | 
| 
      
 47 
     | 
    
         
            +
                    .create_and_post( @journal_entry.hash_for hour, now )
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  @filer.write hour
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,83 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'singleton'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            gem 'minitest'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            require 'minitest/spec'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            require 'minitest/pride' unless ENV['SUBLEDGER_ENV'] == 'ci'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require 'minitest/autorun'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            MiniTest::Test.parallelize_me!
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            module Kernel
         
     | 
| 
      
 15 
     | 
    
         
            +
              def Class thing, &block
         
     | 
| 
      
 16 
     | 
    
         
            +
                describe_set_subject thing, &block
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              def Constant thing, &block
         
     | 
| 
      
 20 
     | 
    
         
            +
                describe_set_subject thing, &block
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              def Module thing, &block
         
     | 
| 
      
 24 
     | 
    
         
            +
                describe_set_subject thing, &block
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              def Instance &block
         
     | 
| 
      
 28 
     | 
    
         
            +
                describe 'instance', &block
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              def RespondsTo desc, &block
         
     | 
| 
      
 32 
     | 
    
         
            +
                describe "responds to #{desc}", &block
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def When desc, &block
         
     | 
| 
      
 36 
     | 
    
         
            +
                describe "when #{desc}", &block
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              def And desc, &block
         
     | 
| 
      
 40 
     | 
    
         
            +
                describe "and #{desc}", &block
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              def RoleTest desc
         
     | 
| 
      
 44 
     | 
    
         
            +
                load Subledger::ROOT + "/spec/roles/#{desc}_spec.rb"
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              private
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              # Thanks Anton Lindqvist!
         
     | 
| 
      
 50 
     | 
    
         
            +
              # https://github.com/mptre/minitest-implicit-subject
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              def describe_set_subject *args, &block
         
     | 
| 
      
 53 
     | 
    
         
            +
                cls = describe *args, &block
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                subject = args.first
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                if subject.respond_to?(:included_modules) &&
         
     | 
| 
      
 58 
     | 
    
         
            +
                   Array(subject.included_modules).include?(Singleton)
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  subject = subject.instance
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                cls.subject { subject }
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                cls
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
            end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            module MiniTest
         
     | 
| 
      
 70 
     | 
    
         
            +
              class Spec
         
     | 
| 
      
 71 
     | 
    
         
            +
                def self.ByRaising desc, &block
         
     | 
| 
      
 72 
     | 
    
         
            +
                  it "by raising #{desc}", &block
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                def self.ByReturning desc, &block
         
     | 
| 
      
 76 
     | 
    
         
            +
                  it "by returning #{desc}", &block
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                def self.ByYielding desc, &block
         
     | 
| 
      
 80 
     | 
    
         
            +
                  it "by yielding #{desc}", &block
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rspec/expectations'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rspec/mocks'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module MiniTest
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Test
         
     | 
| 
      
 7 
     | 
    
         
            +
                include ::RSpec::Mocks::ExampleMethods
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def before_setup
         
     | 
| 
      
 10 
     | 
    
         
            +
                  ::RSpec::Mocks.setup
         
     | 
| 
      
 11 
     | 
    
         
            +
                  super
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def after_teardown
         
     | 
| 
      
 15 
     | 
    
         
            +
                  super
         
     | 
| 
      
 16 
     | 
    
         
            +
                  ::RSpec::Mocks.verify
         
     | 
| 
      
 17 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 18 
     | 
    
         
            +
                  ::RSpec::Mocks.teardown
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              class Spec
         
     | 
| 
      
 23 
     | 
    
         
            +
                include RSpec::Matchers
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/helpers.rb
    ADDED
    
    
| 
         @@ -0,0 +1,72 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'helpers'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'instance_accountant/filer'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module InstanceAccountant
         
     | 
| 
      
 7 
     | 
    
         
            +
              Class File do
         
     | 
| 
      
 8 
     | 
    
         
            +
                Instance do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  subject { Filer.new options }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  let(:options) do
         
     | 
| 
      
 12 
     | 
    
         
            +
                    {
         
     | 
| 
      
 13 
     | 
    
         
            +
                      filepath:   filepath,
         
     | 
| 
      
 14 
     | 
    
         
            +
                      file_klass: file_klass,
         
     | 
| 
      
 15 
     | 
    
         
            +
                      time_klass: time_klass
         
     | 
| 
      
 16 
     | 
    
         
            +
                    }
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  let(:filepath)          { double 'filepath'          }
         
     | 
| 
      
 20 
     | 
    
         
            +
                  let(:expanded_filepath) { double 'expanded_filepath' }
         
     | 
| 
      
 21 
     | 
    
         
            +
                  let(:file_klass)        { double 'file_klass'        }
         
     | 
| 
      
 22 
     | 
    
         
            +
                  let(:time_klass)        { double 'time_klass'        }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  let(:time_inst)         { double 'time_inst'         }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  let(:time_string)       { double 'time_string' }
         
     | 
| 
      
 26 
     | 
    
         
            +
                  let(:hour)              { double 'hour'        }
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  RespondsTo :read do
         
     | 
| 
      
 29 
     | 
    
         
            +
                    When 'it has been written before' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                      ByReturning 'a Time' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                        expect(file_klass)
         
     | 
| 
      
 32 
     | 
    
         
            +
                          .to receive(:expand_path)
         
     | 
| 
      
 33 
     | 
    
         
            +
                          .with(filepath)
         
     | 
| 
      
 34 
     | 
    
         
            +
                          .and_return(expanded_filepath)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                        expect(file_klass)
         
     | 
| 
      
 37 
     | 
    
         
            +
                          .to receive(:open)
         
     | 
| 
      
 38 
     | 
    
         
            +
                          .with(expanded_filepath, File::RDWR | File::CREAT, 0644)
         
     | 
| 
      
 39 
     | 
    
         
            +
                          .and_return(time_string)
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                        expect(time_klass)
         
     | 
| 
      
 42 
     | 
    
         
            +
                          .to receive(:parse)
         
     | 
| 
      
 43 
     | 
    
         
            +
                          .with(time_string)
         
     | 
| 
      
 44 
     | 
    
         
            +
                          .and_return(time_inst)
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                        subject.read.must_be_same_as time_inst
         
     | 
| 
      
 47 
     | 
    
         
            +
                      end
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  RespondsTo :write do
         
     | 
| 
      
 52 
     | 
    
         
            +
                    ByReturning 'the hour' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                      expect(file_klass)
         
     | 
| 
      
 54 
     | 
    
         
            +
                        .to receive(:expand_path)
         
     | 
| 
      
 55 
     | 
    
         
            +
                        .with(filepath)
         
     | 
| 
      
 56 
     | 
    
         
            +
                        .and_return(expanded_filepath)
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                      expect(hour)
         
     | 
| 
      
 59 
     | 
    
         
            +
                        .to receive(:to_s)
         
     | 
| 
      
 60 
     | 
    
         
            +
                        .and_return(time_string)
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                      expect(file_klass)
         
     | 
| 
      
 63 
     | 
    
         
            +
                        .to receive(:open)
         
     | 
| 
      
 64 
     | 
    
         
            +
                        .with(expanded_filepath, File::RDWR | File::CREAT, 0644)
         
     | 
| 
      
 65 
     | 
    
         
            +
                        .and_return(time_string)
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                      subject.write(hour).must_be_same_as time_string
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,136 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'helpers'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'instance_accountant/hour'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module InstanceAccountant
         
     | 
| 
      
 7 
     | 
    
         
            +
              Class Hour do
         
     | 
| 
      
 8 
     | 
    
         
            +
                Instance do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  subject { Hour.new options }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  let(:options) do
         
     | 
| 
      
 12 
     | 
    
         
            +
                    {
         
     | 
| 
      
 13 
     | 
    
         
            +
                      time_klass: time_klass
         
     | 
| 
      
 14 
     | 
    
         
            +
                    }
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  let(:time_klass)  { double 'time_klass'     }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  let(:time_local)  { double 'time_local'     }
         
     | 
| 
      
 20 
     | 
    
         
            +
                  let(:time_utc)    { double 'time_utc'       }
         
     | 
| 
      
 21 
     | 
    
         
            +
                  let(:time_iso)    { double 'time_iso'       }
         
     | 
| 
      
 22 
     | 
    
         
            +
                  let(:hour_string) { double 'hour_string'    }
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  let(:other_hour)        { double 'other_hour'        }
         
     | 
| 
      
 25 
     | 
    
         
            +
                  let(:other_hour_string) { double 'other_hour_string' }
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  let(:other_time_local)  { double 'other_time_local'  }
         
     | 
| 
      
 28 
     | 
    
         
            +
                  let(:other_time_utc)    { double 'other_time_utc'    }
         
     | 
| 
      
 29 
     | 
    
         
            +
                  let(:other_time_iso)    { double 'other_time_iso'    }
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  RespondsTo :to_s do
         
     | 
| 
      
 32 
     | 
    
         
            +
                    ByReturning 'an hour string' do
         
     | 
| 
      
 33 
     | 
    
         
            +
                      expect(time_klass)
         
     | 
| 
      
 34 
     | 
    
         
            +
                        .to receive(:now)
         
     | 
| 
      
 35 
     | 
    
         
            +
                        .and_return(time_local)
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                      expect(time_local)
         
     | 
| 
      
 38 
     | 
    
         
            +
                        .to receive(:utc)
         
     | 
| 
      
 39 
     | 
    
         
            +
                        .and_return(time_utc)
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                      expect(time_utc)
         
     | 
| 
      
 42 
     | 
    
         
            +
                        .to receive(:iso8601)
         
     | 
| 
      
 43 
     | 
    
         
            +
                        .and_return(time_iso)
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                      subject.to_s.must_equal time_iso
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  RespondsTo :hour_string do
         
     | 
| 
      
 50 
     | 
    
         
            +
                    ByReturning 'an hour string' do
         
     | 
| 
      
 51 
     | 
    
         
            +
                      expect(time_klass)
         
     | 
| 
      
 52 
     | 
    
         
            +
                        .to receive(:now)
         
     | 
| 
      
 53 
     | 
    
         
            +
                        .and_return(time_local)
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                      expect(time_local)
         
     | 
| 
      
 56 
     | 
    
         
            +
                        .to receive(:utc)
         
     | 
| 
      
 57 
     | 
    
         
            +
                        .and_return(time_utc)
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                      expect(time_utc)
         
     | 
| 
      
 60 
     | 
    
         
            +
                        .to receive(:iso8601)
         
     | 
| 
      
 61 
     | 
    
         
            +
                        .and_return('2014-11-05T00')
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                      subject.hour_string.must_equal '2014-11-05T00:00:00Z'
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  RespondsTo :== do
         
     | 
| 
      
 68 
     | 
    
         
            +
                    When 'other is equal' do
         
     | 
| 
      
 69 
     | 
    
         
            +
                      ByReturning true do
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                        expect(time_klass)
         
     | 
| 
      
 72 
     | 
    
         
            +
                          .to receive(:now)
         
     | 
| 
      
 73 
     | 
    
         
            +
                          .and_return(time_local)
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                        expect(time_local)
         
     | 
| 
      
 76 
     | 
    
         
            +
                          .to receive(:utc)
         
     | 
| 
      
 77 
     | 
    
         
            +
                          .and_return(time_utc)
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                        expect(time_utc)
         
     | 
| 
      
 80 
     | 
    
         
            +
                          .to receive(:iso8601)
         
     | 
| 
      
 81 
     | 
    
         
            +
                          .and_return(time_iso)
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                        expect(time_iso)
         
     | 
| 
      
 84 
     | 
    
         
            +
                          .to receive(:[])
         
     | 
| 
      
 85 
     | 
    
         
            +
                          .with(0..12)
         
     | 
| 
      
 86 
     | 
    
         
            +
                          .and_return(hour_string)
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                        expect(other_hour)
         
     | 
| 
      
 89 
     | 
    
         
            +
                          .to receive(:hour_string)
         
     | 
| 
      
 90 
     | 
    
         
            +
                          .and_return(hour_string)
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                        expect(hour_string)
         
     | 
| 
      
 93 
     | 
    
         
            +
                          .to receive(:+)
         
     | 
| 
      
 94 
     | 
    
         
            +
                          .with(':00:00Z')
         
     | 
| 
      
 95 
     | 
    
         
            +
                          .and_return(hour_string)
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                        (subject == other_hour).must_equal true
         
     | 
| 
      
 98 
     | 
    
         
            +
                      end
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                    When 'other is not equal' do
         
     | 
| 
      
 102 
     | 
    
         
            +
                      ByReturning false do
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                        expect(time_klass)
         
     | 
| 
      
 105 
     | 
    
         
            +
                          .to receive(:now)
         
     | 
| 
      
 106 
     | 
    
         
            +
                          .and_return(time_local)
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                        expect(time_local)
         
     | 
| 
      
 109 
     | 
    
         
            +
                          .to receive(:utc)
         
     | 
| 
      
 110 
     | 
    
         
            +
                          .and_return(time_utc)
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                        expect(time_utc)
         
     | 
| 
      
 113 
     | 
    
         
            +
                          .to receive(:iso8601)
         
     | 
| 
      
 114 
     | 
    
         
            +
                          .and_return(time_iso)
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                        expect(time_iso)
         
     | 
| 
      
 117 
     | 
    
         
            +
                          .to receive(:[])
         
     | 
| 
      
 118 
     | 
    
         
            +
                          .with(0..12)
         
     | 
| 
      
 119 
     | 
    
         
            +
                          .and_return(hour_string)
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                        expect(hour_string)
         
     | 
| 
      
 122 
     | 
    
         
            +
                          .to receive(:+)
         
     | 
| 
      
 123 
     | 
    
         
            +
                          .with(':00:00Z')
         
     | 
| 
      
 124 
     | 
    
         
            +
                          .and_return(hour_string)
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                        expect(other_hour)
         
     | 
| 
      
 127 
     | 
    
         
            +
                          .to receive(:hour_string)
         
     | 
| 
      
 128 
     | 
    
         
            +
                          .and_return(other_hour_string)
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                        (subject == other_hour).must_equal false
         
     | 
| 
      
 131 
     | 
    
         
            +
                      end
         
     | 
| 
      
 132 
     | 
    
         
            +
                    end
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
              end
         
     | 
| 
      
 136 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,178 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'helpers'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'instance_accountant/journal_entry'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module InstanceAccountant
         
     | 
| 
      
 7 
     | 
    
         
            +
              Class JournalEntry do
         
     | 
| 
      
 8 
     | 
    
         
            +
                Instance do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  let(:options) do
         
     | 
| 
      
 10 
     | 
    
         
            +
                    {
         
     | 
| 
      
 11 
     | 
    
         
            +
                      subledger:    subledger,
         
     | 
| 
      
 12 
     | 
    
         
            +
                      description:  description,
         
     | 
| 
      
 13 
     | 
    
         
            +
                      cost:         cost,
         
     | 
| 
      
 14 
     | 
    
         
            +
                      expense_acct: expense_acct,
         
     | 
| 
      
 15 
     | 
    
         
            +
                      payable_acct: payable_acct
         
     | 
| 
      
 16 
     | 
    
         
            +
                    }
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  let(:price_options) do
         
     | 
| 
      
 20 
     | 
    
         
            +
                    {
         
     | 
| 
      
 21 
     | 
    
         
            +
                      price:           price,
         
     | 
| 
      
 22 
     | 
    
         
            +
                      income_acct:     income_acct,
         
     | 
| 
      
 23 
     | 
    
         
            +
                      receivable_acct: receivable_acct
         
     | 
| 
      
 24 
     | 
    
         
            +
                    }
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  let(:subledger)    { double 'subledger'         }
         
     | 
| 
      
 28 
     | 
    
         
            +
                  let(:description)  { 'description with time %s' }
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  let(:cost)         { double 'cost'         }
         
     | 
| 
      
 31 
     | 
    
         
            +
                  let(:expense_acct) { double 'expense_acct' }
         
     | 
| 
      
 32 
     | 
    
         
            +
                  let(:payable_acct) { double 'payable_acct' }
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  let(:price)           { double 'price'           }
         
     | 
| 
      
 35 
     | 
    
         
            +
                  let(:income_acct)     { double 'income_acct'     }
         
     | 
| 
      
 36 
     | 
    
         
            +
                  let(:receivable_acct) { double 'receivable_acct' }
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  let(:expense_debit)  { double 'expense_debit'  }
         
     | 
| 
      
 39 
     | 
    
         
            +
                  let(:payable_credit) { double 'payable_credit' }
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  let(:receivable_debit) { double 'receivable_debit' }
         
     | 
| 
      
 42 
     | 
    
         
            +
                  let(:income_credit)    { double 'income_credit'    }
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  let(:concat_desc) { 'description with time 2014-11-05T18:00:00Z' }
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  let(:hour)        { double 'hour' }
         
     | 
| 
      
 47 
     | 
    
         
            +
                  let(:hour_string) { '2014-11-05T18:00:00Z' }
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  let(:now)  { double 'now'  }
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  RespondsTo :hash_for do
         
     | 
| 
      
 52 
     | 
    
         
            +
                    When 'price lines are not included' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                      subject { JournalEntry.new options }
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                      ByReturning true do
         
     | 
| 
      
 56 
     | 
    
         
            +
                        expect(hour)
         
     | 
| 
      
 57 
     | 
    
         
            +
                          .to receive(:hour_string)
         
     | 
| 
      
 58 
     | 
    
         
            +
                          .and_return(hour_string)
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 61 
     | 
    
         
            +
                          .to receive(:account)
         
     | 
| 
      
 62 
     | 
    
         
            +
                          .with(id: expense_acct)
         
     | 
| 
      
 63 
     | 
    
         
            +
                          .and_return(expense_acct)
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 66 
     | 
    
         
            +
                          .to receive(:debit)
         
     | 
| 
      
 67 
     | 
    
         
            +
                          .with(cost)
         
     | 
| 
      
 68 
     | 
    
         
            +
                          .and_return(expense_debit)
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 71 
     | 
    
         
            +
                          .to receive(:account)
         
     | 
| 
      
 72 
     | 
    
         
            +
                          .with(id: payable_acct)
         
     | 
| 
      
 73 
     | 
    
         
            +
                          .and_return(payable_acct)
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 76 
     | 
    
         
            +
                          .to receive(:credit)
         
     | 
| 
      
 77 
     | 
    
         
            +
                          .with(cost)
         
     | 
| 
      
 78 
     | 
    
         
            +
                          .and_return(payable_credit)
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                        # expect(description)
         
     | 
| 
      
 81 
     | 
    
         
            +
                        #   .to receive(:+)
         
     | 
| 
      
 82 
     | 
    
         
            +
                        #   .and_return(concat_desc)
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                        subject.hash_for(hour, now)
         
     | 
| 
      
 85 
     | 
    
         
            +
                          .must_equal effective_at: now,
         
     | 
| 
      
 86 
     | 
    
         
            +
                                      description:  concat_desc,
         
     | 
| 
      
 87 
     | 
    
         
            +
                                      lines: [
         
     | 
| 
      
 88 
     | 
    
         
            +
                                        {
         
     | 
| 
      
 89 
     | 
    
         
            +
                                          account: expense_acct,
         
     | 
| 
      
 90 
     | 
    
         
            +
                                          value:   expense_debit
         
     | 
| 
      
 91 
     | 
    
         
            +
                                        },
         
     | 
| 
      
 92 
     | 
    
         
            +
                                        {
         
     | 
| 
      
 93 
     | 
    
         
            +
                                          account: payable_acct,
         
     | 
| 
      
 94 
     | 
    
         
            +
                                          value:   payable_credit
         
     | 
| 
      
 95 
     | 
    
         
            +
                                        }
         
     | 
| 
      
 96 
     | 
    
         
            +
                                      ]
         
     | 
| 
      
 97 
     | 
    
         
            +
                      end
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                    When 'price lines are included' do
         
     | 
| 
      
 101 
     | 
    
         
            +
                      subject { JournalEntry.new options.merge price_options }
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                      ByReturning true do
         
     | 
| 
      
 104 
     | 
    
         
            +
                        expect(hour)
         
     | 
| 
      
 105 
     | 
    
         
            +
                          .to receive(:hour_string)
         
     | 
| 
      
 106 
     | 
    
         
            +
                          .and_return(hour_string)
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 109 
     | 
    
         
            +
                          .to receive(:account)
         
     | 
| 
      
 110 
     | 
    
         
            +
                          .with(id: expense_acct)
         
     | 
| 
      
 111 
     | 
    
         
            +
                          .and_return(expense_acct)
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 114 
     | 
    
         
            +
                          .to receive(:debit)
         
     | 
| 
      
 115 
     | 
    
         
            +
                          .with(cost)
         
     | 
| 
      
 116 
     | 
    
         
            +
                          .and_return(expense_debit)
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 119 
     | 
    
         
            +
                          .to receive(:account)
         
     | 
| 
      
 120 
     | 
    
         
            +
                          .with(id: payable_acct)
         
     | 
| 
      
 121 
     | 
    
         
            +
                          .and_return(payable_acct)
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 124 
     | 
    
         
            +
                          .to receive(:credit)
         
     | 
| 
      
 125 
     | 
    
         
            +
                          .with(cost)
         
     | 
| 
      
 126 
     | 
    
         
            +
                          .and_return(payable_credit)
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 129 
     | 
    
         
            +
                          .to receive(:account)
         
     | 
| 
      
 130 
     | 
    
         
            +
                          .with(id: receivable_acct)
         
     | 
| 
      
 131 
     | 
    
         
            +
                          .and_return(receivable_acct)
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 134 
     | 
    
         
            +
                          .to receive(:debit)
         
     | 
| 
      
 135 
     | 
    
         
            +
                          .with(price)
         
     | 
| 
      
 136 
     | 
    
         
            +
                          .and_return(receivable_debit)
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 139 
     | 
    
         
            +
                          .to receive(:account)
         
     | 
| 
      
 140 
     | 
    
         
            +
                          .with(id: income_acct)
         
     | 
| 
      
 141 
     | 
    
         
            +
                          .and_return(income_acct)
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 144 
     | 
    
         
            +
                          .to receive(:credit)
         
     | 
| 
      
 145 
     | 
    
         
            +
                          .with(price)
         
     | 
| 
      
 146 
     | 
    
         
            +
                          .and_return(income_credit)
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                        # expect(description)
         
     | 
| 
      
 149 
     | 
    
         
            +
                        #   .to receive(:+)
         
     | 
| 
      
 150 
     | 
    
         
            +
                        #   .and_return(concat_desc)
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                        subject.hash_for(hour, now)
         
     | 
| 
      
 153 
     | 
    
         
            +
                          .must_equal effective_at: now,
         
     | 
| 
      
 154 
     | 
    
         
            +
                                      description:  concat_desc,
         
     | 
| 
      
 155 
     | 
    
         
            +
                                      lines: [
         
     | 
| 
      
 156 
     | 
    
         
            +
                                        {
         
     | 
| 
      
 157 
     | 
    
         
            +
                                          account: expense_acct,
         
     | 
| 
      
 158 
     | 
    
         
            +
                                          value:   expense_debit
         
     | 
| 
      
 159 
     | 
    
         
            +
                                        },
         
     | 
| 
      
 160 
     | 
    
         
            +
                                        {
         
     | 
| 
      
 161 
     | 
    
         
            +
                                          account: payable_acct,
         
     | 
| 
      
 162 
     | 
    
         
            +
                                          value:   payable_credit
         
     | 
| 
      
 163 
     | 
    
         
            +
                                        },
         
     | 
| 
      
 164 
     | 
    
         
            +
                                        {
         
     | 
| 
      
 165 
     | 
    
         
            +
                                          account: receivable_acct,
         
     | 
| 
      
 166 
     | 
    
         
            +
                                          value:   receivable_debit
         
     | 
| 
      
 167 
     | 
    
         
            +
                                        },
         
     | 
| 
      
 168 
     | 
    
         
            +
                                        {
         
     | 
| 
      
 169 
     | 
    
         
            +
                                          account: income_acct,
         
     | 
| 
      
 170 
     | 
    
         
            +
                                          value:   income_credit
         
     | 
| 
      
 171 
     | 
    
         
            +
                                        }
         
     | 
| 
      
 172 
     | 
    
         
            +
                                      ]
         
     | 
| 
      
 173 
     | 
    
         
            +
                      end
         
     | 
| 
      
 174 
     | 
    
         
            +
                    end
         
     | 
| 
      
 175 
     | 
    
         
            +
                  end
         
     | 
| 
      
 176 
     | 
    
         
            +
                end
         
     | 
| 
      
 177 
     | 
    
         
            +
              end
         
     | 
| 
      
 178 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,109 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding : utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'helpers'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'instance_accountant/poster'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module InstanceAccountant
         
     | 
| 
      
 7 
     | 
    
         
            +
              Class Poster do
         
     | 
| 
      
 8 
     | 
    
         
            +
                Instance do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  subject { Poster.new options }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  let(:options) do
         
     | 
| 
      
 12 
     | 
    
         
            +
                    {
         
     | 
| 
      
 13 
     | 
    
         
            +
                      subledger:         subledger,
         
     | 
| 
      
 14 
     | 
    
         
            +
                      filer:             filer,
         
     | 
| 
      
 15 
     | 
    
         
            +
                      hour_klass:        hour_klass,
         
     | 
| 
      
 16 
     | 
    
         
            +
                      journal_entry:     journal_entry
         
     | 
| 
      
 17 
     | 
    
         
            +
                    }
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  let(:subledger)          { double 'subledger'          }
         
     | 
| 
      
 21 
     | 
    
         
            +
                  let(:sl_journal_entry)   { double 'sl_journal_entry'   }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  let(:filer)              { double 'filer'              }
         
     | 
| 
      
 24 
     | 
    
         
            +
                  let(:hour_klass)         { double 'hour_klass'         }
         
     | 
| 
      
 25 
     | 
    
         
            +
                  let(:journal_entry)      { double 'journal_entry'      }
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  let(:journal_entry_hash) { double 'journal_entry_hash' }
         
     | 
| 
      
 28 
     | 
    
         
            +
                  let(:hour)               { double 'hour'               }
         
     | 
| 
      
 29 
     | 
    
         
            +
                  let(:different_hour)     { double 'different_hour'     }
         
     | 
| 
      
 30 
     | 
    
         
            +
                  let(:now)                { double 'now'                }
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  RespondsTo :post do
         
     | 
| 
      
 33 
     | 
    
         
            +
                    When 'no hours have been posted' do
         
     | 
| 
      
 34 
     | 
    
         
            +
                      ByReturning true do
         
     | 
| 
      
 35 
     | 
    
         
            +
                        expect(filer)
         
     | 
| 
      
 36 
     | 
    
         
            +
                          .to receive(:read)
         
     | 
| 
      
 37 
     | 
    
         
            +
                          .and_return(nil)
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                        expect(journal_entry)
         
     | 
| 
      
 40 
     | 
    
         
            +
                          .to receive(:hash_for)
         
     | 
| 
      
 41 
     | 
    
         
            +
                          .with(hour, now)
         
     | 
| 
      
 42 
     | 
    
         
            +
                          .and_return(journal_entry_hash)
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                        expect(filer)
         
     | 
| 
      
 45 
     | 
    
         
            +
                          .to receive(:write)
         
     | 
| 
      
 46 
     | 
    
         
            +
                          .with(hour)
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 49 
     | 
    
         
            +
                          .to receive(:journal_entry)
         
     | 
| 
      
 50 
     | 
    
         
            +
                          .and_return(sl_journal_entry)
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                        expect(sl_journal_entry)
         
     | 
| 
      
 53 
     | 
    
         
            +
                          .to receive(:create_and_post)
         
     | 
| 
      
 54 
     | 
    
         
            +
                          .with(journal_entry_hash)
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                        subject.post(hour, now).must_equal true
         
     | 
| 
      
 57 
     | 
    
         
            +
                      end
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    When 'the hour has not been posted' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                      ByReturning true do
         
     | 
| 
      
 62 
     | 
    
         
            +
                        expect(filer)
         
     | 
| 
      
 63 
     | 
    
         
            +
                          .to receive(:read)
         
     | 
| 
      
 64 
     | 
    
         
            +
                          .and_return(different_hour)
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                        expect(hour_klass)
         
     | 
| 
      
 67 
     | 
    
         
            +
                          .to receive(:new)
         
     | 
| 
      
 68 
     | 
    
         
            +
                          .with(time: different_hour)
         
     | 
| 
      
 69 
     | 
    
         
            +
                          .and_return(different_hour)
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                        expect(journal_entry)
         
     | 
| 
      
 72 
     | 
    
         
            +
                          .to receive(:hash_for)
         
     | 
| 
      
 73 
     | 
    
         
            +
                          .with(hour, now)
         
     | 
| 
      
 74 
     | 
    
         
            +
                          .and_return(journal_entry_hash)
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                        expect(subledger)
         
     | 
| 
      
 77 
     | 
    
         
            +
                          .to receive(:journal_entry)
         
     | 
| 
      
 78 
     | 
    
         
            +
                          .and_return(sl_journal_entry)
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                        expect(sl_journal_entry)
         
     | 
| 
      
 81 
     | 
    
         
            +
                          .to receive(:create_and_post)
         
     | 
| 
      
 82 
     | 
    
         
            +
                          .with(journal_entry_hash)
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                        expect(filer)
         
     | 
| 
      
 85 
     | 
    
         
            +
                          .to receive(:write)
         
     | 
| 
      
 86 
     | 
    
         
            +
                          .with(hour)
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                        subject.post(hour, now).must_equal true
         
     | 
| 
      
 89 
     | 
    
         
            +
                      end
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                    When 'the hour has been posted' do
         
     | 
| 
      
 93 
     | 
    
         
            +
                      ByReturning false do
         
     | 
| 
      
 94 
     | 
    
         
            +
                        expect(filer)
         
     | 
| 
      
 95 
     | 
    
         
            +
                          .to receive(:read)
         
     | 
| 
      
 96 
     | 
    
         
            +
                          .and_return(hour)
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                        expect(hour_klass)
         
     | 
| 
      
 99 
     | 
    
         
            +
                          .to receive(:new)
         
     | 
| 
      
 100 
     | 
    
         
            +
                          .with(time: hour)
         
     | 
| 
      
 101 
     | 
    
         
            +
                          .and_return(hour)
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                        subject.post(hour, now).must_equal false
         
     | 
| 
      
 104 
     | 
    
         
            +
                      end
         
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,226 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: instance_accountant
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.1
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Tom Mornini
         
     | 
| 
      
 8 
     | 
    
         
            +
            - John McKee
         
     | 
| 
      
 9 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 10 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 11 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2014-11-05 00:00:00.000000000 Z
         
     | 
| 
      
 13 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 14 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 15 
     | 
    
         
            +
              name: subledger
         
     | 
| 
      
 16 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 17 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 18 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 19 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 20 
     | 
    
         
            +
                    version: '0.7'
         
     | 
| 
      
 21 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 22 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 23 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 24 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 25 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 26 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 27 
     | 
    
         
            +
                    version: '0.7'
         
     | 
| 
      
 28 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 29 
     | 
    
         
            +
              name: thor
         
     | 
| 
      
 30 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 31 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 32 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 33 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 34 
     | 
    
         
            +
                    version: '0.19'
         
     | 
| 
      
 35 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 36 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 37 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 38 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 39 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 40 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 41 
     | 
    
         
            +
                    version: '0.19'
         
     | 
| 
      
 42 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 43 
     | 
    
         
            +
              name: guard
         
     | 
| 
      
 44 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 45 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 46 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 47 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 48 
     | 
    
         
            +
                    version: '2.8'
         
     | 
| 
      
 49 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 50 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 51 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 52 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 53 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 54 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 55 
     | 
    
         
            +
                    version: '2.8'
         
     | 
| 
      
 56 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 57 
     | 
    
         
            +
              name: guard-minitest
         
     | 
| 
      
 58 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 59 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 60 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 61 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 62 
     | 
    
         
            +
                    version: '2.3'
         
     | 
| 
      
 63 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 64 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 65 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 66 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 67 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 68 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 69 
     | 
    
         
            +
                    version: '2.3'
         
     | 
| 
      
 70 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 71 
     | 
    
         
            +
              name: guard-rubocop
         
     | 
| 
      
 72 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 73 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 74 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 75 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 76 
     | 
    
         
            +
                    version: '1.1'
         
     | 
| 
      
 77 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 78 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 79 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 80 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 81 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 82 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 83 
     | 
    
         
            +
                    version: '1.1'
         
     | 
| 
      
 84 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 85 
     | 
    
         
            +
              name: minitest
         
     | 
| 
      
 86 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 87 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 88 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 89 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 90 
     | 
    
         
            +
                    version: '5.4'
         
     | 
| 
      
 91 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 92 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 93 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 94 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 95 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 96 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 97 
     | 
    
         
            +
                    version: '5.4'
         
     | 
| 
      
 98 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 99 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 100 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 101 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 102 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 103 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 104 
     | 
    
         
            +
                    version: '10.3'
         
     | 
| 
      
 105 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 106 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 107 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 108 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 109 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 110 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 111 
     | 
    
         
            +
                    version: '10.3'
         
     | 
| 
      
 112 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 113 
     | 
    
         
            +
              name: rb-fsevent
         
     | 
| 
      
 114 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 115 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 116 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 117 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 118 
     | 
    
         
            +
                    version: '0.9'
         
     | 
| 
      
 119 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 120 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 121 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 122 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 123 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 124 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 125 
     | 
    
         
            +
                    version: '0.9'
         
     | 
| 
      
 126 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 127 
     | 
    
         
            +
              name: rspec-expectations
         
     | 
| 
      
 128 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 129 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 130 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 131 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 132 
     | 
    
         
            +
                    version: '3.1'
         
     | 
| 
      
 133 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 134 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 135 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 136 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 137 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 138 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 139 
     | 
    
         
            +
                    version: '3.1'
         
     | 
| 
      
 140 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 141 
     | 
    
         
            +
              name: rspec-mocks
         
     | 
| 
      
 142 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 143 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 144 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 145 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 146 
     | 
    
         
            +
                    version: '3.1'
         
     | 
| 
      
 147 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 148 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 149 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 150 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 151 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 152 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 153 
     | 
    
         
            +
                    version: '3.1'
         
     | 
| 
      
 154 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 155 
     | 
    
         
            +
              name: rubocop
         
     | 
| 
      
 156 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 157 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 158 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 159 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 160 
     | 
    
         
            +
                    version: '0.27'
         
     | 
| 
      
 161 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 162 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 163 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 164 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 165 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 166 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 167 
     | 
    
         
            +
                    version: '0.27'
         
     | 
| 
      
 168 
     | 
    
         
            +
            description: account for hourly instance usage using Subledger
         
     | 
| 
      
 169 
     | 
    
         
            +
            email: admin@subledger.com
         
     | 
| 
      
 170 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 171 
     | 
    
         
            +
            - instance_accountant
         
     | 
| 
      
 172 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 173 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 174 
     | 
    
         
            +
            files:
         
     | 
| 
      
 175 
     | 
    
         
            +
            - LICENSE.txt
         
     | 
| 
      
 176 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 177 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 178 
     | 
    
         
            +
            - bin/instance_accountant
         
     | 
| 
      
 179 
     | 
    
         
            +
            - instance_accountant.gemspec
         
     | 
| 
      
 180 
     | 
    
         
            +
            - lib/instance_accountant.rb
         
     | 
| 
      
 181 
     | 
    
         
            +
            - lib/instance_accountant/cli.rb
         
     | 
| 
      
 182 
     | 
    
         
            +
            - lib/instance_accountant/filer.rb
         
     | 
| 
      
 183 
     | 
    
         
            +
            - lib/instance_accountant/hour.rb
         
     | 
| 
      
 184 
     | 
    
         
            +
            - lib/instance_accountant/journal_entry.rb
         
     | 
| 
      
 185 
     | 
    
         
            +
            - lib/instance_accountant/poster.rb
         
     | 
| 
      
 186 
     | 
    
         
            +
            - spec/helpers.rb
         
     | 
| 
      
 187 
     | 
    
         
            +
            - spec/helpers/minitest.rb
         
     | 
| 
      
 188 
     | 
    
         
            +
            - spec/helpers/rspec.rb
         
     | 
| 
      
 189 
     | 
    
         
            +
            - spec/instance_accountant/cli_spec.rb
         
     | 
| 
      
 190 
     | 
    
         
            +
            - spec/instance_accountant/filer_spec.rb
         
     | 
| 
      
 191 
     | 
    
         
            +
            - spec/instance_accountant/hour_spec.rb
         
     | 
| 
      
 192 
     | 
    
         
            +
            - spec/instance_accountant/journal_entry_spec.rb
         
     | 
| 
      
 193 
     | 
    
         
            +
            - spec/instance_accountant/poster_spec.rb
         
     | 
| 
      
 194 
     | 
    
         
            +
            homepage: https://github.com/subledger/instance_accountant
         
     | 
| 
      
 195 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 196 
     | 
    
         
            +
            - BSD 3-Clause
         
     | 
| 
      
 197 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 198 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 199 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 200 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 201 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 202 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 203 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 204 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 205 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 206 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 207 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 208 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 209 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 210 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 211 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 212 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 213 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 214 
     | 
    
         
            +
            rubygems_version: 2.4.2
         
     | 
| 
      
 215 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 216 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 217 
     | 
    
         
            +
            summary: account for hourly instance usage using Subledger
         
     | 
| 
      
 218 
     | 
    
         
            +
            test_files:
         
     | 
| 
      
 219 
     | 
    
         
            +
            - spec/helpers/minitest.rb
         
     | 
| 
      
 220 
     | 
    
         
            +
            - spec/helpers/rspec.rb
         
     | 
| 
      
 221 
     | 
    
         
            +
            - spec/helpers.rb
         
     | 
| 
      
 222 
     | 
    
         
            +
            - spec/instance_accountant/cli_spec.rb
         
     | 
| 
      
 223 
     | 
    
         
            +
            - spec/instance_accountant/filer_spec.rb
         
     | 
| 
      
 224 
     | 
    
         
            +
            - spec/instance_accountant/hour_spec.rb
         
     | 
| 
      
 225 
     | 
    
         
            +
            - spec/instance_accountant/journal_entry_spec.rb
         
     | 
| 
      
 226 
     | 
    
         
            +
            - spec/instance_accountant/poster_spec.rb
         
     |