enju_standalone_interface 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.
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
+