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