Ajout des menu de configuration pour les tarifs et les taux de tva
[bilio:bilio.git] / src / article.rb
1 # coding: utf-8
2
3 class Article_box < Gtk::VBox
4
5         attr_reader :article
6         MAX_SPIN = 999999
7
8         def initialize window, dial=false
9         
10                 super(false, 3)
11                 
12                 set_border_width 10
13                 
14                 @id = 0
15                 
16                 @window = window
17                 @login = window.login
18                 @dial = dial
19                 
20                 @activer_combo = false
21                 @graph = GraphBar.new absolu=true
22                 
23                 @info1 = Gtk::Entry.new
24                 @info2 = Gtk::Entry.new
25                 @description = Gtk::TextView.new
26                 @datecreation = Gtk::Calendar.new
27                 @valider = Gtk::Button.new
28                 hboxvalider = Gtk::HBox.new false, 2
29                 hboxvalider.add Gtk::Image.new( "./resources/icons/ok.png" )
30                 hboxvalider.add Gtk::Label.new "Valider"
31                 @valider.add hboxvalider
32                 @annuler = Gtk::Button.new
33                 hboxannuler = Gtk::HBox.new false, 2
34                 hboxannuler.add Gtk::Image.new( "./resources/icons/cancel.png" )
35                 hboxannuler.add Gtk::Label.new "Annuler"
36                 @annuler.add hboxannuler
37                 @supprimer = Gtk::Button.new
38                 hboxsupprimer = Gtk::HBox.new false, 2
39                 hboxsupprimer.add Gtk::Image.new( "./resources/icons/remove.png" )
40                 hboxsupprimer.add Gtk::Label.new "Supprimer"
41                 @supprimer.add hboxsupprimer
42                 
43                 agencement
44                 
45                 @valider.signal_connect( "clicked" ) { validate }
46                 @annuler.signal_connect( "clicked" ) { quit }
47                 @supprimer.signal_connect( "clicked" ) { supprimer }
48         
49         end
50         
51         def agencement
52         
53                 vbox = Gtk::VBox.new false, 3
54                 @frame = Gtk::Frame.new
55                 @frame.label = "Nouvel article"
56                 vbox.pack_start( @frame, true, true, 3 )
57                 
58                 vbox_corps = Gtk::VBox.new false, 3
59                 @frame.add vbox_corps
60                 vbox_corps.pack_start( en_tete, true, true, 3 )         
61                 
62                 hbox3 = Gtk::HBox.new false, 2
63                 align1 = Gtk::Alignment.new 1, 1, 0, 0
64                 hbox3.pack_start( @annuler, true, true, 3 )
65                 hbox3.pack_start( @valider, true, true, 3 )
66                 align1.add hbox3
67                 
68                 hbox1 = Gtk::HBox.new false, 2
69                 hbox1.pack_start @supprimer, false, false, 2
70                 hbox1.pack_start align1, true, true, 2
71                 
72                 vbox.pack_start( hbox1, false, false, 3 ) unless @dial
73                 
74                 self.add vbox
75         
76         end
77         
78         def en_tete
79         
80                 # Objets
81                 @code = Gtk::Entry.new
82                 @groupe_model = Gtk::TreeStore.new(Integer, String)
83                 @groupe = Gtk::ComboBox.new @groupe_model
84                 renderer_left = Gtk::CellRendererText.new
85                 @rayon_model = Gtk::TreeStore.new(Integer, String)
86                 @rayon_cb = Gtk::ComboBox.new @rayon_model
87                 @designation = Gtk::Entry.new           
88                 @description = Gtk::TextView.new        
89                 @image = Gtk::Image.new( "./resources/articles/#{@id}.png")
90                 
91                 # Propriétés
92                 @description.wrap_mode = Gtk::TextTag::WRAP_WORD
93                 @code.width_chars = 8
94                 renderer_left.xalign = 0
95                 
96                 # Agencement            
97                 vbox = Gtk::VBox.new false, 3
98                 
99                 table = Gtk::Table.new 3, 9, false
100                 
101                 table.attach( Gtk::Label.new("Code :"), 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
102                 table.attach( @code, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
103                 
104                 @groupe.pack_start renderer_left, true
105                 @groupe.add_attribute renderer_left, "text", 1
106                 table.attach( Gtk::Label.new("Groupe :"), 2, 3, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
107                 table.attach( @groupe, 3, 4, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
108                 
109                 @rayon_cb.pack_start renderer_left, true
110                 @rayon_cb.add_attribute renderer_left, "text", 1
111                 table.attach( Gtk::Label.new("Rayonnage :"), 4, 5, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
112                 table.attach( @rayon_cb, 5, 6, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
113                 
114                 table.attach( Gtk::Label.new("Désignation :"), 0, 1, 1, 2, Gtk::FILL, Gtk::FILL, 5, 5 )
115                 table.attach( @designation, 1, 8, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 5, 5 )                
116                 
117                 table.attach( @image, 8, 9, 0, 3, Gtk::FILL, Gtk::FILL, 5, 5 )
118                 
119                 vbox.pack_start table, false, false, 3
120                 
121                 hbox = Gtk::HBox.new true, 23
122                 vbox_note = Gtk::VBox.new false, 3
123                 vbox_tarifs = Gtk::VBox.new false, 3
124                 hbox.add vbox_tarifs
125                 hbox.add vbox_note
126                 
127                 align_tarifs = Gtk::Alignment.new 0, 0, 0, 0
128                 align_tarifs.add Gtk::Label.new( "Tarifs :" )
129                 vbox_tarifs.pack_start align_tarifs, false, false, 3
130                 vbox_tarifs.pack_start tableau_tarifs, true, true, 3
131                 align_stock = Gtk::Alignment.new 0, 0, 0, 0
132                 align_stock.add Gtk::Label.new( "Stock :" )
133                 vbox_tarifs.pack_start align_stock, false, false, 3
134                 vbox_tarifs.pack_start tableau_stock, true, true, 3
135                 bouton_stock = Gtk::Button.new "Transaction manuelle"
136                 #vbox_tarifs.pack_start bouton_stock, false, false, 3
137                 
138                 scroll_desc = Gtk::ScrolledWindow.new
139                 scroll_desc.add @description
140                 scroll_desc.set_policy Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC
141                 scroll_desc.shadow_type = Gtk::SHADOW_IN
142                 
143                 align_desc = Gtk::Alignment.new 0, 0, 0, 0
144                 align_desc.add Gtk::Label.new( "Description :" )
145                 
146                 vbox_note.pack_start align_desc, false, false, 3
147                 vbox_note.pack_start scroll_desc, true, true, 3
148                 
149                 vbox_note.pack_start notebook, true, true, 3
150                 
151                 vbox.pack_start hbox, true, true, 3
152                 
153                 vbox
154         
155         end
156         
157         def tableau_tarifs
158         
159                 @star = Gdk::Pixbuf.new("resources/icons/starred.png", 16, 16)
160                 @empty = Gdk::Pixbuf.new("resources/icons/empty.png", 16, 16)
161                 @iter_pa = nil
162                 @iter_cr = nil
163                 
164                 # list_store (tarif_id, designation_tarif, tarif, id, Etoile, vente, marge, marge%, marge_defaut)
165                 @list_store = Gtk::ListStore.new(Integer, String, String, Integer, Gdk::Pixbuf, Integer, String, String, Float)
166                 @view = Gtk::TreeView.new(@list_store)
167                 
168                 @view.signal_connect ("button-release-event") { |tree,event|
169                         # Si clic gauche et clic sur colonne étoile
170                         e = @view.get_path_at_pos(event.x, event.y)
171                         if (e and event.button.eql?(1))
172                                 colonne = e[1]
173                                 if colonne.eql?(@view.get_column(4))
174                                         l = @list_store.get_iter(e[0])
175                                         l[7] = "%.2f" % l[8]
176                                         calcule_pu l, true
177                                         calcule_marge
178                                 end
179                         end
180                 }
181                 
182                 renderer_left = Gtk::CellRendererText.new
183                 renderer_left.background = "white"
184                 renderer_left.xalign = 0
185                 renderer_right = Gtk::CellRendererText.new
186                 renderer_right.background = "white"
187                 renderer_right.xalign = 1
188                 
189                 col = Gtk::TreeViewColumn.new("Type de tarif", renderer_left, :text => 1)
190                 col.resizable = true
191                 col.expand = true
192                 @view.append_column(col)
193                 
194                 # Colonne pour le PU :
195                 renderer_pu = Gtk::CellRendererSpin.new
196                 renderer_pu.adjustment = Gtk::Adjustment.new(0, 0, 999999, 0.1, 10, 0)
197                 renderer_pu.digits = 2
198                 renderer_pu.xalign = 1
199                 renderer_pu.mode = Gtk::CellRendererText::MODE_EDITABLE
200                 renderer_pu.editable = true
201                 renderer_pu.signal_connect('edited') { |spin, data, text|
202                         l=@view.model.get_iter(data)
203                         l[2] = "%.2f" % text
204                         calcule_cr
205                         #calcule_pu l, true
206                         calcule_marge
207                 } 
208                 col = Gtk::TreeViewColumn.new("Prix unitaire (€)", renderer_pu, :text => 2)
209                 col.resizable = true
210                 @view.append_column(col)
211                 
212                 renderer_marge = Gtk::CellRendererSpin.new
213                 renderer_marge.adjustment = Gtk::Adjustment.new(0, 0, 999999, 0.1, 10, 0)
214                 renderer_marge.digits = 2
215                 renderer_marge.xalign = 1
216                 renderer_marge.mode = Gtk::CellRendererText::MODE_EDITABLE
217                 renderer_marge.editable = true
218                 renderer_marge.signal_connect('edited') { |spin, data, text|
219                         l = @view.model.get_iter(data)
220                         if l[5].eql?(1) then
221                                 l[6] = "%.2f" % text
222                                 calcule_pu l
223                                 calcule_marge
224                         end
225                 } 
226                 col = Gtk::TreeViewColumn.new("Marge (€)", renderer_marge, :text => 6)
227                 col.resizable = true
228                 @view.append_column(col)
229                 
230                 renderer_margep = Gtk::CellRendererSpin.new
231                 renderer_margep.adjustment = Gtk::Adjustment.new(0, 0, 999999, 0.1, 10, 0)
232                 renderer_margep.digits = 2
233                 renderer_margep.xalign = 1
234                 renderer_margep.mode = Gtk::CellRendererText::MODE_EDITABLE
235                 renderer_margep.editable = true
236                 renderer_margep.signal_connect('edited') { |spin, data, text|
237                         l = @view.model.get_iter(data)
238                         if l[5].eql?(1) then
239                                 l[7] = "%.2f" % text
240                                 calcule_pu l, true
241                                 calcule_marge
242                         end
243                 } 
244                 col = Gtk::TreeViewColumn.new("Marge (%)", renderer_margep, :text => 7)
245                 col.resizable = true
246                 @view.append_column(col)
247                 
248                 renderer_pix = Gtk::CellRendererPixbuf.new              
249                 col = Gtk::TreeViewColumn.new("", renderer_pix, :pixbuf => 4)
250                 @view.append_column(col)
251                 
252                 scroll = Gtk::ScrolledWindow.new
253         scroll.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
254         scroll.add @view
255         
256         scroll
257         
258         end
259         
260         def tableau_stock
261         
262                 # list_stock (id, designation_stock, n°lot, qtite, couleur)
263                 @list_stock = Gtk::ListStore.new(Integer, String, String, String, Float, String)
264                 @view_stock = Gtk::TreeView.new(@list_stock)
265                 
266                 # Create a renderer with the background property set
267                 renderer_left = Gtk::CellRendererText.new
268                 renderer_left.background = "white"
269                 renderer_left.xalign = 0
270                 
271                 # Create a renderer with the background property set
272                 renderer_right = Gtk::CellRendererText.new
273                 renderer_right.background = "white"
274                 renderer_right.xalign = 1
275                 
276                 col = Gtk::TreeViewColumn.new("Stock", renderer_left, :text => 1, :background => 5)
277                 col.resizable = true
278                 col.expand = true
279                 @view_stock.append_column(col)
280                 
281                 col = Gtk::TreeViewColumn.new("N° Lot/Série", renderer_right, :text => 2, :background => 5)
282                 col.resizable = true
283                 @view_stock.append_column(col)
284                 
285                 col = Gtk::TreeViewColumn.new("Quantité", renderer_right, :text => 3, :background => 5)
286                 col.resizable = true
287                 @view_stock.append_column(col)
288                 
289                 scroll = Gtk::ScrolledWindow.new
290         scroll.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
291         scroll.add @view_stock
292         
293         scroll
294         
295         end
296         
297         def notebook
298         
299                 # Objets        
300                 @note = Gtk::TextView.new
301                 @etiquette = Gtk::CheckButton.new "Etiquette à refaire"
302                 @lot = Gtk::CheckButton.new "Article géré par lot ou série ?"
303                 @service = Gtk::CheckButton.new "Service (sinon produit)"
304                 @en_vente = Gtk::CheckButton.new "Article en vente ?"
305                 @en_achat = Gtk::CheckButton.new "Article en achat ?"
306                 @colisage = Gtk::SpinButton.new 0, MAX_SPIN, 1
307                 renderer_left = Gtk::CellRendererText.new
308                 @tva_model = Gtk::TreeStore.new(Integer, String)
309                 @tva_cb = Gtk::ComboBox.new @tva_model
310                 @gencode = Gtk::Entry.new
311                 @gencode2 = Gtk::Entry.new
312                 @ged = Ged_box.new @window, "articles"
313                 @annee = Gtk::ComboBox.new
314                 
315                 # Conteneurs
316                 notebook = Gtk::Notebook.new
317                 scroll_note = Gtk::ScrolledWindow.new
318                 table_carac = Gtk::Table.new 2, 4, false
319                 table_vente = Gtk::Table.new 2, 4, false
320                 table_achat = Gtk::Table.new 2, 4, false
321                 scroll_carac = Gtk::ScrolledWindow.new
322                 scroll_vente = Gtk::ScrolledWindow.new
323                 scroll_achat = Gtk::ScrolledWindow.new
324                 scroll_stat = Gtk::ScrolledWindow.new
325                 hbox_stat = Gtk::HBox.new false, 2
326                 vbox_stat = Gtk::VBox.new false, 2
327
328                 # Propriétés des objets
329                 @note.wrap_mode = Gtk::TextTag::WRAP_WORD
330                 scroll_note.set_policy Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC
331                 scroll_note.shadow_type = Gtk::SHADOW_NONE
332                 scroll_carac.set_policy Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC
333                 scroll_carac.shadow_type = Gtk::SHADOW_NONE
334                 scroll_vente.set_policy Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC
335                 scroll_vente.shadow_type = Gtk::SHADOW_NONE
336                 scroll_achat.set_policy Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC
337                 scroll_achat.shadow_type = Gtk::SHADOW_NONE
338                 scroll_stat.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
339                 @colisage.width_chars = 8 
340                 @gencode2.width_chars = 13
341                 @gencode2.width_chars = 13
342                 remplir_annee
343                 @annee.active = 0
344                 @annee.signal_connect('changed') {
345                         graphique if @activer_combo
346                 }
347                 @service.signal_connect('toggled') {
348                         if @service.active?
349                                 @lot.active = false 
350                                 @lot.sensitive = false
351                         else
352                                 @lot.sensitive = true
353                         end
354                 }
355                 
356                 # Agencement du conteneur Caractéristique
357                 table_carac.attach( @service, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
358                 table_carac.attach( @lot, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 5, 5 )
359                 table_carac.attach( @etiquette, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL, 5, 5 )
360                 table_carac.attach( Gtk::Label.new("Code barre 1 :") , 0, 1, 2, 3, Gtk::FILL, Gtk::FILL, 5, 5 )
361                 table_carac.attach( @gencode, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 5, 5 )
362                 table_carac.attach( Gtk::Label.new("Code barre 2 :") , 0, 1, 3, 4, Gtk::FILL, Gtk::FILL, 5, 5 )
363                 table_carac.attach( @gencode2, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 5, 5 )
364                 scroll_carac.add_with_viewport table_carac
365                 
366                 # Agencement du conteneur Achat
367                 table_achat.attach( @en_achat , 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
368                 scroll_achat.add_with_viewport table_achat
369                 
370                 # Agencement du conteneur Vente
371                 table_vente.attach( @en_vente , 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
372                 table_vente.attach( Gtk::Label.new("Colisage lors de la vente :") , 0, 1, 1, 2, Gtk::FILL, Gtk::FILL, 5, 5 )
373                 table_vente.attach( @colisage, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 5, 5 )
374                 @tva_cb.pack_start renderer_left, true
375                 @tva_cb.add_attribute renderer_left, "text", 1
376                 table_vente.attach( Gtk::Label.new("TVA lors de la vente :") , 0, 1, 2, 3, Gtk::FILL, Gtk::FILL, 5, 5 )
377                 table_vente.attach( @tva_cb, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 5, 5 )
378                 scroll_vente.add_with_viewport table_vente
379                 
380                 # Agencement du conteneur Note
381                 scroll_note.add @note
382                 
383                 # Agencement du conteneur Stat
384                 vbox_stat.pack_start hbox_stat, false, false, 3
385                 vbox_stat.pack_start scroll_stat, true, true, 3
386                 hbox_stat.pack_start Gtk::Label.new("Annéee :"), false, false, 3
387                 hbox_stat.pack_start @annee, false, false, 3
388                 scroll_stat.add_with_viewport @graph
389                 
390                 # Agencement du notebook
391                 notebook.append_page scroll_carac, Gtk::Label.new("Caractéristiques")
392                 notebook.append_page scroll_achat, Gtk::Label.new("Achat")
393                 notebook.append_page scroll_vente, Gtk::Label.new("Vente")
394                 notebook.append_page scroll_note, Gtk::Label.new("Note")
395                 notebook.append_page @ged, Gtk::Label.new("GED")
396                 notebook.append_page vbox_stat, Gtk::Label.new("Stats")
397
398                 # Renvoie
399                 notebook
400                 
401         end
402         
403         def refresh id=0
404         
405                 @id = id
406                 @code.text = ""
407                 @gencode.text = ""
408                 @gencode2.text = ""
409                 @designation.text = ""
410                 @colisage.value = 1
411                 @note.buffer.text = ""
412                 @article = nil
413                 
414                 if id>0 then
415                         @frame.label = "Article n° " + id.to_s
416                         #@lot.sensitive = false
417                         @article = Article.find(id)
418                         if @article then
419                                 @code.text = @article.code
420                                 @code.sensitive = false
421                                 @gencode.text = @article.gencode
422                                 @gencode2.text = @article.gencode2
423                                 @designation.text = @article.designation
424                                 @colisage.value = @article.colisage
425                                 @note.buffer.text = @article.note
426                                 @description.buffer.text = @article.description
427
428                                 remplir_rayons @article.rayon_id
429                                 remplir_tva @article.tva_id
430                                 remplir_groupe @article.articlegroupe_id
431                                 @etiquette.active = @article.refaire_etiquette
432                                 @en_vente.active = @article.vente
433                                 @en_achat.active = @article.achat
434                                 @service.active = @article.service
435                                 @lot.active = @article.lot
436                                 @lot.sensitive = !@article.service
437                                 @service.sensitive = false
438                         else
439                                 MessageController.erreur @window,  @article.error
440                         end
441                         remplir_tarifs
442                         calcule_marge
443                         remplir_stock unless @article.service
444                         @ged.refresh @id
445                 else
446                         @frame.label = "Nouvel article"
447                         @lot.sensitive = true
448                         @lot.active = false
449                         @article = Article.new
450                         @code.sensitive = true
451                         remplir_rayons
452                         remplir_tva
453                         remplir_groupe
454                         @en_vente.active = true
455                         @en_achat.active = true
456                         @service.active = false
457                         @service.sensitive = true
458                         @description.buffer.text = ""
459                         
460                         tarifs = Tarif.order("id")      
461                         
462                         @list_stock.clear
463                         
464                         remplir_tarifs
465                         
466                 end
467                 
468                 graphique
469                 
470                 if File.exist?("./resources/articles/#{@id}.png") then
471                         @image.file = "./resources/articles/#{@id}.png"
472                 else
473                         @image.clear
474                 end
475         
476         end
477         
478         def graphique
479         
480                 combo_sensitive false
481
482                 serie = graph_donnees
483                 couleur = [[0.65,1,0.65],[1,0.65,0.65]]
484                 legende = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"]
485                 Thread.new { 
486                         @graph.refresh(serie, couleur, legende, ["","unité(s)"])
487                         @activer_combo = true
488                         combo_sensitive true
489                 }
490         
491         end
492         
493         def graph_donnees
494                 
495                 serie0 = []
496                 serie1 = []
497                 
498                 annee = @annee.active_text.to_i
499                 
500                 [4,8].each do |type|
501                 
502                         req =   "               SELECT EXTRACT(MONTH FROM t1.date_document) AS mois, SUM(t0.qtite) AS total
503                                                                         FROM documentlignes t0 INNER JOIN documents t1 ON t0.document_id=t1.id
504                                                                         WHERE t0.article_id=#{@id} AND t1.documenttype_id=#{type}
505                                                                         AND EXTRACT(YEAR FROM t1.date_document)=#{annee}
506                                                                         AND t0.suppr=false
507                                                                         GROUP BY mois
508                                                                         ORDER BY mois
509                                                         "               
510                 
511                         res = Documentligne.find_by_sql(req)
512
513                         (1..12).to_a.each { |m|
514                 
515                                 mois_rempli = false
516                         
517                                 res.each { |r|
518                                         if r.mois.to_i.eql?(m)
519                                                 if type.eql?(4)
520                                                         serie0 << r.total.to_f
521                                                 else
522                                                         serie1 << r.total.to_f
523                                                 end
524                                                 mois_rempli = true
525                                         end
526                                 }
527                                 
528                                 if type.eql?(4)
529                                         serie0 << 0.0 unless mois_rempli
530                                 else
531                                         serie1 << 0.0 unless mois_rempli
532                                 end
533                         
534                         }
535                 
536                 end
537                 
538                 serie = []
539                 serie0.count.times do |i|
540                         serie << [serie0[i],serie1[i]]
541                 end
542                 
543                 return serie
544
545         end
546         
547         def remplir_annee
548                 
549                 doc = Document.find_by_sql("SELECT MIN(date_document) AS min, MAX(date_document) AS max FROM documents").first
550                 if doc.min and doc.max
551                         min = doc.min.year
552                         max = doc.max.year
553                         (min..max).to_a.reverse.each do |a|
554                                 @annee.append_text a.to_s
555                         end
556                 end
557                 
558         end
559         
560         def remplir_tarifs
561                 
562                 tarifs = Tarif.order("vente DESC", :id)
563                 
564                 @list_store.clear       
565                 
566                 if tarifs then
567                         tarifs.each { |t|
568                                 
569                                 iter = @list_store.append
570                                 iter[0] = t.id
571                                 iter[1] = t.designation
572                                 iter[4] = t.vente ? @star : @empty
573                                 iter[5] = t.vente ? 1 : 0
574                                 iter[8] = t.vente ? t.marge : 0
575                                 at = Articletarif.where(:article_id => @article.id, :tarif_id => t.id).first
576                                 if at then
577                                         iter[2] = "%.2f" % at.pu
578                                         iter[3] = at.id
579                                         iter[6] = "%.2f" % at.marge.to_f unless at.marge.eql?(0.0)
580                                 else
581                                         iter[2] = "%.2f" % 0.0
582                                         iter[3] = -1
583                                 end             
584                                 @iter_pa = iter if t.pa
585                                 @iter_cr = iter if t.cr
586                         } 
587                 else
588                         MessageController.erreur @window,  tarifs.error
589                 end
590
591         end
592         
593         def calcule_cr
594                 @iter_cr[2] = "%.2f" % @iter_pa[2].to_f if @iter_pa[2].to_f>@iter_cr[2].to_f
595         end
596         
597         def calcule_marge
598         
599                 cr = @iter_cr[2].to_f
600                 # Pour chaque tarifs
601                 @list_store.each { |model, path, iter|          
602                         l = @view.model.get_iter(path)
603                         l[6] = "%.2f" % (l[2].to_f-cr) if l[5].eql?(1)
604                         l[7] = "%.2f" % (((l[2].to_f/cr)-1)*100) if l[5].eql?(1)
605                 }
606         
607         end
608         
609         def calcule_pu l, pourcentage=false
610                 
611                 # On procède au calcul du PU
612                 if pourcentage then
613                         m = (l[7].to_f/100) + 1
614                         l[2] = "%.2f" % (m*@iter_cr[2].to_f)
615                 else
616                         l[2] = "%.2f" % (@iter_cr[2].to_f+l[6].to_f)
617                 end
618         
619         end
620         
621         def remplir_stock
622         
623                 stocks = Articlestock.includes(:stock).where(:article_id => @article.id)
624                 
625                 @list_stock.clear
626                 
627                 total = 0.0
628                 
629                 if stocks then
630                         stocks.each { |s|
631                                 if s.qtite>0
632                                         iter = @list_stock.append
633                                         iter[0] = s.id
634                                         iter[1] = s.stock.designation
635                                         iter[2] = s.lot
636                                         iter[3] = "%.3f" % s.qtite
637                                         iter[5] = "#ffffff"
638                                         total += s.qtite
639                                 end
640                         } 
641                         iter = @list_stock.append
642                         iter[1] = "Total"
643                         iter[2] = ""
644                         iter[3] = "%.3f" % total
645                         iter[5] = "#eeeeee"
646                 else
647                         MessageController.erreur @window,  stocks.error
648                 end
649
650         end
651         
652         def remplir_rayons nom=nil
653                 
654                 @rayon_model.clear
655                 
656                 rayons = Rayon.order(:nom)
657                                 
658                 if rayons then
659                         i=0
660                         id=-1
661                         rayons.each do |rayon|
662                                 iter = @rayon_model.append nil
663                                 iter[0] = rayon.id
664                                 iter[1] = rayon.nom
665                                 if !nom.nil? then 
666                                         id = i if nom.eql?(rayon.id) 
667                                 end
668                                 i += 1
669                         end
670                         @rayon_cb.active = ( nom.nil? ? -1 : id )
671                 else
672                         MessageController.erreur @window,  rayons.error
673                 end
674                 
675         end
676         
677         def remplir_tva nom=nil
678                 
679                 @tva_model.clear
680                 
681                 tvas = Tva.order(:id)
682                 
683                 if tvas then
684                         i=0
685                         id=-1
686                         tvas.each do |tva|
687                                 iter = @tva_model.append nil
688                                 iter[0] = tva.id
689                                 iter[1] = tva.designation
690                                 if !nom.nil? then id = i if nom.eql?(tva.id) end
691                                 i += 1
692                         end
693                 
694                         @tva_cb.active = ( nom.nil? ? 0 : id )
695                 else
696                         MessageController.erreur @window,  tvas.error
697                 end
698                 
699         end
700         
701         def remplir_groupe nom=nil
702                 
703                 @groupe.model.clear
704                 
705                 groupesp = Articlegroupe.order(:designation)
706                 
707                 if groupesp then
708                         active_iter = nil
709                         groupesp.each do |gr|
710                                 if gr.parent_id.eql?(0)
711                                         iter = @groupe_model.append nil
712                                         iter[0] = gr.id
713                                         iter[1] = gr.designation        
714                                         if !nom.nil?
715                                                 active_iter = iter if nom.eql?(gr.id)           
716                                         end                                             
717                                         groupesp.each do |gr2|
718                                                 if gr2.parent_id.eql?(gr.id)
719                                                         iter2 = @groupe_model.append iter
720                                                         iter2[0] = gr2.id.to_i
721                                                         iter2[1] = gr2.designation
722                                         
723                                                         if !nom.nil?
724                                                                 active_iter = iter2 if nom.eql?(gr2.id)         
725                                                         end     
726                                                 end
727                                         end
728                                 end
729                         end
730                 
731                         if !active_iter.nil? then @groupe.active_iter = active_iter end
732                 else
733                         MessageController.erreur @window,  groupesp.error
734                 end
735                 
736         end
737         
738         def validate quitter=true
739                 
740                 # Vérification d'erreurs
741                 res = false
742                 error = ""
743                 if !(@id>0) then
744                         if @code.text.empty? then
745                                 error += "Vous devez saisir un code pour cet article\n"
746                         else
747                                 error += "Le code article saisi existe déjà. Veuillez en saisir un autre.\n" if Article.where("code ILIKE ?", @code.text).count>0
748                         end
749                 end
750                 error += @designation.text.empty? ? "Vous devez saisir une désignation pour cet article\n" : ""
751                 
752                 # Si pas d'erreurs on continue
753                 if error.empty? then
754
755                         date_modif = Date.today.strftime("%Y-%m-%d")
756                         groupe = @groupe.active_iter.nil? ? 0 : @groupe_model.get_value(@groupe.active_iter,0)
757                         rayon = @rayon_model.get_value(@rayon_cb.active_iter,0) unless @rayon_cb.active_iter.nil?
758                         tva = @tva_cb.active_iter.nil? ? 0 : @tva_model.get_value(@tva_cb.active_iter,0)
759                 
760                         # sauvegarde des données de l'article
761                         @article.designation = @designation.text
762                         @article.colisage = @colisage.value.round
763                         @article.tva_id = tva
764                         @article.code = @code.text
765                         @article.gencode = @gencode.text
766                         @article.gencode2 = @gencode2.text
767                         @article.description = @description.buffer.text
768                         @article.note = @note.buffer.text
769                         @article.rayon_id = rayon
770                         @article.refaire_etiquette = @etiquette.active?
771                         @article.lot = @lot.active?
772                         @article.date_modif = date_modif
773                         @article.achat = @en_achat.active?
774                         @article.vente = @en_vente.active?
775                         @article.service = @service.active?
776                         @article.articlegroupe_id = groupe
777
778                         res = @article.save
779                 
780                         if res then
781                 
782                                 @list_store.each { |model, path, iter|          
783                                         pu = @view.model.get_iter(path)[2]
784                                         tarif_id = @view.model.get_iter(path)[0]
785                                         id = @view.model.get_iter(path)[3]
786                                         marge = @view.model.get_iter(path)[6].nil? ? 0 : @view.model.get_iter(path)[6]
787                                 
788                                         if id>0 then
789                                                 tarif = Articletarif.find(id)
790                                         else
791                                                 tarif = Articletarif.new
792                                         end
793                                         tarif.tarif_id = tarif_id
794                                         tarif.article_id = @article.id                                                          
795                                         tarif.pu = pu
796                                         tarif.marge = marge
797                                         tarif.save      
798                                 }
799                 
800                         end
801                 
802                         quit if (!@dial and quitter)
803                 
804                 else
805                         MessageController.erreur @window,  error
806                 end
807                 return res
808         
809         end
810         
811         def combo_sensitive status
812                 @annee.sensitive = status
813         end
814         
815         def focus
816                 @annuler.grab_focus
817         end
818         
819         def supprimer
820         
821                 if MessageController.question_oui_non @window, "Voulez-vous réellement supprimer cet article ?"
822                                 @article.suppr = true
823                                 res = @article.save
824                                 quit
825                 end 
826         
827         end
828         
829         def quit
830         
831                 @window.liste_articles.refresh
832                 @window.affiche @window.liste_articles
833                 @window.liste_articles.focus
834         
835         end
836         
837 end
838