mercator_mesonic 0.0.1 → 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,12 @@ module MercatorMesonic
3
3
 
4
4
  self.table_name = "T026"
5
5
  self.primary_key = "c000"
6
+ attr_accessible :c000, :c003, :c004, :c005, :c006, :c007, :c008, :c009, :c010, :c011, :c012, :c013, :c014,
7
+ :c015, :c016, :c018, :c019, :c020, :c021, :c022, :c023, :c024, :c025, :c026, :c027, :c031,
8
+ :c032, :c033, :c034, :c035, :c042, :c044, :c045, :c046, :c047, :c048, :c052, :c054, :c055,
9
+ :c056, :c057, :c058, :c059, :c060, :c061, :c062, :c063, :c068, :c070, :c071, :c072, :c073,
10
+ :c074, :c075, :c077, :c078, :c081, :c082, :c083, :c085, :c086, :c087, :c088, :c091, :c092,
11
+ :c098, :c099, :c100, :c101, :c104, :C106, :C107, :C108, :C109, :mesocomp, :mesoyear, :mesoprim
6
12
 
7
13
  belongs_to :inventory, :foreign_key => "C003"
8
14
 
@@ -12,20 +18,23 @@ module MercatorMesonic
12
18
  # --- Class Methods --- #
13
19
 
14
20
  def self.initialize_mesonic(mesonic_order: nil, lineitem: nil, customer: nil, index: nil)
15
- id = mesonic_order.C000 + "-" + "%06d" % (index + 1 )
21
+ id = mesonic_order.c000 + "-" + "%06d" % (index + 1 )
22
+ product = lineitem.product
23
+ inventory = product.determine_inventory(amount: lineitem.amount)
24
+
16
25
  self.new(c000: id,
17
- c003: lineitem.inventory.article_number,
18
- c004: lineitem.inventory.Bezeichnung,
19
- c005: lineitem.menge, # menge bestellt
20
- c006: lineitem.menge, # menge geliefert
21
- c007: lineitem.einzelpreis, # einzelpreis
22
- c008: 0, # zeilenrabatt 1 und 2
26
+ c003: lineitem.product_number,
27
+ c004: lineitem.description_de,
28
+ c005: lineitem.amount, # menge bestellt
29
+ c006: lineitem.amount, # menge geliefert
30
+ c007: lineitem.product_price, # einzelpreis
31
+ c008: 0, # zeilenrabatt 1 und 2 #FIXME lineitem.discount_abs ?
23
32
  c009: 4002, # erlöskonto
24
- c010: lineitem.inventory.Steuersatzzeile, # umsatzsteuer prozentsatz #FIXME
33
+ c010: inventory.erp_vatline, # umsatzsteuer prozentsatz -> Steuersatzzeile
25
34
  c011: 1, # statistikkennzeichen
26
- c012: lineitem.inventory.ArtGruppe, # artikelgruppe #FIXME
35
+ c012: inventory.erp_article_group, # artikelgruppe
27
36
  c013: 0, # liefertage
28
- c014: lineitem.inventory.Provisionscode, # provisionscode #FIXME
37
+ c014: inventory.erp_provision_code, # provisionscode
29
38
  c015: nil, # colli
30
39
  c016: 0, # menge bereits geliefert
31
40
  c018: 0, # faktor 1 nach formeleingabe
@@ -38,10 +47,10 @@ module MercatorMesonic
38
47
  c025: mesonic_order.c027, # lieferdatum
39
48
  c026: 400, # kostenstelle
40
49
  c027: 0, # lieferwoche
41
- c031: lineitem.gesamtwert, # gesamtwert #FIXME
50
+ c031: lineitem.value, # gesamtwert
42
51
  c032: 0, # positionslevel
43
52
  c033: nil, # positionsnummer text
44
- c034: lineitem.inventory.Gewicht, # gewicht #FIXME
53
+ c034: inventory.weight, # gewicht
45
54
  c035: 0, # einstandspreis KZ
46
55
  c042: 1, # datentyp
47
56
  c044: mesonic_order.c021, # kontonummer
@@ -51,8 +60,8 @@ module MercatorMesonic
51
60
  c048: mesonic_order.c027.year, # lieferjahr
52
61
  c052: 0, # stat. wert
53
62
  c054: 0, # bewertungspreis editieren
54
- c055: lineitem.inventory.Auspraegungsflag, #FIXME
55
- c056: customer.erp_account_nr, # interessentenkontonummer
63
+ c055: inventory.erp_characteristic_flag, #Ausprägungsflag
64
+ c056: customer.mesonic_account_number, # interessentenkontonummer
56
65
  c057: 0, # lagerbestand ändern J/N
57
66
  c058: 0, # key für dispozeile
58
67
  c059: 0, # zeilennummer d kundenauftrags
@@ -71,7 +80,7 @@ module MercatorMesonic
71
80
  c078: index + 1, # zeilennummer (intern)
72
81
  c081: 0, # nummer des kontraktpreises
73
82
  c082: 0, # menge 2
74
- c083: lineitem.inventory.Steuersatzzeile * 10, #FIXME
83
+ c083: lineitem.vat, # Steuersatz in Prozent
75
84
  c085: 2, # exim durchgeführt änderungen
76
85
  c086: 0, # EURO einstandspreis
77
86
  c087: 0, # bnk-prozent
@@ -85,17 +94,11 @@ module MercatorMesonic
85
94
  c104: 0,
86
95
  mesocomp: AktMandant.mesocomp,
87
96
  mesoyear: AktMandant.mesoyear,
88
- mesoprim: id + "-" + AktMandant.mesocomp + "-" + AktMandant.mesoyear,
97
+ mesoprim: [id, AktMandant.mesocomp, AktMandant.mesoyear].join("-"),
89
98
  C106: "",
90
99
  C107: 0,
91
100
  C108: "",
92
101
  C109: 0 )
