elibri_onix_generator 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,1046 +6,1043 @@ module Elibri
6
6
  module ONIX
7
7
 
8
8
  module Generator
9
-
9
+ extend ActiveSupport::Concern
10
10
 
11
11
  SHORT_TAGS = YAML::load_file(File.dirname(__FILE__) + "/xml_tags.yml")
12
12
  DOC_ORDER = ["record_identifiers", "publishing_status", "product_form", "contributors", "titles", "series_memberships", "measurement",
13
13
  "sale_restrictions", "territorial_rights", "audience_range", "publisher_info", "extent", "edition", "languages", "epub_details",
14
14
  "texts", "supporting_resources", "subjects", "elibri_extensions"]
15
- #"related_products", "supply_details"
16
-
17
- def self.included(base)
18
- base.class_eval do
19
- #"subjects", "related_products", "supply_details"
20
- attr_reader :builder, :tags_type
21
-
22
-
23
- def self.tag(builder, short_tags, tag_id, *args, &block)
24
- if short_tags
25
- if SHORT_TAGS[tag_id]
26
- tag_id = SHORT_TAGS[tag_id]
27
- elsif tag_id.starts_with?("elibri")
28
- tag_id
29
- else
30
- raise "Unknow short tag for: #{tag_id}"
31
- end
32
- end
33
- builder.__send__(tag_id, *args, &block)
34
- end
15
+ # "related_products", "supply_details"
35
16
 
36
- def self.render_header(builder, options = {}, &block)
37
- options.reverse_merge!({:short_tags => false, :elibri_onix_dialect => '3.0.1'})
38
- short_tags = options[:short_tags]
17
+ included do
18
+ attr_reader :builder, :tags_type
19
+ end
39
20
 
40
- builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
41
- message_attributes = {:release => "3.0", :xmlns => "http://ns.editeur.org/onix/3.0/reference", "xmlns:elibri" => "http://elibri.com.pl/ns/extensions"}
42
- message_attributes.delete('xmlns:elibri') if options[:pure_onix]
21
+ module ClassMethods
43
22
 
44
- builder.ONIXMessage message_attributes do
45
- unless options[:pure_onix]
46
- builder.elibri :Dialect, options[:elibri_onix_dialect] # potrzebne, aby parser wiedział jak interpretować niektóre tagi
47
- end
48
- tag(builder, short_tags, :Header) do
49
- tag(builder, short_tags, :Sender) do
50
- tag(builder, short_tags, :SenderName, "Elibri.com.pl")
51
- tag(builder, short_tags, :ContactName, "Tomasz Meka")
52
- tag(builder, short_tags, :EmailAddress, "kontakt@elibri.com.pl")
53
- end
54
- tag(builder, short_tags, :SentDateTime, Date.today.strftime("%Y%m%d"))
55
- end
56
- yield(builder) if block_given?
23
+ def tag(builder, short_tags, tag_id, *args, &block)
24
+ if short_tags
25
+ if SHORT_TAGS[tag_id]
26
+ tag_id = SHORT_TAGS[tag_id]
27
+ elsif tag_id.starts_with?("elibri")
28
+ tag_id
29
+ else
30
+ raise "Unknow short tag for: #{tag_id}"
57
31
  end
58
32
  end
33
+ builder.__send__(tag_id, *args, &block)
34
+ end
35
+
59
36
 
37
+ def render_header(builder, options = {}, &block)
38
+ options.reverse_merge!({:short_tags => false, :elibri_onix_dialect => '3.0.1'})
39
+ short_tags = options[:short_tags]
60
40
 
61
- def initialize(products, options = {})
62
- options.reverse_merge!({
63
- :tags_type => :full,
64
- :export_headers => true,
65
- :elibri_onix_dialect => '3.0.1',
66
- :comments => false,
67
- :xml_variant => Elibri::XmlVariant::FULL_VARIANT
68
- })
69
-
70
- @xml_variant = options[:xml_variant]
71
- raise ":xml_variant unspecified" if @xml_variant.blank? or !@xml_variant.kind_of?(::Elibri::XmlVariant)
72
-
73
- @products = Array(products)
74
- @tags_type = ActiveSupport::StringInquirer.new(options[:tags_type].to_s)
75
- @comments = options[:comments]
76
- @comment_kinds = options[:comment_kinds]
77
- @out = []
78
- @builder = Builder::XmlMarkup.new(:indent => 2, :target => @out)
79
- @elibri_onix_dialect = options[:elibri_onix_dialect]
80
- # Gdy true, ignorujemy rozszerzenia eLibri
81
- @pure_onix = options[:pure_onix]
82
-
83
- # W testach często nie chcę żadnych nagłówków - interesuje mnie tylko tag <Product>
84
- if options[:export_headers]
85
- ONIX::XMLGenerator.render_header(builder, :short_tags => tags_type.short?, :elibri_onix_dialect => @elibri_onix_dialect, :pure_onix => @pure_onix) do
86
- render_products!
41
+ builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
42
+ message_attributes = {:release => "3.0", :xmlns => "http://ns.editeur.org/onix/3.0/reference", "xmlns:elibri" => "http://elibri.com.pl/ns/extensions"}
43
+ message_attributes.delete('xmlns:elibri') if options[:pure_onix]
44
+
45
+ builder.ONIXMessage message_attributes do
46
+ unless options[:pure_onix]
47
+ builder.elibri :Dialect, options[:elibri_onix_dialect] # potrzebne, aby parser wiedział jak interpretować niektóre tagi
48
+ end
49
+ tag(builder, short_tags, :Header) do
50
+ tag(builder, short_tags, :Sender) do
51
+ tag(builder, short_tags, :SenderName, "Elibri.com.pl")
52
+ tag(builder, short_tags, :ContactName, "Tomasz Meka")
53
+ tag(builder, short_tags, :EmailAddress, "kontakt@elibri.com.pl")
87
54
  end
88
- else
89
- render_products!
55
+ tag(builder, short_tags, :SentDateTime, Date.today.strftime("%Y%m%d"))
90
56
  end
57
+ yield(builder) if block_given?
91
58
  end
