enju_standalone_interface 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +35 -0
  4. data/app/assets/javascripts/enju_standalone_interface/application.js +15 -0
  5. data/app/assets/javascripts/enju_standalone_interface/batch_action.js +2 -0
  6. data/app/assets/stylesheets/enju_standalone_interface/application.css +13 -0
  7. data/app/assets/stylesheets/enju_standalone_interface/batch_action.css +4 -0
  8. data/app/controllers/application_controller.rb +4 -0
  9. data/app/controllers/batch_action_controller.rb +9 -0
  10. data/app/helpers/enju_standalone_interface/application_helper.rb +4 -0
  11. data/app/helpers/enju_standalone_interface/batch_action_helper.rb +4 -0
  12. data/app/views/enju_standalone_interface/batch_action/recept.html.erb +1 -0
  13. data/app/views/layouts/enju_standalone_interface/application.html.erb +14 -0
  14. data/config/routes.rb +3 -0
  15. data/lib/enju_standalone_interface.rb +233 -0
  16. data/lib/enju_standalone_interface/engine.rb +5 -0
  17. data/lib/enju_standalone_interface/version.rb +3 -0
  18. data/lib/tasks/enju_standalone_interface_tasks.rake +4 -0
  19. data/spec/controllers/enju_standalone_interface/batch_action_controller_spec.rb +21 -0
  20. data/spec/dummy/README.rdoc +261 -0
  21. data/spec/dummy/Rakefile +7 -0
  22. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  23. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  24. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  25. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  26. data/spec/dummy/app/helpers/users_helper.rb +36 -0
  27. data/spec/dummy/app/models/basket.rb +70 -0
  28. data/spec/dummy/app/models/carrier_type.rb +33 -0
  29. data/spec/dummy/app/models/checked_item.rb +177 -0
  30. data/spec/dummy/app/models/checkout.rb +307 -0
  31. data/spec/dummy/app/models/checkout_type.rb +33 -0
  32. data/spec/dummy/app/models/circulation_status.rb +23 -0
  33. data/spec/dummy/app/models/event.rb +124 -0
  34. data/spec/dummy/app/models/item.rb +1234 -0
  35. data/spec/dummy/app/models/item_has_use_restriction.rb +23 -0
  36. data/spec/dummy/app/models/lending_policy.rb +32 -0
  37. data/spec/dummy/app/models/library.rb +105 -0
  38. data/spec/dummy/app/models/library_group.rb +88 -0
  39. data/spec/dummy/app/models/manifestation.rb +698 -0
  40. data/spec/dummy/app/models/patron.rb +342 -0
  41. data/spec/dummy/app/models/role.rb +47 -0
  42. data/spec/dummy/app/models/shelf.rb +83 -0
  43. data/spec/dummy/app/models/use_restriction.rb +22 -0
  44. data/spec/dummy/app/models/user.rb +580 -0
  45. data/spec/dummy/app/models/user_group.rb +43 -0
  46. data/spec/dummy/app/models/user_group_has_checkout_type.rb +80 -0
  47. data/spec/dummy/app/models/user_has_role.rb +4 -0
  48. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  49. data/spec/dummy/config.ru +4 -0
  50. data/spec/dummy/config/application.rb +57 -0
  51. data/spec/dummy/config/boot.rb +10 -0
  52. data/spec/dummy/config/database.yml +25 -0
  53. data/spec/dummy/config/environment.rb +5 -0
  54. data/spec/dummy/config/environments/development.rb +37 -0
  55. data/spec/dummy/config/environments/production.rb +67 -0
  56. data/spec/dummy/config/environments/test.rb +37 -0
  57. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  58. data/spec/dummy/config/initializers/inflections.rb +15 -0
  59. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  60. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  61. data/spec/dummy/config/initializers/session_store.rb +8 -0
  62. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  63. data/spec/dummy/config/locales/en.yml +5 -0
  64. data/spec/dummy/config/locales/translation_en.yml +1724 -0
  65. data/spec/dummy/config/locales/validates_timeliness.en.yml +16 -0
  66. data/spec/dummy/config/routes.rb +4 -0
  67. data/spec/dummy/db/development.sqlite3 +0 -0
  68. data/spec/dummy/db/migrate/20120322223037_create_users.rb +71 -0
  69. data/spec/dummy/db/migrate/20120323053037_create_roles.rb +15 -0
  70. data/spec/dummy/db/migrate/20120323060718_create_user_has_roles.rb +10 -0
  71. data/spec/dummy/db/migrate/20120323062239_create_libraries.rb +37 -0
  72. data/spec/dummy/db/migrate/20120323063602_create_items.rb +33 -0
  73. data/spec/dummy/db/migrate/20120323064619_craete_circulation_statuses.rb +13 -0
  74. data/spec/dummy/db/migrate/20120323065157_craete_checkout_types.rb +13 -0
  75. data/spec/dummy/db/migrate/20120323070102_craete_shelves.rb +17 -0
  76. data/spec/dummy/db/migrate/20120323071616_craete_library_groups.rb +24 -0
  77. data/spec/dummy/db/migrate/20120323073022_craete_patrons.rb +72 -0
  78. data/spec/dummy/db/migrate/20120323141030_create_manifestations.rb +97 -0
  79. data/spec/dummy/db/migrate/20120323142330_create_carrier_types.rb +12 -0
  80. data/spec/dummy/db/migrate/20120324132708_create_baskets.rb +20 -0
  81. data/spec/dummy/db/migrate/20120324135409_checked_items.rb +16 -0
  82. data/spec/dummy/db/migrate/20120324141007_create_user_groups.rb +22 -0
  83. data/spec/dummy/db/migrate/20120324141950_create_user_group_has_checkout_type.rb +26 -0
  84. data/spec/dummy/db/migrate/20120324151951_create_lending_policies.rb +22 -0
  85. data/spec/dummy/db/migrate/20120324153756_create_use_restrictions.rb +15 -0
  86. data/spec/dummy/db/migrate/20120324154009_create_item_has_use_restrictions.rb +16 -0
  87. data/spec/dummy/db/migrate/20120324164815_create_checkouts.rb +26 -0
  88. data/spec/dummy/db/migrate/20120325160112_create_events.rb +23 -0
  89. data/spec/dummy/db/schema.rb +518 -0
  90. data/spec/dummy/db/test.sqlite3 +0 -0
  91. data/spec/dummy/lib/enju_leaf.rb +6 -0
  92. data/spec/dummy/lib/enju_leaf/master_model.rb +41 -0
  93. data/spec/dummy/lib/enju_leaf/url_validator.rb +10 -0
  94. data/spec/dummy/log/development.log +116 -0
  95. data/spec/dummy/log/test.log +17849 -0
  96. data/spec/dummy/public/404.html +26 -0
  97. data/spec/dummy/public/422.html +26 -0
  98. data/spec/dummy/public/500.html +25 -0
  99. data/spec/dummy/public/favicon.ico +0 -0
  100. data/spec/dummy/script/rails +6 -0
  101. data/spec/factories/item.rb +9 -0
  102. data/spec/factories/manifestation.rb +6 -0
  103. data/spec/factories/user.rb +27 -0
  104. data/spec/fixtures/carrier_types.yml +38 -0
  105. data/spec/fixtures/checkout_types.yml +34 -0
  106. data/spec/fixtures/circulation_statuses.yml +135 -0
  107. data/spec/fixtures/libraries.yml +40 -0
  108. data/spec/fixtures/roles.yml +21 -0
  109. data/spec/fixtures/shelves.yml +53 -0
  110. data/spec/fixtures/user_group_has_checkout_types.yml +14 -0
  111. data/spec/fixtures/user_groups.yml +7 -0
  112. data/spec/libs/enju_standalone_interface_spec.rb +133 -0
  113. data/spec/spec_helper.rb +36 -0
  114. metadata +358 -0
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree .
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,36 @@
1
+ module UsersHelper
2
+ def enumrate_user_name(family)
3
+ v = ""
4
+ family.users.each do |u|
5
+ v.concat("#{u.patron.full_name if u.patron} (#{u.username}) ")
6
+ end
7
+ return v
8
+ end
9
+
10
+ def family_radio_check?(btn_value, family)
11
+ #logger.info "family_radio_check v=[#{btn_value}] f=[#{family}]"
12
+ #logger.info "family_radio_check v=[#{btn_value.class}] f=[#{family.class}]"
13
+ if family.empty? && btn_value == 0
14
+ return true
15
+ end
16
+ if btn_value.to_s == family
17
+ #logger.info "true"
18
+ return true
19
+ end
20
+ #logger.info "false"
21
+ return false
22
+ end
23
+
24
+ def i18n_telephone_type(type)
25
+ case type
26
+ when 1
27
+ t('activerecord.attributes.patron.home_phone')
28
+ when 2
29
+ t('activerecord.attributes.patron.fax')
30
+ when 3
31
+ t('activerecord.attributes.patron.mobile_phone')
32
+ when 4
33
+ t('activerecord.attributes.patron.company_phone')
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,70 @@
1
+ class Basket < ActiveRecord::Base
2
+ default_scope :order => 'id DESC'
3
+ scope :will_expire, lambda {|date| {:conditions => ['created_at < ?', date]}}
4
+ belongs_to :user, :validate => true
5
+ has_many :checked_items, :dependent => :destroy
6
+ has_many :items, :through => :checked_items
7
+ has_many :checkouts
8
+ has_many :checkins
9
+ #acts_as_paranoid
10
+
11
+ validates_associated :user, :on => :create
12
+ # 貸出完了後にかごのユーザidは破棄する
13
+ validates_presence_of :user, :on => :create
14
+ validate :check_suspended
15
+
16
+ attr_accessor :user_number
17
+
18
+ def check_suspended
19
+ if self.user
20
+ errors[:base] << I18n.t('basket.this_account_is_suspended') unless self.user.active_for_authentication?
21
+ else
22
+ errors[:base] << I18n.t('user.not_found')
23
+ end
24
+ end
25
+
26
+ def basket_checkout(librarian)
27
+ return nil if self.checked_items.size == 0
28
+ begin
29
+ Item.transaction do
30
+ self.checked_items.each do |checked_item|
31
+ checked_item.ignore_restriction = '1'
32
+ if checked_item.available_for_checkout?
33
+ checkout = self.user.checkouts.new(:librarian_id => librarian.id, :item_id => checked_item.item.id, :basket_id => self.id, :due_date => checked_item.due_date)
34
+ checked_item.item.checkout!(self.user, librarian)
35
+ checkout.save!
36
+ else
37
+ #errors[:base] << I18n.t('activerecord.errors.messages.checked_item.not_available_for_checkout')
38
+ errors[:base] << 'checked_item.not_available_for_checkout'
39
+ return false
40
+ end
41
+ end
42
+ CheckedItem.destroy_all(:basket_id => self.id)
43
+ self.destroy
44
+ end
45
+ rescue Exception => e
46
+ logger.error "Failed to checkout: #{e}"
47
+ return false
48
+ end
49
+ end
50
+
51
+ def self.expire
52
+ Basket.will_expire(Time.zone.now.beginning_of_day).destroy_all
53
+ logger.info "#{Time.zone.now} baskets expired!"
54
+ end
55
+
56
+ end
57
+
58
+ # == Schema Information
59
+ #
60
+ # Table name: baskets
61
+ #
62
+ # id :integer not null, primary key
63
+ # user_id :integer
64
+ # note :text
65
+ # type :string(255)
66
+ # lock_version :integer default(0), not null
67
+ # created_at :datetime
68
+ # updated_at :datetime
69
+ #
70
+
@@ -0,0 +1,33 @@
1
+ class CarrierType < ActiveRecord::Base
2
+ include MasterModel
3
+ default_scope :order => "position"
4
+ scope :audio, where(:name => ["CD", "DVD", "AV"])
5
+ scope :not_audio, where(["name NOT IN (?)", ["CD", "DVD", "AV"]])
6
+ has_many :manifestation
7
+ has_many :carrier_type_has_checkout_types, :dependent => :destroy
8
+ has_many :checkout_types, :through => :carrier_type_has_checkout_types
9
+
10
+ def mods_type
11
+ case name
12
+ when 'print'
13
+ 'text'
14
+ else
15
+ # TODO: その他のタイプ
16
+ 'software, multimedia'
17
+ end
18
+ end
19
+ end
20
+
21
+ # == Schema Information
22
+ #
23
+ # Table name: carrier_types
24
+ #
25
+ # id :integer not null, primary key
26
+ # name :string(255) not null
27
+ # display_name :text
28
+ # note :text
29
+ # position :integer
30
+ # created_at :datetime
31
+ # updated_at :datetime
32
+ #
33
+
@@ -0,0 +1,177 @@
1
+ class CheckedItem < ActiveRecord::Base
2
+ belongs_to :item #, :validate => true
3
+ belongs_to :basket #, :validate => true
4
+
5
+ validates_associated :item, :basket, :on => :update
6
+ validates_presence_of :item, :basket, :due_date, :on => :update
7
+ validates_uniqueness_of :item_id, :scope => :basket_id
8
+ validate :available_for_checkout?, :on => :create
9
+
10
+ before_validation :set_due_date, :on => :create
11
+ #normalize_attributes :item_identifier
12
+
13
+ attr_accessor :item_identifier, :ignore_restriction
14
+
15
+ def available_for_checkout?
16
+ if self.item.blank?
17
+ # errors[:base] << I18n.t('activerecord.errors.messages.checked_item.item_not_found')
18
+ errors[:base] << 'checked_item.item_not_found'
19
+ return false
20
+ end
21
+
22
+ unless self.item.available_for_checkout?
23
+ # errors[:base] << I18n.t('activerecord.errors.messages.checked_item.not_available_for_checkout')
24
+ errors[:base] << 'checked_item.not_available_for_checkout'
25
+ return false
26
+ end
27
+
28
+ if self.item_checkout_type.blank?
29
+ # errors[:base] << I18n.t('activerecord.errors.messages.checked_item.this_group_cannot_checkout')
30
+ errors[:base] << 'checked_item.this_group_cannot_checkout'
31
+ return false
32
+ end
33
+ # ここまでは絶対に貸出ができない場合
34
+
35
+ # if self.item.rent?
36
+ # errors[:base] << I18n.t('activerecord.errors.messages.checked_item.already_checked_out')
37
+ # errors[:base] << 'checked_item.already_checked_out'
38
+ # return #
39
+ # end
40
+
41
+ return true if self.ignore_restriction == "1"
42
+
43
+ if self.item.manifestation.new_serial? && SystemConfiguration.get("checkouts.cannot_for_new_serial")
44
+ errors[:base] << 'checked_item.new_serial'
45
+ return false
46
+ end
47
+
48
+ checkout_count = self.basket.user.checked_item_count
49
+ CheckoutType.all.each do |checkout_type|
50
+ if checkout_count[:"#{checkout_type.name}"] + self.basket.checked_items.count(:id) >= self.item_checkout_type.checkout_limit
51
+ #errors[:base] << t('activerecord.errors.messages.checked_item.excessed_checkout_limit')
52
+ errors[:base] << 'checked_item.excessed_checkout_limit'
53
+ break
54
+ end
55
+ end
56
+
57
+ #errors[:base] << I18n.t('activerecord.errors.messages.checked_item.in_transcation') if self.in_transaction?
58
+ if self.in_transaction?
59
+ errors[:base] << 'checked_item.in_transcation'
60
+ return
61
+ end
62
+ if self.item.reserved?
63
+ if self.available_for_reserve_checkout?
64
+ return true
65
+ else
66
+ #errors[:base] << I18n.t('activerecord.errors.messages.checked_item.reserved_item_included')
67
+ errors[:base] << 'checked_item.reserved_item_included'
68
+ end
69
+ end
70
+ #errors[:base] << I18n.t('activerecord.errors.messages.checked_item.not_available_for_checkout') if self.item.not_for_loan?
71
+ if self.item.not_for_loan?
72
+ errors[:base] << 'checked_item.not_for_loan'
73
+ end
74
+
75
+ return false unless errors[:base]
76
+ end
77
+
78
+ def item_checkout_type
79
+ if item
80
+ self.basket.user.user_group.user_group_has_checkout_types.available_for_item(item).first
81
+ end
82
+ end
83
+
84
+ def set_due_date
85
+ return nil unless self.item_checkout_type
86
+
87
+ lending_rule = self.item.lending_rule(self.basket.user)
88
+ return nil if lending_rule.nil?
89
+
90
+ if lending_rule.fixed_due_date.blank?
91
+ #self.due_date = item_checkout_type.checkout_period.days.since Time.zone.today
92
+ self.due_date = lending_rule.loan_period.days.since Time.zone.now
93
+ else
94
+ #self.due_date = item_checkout_type.fixed_due_date
95
+ self.due_date = lending_rule.fixed_due_date
96
+ end
97
+ # 返却期限日が閉館日の場合
98
+ # TODO date_truncはPostgreSQL独自の機能なので他のDBも少しは考慮に入れる
99
+ events = Event.find(:all, :conditions => ["? BETWEEN date_trunc('day', start_at) AND date_trunc('day', end_at)", due_date.beginning_of_day])
100
+ checkin_before = false
101
+ events.each do |e|
102
+ checkin_before = true if e.event_category.move_checkin_date == 2
103
+ end
104
+ while item.shelf.library.closed?(due_date)
105
+ if item_checkout_type.set_due_date_before_closing_day
106
+ self.due_date = due_date.yesterday.end_of_day
107
+ elsif checkin_before
108
+ self.due_date = due_date.yesterday.end_of_day
109
+ else
110
+ self.due_date = due_date.tomorrow.end_of_day
111
+ end
112
+ end
113
+
114
+ return self.due_date
115
+ end
116
+
117
+ def in_transaction?
118
+ true if CheckedItem.where(:item_id => self.item_id, :basket_id => self.basket_id).first
119
+ end
120
+
121
+ def destroy_reservation(basket)
122
+ if self.item.reserved?
123
+ if self.item.manifestation.is_reserved_by(basket.user)
124
+ reserve = Reserve.where(:user_id => basket.user_id, :manifestation_id => self.item.manifestation.id).first
125
+ reserve.destroy
126
+ end
127
+ end
128
+ end
129
+
130
+ def available_for_reserve_checkout?
131
+ reserve = Reserve.waiting.where(:manifestation_id => self.item.manifestation.id, :user_id => self.basket.user.id).first rescue nil
132
+ retained_reserves = self.item.manifestation.reserves.hold
133
+ if retained_reserves && retained_reserves.include?(reserve)
134
+ begin
135
+ return true if self.item.reserve.user_id == self.basket.user.id
136
+ exchange_reserve_item(self.item, reserve)
137
+ return true
138
+ rescue Exception => e
139
+ logger.error e
140
+ end
141
+ end
142
+ false
143
+ end
144
+
145
+ def exchange_reserve_item(checkin_item, checkin_reserve)
146
+ begin
147
+ Reserve.transaction do
148
+ reserve = Reserve.waiting.where(:item_id => checkin_item.id).first rescue nil
149
+ item = checkin_reserve.item
150
+ raise Exception if CheckedItem.where(:item_id => checkin_reserve.item_id, :basket_id => self.basket_id).first
151
+ checkin_reserve.item = checkin_item
152
+ unless reserve.blank?
153
+ reserve.item = item
154
+ reserve.save(:validate => false)
155
+ end
156
+ checkin_reserve.save
157
+ end
158
+ rescue Exception => e
159
+ logger.error e
160
+ raise e
161
+ end
162
+ end
163
+
164
+ end
165
+
166
+ # == Schema Information
167
+ #
168
+ # Table name: checked_items
169
+ #
170
+ # id :integer not null, primary key
171
+ # item_id :integer not null
172
+ # basket_id :integer not null
173
+ # due_date :datetime not null
174
+ # created_at :datetime
175
+ # updated_at :datetime
176
+ #
177
+
@@ -0,0 +1,307 @@
1
+ class Checkout < ActiveRecord::Base
2
+ default_scope :order => 'due_date ASC, id DESC'#:order => 'id DESC'
3
+ scope :not_returned, where(:checkin_id => nil)
4
+ scope :overdue, lambda {|date| {:conditions => ['checkin_id IS NULL AND due_date < ?', date]}}
5
+ scope :due_date_on, lambda {|date| where(:checkin_id => nil, :due_date => date.beginning_of_day .. date.end_of_day)}
6
+ scope :completed, lambda {|start_date, end_date| {:conditions => ['created_at >= ? AND created_at < ?', start_date, end_date]}}
7
+ scope :on, lambda {|date| {:conditions => ['created_at >= ? AND created_at < ?', date.beginning_of_day, date.tomorrow.beginning_of_day]}}
8
+
9
+ belongs_to :user #, :counter_cache => true #, :validate => true
10
+ delegate :username, :user_number, :to => :user, :prefix => true
11
+ belongs_to :item #, :counter_cache => true #, :validate => true
12
+ belongs_to :checkin #, :validate => true
13
+ belongs_to :librarian, :class_name => 'User' #, :validate => true
14
+ belongs_to :basket #, :validate => true
15
+ has_many :reminder_list
16
+
17
+ validates_associated :user, :item, :librarian, :checkin #, :basket
18
+ # TODO: 貸出履歴を保存しない場合は、ユーザ名を削除する
19
+ #validates_presence_of :user, :item, :basket
20
+ validates_presence_of :item_id, :basket_id, :due_date
21
+ validates_uniqueness_of :item_id, :scope => [:basket_id, :user_id]
22
+ validate :is_not_checked?, :on => :create
23
+ #validates_date :due_date
24
+
25
+ def self.per_page
26
+ 10
27
+ end
28
+
29
+ def day_of_overdue
30
+ due_date_datetype = due_date.strftime("%Y-%m-%d")
31
+ overdue = (Date.today - due_date_datetype.to_date)
32
+ overdue = 0 if overdue < 0
33
+ return overdue
34
+ end
35
+
36
+ def is_not_checked?
37
+ checkout = Checkout.not_returned.find(self.item) rescue nil
38
+ unless checkout.nil?
39
+ errors[:base] << I18n.t('activerecord.errors.messages.checkin.already_checked_out')
40
+ end
41
+ end
42
+
43
+ def checkout_renewable?
44
+ return false if self.overdue?
45
+ if self.item
46
+ return false if self.over_checkout_renewal_limit?
47
+ return false if self.reserved?
48
+ end
49
+ true
50
+ end
51
+
52
+ def reserved?
53
+ return true if self.item.reserved?
54
+ end
55
+
56
+ def over_checkout_renewal_limit?
57
+ return true if self.item.checkout_status(self.user).checkout_renewal_limit <= self.checkout_renewal_count
58
+ end
59
+
60
+ def overdue?
61
+ # if Time.zone.now.tomorrow.beginning_of_day >= self.due_date
62
+ if Time.zone.now.beginning_of_day > self.due_date
63
+ return true
64
+ else
65
+ return false
66
+ end
67
+ end
68
+
69
+ def is_today_due_date?
70
+ if Time.zone.now.beginning_of_day == self.due_date.beginning_of_day
71
+ return true
72
+ else
73
+ return false
74
+ end
75
+ end
76
+
77
+ def set_renew_due_date(user)
78
+ if self.item
79
+ if self.checkout_renewal_count <= self.item.checkout_status(user).checkout_renewal_limit
80
+ renew_due_date = self.due_date.advance(:days => self.item.checkout_status(user).checkout_period)
81
+ else
82
+ renew_due_date = self.due_date
83
+ end
84
+ end
85
+ end
86
+
87
+ def self.manifestations_count(start_date, end_date, manifestation)
88
+ self.completed(start_date, end_date).where(:item_id => manifestation.items.collect(&:id)).count
89
+ end
90
+
91
+ def self.send_due_date_notification
92
+ template = 'recall_item'
93
+ queues = []
94
+ User.find_each do |user|
95
+ # 未来の日時を指定する
96
+ checkouts = user.checkouts.due_date_on(user.user_group.number_of_day_to_notify_due_date.days.from_now.beginning_of_day)
97
+ unless checkouts.empty?
98
+ queues << user.send_message(template, :manifestations => checkouts.collect(&:item).collect(&:manifestation))
99
+ end
100
+ end
101
+ queues.size
102
+ end
103
+
104
+ def self.send_overdue_notification
105
+ template = 'recall_overdue_item'
106
+ queues = []
107
+ User.find_each do |user|
108
+ user.user_group.number_of_time_to_notify_overdue.times do |i|
109
+ checkouts = user.checkouts.due_date_on((user.user_group.number_of_day_to_notify_overdue * (i + 1)).days.ago.beginning_of_day)
110
+ unless checkouts.empty?
111
+ queues << user.send_message(template, :manifestations => checkouts.collect(&:item).collect(&:manifestation))
112
+ end
113
+ end
114
+ end
115
+ queues.size
116
+ end
117
+
118
+ def self.apend_to_reminder_list
119
+ queues_size = 0
120
+ User.find_each do |user|
121
+ user.user_group.number_of_time_to_notify_overdue.times do |i|
122
+ checkouts = user.checkouts.due_date_on((user.user_group.number_of_day_to_notify_overdue * (i + 1)).days.ago.beginning_of_day)
123
+ unless checkouts.empty?
124
+ checkouts.each do |checkout|
125
+ #logger.info checkout
126
+ r = ReminderList.where(:checkout_id => checkout.id)
127
+ unless r.nil?
128
+ r = ReminderList.new
129
+ r.checkout_id = checkout.id
130
+ r.status = 0
131
+ r.save!
132
+ logger.info "create ReminderList checkout_id=#{checkout.id}"
133
+ queues_size += 1
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ queues_size
141
+ end
142
+
143
+ # output
144
+ def self.output_checkouts(checkouts, user, current_user)
145
+ report = ThinReports::Report.new :layout => File.join(Rails.root, 'report', 'checkouts.tlf')
146
+
147
+ report.layout.config.list(:list) do
148
+ use_stores :total => 0
149
+ events.on :footer_insert do |e|
150
+ e.section.item(:total).value(checkouts.size)
151
+ e.section.item(:message).value(SystemConfiguration.get("checkouts_print.message"))
152
+ end
153
+ end
154
+
155
+ library = Library.find(current_user.library_id) rescue nil
156
+
157
+ report.start_new_page do |page|
158
+ page.item(:library).value(LibraryGroup.system_name(@locale))
159
+ page.item(:user).value(user.user_number)
160
+ page.item(:lend_user).value(current_user.user_number)
161
+ page.item(:lend_library).value(library.display_name)
162
+ page.item(:lend_library_telephone_number_1).value(library.telephone_number_1)
163
+ page.item(:lend_library_telephone_number_2).value(library.telephone_number_2)
164
+ page.item(:date).value(Time.now.strftime('%Y/%m/%d'))
165
+
166
+ checkouts.each do |checkout|
167
+ page.list(:list).add_row do |row|
168
+ row.item(:book).value(checkout.item.manifestation.original_title)
169
+ row.item(:due_date).value(checkout.due_date)
170
+ end
171
+ end
172
+ end
173
+ return report
174
+ end
175
+
176
+ def self.output_checkoutlist_pdf(checkouts, view)
177
+ report = ThinReports::Report.new :layout => File.join(Rails.root, 'report', 'checkoutlist.tlf')
178
+
179
+ # set page_num
180
+ report.events.on :page_create do |e|
181
+ e.page.item(:page).value(e.page.no)
182
+ end
183
+ report.events.on :generate do |e|
184
+ e.pages.each do |page|
185
+ page.item(:total).value(e.report.page_count)
186
+ end
187
+ end
188
+
189
+ report.start_new_page do |page|
190
+ page.item(:date).value(Time.now)
191
+ if view == 'overdue'
192
+ page.item(:page_title).value(I18n.t('checkout.listing_overdue_item'))
193
+ else
194
+ page.item(:page_title).value(I18n.t('page.listing', :model => I18n.t('activerecord.models.checkout')))
195
+ end
196
+
197
+ if checkouts.size == 0
198
+ page.list(:list).add_row do |row|
199
+ row.item(:not_found).show
200
+ row.item(:not_found).value(I18n.t('page.no_record_found'))
201
+ (1..7).each do |i|
202
+ row.item("line#{i}").hide
203
+ end
204
+ end
205
+ else
206
+ checkouts.each do |checkout|
207
+ page.list(:list).add_row do |row|
208
+ row.item(:not_found).hide
209
+ user = checkout.user.patron.full_name
210
+ if SystemConfiguration.get("checkout_print.old") == true and checkout.user.patron.date_of_birth
211
+ age = (Time.now.strftime("%Y%m%d").to_f - checkout.user.patron.date_of_birth.strftime("%Y%m%d").to_f) / 10000
212
+ age = age.to_i
213
+ user = user + '(' + age.to_s + I18n.t('activerecord.attributes.patron.old') +')'
214
+ end
215
+ row.item(:user).value(user)
216
+ row.item(:title).value(checkout.item.manifestation.original_title)
217
+ row.item(:item_identifier).value(checkout.item.item_identifier)
218
+ row.item(:library).value(checkout.item.shelf.library.display_name.localize)
219
+ row.item(:shelf).value(checkout.item.shelf.display_name.localize)
220
+ row.item(:due_date).value(checkout.due_date.strftime("%Y/%m/%d"))
221
+ renewal_count = checkout.checkout_renewal_count.to_s + '/' + checkout.item.checkout_status(checkout.user).checkout_renewal_limit.to_s
222
+ row.item(:renewal_count).value(renewal_count)
223
+ due_date_datetype = checkout.due_date.strftime("%Y-%m-%d")
224
+ overdue = Date.today - due_date_datetype.to_date
225
+ overdue = 0 if overdue < 0
226
+ row.item(:overdue).value(overdue)
227
+ end
228
+ end
229
+ end
230
+ end
231
+ return report
232
+ end
233
+
234
+ def self.output_checkoutlist_csv(checkouts, view)
235
+ data = String.new
236
+ data << "\xEF\xBB\xBF".force_encoding("UTF-8") + "\n"
237
+ columns = [
238
+ [:user,'activerecord.models.user'],
239
+ [:title, 'activerecord.attributes.manifestation.original_title'],
240
+ [:item_identifier,'activerecord.attributes.item.item_identifier'],
241
+ [:library, 'activerecord.models.library'],
242
+ [:shelf, 'activerecord.models.shelf'],
243
+ [:due_date, 'activerecord.attributes.checkout.due_date'],
244
+ [:renewal_count, 'activerecord.attributes.checkout.renewal_count'],
245
+ [:overdue, 'checkout.number_of_day_overdue'],
246
+ ]
247
+
248
+ # title column
249
+ row = columns.map {|column| I18n.t(column[1])}
250
+ data << '"'+row.join("\"\t\"")+"\"\n"
251
+
252
+ # set
253
+ checkouts.each do |checkout|
254
+ row = []
255
+ columns.each do |column|
256
+ case column[0]
257
+ when :user
258
+ user = checkout.user.patron.full_name
259
+ if SystemConfiguration.get("reserve_print.old") == true and checkout.user.patron.date_of_birth
260
+ age = (Time.now.strftime("%Y%m%d").to_f - checkout.user.patron.date_of_birth.strftime("%Y%m%d").to_f) / 10000
261
+ age = age.to_i
262
+ user = user + '(' + age.to_s + I18n.t('activerecord.attributes.patron.old') +')'
263
+ end
264
+ row << user
265
+ when :title
266
+ row << checkout.item.manifestation.original_title
267
+ when :item_identifier
268
+ row << checkout.item.item_identifier
269
+ when :library
270
+ row << checkout.item.shelf.library.display_name.localize
271
+ when :shelf
272
+ row << checkout.item.shelf.display_name.localize
273
+ when :due_date
274
+ row << checkout.due_date.strftime("%Y/%m/%d")
275
+ when :renewal_count
276
+ renewal_count = checkout.checkout_renewal_count.to_s + '/' + checkout.item.checkout_status(checkout.user).checkout_renewal_limit.to_s
277
+ row << renewal_count
278
+ when :overdue
279
+ due_date_datetype = checkout.due_date.strftime("%Y-%m-%d")
280
+ overdue = Date.today - due_date_datetype.to_date
281
+ overdue = 0 if overdue < 0
282
+ row << overdue
283
+ end
284
+ end
285
+ data << '"'+row.join("\"\t\"")+"\"\n"
286
+ end
287
+ return data
288
+ end
289
+ end
290
+
291
+ # == Schema Information
292
+ #
293
+ # Table name: checkouts
294
+ #
295
+ # id :integer not null, primary key
296
+ # user_id :integer
297
+ # item_id :integer not null
298
+ # checkin_id :integer
299
+ # librarian_id :integer
300
+ # basket_id :integer
301
+ # due_date :datetime
302
+ # checkout_renewal_count :integer default(0), not null
303
+ # lock_version :integer default(0), not null
304
+ # created_at :datetime
305
+ # updated_at :datetime
306
+ #
307
+