93
102
  end
94
-
95
- # --- Instance Methods --- #
96
-
97
- def readonly? # prevents unintentional changes
98
- true
99
- end
100
103
  end
101
104
  end
@@ -6,7 +6,7 @@ module MercatorMesonic
6
6
 
7
7
  scope :mesoyear, -> { where(mesoyear: AktMandant.mesoyear) }
8
8
  scope :mesocomp, -> { where(mesocomp: AktMandant.mesocomp) }
9
- default_scope { mesocomp.mesoyear.where(c002: 3).pluck(:c002, :c001, :c003, :c013) }
9
+ default_scope { mesocomp.mesoyear.where(c002: 3) }
10
10
 
11
11
  alias_attribute :price_column, :c013
12
12
 
@@ -36,12 +36,12 @@ module MercatorMesonic
36
36
  # find regular price
37
37
  scope :regular, -> { where(c001: "1") }
38
38
 
39
+ # --- Instance Methods --- #
40
+
39
41
  def price
40
- self.send( self.class.price_column )
42
+ self.c013
41
43
  end
42
44
 
43
- # --- Instance Methods --- #
44
-
45
45
  def readonly? # prevents unintentional changes
46
46
  true
47
47
  end
@@ -4,6 +4,9 @@ module MercatorMesonic
4
4
  self.table_name = "WEBARTIKEL"
5
5
  self.primary_key = "Artikelnummer"
6
6
 
7
+ has_many :mesonic_prices, :class_name => "Price",
8
+ :foreign_key => "c000", :primary_key => "Artikelnummer"
9
+
7
10
  # --- Class Methods --- #
8
11
 
9
12
  def self.import(update: "changed")
@@ -18,10 +21,18 @@ module MercatorMesonic
18
21
  @webartikel = Webartikel.all
19
22
  end
20
23
 
24
+ amount = @webartikel.count
25
+ index = 0
21
26
  if @webartikel.any?
22
27
  @webartikel.group_by{|webartikel| webartikel.Artikelnummer }.each do |artikelnummer, artikel|
28
+ index = index + 1
23
29
 
24
- Inventory.where(number: artikelnummer).destroy_all # This also deletes the prices!
30
+ @old_inventories = Inventory.where(number: artikelnummer)
31
+ if ( @old_inventories.destroy_all if @old_inventories )# This also deletes the prices!
32
+ ::JobLogger.info("Inventories deleted for Product " + artikelnummer)
33
+ else
34
+ ::JobLogger.error("Deleting Inventory failed: " + @old_inventories.errors.first)
35
+ end
25
36
 
