Quantité dans les lignes de documents passée en float et plus en integer
[bilio:bilio.git] / src / document.rb
1 # coding: utf-8
2
3 class Document_box < Gtk::VBox
4
5         def initialize window
6         
7                 super(false, 3)
8                 
9                 set_border_width 10
10                 
11                 @window = window
12                 @login = window.login
13                 
14                 @id = 0
15                 @type = 0
16                 @mail = ""
17                 
18                 @ligne_modif_id = []
19                 @ligne_supp_id = []
20                 
21                 @imprimer = Gtk::Button.new
22                 hbox_imprimer = Gtk::HBox.new false, 2
23                 hbox_imprimer.add Gtk::Image.new( "./resources/icons/print.png" )
24                 hbox_imprimer.add Gtk::Label.new "Imprimer"
25                 @imprimer.add hbox_imprimer
26                 
27                 @valider = Gtk::Button.new
28                 hbox_valider = Gtk::HBox.new false, 2
29                 hbox_valider.add Gtk::Image.new( "./resources/icons/ok.png" )
30                 hbox_valider.add Gtk::Label.new "Valider"
31                 @valider.add hbox_valider
32                 
33                 @annuler = Gtk::Button.new
34                 hbox_annuler = Gtk::HBox.new false, 2
35                 hbox_annuler.add Gtk::Image.new( "./resources/icons/cancel.png" )
36                 hbox_annuler.add Gtk::Label.new "Annuler"
37                 @annuler.add hbox_annuler
38                 
39                 @transfert = Gtk::Button.new
40                 hbox_transfert = Gtk::HBox.new false, 2
41                 hbox_transfert.add Gtk::Image.new( "./resources/icons/transfert.png" )
42                 hbox_transfert.add Gtk::Label.new "Transférer"
43                 @transfert.add hbox_transfert
44                 
45                 @email = Gtk::Button.new
46                 hbox_email = Gtk::HBox.new false, 2
47                 hbox_email.add Gtk::Image.new( "./resources/icons/transfert.png" )
48                 hbox_email.add Gtk::Label.new "Email"
49                 @email.add hbox_email
50                 
51                 agencement
52                 
53                 @valider.signal_connect( "clicked" ) { validate }
54                 @annuler.signal_connect( "clicked" ) { quit }
55                 @imprimer.signal_connect( "clicked" ) { imprimer }
56                 @transfert.signal_connect("clicked") { transfert }
57                 @email.signal_connect("clicked") { mailer }
58         
59         end
60         
61         def agencement
62         
63                 vbox = Gtk::VBox.new false, 3
64                 @frame = Gtk::Frame.new
65                 @frame.label = "Nouveau document"
66                 vbox.pack_start( @frame, true, true, 3 )
67                 
68                 vbox_corps = Gtk::VBox.new false, 3
69                 @frame.add vbox_corps
70                 vbox_corps.pack_start( en_tete, false, false, 3 )
71                 vbox_corps.pack_start( lignes, true, true, 3 )
72                 vbox_corps.pack_start( pieds, false, false, 3 )
73                 
74                 hbox_button = Gtk::HBox.new false, 2
75                 hbox2 = Gtk::HBox.new false, 2
76                 hbox2.pack_start( @imprimer, true, true, 3 )
77                 hbox2.pack_start( @email, true, true, 3 )
78                 hbox2.pack_start( @transfert, true, true, 3 )
79                 hbox3 = Gtk::HBox.new false, 2
80                 align0 = Gtk::Alignment.new 0, 0, 0, 0
81                 align0.add hbox2
82                 align1 = Gtk::Alignment.new 1, 1, 0, 0
83                 hbox3.pack_start( @annuler, true, true, 3 )
84                 hbox3.pack_start( @valider, true, true, 3 )
85                 align1.add hbox3
86                 hbox_button.add align0
87                 hbox_button.add align1
88                 
89                 vbox.pack_start( hbox_button, false, false, 3 )
90                 
91                 self.add vbox
92         
93         end
94
95         def en_tete
96         
97                 # Objets
98                 @ref = ""
99                 @provenance = ""
100                 @id_client = 0
101                 @client = Gtk::Entry.new
102                 @id_tarif = 0
103                 @date_document = Gtk::Entry.new
104                 @date_livraison = Gtk::Entry.new
105                 @date_echeance = Gtk::Entry.new
106                 @label_livraison = Gtk::Label.new "Date de livraison :"
107                 @note = Gtk::TextView.new       
108                 @note_priv = Gtk::TextView.new          
109                 @tranfere = false
110                 @status = Gtk::Image.new "resources/icons/empty.png"
111                 @status.tooltip_text = ""
112                 
113                 # Propriétés
114                 @note.wrap_mode = Gtk::TextTag::WRAP_WORD
115                 @note.set_size_request(10, 60)
116                 @note_priv.wrap_mode = Gtk::TextTag::WRAP_WORD
117                 @note_priv.set_size_request(10, 60)
118                 @client.primary_icon_stock = Gtk::Stock::FIND
119                 
120                 # Agencement            
121                 table = Gtk::Table.new 6, 3, false
122                 
123                 table.attach( Gtk::Label.new("Client :"), 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
124                 table.attach( @client, 1, 4, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 5, 5 )
125                 
126                 table.attach( Gtk::Label.new("Date du document :"), 4, 5, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
127                 table.attach( @date_document, 5, 6, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
128                 
129                 table.attach( @label_livraison, 6, 7, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
130                 table.attach( @date_livraison, 7, 8, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
131                 
132                 table.attach( Gtk::Label.new("Date d'échéance :"), 8, 9, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
133                 table.attach( @date_echeance, 9, 10, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
134                 
135                 table.attach( @status, 10, 11, 0, 1, Gtk::FILL, Gtk::FILL, 5, 5 )
136                 
137                 @client.signal_connect('activate') { 
138                         chercher_tiers @client.text
139                 }
140                 
141                 @client.signal_connect('icon-press') { 
142                         chercher_tiers @client.text
143                 }
144                 
145                 #@date_document.signal_connect ("insert_text") { |entry, text| changement_condition_paiement }
146                 
147                 table
148         
149         end
150         
151         def chercher_tiers text
152                 vente = @window.type_doc[@type][:vente] ? 0 : 1
153                 search = SearchTiers.new @window, @client.text, vente
154                 search.run { |response| 
155                         if ( !search.liste.view.selection.selected.nil? ) then
156                                 @client.sensitive = false
157                                 @client.text = search.liste.view.model.get_value( search.liste.view.selection.selected, 1 )
158                                 @id_client = search.liste.view.model.get_value( search.liste.view.selection.selected, 0 )
159                                 @id_tarif = search.liste.view.model.get_value( search.liste.view.selection.selected, 8 )
160                                 @mail = search.liste.view.model.get_value( search.liste.view.selection.selected, 9 )
161                                 @email.sensitive = @mail.nil? ? false : !@mail.empty?
162                         else
163                                 @client.text = ""
164                         end
165                         search.destroy
166                         focus_dernière_ligne unless @client.sensitive?
167                 }
168         end
169         
170         def lignes
171                 
172                 # list_store (id, id_document, id_article, code, designation, qtite, id_tva, colisage, pu, remise, total_ligne, tva, tva_taux, tva_np, commentaire, lot, qtite_orig, trash)
173                 @list_store = Gtk::ListStore.new(Integer, Integer, Integer, String, String, Float, Integer, Integer, String, Integer, String, String, Float, Integer, String, String, Integer, Gdk::Pixbuf, Gdk::Pixbuf)
174                 @view = Gtk::TreeView.new(@list_store)
175                 
176                 @view.signal_connect ("button-release-event") { |tree,event|
177                         # Gestion du clic droit sur une ligne
178                         if event.button.eql?(3)
179                                 npath = @view.get_path_at_pos(@view.pointer[0], @view.pointer[1]-30)
180                                 if !npath.nil? 
181                                         @view.set_cursor(npath[0], nil, false)
182                                         menu_modifie_article
183                                 end
184                         end
185                         # Si clic gauche
186                         e = npath = @view.get_path_at_pos(@view.pointer[0], @view.pointer[1]-30)
187                         if (e and event.button.eql?(1))
188                                 colonne = e[1]
189                                 #si clic sur colonne supprimer
190                                 if colonne.eql?(@view.get_column(10))
191                                         suppr_article @list_store.get_iter(e[0])
192                                 #si clic sur colonne commentaire
193                                 elsif colonne.eql?(@view.get_column(2))
194                                         modif_commentaire @list_store.get_iter(e[0])
195                                 end
196                         end
197                 }
198                 
199                 # Create a renderer with the background property set
200                 renderer_center = Gtk::CellRendererText.new
201                 renderer_center.background = "white"
202                 renderer_center.xalign = 0.5
203                 renderer_center.yalign = 0
204                 renderer_center.mode = Gtk::CellRendererText::MODE_EDITABLE
205                 
206                 # Create a renderer with the background property set
207                 renderer_left = Gtk::CellRendererText.new
208                 renderer_left.xalign = 0
209                 renderer_left.yalign = 0
210                 renderer_left.mode = Gtk::CellRendererText::MODE_EDITABLE
211                 
212                 # Create a renderer with the background property set
213                 renderer_right = Gtk::CellRendererText.new
214                 renderer_right.xalign = 1
215                 renderer_right.yalign = 0
216                 renderer_right.mode = Gtk::CellRendererText::MODE_EDITABLE
217                 
218                 # Create a renderer with the background property set
219                 renderer_right_bold = Gtk::CellRendererText.new
220                 renderer_right_bold.xalign = 1
221                 renderer_right_bold.yalign = 0
222                 renderer_right_bold.mode = Gtk::CellRendererText::MODE_EDITABLE
223                 renderer_right_bold.background = "#eee"
224                 
225                 # Colonne pour le code article :
226                 renderer_code = Gtk::CellRendererText.new
227                 renderer_code.xalign = 0
228                 renderer_code.yalign = 0
229                 renderer_code.mode = Gtk::CellRendererText::MODE_EDITABLE
230                 renderer_code.editable = true
231                 renderer_code.signal_connect('edited') { |combo, data, text|
232                         if !text.eql?(@list_store.get_iter(data)[3])
233                                 #edit_cell(data, text, 3) 
234                                 ajout = add_article text, true
235                                 # on passe ou on reste à la ligne
236                                 focus_dernière_ligne if ajout
237                         end
238                 }  
239                 col = Gtk::TreeViewColumn.new("Code article", renderer_code, :text => 3)
240                 col.resizable = true
241                 @view.append_column(col)
242                 
243                 # Colonne pour la quantité :
244                 renderer_designation = Gtk::CellRendererText.new
245                 renderer_designation.xalign = 0
246                 renderer_designation.mode = Gtk::CellRendererText::MODE_EDITABLE
247                 renderer_designation.editable = true
248                 renderer_designation.signal_connect('edited') { |combo, data, text|
249                         if (!text.empty? and !text.eql?(@list_store.get_iter(data)[4])) then
250                                 search = SearchArticles_box.new @window, text
251                                 search.run { |response| 
252                                         code = nil
253                                         if ( !search.liste.view.selection.selected.nil? and response.eql?(-5) )
254                                                 code = search.liste.view.model.get_value( search.liste.view.selection.selected, 1 )
255                                         end
256                                         search.destroy
257                                         add_article code, true unless code.nil?
258                                 }
259                         end
260                 }  
261                 col = Gtk::TreeViewColumn.new("Désignation", renderer_designation, :text => 4)
262                 col.resizable = true
263                 col.expand = true
264                 @view.append_column(col)
265                 
266                 renderer_commentaires = Gtk::CellRendererText.new
267                 renderer_commentaires.xalign = 0
268                 renderer_commentaires.yalign = 0
269                 renderer_commentaires.mode = Gtk::CellRendererText::MODE_EDITABLE
270                 renderer_commentaires.editable = false
271                 renderer_commentaires.signal_connect('editing-started') { |cellrenderer, entry, data|
272                         #edit_cell(data, text, 14)
273                         
274                 }  
275                 col = Gtk::TreeViewColumn.new("Commentaires", renderer_commentaires, :text => 14)
276                 col.resizable = true
277                 col.expand = true
278                 @view.append_column(col)
279                 
280                 # Colonne pour le commentaire
281                 @pix_comm = Gdk::Pixbuf.new("resources/icons/saisie.png", 20, 20)
282                 renderer_pix = Gtk::CellRendererPixbuf.new              
283                 renderer_pix.xalign = 0.5
284                 renderer_pix.yalign = 0
285                 col = Gtk::TreeViewColumn.new("", renderer_pix, :pixbuf => 18)
286                 #@view.append_column(col)
287                 
288                 col = Gtk::TreeViewColumn.new("Lot / Série", renderer_left, :text => 15)
289                 col.resizable = true
290                 col.expand = true
291                 @view.append_column(col)
292                 
293                 # Colonne pour la quantité :
294                 renderer_qtite = Gtk::CellRendererSpin.new
295                 renderer_qtite.adjustment = Gtk::Adjustment.new(0, 0, 999999, 1, 10, 0)
296                 renderer_qtite.digits = 2
297                 renderer_qtite.xalign = 1
298                 renderer_qtite.yalign = 0
299                 renderer_qtite.mode = Gtk::CellRendererText::MODE_EDITABLE
300                 renderer_qtite.editable = true
301                 renderer_qtite.signal_connect('edited') { |combo, data, text|
302                         edit_cell(data, text, 5)
303                 } 
304                 col = Gtk::TreeViewColumn.new("Quantité", renderer_qtite, :text => 5)
305                 #col.sort_column_id = 5
306                 col.resizable = true
307                 @view.append_column(col)
308                 
309                 # Colonne pour le colisage :
310                 renderer_colisage = Gtk::CellRendererSpin.new
311                 renderer_colisage.adjustment = Gtk::Adjustment.new(0, 0, 999999, 1, 10, 0)
312                 renderer_colisage.xalign = 1
313                 renderer_colisage.yalign = 0
314                 renderer_colisage.mode = Gtk::CellRendererText::MODE_EDITABLE
315                 renderer_colisage.editable = true
316                 renderer_colisage.signal_connect('edited') { |combo, data, text|
317                         edit_cell(data, text, 7)
318                 } 
319                 col = Gtk::TreeViewColumn.new("Colisage", renderer_colisage, :text => 7)
320                 col.resizable = true
321                 @view.append_column(col)
322                 
323                 # Colonne pour le PU :
324                 renderer_pu = Gtk::CellRendererSpin.new
325                 renderer_pu.adjustment = Gtk::Adjustment.new(0, 0, 999999, 1, 10, 0)
326                 renderer_pu.digits = 2
327                 renderer_pu.xalign = 1
328                 renderer_pu.yalign = 0
329                 renderer_pu.mode = Gtk::CellRendererText::MODE_EDITABLE
330                 renderer_pu.editable = true
331                 renderer_pu.signal_connect('edited') { |combo, data, text|
332                         edit_cell(data, text, 8)
333                 } 
334                 col = Gtk::TreeViewColumn.new("Prix unitaire", renderer_pu, :text => 8)
335                 #col.sort_column_id = 8
336                 col.resizable = true
337                 @view.append_column(col)
338                 
339                 # Colonne pour la remise :
340                 renderer_remise = Gtk::CellRendererSpin.new
341                 renderer_remise.adjustment = Gtk::Adjustment.new(0, 0, 100, 1, 10, 0)
342                 renderer_remise.xalign = 1
343                 renderer_remise.yalign = 0
344                 renderer_remise.mode = Gtk::CellRendererText::MODE_EDITABLE
345                 renderer_remise.editable = true
346                 renderer_remise.signal_connect('edited') { |combo, data, text|
347                         edit_cell(data, text, 9)
348                 } 
349                 col = Gtk::TreeViewColumn.new("Remise %", renderer_remise, :text => 9)
350                 col.resizable = true
351                 @view.append_column(col)
352                 
353                 col = Gtk::TreeViewColumn.new("Total ligne", renderer_right_bold, :text => 10)
354                 col.resizable = true
355                 @view.append_column(col)
356                 
357                 renderer_tva = Gtk::CellRendererCombo.new
358                 renderer_tva.xalign = 1
359                 renderer_tva.yalign = 0
360                 renderer_tva.editable = true            
361                 renderer_tva.model = modele_tva
362                 renderer_tva.text_column = 1
363                 renderer_tva.signal_connect('edited') { |combo, data, text|
364                         edit_cell(data, text, 11)
365                 } 
366                 col = Gtk::TreeViewColumn.new("TVA", renderer_tva, :text => 11)
367                 col.resizable = true
368                 @view.append_column(col)
369                 
370                 # Colonne pour la corbeille
371                 @pix_trash = Gdk::Pixbuf.new("resources/icons/trash-full.png", 20, 20)
372                 col = Gtk::TreeViewColumn.new("", renderer_pix, :pixbuf => 17)
373                 @view.append_column(col)
374                 
375                 scroll = Gtk::ScrolledWindow.new
376         scroll.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
377         scroll.add @view
378         
379         scroll
380         
381         end
382         
383         def modif_commentaire ligne
384                 if possible_modif?
385                         mod = DialCommentaire.new @window, ligne[14]
386                         mod.run { |response| 
387                                 text = ""
388                                 modif = false
389                                 if response.eql?(-5)
390                                         text = mod.memo.buffer.text
391                                         modif = true
392                                 end
393                                 mod.destroy
394                                 ajout_commentaire ligne, text if modif
395                         }
396                 end
397         end
398         
399         def ajout_commentaire ligne, text
400                 ligne[14] = text
401                 @ligne_modif_id << ligne[0] unless @ligne_modif_id.include?(ligne[0])
402                 ligne[17] = @pix_trash
403                 ligne[6] = 1 if ligne[6].eql?(0) # taux de tva à 0%
404                 # On détermine le nombre de lignes
405                 i = -1
406                 @list_store.each { i += 1 }
407                 n = @view.selection.selected.path.to_s.to_i
408                 # Nouvelle ligne si on est sur une ligne de commentaire seul
409                 if (ligne[2].eql?(0) and i.eql?(n))
410                         iter = @list_store.append
411                         iter[18] = @pix_comm
412                 end             
413                 
414         end
415         
416         def modele_tva
417                 tvas = Tva.order(:id)
418                 tva_model = Gtk::ListStore.new(Integer, String, Float)
419                 tvas.each { |tva|
420                         iter = tva_model.append
421                         iter[0] = tva.id
422                         iter[1] = tva.designation
423                         iter[2] = tva.taux
424                 }       
425                 tva_model       
426         end
427         
428         def pieds
429         
430                 @ht = Gtk::Entry.new
431                 @tva = Gtk::Entry.new
432                 @ttc = Gtk::Entry.new
433                 @a_payer = Gtk::Entry.new
434                 
435                 @ht.editable = @tva.editable = @ttc.editable = @a_payer.editable = false
436                 @ht.width_chars = @tva.width_chars = @ttc.width_chars = @a_payer.width_chars = 8
437                 @ht.xalign = @tva.xalign = @ttc.xalign = @a_payer.xalign = 1
438                 
439                 @regler = Gtk::Button.new
440                 hbox_regler = Gtk::HBox.new false, 2
441                 hbox_regler.add Gtk::Image.new( "./resources/icons/document-send.png" )
442                 hbox_regler.add Gtk::Label.new "Régler"
443                 @regler.add hbox_regler
444                 @regler.signal_connect("clicked") { regler }
445                 
446                 @scan = Gtk::Button.new
447                 hbox_scan = Gtk::HBox.new false, 2
448                 hbox_scan.add Gtk::Image.new( "./resources/icons/scanner.png" )
449                 hbox_scan.add Gtk::Label.new "Scanner"
450                 @scan.add hbox_scan
451                 @scan.signal_connect("clicked") { scanner }
452                 
453                 @suppr_ged = Gtk::Button.new
454                 hbox_suppr_ged = Gtk::HBox.new false, 2
455                 hbox_suppr_ged.add Gtk::Image.new( "./resources/icons/trash-full.png" )
456                 hbox_suppr_ged.add Gtk::Label.new "Supprimer"
457                 @suppr_ged.add hbox_suppr_ged
458                 @suppr_ged.signal_connect("clicked") { supprime_ged }
459                 
460                 @nouveau_ged = Gtk::Button.new
461                 hbox_nouveau_ged = Gtk::HBox.new false, 2
462                 hbox_nouveau_ged.add Gtk::Image.new( "./resources/icons/document-new.png" )
463                 hbox_nouveau_ged.add Gtk::Label.new "Nouveau"
464                 @nouveau_ged.add hbox_nouveau_ged
465                 @nouveau_ged.signal_connect("clicked") {  }
466                 
467                 # Les réglements et le montants du pieds de page :
468                 table_montants = Gtk::Table.new 3, 2, false
469                 table_montants.attach( notebook, 0, 1, 0, 4, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 2, 2 )
470                 table_montants.attach( Gtk::Label.new("Réglements:"), 1, 2, 0, 1, Gtk::FILL, Gtk::FILL, 2, 2 )
471                 table_montants.attach( @regler, 1, 2, 1, 2, Gtk::FILL, Gtk::FILL, 2, 2 )
472                 table_montants.attach( table_reglements, 2, 3, 0, 4, Gtk::FILL, Gtk::FILL, 2, 2 )
473                 table_montants.attach( Gtk::Label.new("HT :"), 3, 4, 0, 1, Gtk::FILL, Gtk::FILL, 2, 2 )
474                 table_montants.attach( @ht, 4, 5, 0, 1, Gtk::FILL, Gtk::FILL, 2, 2 )
475                 table_montants.attach( Gtk::Label.new("TVA :"), 3, 4, 1, 2, Gtk::FILL, Gtk::FILL, 2, 2 )
476                 table_montants.attach( @tva, 4, 5, 1, 2, Gtk::FILL, Gtk::FILL, 2, 2 )
477                 table_montants.attach( Gtk::Label.new("TTC :"), 3, 4, 2, 3, Gtk::FILL, Gtk::FILL, 2, 2 )
478                 table_montants.attach( @ttc, 4, 5, 2, 3, Gtk::FILL, Gtk::FILL, 2, 2 )
479                 table_montants.attach( Gtk::Label.new("A PAYER :"), 3, 4, 3, 4, Gtk::FILL, Gtk::FILL, 2, 2 )
480                 table_montants.attach( @a_payer, 4, 5, 3, 4, Gtk::FILL, Gtk::FILL, 2, 2 )
481                 
482                 table_montants.set_column_spacing(0, 30)
483                 table_montants.set_column_spacing(2, 30)
484                 
485                 table_montants
486         
487         end
488         
489         def regler
490                 if validate(quit=false)
491                         popup = Saisie_reglement.new @window, @type, @id_client
492                         popup.run
493                         refresh @id, @type
494                 end
495         end 
496         
497         def table_reglements
498                                                                                         # id     date    type   montant         
499                 @list_paiement = Gtk::ListStore.new(Integer, String, String, String)
500                 table_paiement = Gtk::TreeView.new(@list_paiement)
501                 
502                 # Create a renderer with the background property set
503                 renderer_center = Gtk::CellRendererText.new
504                 renderer_right = Gtk::CellRendererText.new
505                 renderer_right.background = renderer_center.background = "white"
506                 renderer_center.xalign = 0.5
507                 renderer_right.xalign = 1
508                 renderer_right.yalign = renderer_center.yalign = 0
509                 
510                 col = Gtk::TreeViewColumn.new("ID", renderer_center, :text => 0)
511                 #table_paiement.append_column(col)
512                 
513                 col = Gtk::TreeViewColumn.new("Date", renderer_center, :text => 1)
514                 table_paiement.append_column(col)
515                 
516                 col = Gtk::TreeViewColumn.new("Type", renderer_center, :text => 2)
517                 table_paiement.append_column(col)
518                 
519                 col = Gtk::TreeViewColumn.new("Montant", renderer_right, :text => 3)
520                 table_paiement.append_column(col)
521                 
522                 scroll = Gtk::ScrolledWindow.new
523         scroll.set_policy(Gtk::POLICY_NEVER,Gtk::POLICY_AUTOMATIC)
524         scroll.add table_paiement
525                 
526                 scroll
527         end
528         
529         def ged
530                                                                                 # ID     Fichier  Miniature    Size
531                 @liste_ged = Gtk::ListStore.new(Integer, String, Gdk::Pixbuf, String)
532                 @table_ged = Gtk::TreeView.new(@liste_ged)
533                 
534                 @table_ged.signal_connect ("row-activated") { |view, path, column|
535                         if !@research then
536                                  fichier = @liste_ged.get_value(@table_ged.selection.selected, 1)
537                                  chemin = "#{@window.config_db.conf["chemin_documents"]}/documents/#{@id}/#{fichier}"
538                                  system "xdg-open", chemin
539                         end
540                 }
541                 
542                 # Create a renderer with the background property set
543                 renderer_left = Gtk::CellRendererText.new
544                 renderer_right = Gtk::CellRendererText.new
545                 renderer_left.background = renderer_right.background = "white"
546                 renderer_left.yalign = renderer_right.yalign = 0.5
547                 renderer_left.xalign = 0
548                 renderer_right.xalign = 1
549                 
550                 col = Gtk::TreeViewColumn.new("ID", renderer_left, :text => 0)
551                 #@table_ged.append_column(col)
552                 
553                 col = Gtk::TreeViewColumn.new("Fichier", renderer_left, :text => 1)
554                 col.expand = true
555                 @table_ged.append_column(col)   
556                 
557                 renderer_pix = Gtk::CellRendererPixbuf.new
558                 col = Gtk::TreeViewColumn.new
559                 col.title = "Aperçu"
560                 col.pack_start(renderer_pix, true)
561                 col.add_attribute(renderer_pix, 'pixbuf', 2)
562                 @table_ged.append_column(col)   
563                 
564                 col = Gtk::TreeViewColumn.new("Taille", renderer_right, :text => 3)
565                 @table_ged.append_column(col)
566                 
567                 scroll = Gtk::ScrolledWindow.new
568         scroll.set_policy(Gtk::POLICY_NEVER,Gtk::POLICY_AUTOMATIC)
569         scroll.add @table_ged
570                 
571                 scroll
572         end
573         
574         def scanner
575                 if validate(quitter=false)
576                         dial_scan = DialScan.new @window
577                         dial_scan.nom.text = @doc.ref2
578                         dial_scan.run { |response| 
579                                 if response.eql?(-5)
580                                         nom = (dial_scan.nom.text.empty? ? "scan" : dial_scan.nom.text.gsub(" ","_") )
581                                         mode = dial_scan.mode.active_text
582                                         @window.scan.acquisition nom, id=@doc.id, tiers=false, ext=".pdf", mode
583                                         refresh_ged
584                                 end
585                                 dial_scan.destroy                       
586                         }
587                 end
588         end
589         
590         # Suppression d'un fichier de la GED
591         def supprime_ged
592                 if @table_ged.selection.selected
593                         dialog = Gtk::MessageDialog.new(@window, 
594                                 Gtk::Dialog::DESTROY_WITH_PARENT,
595                                 Gtk::MessageDialog::QUESTION,
596                                 Gtk::MessageDialog::BUTTONS_YES_NO,
597                                 "Voulez-vous réellement supprimer ce fichier de la GED ?")
598                         response = dialog.run
599                         case response
600                           when Gtk::Dialog::RESPONSE_YES
601                                 id = @liste_ged.get_value(@table_ged.selection.selected, 0)
602                                 res = Geddocument.delete(id)
603                                 if res
604                                         fichier = @liste_ged.get_value(@table_ged.selection.selected, 1)
605                                         chemin = "#{@window.config_db.conf["chemin_documents"]}/documents/#{@id}/#{fichier}"
606                                         File.delete(chemin) if File.exist?(chemin)
607                                         refresh_ged
608                                 end
609                         end 
610                         dialog.destroy
611                         
612                 end
613         end
614         
615         def remplir_liste_paiements
616                 reglements = Paiementdocument.where(:document_id => @id).order(:id)
617                 montant_regle = 0
618                 reglements.each { |r|
619                         iter = @list_paiement.append
620                         iter[0] = r.id
621                         iter[1] = r.paiement.date_paiement.strftime("%d/%m/%Y")
622                         iter[2] = r.paiement.paiementtype.designation
623                         iter[3] = "%.2f €" % r.montant
624                         montant_regle += r.montant
625                 }
626                 @a_payer.text = "%.2f €" % (@ttc.text.to_f-montant_regle)
627         end
628         
629         def notebook
630                 
631                 # Conteneurs
632                 notebook = Gtk::Notebook.new
633                 scroll_note1 = Gtk::ScrolledWindow.new
634                 scroll_note2 = Gtk::ScrolledWindow.new
635                 scroll_info = Gtk::ScrolledWindow.new
636                 table_ged = Gtk::Table.new 3, 2, false
637                 table_info = Gtk::Table.new 3, 2, false
638                 
639                 # Les objets
640                 @prov = Gtk::Entry.new
641                 conditionpaiement_model = Gtk::ListStore.new(Integer, String, String, Integer, Integer)
642                 @conditionpaiement = Gtk::ComboBox.new conditionpaiement_model
643                 @ref2 = Gtk::Entry.new
644                 label_provenance = Gtk::Alignment.new 0, 0.5, 0, 0
645                 label_provenance.add Gtk::Label.new("Provenance:")
646                 label_conditionpaiement = Gtk::Alignment.new 0, 0.5, 0, 0
647                 label_conditionpaiement.add Gtk::Label.new("Condition de paiement:")
648                 label_ref2 = Gtk::Alignment.new 0, 0.5, 0, 0
649                 label_ref2.add Gtk::Label.new("Référence secondaire:")
650
651                 # Propriétés des objets
652                 scroll_note1.set_policy Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC
653                 scroll_note1.shadow_type = Gtk::SHADOW_NONE
654                 scroll_note2.set_policy Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC
655                 scroll_note2.shadow_type = Gtk::SHADOW_NONE
656                 scroll_info.set_policy Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC
657                 scroll_info.shadow_type = Gtk::SHADOW_NONE
658                 @prov.editable = false
659                 renderer_conditionpaiement = Gtk::CellRendererText.new 
660                 @conditionpaiement.pack_start(renderer_conditionpaiement, true)
661                 @conditionpaiement.set_attributes(renderer_conditionpaiement, :text => 2)
662                 @conditionpaiement.signal_connect("changed") { changement_condition_paiement } 
663                 
664                 # Agencement des conteneurs Note
665                 scroll_note1.add @note
666                 scroll_note2.add @note_priv
667                 table_ged.attach( @scan, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 2, 2 )
668                 table_ged.attach( @nouveau_ged, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL, 2, 2 )
669                 table_ged.attach( @suppr_ged, 0, 1, 2, 3, Gtk::FILL, Gtk::FILL, 2, 2 )
670                 table_ged.attach( ged, 1, 2, 0, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 2, 2 )
671                 
672                 # Agencement du conteneur Informations
673                 table_info.attach( label_ref2, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 2, 2 )
674                 table_info.attach( @ref2, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL, 2, 2 )
675                 table_info.attach( label_provenance, 2, 3, 0, 1, Gtk::FILL, Gtk::FILL, 2, 2 )
676                 table_info.attach( @prov, 3, 4, 0, 1, Gtk::FILL, Gtk::FILL, 2, 2 )
677                 table_info.attach( label_conditionpaiement, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL, 2, 2 )
678                 table_info.attach( @conditionpaiement, 1, 2, 1, 2, Gtk::FILL, Gtk::FILL, 2, 2 )
679                 scroll_info.add_with_viewport table_info
680                 
681                 # Agencement du notebook
682                 notebook.append_page scroll_info, Gtk::Label.new("Informations")
683                 notebook.append_page table_ged, Gtk::Label.new("GED")
684                 notebook.append_page scroll_note1, Gtk::Label.new("Note publique")
685                 notebook.append_page scroll_note2, Gtk::Label.new("Note privée")
686
687                 # Renvoie
688                 notebook
689                 
690         end
691         
692         def changement_condition_paiement
693                 date_valide = false
694                 date_document = nil
695                 begin
696                         date_document = Date.parse(@date_document.text)
697                 rescue
698                         date_valide = false
699                 else
700                         date_valide = true
701                 end
702                 if date_valide
703                         begin
704                                 nb_jours = @conditionpaiement.model.get_value(@conditionpaiement.active_iter, 3) if @conditionpaiement.active_iter
705                                 fin_de_mois = @conditionpaiement.model.get_value(@conditionpaiement.active_iter, 4).eql?(1) if @conditionpaiement.active_iter
706                                 date = Date.parse(@date_document.text) + nb_jours
707                                 date = Date.new(date.year, date.month, -1) if fin_de_mois
708                                 @date_echeance.text = date.strftime("%d/%m/%Y")
709                         rescue
710                         end
711                 end
712         end
713         
714         def refresh id, type
715         
716                 @doc = nil
717                 @id = id        
718                 @type = type    
719                 @ligne_modif_id = []
720                 @ligne_supp_id = []             
721                 @date_livraison.sensitive = type.eql?(3)
722                 @list_paiement.clear
723                 
724                 if id>0 then
725                         
726                         @doc = Document.includes(:documenttype, :tiers).where(:id => id).first
727                         if @doc then
728                                 remplir_en_tete @doc
729                         end
730                         
731                         doclignes = Documentligne.where(:document_id => id).includes(:tva).order(:id)
732                         if doclignes then
733                                 remplir_lignes doclignes
734                         end
735                         
736                         remplir_pieds
737                 else
738                         @doc = Document.new
739                         @frame.label = nouveau_nouvelle type            
740                         @frame.label += @window.type_doc[type][:nom].downcase 
741                         empty_component
742                         iter = @list_store.append
743                         iter[18] = @pix_comm
744                         @doc.montant_ttc = 0.0
745                         @doc.montant_regle = 0.0
746                         @mail = ""      
747                 end
748                 
749                 refresh_ged
750                 @regler.sensitive = ([4,8].include?(@type) and (@doc.montant_regle<@doc.montant_ttc))
751                 remplir_conditionpaiement
752                 @email.sensitive = !@mail.empty?
753         
754         end
755         
756         def refresh_ged
757                 @liste_ged.clear
758                 ged = Geddocument.where(:document_id => @id).order(:fichier)
759                 ged.each { |g|
760                         iter = @liste_ged.append
761                         iter[0] = g.id
762                         iter[1] = g.fichier
763                         miniature = "#{File.basename(g.fichier, File.extname(g.fichier))}_miniature.jpg"
764                         chemin = "#{@window.config_db.conf["chemin_documents"]}/documents/#{@id}/#{miniature}"
765                         iter[2] = Gdk::Pixbuf.new(chemin, 25, 40) if File.exist?(chemin)
766                         chemin = "#{@window.config_db.conf["chemin_documents"]}/documents/#{@id}/#{g.fichier}"
767                         iter[3] = ("%.1f ko" % (File.size(chemin)/1000) ) if File.exist?(chemin)
768                 }
769         end
770         
771         def nouveau_nouvelle num
772                 texte = ""
773                 case num
774                         when 1, 3
775                                 texte = "Nouveau "
776                         when 5
777                                 texte = "Nouvel "
778                         else
779                                 texte = "Nouvelle "
780                 end
781                 texte
782         end
783         
784         def remplir_conditionpaiement
785                 @conditionpaiement.model.clear
786                 cond = Conditionpaiement.where(:actif => true).order(:id)
787                 active_iter = nil
788                 cond.each { |c|
789                         iter = @conditionpaiement.model.append
790                         iter[0] = c.id
791                         iter[1] = c.code
792                         iter[2] = c.designation
793                         iter[3] = c.nb_jours
794                         iter[4] = (c.fin_mois ? 1 : 0)
795                         active_iter = iter if @doc.conditionpaiement_id.eql?(c.id)
796                 }
797                 if active_iter
798                         @conditionpaiement.active_iter = active_iter
799                 else
800                         @conditionpaiement.active = 0
801                 end
802         end
803         
804         def remplir_en_tete doc
805         
806                 date_document = ""
807                 date_livraison = ""
808                 @id_client = doc.tiers_id
809                 @client.text = doc.tiers.nom
810                 @mail = doc.tiers.mail
811                 @client.sensitive = false
812                 @id_tarif = doc.tarif_id
813                 date_document = doc.date_document.to_s
814                 date_livraison = doc.date_livraison.to_s
815                 date_echeance = doc.date_echeance.to_s
816                 @note.buffer.text = doc.note
817                 @note_priv.buffer.text = doc.note_priv
818                 @ref = doc.ref
819                 @transfere = doc.transfere
820                 @frame.label = @window.type_doc[@type][:nom] + " #{@ref}" 
821                 begin
822                         @date_document.text = Date.parse(date_document).strftime("%d/%m/%Y")
823                         @date_livraison.text = Date.parse(date_livraison).strftime("%d/%m/%Y")
824                         @date_echeance.text = Date.parse(date_echeance).strftime("%d/%m/%Y")
825                 rescue
826                 end
827                 @transfert.sensitive = (!@transfere and !@type.eql?(5) and !@type.eql?(8))
828                 remplir_liste_paiements 
829                 @provenance = @doc.provenance_ref
830                 @prov.text = @provenance ? @provenance : ""
831                 @ref2.text = @doc.ref2 ? @doc.ref2 : ""
832         end
833         
834         def remplir_lignes doclignes
835         
836                 @list_store.clear
837                 
838                 doclignes.each { |h| 
839                         
840                         iter = @list_store.append
841                         iter[0] = h.id
842                         iter[1] = h.document_id
843                         iter[2] = h.article_id
844                         iter[3] = h.code
845                         iter[4] = h.designation
846                         iter[5] = h.qtite
847                         iter[6] = h.tva_id
848                         iter[7] = h.colisage
849                         iter[8] = "%.2f" % h.pu
850                         iter[9] = h.remise
851                         iter[10] = "%.2f €" % h.total_ligne
852                         iter[11] = h.tva.designation.to_s
853                         iter[12] = h.tva.taux
854                         iter[13] = (h.tva.np ? 1 : 0)
855                         iter[14] = h.commentaires
856                         iter[15] = h.lot
857                         iter[16] = h.qtite
858                         iter[17] = @pix_trash
859                         iter[18] = @pix_comm
860                 }
861                 
862                 iter = @list_store.append
863                 iter[18] = @pix_comm
864
865         end
866         
867         def remplir_pieds
868                 
869                 ht = 0.0
870                 tva = 0.0
871         
872                 @list_store.each { |model, path, iter|
873                         ligne = @view.model.get_iter(path)
874                         ht += ligne[10].to_f unless ligne[10].nil?
875                         tva += ligne[10].to_f*(ligne[12].to_f/100) unless ligne[10].nil? or ligne[12].nil? or ligne[13].eql?(1)
876                 }
877                 
878                 ht = ht.round(2)
879                 tva = tva.round(2)
880                 
881                 @ht.text = "%.2f €" % ht
882                 @tva.text = "%.2f €" % tva
883                 @ttc.text = "%.2f €" % (ht+tva).round(2)
884                 
885                 @a_payer.text = "%.2f €" % (@ttc.text.to_f-@doc.montant_regle)
886                 @regler.sensitive = true if (@a_payer.text.to_f>0.0 and [4,8].include?(@type))
887                 
888                 if @type.eql?(4) or @type.eql?(8)
889                         if @a_payer.text.to_f<=0.0
890                                 @status.set "resources/icons/paye.png"
891                                 @status.tooltip_text = "Payée"
892                         elsif @a_payer.text.to_f.eql?(@ttc.text.to_f)
893                                 @status.set "resources/icons/impaye.png"
894                                 @status.tooltip_text = "Impayée"
895                         else
896                                 @status.set "resources/icons/partiel.png"
897                                 @status.tooltip_text = "Payée partiellement"
898                         end
899                 else
900                         @status.set "resources/icons/empty.png"
901                         @status.tooltip_text = ""
902                 end
903                 
904         end
905         
906         def empty_component entierement=true
907         
908                 @ref = ""
909                 @ref2.text = ""
910                 @provenance = "" if entierement
911                 @prov.text = "" if entierement
912                 @client.text = "" if entierement
913                 @client.sensitive = true if entierement
914                 @id_client = 0 if entierement
915                 if entierement
916                         t = Tarif.where(:vente => true, :default => true).first
917                         @id_tarif = t.id
918                 end
919                 date = DateTime.now
920                 @date_document.text = date.strftime("%d/%m/%Y")
921                 date += 1
922                 @date_livraison.text = ""
923                 @date_echeance.text = date.strftime("%d/%m/%Y")
924                 @note.buffer.text = "" if entierement
925                 @note_priv.buffer.text = "" if entierement
926                 @transfere = false
927                 @transfert.sensitive = (!@type.eql?(5) and !@type.eql?(8))
928                 
929                 @list_store.clear if entierement
930                 
931                 @ht.text = "0 €" if entierement
932                 @tva.text = "0 €" if entierement
933                 @ttc.text = "0 €" if entierement
934                 
935                 if !entierement #Si on est dans un transfert on vide la qtité initiale pour chaque article
936                         @list_store.each { |model, path, iter|
937                                 @view.model.get_iter(path)[16]=0
938                         }
939                 end
940                 
941                 @status.set "resources/icons/empty.png"
942                 @status.tooltip_text = ""
943         
944         end
945         
946         def edit_cell data, text, col
947         
948                 if possible_modif?
949                         ligne = @view.model.get_iter(data)      
950                         if !text.empty? then
951                         
952                                 case col
953                         
954                                         when 3
955                                                 # Changement du code article
956                                                 add_article text                                        
957                                         when 4
958                                                 ligne[col] = text
959                                         when 5
960                                                 # Changement de quantité
961                                                 ligne[col] = text.to_f
962                                                 # On indique quel est la ligne qui a été modifiée
963                                                 @ligne_modif_id << ligne[0] unless @ligne_modif_id.include?(ligne[0])
964                                         when 7
965                                                 # Changement de colisage
966                                                 ligne[col] = text.to_i
967                                                 # On indique quel est la ligne qui a été modifiée
968                                                 @ligne_modif_id << ligne[0] unless @ligne_modif_id.include?(ligne[0])
969                                         when 8
970                                                 ligne[col] = text if text.to_f>=0.0
971                                                 # On indique quel est la ligne qui a été modifiée
972                                                 @ligne_modif_id << ligne[0] unless @ligne_modif_id.include?(ligne[0])
973                                         when 9
974                                                 ligne[col] = text.to_i if (text.to_i>=0 and text.to_i<=100)
975                                                 # On indique quel est la ligne qui a été modifiée
976                                                 @ligne_modif_id << ligne[0] unless @ligne_modif_id.include?(ligne[0])
977                                         when 11
978                                                 tva = Tva.where(:designation => text).first
979                                                 ligne[6] = tva.id
980                                                 ligne[11] = tva.designation.to_s
981                                                 ligne[12] = tva.taux
982                                                 ligne[13] = (tva.np ? 1 : 0)
983                                                 @ligne_modif_id << ligne[0] unless @ligne_modif_id.include?(ligne[0])
984                                         when 14
985                                                 # Ajout d'un commentaire
986                                                 ajout_commentaire ligne, text
987                         
988                                 end             
989                                 calcule_total_ligne ligne
990                         else
991                                 # Suppresion de la ligne si le code article est vide
992                                 suppr_article ligne if col.eql?(3)
993                                 if col.eql?(14) then
994                                         ligne[col] = ""
995                                         @ligne_modif_id << ligne[0] unless @ligne_modif_id.include?(ligne[0])
996                                         # Si on est sur une ligne de commentaire libre, on supprime la ligne
997                                         suppr_article ligne if ligne[2].eql?(0)
998                                 end
999                         end
1000                 end     
1001                 
1002         end
1003         
1004         def add_article code, recalcule=false
1005                 
1006                 ajout = false
1007                 
1008                 if (possible_modif? and !code.empty?)
1009                         ligne = @view.selection.selected
1010                 
1011                         # on vérifie si on prends un tarif d'achat ou de vente
1012                         tarif = (@type.eql?(8) ? 3 : @id_tarif)
1013                 
1014                         ajout = true
1015                 
1016                         article = Article.includes(:tva).where("code=? OR gencode=? OR gencode2=?", code, code, code).first
1017                         
1018                         if article then         
1019                                 ajout = true
1020                                 if ligne[3].nil?
1021                                         iter = @list_store.append
1022                                         iter[18] = @pix_comm
1023                                 end
1024                                 ligne[2] = article.id
1025                                 ligne[3] = article.code
1026                                 ligne[4] = article.description.to_s.empty? ? article.designation : "#{article.designation}\n#{article.description}"
1027                                 ligne[6] = article.tva_id
1028                                 ligne[7] = article.colisage
1029                                 at = Articletarif.where(:article_id =>  article.id, :tarif_id => tarif).first
1030                                 ligne[8] = "%.2f" % at.pu
1031                                 ligne[5] = 1 if ligne[5].eql?(0)
1032                                 ligne[11] = article.tva.designation
1033                                 ligne[12] = article.tva.taux
1034                                 ligne[13] = (article.tva.np ? 1 : 0)
1035                                 ligne[17] = @pix_trash
1036                         
1037                                 # Si l'article est géré par lot, on le demande tout de suite si on est sur un certain type de document
1038                                 ajout = verif_lot(article.id, ligne) if article.lot 
1039                 
1040                                 if ajout then
1041                                         calcule_total_ligne ligne if recalcule
1042                 
1043                                         # On indique quels sont les lignes qui ont été modifiées ou ajoutées
1044                                         id_ligne = @view.selection.selected[0]
1045                                         @ligne_modif_id << id_ligne unless @ligne_modif_id.include?(id_ligne)
1046                                 end
1047                         end
1048                 end
1049                 return ajout
1050         end
1051         
1052         # Indique si le document est modifiable ou pas
1053         def possible_modif?
1054                 if (@doc.montant_regle<@doc.montant_ttc or @doc.montant_ttc.eql?(0.0))
1055                         return true
1056                 else
1057                         dialog = Gtk::MessageDialog.new(@window, 
1058                                 Gtk::Dialog::DESTROY_WITH_PARENT,
1059                                 Gtk::MessageDialog::ERROR,
1060                                 Gtk::MessageDialog::BUTTONS_OK,
1061                                 "Le document a déjà été réglé intégralement.\nAucune modification possible")
1062                         dialog.run
1063                         dialog.destroy
1064                         return false
1065                 end
1066         end
1067         
1068         def focus_dernière_ligne
1069                 Thread.new { 
1070                         sleep 0
1071                         # on trouve la dernière ligne du tableau
1072                         npath = nil
1073                         @view.model.each {|model, path, iter| 
1074                                 npath = path
1075                         }
1076                         # et on met le focus sur la première colonne.
1077                         @view.set_cursor(npath, @view.get_column(0), true)
1078                 }
1079         end
1080         
1081         def verif_lot article_id, ligne
1082                 ajout = true
1083         
1084                 if [4, 5].include?(@type)
1085                         search = SearchLots.new @window, article_id
1086                         search.run { |response| 
1087                                 if ( !search.liste.view.selection.selected.nil? and response.eql?(-5)) then
1088                                         ligne[15] = search.liste.view.model.get_value( search.liste.view.selection.selected, 1 )
1089                                 else
1090                                         suppr_article ligne
1091                                         ajout = false
1092                                 end
1093                                 search.destroy                  
1094                         }
1095                 elsif @type.eql?(8)
1096                         search = SaisieLot.new @window, article_id
1097                         search.run { |response| 
1098                                 if (!search.lot.text.empty? and response.eql?(-5))
1099                                         ligne[15] = search.lot.text
1100                                 else
1101                                         suppr_article ligne
1102                                         ajout = false
1103                                 end     
1104                                 search.destroy  
1105                         }
1106                 end
1107
1108                 return ajout
1109         end
1110         
1111         def suppr_article ligne
1112         
1113                 if possible_modif?
1114                 
1115                         suppr = false
1116                         
1117                         dialog = Gtk::MessageDialog.new(@window, 
1118                                 Gtk::Dialog::DESTROY_WITH_PARENT,
1119                                 Gtk::MessageDialog::QUESTION,
1120                                 Gtk::MessageDialog::BUTTONS_YES_NO,
1121                                 "Voulez-vous réellement supprimer cette ligne ?")
1122                         response = dialog.run
1123                         case response
1124                           when Gtk::Dialog::RESPONSE_YES
1125                                 suppr = true
1126                         end 
1127                         dialog.destroy
1128                 
1129                         if suppr
1130                                 # Si la ligne était déjà enregistrée dans la base, on la marque à supprimer
1131                                 @ligne_supp_id << ligne[0].to_i if ligne[0].to_i>0              
1132
1133                                 # On réinitialise les valeurs des champs
1134                                 ligne[0] = ligne[1] = ligne[2] = ligne[5] = ligne[16] = 0
1135                                 ligne[3] = nil
1136                                 ligne[4] = nil
1137                                 ligne[6] = 1
1138                                 ligne[8] = nil
1139                                 ligne[14] = nil
1140                                 ligne[7] = 1
1141                 
1142                                 # On détermine le nombre de lignes
1143                                 i = -1
1144                                 @list_store.each { i += 1 }
1145                                 n = @view.selection.selected.path.to_s.to_i
1146                 
1147                                 # Puis on retire la ligne du tableau sauf si il s'agit de la dernière ligne
1148                                 @list_store.remove @view.selection.selected unless i.eql?(n)
1149                 
1150                                 # on recalcule le pieds
1151                                 remplir_pieds
1152                         end
1153                 end
1154         
1155         end
1156         
1157         def calcule_total_ligne ligne
1158                 ligne[10] = "%.2f €" % ( ligne[5]*ligne[8].to_f*ligne[7]*( 1-ligne[9].to_f/100 ) ).round(2)
1159                 remplir_pieds
1160         end
1161         
1162         def imprimer
1163                 validate
1164                 chemin = @window.config_db.chemin_temp
1165                 Edition.new @doc.id, chemin
1166                 if RUBY_PLATFORM.include?("linux") then 
1167                         system "xdg-open","#{chemin}/#{@doc.ref}.pdf"
1168                 else
1169                         if RUBY_PLATFORM.include?("mingw") then 
1170                                 system "start","#{chemin}/#{@doc.ref}.pdf"
1171                         else
1172                                 
1173                         end
1174                 end
1175         end
1176         
1177         def mailer
1178                 validate
1179                 chemin = @window.config_db.chemin_temp
1180                 Edition.new @doc.id, chemin
1181                 if RUBY_PLATFORM.include?("linux") then 
1182                         system "xdg-email --subject '#{@window.type_doc[@type][:nom].downcase}' --attach #{chemin}/#{@doc.ref}.pdf #{@mail}" 
1183                 else
1184                         if RUBY_PLATFORM.include?("mingw") then 
1185                                 # TODO
1186                         else
1187                                 
1188                         end
1189                 end
1190         end
1191         
1192         def validate quitter=true
1193         
1194                 date_document = Date.parse(@date_document.text).strftime("%Y-%m-%d")
1195                 date_livraison = @date_livraison.text.empty? ? "" : Date.parse(@date_livraison.text).strftime("%Y-%m-%d")
1196                 date_echeance =  Date.parse(@date_echeance.text).strftime("%Y-%m-%d")
1197                 tarif = @id_tarif
1198                 
1199                 res = !@id_client.eql?(0)  # Il faut qu'un client soit sélectionné pour pouvoir enregistrer le document !
1200                         
1201                 if res then
1202                         @ref = reference if @ref.empty?
1203                         @doc.tiers_id = @id_client
1204                         @doc.date_document = date_document
1205                         @doc.note = @note.buffer.text
1206                         @doc.note_priv = @note_priv.buffer.text
1207                         @doc.documenttype_id = @type
1208                         @doc.date_livraison = date_livraison
1209                         @doc.date_echeance = date_echeance
1210                         @doc.tarif_id = tarif
1211                         @doc.utilisateur_id = @login.user.id
1212                         @doc.montant_ht = @ht.text
1213                         @doc.montant_ttc = @ttc.text
1214                         @doc.ref = @ref
1215                         @doc.ref2 = @ref2.text
1216                         @doc.transfere = @tranfere
1217                         @doc.provenance_ref = @provenance
1218                         @doc.conditionpaiement_id = @conditionpaiement.model.get_value(@conditionpaiement.active_iter,0)
1219                         
1220                         res = @doc.save
1221                 else
1222                         erreur = "Vous devez sélectionner un client valide !"
1223                         dialog = Gtk::MessageDialog.new @window, Gtk::Dialog::MODAL, Gtk::MessageDialog::ERROR, Gtk::MessageDialog::BUTTONS_CLOSE, erreur
1224                         dialog.title = "Erreur"
1225                         dialog.signal_connect('response') { dialog.destroy }
1226                 dialog.run                               
1227                 end
1228                 
1229                 if res and !@ligne_modif_id.empty? then
1230                         
1231                         @list_store.each { |model, path, iter|
1232                                 
1233                                 if !@view.model.get_iter(path)[3].nil? or !@view.model.get_iter(path)[14].nil? then
1234                                         id_ligne = @view.model.get_iter(path)[0]
1235                                         id_article = @view.model.get_iter(path)[2]
1236                                         code = @view.model.get_iter(path)[3]
1237                                         designation = @view.model.get_iter(path)[4]
1238                                         qtite = @view.model.get_iter(path)[5]
1239                                         id_tva = @view.model.get_iter(path)[6].nil? ? "1" :  @view.model.get_iter(path)[6]
1240                                         colisage = @view.model.get_iter(path)[7]
1241                                         pu = @view.model.get_iter(path)[8].nil? ? 0 : @view.model.get_iter(path)[8]
1242                                         remise = @view.model.get_iter(path)[9]
1243                                         total_ligne = @view.model.get_iter(path)[10]
1244                                         commentaires = @view.model.get_iter(path)[14]
1245                                         lot = @view.model.get_iter(path)[15].to_s
1246                                                 
1247                                         dl = nil
1248                                         if id_ligne>0 then
1249                                                 dl = Documentligne.find(id_ligne)
1250                                         else
1251                                                 dl = Documentligne.new
1252                                         end
1253                                         
1254                                         dl.document_id = @doc.id
1255                                         dl.article_id = id_article
1256                                         dl.qtite = qtite
1257                                         dl.tva_id = id_tva
1258                                         dl.colisage = colisage
1259                                         dl.pu = pu
1260                                         dl.remise = remise
1261                                         dl.code = code
1262                                         dl.designation = designation
1263                                         dl.total_ligne = total_ligne
1264                                         dl.commentaires = commentaires
1265                                         dl.lot = lot
1266                                         
1267                                         res = dl.save
1268                                         
1269                                         if res then
1270                                                 # Gestion des stocks
1271                                                 stock qtite, @view.model.get_iter(path)[16], id_article, lot
1272                                         end
1273                                 
1274                                 end
1275                                 
1276                         }
1277                         
1278                 end
1279                 
1280                 if res then 
1281                         # suppression en base des lignes supprimées dans le tableau
1282                         @ligne_supp_id.each { |l|                                                               
1283                                 dl = Documentligne.find(l)                              
1284                                 if dl then
1285                                         stock 0, dl.qtite, dl.article_id, dl.lot
1286                                         res = dl.destroy
1287                                         p "Suppresion de ligne : #{l}" if res
1288                                 end                             
1289                         }
1290                 end
1291                 
1292                 if res
1293                         if quitter
1294                                 quit @type
1295                         else
1296                                 refresh @doc.id, @type
1297                         end
1298                 end
1299                 return res      
1300         end
1301         
1302         def reference
1303                 num = Documenttype.find(@type)
1304                 if num then
1305                         d = num.dernier_num + 1
1306                         n = "%04d" % d
1307                         date_document = Date.parse(@date_document.text).strftime("%y%m")                        
1308                         ref = "#{num.code}#{date_document}-#{n}"
1309                         
1310                         res = num.increment!(:dernier_num)
1311                         
1312                         if res then
1313                                 return ref
1314                         else
1315                                 return ""
1316                         end
1317                 else
1318                         return ""
1319                 end
1320         end
1321         
1322         def stock qtite, qtite_orig, id_article, lot
1323                         
1324                 if [4,5,8].include?(@type) # Si on est sur une Facture ou un Avoir alors on modifie le stock
1325                         ajoute = [5,8].include?(@type) # Si on est sur un avoir ou une facture fournisseur, on ajoute, sinon on enlève 
1326                         change_stock qtite, qtite_orig, id_article, lot, ajoute
1327                 end     
1328                 
1329         end
1330         
1331         def change_stock qtite, qtite_orig, id_article, lot, ajoute
1332         
1333                 qtite_delta = qtite-qtite_orig
1334                 
1335                 stock = Articlestock.where(:article_id => id_article, :lot => lot).first
1336                 if stock then 
1337                         id_stock = stock.id
1338                         qtite_finale = ajoute ? stock.qtite+qtite_delta : stock.qtite-qtite_delta
1339                 else
1340                         stock = Articlestock.new
1341                         qtite_finale = ajoute ? qtite_delta : -qtite_delta 
1342                 end
1343         
1344                 stock.stock_id = 1
1345                 stock.lot = lot
1346                 stock.qtite = qtite_finale
1347                 stock.article_id = id_article
1348                 
1349                 p "nouveau stock = #{qtite_finale}"
1350                 
1351                 res = stock.save
1352         
1353         end
1354         
1355         def transfert
1356         
1357                 dialog = Gtk::MessageDialog.new(@window, 
1358                                 Gtk::Dialog::DESTROY_WITH_PARENT,
1359                                 Gtk::MessageDialog::QUESTION,
1360                                 Gtk::MessageDialog::BUTTONS_YES_NO,
1361                                 "Voulez-vous réellement transférer votre document en #{@window.type_doc[@type+1][:nom].downcase} ?")
1362                 response = dialog.run
1363                 case response
1364                         when Gtk::Dialog::RESPONSE_YES
1365                                 @tranfere = true
1366                                 if validate(false) then
1367                                         @doc = Document.new
1368                                         @tranfere = false
1369                                         @provenance = @ref
1370                                         @prov.text = "Provenance : #{@provenance}" unless @provenance.empty?
1371                                         empty_component entierement=false
1372                                         @id=0
1373                                         @type = @type+1
1374                                         @frame.label = nouveau_nouvelle @type
1375                                         @frame.label += @window.type_doc[@type][:nom].downcase 
1376                         
1377                                         @list_store.each { |model, path, iter|
1378                                                 ligne = @view.model.get_iter(path)
1379                                                 ligne[0] = 0
1380                                                 @ligne_modif_id << ligne[0] unless @ligne_modif_id.include?(ligne[0])
1381                                         }
1382                                         
1383                                         @transfert.sensitive = (!@type.eql?(5) and !@type.eql?(8))
1384                                 end                     
1385                 end 
1386                 dialog.destroy  
1387         
1388         end
1389         
1390         def focus
1391                 @client.grab_focus
1392         end
1393         
1394         def menu_modifie_article
1395                 id = @view.model.get_value( @view.selection.selected, 2 )
1396                 code = @view.model.get_value( @view.selection.selected, 3 )
1397                 if id>0
1398                         modif_tb = Gtk::MenuItem.new "Modifier article #{code}"
1399                         modif_tb.signal_connect( "activate" ) { 
1400                                 dial_article = DialNewArticle.new @window, id
1401                                 dial_article.run { |response| 
1402                                         if response.eql?(-5)
1403                                                 dial_article.article_window.validate
1404                                         end
1405                                         dial_article.destroy
1406                                 }
1407                         }
1408                         menu = Gtk::Menu.new
1409                         menu.append modif_tb
1410                         menu.show_all
1411                         menu.popup(nil, nil, 0, 0)
1412                 end
1413         end
1414         
1415         def quit statut=nil
1416                 
1417                 @window.liste_documents.refresh statut unless statut.nil?       
1418                 @window.affiche @window.liste_documents
1419         
1420         end
1421         
1422 end