92
-
93
-
94
- def to_s
95
- @out.join
59
+ end
60
+
61
+
62
+ # Zwróć dokumentację dla metod sekcji ONIX z bieżącego pliku. Dzięki temu dokumentacja ONIX jest generowana w locie
63
+ # i nie rozjedzie się z kodem. Dokumentacje można wygenerować tylko dla metod 'def export_XXX!'.
64
+ #
65
+ # Przykład dokumentowania:
66
+ # # @hidden_tags RecordReference NotificationType
67
+ # # @title Wymiary produktu
68
+ # # eLibri zachowuje tylko <strong>wysokość, szerokość, grubość oraz masę produktu.</strong> Dla produktów typu mapa, eksportujemy również jej skalę
69
+ # # w tagu &lt;MapScale&gt;
70
+ # def export_measurement!(product)
71
+ # [...]
72
+ # end
73
+ #
74
+ # @hidden_tags określa tagi ONIX, które należy zwinąć w celu zachowania czytelności XML`a.
75
+ # @title to tytuł sekcji a reszta to wieloliniowy opis.
76
+ #
77
+ # Dla każdej sekcji trzeba utworzyć odpowiednią metodę w Product::Examples, która zwróci stub produktu.
78
+ # Np. dla metody 'export_measurement!' w Product::Examples należy utworzyć metodę 'onix_measurement_example'.
79
+ def onix_sections_docs
80
+ # Wczytaj bieżący plik
81
+ code_lines = File.readlines(__FILE__)
82
+
83
+ section_docs = Array.new
84
+ # Dla każdej metody o sygnaturze 'def export_NAZWA_SEKCJI!' czytaj otaczające linie komentarzy:
85
+ instance_methods.grep(/export_/).each_with_index do |method_name, section_idx|
86
+ section_docs[section_idx] ||= Hash.new
87
+ section_docs[section_idx][:section_name] = method_name[/export_(.*)!/, 1] # "export_supplier_identifier!" => "supplier_identifier"
88
+ section_docs[section_idx][:hidden_tags] = Array.new
89
+ section_docs[section_idx][:auto_render] = true
90
+
91
+ # Znajdź numer linii z definicją metody:
92
+ method_definition_line_idx = code_lines.find_index {|line| line.match(/^\s*def #{method_name}/)}
93
+
94
+ # Cofamy się w gorę kodu, aż do początku pliku w poszukiwaniu linii zawierającej tag @title w komentarzu.
95
+ (method_definition_line_idx-1).downto(0).each do |line_idx|
96
+ # Oczyść linię kodu ze znaku komentarza i zbędnych spacji:
97
+ line = code_lines[line_idx].strip.sub(/^\s*#\s*/, '#')
98
+ raise "Nieprawidłowy format dokumentacji dla metody #{method_name}" if line.match(/^end$/)
99
+ if md = line.match(/^\s*$/)
100
+ break
101
+ elsif md = line.match(/@render (.*)$/)
102
+ section_docs[section_idx][:auto_render] = false
103
+ render_call = "\n= render :partial => 'example', :locals => { :method => '#{md[1].strip}' }\n"
104
+ section_docs[section_idx][:description] = [render_call, section_docs[section_idx][:description]].join("\n")
105
+ elsif md = line.match(/@title (.*)$/)
106
+ section_docs[section_idx][:section_title] = md[1].gsub(/^#/, '')
107
+ elsif md = line.match(/@hidden_tags (.*)$/)
108
+ section_docs[section_idx][:hidden_tags] = md[1].gsub(/^#/, '').scan(/\w+/)
109
+ elsif line == '#'
110
+ section_docs[section_idx][:description] = ["\n%br/\n", section_docs[section_idx][:description]].join("\n")
111
+ else
112
+ section_docs[section_idx][:description] = [line.gsub(/^#/, ''), section_docs[section_idx][:description]].join("\n")
113
+ end
114
+ end
96
115
  end
116
+ # Zwróć posortowane według kolejności sekcji:
117
+ section_docs.find_all { |section_hash| DOC_ORDER.index(section_hash[:section_name]) }.sort_by {|section_hash| DOC_ORDER.index(section_hash[:section_name]) }
118
+ end
119
+ end
97
120
 
98
121
 
99
- # Zwróć dokumentację dla metod sekcji ONIX z bieżącego pliku. Dzięki temu dokumentacja ONIX jest generowana w locie
100
- # i nie rozjedzie się z kodem. Dokumentacje można wygenerować tylko dla metod 'def export_XXX!'.
101
- #
102
- # Przykład dokumentowania:
103
- # # @hidden_tags RecordReference NotificationType
104
- # # @title Wymiary produktu
105
- # # eLibri zachowuje tylko <strong>wysokość, szerokość, grubość oraz masę produktu.</strong> Dla produktów typu mapa, eksportujemy również jej skalę
106
- # # w tagu &lt;MapScale&gt;
107
- # def export_measurement!(product)
108
- # [...]
109
- # end
110
- #
111
- # @hidden_tags określa tagi ONIX, które należy zwinąć w celu zachowania czytelności XML`a.
112
- # @title to tytuł sekcji a reszta to wieloliniowy opis.
113
- #
114
- # Dla każdej sekcji trzeba utworzyć odpowiednią metodę w Product::Examples, która zwróci stub produktu.
115
- # Np. dla metody 'export_measurement!' w Product::Examples należy utworzyć metodę 'onix_measurement_example'.
116
- def self.onix_sections_docs
117
- # Wczytaj bieżący plik
118
- code_lines = File.readlines(__FILE__)
119
-
120
- section_docs = Array.new
121
- # Dla każdej metody o sygnaturze 'def export_NAZWA_SEKCJI!' czytaj otaczające linie komentarzy:
122
- ONIX::XMLGenerator.instance_methods.grep(/export_/).each_with_index do |method_name, section_idx|
123
- section_docs[section_idx] ||= Hash.new
124
- section_docs[section_idx][:section_name] = method_name[/export_(.*)!/, 1] # "export_supplier_identifier!" => "supplier_identifier"
125
- section_docs[section_idx][:hidden_tags] = Array.new
126
- section_docs[section_idx][:auto_render] = true
127
-
128
- # Znajdź numer linii z definicją metody:
129
- method_definition_line_idx = code_lines.find_index {|line| line.match(/^\s*def #{method_name}/)}
130
-
131
- # Cofamy się w gorę kodu, aż do początku pliku w poszukiwaniu linii zawierającej tag @title w komentarzu.
132
- (method_definition_line_idx-1).downto(0).each do |line_idx|
133
- # Oczyść linię kodu ze znaku komentarza i zbędnych spacji:
134
- line = code_lines[line_idx].strip.sub(/^\s*#\s*/, '#')
135
- raise "Nieprawidłowy format dokumentacji dla metody #{method_name}" if line.match(/^end$/)
136
- if md = line.match(/^\s*$/)
137
- break
138
- elsif md = line.match(/@render (.*)$/)
139
- section_docs[section_idx][:auto_render] = false
140
- render_call = "\n= render :partial => 'example', :locals => { :method => '#{md[1].strip}' }\n"
141
- section_docs[section_idx][:description] = [render_call, section_docs[section_idx][:description]].join("\n")
142
- elsif md = line.match(/@title (.*)$/)
143
- section_docs[section_idx][:section_title] = md[1].gsub(/^#/, '')
144
- elsif md = line.match(/@hidden_tags (.*)$/)
145
- section_docs[section_idx][:hidden_tags] = md[1].gsub(/^#/, '').scan(/\w+/)
146
- elsif line == '#'
147
- section_docs[section_idx][:description] = ["\n%br/\n", section_docs[section_idx][:description]].join("\n")
148
- else
149
- section_docs[section_idx][:description] = [line.gsub(/^#/, ''), section_docs[section_idx][:description]].join("\n")
150
- end
151
- end
152
- end
153
- # Zwróć posortowane według kolejności sekcji:
154
- section_docs.find_all { |section_hash| DOC_ORDER.index(section_hash[:section_name]) }.sort_by {|section_hash| DOC_ORDER.index(section_hash[:section_name]) }
122
+ def initialize(products, options = {})
123
+ options.reverse_merge!({
124
+ :tags_type => :full,
125
+ :export_headers => true,
126
+ :elibri_onix_dialect => '3.0.1',
127
+ :comments => false,
128
+ :xml_variant => Elibri::XmlVariant::FULL_VARIANT
129
+ })
130
+
131
+ @xml_variant = options[:xml_variant]
132
+ raise ":xml_variant unspecified" if @xml_variant.blank? or !@xml_variant.kind_of?(::Elibri::XmlVariant)
133
+
134
+ @products = Array.wrap(products)
135
+ @tags_type = ActiveSupport::StringInquirer.new(options[:tags_type].to_s)
136
+ @comments = options[:comments]
137
+ @comment_kinds = options[:comment_kinds]
138
+ @out = []
139
+ @builder = Builder::XmlMarkup.new(:indent => 2, :target => @out)
140
+ @elibri_onix_dialect = options[:elibri_onix_dialect]
141
+ # Gdy true, ignorujemy rozszerzenia eLibri
142
+ @pure_onix = options[:pure_onix]
143
+
144
+ # W testach często nie chcę żadnych nagłówków - interesuje mnie tylko tag <Product>
145
+ if options[:export_headers]
146
+ self.class.render_header(builder, :short_tags => tags_type.short?, :elibri_onix_dialect => @elibri_onix_dialect, :pure_onix => @pure_onix) do
147
+ render_products!
155
148
  end
149
+ else
150
+ render_products!
151
+ end
152
+ end
156
153
 
157
154
 
158
- protected
159
-
160
- # Wstaw do XML`a komentarz
161
- def comment(text, options = {})
162
- if options[:kind] && @comment_kinds
163
- Array(options[:kind]).each do |kind|
164
- builder.comment!("$#{kind}$ #{text}")
165
- end
166
- elsif @comments
167
- builder.comment!(text)
168
- end
169
- end
170
-
171
-
172
- def comment_dictionary(description, dict, options = {})
173
- indent = options[:indent] || 4
174
- pretty_string = lambda {|dict_item| "\n" + " " * indent + "#{dict_item.onix_code} - #{dict_item.name}" }
175
- case dict
176
- when Symbol
177
- dictionary_items = Elibri::ONIX::Dict::Release_3_0.const_get(dict)::ALL.map(&pretty_string)
178
- when Array
179
- dictionary_items = dict.map {|dict_item| "\n" + " " * indent + dict_item }
180
- end
155
+ def to_s
156
+ @out.join
157
+ end
181
158
 
182
- comment(description + dictionary_items.join, options)
183
- end
184
159
 
160
+ protected
185
161
 
186
- def render_products!
187
- @products.each do |product|
188
- next unless product.public?
189
-
190
- tag(:Product) do
191
- export_record_identifiers!(product) #PR.1 + PR.2
192
- if @xml_variant.includes_basic_meta?
193
- tag(:DescriptiveDetail) do
194
- export_product_form!(product) #PR.3
195
- export_epub_details!(product) #PR.3
196
- export_measurement!(product)
197
- #jak się dodaje tytuł, który nie jest samodzielne w sprzedaży?
198
- #jak się dodaje tytuł, który zostanie przeceniony?
199
- export_series_memberships!(product) #P.5
200
- export_titles!(product) #PR.6
201
- export_contributors!(product) #PR.7
202
- #PR.8 - konferencje
203
- export_edition!(product) #PR.9
204
- export_languages!(product) #PR.10
205
- export_extent!(product) #PR.11
206
- export_subjects!(product) #PR.12
207
- export_audience_range!(product) if product.audience_range_present? #PR.13
208
- end
209
- end
210
- if @xml_variant.includes_other_texts? || @xml_variant.includes_media_files?
211
- tag(:CollateralDetail) do
212
- if @xml_variant.includes_other_texts? #TODO zmienić nazwę wariantu
213
- export_texts!(product) #PR.14
214
- end
215
- #P.15 - citywany kontent - sprawdzić
216
- if @xml_variant.includes_media_files?
217
- export_supporting_resources!(product) #PR.16 #TODO - to jest też do przerobienia
218
- end
219
- #P.17 - nagrody
220
- end
221
- end
222
- remove_tag_if_empty!(:CollateralDetail)
223
- #P.18 - ContentItem
224
- tag(:PublishingDetail) do
225
- export_publisher_info!(product) #P.19
226
- export_publishing_status!(product) #PR.20
227
- export_territorial_rights!(product)
228
- export_sale_restrictions!(product) if product.sale_restricted? #PR.21
229
- end
230
- remove_tag_if_empty!(:PublishingDetail)
231
-
232
- #P.23 - related products
233
- if product.facsimiles.present?
234
- export_related_products!(product)
235
- end
236
- #P.24 - Market
237
- #P.25 - market representation
238
- if @xml_variant.includes_stocks?
239
- export_supply_details!(product) #PR.26
240
- end
241
- #fake dla exportu ze sklepu - w elibri ten kod nie zadziała
242
- # if @xml_variant.respond_to?(:cover_price?) && @xml_variant.cover_price?
243
- # export_cover_price!(product) #fake, żeby jakoś te dane wysłać
244
- # end
245
- export_elibri_extensions!(product) unless @pure_onix
246
- end
247
- end
162
+ # Wstaw do XML`a komentarz
163
+ def comment(text, options = {})
164
+ if options[:kind] && @comment_kinds
165
+ Array(options[:kind]).each do |kind|
166
+ builder.comment!("$#{kind}$ #{text}")
248
167
  end
168
+ elsif @comments
169
+ builder.comment!(text)
170
+ end
171
+ end
249
172
 
250
173
 
251
- # Renderuj tag w XML`u za pomocą Buildera. Jeśli wybrano opcję krótkich tagów,
252
- # wstaw krótki tag z hasha SHORT_TAGS.
253
- def tag(tag_id, *args, &block)
254
- self.class.tag(builder, tags_type.short?, tag_id, *args, &block)
255
- end
256
-
257
- def remove_tag_if_empty!(tag_name)
258
- idx = @out.rindex("<#{tag_name}")
259
- if idx
260
- tail = @out[idx..-1].join.strip.gsub("\n", "").gsub(" ", "")
261
- if tail == "<#{tag_name}></#{tag_name}>" #wycinaj końcówkę
262
- (@out.size - idx + 1).times do #zmieniaj listę in-place
263
- @out.pop
264
- end
265
- end
266
- end
267
- end
174
+ def comment_dictionary(description, dict, options = {})
175
+ indent = options[:indent] || 4
176
+ pretty_string = lambda {|dict_item| "\n" + " " * indent + "#{dict_item.onix_code} - #{dict_item.name}" }
177
+ case dict
178
+ when Symbol
179
+ dictionary_items = Elibri::ONIX::Dict::Release_3_0.const_get(dict)::ALL.map(&pretty_string)
180
+ when Array
181
+ dictionary_items = dict.map {|dict_item| "\n" + " " * indent + dict_item }
182
+ end
268
183
 
269
- # @hidden_tags NotificationType DescriptiveDetail ProductSupply PublishingDetail
270
- # @title Identyfikatory rekordu
271
- # Każdy rekord w ONIX-ie posiada wewnętrzny identyfikator, który jest dowolnym ciągiem znaków, i jest przekazywany
272
- # w tagu <strong>&lt;ProductIdentifier&gt;</strong>. Gwarantowana jest jego niezmienność.
273
- #
274
- #
275
- # Oprócz tego każdy produkt może posiadać numer ISBN, EAN oraz jeden lub więcej identyfikatorów dostawców (np. numer w bazie Olesiejuka)
276
- # Tutaj już nie ma gwarancji niezmienności, choć jest to bardzo rzadka sytuacja (np. wydrukowany został jednak inny numer ISBN na okładce,
277
- # i wydawcnictwo zmienia wpis w eLibri)
278
- def export_record_identifiers!(product)
279
- comment 'Unikalne ID rekordu produktu', :kind => :onix_record_identifiers
280
- tag(:RecordReference, product.record_reference) #doc
281
- comment_dictionary "Typ powiadomienia", :NotificationType, :kind => :onix_publishing_status
282
- tag(:NotificationType, product.notification_type.onix_code) # Notification confirmed on publication - Lista 1
283
- if product.respond_to?(:deletion_text) && product.deletion_text.present?
284
- comment "Występuje tylko gdy NotificationType == #{Elibri::ONIX::Dict::Release_3_0::NotificationType::DELETE}", :kind => :onix_record_identifiers
285
- tag(:DeletionText, product.deletion_text)
184
+ comment(description + dictionary_items.join, options)
185
+ end
186
+
187
+
188
+ def render_products!
189
+ @products.each do |product|
190
+ next unless product.public?
191
+
192
+ tag(:Product) do
193
+ export_record_identifiers!(product) #PR.1 + PR.2
194
+ if @xml_variant.includes_basic_meta?
195
+ tag(:DescriptiveDetail) do
196
+ export_product_form!(product) #PR.3
197
+ export_epub_details!(product) #PR.3
198
+ export_measurement!(product)
199
+ #jak się dodaje tytuł, który nie jest samodzielne w sprzedaży?
200
+ #jak się dodaje tytuł, który zostanie przeceniony?
201
+ export_series_memberships!(product) #P.5
202
+ export_titles!(product) #PR.6
203
+ export_contributors!(product) #PR.7
204
+ #PR.8 - konferencje
205
+ export_edition!(product) #PR.9
206
+ export_languages!(product) #PR.10
207
+ export_extent!(product) #PR.11
208
+ export_subjects!(product) #PR.12
209
+ export_audience_range!(product) if product.audience_range_present? #PR.13
210
+ end
286
211
  end
287
-
288
- if product.isbn_value
289
- comment 'ISBN', :kind => :onix_record_identifiers
290
- tag(:ProductIdentifier) do
291
- tag(:ProductIDType, Elibri::ONIX::Dict::Release_3_0::ProductIDType::ISBN13) #lista 5
292
- tag(:IDValue, product.isbn_value)
293
- end
212
+ if @xml_variant.includes_other_texts? || @xml_variant.includes_media_files?
213
+ tag(:CollateralDetail) do
214
+ if @xml_variant.includes_other_texts? #TODO zmienić nazwę wariantu
215
+ export_texts!(product) #PR.14
216
+ end
217
+ #P.15 - citywany kontent - sprawdzić
218
+ if @xml_variant.includes_media_files?
219
+ export_supporting_resources!(product) #PR.16 #TODO - to jest też do przerobienia
220
+ end
221
+ #P.17 - nagrody
222
+ end
294
223
  end
295
-
296
- if product.ean.present? && product.ean != product.isbn_value
297
- comment 'EAN-13 - gdy inny niż ISBN', :kind => :onix_record_identifiers
298
-
299
- tag(:ProductIdentifier) do
300
- tag(:ProductIDType, Elibri::ONIX::Dict::Release_3_0::ProductIDType::EAN)
301
- tag(:IDValue, product.ean)
302
- end
224
+ remove_tag_if_empty!(:CollateralDetail)
225
+ #P.18 - ContentItem
226
+ tag(:PublishingDetail) do
227
+ export_publisher_info!(product) #P.19
228
+ export_publishing_status!(product) #PR.20
229
+ export_territorial_rights!(product)
230
+ export_sale_restrictions!(product) if product.sale_restricted? #PR.21
231
+ end
232
+ remove_tag_if_empty!(:PublishingDetail)
233
+
234
+ #P.23 - related products
235
+ if product.facsimiles.present?
236
+ export_related_products!(product)
303
237
  end
304
-
238
+ #P.24 - Market
239
+ #P.25 - market representation
305
240
  if @xml_variant.includes_stocks?
306
- product.product_availabilities.each do |pa|
307
- if pa.supplier_identifier.present?
308
- comment "Identyfikator dostawcy: #{pa.supplier.name}", :kind => :onix_record_identifiers
309
- tag(:ProductIdentifier) do
310
- tag(:ProductIDType, Elibri::ONIX::Dict::Release_3_0::ProductIDType::PROPRIETARY) #lista 5
311
- tag(:IDTypeName, pa.supplier.name)
312
- tag(:IDValue, pa.supplier_identifier)
313
- end
314
- end
315
- end
241
+ export_supply_details!(product) #PR.26
316
242
  end
243
+ #fake dla exportu ze sklepu - w elibri ten kod nie zadziała
244
+ # if @xml_variant.respond_to?(:cover_price?) && @xml_variant.cover_price?
245
+ # export_cover_price!(product) #fake, żeby jakoś te dane wysłać
246
+ # end
247
+ export_elibri_extensions!(product) unless @pure_onix
317
248
  end
249
+ end
250
+ end
251
+
252
+
253
+ # Renderuj tag w XML`u za pomocą Buildera. Jeśli wybrano opcję krótkich tagów,
254
+ # wstaw krótki tag z hasha SHORT_TAGS.
255
+ def tag(tag_id, *args, &block)
256
+ self.class.tag(builder, tags_type.short?, tag_id, *args, &block)
257
+ end
258
+
259
+ def remove_tag_if_empty!(tag_name)
260
+ idx = @out.rindex("<#{tag_name}")
261
+ if idx
262
+ tail = @out[idx..-1].join.strip.gsub("\n", "").gsub(" ", "")
263
+ if tail == "<#{tag_name}></#{tag_name}>" #wycinaj końcówkę
264
+ (@out.size - idx + 1).times do #zmieniaj listę in-place
265
+ @out.pop
266
+ end
267
+ end
268
+ end
269
+ end
270
+
271
+ # @hidden_tags NotificationType DescriptiveDetail ProductSupply PublishingDetail
272
+ # @title Identyfikatory rekordu
273
+ # Każdy rekord w ONIX-ie posiada wewnętrzny identyfikator, który jest dowolnym ciągiem znaków, i jest przekazywany
274
+ # w tagu <strong>&lt;ProductIdentifier&gt;</strong>. Gwarantowana jest jego niezmienność.
275
+ #
276
+ #
277
+ # Oprócz tego każdy produkt może posiadać numer ISBN, EAN oraz jeden lub więcej identyfikatorów dostawców (np. numer w bazie Olesiejuka)
278
+ # Tutaj już nie ma gwarancji niezmienności, choć jest to bardzo rzadka sytuacja (np. wydrukowany został jednak inny numer ISBN na okładce,
279
+ # i wydawcnictwo zmienia wpis w eLibri)
280
+ def export_record_identifiers!(product)
281
+ comment 'Unikalne ID rekordu produktu', :kind => :onix_record_identifiers
282
+ tag(:RecordReference, product.record_reference) #doc
283
+ comment_dictionary "Typ powiadomienia", :NotificationType, :kind => :onix_publishing_status
284
+ tag(:NotificationType, product.notification_type.onix_code) # Notification confirmed on publication - Lista 1
285
+ if product.respond_to?(:deletion_text) && product.deletion_text.present?
286
+ comment "Występuje tylko gdy NotificationType == #{Elibri::ONIX::Dict::Release_3_0::NotificationType::DELETE}", :kind => :onix_record_identifiers
287
+ tag(:DeletionText, product.deletion_text)
288
+ end
318
289
 
290
+ if product.isbn_value
291
+ comment 'ISBN', :kind => :onix_record_identifiers
292
+ tag(:ProductIdentifier) do
293
+ tag(:ProductIDType, Elibri::ONIX::Dict::Release_3_0::ProductIDType::ISBN13) #lista 5
294
+ tag(:IDValue, product.isbn_value)
295
+ end
296
+ end
319
297
 
320
- # @hidden_tags RecordReference NotificationType ProductIdentifier TitleDetail
321
- # @title Forma produktu
322
- # <strong>&lt;ProductForm&gt;</strong> określa typ produktu. Np. BA to książka.<br/>
323
- # <strong>&lt;ProductComposition&gt;</strong> przybiera aktualnie zawsze wartość 00 - czyli że przedmiotem handlu jest pojedyncza książka.
324
- # W przyszłości ulegnie to zmianie, gdy dodamy do eLibri obsługę pakietów książek. Pakiet książek to komplet kilku książek,
325
- # z nowym numerem ISBN, i nową ceną, na ogół niższą, niż suma cen książek zawartych w pakiecie.
326
- def export_product_form!(product)
327
- comment 'W tej chwili tylko 00 - pojedynczy element', :kind => :onix_product_form
328
- tag(:ProductComposition, '00') #lista 2 - Single-item retail product
298
+ if product.ean.present? && product.ean != product.isbn_value
299
+ comment 'EAN-13 - gdy inny niż ISBN', :kind => :onix_record_identifiers
329
300
 
330
- if product.product_form_onix_code
331
- comment_dictionary "Format produktu", :ProductFormCode, :indent => 10, :kind => [:onix_product_form]
332
- tag(:ProductForm, product.product_form_onix_code)
333
- end
301
+ tag(:ProductIdentifier) do
302
+ tag(:ProductIDType, Elibri::ONIX::Dict::Release_3_0::ProductIDType::EAN)
303
+ tag(:IDValue, product.ean)
334
304
  end
305
+ end
335
306
 
336
-
337
- # @hidden_tags RecordReference NotificationType ProductIdentifier TitleDetail PublishingDetail ProductComposition
338
- # @title E-booki
339
- # <strong>&lt;EpubTechnicalProtection&gt;</strong> Określa typ zabezpieczenia stosowanego przy publikacji e-booka.<br/>
340
- #
341
- # <strong>&lt;ProductFormDetail&gt;</strong> zawiera format w jakim rozprowadzany jest e-book.
342
- # Aktualnie może przyjąć wartości takie jak:
343
- # #{Elibri::ONIX::Dict::Release_3_0::ProductFormDetail::ALL.map(&:name).to_sentence(:last_word_connector => ' lub ')}<br/>
344
- #
345
- # @render onix_epub_details_example
346
- #
347
- # Wydawca może również umieścić informacje o tym, czy pozwala na publikację fragmentu książki, a jeśli tak,
348
- # to czy narzuca ograniczenie co do wielkości fragmentu (w ilości znaków albo procentowo). Ta informacja ma tylko wtedy
349
- # znaczenie, gdy dystrybutor samodzielnie dokonuje konwersji, a tym samym tworzy ebooka z fragmentem publikacji.
350
- # Wydawnictwa, które samodzielnie konwertują książki nie będą publikować tej informacji.<br/>
351
- # @render onix_unlimited_book_sample_example
352
- # @render onix_prohibited_book_sample_example
353
- # @render onix_limited_book_sample_example
354
- # <br/>
355
- # Wydawnictwa podają też w systemie eLibri informację, czy prawo do sprzedaży ebook-a jest bezterminowe.
356
- # W takim przypadku w opisie produktu wystąpi pusty tag <strong>&lt;elibri:SaleNotRestricted&gt;</strong> (ostatnie trzy przykłady).<br/><br/>
357
- # Jeśli wydawca posiada licencję na określony czas, to w opisie produktu wystąpi tag
358
- # <strong>&lt;elibri:SaleRestrictedTo&gt;</strong>, w którym będzie podana data wygaśnięcia licencji (w formacie YYYYMMDD).
359
- # Przykład użycia w pierwszym przykładzie.
360
- #
361
- def export_epub_details!(product)
362
- if product.product_form_detail_onix_codes.present? #lista 175
363
- comment_dictionary "Dostępne formaty produktu", :ProductFormDetail, :indent => 10, :kind => :onix_epub_details
364
- product.product_form_detail_onix_codes.each do |onix_code|
365
- tag(:ProductFormDetail, onix_code)
307
+ if @xml_variant.includes_stocks?
308
+ product.product_availabilities.each do |pa|
309
+ if pa.supplier_identifier.present?
310
+ comment "Identyfikator dostawcy: #{pa.supplier.name}", :kind => :onix_record_identifiers
311
+ tag(:ProductIdentifier) do
312
+ tag(:ProductIDType, Elibri::ONIX::Dict::Release_3_0::ProductIDType::PROPRIETARY) #lista 5
313
+ tag(:IDTypeName, pa.supplier.name)
314
+ tag(:IDValue, pa.supplier_identifier)
366
315
  end
367
316
  end
368
-
369
- if product.digital?
370
- if product.epub_technical_protection
371
- comment_dictionary "Zabezpieczenie", :EpubTechnicalProtection, :indent => 10, :kind => :onix_epub_details
372
- tag(:EpubTechnicalProtection, product.epub_technical_protection_onix_code)
373
- end
317
+ end
318
+ end
319
+ end
320
+
321
+
322
+ # @hidden_tags RecordReference NotificationType ProductIdentifier TitleDetail
323
+ # @title Forma produktu
324
+ # <strong>&lt;ProductForm&gt;</strong> określa typ produktu. Np. BA to książka.<br/>
325
+ # <strong>&lt;ProductComposition&gt;</strong> przybiera aktualnie zawsze wartość 00 - czyli że przedmiotem handlu jest pojedyncza książka.
326
+ # W przyszłości ulegnie to zmianie, gdy dodamy do eLibri obsługę pakietów książek. Pakiet książek to komplet kilku książek,
327
+ # z nowym numerem ISBN, i nową ceną, na ogół niższą, niż suma cen książek zawartych w pakiecie.
328
+ def export_product_form!(product)
329
+ comment 'W tej chwili tylko 00 - pojedynczy element', :kind => :onix_product_form
330
+ tag(:ProductComposition, '00') #lista 2 - Single-item retail product
331
+
332
+ if product.product_form_onix_code
333
+ comment_dictionary "Format produktu", :ProductFormCode, :indent => 10, :kind => [:onix_product_form]
334
+ tag(:ProductForm, product.product_form_onix_code)
335
+ end
336
+ end
337
+
338
+
339
+ # @hidden_tags RecordReference NotificationType ProductIdentifier TitleDetail PublishingDetail ProductComposition
340
+ # @title E-booki
341
+ # <strong>&lt;EpubTechnicalProtection&gt;</strong> Określa typ zabezpieczenia stosowanego przy publikacji e-booka.<br/>
342
+ #
343
+ # <strong>&lt;ProductFormDetail&gt;</strong> zawiera format w jakim rozprowadzany jest e-book.
344
+ # Aktualnie może przyjąć wartości takie jak:
345
+ # #{Elibri::ONIX::Dict::Release_3_0::ProductFormDetail::ALL.map(&:name).to_sentence(:last_word_connector => ' lub ')}<br/>
346
+ #
347
+ # @render onix_epub_details_example
348
+ #
349
+ # Wydawca może również umieścić informacje o tym, czy pozwala na publikację fragmentu książki, a jeśli tak,
350
+ # to czy narzuca ograniczenie co do wielkości fragmentu (w ilości znaków albo procentowo). Ta informacja ma tylko wtedy
351
+ # znaczenie, gdy dystrybutor samodzielnie dokonuje konwersji, a tym samym tworzy ebooka z fragmentem publikacji.
352
+ # Wydawnictwa, które samodzielnie konwertują książki nie będą publikować tej informacji.<br/>
353
+ # @render onix_unlimited_book_sample_example
354
+ # @render onix_prohibited_book_sample_example
355
+ # @render onix_limited_book_sample_example
356
+ # <br/>
357
+ # Wydawnictwa podają też w systemie eLibri informację, czy prawo do sprzedaży ebook-a jest bezterminowe.
358
+ # W takim przypadku w opisie produktu wystąpi pusty tag <strong>&lt;elibri:SaleNotRestricted&gt;</strong> (ostatnie trzy przykłady).<br/><br/>
359
+ # Jeśli wydawca posiada licencję na określony czas, to w opisie produktu wystąpi tag
360
+ # <strong>&lt;elibri:SaleRestrictedTo&gt;</strong>, w którym będzie podana data wygaśnięcia licencji (w formacie YYYYMMDD).
361
+ # Przykład użycia w pierwszym przykładzie.
362
+ #
363
+ def export_epub_details!(product)
364
+ if product.product_form_detail_onix_codes.present? #lista 175
365
+ comment_dictionary "Dostępne formaty produktu", :ProductFormDetail, :indent => 10, :kind => :onix_epub_details
366
+ product.product_form_detail_onix_codes.each do |onix_code|
367
+ tag(:ProductFormDetail, onix_code)
368
+ end
369
+ end
370
+
371
+ if product.digital?
372
+ if product.epub_technical_protection
373
+ comment_dictionary "Zabezpieczenie", :EpubTechnicalProtection, :indent => 10, :kind => :onix_epub_details
374
+ tag(:EpubTechnicalProtection, product.epub_technical_protection_onix_code)
375
+ end
376
+
377
+ if product.epub_fragment_info?
378
+ tag(:EpubUsageConstraint) do
379
+ comment "Rodzaj ograniczenia - w tym przypadku zawsze dotyczy dostępności fragmentu książki", :indent => 12, :kind => :onix_epub_details
380
+ tag(:EpubUsageType, Elibri::ONIX::Dict::Release_3_0::EpubUsageType::PREVIEW)
374
381
 
375
- if product.epub_fragment_info?
376
- tag(:EpubUsageConstraint) do
377
- comment "Rodzaj ograniczenia - w tym przypadku zawsze dotyczy dostępności fragmentu książki", :indent => 12, :kind => :onix_epub_details
378
- tag(:EpubUsageType, Elibri::ONIX::Dict::Release_3_0::EpubUsageType::PREVIEW)
379
-
380
- comment_dictionary "Jaka jest decyzja wydawcy?", :EpubUsageStatus, :indent => 12, :kind => :onix_epub_details
381
- tag(:EpubUsageStatus, product.epub_publication_preview_usage_status_onix_code)
382
- if product.epub_publication_preview_usage_status_onix_code == Elibri::ONIX::Dict::Release_3_0::EpubUsageStatus::LIMITED
383
- tag(:EpubUsageLimit) do
384
- if product.epub_publication_preview_unit_onix_code == Elibri::ONIX::Dict::Release_3_0::EpubUsageUnit::PERCENTAGE
385
- tag(:Quantity, product.epub_publication_preview_percentage_limit)
386
- elsif product.epub_publication_preview_unit_onix_code == Elibri::ONIX::Dict::Release_3_0::EpubUsageUnit::CHARACTERS
387
- tag(:Quantity, product.epub_publication_preview_characters_limit)
388
- end
389
- comment_dictionary "Jednostka limitu", :EpubUsageUnit, :indent => 12, :kind => :onix_epub_details
390
- tag(:EpubUsageUnit, product.epub_publication_preview_unit_onix_code)
391
- end
382
+ comment_dictionary "Jaka jest decyzja wydawcy?", :EpubUsageStatus, :indent => 12, :kind => :onix_epub_details
383
+ tag(:EpubUsageStatus, product.epub_publication_preview_usage_status_onix_code)
384
+ if product.epub_publication_preview_usage_status_onix_code == Elibri::ONIX::Dict::Release_3_0::EpubUsageStatus::LIMITED
385
+ tag(:EpubUsageLimit) do
386
+ if product.epub_publication_preview_unit_onix_code == Elibri::ONIX::Dict::Release_3_0::EpubUsageUnit::PERCENTAGE
387
+ tag(:Quantity, product.epub_publication_preview_percentage_limit)
388
+ elsif product.epub_publication_preview_unit_onix_code == Elibri::ONIX::Dict::Release_3_0::EpubUsageUnit::CHARACTERS
389
+ tag(:Quantity, product.epub_publication_preview_characters_limit)
392
390
  end
391
+ comment_dictionary "Jednostka limitu", :EpubUsageUnit, :indent => 12, :kind => :onix_epub_details
392
+ tag(:EpubUsageUnit, product.epub_publication_preview_unit_onix_code)
393
393
  end
394
394
  end
395
395
  end
396
396
  end
397
+ end
398
+ end
399
+
400
+
401
+ # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
402
+ # @title Wymiary produktu
403
+ # Następujące atrybuty są udostępniane: wysokość, szerokość, grubość oraz masę produktu. Pierwsze trzy podajemy zawsze w milimetrach, masę w gramach.
404
+ # W przypadku map eksportujemy również jej skalę w tagu &lt;MapScale&gt;
405
+ def export_measurement!(product)
406
+ return unless product.kind_of_measurable?
407
+ [[product.height, Elibri::ONIX::Dict::Release_3_0::MeasureType::HEIGHT, Product::HEIGHT_UNIT, 'Wysokość'],
408
+ [product.width, Elibri::ONIX::Dict::Release_3_0::MeasureType::WIDTH, Product::WIDTH_UNIT, 'Szerokość'],
409
+ [product.thickness, Elibri::ONIX::Dict::Release_3_0::MeasureType::THICKNESS, Product::THICKNESS_UNIT, 'Grubość'],
410
+ [product.weight, Elibri::ONIX::Dict::Release_3_0::MeasureType::WEIGHT, Product::WEIGHT_UNIT, 'Masa']
411
+ ].each do |value, measure_type_code, unit_code, name|
412
+ if value
413
+ tag(:Measure) do
414
+ comment "#{name}: #{value}#{unit_code}", :kind => :onix_measurement
415
+ tag(:MeasureType, measure_type_code) #lista 48
416
+ tag(:Measurement, value)
417
+ tag(:MeasureUnitCode, unit_code)
418
+ end
419
+ end
420
+ end
397
421
 
422
+ if product.kind_of_map? and product.map_scale
423
+ comment 'Skala mapy - tylko dla produktów typu mapa'
424
+ tag(:MapScale, product.map_scale)
425
+ end
426
+ end
427
+
428
+
429
+ # @hidden_tags ProductIdentifier DescriptiveDetail ProductSupply
430
+ # @title Cykl życia rekordu
431
+ # W ONIX-ie status rekordu jest reprezentowany za pomocą kombinacji tagów <strong>&lt;NotificationType&gt;</strong> i <strong>&lt;PublishingStatus&gt;</strong>
432
+ #
433
+ #
434
+ # Tuż po założeniu przez wydawnictwo każdy rekord ma status prywatny. Jest to wtedy widoczny tylko i wyłącznie dla pracowników wydawnictwa,
435
+ # i nie jest udostępniany na zewnątrz. Po wypełnieniu kilku podstawowych danych (autor, tytuł) pracownik wydawnictwa może zmienić status
436
+ # rekordu na <i>zapowiedź</i>. W tym przypadku wartość <strong>&lt;NotificationType&gt;</strong> to 01 - wczesne powiadomienie.
437
+ #
438
+ # @render onix_announced_product_example
439
+ #
440
+ # Po uzupełnieniu większości danych niezbędnych (okładka, cena, ISBN, okładka, dokładna data premiery) wydawnictwo może zmienić
441
+ # status rekordu na <i>przedsprzedaż</i>.
442
+ # W zależności od naszego poziomu zaufania do terminowości wydawnictwa można uruchomić dla takiego tytułu przedsprzedaż na stronie księgarni.
443
+ # Wydawnictwo może zmienić datę premiery, jeśli produkt znajduje się w przedsprzedaży, warto zaimplementować procedurę poinformowania klientów
444
+ # o zmianie.
445
+ # Rekord o takim statusie ma wartość 02 w <strong>&lt;NotificationType&gt;</strong>
446
+ #
447
+ # @render onix_preorder_product_example
448
+ #
449
+ # Po ukazaniu się książki jej status zostaje zmieniony na <i>dostępna na rynku</i>.
450
+ # Rekord o takim statusie ma wartość 03 w <strong>&lt;NotificationType&gt;</strong> i 04 w <strong>&lt;PublishingDetail&gt;</strong>
451
+ #
452
+ # @render onix_published_product_example
453
+ #
454
+ # Każde wydawnictwo oczywiście liczy na to, że nakład książki się wyprzeda. Bardzo trudno jest poprawnie zdefiniować, co oznacza wyczerpany nakład.
455
+ # Bardzo długo egzemplarze książki, której nie ma już w magazynie wydawnictwa, mogą znajdować się w księgarniach i być zwracane co jakiś czas do hurtowni,
456
+ # co powoduje, że dany tytuł będzie się stawał na jakiś czas dostępny. W związku z tym informacje o wyczerpaniu się nakładu podejmuje wydawnictwo, i oznacza
457
+ # to, że nie będzie akceptować zamówień na określony tytuł. Nie oznacza to jednak, że tytuł jest w ogóle niedostępny, w dalszym ciągu może być w ofercie
458
+ # hurtowni.
459
+ # Rekord o statusie <i>nakład wyczerpany</i> ma wartość 03 w <strong>&lt;NotificationType&gt;</strong> i 07 w <strong>&lt;PublishingDetail&gt;</strong>
460
+ #
461
+ # @render onix_out_of_print_product_example
462
+ #
463
+ # Status 08 (niedostępny) w <strong>&lt;PublishingDetail&gt;</strong> nie jest w tej chwili używany przez eLibri. W przyszłości proszę się spodziewać również
464
+ # dodania informacji o dodrukach realizowanych pod tym samym numerem ISBN.
465
+ #
466
+ def export_publishing_status!(product)
467
+ if product.publishing_status_onix_code.present?
468
+ comment_dictionary 'Status publikacji', :PublishingStatusCode, :indent => 10, :kind => :onix_publishing_status
469
+ tag(:PublishingStatus, product.publishing_status_onix_code) #lista 64 #TODO sprawdzić
470
+ end
398
471
 
399
- # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
400
- # @title Wymiary produktu
401
- # Następujące atrybuty są udostępniane: wysokość, szerokość, grubość oraz masę produktu. Pierwsze trzy podajemy zawsze w milimetrach, masę w gramach.
402
- # W przypadku map eksportujemy również jej skalę w tagu &lt;MapScale&gt;
403
- def export_measurement!(product)
404
- return unless product.kind_of_measurable?
405
- [[product.height, Elibri::ONIX::Dict::Release_3_0::MeasureType::HEIGHT, Product::HEIGHT_UNIT, 'Wysokość'],
406
- [product.width, Elibri::ONIX::Dict::Release_3_0::MeasureType::WIDTH, Product::WIDTH_UNIT, 'Szerokość'],
407
- [product.thickness, Elibri::ONIX::Dict::Release_3_0::MeasureType::THICKNESS, Product::THICKNESS_UNIT, 'Grubość'],
408
- [product.weight, Elibri::ONIX::Dict::Release_3_0::MeasureType::WEIGHT, Product::WEIGHT_UNIT, 'Masa']
409
- ].each do |value, measure_type_code, unit_code, name|
410
- if value
411
- tag(:Measure) do
412
- comment "#{name}: #{value}#{unit_code}", :kind => :onix_measurement
413
- tag(:MeasureType, measure_type_code) #lista 48
414
- tag(:Measurement, value)
415
- tag(:MeasureUnitCode, unit_code)
416
- end
417
- end
418
- end
419
-
420
- if product.kind_of_map? and product.map_scale
421
- comment 'Skala mapy - tylko dla produktów typu mapa'
422
- tag(:MapScale, product.map_scale)
472
+ #TODO - tu można również zawrzeć datę, przed którą produkt nie może być importowany do baz sklepów
473
+ date, format_code = product.publication_date_with_onix_format_code
474
+ if date && format_code
475
+ tag(:PublishingDate) do
476
+ comment 'Zawsze 01 - data publikacji', :kind => :onix_publishing_status
477
+ tag(:PublishingDateRole, Elibri::ONIX::Dict::Release_3_0::PublishingDateRole::PUBLICATION_DATE) #lista 163
478
+ comment_dictionary "Format daty", :DateFormat, :indent => 12, :kind => :onix_publishing_status
479
+ tag(:DateFormat, format_code) #lista 55
480
+ tag(:Date, date)
481
+ end
482
+ end
483
+ end
484
+
485
+ # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail Publisher PublishingStatus
486
+ # @title Terytorialne ograniczenia sprzedaży.
487
+ # W tej chwili w systemie eLibri można zastrzec, że sprzedaż książek/ebooków jest ograniczona do terenu Polski,
488
+ # albo pozwolić na sprzedaż na całym świecie. Poniżej dwa przykłady, jeden dla wyłączości na terenie Polski, drugi
489
+ # dopuszczający sprzedaż na całym świecie. Informacja o ograniczeniu jest zawarta w obręcie <strong>&lt;SalesRights&gt;</strong>
490
+ def export_territorial_rights!(product)
491
+ tag(:SalesRights) do
492
+ comment "Typ restrykcji - sprzedaż tylko w wymienionym kraju, regionie, zawsze '01'", :kind => :onix_territorial_rights
493
+ tag(:SalesRightsType, "01")
494
+ tag(:Territory) do
495
+ if product.sale_restricted_to_poland?
496
+ tag(:CountriesIncluded, "PL")
497
+ else
498
+ tag(:RegionsIncluded, "WORLD")
423
499
  end
424
500
  end
425
-
426
-
427
- # @hidden_tags ProductIdentifier DescriptiveDetail ProductSupply
428
- # @title Cykl życia rekordu
429
- # W ONIX-ie status rekordu jest reprezentowany za pomocą kombinacji tagów <strong>&lt;NotificationType&gt;</strong> i <strong>&lt;PublishingStatus&gt;</strong>
430
- #
431
- #
432
- # Tuż po założeniu przez wydawnictwo każdy rekord ma status prywatny. Jest to wtedy widoczny tylko i wyłącznie dla pracowników wydawnictwa,
433
- # i nie jest udostępniany na zewnątrz. Po wypełnieniu kilku podstawowych danych (autor, tytuł) pracownik wydawnictwa może zmienić status
434
- # rekordu na <i>zapowiedź</i>. W tym przypadku wartość <strong>&lt;NotificationType&gt;</strong> to 01 - wczesne powiadomienie.
435
- #
436
- # @render onix_announced_product_example
437
- #
438
- # Po uzupełnieniu większości danych niezbędnych (okładka, cena, ISBN, okładka, dokładna data premiery) wydawnictwo może zmienić
439
- # status rekordu na <i>przedsprzedaż</i>.
440
- # W zależności od naszego poziomu zaufania do terminowości wydawnictwa można uruchomić dla takiego tytułu przedsprzedaż na stronie księgarni.
441
- # Wydawnictwo może zmienić datę premiery, jeśli produkt znajduje się w przedsprzedaży, warto zaimplementować procedurę poinformowania klientów
442
- # o zmianie.
443
- # Rekord o takim statusie ma wartość 02 w <strong>&lt;NotificationType&gt;</strong>
444
- #
445
- # @render onix_preorder_product_example
446
- #
447
- # Po ukazaniu się książki jej status zostaje zmieniony na <i>dostępna na rynku</i>.
448
- # Rekord o takim statusie ma wartość 03 w <strong>&lt;NotificationType&gt;</strong> i 04 w <strong>&lt;PublishingDetail&gt;</strong>
449
- #
450
- # @render onix_published_product_example
451
- #
452
- # Każde wydawnictwo oczywiście liczy na to, że nakład książki się wyprzeda. Bardzo trudno jest poprawnie zdefiniować, co oznacza wyczerpany nakład.
453
- # Bardzo długo egzemplarze książki, której nie ma już w magazynie wydawnictwa, mogą znajdować się w księgarniach i być zwracane co jakiś czas do hurtowni,
454
- # co powoduje, że dany tytuł będzie się stawał na jakiś czas dostępny. W związku z tym informacje o wyczerpaniu się nakładu podejmuje wydawnictwo, i oznacza
455
- # to, że nie będzie akceptować zamówień na określony tytuł. Nie oznacza to jednak, że tytuł jest w ogóle niedostępny, w dalszym ciągu może być w ofercie
456
- # hurtowni.
457
- # Rekord o statusie <i>nakład wyczerpany</i> ma wartość 03 w <strong>&lt;NotificationType&gt;</strong> i 07 w <strong>&lt;PublishingDetail&gt;</strong>
458
- #
459
- # @render onix_out_of_print_product_example
460
- #
461
- # Status 08 (niedostępny) w <strong>&lt;PublishingDetail&gt;</strong> nie jest w tej chwili używany przez eLibri. W przyszłości proszę się spodziewać również
462
- # dodania informacji o dodrukach realizowanych pod tym samym numerem ISBN.
463
- #
464
- def export_publishing_status!(product)
465
- if product.publishing_status_onix_code.present?
466
- comment_dictionary 'Status publikacji', :PublishingStatusCode, :indent => 10, :kind => :onix_publishing_status
467
- tag(:PublishingStatus, product.publishing_status_onix_code) #lista 64 #TODO sprawdzić
501
+ end
502
+ end
503
+
504
+
505
+ # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
506
+ # @title Ograniczenia sprzedaży
507
+ # eLibri umożliwia przechowywanie informacji o ograniczaniach dotyczących sprzedaży produktu.
508
+ # Obecnie obsługuje tylko 1 typ ograniczenia: wyłączność na produkt dla określonego detalisty.
509
+ # Opcjonalnie może się też pojawić data wygaśnięcia ograniczenia - w innym przypadku oznacza to, że produkt został przeznaczony tylko
510
+ # dla jednej, określonej sieci.
511
+ # W przypadku, gdy jest podana data wyłączności na sprzedaż produktu, należy ją traktować jako faktyczną datę premiery.
512
+ def export_sale_restrictions!(product)
513
+ if product.sale_restricted?
514
+ tag(:SalesRestriction) do
515
+ #lista 71 - For sale only through designated retailer, though not under retailer's own brand/imprint.
516
+ comment "Typ restrykcji - używamy tylko #{Elibri::ONIX::Dict::Release_3_0::SalesRestrictionType::RETAILER_EXCLUSIVE} (sprzedaż tylko poprzez wybranego detalistę)", :kind => :onix_sale_restrictions
517
+ tag(:SalesRestrictionType, Elibri::ONIX::Dict::Release_3_0::SalesRestrictionType::RETAILER_EXCLUSIVE)
518
+ tag(:SalesOutlet) do
519
+ tag(:SalesOutletName, product.sale_restricted_for)
468
520
  end
521
+ comment "Ograniczenie wygasa #{product.sale_restricted_to.strftime("%d.%m.%Y")}", :kind => :onix_sale_restrictions
522
+ tag(:EndDate, product.sale_restricted_to.strftime("%Y%m%d"))
523
+ end
524
+ end
525
+ end
526
+
527
+
528
+ # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
529
+ # @title Wiek czytelnika
530
+ # Zarówno wiek 'od', jak i wiek 'do' są opcjonalne.
531
+ def export_audience_range!(product)
532
+ if product.audience_age_from.present?
533
+ tag(:AudienceRange) do
534
+ comment "Ograniczenie dotyczy wieku czytelnika - zawsze #{Elibri::ONIX::Dict::Release_3_0::AudienceRangeQualifier::READING_AGE}", :kind => :onix_audience_range
535
+ tag(:AudienceRangeQualifier, Elibri::ONIX::Dict::Release_3_0::AudienceRangeQualifier::READING_AGE)
536
+ comment "Wiek od #{product.audience_age_from} lat", :kind => :onix_audience_range
537
+ tag(:AudienceRangePrecision, Elibri::ONIX::Dict::Release_3_0::AudienceRangePrecision::FROM)
538
+ tag(:AudienceRangeValue, product.audience_age_from)
539
+ end
540
+ end
469
541
 
470
- #TODO - tu można również zawrzeć datę, przed którą produkt nie może być importowany do baz sklepów
471
- date, format_code = product.publication_date_with_onix_format_code
472
- if date && format_code
473
- tag(:PublishingDate) do
474
- comment 'Zawsze 01 - data publikacji', :kind => :onix_publishing_status
475
- tag(:PublishingDateRole, Elibri::ONIX::Dict::Release_3_0::PublishingDateRole::PUBLICATION_DATE) #lista 163
476
- comment_dictionary "Format daty", :DateFormat, :indent => 12, :kind => :onix_publishing_status
477
- tag(:DateFormat, format_code) #lista 55
478
- tag(:Date, date)
479
- end
480
- end
542
+ if product.audience_age_to.present?
543
+ tag(:AudienceRange) do
544
+ comment "Ograniczenie dotyczy wieku czytelnika - zawsze #{Elibri::ONIX::Dict::Release_3_0::AudienceRangeQualifier::READING_AGE}", :kind => :onix_audience_range
545
+ tag(:AudienceRangeQualifier, Elibri::ONIX::Dict::Release_3_0::AudienceRangeQualifier::READING_AGE)
546
+ comment "Wiek do #{product.audience_age_to} lat", :kind => :onix_audience_range
547
+ tag(:AudienceRangePrecision, Elibri::ONIX::Dict::Release_3_0::AudienceRangePrecision::TO)
548
+ tag(:AudienceRangeValue, product.audience_age_to)
549
+ end
550
+ end
551
+ end
552
+
553
+
554
+ # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
555
+ # @title Informacje o wydawcy
556
+ # W rekordzie znajduje się oczywiście nazwa wydawnictwa. Wydawca może określić też imprint oraz miasto, w którym została wydana ksiażka.
557
+ # Z imprintem mamy do czynienia wtedy, gdy książki są wydawane pod różnymi markami, pula ISBN jest jednak wspólna.
558
+ # Jeśli wydawnictwo uzupełnia nazwę imprintu, to powinna być ona traktowana jako nazwa wydawnictwa przy prezentacji
559
+ # książki klientowi końcowemu.
560
+ def export_publisher_info!(product)
561
+ if product.imprint
562
+ tag(:Imprint) do
563
+ comment "Nazwa imprintu", :kind => :onix_publisher_info
564
+ tag(:ImprintName, product.imprint.name)
481
565
  end
566
+ end
482
567
 
483
- # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail Publisher PublishingStatus
484
- # @title Terytorialne ograniczenia sprzedaży.
485
- # W tej chwili w systemie eLibri można zastrzec, że sprzedaż książek/ebooków jest ograniczona do terenu Polski,
486
- # albo pozwolić na sprzedaż na całym świecie. Poniżej dwa przykłady, jeden dla wyłączości na terenie Polski, drugi
487
- # dopuszczający sprzedaż na całym świecie. Informacja o ograniczeniu jest zawarta w obręcie <strong>&lt;SalesRights&gt;</strong>
488
- def export_territorial_rights!(product)
489
- tag(:SalesRights) do
490
- comment "Typ restrykcji - sprzedaż tylko w wymienionym kraju, regionie, zawsze '01'", :kind => :onix_territorial_rights
491
- tag(:SalesRightsType, "01")
492
- tag(:Territory) do
493
- if product.sale_restricted_to_poland?
494
- tag(:CountriesIncluded, "PL")
495
- else
496
- tag(:RegionsIncluded, "WORLD")
497
- end
498
- end
568
+ if product.publisher_name
569
+ tag(:Publisher) do
570
+ comment "Wydawca - używamy tylko kodu 01 (główny wydawca)", :kind => :onix_publisher_info
571
+ tag(:PublishingRole, '01') # Publisher, lista 45 #TODO jeszcze może być współwydawca
572
+ tag(:PublisherIdentifier) do
573
+ tag(:PublisherIDType, '01') #prioprietary
574
+ tag(:IDTypeName, 'ElibriPublisherCode')
575
+ tag(:IDValue, product.publisher_id)
499
576
  end
577
+ tag(:PublisherName, product.publisher_name)
500
578
  end
579
+ end
501
580
 
581
+ if product.city_of_publication.present?
582
+ tag(:CityOfPublication, product.city_of_publication)
583
+ end
584
+ end
585
+
586
+
587
+ # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
588
+ # @title Pozostałe atrybuty
589
+ # Dodatkowo każdy produkt może mieć kilka dodatkowych atrybutów: wielkość pliku (w Mb, tylko e-book),
590
+ # czas trwania (tylko audiobook, w minutach), ilość stron, ilość ilustracji.
591
+ #
592
+ # Poniżej przykład dla e-booka (wielkość pliku, ilość stron i ilustracji)
593
+ # @render onix_ebook_extent_example
594
+ #
595
+ # I przykład dla audiobook-a, z czasem trwania nagrania:
596
+ # @render onix_audiobook_extent_example
597
+ def export_extent!(product)
598
+ if product.digital? and product.file_size
599
+ tag(:Extent) do
600
+ comment 'Rozmiar pliku (w MB) - tylko dla produktów cyfrowych (e-book, audiobook)', :kind => :onix_extent
601
+ tag(:ExtentType, Elibri::ONIX::Dict::Release_3_0::ExtentType::FILE_SIZE)
602
+ tag(:ExtentValue, product.file_size)
603
+ comment 'W MB', :kind => :onix_extent
604
+ tag(:ExtentUnit, Elibri::ONIX::Dict::Release_3_0::ExtentUnit::MEGABYTES)
605
+ end
606
+ end
502
607
 
503
- # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
504
- # @title Ograniczenia sprzedaży
505
- # eLibri umożliwia przechowywanie informacji o ograniczaniach dotyczących sprzedaży produktu.
506
- # Obecnie obsługuje tylko 1 typ ograniczenia: wyłączność na produkt dla określonego detalisty.
507
- # Opcjonalnie może się też pojawić data wygaśnięcia ograniczenia - w innym przypadku oznacza to, że produkt został przeznaczony tylko
508
- # dla jednej, określonej sieci.
509
- # W przypadku, gdy jest podana data wyłączności na sprzedaż produktu, należy ją traktować jako faktyczną datę premiery.
510
- def export_sale_restrictions!(product)
511
- if product.sale_restricted?
512
- tag(:SalesRestriction) do
513
- #lista 71 - For sale only through designated retailer, though not under retailer's own brand/imprint.
514
- comment "Typ restrykcji - używamy tylko #{Elibri::ONIX::Dict::Release_3_0::SalesRestrictionType::RETAILER_EXCLUSIVE} (sprzedaż tylko poprzez wybranego detalistę)", :kind => :onix_sale_restrictions
515
- tag(:SalesRestrictionType, Elibri::ONIX::Dict::Release_3_0::SalesRestrictionType::RETAILER_EXCLUSIVE)
516
- tag(:SalesOutlet) do
517
- tag(:SalesOutletName, product.sale_restricted_for)
518
- end
519
- comment "Ograniczenie wygasa #{product.sale_restricted_to.strftime("%d.%m.%Y")}", :kind => :onix_sale_restrictions
520
- tag(:EndDate, product.sale_restricted_to.strftime("%Y%m%d"))
521
- end
522
- end
608
+ if product.kind_of_audio? and product.duration
609
+ tag(:Extent) do
610
+ comment 'Czas trwania (w minutach) - tylko dla produktów typu audio', :kind => :onix_extent
611
+ tag(:ExtentType, Elibri::ONIX::Dict::Release_3_0::ExtentType::DURATION)
612
+ tag(:ExtentValue, product.duration)
613
+ comment 'W minutach', :kind => :onix_extent
614
+ tag(:ExtentUnit, Elibri::ONIX::Dict::Release_3_0::ExtentUnit::MINUTES)
523
615
  end
616
+ end
524
617
 
618
+ if (product.kind_of_book? or product.kind_of_ebook?) && product.number_of_pages #number_of_pages to int
619
+ tag(:Extent) do
620
+ comment 'Liczba stron - tylko dla produktów typu książka', :kind => :onix_extent
621
+ tag(:ExtentType, Elibri::ONIX::Dict::Release_3_0::ExtentType::PAGE_COUNT)
622
+ tag(:ExtentValue, product.number_of_pages)
623
+ tag(:ExtentUnit, Elibri::ONIX::Dict::Release_3_0::ExtentUnit::PAGES)
624
+ end
625
+ end
525
626
 
526
- # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
527
- # @title Wiek czytelnika
528
- # Zarówno wiek 'od', jak i wiek 'do' są opcjonalne.
529
- def export_audience_range!(product)
530
- if product.audience_age_from.present?
531
- tag(:AudienceRange) do
532
- comment "Ograniczenie dotyczy wieku czytelnika - zawsze #{Elibri::ONIX::Dict::Release_3_0::AudienceRangeQualifier::READING_AGE}", :kind => :onix_audience_range
533
- tag(:AudienceRangeQualifier, Elibri::ONIX::Dict::Release_3_0::AudienceRangeQualifier::READING_AGE)
534
- comment "Wiek od #{product.audience_age_from} lat", :kind => :onix_audience_range
535
- tag(:AudienceRangePrecision, Elibri::ONIX::Dict::Release_3_0::AudienceRangePrecision::FROM)
536
- tag(:AudienceRangeValue, product.audience_age_from)
537
- end
538
- end
627
+ if (product.kind_of_book? or product.kind_of_ebook?) and product.number_of_illustrations
628
+ comment 'Liczba ilustracji - tylko dla produktów typu książka', :kind => :onix_extent
629
+ tag(:NumberOfIllustrations, product.number_of_illustrations)
630
+ end
631
+ end
539
632
 
540
- if product.audience_age_to.present?
541
- tag(:AudienceRange) do
542
- comment "Ograniczenie dotyczy wieku czytelnika - zawsze #{Elibri::ONIX::Dict::Release_3_0::AudienceRangeQualifier::READING_AGE}", :kind => :onix_audience_range
543
- tag(:AudienceRangeQualifier, Elibri::ONIX::Dict::Release_3_0::AudienceRangeQualifier::READING_AGE)
544
- comment "Wiek do #{product.audience_age_to} lat", :kind => :onix_audience_range
545
- tag(:AudienceRangePrecision, Elibri::ONIX::Dict::Release_3_0::AudienceRangePrecision::TO)
546
- tag(:AudienceRangeValue, product.audience_age_to)
547
- end
548
- end
549
- end
550
633
 
634
+ # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
635
+ # @title Kategorie
636
+ # eLibri stosuje wewnętrzną hierarchę kategorii, ich lista dostępna jest
637
+ # = link_to "tutaj", doc_api_path("categories")
638
+ def export_subjects!(product)
639
+ if product.elibri_product_categories.present? or product.publisher_product_categories.present?
640
+ comment 'Stosujemy wewnętrzną kategoryzację.'
641
+ end
551
642
 
552
- # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
553
- # @title Informacje o wydawcy
554
- # W rekordzie znajduje się oczywiście nazwa wydawnictwa. Wydawca może określić też imprint oraz miasto, w którym została wydana ksiażka.
555
- # Z imprintem mamy do czynienia wtedy, gdy książki są wydawane pod różnymi markami, pula ISBN jest jednak wspólna.
556
- # Jeśli wydawnictwo uzupełnia nazwę imprintu, to powinna być ona traktowana jako nazwa wydawnictwa przy prezentacji
557
- # książki klientowi końcowemu.
558
- def export_publisher_info!(product)
559
- if product.imprint
560
- tag(:Imprint) do
561
- comment "Nazwa imprintu", :kind => :onix_publisher_info
562
- tag(:ImprintName, product.imprint.name)
563
- end
564
- end
643
+ # Kategorie wg. eLibri
644
+ product.elibri_product_categories.each_with_index do |product_category, i|
645
+ tag(:Subject) do
646
+ tag(:MainSubject) if i.zero?
647
+ tag(:SubjectSchemeIdentifier, Elibri::ONIX::Dict::Release_3_0::SubjectSchemeIdentifier::PROPRIETARY)
648
+ tag(:SubjectSchemeName, 'elibri.com.pl')
649
+ tag(:SubjectSchemeVersion, '1.0')
650
+ tag(:SubjectCode, product_category.id)
651
+ tag(:SubjectHeadingText, product_category.full_node_path_name)
652
+ end
653
+ end
565
654
 
566
- if product.publisher_name
567
- tag(:Publisher) do
568
- comment "Wydawca - używamy tylko kodu 01 (główny wydawca)", :kind => :onix_publisher_info
569
- tag(:PublishingRole, '01') # Publisher, lista 45 #TODO jeszcze może być współwydawca
570
- tag(:PublisherIdentifier) do
571
- tag(:PublisherIDType, '01') #prioprietary
572
- tag(:IDTypeName, 'ElibriPublisherCode')
573
- tag(:IDValue, product.publisher_id)
574
- end
575
- tag(:PublisherName, product.publisher_name)
576
- end
655
+ # Kategorie wg. wydawnictwa
656
+ #product.publisher_product_categories.each do |product_category|
657
+ # tag(:Subject) do
658
+ # tag(:SubjectSchemeIdentifier, Elibri::ONIX::Dict::Release_3_0::SubjectSchemeIdentifier::PROPRIETARY)
659
+ # tag(:SubjectSchemeName, product.publisher_name)
660
+ # tag(:SubjectHeadingText, product_category.name)
661
+ # end
662
+ #end
663
+ end
664
+
665
+
666
+ # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
667
+ # @title Autorzy, redaktorzy ...
668
+ # Każdy produkt może mieć wymienionych autorów, może być informacja, że jest to praca zbiorowa, produkt może nie mieć też żadnego autora (np. mapa)
669
+ #
670
+ #
671
+ # Każdy twórca ma przypisaną jedną z wielu ról (&lt;ContributorRole&gt;). W przypadku tłumacza dodawana jest informacja, z jakiego języka
672
+ # nastąpiło tłumaczenie (&lt;FromLanguage&gt;)
673
+ #
674
+ #
675
+ # W przypadku właściwego uzupełnienia danych w eLibri, system potrafi podzielić fragmenty personaliów
676
+ # autora i wyeksportować je w oddzielnych tagach ONIX. Rozróżniane są następujące fragmenty: tytuł naukowy (&lt;TitlesBeforeNames&gt;),
677
+ # imię (&lt;NamesBeforeKey&gt;), prefix nazwiska (von, van - &lt;PrefixToKey&gt;), nazwisko (&lt;KeyNames&gt;),
678
+ # postfix nazwiska (najczęściej określenie zakonu, np. OP - &lt;NamesAfterKey&gt;).
679
+ # Zawsze jest jednak exportowane pełne brzemienie imienia i nazwiska (&lt;PersonName&gt;)
680
+ #
681
+ #
682
+ # Zdarzają się również przypadki, gdzie wyżej podany podział nie jest albo znany, albo możliwy (np. św. Tomasz z Akwinu), wtedy
683
+ # exportowany jest tylko tag &lt;PersonName&gt;
684
+ #
685
+ # Jeśli wydawnictwo uzupełniło biogram autora, to jest on dostępny w tagu &lt;BiographicalNote&gt;
686
+ #
687
+ # @render onix_contributors_example
688
+ #
689
+ # W przypadku pracy zbiorowej rekord wygląda następująco:
690
+ #
691
+ # @render onix_collective_work_example
692
+ #
693
+ # Jeśli produkt nie ma żadnego autora, użyty zostaje tag &lt;NoContributor&gt;
694
+ #
695
+ # @render onix_no_contributors_example
696
+ #
697
+ #
698
+ def export_contributors!(product)
699
+ if product.authorship_kind.user_given?
700
+ comment 'Gdy wyszczególniono autorów', :kind => :onix_contributors if product.contributors.present?
701
+ product.contributors.each_with_index do |contributor, idx|
702
+ tag(:Contributor, :sourcename => "contributorid:#{contributor.id}", :datestamp => contributor.updated_at.to_s(:onix)) do
703
+ tag(:SequenceNumber, idx + 1)
704
+ comment_dictionary 'Rola autora', :ContributorRole, :indent => 10, :kind => :onix_contributors
705
+ tag(:ContributorRole, contributor.role_onix_code) #lista 17
706
+ comment 'Tylko w przypadku tłumaczy:', :kind => :onix_contributors
707
+ tag(:FromLanguage, contributor.language_onix_code) if contributor.language_onix_code
708
+ tag(:PersonName, contributor.generated_full_name) #zawsze jest TODO - dodać takie pole do bazy danych
709
+
710
+ tag(:TitlesBeforeNames, contributor.title) if contributor.title.present? #tytuł
711
+ tag(:NamesBeforeKey, contributor.name) if contributor.name.present? #imię
712
+ tag(:PrefixToKey, contributor.last_name_prefix) if contributor.last_name_prefix.present? #van, von
713
+ tag(:KeyNames, contributor.last_name) if contributor.last_name.present?
714
+ tag(:NamesAfterKey, contributor.last_name_postfix) if contributor.last_name_postfix.present?
715
+ tag(:BiographicalNote, contributor.biography.text) if contributor.biography
577
716
  end
717
+ end
718
+ end
578
719
 
579
- if product.city_of_publication.present?
580
- tag(:CityOfPublication, product.city_of_publication)
581
- end
720
+ if product.authorship_kind.collective?
721
+ comment 'Gdy jest to praca zbiorowa', :kind => :onix_contributors
722
+ tag(:Contributor) do
723
+ comment "Autor - #{Elibri::ONIX::Dict::Release_3_0::ContributorRole::AUTHOR}", :kind => :onix_contributors
724
+ tag(:ContributorRole, Elibri::ONIX::Dict::Release_3_0::ContributorRole::AUTHOR)
725
+ comment "Różne osoby - #{Elibri::ONIX::Dict::Release_3_0::UnnamedPersons::VARIOUS_AUTHORS}", :kind => :onix_contributors
726
+ tag(:UnnamedPersons, Elibri::ONIX::Dict::Release_3_0::UnnamedPersons::VARIOUS_AUTHORS)
582
727
  end
728
+ end
583
729
 
730
+ if product.authorship_kind.no_contributor?
731
+ comment 'Gdy brak autorów', :kind => :onix_contributors
732
+ tag(:NoContributor)
733
+ end
734
+ end
735
+
736
+ # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm
737
+ # @title Tytuły
738
+ # W dokumencie XML mogą pojawić się 3 typy tytułu: pełen tytuł produktu, tytuł w języku oryginału (jeśli jest tłumaczeniem)
739
+ # oraz roboczy tytuł nadany przez wydawcę.
740
+ # @render onix_titles_example
741
+ #
742
+ # Tytuł może być też kaskadowy. Dobrym przykładem jest na przykład Thorgal, komiks, który ma wiele tomów, każdy tom ma swój numer, jak i tytuł.
743
+ # W kategoriach ONIX-a Thorgal jest kolekcją. Od serii odróżnia go to, że jest częścią tytułu. Innym dobrym przykładem jest książka "Gra o Tron",
744
+ # która należy do kolekcji "Pieśń Lodu i Ognia" - ponieważ jest to częścią tytułu.
745
+ # @render onix_title_with_collection_example
746
+ #
747
+ #
748
+ def export_titles!(product)
749
+ if product.title_parts.present? or product.original_title.present? or product.trade_title.present?
750
+ #comment_dictionary 'Rozróżniane typy tytułów', :TitleType, :indent => 10, :kind => :onix_titles
751
+ end
584
752
 
585
- # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
586
- # @title Pozostałe atrybuty
587
- # Dodatkowo każdy produkt może mieć kilka dodatkowych atrybutów: wielkość pliku (w Mb, tylko e-book),
588
- # czas trwania (tylko audiobook, w minutach), ilość stron, ilość ilustracji.
589
- #
590
- # Poniżej przykład dla e-booka (wielkość pliku, ilość stron i ilustracji)
591
- # @render onix_ebook_extent_example
592
- #
593
- # I przykład dla audiobook-a, z czasem trwania nagrania:
594
- # @render onix_audiobook_extent_example
595
- def export_extent!(product)
596
- if product.digital? and product.file_size
597
- tag(:Extent) do
598
- comment 'Rozmiar pliku (w MB) - tylko dla produktów cyfrowych (e-book, audiobook)', :kind => :onix_extent
599
- tag(:ExtentType, Elibri::ONIX::Dict::Release_3_0::ExtentType::FILE_SIZE)
600
- tag(:ExtentValue, product.file_size)
601
- comment 'W MB', :kind => :onix_extent
602
- tag(:ExtentUnit, Elibri::ONIX::Dict::Release_3_0::ExtentUnit::MEGABYTES)
603
- end
604
- end
605
-
606
- if product.kind_of_audio? and product.duration
607
- tag(:Extent) do
608
- comment 'Czas trwania (w minutach) - tylko dla produktów typu audio', :kind => :onix_extent
609
- tag(:ExtentType, Elibri::ONIX::Dict::Release_3_0::ExtentType::DURATION)
610
- tag(:ExtentValue, product.duration)
611
- comment 'W minutach', :kind => :onix_extent
612
- tag(:ExtentUnit, Elibri::ONIX::Dict::Release_3_0::ExtentUnit::MINUTES)
753
+ if product.title_parts.present?
754
+ tag(:TitleDetail) do
755
+ comment "Pełen tytuł produktu - #{Elibri::ONIX::Dict::Release_3_0::TitleType::DISTINCTIVE_TITLE}", :kind => :onix_titles
756
+ tag(:TitleType, Elibri::ONIX::Dict::Release_3_0::TitleType::DISTINCTIVE_TITLE)
757
+ product.title_parts.each do |title_part|
758
+ tag(:TitleElement) do
759
+ if title_part.level == Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT
760
+ comment "Tytuł na poziomie produktu - #{Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT}", :kind => :onix_titles
761
+ elsif title_part.level == Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::COLLECTION
762
+ comment "Tytuł na poziomie kolekcji - #{Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::COLLECTION}", :kind => :onix_titles
763
+ end
764
+ tag(:TitleElementLevel, title_part.level) #odnosi się do tego produktu tylko
765
+ tag(:PartNumber, title_part.part) if title_part.part.present?
766
+ tag(:TitleText, title_part.title) if title_part.title.present?
767
+ tag(:Subtitle, title_part.subtitle) if title_part.subtitle.present?
613
768
  end
614
769
  end
615
-
616
- if (product.kind_of_book? or product.kind_of_ebook?) && product.number_of_pages #number_of_pages to int
617
- tag(:Extent) do
618
- comment 'Liczba stron - tylko dla produktów typu książka', :kind => :onix_extent
619
- tag(:ExtentType, Elibri::ONIX::Dict::Release_3_0::ExtentType::PAGE_COUNT)
620
- tag(:ExtentValue, product.number_of_pages)
621
- tag(:ExtentUnit, Elibri::ONIX::Dict::Release_3_0::ExtentUnit::PAGES)
622
- end
770
+ end
771
+ end
772
+ if product.original_title.present?
773
+ tag(:TitleDetail) do
774
+ comment "Tytuł w języku oryginału - #{Elibri::ONIX::Dict::Release_3_0::TitleType::DISTINCTIVE_TITLE}", :kind => :onix_titles
775
+ tag(:TitleType, Elibri::ONIX::Dict::Release_3_0::TitleType::ORIGINAL_TITLE)
776
+ tag(:TitleElement) do
777
+ comment "Tytuł na poziomie produktu - #{Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT}", :kind => :onix_titles
778
+ tag(:TitleElementLevel, Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT)
779
+ tag(:TitleText, product.original_title)
623
780
  end
624
-
625
- if (product.kind_of_book? or product.kind_of_ebook?) and product.number_of_illustrations
626
- comment 'Liczba ilustracji - tylko dla produktów typu książka', :kind => :onix_extent
627
- tag(:NumberOfIllustrations, product.number_of_illustrations)
781
+ end
782
+ end
783
+ if product.trade_title.present?
784
+ tag(:TitleDetail) do
785
+ comment "Tytuł handlowy używany przez wydawnictwo - #{Elibri::ONIX::Dict::Release_3_0::TitleType::DISTRIBUTORS_TITLE}", :kind => :onix_titles
786
+ tag(:TitleType, Elibri::ONIX::Dict::Release_3_0::TitleType::DISTRIBUTORS_TITLE) #tytuł produktu
787
+ tag(:TitleElement) do
788
+ comment "Tytuł na poziomie produktu - #{Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT}", :kind => :onix_titles
789
+ tag(:TitleElementLevel, Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT)
790
+ tag(:TitleText, product.trade_title)
628
791
  end
629
792
  end
793
+ end
794
+ end
630
795
 
631
- # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
632
- # @title Kategorie
633
- # eLibri stosuje wewnętrzną hierarchę kategorii, ich lista dostępna jest
634
- # = link_to "tutaj", doc_api_path("categories")
635
- def export_subjects!(product)
636
- if product.elibri_product_categories.present? or product.publisher_product_categories.present?
637
- comment 'Stosujemy wewnętrzną kategoryzację.'
638
- end
639
796
 
640
- # Kategorie wg. eLibri
641
- product.elibri_product_categories.each_with_index do |product_category, i|
642
- tag(:Subject) do
643
- tag(:MainSubject) if i.zero?
644
- tag(:SubjectSchemeIdentifier, Elibri::ONIX::Dict::Release_3_0::SubjectSchemeIdentifier::PROPRIETARY)
645
- tag(:SubjectSchemeName, 'elibri.com.pl')
646
- tag(:SubjectSchemeVersion, '1.0')
647
- tag(:SubjectCode, product_category.id)
648
- tag(:SubjectHeadingText, product_category.full_node_path_name)
649
- end
650
- end
651
-
652
- # Kategorie wg. wydawnictwa
653
- #product.publisher_product_categories.each do |product_category|
654
- # tag(:Subject) do
655
- # tag(:SubjectSchemeIdentifier, Elibri::ONIX::Dict::Release_3_0::SubjectSchemeIdentifier::PROPRIETARY)
656
- # tag(:SubjectSchemeName, product.publisher_name)
657
- # tag(:SubjectHeadingText, product_category.name)
658
- # end
659
- #end
797
+ # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
798
+ # @title Opis wydania
799
+ def export_edition!(product)
800
+ if product.edition_statement.present?
801
+ comment 'Opis wydania', :kind => :onix_edition
802
+ tag(:EditionStatement, product.edition_statement)
803
+ end
804
+ end
805
+
806
+
807
+ # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
808
+ # @title Języki
809
+ # Języki, w których dostępny jest produkt.
810
+ def export_languages!(product)
811
+ comment_dictionary 'Rola języka', :LanguageRole, :indent => 10, :kind => :onix_languages if product.languages.present?
812
+ product.languages.each do |language|
813
+ tag(:Language) do
814
+ tag(:LanguageRole, language.role_onix_code) #lista 22
815
+ tag(:LanguageCode, language.language_onix_code) #lista 74
660
816
  end
661
-
662
-
663
- # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
664
- # @title Autorzy, redaktorzy ...
665
- # Każdy produkt może mieć wymienionych autorów, może być informacja, że jest to praca zbiorowa, produkt może nie mieć też żadnego autora (np. mapa)
666
- #
667
- #
668
- # Każdy twórca ma przypisaną jedną z wielu ról (&lt;ContributorRole&gt;). W przypadku tłumacza dodawana jest informacja, z jakiego języka
669
- # nastąpiło tłumaczenie (&lt;FromLanguage&gt;)
670
- #
671
- #
672
- # W przypadku właściwego uzupełnienia danych w eLibri, system potrafi podzielić fragmenty personaliów
673
- # autora i wyeksportować je w oddzielnych tagach ONIX. Rozróżniane następujące fragmenty: tytuł naukowy (&lt;TitlesBeforeNames&gt;),
674
- # imię (&lt;NamesBeforeKey&gt;), prefix nazwiska (von, van - &lt;PrefixToKey&gt;), nazwisko (&lt;KeyNames&gt;),
675
- # postfix nazwiska (najczęściej określenie zakonu, np. OP - &lt;NamesAfterKey&gt;).
676
- # Zawsze jest jednak exportowane pełne brzemienie imienia i nazwiska (&lt;PersonName&gt;)
677
- #
678
- #
679
- # Zdarzają się również przypadki, gdzie wyżej podany podział nie jest albo znany, albo możliwy (np. św. Tomasz z Akwinu), wtedy
680
- # exportowany jest tylko tag &lt;PersonName&gt;
681
- #
682
- # Jeśli wydawnictwo uzupełniło biogram autora, to jest on dostępny w tagu &lt;BiographicalNote&gt;
683
- #
684
- # @render onix_contributors_example
685
- #
686
- # W przypadku pracy zbiorowej rekord wygląda następująco:
687
- #
688
- # @render onix_collective_work_example
689
- #
690
- # Jeśli produkt nie ma żadnego autora, użyty zostaje tag &lt;NoContributor&gt;
691
- #
692
- # @render onix_no_contributors_example
693
- #
694
- #
695
- def export_contributors!(product)
696
- if product.authorship_kind.user_given?
697
- comment 'Gdy wyszczególniono autorów', :kind => :onix_contributors if product.contributors.present?
698
- product.contributors.each_with_index do |contributor, idx|
699
- tag(:Contributor, :sourcename => "contributorid:#{contributor.id}", :datestamp => contributor.updated_at.to_s(:onix)) do
700
- tag(:SequenceNumber, idx + 1)
701
- comment_dictionary 'Rola autora', :ContributorRole, :indent => 10, :kind => :onix_contributors
702
- tag(:ContributorRole, contributor.role_onix_code) #lista 17
703
- comment 'Tylko w przypadku tłumaczy:', :kind => :onix_contributors
704
- tag(:FromLanguage, contributor.language_onix_code) if contributor.language_onix_code
705
- tag(:PersonName, contributor.generated_full_name) #zawsze jest TODO - dodać takie pole do bazy danych
706
-
707
- tag(:TitlesBeforeNames, contributor.title) if contributor.title.present? #tytuł
708
- tag(:NamesBeforeKey, contributor.name) if contributor.name.present? #imię
709
- tag(:PrefixToKey, contributor.last_name_prefix) if contributor.last_name_prefix.present? #van, von
710
- tag(:KeyNames, contributor.last_name) if contributor.last_name.present?
711
- tag(:NamesAfterKey, contributor.last_name_postfix) if contributor.last_name_postfix.present?
712
- tag(:BiographicalNote, contributor.biography.text) if contributor.biography
713
- end
714
- end
817
+ end
818
+ end
819
+
820
+
821
+ # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
822
+ # @title Teksty
823
+ # Wydawca może wprowadzić do eLibri różne informacje tekstowe - opis produktu, spis treści, recenzję (jeśli ma prawa ją udostępnić), jak i fragment książki.
824
+ # Biogramy autorów udostępniane wraz z informacjami o
825
+ # = link_to "autorach", doc_api_path("onix_contributors")
826
+ def export_texts!(product)
827
+ comment_dictionary 'Typy tekstów', :OtherTextType, :indent => 10, :kind => :onix_texts if product.other_texts.present?
828
+ product.other_texts.each do |other_text|
829
+ #jeśli jest pusty tekst, nie nadaje się do umieszczania w ONIX albo tekst dotyczy autora (type_onix_code.blank?) -> nie exportuj
830
+ next if other_text.text.blank? || other_text.type_onix_code.blank? || !other_text.exportable?
831
+
832
+ tag(:TextContent, :sourcename => "textid:#{other_text.id}", :datestamp => other_text.updated_at.to_s(:onix)) do
833
+ tag(:TextType, other_text.type_onix_code) #lista 153
834
+ comment "Zawsze #{Elibri::ONIX::Dict::Release_3_0::ContentAudience::UNRESTRICTED} - Unrestricted", :kind => :onix_texts
835
+ tag(:ContentAudience, Elibri::ONIX::Dict::Release_3_0::ContentAudience::UNRESTRICTED)
836
+
837
+ if other_text.is_a_review? && other_text.resource_link.present?
838
+ text_source = {:sourcename => other_text.resource_link}
839
+ else
840
+ text_source = {}
715
841
  end
716
842
 
717
- if product.authorship_kind.collective?
718
- comment 'Gdy jest to praca zbiorowa', :kind => :onix_contributors
719
- tag(:Contributor) do
720
- comment "Autor - #{Elibri::ONIX::Dict::Release_3_0::ContributorRole::AUTHOR}", :kind => :onix_contributors
721
- tag(:ContributorRole, Elibri::ONIX::Dict::Release_3_0::ContributorRole::AUTHOR)
722
- comment "Różne osoby - #{Elibri::ONIX::Dict::Release_3_0::UnnamedPersons::VARIOUS_AUTHORS}", :kind => :onix_contributors
723
- tag(:UnnamedPersons, Elibri::ONIX::Dict::Release_3_0::UnnamedPersons::VARIOUS_AUTHORS)
724
- end
843
+ tag(:Text, text_source) do |builder|
844
+ builder.cdata!(other_text.text)
725
845
  end
726
846
 
727
- if product.authorship_kind.no_contributor?
728
- comment 'Gdy brak autorów', :kind => :onix_contributors
729
- tag(:NoContributor)
730
- end
847
+ tag(:TextAuthor, other_text.text_author) if other_text.text_author.present?
848
+ tag(:SourceTitle, other_text.source_title) if other_text.source_title.present?
731
849
  end
732
-
733
- # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm
734
- # @title Tytuły
735
- # W dokumencie XML mogą pojawić się 3 typy tytułu: pełen tytuł produktu, tytuł w języku oryginału (jeśli jest tłumaczeniem)
736
- # oraz roboczy tytuł nadany przez wydawcę.
737
- # @render onix_titles_example
738
- #
739
- # Tytuł może być też kaskadowy. Dobrym przykładem jest na przykład Thorgal, komiks, który ma wiele tomów, każdy tom ma swój numer, jak i tytuł.
740
- # W kategoriach ONIX-a Thorgal jest kolekcją. Od serii odróżnia go to, że jest częścią tytułu. Innym dobrym przykładem jest książka "Gra o Tron",
741
- # która należy do kolekcji "Pieśń Lodu i Ognia" - ponieważ jest to częścią tytułu.
742
- # @render onix_title_with_collection_example
743
- #
744
- #
745
- def export_titles!(product)
746
- if product.title_parts.present? or product.original_title.present? or product.trade_title.present?
747
- #comment_dictionary 'Rozróżniane typy tytułów', :TitleType, :indent => 10, :kind => :onix_titles
748
- end
749
-
750
- if product.title_parts.present?
751
- tag(:TitleDetail) do
752
- comment "Pełen tytuł produktu - #{Elibri::ONIX::Dict::Release_3_0::TitleType::DISTINCTIVE_TITLE}", :kind => :onix_titles
753
- tag(:TitleType, Elibri::ONIX::Dict::Release_3_0::TitleType::DISTINCTIVE_TITLE)
754
- product.title_parts.each do |title_part|
755
- tag(:TitleElement) do
756
- if title_part.level == Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT
757
- comment "Tytuł na poziomie produktu - #{Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT}", :kind => :onix_titles
758
- elsif title_part.level == Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::COLLECTION
759
- comment "Tytuł na poziomie kolekcji - #{Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::COLLECTION}", :kind => :onix_titles
760
- end
761
- tag(:TitleElementLevel, title_part.level) #odnosi się do tego produktu tylko
762
- tag(:PartNumber, title_part.part) if title_part.part.present?
763
- tag(:TitleText, title_part.title) if title_part.title.present?
764
- tag(:Subtitle, title_part.subtitle) if title_part.subtitle.present?
765
- end
850
+ end
851
+ end
852
+
853
+
854
+ # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
855
+ # @title Załączniki
856
+ # Wydawca może załączyć do każdego produktu dowolną liczbę plików - a przynajmniej jeden, okładkę. Proszę za każdym razem
857
+ # tworzyć kopię pliku na swoim serwerze, hotlinking jest niedozwolony.
858
+ def export_supporting_resources!(product)
859
+ product.attachments.each do |attachment|
860
+ if attachment.onix_resource_mode #jeśli klient coś dzikiego wgrał, to ignoruj to
861
+ tag(:SupportingResource, :sourcename => "resourceid:#{attachment.id}", :datestamp => attachment.updated_at.to_s(:onix)) do
862
+ comment_dictionary 'Typ załącznika', :ResourceContentType, :indent => 12, :kind => :onix_supporting_resources
863
+ tag(:ResourceContentType, attachment.attachment_type_code) #lista 158
864
+ comment 'Zawsze 00 - Unrestricted', :kind => :onix_supporting_resources
865
+ tag(:ContentAudience, Elibri::ONIX::Dict::Release_3_0::ContentAudience::UNRESTRICTED)
866
+ comment_dictionary 'Rodzaj załącznika', :ResourceMode, :indent => 12, :kind => :onix_supporting_resources
867
+ tag(:ResourceMode, attachment.onix_resource_mode) #lista 159
868
+ tag(:ResourceVersion) do
869
+ comment 'Zawsze 02 - Downloadable file', :kind => :onix_supporting_resources
870
+ tag(:ResourceForm, Elibri::ONIX::Dict::Release_3_0::ResourceForm::DOWNLOADABLE_FILE)
871
+ url = attachment.file.url
872
+ if url.index("http://") #w sklepie zwraca mi całego linka, wygodniej mi jest to tutaj wychwycić
873
+ tag(:ResourceLink, URI.escape(url))
874
+ else
875
+ tag(:ResourceLink, URI.escape('http://' + HOST_NAME + url))
766
876
  end
767
- end
877
+ end
768
878
  end
769
- if product.original_title.present?
879
+ end
880
+ end
881
+ end
882
+
883
+
884
+ # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm
885
+ # @title Serie wydawnicze
886
+ # Serie wydawnicze są opisywane w podobny sposób co tytuł, zawarte są jednak w tagu <strong>&lt;Collection&gt;</strong>
887
+ # Struktura jest dosyć zawiła, ale wszystkie wartości są sztywne, więc nie powinno być problemu z odczytaniem informacji.
888
+ # Oprócz nazwy serii może zostać również podany numer wewnątrz serii, jeśli seria jest numerowana.
889
+ # Książka może należeć do kilku serii, wtedy tag <strong>&lt;Collection&gt;</strong> występuje kilkukrotnie.
890
+ def export_series_memberships!(product)
891
+ if product.series_membership_kind.user_given?
892
+ product.series_memberships.each_with_index do |series_membership, idx|
893
+ tag(:Collection) do
894
+ comment "Używamy tylko #{Elibri::ONIX::Dict::Release_3_0::CollectionType::PUBLISHER_COLLECTION} - seria wydawnictwa", :kind => :onix_series_memberships
895
+ tag(:CollectionType, Elibri::ONIX::Dict::Release_3_0::CollectionType::PUBLISHER_COLLECTION) #lista 148
896
+ comment "Teraz następuje podobna struktura, jak w przypadku tytułu", :kind => :onix_series_memberships
770
897
  tag(:TitleDetail) do
771
- comment "Tytuł w języku oryginału - #{Elibri::ONIX::Dict::Release_3_0::TitleType::DISTINCTIVE_TITLE}", :kind => :onix_titles
772
- tag(:TitleType, Elibri::ONIX::Dict::Release_3_0::TitleType::ORIGINAL_TITLE)
898
+ comment "Używamy tylko #{Elibri::ONIX::Dict::Release_3_0::TitleType::DISTINCTIVE_TITLE}", :kind => :onix_series_memberships
899
+ tag(:TitleType, Elibri::ONIX::Dict::Release_3_0::TitleType::DISTINCTIVE_TITLE)
773
900
  tag(:TitleElement) do
774
- comment "Tytuł na poziomie produktu - #{Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT}", :kind => :onix_titles
775
- tag(:TitleElementLevel, Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT)
776
- tag(:TitleText, product.original_title)
777
- end
778
- end
779
- end
780
- if product.trade_title.present?
781
- tag(:TitleDetail) do
782
- comment "Tytuł handlowy używany przez wydawnictwo - #{Elibri::ONIX::Dict::Release_3_0::TitleType::DISTRIBUTORS_TITLE}", :kind => :onix_titles
783
- tag(:TitleType, Elibri::ONIX::Dict::Release_3_0::TitleType::DISTRIBUTORS_TITLE) #tytuł produktu
784
- tag(:TitleElement) do
785
- comment "Tytuł na poziomie produktu - #{Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT}", :kind => :onix_titles
786
- tag(:TitleElementLevel, Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::PRODUCT)
787
- tag(:TitleText, product.trade_title)
901
+ comment "Używamy tylko #{Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::COLLECTION}", :kind => :onix_series_memberships
902
+ tag(:TitleElementLevel, Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::COLLECTION)
903
+ tag(:PartNumber, series_membership.number_within_series) if series_membership.number_within_series.present?
904
+ tag(:TitleText, series_membership.series_name)
788
905
  end
789
906
  end
790
907
  end
791
- end
792
-
793
-
794
- # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
795
- # @title Opis wydania
796
- def export_edition!(product)
797
- if product.edition_statement.present?
798
- comment 'Opis wydania', :kind => :onix_edition
799
- tag(:EditionStatement, product.edition_statement)
800
- end
801
- end
802
-
803
-
804
- # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm TitleDetail
805
- # @title Języki
806
- # Języki, w których dostępny jest produkt.
807
- def export_languages!(product)
808
- comment_dictionary 'Rola języka', :LanguageRole, :indent => 10, :kind => :onix_languages if product.languages.present?
809
- product.languages.each do |language|
810
- tag(:Language) do
811
- tag(:LanguageRole, language.role_onix_code) #lista 22
812
- tag(:LanguageCode, language.language_onix_code) #lista 74
813
- end
814
- end
815
- end
816
-
817
-
818
- # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
819
- # @title Teksty
820
- # Wydawca może wprowadzić do eLibri różne informacje tekstowe - opis produktu, spis treści, recenzję (jeśli ma prawa ją udostępnić), jak i fragment książki.
821
- # Biogramy autorów są udostępniane wraz z informacjami o
822
- # = link_to "autorach", doc_api_path("onix_contributors")
823
- def export_texts!(product)
824
- comment_dictionary 'Typy tekstów', :OtherTextType, :indent => 10, :kind => :onix_texts if product.other_texts.present?
825
- product.other_texts.each do |other_text|
826
- #jeśli jest pusty tekst, nie nadaje się do umieszczania w ONIX albo tekst dotyczy autora (type_onix_code.blank?) -> nie exportuj
827
- next if other_text.text.blank? || other_text.type_onix_code.blank? || !other_text.exportable?
828
-
829
- tag(:TextContent, :sourcename => "textid:#{other_text.id}", :datestamp => other_text.updated_at.to_s(:onix)) do
830
- tag(:TextType, other_text.type_onix_code) #lista 153
831
- comment "Zawsze #{Elibri::ONIX::Dict::Release_3_0::ContentAudience::UNRESTRICTED} - Unrestricted", :kind => :onix_texts
832
- tag(:ContentAudience, Elibri::ONIX::Dict::Release_3_0::ContentAudience::UNRESTRICTED)
833
-
834
- if other_text.is_a_review? && other_text.resource_link.present?
835
- text_source = {:sourcename => other_text.resource_link}
836
- else
837
- text_source = {}
838
- end
839
-
840
- tag(:Text, text_source) do |builder|
841
- builder.cdata!(other_text.text)
842
- end
908
+ end
909
+ end
910
+ end
843
911
 
844
- tag(:TextAuthor, other_text.text_author) if other_text.text_author.present?
845
- tag(:SourceTitle, other_text.source_title) if other_text.source_title.present?
846
- end
847
- end
848
- end
849
912
 
913
+ # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
914
+ # @title Powiązane produkty
915
+ def export_related_products!(product)
916
+ tag(:RelatedMaterial) do
850
917
 
851
- # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
852
- # @title Załączniki
853
- # Wydawca może załączyć do każdego produktu dowolną liczbę plików - a przynajmniej jeden, okładkę. Proszę za każdym razem
854
- # tworzyć kopię pliku na swoim serwerze, hotlinking jest niedozwolony.
855
- def export_supporting_resources!(product)
856
- product.attachments.each do |attachment|
857
- if attachment.onix_resource_mode #jeśli klient coś dzikiego wgrał, to ignoruj to
858
- tag(:SupportingResource, :sourcename => "resourceid:#{attachment.id}", :datestamp => attachment.updated_at.to_s(:onix)) do
859
- comment_dictionary 'Typ załącznika', :ResourceContentType, :indent => 12, :kind => :onix_supporting_resources
860
- tag(:ResourceContentType, attachment.attachment_type_code) #lista 158
861
- comment 'Zawsze 00 - Unrestricted', :kind => :onix_supporting_resources
862
- tag(:ContentAudience, Elibri::ONIX::Dict::Release_3_0::ContentAudience::UNRESTRICTED)
863
- comment_dictionary 'Rodzaj załącznika', :ResourceMode, :indent => 12, :kind => :onix_supporting_resources
864
- tag(:ResourceMode, attachment.onix_resource_mode) #lista 159
865
- tag(:ResourceVersion) do
866
- comment 'Zawsze 02 - Downloadable file', :kind => :onix_supporting_resources
867
- tag(:ResourceForm, Elibri::ONIX::Dict::Release_3_0::ResourceForm::DOWNLOADABLE_FILE)
868
- url = attachment.file.url
869
- if url.index("http://") #w sklepie zwraca mi całego linka, wygodniej mi jest to tutaj wychwycić
870
- tag(:ResourceLink, URI.escape(url))
871
- else
872
- tag(:ResourceLink, URI.escape('http://' + HOST_NAME + url))
873
- end
874
- end
875
- end
918
+ comment_dictionary "Typy relacji", :ProductRelationType, :indent => 10, :kind => :onix_related_products
919
+ product.facsimiles.each do |facsimile|
920
+ tag(:RelatedProduct) do
921
+ tag(:ProductRelationCode, Elibri::ONIX::Dict::Release_3_0::ProductRelationType::FACSIMILES)
922
+ tag(:ProductIdentifier) do
923
+ comment "Zawsze #{Elibri::ONIX::Dict::Release_3_0::ProductIDType::PROPRIETARY} - wewnętrzny kod elibri (record reference)",
924
+ :kind => :onix_related_products
925
+ tag(:ProductIDType, Elibri::ONIX::Dict::Release_3_0::ProductIDType::PROPRIETARY)
926
+ tag(:IDTypeName, "elibri")
927
+ tag(:IDValue, facsimile.record_reference)
876
928
  end
877
929
  end
878
930
  end
879
-
880
-
881
- # @hidden_tags RecordReference NotificationType ProductIdentifier ProductComposition ProductForm
882
- # @title Serie wydawnicze
883
- # Serie wydawnicze opisywane w podobny sposób co tytuł, zawarte są jednak w tagu <strong>&lt;Collection&gt;</strong>
884
- # Struktura jest dosyć zawiła, ale wszystkie wartości są sztywne, więc nie powinno być problemu z odczytaniem informacji.
885
- # Oprócz nazwy serii może zostać również podany numer wewnątrz serii, jeśli seria jest numerowana.
886
- # Książka może należeć do kilku serii, wtedy tag <strong>&lt;Collection&gt;</strong> występuje kilkukrotnie.
887
- def export_series_memberships!(product)
888
- if product.series_membership_kind.user_given?
889
- product.series_memberships.each_with_index do |series_membership, idx|
890
- tag(:Collection) do
891
- comment "Używamy tylko #{Elibri::ONIX::Dict::Release_3_0::CollectionType::PUBLISHER_COLLECTION} - seria wydawnictwa", :kind => :onix_series_memberships
892
- tag(:CollectionType, Elibri::ONIX::Dict::Release_3_0::CollectionType::PUBLISHER_COLLECTION) #lista 148
893
- comment "Teraz następuje podobna struktura, jak w przypadku tytułu", :kind => :onix_series_memberships
894
- tag(:TitleDetail) do
895
- comment "Używamy tylko #{Elibri::ONIX::Dict::Release_3_0::TitleType::DISTINCTIVE_TITLE}", :kind => :onix_series_memberships
896
- tag(:TitleType, Elibri::ONIX::Dict::Release_3_0::TitleType::DISTINCTIVE_TITLE)
897
- tag(:TitleElement) do
898
- comment "Używamy tylko #{Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::COLLECTION}", :kind => :onix_series_memberships
899
- tag(:TitleElementLevel, Elibri::ONIX::Dict::Release_3_0::TitleElementLevel::COLLECTION)
900
- tag(:PartNumber, series_membership.number_within_series) if series_membership.number_within_series.present?
901
- tag(:TitleText, series_membership.series_name)
931
+ end
932
+ end
933
+
934
+
935
+ # @hidden_tags RecordReference NotificationType DescriptiveDetail Supplier ProductAvailability Price
936
+ # @title Stany magazynowe
937
+ # Tag <strong>&lt;Stock&gt;</strong> może zawierać konkretną ilość produktu w <strong>&ltOnHand&gt;</strong>,
938
+ # lub słownie określoną ilość w <strong>&lt;StockQuantityCoded&gt;</strong>.<br/><br/>
939
+ # Dokument XML zawierający dane o stanach magazynowych produktu najczęściej zawiera także rozszerzoną listę
940
+ # identyfikatorów produktu. Poza podstawowym <strong>&lt;ProductIdentifier&gt;</strong>, znajdują się także identyfikatory
941
+ # poszczególnych dostawców. Tag <strong>&lt;IDTypeName&gt;</strong> zawiera nazwę dostawcy.
942
+ def export_supply_details!(product)
943
+ return if product.try(:skip_ProductSupply)
944
+ unless product.product_availabilities.empty?
945
+ tag(:ProductSupply) do
946
+ product.product_availabilities.each do |pa|
947
+ tag(:SupplyDetail) do
948
+ tag(:Supplier) do
949
+ comment_dictionary "Rola dostawcy", :SupplierRole, :indent => 12
950
+ tag(:SupplierRole, pa.supplier_role_onix_code) #lista 93
951
+ tag(:SupplierIdentifier) do
952
+ comment "Zawsze 02 - Proprietary. Identyfikujemy dostawcę po NIP"
953
+ tag(:SupplierIDType, '02') #lista 92, Proprietary
954
+ tag(:IDTypeName, 'NIP')
955
+ tag(:IDValue, pa.supplier.nip.gsub("-", ""))
956
+ end
957
+ tag(:SupplierName, pa.supplier.name)
958
+ tag(:TelephoneNumber, pa.supplier.phone) if pa.supplier.phone.present?
959
+ tag(:EmailAddress, pa.supplier.email) if pa.supplier.email.present?
960
+ if pa.supplier.website.present?
961
+ tag(:Website) do
962
+ tag(:WebsiteLink, pa.supplier.website)
902
963
  end
903
964
  end
904
965
  end
905
- end
906
- end
907
- end
908
966
 
909
-
910
- # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
911
- # @title Powiązane produkty
912
- def export_related_products!(product)
913
- tag(:RelatedMaterial) do
914
-
915
- comment_dictionary "Typy relacji", :ProductRelationType, :indent => 10, :kind => :onix_related_products
916
- product.facsimiles.each do |facsimile|
917
- tag(:RelatedProduct) do
918
- tag(:ProductRelationCode, Elibri::ONIX::Dict::Release_3_0::ProductRelationType::FACSIMILES)
919
- tag(:ProductIdentifier) do
920
- comment "Zawsze #{Elibri::ONIX::Dict::Release_3_0::ProductIDType::PROPRIETARY} - wewnętrzny kod elibri (record reference)",
921
- :kind => :onix_related_products
922
- tag(:ProductIDType, Elibri::ONIX::Dict::Release_3_0::ProductIDType::PROPRIETARY)
923
- tag(:IDTypeName, "elibri")
924
- tag(:IDValue, facsimile.record_reference)
967
+ comment_dictionary "Typ dostępności", :ProductAvailabilityType, :indent => 10
968
+ tag(:ProductAvailability, pa.product_availability_onix_code) #lista 65
969
+ if pa.stock_info
970
+ tag(:Stock) do
971
+ if pa.stock_info.exact_info?
972
+ tag(:OnHand, pa.stock_info.on_hand)
973
+ else
974
+ comment 'Nie znamy konkretnej ilości produktów na stanie'
975
+ tag(:StockQuantityCoded) do
976
+ comment 'Zawsze 01 - Proprietary'
977
+ tag(:StockQuantityCodeType, '01') #lista 70 - proprietary
978
+ tag(:StockQuantityCode, pa.stock_info.quantity_code) #low/high
979
+ end
980
+ end
925
981
  end
926
- end
927
- end
928
- end
929
- end
930
-
931
-
932
- # @hidden_tags RecordReference NotificationType DescriptiveDetail Supplier ProductAvailability Price
933
- # @title Stany magazynowe
934
- # Tag <strong>&lt;Stock&gt;</strong> może zawierać konkretną ilość produktu w <strong>&ltOnHand&gt;</strong>,
935
- # lub słownie określoną ilość w <strong>&lt;StockQuantityCoded&gt;</strong>.<br/><br/>
936
- # Dokument XML zawierający dane o stanach magazynowych produktu najczęściej zawiera także rozszerzoną listę
937
- # identyfikatorów produktu. Poza podstawowym <strong>&lt;ProductIdentifier&gt;</strong>, znajdują się także identyfikatory
938
- # poszczególnych dostawców. Tag <strong>&lt;IDTypeName&gt;</strong> zawiera nazwę dostawcy.
939
- def export_supply_details!(product)
940
- return if product.try(:skip_ProductSupply)
941
- unless product.product_availabilities.empty?
942
- tag(:ProductSupply) do
943
- product.product_availabilities.each do |pa|
944
- tag(:SupplyDetail) do
945
- tag(:Supplier) do
946
- comment_dictionary "Rola dostawcy", :SupplierRole, :indent => 12
947
- tag(:SupplierRole, pa.supplier_role_onix_code) #lista 93
948
- tag(:SupplierIdentifier) do
949
- comment "Zawsze 02 - Proprietary. Identyfikujemy dostawcę po NIP"
950
- tag(:SupplierIDType, '02') #lista 92, Proprietary
951
- tag(:IDTypeName, 'NIP')
952
- tag(:IDValue, pa.supplier.nip.gsub("-", ""))
953
- end
954
- tag(:SupplierName, pa.supplier.name)
955
- tag(:TelephoneNumber, pa.supplier.phone) if pa.supplier.phone.present?
956
- tag(:EmailAddress, pa.supplier.email) if pa.supplier.email.present?
957
- if pa.supplier.website.present?
958
- tag(:Website) do
959
- tag(:WebsiteLink, pa.supplier.website)
960
- end
961
- end
962
- end
982
+ end
983
+ if product.pack_quantity.present?
984
+ comment 'Ile produktów dostawca umieszcza w paczce'
985
+ tag(:PackQuantity, product.pack_quantity)
986
+ end
963
987
 
964
- comment_dictionary "Typ dostępności", :ProductAvailabilityType, :indent => 10
965
- tag(:ProductAvailability, pa.product_availability_onix_code) #lista 65
966
- if pa.stock_info
967
- tag(:Stock) do
968
- if pa.stock_info.exact_info?
969
- tag(:OnHand, pa.stock_info.on_hand)
970
- else
971
- comment 'Nie znamy konkretnej ilości produktów na stanie'
972
- tag(:StockQuantityCoded) do
973
- comment 'Zawsze 01 - Proprietary'
974
- tag(:StockQuantityCodeType, '01') #lista 70 - proprietary
975
- tag(:StockQuantityCode, pa.stock_info.quantity_code) #low/high
976
- end
977
- end
978
- end
988
+ pa.price_infos.each do |price_info|
989
+ tag(:Price) do
990
+ comment_dictionary "Typ ceny", :PriceTypeCode, :indent => 12
991
+ tag(:PriceType, Elibri::ONIX::Dict::Release_3_0::PriceTypeCode::RRP_WITH_TAX) #lista 58
992
+ tag(:MinimumOrderQuantity, price_info.minimum_order_quantity) if price_info.minimum_order_quantity
993
+ tag(:PriceAmount, price_info.amount)
994
+ tag(:Tax) do
995
+ comment 'VAT'
996
+ tag(:TaxType, '01') #lista 174, VAT
997
+ tag(:TaxRatePercent, price_info.vat)
979
998
  end
980
- if product.pack_quantity.present?
981
- comment 'Ile produktów dostawca umieszcza w paczce'
982
- tag(:PackQuantity, product.pack_quantity)
983
- end
984
-
985
- pa.price_infos.each do |price_info|
986
- tag(:Price) do
987
- comment_dictionary "Typ ceny", :PriceTypeCode, :indent => 12
988
- tag(:PriceType, Elibri::ONIX::Dict::Release_3_0::PriceTypeCode::RRP_WITH_TAX) #lista 58
989
- tag(:MinimumOrderQuantity, price_info.minimum_order_quantity) if price_info.minimum_order_quantity
990
- tag(:PriceAmount, price_info.amount)
991
- tag(:Tax) do
992
- comment 'VAT'
993
- tag(:TaxType, '01') #lista 174, VAT
994
- tag(:TaxRatePercent, price_info.vat)
995
- end
996
- tag(:CurrencyCode, price_info.currency_code)
997
- if product.price_printed_on_product_onix_code.present?
998
- comment_dictionary "Cena na okładce?", :PricePrintedOnProduct, :indent => 12
999
- tag(:PrintedOnProduct, product.price_printed_on_product_onix_code) #lista 174
1000
- comment 'Zawsze 00 - Unknown / unspecified'
1001
- tag(:PositionOnProduct, '00') #lista 142 - Position unknown or unspecified
1002
- end
1003
- end
999
+ tag(:CurrencyCode, price_info.currency_code)
1000
+ if product.price_printed_on_product_onix_code.present?
1001
+ comment_dictionary "Cena na okładce?", :PricePrintedOnProduct, :indent => 12
1002
+ tag(:PrintedOnProduct, product.price_printed_on_product_onix_code) #lista 174
1003
+ comment 'Zawsze 00 - Unknown / unspecified'
1004
+ tag(:PositionOnProduct, '00') #lista 142 - Position unknown or unspecified
1004
1005
  end
1005
1006
  end
1006
1007
  end
1007
1008
  end
1008
- end
1009
+ end
1009
1010
  end
1011
+ end
1012
+ end
1010
1013
 
1011
1014
 
1012
- # @title Rozszerzenia eLibri dla ONIX
1013
- # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
1014
- # Standard ONIX nie przewiduje w chwili obecnej atrybutów produktów niezbędnych z punktu widzenia polskiego rynku wydawniczego.
1015
- # Są to atrybuty takie jak np. Vat czy PKWiU. eLibri rozszerza więc ONIX o kilka użytecznych tagów, wprowadzając nową przestrzeń nazw
1016
- # w generowanych XML`ach.
1017
- def export_elibri_extensions!(product)
1018
- if @elibri_onix_dialect >= '3.0.1'
1015
+ # @title Rozszerzenia eLibri dla ONIX
1016
+ # @hidden_tags RecordReference NotificationType ProductIdentifier DescriptiveDetail
1017
+ # Standard ONIX nie przewiduje w chwili obecnej atrybutów produktów niezbędnych z punktu widzenia polskiego rynku wydawniczego.
1018
+ # Są to atrybuty takie jak np. Vat czy PKWiU. eLibri rozszerza więc ONIX o kilka użytecznych tagów, wprowadzając nową przestrzeń nazw
1019
+ # w generowanych XML`ach.
1020
+ def export_elibri_extensions!(product)
1021
+ if @elibri_onix_dialect >= '3.0.1'
1019
1022
 
1020
- if product.cover_type
1021
- comment_dictionary "Format okładki", Product::CoverType.all.map(&:name), :indent => 10
1022
- tag("elibri:CoverType", product.cover_type.name)
1023
- end
1023
+ if product.cover_type
1024
+ comment_dictionary "Format okładki", Product::CoverType.all.map(&:name), :indent => 10
1025
+ tag("elibri:CoverType", product.cover_type.name)
1026
+ end
1024
1027
 
1025
- comment 'Cena na okładce'
1026
- tag("elibri:CoverPrice", product.price_amount) if product.price_amount.present?
1027
- comment 'Vat w procentach'
1028
- tag("elibri:Vat", product.vat) if product.vat.present?
1029
- tag("elibri:PKWiU", product.pkwiu) if product.pkwiu.present?
1030
- tag("elibri:preview_exists", product.preview_exists?.to_s)
1031
- if product.digital?
1032
- if product.epub_sale_not_restricted? || product.epub_sale_restricted_to.nil?
1033
- tag("elibri:SaleNotRestricted")
1034
- else
1035
- tag("elibri:SaleRestrictedTo", product.epub_sale_restricted_to.strftime("%Y%m%d"))
1036
- end
1037
- end
1038
- if product.isbn
1039
- tag("elibri:HyphenatedISBN", product.isbn.human_value)
1040
- end
1028
+ comment 'Cena na okładce'
1029
+ tag("elibri:CoverPrice", product.price_amount) if product.price_amount.present?
1030
+ comment 'Vat w procentach'
1031
+ tag("elibri:Vat", product.vat) if product.vat.present?
1032
+ tag("elibri:PKWiU", product.pkwiu) if product.pkwiu.present?
1033
+ tag("elibri:preview_exists", product.preview_exists?.to_s)
1034
+ if product.digital?
1035
+ if product.epub_sale_not_restricted? || product.epub_sale_restricted_to.nil?
1036
+ tag("elibri:SaleNotRestricted")
1037
+ else
1038
+ tag("elibri:SaleRestrictedTo", product.epub_sale_restricted_to.strftime("%Y%m%d"))
1041
1039
  end
1042
1040
  end
1043
-
1044
-
1041
+ if product.isbn
1042
+ tag("elibri:HyphenatedISBN", product.isbn.human_value)
1043
+ end
1045
1044
  end
1046
-
1047
- end
1048
-
1045
+ end
1049
1046
 
1050
1047
  end
1051
1048
  end