26
37
  artikel.each do |webartikel|
27
38
  @product = Product.where(number: webartikel.Artikelnummer).first
@@ -32,8 +43,11 @@ module MercatorMesonic
32
43
  @product.categorizations.where(category_id: @discounts.id).destroy_all
33
44
  @product.categorizations.where(category_id: @topsellers.id).destroy_all
34
45
  if @product.lifecycle.can_reactivate?(User.where(administrator: true).first)
35
- @product.lifecycle.reactivate!(User.where(administrator: true).first)
36
- puts @product.number + " reactivated"
46
+ if @product.lifecycle.reactivate!(User.where(administrator: true).first)
47
+ ::JobLogger.info("Product " + @product.number + " reactivated.")
48
+ else
49
+ ::JobLogger.error("Product " + @product.number + " could not be reactivated!")
50
+ end
37
51
  end
38
52
  else
39
53
  @product = Product.create_in_auto(number: webartikel.Artikelnummer,
@@ -41,7 +55,7 @@ module MercatorMesonic
41
55
  description: webartikel.comment)
42
56
  end
43
57
 
44
- webartikel.Zusatzfeld5 ? delivery_time = webartikel.Zusatzfeld5 : delivery_time = "Auf Anfrage"
58
+ delivery_time = webartikel.Zusatzfeld5 ? webartikel.Zusatzfeld5 : I18n.t("mercator.on_request")
45
59
 
46
60
  @inventory = Inventory.new(product_id: @product.id,
47
61
  number: webartikel.Artikelnummer,
@@ -51,45 +65,60 @@ module MercatorMesonic
51
65
  charge: webartikel.LfdChargennr,
52
66
  unit: "Stk.",
53
67
  delivery_time: delivery_time,
54
- amount: 9999,
55
- erp_updated_at: webartikel.letzteAend)
56
-
57
- if webartikel.Kennzeichen = "T"
68
+ amount: 0,
69
+ erp_updated_at: webartikel.letzteAend,
70
+ erp_vatline: webartikel.Steuersatzzeile,
71
+ erp_article_group: webartikel.ArtGruppe,
72
+ erp_provision_code: webartikel.Provisionscode,
73
+ erp_characteristic_flag: webartikel.Auspraegungsflag,
74
+ infinite: true,
75
+ just_imported: true,
76
+ alternative_number: webartikel.AltArtNr1)
77
+
78
+ if ( webartikel.Kennzeichen == "T" ) &&
79
+ ( webartikel.Artikelnummer != Constant.find_by_key("shipping_cost_article").value )
58
80
  @product.topseller = true
59
81
  position = 1
60
82
  position = @topsellers.categorizations.maximum(:position) + 1 if @topsellers.categorizations.any?
61
83
  @product.categorizations.new(category_id: @topsellers.id, position: position)
84
+ else
85
+ @product.categorizations.where(category_id: @topsellers.id).destroy_all
62
86
  end
63
87
 
64
- if webartikel.Kennzeichen = "N"
88
+ if ( webartikel.Kennzeichen == "N" ) &&
89
+ ( webartikel.Artikelnummer != Constant.find_by_key("shipping_cost_article").value )
65
90
  @product.novelty = true
66
91
  position = 1
67
92
  position = @novelties.categorizations.maximum(:position) + 1 if @novelties.categorizations.any?
68
93
  @product.categorizations.new(category_id: @novelties.id, position: position)
94
+ else
95
+ @product.categorizations.where(category_id: @novelties.id).destroy_all
69
96
  end
70
97
 
71
- if webartikel.PreisdatumVON && webartikel.PreisdatumVON <= Time.now &&
72
- webartikel.PreisdatumBIS && webartikel.PreisdatumBIS >= Time.now
98
+ if webartikel.PreisdatumVON && ( webartikel.PreisdatumVON <= Time.now ) &&
99
+ webartikel.PreisdatumBIS && ( webartikel.PreisdatumBIS >= Time.now )
73
100
  position = 1
74
101
  position = @discounts.categorizations.maximum(:position) + 1 if @discounts.categorizations.any?
75
102
  @product.categorizations.new(category_id: @discounts.id, position: position)
103
+ else
104
+ @product.categorizations.where(category_id: @discounts.id).destroy_all
76
105
  end
77
106
 
78
107
  if @inventory.save
79
- print "I"
108
+ ::JobLogger.info("Inventory " + @inventory.number + " saved.")
80
109
  else
81
- puts @inventory.errors.first.to_s
110
+ ::JobLogger.error("Saving Inventory failed: " + @inventory.errors.first.to_s)
82
111
  end
83
112
 
84
113
  # --- Price-Handling --- #
85
114
  @price = Price.new(value: webartikel.Preis,
86
115
  scale_from: webartikel.AbMenge,
87
116
  scale_to: 9999,
88
- vat: 20,
117
+ vat: webartikel.Steuersatzzeile * 10,
89
118
  inventory_id: @inventory.id)
90
119
 
91
- if webartikel.PreisdatumVON && webartikel.PreisdatumVON <= Time.now &&
92
- webartikel.PreisdatumBIS && webartikel.PreisdatumBIS >= Time.now
120
+ if webartikel.PreisdatumVON && ( webartikel.PreisdatumVON <= Time.now ) &&
121
+ webartikel.PreisdatumBIS && ( webartikel.PreisdatumBIS >= Time.now )
93
122
  @price.promotion = true
94
123
  @price.valid_from = webartikel.PreisdatumVON
95
124
  @price.valid_to = webartikel.PreisdatumBIS
@@ -99,9 +128,9 @@ module MercatorMesonic
99
128
  end
100
129
 
101
130
  if @price.save
102
- print "$"
131
+ ::JobLogger.info("Price for Inventory " + @price.inventory_id.to_s + " saved.")
103
132
  else
104
- puts @price.errors.first.to_s
133
+ ::JobLogger.error("Saving Price failed: " + @price.errors.first.to_s)
105
134
  end
106
135
 
107
136
  # --- recommendations-Handling --- #
@@ -112,15 +141,64 @@ module MercatorMesonic
112
141
  end
113
142
 
114
143
  if @product.save
115
- print "P"
144
+ ::JobLogger.info("Recommendation for Product " + @product.number + " saved.")
116
145
  else
117
- puts @inventory.errors.first.to_s
146
+ ::JobLogger.error("Saving Recommendation failed: " + @product.errors.first.to_s)
118
147
  end
119
148
  end
149
+ ::JobLogger.info("----- Finished: " + artikelnummer.to_s + " (" + index.to_s + "/" + amount.to_s + ") -----")
120
150
  end
121
151
  else
122
- puts "No new entries in WEBARTIKEL View"
152
+ ::JobLogger.info("No new entries in WEBARTIKEL View, nothing updated.")
153
+ end
154
+
155
+ self.remove_orphans(only_old: true)
156
+
157
+ ::JobLogger.info("Deprecating products ... ")
158
+ ::Product.deprecate
159
+ end
160
+
161
+
162
+ def self.remove_orphans(only_old: false)
163
+ ::JobLogger.info("Removing orphans ...")
164
+ if only_old
165
+ @inventories = Inventory.where(just_imported: [false, nil])
166
+ else
167
+ @inventories = Inventory.all
168
+ end
169
+ @inventories.each do |inventory|
170
+ if MercatorMesonic::Webartikel.where(Artikelnummer: inventory.number).count == 0
171
+ if inventory.destroy
172
+ ::JobLogger.info("Deleted Inventory " + inventory.number.to_s)
173
+ else
174
+ ::JobLogger.info("Deleting Inventory failed: " + inventory.errors.first)
175
+ end
176
+ else
177
+ ::JobLogger.info("Inventory " + inventory.number.to_s + " still present in MercatorMesonic::Webartikel.")
178
+ end
179
+ end
180
+ ::JobLogger.info("Resetting new inventories ...")
181
+ Inventory.where(just_imported: true).each do |inventory|
182
+ inventory.update_attributes(just_imported: false)
123
183
  end
184
+ ::JobLogger.info("... completed, removing orphans finished.")
185
+ end
186
+
187
+
188
+ def self.test_connection
189
+ [1,2,3].each do |attempt|
190
+ begin
191
+ self.count # that actually tries to establish a connection
192
+ ::JobLogger.info("Connection to Mesonic database established successfully.")
193
+ puts "further logging goes to Joblog: /log/RAILS_ENV_job.log ..."
194
+ return true
195
+ rescue
196
+ ::JobLogger.fatal("Connection to Mesonic database could not be established! (attempt no." + attempt.to_s + ")")
197
+ puts "FATAL ERROR: Connection to Mesonic database could not be established! (attempt no." + attempt.to_s + ")"
198
+ end
199
+ end
200
+
201
+ return false
124
202
  end
125
203
 
126
204
  # --- Instance Methods --- #
@@ -0,0 +1,45 @@
1
+ module OrderExtensions
2
+
3
+ # --- Instance Methods --- #
4
+ def mesonic_payment_id
5
+ {"cash_payment" => '1002', "atm_payment" => '1003', "pre_payment" => '1010', "e_payment" => '1011'}[self.billing_method]
6
+ # further Mesonic ids Nachnahme => '1001'
7
+ end
8
+
9
+ def mesonic_payment_id2
10
+ {"1002" => "17", "1003" => "17", "1010" => "19", "1011" => "25" }[self.mesonic_payment_id]
11
+ # "1001" => "17"
12
+ end
13
+
14
+ def mesonic_shipping_id
15
+ {"parcel_service_shipment" => '1', "pickup_shipment" => '2'}[self.shipping_method]
16
+ end
17
+
18
+ def push_to_mesonic
19
+ mesonic_order = MercatorMesonic::Order.initialize_mesonic(order: self)
20
+ mesonic_order_items = []
21
+ self.lineitems.each_with_index do |lineitem, index|
22
+ mesonic_order_items << MercatorMesonic::OrderItem.initialize_mesonic(mesonic_order: mesonic_order, lineitem: lineitem,
23
+ customer: self.user, index: index)
24
+ end
25
+
26
+ ::JobLogger.debug(mesonic_order)
27
+ mesonic_order_items.each do |mesonic_order_item|
28
+ ::JobLogger.debug(mesonic_order_item)
29
+ end
30
+
31
+ save_return_value = Order.transaction do
32
+ mesonic_order.save
33
+ mesonic_order_items.collect(&:save)
34
+ end
35
+
36
+ if save_return_value
37
+ self.update(erp_customer_number: self.user.erp_account_nr,
38
+ erp_billing_number: mesonic_order.c021,
39
+ erp_order_number: mesonic_order.c022)
40
+ OrderMailer.order_confirmation(order: self)
41
+ else
42
+ raise "Error! Order could not be pushed to mesonic!"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,89 @@
1
+ module UserExtensions
2
+
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attr_accessible :mesonic_kontakte_stamm, :mesonic_kontenstamm, :mesonic_kontenstamm_fakt,
7
+ :mesonic_kontenstamm_fibu, :mesonic_kontenstamm_adresse
8
+
9
+ belongs_to :mesonic_kontakte_stamm, class_name: "MercatorMesonic::KontakteStamm",
10
+ foreign_key: :erp_contact_nr, primary_key: :mesoprim
11
+
12
+ belongs_to :mesonic_kontenstamm, class_name: "MercatorMesonic::Kontenstamm",
13
+ foreign_key: :erp_account_nr, primary_key: :mesoprim
14
+ accepts_nested_attributes_for :mesonic_kontenstamm, allow_destroy: false
15
+
16
+ belongs_to :mesonic_kontenstamm_fakt, class_name: "MercatorMesonic::KontenstammFakt",
17
+ foreign_key: :erp_account_nr, primary_key: :mesoprim
18
+ accepts_nested_attributes_for :mesonic_kontenstamm_fakt, allow_destroy: false
19
+
20
+ belongs_to :mesonic_kontenstamm_fibu, class_name: "MercatorMesonic::KontenstammFibu",
21
+ foreign_key: :erp_account_nr, primary_key: :mesoprim
22
+ accepts_nested_attributes_for :mesonic_kontenstamm_fibu, allow_destroy: false
23
+
24
+ belongs_to :mesonic_kontenstamm_adresse, class_name: "MercatorMesonic::KontenstammAdresse",
25
+ foreign_key: :erp_account_nr, primary_key: :mesoprim
26
+ accepts_nested_attributes_for :mesonic_kontenstamm_adresse, allow_destroy: false
27
+
28
+ def self.update_erp_account_nrs
29
+ erp_users = User.where.not(erp_contact_nr: nil)
30
+ erp_users.each {|erp_user| erp_user.update_erp_account_nr}
31
+ end
32
+ end
33
+
34
+ # --- Instance Methods --- #
35
+
36
+ def push_to_mesonic
37
+ @timestamp = Time.now
38
+
39
+ @kontonummer = MercatorMesonic::Kontenstamm.next_kontonummer
40
+ @kontaktenummer = MercatorMesonic::KontakteStamm.next_kontaktenummer
41
+
42
+ @mesonic_kontakte_stamm = MercatorMesonic::KontakteStamm.initialize_mesonic(user: self, kontonummer: @kontonummer, kontaktenummer: @kontaktenummer)
43
+ @mesonic_kontenstamm = MercatorMesonic::Kontenstamm.initialize_mesonic(user: self, kontonummer: @kontonummer, timestamp: @timestamp)
44
+ @mesonic_kontenstamm_fakt = MercatorMesonic::KontenstammFakt.initialize_mesonic(kontonummer: @kontonummer, email: self.email_address)
45
+ @mesonic_kontenstamm_fibu = MercatorMesonic::KontenstammFibu.initialize_mesonic(kontonummer: @kontonummer)
46
+ @mesonic_kontenstamm_adresse = MercatorMesonic::KontenstammAdresse.initialize_mesonic(billing_address: self.billing_addresses.first, kontonummer: @kontonummer)
47
+
48
+ if [@mesonic_kontakte_stamm, @mesonic_kontenstamm, @mesonic_kontenstamm_adresse,
49
+ @mesonic_kontenstamm_fibu, @mesonic_kontenstamm_fakt ].collect(&:valid?).all?
50
+
51
+ [@mesonic_kontakte_stamm, @mesonic_kontenstamm, @mesonic_kontenstamm_adresse,
52
+ @mesonic_kontenstamm_fibu, @mesonic_kontenstamm_fakt ].collect(&:save).all?
53
+
54
+ end
55
+
56
+ self.update(erp_account_nr: User.mesoprim(number: @kontonummer),
57
+ erp_contact_nr: User.mesoprim(number: @kontaktenummer) )
58
+ end
59
+
60
+ def update_mesonic(billing_address: self.billing_addresses.first)
61
+ mesonic_kontenstamm_adresse = MercatorMesonic::KontenstammAdresse.where(mesoprim: self.erp_account_nr).first
62
+
63
+ mesonic_kontenstamm_adresse.update(c050: billing_address.street,
64
+ c051: billing_address.postalcode,
65
+ c052: billing_address.city,
66
+ c053: billing_address.c_o,
67
+ c123: billing_address.country,
68
+ c181: billing_address.name.split(/\s/).last,
69
+ c116: billing_address.email_address.to_s)
70
+ end
71
+
72
+ def mesonic_account_number
73
+ "%06d" % self.erp_account_nr[0..-11] # ...it is actually a string and may contain 1I for potential buyers
74
+ end
75
+
76
+ def update_erp_account_nr
77
+ # We want to fix the local database entry for erp_account_nr if someone changed the Account on mesonic side,
78
+ # e.g. if the potential customer ('Interessent') was changed to an actual customer accout.
79
+ if self.erp_contact_nr && !self.mesonic_kontenstamm && self.mesonic_kontakte_stamm
80
+ mesonic_kontenstamm = MercatorMesonic::Kontenstamm.where(c002: self.mesonic_kontakte_stamm.c039).first
81
+
82
+ if self.update(erp_account_nr: mesonic_kontenstamm.mesoprim)
83
+ ::JobLogger.info("Updated user " + self.id.to_s + "'s erp account number to " + self.erp_account_nr)
84
+ else
85
+ ::JobLogger.error("Error updating user" + self.id.to_s + "'s erp account number")
86
+ end
87
+ end
88
+ end
89
+ end