From 6e0486811610809fc89df56e4bfacc8a702c1b8a Mon Sep 17 00:00:00 2001 From: Nicolas Bally Date: Thu, 18 May 2017 01:21:04 +0200 Subject: [PATCH] =?UTF-8?q?r=C3=A9seaux=20etc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/public.scss | 238 +++++++++++++++++- app/controllers/admin/offers_controller.rb | 2 +- app/controllers/admin/reseauxes_controller.rb | 64 +++++ .../public/customer_messages_controller.rb | 124 +++++++++ .../public/customers_controller.rb | 32 ++- app/controllers/public/offers_controller.rb | 15 +- .../public/reseauxes_controller.rb | 18 ++ app/controllers/public/wishes_controller.rb | 4 +- app/models/accepted_offer.rb | 4 + app/models/binary_point.rb | 22 -- app/models/count_part_com.rb | 43 ---- app/models/credit.rb | 33 --- app/models/credit_expense.rb | 4 - app/models/credit_product.rb | 30 --- app/models/customer.rb | 61 ++--- app/models/customer_message.rb | 13 + app/models/need.rb | 5 + app/models/offer.rb | 3 +- app/models/offer_reseaux.rb | 4 + app/models/reseaux.rb | 13 + app/models/reseaux_customer.rb | 4 + app/views/admin/customers/_form.html.haml | 10 +- app/views/admin/needs/_form.html.haml | 5 + app/views/admin/offers/_form.html.haml | 12 +- app/views/admin/reseauxes/_form.html.haml | 9 + app/views/admin/reseauxes/_reseaux.html.haml | 12 + app/views/admin/reseauxes/edit.html.haml | 2 + app/views/admin/reseauxes/index.html.haml | 16 ++ app/views/admin/reseauxes/new.html.haml | 2 + app/views/admin/reseauxes/show.html.haml | 62 +++++ app/views/layouts/admin.html.haml | 4 +- .../_customer_message.html.haml | 23 ++ .../_customer_message_show.html.haml | 41 +++ .../public/customer_messages/_form.html.haml | 11 + .../_message_answers.html.haml | 6 + .../public/customer_messages/_show.html.haml | 22 ++ .../public/customer_messages/answer.js.erb | 3 + .../customer_messages/answer_save.js.erb | 3 + .../public/customer_messages/index.html.haml | 16 ++ .../public/customer_messages/show.html.haml | 1 + .../public/customer_messages/show.js.erb | 4 + .../public/customers/_annonce_account.haml | 11 - .../customers/_annonce_account_binary.haml | 8 - .../_annonce_account_binary_nil.haml | 6 - app/views/public/customers/_binary_table.haml | 21 -- .../public/customers/_customer.html.haml | 31 +++ app/views/public/customers/mail.haml | 42 ++-- app/views/public/customers/show.haml | 109 ++++++-- .../public/needs/_accepted_offer.html.haml | 5 + .../needs/_accepted_offers_index.html.haml | 5 +- app/views/public/needs/_message.html.haml | 6 + app/views/public/needs/_need_item.html.haml | 36 +-- app/views/public/needs/show.html.haml | 2 +- app/views/public/offers/accept.html.haml | 11 + app/views/public/reseauxes/_reseaux.html.haml | 10 + app/views/public/reseauxes/index.html.haml | 13 + app/views/public/reseauxes/show.html.haml | 86 +++++++ app/views/public/shared/_menu.html.haml | 6 + app/views/public/wishes/_form.html.haml | 2 + config/database.yml | 1 - config/environments/development.rb | 2 +- config/routes.rb | 14 +- ...20150704130444_create_customer_messages.rb | 22 ++ ...0170517084633_add_referent_to_customers.rb | 5 + .../20170517085613_add_referents_to_needs.rb | 6 + db/migrate/20170517090646_create_reseauxes.rb | 11 + ...20170517090709_create_reseaux_customers.rb | 12 + ...0517095531_add_chef_reseau_to_customers.rb | 5 + .../20170517220522_add_qte_to_wishes.rb | 5 + .../20170517222240_add_qte_to_offers.rb | 5 + ...170517224054_add_qte_to_accepted_offers.rb | 5 + .../20170517224743_add_gain_to_offers.rb | 5 + .../20170517225135_create_offer_reseauxes.rb | 12 + db/schema.rb | 91 +++++-- fichier-final.pdf | Bin 0 -> 827839 bytes pdf/documents/3-2.pdf | Bin 0 -> 828036 bytes pdf/documents/3.pdf | Bin 0 -> 538819 bytes pdf/documents/3_temp.pdf | Bin 0 -> 4129 bytes sortie.pdf | Bin 0 -> 92835 bytes test/fixtures/offer_reseauxes.yml | 9 + test/fixtures/reseaux_customers.yml | 9 + test/fixtures/reseauxes.yml | 11 + test/models/offer_reseaux_test.rb | 7 + test/models/reseaux_customer_test.rb | 7 + test/models/reseaux_test.rb | 7 + untitled.txt | 0 86 files changed, 1325 insertions(+), 336 deletions(-) create mode 100755 app/controllers/admin/reseauxes_controller.rb create mode 100644 app/controllers/public/customer_messages_controller.rb create mode 100755 app/controllers/public/reseauxes_controller.rb delete mode 100755 app/models/binary_point.rb delete mode 100755 app/models/count_part_com.rb delete mode 100755 app/models/credit.rb delete mode 100755 app/models/credit_expense.rb delete mode 100755 app/models/credit_product.rb create mode 100644 app/models/customer_message.rb create mode 100644 app/models/offer_reseaux.rb create mode 100644 app/models/reseaux.rb create mode 100644 app/models/reseaux_customer.rb create mode 100755 app/views/admin/reseauxes/_form.html.haml create mode 100755 app/views/admin/reseauxes/_reseaux.html.haml create mode 100755 app/views/admin/reseauxes/edit.html.haml create mode 100755 app/views/admin/reseauxes/index.html.haml create mode 100755 app/views/admin/reseauxes/new.html.haml create mode 100644 app/views/admin/reseauxes/show.html.haml create mode 100644 app/views/public/customer_messages/_customer_message.html.haml create mode 100644 app/views/public/customer_messages/_customer_message_show.html.haml create mode 100644 app/views/public/customer_messages/_form.html.haml create mode 100644 app/views/public/customer_messages/_message_answers.html.haml create mode 100644 app/views/public/customer_messages/_show.html.haml create mode 100644 app/views/public/customer_messages/answer.js.erb create mode 100644 app/views/public/customer_messages/answer_save.js.erb create mode 100644 app/views/public/customer_messages/index.html.haml create mode 100644 app/views/public/customer_messages/show.html.haml create mode 100644 app/views/public/customer_messages/show.js.erb delete mode 100755 app/views/public/customers/_annonce_account.haml delete mode 100755 app/views/public/customers/_annonce_account_binary.haml delete mode 100755 app/views/public/customers/_annonce_account_binary_nil.haml delete mode 100755 app/views/public/customers/_binary_table.haml create mode 100755 app/views/public/customers/_customer.html.haml mode change 100755 => 100644 app/views/public/customers/mail.haml create mode 100644 app/views/public/offers/accept.html.haml create mode 100755 app/views/public/reseauxes/_reseaux.html.haml create mode 100755 app/views/public/reseauxes/index.html.haml create mode 100644 app/views/public/reseauxes/show.html.haml create mode 100644 db/migrate/20150704130444_create_customer_messages.rb create mode 100644 db/migrate/20170517084633_add_referent_to_customers.rb create mode 100644 db/migrate/20170517085613_add_referents_to_needs.rb create mode 100644 db/migrate/20170517090646_create_reseauxes.rb create mode 100644 db/migrate/20170517090709_create_reseaux_customers.rb create mode 100644 db/migrate/20170517095531_add_chef_reseau_to_customers.rb create mode 100644 db/migrate/20170517220522_add_qte_to_wishes.rb create mode 100644 db/migrate/20170517222240_add_qte_to_offers.rb create mode 100644 db/migrate/20170517224054_add_qte_to_accepted_offers.rb create mode 100644 db/migrate/20170517224743_add_gain_to_offers.rb create mode 100644 db/migrate/20170517225135_create_offer_reseauxes.rb create mode 100644 fichier-final.pdf create mode 100644 pdf/documents/3-2.pdf create mode 100644 pdf/documents/3.pdf create mode 100644 pdf/documents/3_temp.pdf create mode 100644 sortie.pdf create mode 100644 test/fixtures/offer_reseauxes.yml create mode 100644 test/fixtures/reseaux_customers.yml create mode 100644 test/fixtures/reseauxes.yml create mode 100644 test/models/offer_reseaux_test.rb create mode 100644 test/models/reseaux_customer_test.rb create mode 100644 test/models/reseaux_test.rb create mode 100644 untitled.txt diff --git a/app/assets/stylesheets/public.scss b/app/assets/stylesheets/public.scss index bd69ca5..16091e6 100755 --- a/app/assets/stylesheets/public.scss +++ b/app/assets/stylesheets/public.scss @@ -245,7 +245,7 @@ position:relative; } -.annonce_message_li{ +.customer_message_li{ &.active, &:hover{ background:#3677AF; color:white; @@ -293,7 +293,7 @@ position:relative; border-bottom:1px solid gray; } -.annonce_message_show{ +.customer_message_show{ background:white;min-height:600px; padding-top:10px; padding-bottom:10px; @@ -698,3 +698,237 @@ height: 100%; max-width: 100%; } + + +.customer_message_li{ + &.active, &:hover{ + background:#3677AF; + color:white; + text-decoration:none; + border-color:transparent; + .time{ + color:white; + + } + } + display:block; + text-align:left; + padding:10px 10px; + color:#454340; + + img{ + float:left; + border-radius:50%; + height:60px; + margin-right:5px; + + } + .new{ + + display:inline-block; + width:10px; + height:10px; + background:#3677AF; + border-radius:50%; + } + .pseudo{ + + font-weight:600; + margin-bottom:10px; + + } + .time{ + font-size:0.7em; + color:rgba(120,118,115,1); + float:right; + margin-left:10px; + + } + border-radius:0; + border-bottom:1px solid gray; + +} + +.message_avertissement{ + padding:10px; + h3{ + margin-top:0; + } + background-color: #fcf8e3; + border-top: 1px solid #faebcc; + color: #8a6d3b; +} + + +.customer_message_show_container{ + padding:0 !important; + background:white; + border:1px solid #ddd; + border-radius:3px; + .speak_with{ + padding:10px; + line-height:60px; + background-color: #f5f5f5; + border-bottom: 1px solid #ddd; + img{ + float:left; + border-radius:50%; + height:60px; + margin-right:5px; + + } + } + +} +.customer_message_list{ + padding:0; + padding-right:5px; +} +.customer_message_show{ + + + .customer_message_container{ + + padding:10px; + margin-bottom:20px; + .side{ + float:left; + width:150px; + text-align:center; + position:relative; + .square{ + position:absolute; + background-color: #f5f5f5; + top:16px; + width:12px; + height:12px; + right:-6px; + transform: rotate(45deg); + + } + img{ + + border-radius:50%; + height:60px; + + + } + .pseudo{ + + font-weight:600; + margin-bottom:10px; + + } + .time{ + font-size:0.7em; + color:rgba(120,118,115,1); + + + } + + + } + .content{ + background-color: #f5f5f5; + padding:15px; + margin-left:150px; + min-height:150px; + border-radius:10px; + margin-right:80px; + + } + .ip_country{ + font-size:0.8em; + margin-left:150px; + margin-right:80px; + padding-top:5px; + } + + &.me{ + + .ip_country{ + font-size:0.8em; + margin-right:150px; + margin-left:80px; + } + + .side{ + .square{ + right:auto; + left:-6px; + + } + + + float:right; + } + + .content{ + margin-left:80px; + margin-right:150px; + + } + + + } + + &.desactivated{ + + .side{ + .square{ + background-color: #fcf8e3; + + } + + + + } + + .content{ + background-color: #fcf8e3; + color: #8a6d3b; + h3{ + margin-top:0; + } + + } + + + } + } + .message_annonce{ + + background:rgba(252,248,228,0.5); + padding:10px; + margin-bottom:10px; + a{ + //color:white; + + } + + } +} + + +@media screen and (max-width:740px) { + .customer_message_show{ + + .customer_message_container{ + + .content{ + margin-right:0px; + + } + + &.me{ + .content{ + margin-left:0px; + + } + + } + + } + } + +} diff --git a/app/controllers/admin/offers_controller.rb b/app/controllers/admin/offers_controller.rb index a213ece..d887937 100755 --- a/app/controllers/admin/offers_controller.rb +++ b/app/controllers/admin/offers_controller.rb @@ -229,7 +229,7 @@ class Admin::OffersController < ApplicationController private def offer_params - params.require(:offer).permit(:supplier, :price, :fee_percentage) + params.require(:offer).permit! #(:supplier, :price, :fee_percentage, :reseaux_ids, :gain) end end diff --git a/app/controllers/admin/reseauxes_controller.rb b/app/controllers/admin/reseauxes_controller.rb new file mode 100755 index 0000000..a5135e2 --- /dev/null +++ b/app/controllers/admin/reseauxes_controller.rb @@ -0,0 +1,64 @@ +class Admin::ReseauxesController < ApplicationController + layout "admin" + + + def index + @reseauxes = Reseaux.order(:name) + end + + def new + @reseaux = Reseaux.new() + + end + + def create + @reseaux = Reseaux.new(reseaux_params) + + if @reseaux.save + flash[:notice] = "Catégorie créée avec succès." + redirect_to admin_reseauxes_path + else + + render "new" + end + end + + def edit + @reseaux = Reseaux.find(params[:id]) + + end + + def show + @reseaux = Reseaux.find(params[:id]) + + end + + def update + @reseaux = Reseaux.find(params[:id]) + if @reseaux.update_attributes(reseaux_params) + flash[:notice] = "Catégorie modifiée avec succès." + redirect_to admin_reseauxes_path + else + + render :action => "edit" + end + end + + def destroy + @reseaux = Reseaux.find(params[:id]) + if !@reseaux.superadmin and @reseaux.destroy + flash[:notice] = "Reseauxe supprimée avec succès." + else + flash[:error] = "Impossible de supprimer ce reseauxe." + end + + redirect_to :action => :index + end + + def reseaux_params + params.require(:reseaux).permit! + end + + + +end diff --git a/app/controllers/public/customer_messages_controller.rb b/app/controllers/public/customer_messages_controller.rb new file mode 100644 index 0000000..3151bce --- /dev/null +++ b/app/controllers/public/customer_messages_controller.rb @@ -0,0 +1,124 @@ +class Public::CustomerMessagesController < ApplicationController + layout "public" + + before_filter :auth_customer + + def index + + @no_search = true + + + + @customer_messages = CustomerMessage.where("destinataire_id = ? or expediteur_id = ?",current_customer.id, current_customer.id).where("parent_id is null") + + @customer_messages = @customer_messages.order("last_message_at DESC, created_at DESC").all + + + + + end + + + def show + @customer_message = CustomerMessage.where("destinataire_id = ? or expediteur_id = ?",current_customer.id, current_customer.id).find(params[:id]) + @customer_message.readed = true + @customer_message.save + end + + def answer + @parent_customer_message = CustomerMessage.where("destinataire_id = ? or expediteur_id = ?",current_customer.id, current_customer.id).find(params[:id]) + @customer_message = CustomerMessage.new() + @customer_message.expediteur = current_customer + @customer_message.destinataire = @parent_customer_message.expediteur + end + + def answer_save + + @parent_customer_message = CustomerMessage.where("destinataire_id = ? or expediteur_id = ?",current_customer.id, current_customer.id).find(params[:id]) + @customer_message = CustomerMessage.new(params.require(:customer_message).permit!) + @customer_message.expediteur = current_customer + if @parent_customer_message.expediteur == current_customer + @customer_message.destinataire = @parent_customer_message.destinataire + else + @customer_message.destinataire = @parent_customer_message.expediteur + end + @customer_message.parent_id = @parent_customer_message.id + + if @customer_message.save + @parent_customer_message.last_message_at = Time.now + @parent_customer_message.save + + else + render :action => :answer + end + + + end + + + def new + + end + + def edit + + end + + + + def create + @customer_message = CustomerMessage.new(params.require(:customer_message).permit!) + @customer_message.expediteur = current_customer if current_customer + @customer_message.remote_ip = request.remote_ip + @customer_message.last_message_at = Time.now + + if @customer_message.save + redirect_to public_customer_messages_path + end + end + + + def update + @annonce = current_customer.annonces.find(params[:id]) + + + + + respond_to do |format| + if @annonce.update_attributes(params.require(:annonce).permit!) + + + + format.html { + redirect_to public_my_account_path + } + format.js + + else + + format.html { render :action => "edit" } + format.js { "" } + end + end + + + + end + + + + def destroy + + #@annonce = current_customer.annonces.find(params[:id]) + #@annonce.enabled = nil + #@annonce.save + + #redirect_to public_my_account_path, :notice => "Votre annonce a bien été désactivée" + + + + end + + + +end diff --git a/app/controllers/public/customers_controller.rb b/app/controllers/public/customers_controller.rb index 180b7f6..771e337 100755 --- a/app/controllers/public/customers_controller.rb +++ b/app/controllers/public/customers_controller.rb @@ -16,11 +16,7 @@ class Public::CustomersController < ApplicationController def show - per_page = (params[:per_page] and params[:per_page] != "") ? params[:per_page] : 10 - page = (params[:page] and params[:page] != "") ? params[:page] : 1 - - @customer = Customer.find(params[:id]) - @annonces = @customer.annonces.valid_to_show.order("list_head DESC, created_at DESC").page(page).per(per_page).all + @customer = current_customer.own_customers.find(params[:id]) end @@ -142,22 +138,22 @@ class Public::CustomersController < ApplicationController + def mail - @customer = Customer.find(params[:id]) - @annonce_message = AnnonceMessage.new(:destinataire => @customer) - if params[:annonce_id] and @annonce = @customer.annonces.where(:id => params[:annonce_id]).first - - @annonce_message.annonce = @annonce - + @no_search = true + @customer = Customer.find_by_id(params[:id]) + + if @customer + @customer_message = CustomerMessage.new(:destinataire => @customer) + + + @customer_message.expediteur = current_customer if current_customer + if @customer_message.expediteur + @customer_message.expediteur_mail = current_customer.email + end end - - @annonce_message.expediteur = current_customer if current_customer - if @annonce_message.expediteur - @annonce_message.expediteur_mail = current_customer.email - @annonce_message.tel = current_customer.tel_number - end - + end diff --git a/app/controllers/public/offers_controller.rb b/app/controllers/public/offers_controller.rb index 69ade48..bbb9014 100755 --- a/app/controllers/public/offers_controller.rb +++ b/app/controllers/public/offers_controller.rb @@ -11,6 +11,16 @@ class Public::OffersController < ApplicationController return redirect_back_or_default :root end @accepted_offer = AcceptedOffer.new + @accepted_offer.offer = @offer + + end + + def accept_save + if @offer.customers.include?(current_customer) + flash[:error] = "Vous avez déjà accepter cette offre" + return redirect_back_or_default :root + end + @accepted_offer = AcceptedOffer.new(params.require(:accepted_offer).permit(:qte)) @accepted_offer.customer = current_customer @accepted_offer.offer = @offer @@ -30,9 +40,12 @@ class Public::OffersController < ApplicationController - redirect_back_or_default :root + redirect_to public_need_path(@need) + else + render :action => :accept end end + def get_need @need = Need.find(params[:need_id]) diff --git a/app/controllers/public/reseauxes_controller.rb b/app/controllers/public/reseauxes_controller.rb new file mode 100755 index 0000000..b9c27b1 --- /dev/null +++ b/app/controllers/public/reseauxes_controller.rb @@ -0,0 +1,18 @@ +class Public::ReseauxesController < ApplicationController + layout "public" + + + def index + @reseauxes = current_customer.own_reseauxes.order(:name) + if @reseauxes.count == 1 + redirect_to public_reseaux_path(@reseauxes.first) + end + end + + def show + @reseaux = current_customer.own_reseauxes.find(params[:id]) + + end + + +end diff --git a/app/controllers/public/wishes_controller.rb b/app/controllers/public/wishes_controller.rb index e77edcb..7851898 100644 --- a/app/controllers/public/wishes_controller.rb +++ b/app/controllers/public/wishes_controller.rb @@ -5,7 +5,7 @@ class Public::WishesController < ApplicationController before_filter :check_enabled def new - @wish = Wish.new + @wish = Wish.new(:qte => 1) @need = Need.find(params[:need_id]) @wish.need = @need end @@ -92,7 +92,7 @@ class Public::WishesController < ApplicationController def wishes_params - params.require(:wish).permit(:devis, :note, :need_id) + params.require(:wish).permit(:devis, :note, :need_id, :qte) end end diff --git a/app/models/accepted_offer.rb b/app/models/accepted_offer.rb index a40bb60..d6a9807 100755 --- a/app/models/accepted_offer.rb +++ b/app/models/accepted_offer.rb @@ -34,4 +34,8 @@ class AcceptedOffer < ActiveRecord::Base "Documents retournés et vérifiés" end end + + def total + self.offer.price * qte + end end diff --git a/app/models/binary_point.rb b/app/models/binary_point.rb deleted file mode 100755 index 7024d4a..0000000 --- a/app/models/binary_point.rb +++ /dev/null @@ -1,22 +0,0 @@ -class BinaryPoint < ActiveRecord::Base - belongs_to :customer - belongs_to :order - - - scope :left, lambda { - where(:side => 1) - } - - scope :right, lambda { - where(:side => 2) - } - - after_save do - if self.side == 1 - self.customer.update_left_binary_points - else - self.customer.update_right_binary_points - end - end - -end diff --git a/app/models/count_part_com.rb b/app/models/count_part_com.rb deleted file mode 100755 index e2dc522..0000000 --- a/app/models/count_part_com.rb +++ /dev/null @@ -1,43 +0,0 @@ -class CountPartCom < ActiveRecord::Base - - def self.last_paid - CountPartCom.where(:paid => true).order("last_day DESC").first - end - - def paid_now - if !self.paid - start = CountPartCom.last_paid.last_day.tomorrow.beginning_of_day - stop = self.last_day.end_of_day - - self.amount = Order.com_part_between(start, stop) - self.nbr_parts = Credit.parts_at(stop) - self.part_price = self.amount / self.nbr_parts - - control_i = 0.0 - - - Customer.all.each do |customer| - if customer.callif(stop) - puts "NOUVELLE COM" - puts "Parts" - puts customer.callif(stop)[3] - com = customer.callif(stop)[3] * self.part_price - puts "Com" - puts com - control_i = control_i + com - if com > 0.0 - customer.commissions.create :count_part_com => self, :amount => com, :commission_type_id => 3 - end - end - - end - self.paid = true - self.paid_at = Time.now - self.control_amount = control_i - - self.save - end - return self - end - -end diff --git a/app/models/credit.rb b/app/models/credit.rb deleted file mode 100755 index 4e1bd80..0000000 --- a/app/models/credit.rb +++ /dev/null @@ -1,33 +0,0 @@ -class Credit < ActiveRecord::Base - has_many :credit_expenses - has_one :credit_product, :through => :order - belongs_to :order, :foreign_key => :operation_id - scope :between, lambda { |start, stop| - where("(credits.created_at <= ? and credits.expire_after >= ?)", stop.end_of_day,start.beginning_of_day) - } - - scope :plus, lambda { - where(:cred => true) - } - - scope :moins, lambda { - where(:debt => true) - } - - scope :boughts, lambda { - includes(:order).where(:orders => {:paid => true}) - - } - - def solde - - self.value - self.credit_expenses.sum(:value) - - - end - - def self.parts_at(date) - Credit.between(date, date).includes(:order).where("orders.unpaid is null").sum("orders.nbr_parts") - end - -end diff --git a/app/models/credit_expense.rb b/app/models/credit_expense.rb deleted file mode 100755 index fcdde83..0000000 --- a/app/models/credit_expense.rb +++ /dev/null @@ -1,4 +0,0 @@ -class CreditExpense < ActiveRecord::Base - belongs_to :credit - belongs_to :expense -end diff --git a/app/models/credit_product.rb b/app/models/credit_product.rb deleted file mode 100755 index 9bb6e64..0000000 --- a/app/models/credit_product.rb +++ /dev/null @@ -1,30 +0,0 @@ -class CreditProduct < ActiveRecord::Base - - def price_ttc - self.price_ht * 1.2 - end - - - def price_ht_final(customer) - self.price_ht - customer.credits.between(Date.today, Date.today).boughts.sum("orders.price_ht") - end - - def price_ttc_final(customer) - self.price_ht_final(customer)* 1.2 - - end - - def nbr_credits_final(customer) - self.nbr_credits - customer.credits_boughts(Date.today) - end - - def binary_points_final(customer) - self.binary_points - customer.credits.between(Date.today, Date.today).boughts.sum("orders.binary_points") - end - - def nbr_parts_final(customer) - self.parts - customer.credits.between(Date.today, Date.today).boughts.sum("orders.nbr_parts") - end - -end - diff --git a/app/models/customer.rb b/app/models/customer.rb index 87959f8..92be9ff 100755 --- a/app/models/customer.rb +++ b/app/models/customer.rb @@ -2,6 +2,16 @@ class Customer < ActiveRecord::Base has_many :domains, :through => :domain_customers has_many :domain_customers, :dependent => :destroy + + has_many :reseaux_customers + has_many :reseauxes, :through => :reseaux_customers + + has_many :own_reseauxes, :class_name => "Reseaux", :foreign_key => :chef_reseau_id + has_many :own_customers, :through => :own_reseauxes, :source => :customers + + + + scope :search, -> (search) { where('name LIKE ? OR firstname LIKE ? OR organisation LIKE ?', "%#{search}%", "%#{search}%", "%#{search}%") @@ -23,15 +33,12 @@ class Customer < ActiveRecord::Base has_many :customer_newsgroups has_many :newsgroups, :through => :customer_newsgroups - has_many :credits - has_many :expenses - has_many :credit_expenses - has_many :mlm_points + has_many :orders has_many :commissions has_many :virements - has_many :inbox_messages, :class_name => "AnnonceMessage", :foreign_key => :destinataire_id + has_many :inbox_messages, :class_name => "CustomerMessage", :foreign_key => :destinataire_id has_secure_password @@ -124,53 +131,13 @@ class Customer < ActiveRecord::Base end - def mlm_detail_ids - - i = 0 - - parents_id = [self.id] - - mlm_children_ids = [] - - mlm_children_id_by_levels = [] - - while i != 14 do - i += 1 - - - parents_id = Customer.where(:parent_id => parents_id).select(:id).map{ |v| v.id} - - mlm_children_id_by_levels[i] = parents_id - mlm_children_ids.concat parents_id - - - - end - - { - :mlm_children_id_by_levels => mlm_children_id_by_levels, - :mlm_children_ids => mlm_children_ids - } - - - end + def anonyme_nick "Utilisateur#{id}" end - def mlm_children_id_by_levels - self.mlm_detail_ids[:mlm_children_id_by_levels] - end - - def mlm_children_ids - self.mlm_detail_ids[:mlm_children_ids] - end - - def solde_commissions - self.commissions.sum(:amount) - end - + def max_virement self.commissions.sum(:amount).floor - 5.0 diff --git a/app/models/customer_message.rb b/app/models/customer_message.rb new file mode 100644 index 0000000..21a1533 --- /dev/null +++ b/app/models/customer_message.rb @@ -0,0 +1,13 @@ +class CustomerMessage < ActiveRecord::Base + belongs_to :need + belongs_to :expediteur, :class_name => "Customer" + belongs_to :destinataire, :class_name => "Customer" + + validates :message, :presence => true + acts_as_tree + + + def not_blocked + true + end +end diff --git a/app/models/need.rb b/app/models/need.rb index e591df0..29cf65b 100755 --- a/app/models/need.rb +++ b/app/models/need.rb @@ -2,6 +2,11 @@ class Need < ActiveRecord::Base include Workflow + + belongs_to :referent_technique, :class_name => "Customer" + belongs_to :referent_negos, :class_name => "Customer" + + has_many :domains, :through => :domain_needs has_many :domain_needs, :dependent => :destroy diff --git a/app/models/offer.rb b/app/models/offer.rb index b945ae2..ef9670f 100755 --- a/app/models/offer.rb +++ b/app/models/offer.rb @@ -9,5 +9,6 @@ class Offer < ActiveRecord::Base :presence => true, numericality: {greater_than_or_equal_to: 0} - + has_many :offer_reseauxes + has_many :reseauxes, :through => :offer_reseauxes end diff --git a/app/models/offer_reseaux.rb b/app/models/offer_reseaux.rb new file mode 100644 index 0000000..5dbe611 --- /dev/null +++ b/app/models/offer_reseaux.rb @@ -0,0 +1,4 @@ +class OfferReseaux < ActiveRecord::Base + belongs_to :offer + belongs_to :reseaux +end diff --git a/app/models/reseaux.rb b/app/models/reseaux.rb new file mode 100644 index 0000000..c10789c --- /dev/null +++ b/app/models/reseaux.rb @@ -0,0 +1,13 @@ +class Reseaux < ActiveRecord::Base + belongs_to :chef_reseau, :class_name => "Customer" + + has_many :reseaux_customers + has_many :customers, :through => :reseaux_customers + + has_many :needs, :through => :customers + + has_many :offer_reseauxes + has_many :offers, :through => :offer_reseauxes + + +end diff --git a/app/models/reseaux_customer.rb b/app/models/reseaux_customer.rb new file mode 100644 index 0000000..efb166f --- /dev/null +++ b/app/models/reseaux_customer.rb @@ -0,0 +1,4 @@ +class ReseauxCustomer < ActiveRecord::Base + belongs_to :reseaux + belongs_to :customer +end diff --git a/app/views/admin/customers/_form.html.haml b/app/views/admin/customers/_form.html.haml index ff8b43f..71a9bb1 100755 --- a/app/views/admin/customers/_form.html.haml +++ b/app/views/admin/customers/_form.html.haml @@ -6,7 +6,12 @@ =f.inputs do - =f.input :domains, :label => "Domaine : ", :collection => Domain.all, :as => :check_boxes + + .row.qi_cancel_margins + .col-sm-6 + =f.input :domains, :label => "Domaine : ", :collection => Domain.all, :as => :check_boxes + .col-sm-6 + =f.input :reseauxes, :label => "Réseaux : ", :collection => Reseaux.all, :as => :check_boxes =f.input :organisation, :label => "Société : " @@ -40,6 +45,7 @@ =f.input :newsgroups, :label => "Newsletters :", :collection => Newsgroup.all, :as => :check_boxes - + =f.input :referent, :label => "Possibilité d'être référent ?" + =f.input :chef_reseau, :label => "Possibilité d'être chef réseau ?" .actions= f.submit "Sauvegarder", :class => "btn btn-primary" diff --git a/app/views/admin/needs/_form.html.haml b/app/views/admin/needs/_form.html.haml index 9a237ec..5157bba 100755 --- a/app/views/admin/needs/_form.html.haml +++ b/app/views/admin/needs/_form.html.haml @@ -13,6 +13,11 @@ =f.input :author, :label => "Auteur", include_blank: "Administrateur" =f.input :domains, :label => "Domaine : ", :collection => Domain.all, :as => :check_boxes + + =f.input :referent_technique, :label => "Référent technique : ", :collection => Customer.where(:referent => true).pluck(Arel.sql("CONCAT(`firstname`, ' ', `name`)"), :id) + + =f.input :referent_negos, :label => "Référent négociation : ", :collection => Customer.where(:referent => true).pluck(Arel.sql("CONCAT(`firstname`, ' ', `name`)"), :id) + -#= f.input :note, :label => "Informations supplémentaires pour Négos (Si vous n'avez pas attaché de proposition, merci de préciser son prix dans ce champ)", :rows => 5, :input_html => {:style => "height:100px;"} .actions diff --git a/app/views/admin/offers/_form.html.haml b/app/views/admin/offers/_form.html.haml index 9218102..69d9dca 100755 --- a/app/views/admin/offers/_form.html.haml +++ b/app/views/admin/offers/_form.html.haml @@ -2,7 +2,13 @@ .content =f.inputs do - =f.input :supplier, :label => "Nom du fournisseur : " - =f.input :price, :label => "Prix négocié : " - + .row.qi_cancel_margins + .col-sm-6 + =f.input :supplier, :label => "Nom du fournisseur : " + =f.input :price, :label => "Prix négocié : " + =f.input :gain, :label => "Gain : " + .col-sm-6 + =f.input :reseauxes, :label => "Réseaux commissionnés : ", :collection => Reseaux.all, :as => :check_boxes + .clear + .actions= f.submit "Sauvegarder", :class => "btn btn-primary" diff --git a/app/views/admin/reseauxes/_form.html.haml b/app/views/admin/reseauxes/_form.html.haml new file mode 100755 index 0000000..4862479 --- /dev/null +++ b/app/views/admin/reseauxes/_form.html.haml @@ -0,0 +1,9 @@ +=semantic_form_for [:admin, @reseaux] do |f| + .content + + + =f.inputs do + =f.input :name, :label => "Nom du réseau : " + =f.input :chef_reseau, :label => "Chef réseau : ", :collection => Customer.where(:chef_reseau => true).pluck(Arel.sql("CONCAT(`firstname`, ' ', `name`)"), :id) + + .actions= f.submit "Sauvegarder", :class => "btn btn-primary" diff --git a/app/views/admin/reseauxes/_reseaux.html.haml b/app/views/admin/reseauxes/_reseaux.html.haml new file mode 100755 index 0000000..1152656 --- /dev/null +++ b/app/views/admin/reseauxes/_reseaux.html.haml @@ -0,0 +1,12 @@ + +%tr{:id => reseaux.id} + %td + = reseaux.name + %td + = reseaux.customers.count + + + %td.actions{:style => "width:150px;text-align:right"} + = link_to i(:"trash-o"), [:admin, reseaux], :data => {:confirm => 'Voulez-vous vraiment supprimer ce reseauxe ?'}, :method => :delete + = link_to i(:pencil), edit_admin_reseaux_path(reseaux) + = link_to i(:eye), admin_reseaux_path(reseaux) diff --git a/app/views/admin/reseauxes/edit.html.haml b/app/views/admin/reseauxes/edit.html.haml new file mode 100755 index 0000000..8291775 --- /dev/null +++ b/app/views/admin/reseauxes/edit.html.haml @@ -0,0 +1,2 @@ +%h1 Modifier un réseau +=render :partial => "form" diff --git a/app/views/admin/reseauxes/index.html.haml b/app/views/admin/reseauxes/index.html.haml new file mode 100755 index 0000000..7926082 --- /dev/null +++ b/app/views/admin/reseauxes/index.html.haml @@ -0,0 +1,16 @@ + +%table.table.admin_table.table-hover.table-striped + %thead.rows_header + + %tr + %th + Nom + %th Utilisateurs + %th{:style => "width:100px"} +   + + %tbody.rows + =render @reseauxes + +%br += link_to "Ajouter un reseaux", new_admin_reseaux_path, class:"btn btn-primary" diff --git a/app/views/admin/reseauxes/new.html.haml b/app/views/admin/reseauxes/new.html.haml new file mode 100755 index 0000000..19b253b --- /dev/null +++ b/app/views/admin/reseauxes/new.html.haml @@ -0,0 +1,2 @@ +%h1 Ajouter un réseau +=render :partial => "admin/reseauxes/form" diff --git a/app/views/admin/reseauxes/show.html.haml b/app/views/admin/reseauxes/show.html.haml new file mode 100644 index 0000000..2e578f0 --- /dev/null +++ b/app/views/admin/reseauxes/show.html.haml @@ -0,0 +1,62 @@ +-@read_only = true + +%h1 Détail d'un réseau +%h2=@reseaux.name + + +%h2 Membres du réseau + +%table.table.table-hover.table-striped.customer_table + %thead#customer_rows_header.rows_header + + %tr + %th + Société + %th + Nom + %th + Téléphone + %th + Ville + %th + Email confirmé ? + %th + Email + + + + %th{:style => "width:100px;text-align:right;"} +   + + + + + %tbody#customer_rows.rows + + =render @reseaux.customers + +%h2 Besoins + +%table.table.admin_table.table-hover.table-striped + %thead.rows_header + + %tr + %th + Titre + %th + Image? + %th + Catégorie + + %th{style: 'text-align:center' } + Commentaires/Intérêts + %th{style: 'text-align:center' } + Propositions + %th + Statut + %th{:style => "width:200px"} +   + + %tbody.rows + + =render @reseaux.needs \ No newline at end of file diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 0dcfe97..fa920b6 100755 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -56,8 +56,8 @@ %li=link_to content_tag(:span,unread_messages , style:"background-color:#D9534F", class: 'badge') + " Contacts", admin_conversations_path -else %li= link_to " Contacts", admin_conversations_path - %li= link_to " Moniteur d'activité", admin_connected_customers_path - + %li= link_to "Moniteur d'activité", admin_connected_customers_path + %li= link_to "Réseaux", admin_reseauxes_path %ul.nav.navbar-nav.navbar-right %li.dropdown diff --git a/app/views/public/customer_messages/_customer_message.html.haml b/app/views/public/customer_messages/_customer_message.html.haml new file mode 100644 index 0000000..5e7e7f3 --- /dev/null +++ b/app/views/public/customer_messages/_customer_message.html.haml @@ -0,0 +1,23 @@ +=link_to [:public, customer_message], :class => "customer_message_li", :id => "customer_message_#{customer_message.id}", :remote => true do + + + .time + =l customer_message.created_at, :format => "%d/%m/%y" + .pseudo + -if !customer_message.readed or customer_message.children.where(:destinataire_id => current_customer.id).where("readed is null").first + .new + + + + -if customer_message.expediteur and customer_message.expediteur == current_customer + moi + -else + = customer_message.expediteur.anonyme_nick + + + + -if answer = customer_message.children.order("created_at DESC").first + = truncate(answer.message) + -else + = truncate(customer_message.message) + .clear \ No newline at end of file diff --git a/app/views/public/customer_messages/_customer_message_show.html.haml b/app/views/public/customer_messages/_customer_message_show.html.haml new file mode 100644 index 0000000..759e6ac --- /dev/null +++ b/app/views/public/customer_messages/_customer_message_show.html.haml @@ -0,0 +1,41 @@ +-if customer_message.destinataire == current_customer + -customer_message.readed = true + -customer_message.save + +.customer_message_container{:class => ("me" if customer_message.expediteur and customer_message.expediteur == current_customer).to_s } + + + + + .side + + .square + + .pseudo + + + -if customer_message.expediteur and customer_message.expediteur == current_customer + moi + -else + =link_to customer_message.expediteur.anonyme_nick, [:public, customer_message.expediteur] + + + + + + + + + .time + =l customer_message.created_at, :format => "%d/%m/%y" + + .content + + + -if customer_message.title + %p + =customer_message.title + %hr + + =simple_format customer_message.message + \ No newline at end of file diff --git a/app/views/public/customer_messages/_form.html.haml b/app/views/public/customer_messages/_form.html.haml new file mode 100644 index 0000000..eb7c7f2 --- /dev/null +++ b/app/views/public/customer_messages/_form.html.haml @@ -0,0 +1,11 @@ +=semantic_form_for [:public, @customer_message], :url => answer_save_public_customer_message_path(@parent_customer_message), :remote => true do |f| + + =#f.input :tel, :label => qit("votre-numero-de-telephone-label","Votre numéro de téléphone :") + =#f.input :expediteur_mail, :label => qit("your-mail-label","Votre mail :") + + =f.input :message, :label => "Message" + =f.hidden_field :destinataire_id + + + + =f.submit "Envoyer mon message", :class => "btn btn-primary" \ No newline at end of file diff --git a/app/views/public/customer_messages/_message_answers.html.haml b/app/views/public/customer_messages/_message_answers.html.haml new file mode 100644 index 0000000..9b9c491 --- /dev/null +++ b/app/views/public/customer_messages/_message_answers.html.haml @@ -0,0 +1,6 @@ +-if @parent_customer_message + -@answer = @parent_customer_message +-else + -@answer = @customer_message + +=render :partial => "customer_message_show", :collection => @answer.children.order("created_at DESC"), :as => :customer_message \ No newline at end of file diff --git a/app/views/public/customer_messages/_show.html.haml b/app/views/public/customer_messages/_show.html.haml new file mode 100644 index 0000000..9b3281f --- /dev/null +++ b/app/views/public/customer_messages/_show.html.haml @@ -0,0 +1,22 @@ +-if @customer_message.expediteur and @customer_message.expediteur != current_customer + .speak_with + + Discussion avec + =link_to @customer_message.expediteur.anonyme_nick, [:public, @customer_message.expediteur] + +-if @customer_message.destinataire and @customer_message.destinataire != current_customer + .speak_with + Discussion avec + =link_to @customer_message.destinataire.anonyme_nick, [:public, @customer_message.destinataire] + + +.answer_link + + %p{:style => "margin:40px;"} + %center=link_to "Répondre", answer_public_customer_message_path(@customer_message), :remote => true, :class => "btn btn-primary" +#message_form +#message_answers + =render :partial => "message_answers" +=render :partial => "customer_message_show", :locals => {:customer_message => @customer_message} + + diff --git a/app/views/public/customer_messages/answer.js.erb b/app/views/public/customer_messages/answer.js.erb new file mode 100644 index 0000000..2ed8a69 --- /dev/null +++ b/app/views/public/customer_messages/answer.js.erb @@ -0,0 +1,3 @@ +$("#message_form").html("<%= escape_javascript(render(:partial => "form")) %>"); +$(".answer_link").hide(); + diff --git a/app/views/public/customer_messages/answer_save.js.erb b/app/views/public/customer_messages/answer_save.js.erb new file mode 100644 index 0000000..b3f8b1a --- /dev/null +++ b/app/views/public/customer_messages/answer_save.js.erb @@ -0,0 +1,3 @@ +$("#message_form").html(""); +$(".answer_link").show(); +$("#message_answers").html("<%= escape_javascript(render(:partial => "message_answers")) %>"); \ No newline at end of file diff --git a/app/views/public/customer_messages/index.html.haml b/app/views/public/customer_messages/index.html.haml new file mode 100644 index 0000000..ee08797 --- /dev/null +++ b/app/views/public/customer_messages/index.html.haml @@ -0,0 +1,16 @@ + +.center.padding + + %h1 Boite de réception + + .col-md-3.customer_message_list + + .inner.height_frame{:style => "overflow:auto;height:300px;"} + + =render @customer_messages + + .col-md-9.customer_message_show_container + .customer_message_show.inner.height_frame{:style => "overflow:auto;height:300px;"} + + .clear + %br diff --git a/app/views/public/customer_messages/show.html.haml b/app/views/public/customer_messages/show.html.haml new file mode 100644 index 0000000..eca5e0d --- /dev/null +++ b/app/views/public/customer_messages/show.html.haml @@ -0,0 +1 @@ +=render :partial => "show" \ No newline at end of file diff --git a/app/views/public/customer_messages/show.js.erb b/app/views/public/customer_messages/show.js.erb new file mode 100644 index 0000000..1a8f790 --- /dev/null +++ b/app/views/public/customer_messages/show.js.erb @@ -0,0 +1,4 @@ +$(".customer_message_show").html("<%= escape_javascript(render(:partial => "show")) %>"); +$(".customer_message_li").removeClass("active"); +$("#customer_message_<%= @customer_message.id %>").addClass("active"); +$("#customer_message_<%= @customer_message.id %> .new").hide(); diff --git a/app/views/public/customers/_annonce_account.haml b/app/views/public/customers/_annonce_account.haml deleted file mode 100755 index b63b3a7..0000000 --- a/app/views/public/customers/_annonce_account.haml +++ /dev/null @@ -1,11 +0,0 @@ -%tr.vertical_center.forum_user#forum_user{:id => forum_user.id} - - %td=image_tag (forum_user.avatar? ? forum_user.avatar.square.url : ""), :class => "avatar", :style => "width:50px; border-radius:50%;" - - %td=link_to forum_user.firstname.to_s+" "+forum_user.name.to_s, forum_forum_user_path(forum_user) - %td=forum_user.topics.count - %td=forum_user.messages.count - - -if moderator? - %td - =link_to i(:"trash-o"), [:forum, forum_user], :method => :delete, :confirm => "Voulez-vous vraiment supprimer cet utilisateur ?" \ No newline at end of file diff --git a/app/views/public/customers/_annonce_account_binary.haml b/app/views/public/customers/_annonce_account_binary.haml deleted file mode 100755 index 5148e9e..0000000 --- a/app/views/public/customers/_annonce_account_binary.haml +++ /dev/null @@ -1,8 +0,0 @@ --inline_b = inline_b || nil -.binary_account{:class => "level_#{@i_table}"} - - =image_tag(customer_binary.avatar_url) - =link_to customer_binary.pseudo, show_details_public_customer_path(customer_binary) --if (@i_table != @nbr_levels )and !inline_b - .binary_line - .line \ No newline at end of file diff --git a/app/views/public/customers/_annonce_account_binary_nil.haml b/app/views/public/customers/_annonce_account_binary_nil.haml deleted file mode 100755 index 56c4a31..0000000 --- a/app/views/public/customers/_annonce_account_binary_nil.haml +++ /dev/null @@ -1,6 +0,0 @@ -.binary_account.binary_account_nill{:class => "level_#{@i_table}"} - =image_tag("/default-nill.png") - Libre --if @i_table != @nbr_levels - .binary_line - .line \ No newline at end of file diff --git a/app/views/public/customers/_binary_table.haml b/app/views/public/customers/_binary_table.haml deleted file mode 100755 index 36e654a..0000000 --- a/app/views/public/customers/_binary_table.haml +++ /dev/null @@ -1,21 +0,0 @@ --i_table += 1 - --liste_o = liste -%table.binary_table - - %tr - %td - -@i_table = i_table - -liste = liste_o+"[1]" - =eval "tree_profile @binary_table#{liste}[0] rescue tree_profile_nil" - -@i_table = 0 - -if i_table < @nbr_levels - =render :partial => "public/customers/binary_table", :locals => {:i_table => i_table, :side => 1, :liste => liste} - - %td - -@i_table = i_table - -liste = liste_o+"[2]" - =eval "tree_profile @binary_table#{liste}[0] rescue tree_profile_nil" - -@i_table = 0 - -if i_table < @nbr_levels - =render :partial => "public/customers/binary_table", :locals => {:i_table => i_table, :side => 2, :liste => liste} \ No newline at end of file diff --git a/app/views/public/customers/_customer.html.haml b/app/views/public/customers/_customer.html.haml new file mode 100755 index 0000000..abfdce4 --- /dev/null +++ b/app/views/public/customers/_customer.html.haml @@ -0,0 +1,31 @@ +-css_class = "" +-css_class "danger" if customer.lock + +%tr#customer_row{:id => customer.id, :class => css_class} + %td + =customer.organisation + %td + =customer.name + =customer.firstname + %td + -if customer.phone? + = i("phone") + " #{customer.phone}" + %td + =customer.city + + %td + = "Oui" if customer.enabled + = "Non" if !customer.enabled + %td + =link_to customer.email, "mailto:#{customer.email}" + + %td + =number_to_currency customer.accepted_offers.joins(:offer).where(:state => "documents_completed").sum("offers.price").to_f + + %td=time_ago_in_words(customer.last_activity) if customer.last_activity + + + %td.actions{:style => "width:150px;text-align:right;"} + =link_to i(:eye), public_customer_path(customer) + =link_to i(:envelope), mail_public_customer_path(customer) + \ No newline at end of file diff --git a/app/views/public/customers/mail.haml b/app/views/public/customers/mail.haml old mode 100755 new mode 100644 index e7cda7b..588e634 --- a/app/views/public/customers/mail.haml +++ b/app/views/public/customers/mail.haml @@ -1,28 +1,24 @@ -.center - %h1 Nouveau message privé +.center.padding + -if @customer - %p - à - %strong=@annonce_message.destinataire.pseudo + %h1 Nouveau message privé - -if @annonce %p - Message au sujet de l'annonce : - %strong= @annonce.title - =semantic_form_for [:public, @annonce_message] do |f| - =f.input :name, :label => "Nom :" if !@annonce_message.expediteur + à + %strong=@customer_message.destinataire.pseudo + - =f.input :tel, :label => "Votre numéro de téléphone :" - =f.input :expediteur_mail, :label => "Votre mail :" - - =f.input :title, :label => "Sujet :" - =f.input :message, :label => "Message" - =f.hidden_field :destinataire_id - =f.hidden_field :annonce_id - - - =f.submit "Envoyer mon message", :class => "btn btn-primary" - - %br - %br + =semantic_form_for [:public, @customer_message] do |f| + =f.input :name, :label => "Nom :" if !@customer_message.expediteur + + + =f.input :message, :label => "Message" + =f.hidden_field :destinataire_id + + + + =f.submit "Envoyer mon message", :class => "btn btn-primary" + + %br + %br \ No newline at end of file diff --git a/app/views/public/customers/show.haml b/app/views/public/customers/show.haml index 1e5593d..ad0bec1 100755 --- a/app/views/public/customers/show.haml +++ b/app/views/public/customers/show.haml @@ -1,19 +1,98 @@ +-@read_only = true + .center.padding + + + + %h2= @customer.pseudo_admin + + + .row - .columns.span_2 - =image_tag (@customer.avatar ? @customer.avatar.square.url : ""), :class => "avatar", :style => "width:100%; border-radius:50%;" - .clear - %br - .columns.span_10 - %h1 - =@customer.pseudo - =simple_format @customer.bio + .col-md-6 + %table.table.table-striped + %tbody + %tr -.clear -.center.search_results.padding - %h2 - Annonces de cet utilisateur - - - =render :partial => "public/annonces/index" + %td + Date d'inscription : + %td + =l @customer.created_at, :format => :date + + %tr + %td + Dernière activité + %td + =time_ago_in_words(@customer.last_activity) if @customer.last_activity + %tr + %td + Organisation : + %td + =@customer.organisation + %tr + %td + Nom : + %td + =@customer.name + %tr + %td + Prénom : + %td + =@customer.firstname + + %tr + %td + Téléphone : + %td + =@customer.phone + + %tr + %td + Email : + %td + =link_to @customer.email, "mailto:#{@customer.email}" + + + + .col-md-6 + %table.table.table-striped + %tbody + %tr + %td + Adresse : + %td=@customer.address + %tr + %td + Adresse (suite) : + %td + =@customer.address2 + %tr + %td + Code postal + %td + =@customer.cp + %tr + %td + Ville : + %td + =@customer.city + + + %h3 Offres acceptées par ce membre + %table.table.table-hover.table-striped.customer_table + %tr + %th Besoin + %th Offre + -@customer.accepted_offers.joins(:offer).where(:state => "documents_completed").each do |accepted_offer| + %tr + %td + =link_to accepted_offer.offer.need.title.upcase, public_need_path(accepted_offer.offer.need) + %td=number_to_currency accepted_offer.offer.price + + %h3 Intérêts de ce membre + + + =render collection: @customer.needs, partial: 'public/needs/need_item', as: :need + + .clear \ No newline at end of file diff --git a/app/views/public/needs/_accepted_offer.html.haml b/app/views/public/needs/_accepted_offer.html.haml index b66f1c6..549c553 100755 --- a/app/views/public/needs/_accepted_offer.html.haml +++ b/app/views/public/needs/_accepted_offer.html.haml @@ -10,6 +10,11 @@ =link_to accepted_offer.offer.need.title, public_need_path(accepted_offer.offer.need) %td =number_to_currency(accepted_offer.offer.price, locale: :fr) + %td + =accepted_offer.qte + %td + =number_to_currency(accepted_offer.total, locale: :fr) + %td{style: 'text-align:center'} =accepted_offer.human_state %td{style: 'text-align:right'} diff --git a/app/views/public/needs/_accepted_offers_index.html.haml b/app/views/public/needs/_accepted_offers_index.html.haml index e43fd91..bc1850c 100755 --- a/app/views/public/needs/_accepted_offers_index.html.haml +++ b/app/views/public/needs/_accepted_offers_index.html.haml @@ -5,7 +5,10 @@ Titre du besoin %th Prix négocié - + %th + Qte + %th + Prix total %th{style: 'text-align:center'} État %th{style: 'text-align:right'} diff --git a/app/views/public/needs/_message.html.haml b/app/views/public/needs/_message.html.haml index 05a3172..31814a0 100755 --- a/app/views/public/needs/_message.html.haml +++ b/app/views/public/needs/_message.html.haml @@ -3,6 +3,12 @@ -if message.customer %h4 =message.customer.anonyme_nick + -if @need.referent_technique and message.customer.id == @need.referent_technique.id and message.customer.id == @need.referent_negos.id + (référent technique & négociation) + -elsif @need.referent_technique and message.customer.id == @need.referent_technique.id + (référent technique) + -elsif @need.referent_negos and message.customer.id == @need.referent_negos.id + (référent négociation) -elsif message.admin %h4 ="#{message.admin.fullname}" diff --git a/app/views/public/needs/_need_item.html.haml b/app/views/public/needs/_need_item.html.haml index 2ad74c2..5dcd1df 100755 --- a/app/views/public/needs/_need_item.html.haml +++ b/app/views/public/needs/_need_item.html.haml @@ -49,25 +49,25 @@ .counters .item=i(:"hand-paper-o") + " " + need.wishes.length.to_s .item=i(:"comment-o") + " " + need.messages.length.to_s + -if !@read_only + -if(need.verified?) + - @wish = need.wishes.where(need_id: need.id, customer_id: current_customer.id).first + -if(@wish) + =link_to i(:"check") + " Intéressé", edit_public_need_wish_path(need, @wish) , :class => "btn btn-square btn-lg btn-success pull-right" + -else + =link_to i(:"hand-paper-o") + " Ça m'intéresse !", new_public_need_wish_path(need) , :class => "btn btn-square btn-lg btn-primary pull-right" + -elsif(need.negociating?) + -if(need.customers.include?(current_customer)) + =link_to "Négociation en cours...", public_need_path(need), class: "btn btn-warning pull-right" + -else + =link_to i(:"times-circle") + " Négociation en cours...", public_need_path(need) , class: "btn btn-warning pull-right" - -if(need.verified?) - - @wish = need.wishes.where(need_id: need.id, customer_id: current_customer.id).first - -if(@wish) - =link_to i(:"check") + " Intéressé", edit_public_need_wish_path(need, @wish) , :class => "btn btn-square btn-lg btn-success pull-right" - -else - =link_to i(:"hand-paper-o") + " Ça m'intéresse !", new_public_need_wish_path(need) , :class => "btn btn-square btn-lg btn-primary pull-right" - -elsif(need.negociating?) - -if(need.customers.include?(current_customer)) - =link_to "Négociation en cours...", public_need_path(need), class: "btn btn-warning pull-right" - -else - =link_to i(:"times-circle") + " Négociation en cours...", public_need_path(need) , class: "btn btn-warning pull-right" - - -elsif(need.negociated?) - -if(need.customers.include?(current_customer)) - =link_to i(:"download") +" Voir les offres", public_need_path(need), class: "btn btn-success pull-right" - -else - =link_to i(:"times-circle") + " Négociation terminée", public_need_path(need) , class: "btn btn-danger pull-right" + -elsif(need.negociated?) + -if(need.customers.include?(current_customer)) + =link_to i(:"download") +" Voir les offres", public_need_path(need), class: "btn btn-success pull-right" + -else + =link_to i(:"times-circle") + " Négociation terminée", public_need_path(need) , class: "btn btn-danger pull-right" - .clear + .clear diff --git a/app/views/public/needs/show.html.haml b/app/views/public/needs/show.html.haml index 2dfc65a..7c6e7c4 100755 --- a/app/views/public/needs/show.html.haml +++ b/app/views/public/needs/show.html.haml @@ -114,7 +114,7 @@ -if offer.need.customers.include?(current_customer) -if !offer.customers.include?(current_customer) .accept-offer - =link_to i(:"check") + " J'accepte l'offre et je retourne le mandat signé", accept_public_need_offer_path(@need, offer), data: {confirm: "Pour que l’offre soit validée veuillez retourné le mandat signé que vous allez recevoir"}, class: "btn btn-lg btn-success " + =link_to i(:"check") + " J'accepte l'offre et je retourne le mandat signé", accept_public_need_offer_path(@need, offer), class: "btn btn-lg btn-success " -else .offer-accepted =i(:"check") + " Offre Acceptée" diff --git a/app/views/public/offers/accept.html.haml b/app/views/public/offers/accept.html.haml new file mode 100644 index 0000000..f745309 --- /dev/null +++ b/app/views/public/offers/accept.html.haml @@ -0,0 +1,11 @@ +.center + %h1 Accepter cette offre + = semantic_form_for [:public, @accepted_offer], :url => accept_save_public_need_offer_path(@offer.need, @offer), :method => :post do |f| + %p + Pour que l’offre soit validée veuillez retourné le mandat signé que vous allez recevoir + =f.inputs do + = f.input :qte, :label => "Quantité demandée :" + + + %br + =f.submit "Sauvegarder", :class => "btn btn-primary" diff --git a/app/views/public/reseauxes/_reseaux.html.haml b/app/views/public/reseauxes/_reseaux.html.haml new file mode 100755 index 0000000..8bdb85d --- /dev/null +++ b/app/views/public/reseauxes/_reseaux.html.haml @@ -0,0 +1,10 @@ + +%tr{:id => reseaux.id} + %td + = reseaux.name + %td + = reseaux.customers.count + + + %td.actions{:style => "width:150px;text-align:right"} + = link_to i(:eye), public_reseaux_path(reseaux) diff --git a/app/views/public/reseauxes/index.html.haml b/app/views/public/reseauxes/index.html.haml new file mode 100755 index 0000000..dff07d8 --- /dev/null +++ b/app/views/public/reseauxes/index.html.haml @@ -0,0 +1,13 @@ +.center.row + %table.table.admin_table.table-hover.table-striped + %thead.rows_header + + %tr + %th + Nom + %th Utilisateurs + %th{:style => "width:100px"} +   + + %tbody.rows + =render @reseauxes diff --git a/app/views/public/reseauxes/show.html.haml b/app/views/public/reseauxes/show.html.haml new file mode 100644 index 0000000..0c1cc52 --- /dev/null +++ b/app/views/public/reseauxes/show.html.haml @@ -0,0 +1,86 @@ +-@read_only = true + +.center.row + %h1 + Mon réseau : + =@reseaux.name + + + %h3 Membres du réseau + %div{:style => "position:relative"} + %table.table.table-hover.table-striped.customer_table + %thead#customer_rows_header.rows_header + + %tr + %th + Société + %th + Nom + %th + Téléphone + %th + Ville + + %th + Email + %th + CA + %th + Gains + + %th Dernière activité + + + + %th{:style => "width:100px;text-align:right;"} +   + + + + + %tbody#customer_rows.rows + -gain = 0.0 + -@reseaux.customers.each do |customer| + -css_class = "" + -css_class "danger" if customer.lock + + %tr#customer_row{:id => customer.id, :class => css_class} + %td + =customer.organisation + %td + =customer.name + =customer.firstname + %td + -if customer.phone? + = i("phone") + " #{customer.phone}" + %td + =customer.city + + + %td + =link_to customer.email, "mailto:#{customer.email}" + + %td + =number_to_currency customer.accepted_offers.joins(:offer).where(:state => "documents_completed").sum("offers.price * accepted_offers.qte").to_f + + %td + -g = customer.accepted_offers.joins(:offer).where(:state => "documents_completed").sum("offers.gain * accepted_offers.qte").to_f + =number_to_currency g + -gain += g + + + %td=time_ago_in_words(customer.last_activity) if customer.last_activity + + + %td.actions{:style => "width:150px;text-align:right;"} + =link_to i(:eye), public_customer_path(customer) + =link_to i(:envelope), mail_public_customer_path(customer) + + + %div{:style => "position:absolute;top:-30px;right:10px;"} + Gains : + =number_to_currency gain + + %h3 Les besoins de mon réseau + + =render collection: @reseaux.needs, partial: 'public/needs/need_item', as: :need diff --git a/app/views/public/shared/_menu.html.haml b/app/views/public/shared/_menu.html.haml index b263b06..38c0eb8 100755 --- a/app/views/public/shared/_menu.html.haml +++ b/app/views/public/shared/_menu.html.haml @@ -10,6 +10,12 @@ - unread_message = ContactMessage.where(contact_id: current_customer.id, read_by_customer: false).count %li=link_to ic(:comment)+" Nous contacter" + (unread_message > 0 ? " (#{unread_message})" : ""), public_contact_messages_path, :class => "btn" %li=link_to ic(:user)+" Mon compte", public_my_account_path, :class => "btn" + + -if current_customer.own_reseauxes.count > 0 + %li=link_to ic(:users)+" Mon réseau", public_reseauxes_path, :class => "btn" + + %li=link_to ic(:envelope)+" Conversations", public_customer_messages_path, :class => "btn" + %li=link_to "Se déconnecter", logout_public_customers_auths_path, :class => "btn" diff --git a/app/views/public/wishes/_form.html.haml b/app/views/public/wishes/_form.html.haml index ff96e39..47e58a5 100644 --- a/app/views/public/wishes/_form.html.haml +++ b/app/views/public/wishes/_form.html.haml @@ -9,6 +9,8 @@ = f.input :devis, type: :file, :label => "Votre proposition (Fichier au format PDF)" = f.input :note, :label => "Informations supplémentaires (Si vous n'avez pas attaché de proposition, merci de préciser son prix dans ce champ)", :rows => 5, :input_html => {:style => "height:100px;"} + + = f.input :qte, :label => "Quantité : ", :input_html => {:style => ""} %br diff --git a/config/database.yml b/config/database.yml index 5476b46..07da583 100755 --- a/config/database.yml +++ b/config/database.yml @@ -14,7 +14,6 @@ default: &default development: <<: *default username: root - password: mysqlpassword host: "127.0.0.1" socket: /var/run/mysqld/mysqld.sock diff --git a/config/environments/development.rb b/config/environments/development.rb index 88882de..2bf00e2 100755 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -41,7 +41,7 @@ Rails.application.configure do config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: "localhost", port: 1025 } - config.action_mailer.default_url_options = { host: 'rails-144740.nitrousapp.com', port: 3000} + config.action_mailer.default_url_options = { host: 'localhost', port: 3000} HOSTNAME="localhost:3000" diff --git a/config/routes.rb b/config/routes.rb index f6ba520..9b8a59c 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -116,6 +116,7 @@ Rails.application.routes.draw do resources :offers do member do get :accept + post :accept_save end end member do @@ -167,9 +168,18 @@ Rails.application.routes.draw do get "sitemap.:f" => "public/sitemap#sitemap" namespace :public do + + resources :reseauxes resources :virements resources :comments - resources :annonce_messages + resources :customer_messages do + member do + get :answer + post :answer_save + end + end + + resources :customers do member do get :confirm @@ -227,7 +237,7 @@ Rails.application.routes.draw do end namespace :admin do - + resources :reseauxes resources :documents resources :domains diff --git a/db/migrate/20150704130444_create_customer_messages.rb b/db/migrate/20150704130444_create_customer_messages.rb new file mode 100644 index 0000000..a106b04 --- /dev/null +++ b/db/migrate/20150704130444_create_customer_messages.rb @@ -0,0 +1,22 @@ +class CreateCustomerMessages < ActiveRecord::Migration + def change + create_table :customer_messages do |t| + t.string :title + t.text :message + + t.string :tel + t.integer :expediteur_id + t.string :expediteur_mail + t.string :destinataire_mail + t.integer :destinataire_id + t.integer :parent_id + t.datetime :last_message_at + t.string :remote_ip + t.boolean :enabled + t.boolean :readed + + t.timestamps null: false + end + + end +end diff --git a/db/migrate/20170517084633_add_referent_to_customers.rb b/db/migrate/20170517084633_add_referent_to_customers.rb new file mode 100644 index 0000000..d210487 --- /dev/null +++ b/db/migrate/20170517084633_add_referent_to_customers.rb @@ -0,0 +1,5 @@ +class AddReferentToCustomers < ActiveRecord::Migration + def change + add_column :customers, :referent, :boolean, :default => false + end +end diff --git a/db/migrate/20170517085613_add_referents_to_needs.rb b/db/migrate/20170517085613_add_referents_to_needs.rb new file mode 100644 index 0000000..0b6f370 --- /dev/null +++ b/db/migrate/20170517085613_add_referents_to_needs.rb @@ -0,0 +1,6 @@ +class AddReferentsToNeeds < ActiveRecord::Migration + def change + add_column :needs, :referent_negos_id, :integer + add_column :needs, :referent_technique_id, :integer + end +end diff --git a/db/migrate/20170517090646_create_reseauxes.rb b/db/migrate/20170517090646_create_reseauxes.rb new file mode 100644 index 0000000..f2279f3 --- /dev/null +++ b/db/migrate/20170517090646_create_reseauxes.rb @@ -0,0 +1,11 @@ +class CreateReseauxes < ActiveRecord::Migration + def change + create_table :reseauxes do |t| + t.string :name + t.text :description + t.integer :chef_reseau_id + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20170517090709_create_reseaux_customers.rb b/db/migrate/20170517090709_create_reseaux_customers.rb new file mode 100644 index 0000000..5a050fd --- /dev/null +++ b/db/migrate/20170517090709_create_reseaux_customers.rb @@ -0,0 +1,12 @@ +class CreateReseauxCustomers < ActiveRecord::Migration + def change + create_table :reseaux_customers do |t| + t.references :reseaux, index: true + t.references :customer, index: true + + t.timestamps null: false + end + add_foreign_key :reseaux_customers, :reseauxes + add_foreign_key :reseaux_customers, :customers + end +end diff --git a/db/migrate/20170517095531_add_chef_reseau_to_customers.rb b/db/migrate/20170517095531_add_chef_reseau_to_customers.rb new file mode 100644 index 0000000..7967473 --- /dev/null +++ b/db/migrate/20170517095531_add_chef_reseau_to_customers.rb @@ -0,0 +1,5 @@ +class AddChefReseauToCustomers < ActiveRecord::Migration + def change + add_column :customers, :chef_reseau, :boolean, :default => false + end +end diff --git a/db/migrate/20170517220522_add_qte_to_wishes.rb b/db/migrate/20170517220522_add_qte_to_wishes.rb new file mode 100644 index 0000000..cfb2f4b --- /dev/null +++ b/db/migrate/20170517220522_add_qte_to_wishes.rb @@ -0,0 +1,5 @@ +class AddQteToWishes < ActiveRecord::Migration + def change + add_column :wishes, :qte, :decimal, precision: 10, scale: 2, :default => 1 + end +end diff --git a/db/migrate/20170517222240_add_qte_to_offers.rb b/db/migrate/20170517222240_add_qte_to_offers.rb new file mode 100644 index 0000000..9a3c846 --- /dev/null +++ b/db/migrate/20170517222240_add_qte_to_offers.rb @@ -0,0 +1,5 @@ +class AddQteToOffers < ActiveRecord::Migration + def change + add_column :offers, :qte, :decimal, precision: 10, scale: 2, :default => 1 + end +end diff --git a/db/migrate/20170517224054_add_qte_to_accepted_offers.rb b/db/migrate/20170517224054_add_qte_to_accepted_offers.rb new file mode 100644 index 0000000..f5345d9 --- /dev/null +++ b/db/migrate/20170517224054_add_qte_to_accepted_offers.rb @@ -0,0 +1,5 @@ +class AddQteToAcceptedOffers < ActiveRecord::Migration + def change + add_column :accepted_offers, :qte, :decimal, precision: 10, scale: 2, :default => 1 + end +end diff --git a/db/migrate/20170517224743_add_gain_to_offers.rb b/db/migrate/20170517224743_add_gain_to_offers.rb new file mode 100644 index 0000000..8a27c60 --- /dev/null +++ b/db/migrate/20170517224743_add_gain_to_offers.rb @@ -0,0 +1,5 @@ +class AddGainToOffers < ActiveRecord::Migration + def change + add_column :offers, :gain, :decimal, precision: 10, scale: 2 + end +end diff --git a/db/migrate/20170517225135_create_offer_reseauxes.rb b/db/migrate/20170517225135_create_offer_reseauxes.rb new file mode 100644 index 0000000..6131dea --- /dev/null +++ b/db/migrate/20170517225135_create_offer_reseauxes.rb @@ -0,0 +1,12 @@ +class CreateOfferReseauxes < ActiveRecord::Migration + def change + create_table :offer_reseauxes do |t| + t.references :offer, index: true + t.references :reseaux, index: true + + t.timestamps null: false + end + add_foreign_key :offer_reseauxes, :offers + add_foreign_key :offer_reseauxes, :reseauxes + end +end diff --git a/db/schema.rb b/db/schema.rb index 2910c70..df95cc3 100755 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,16 +11,17 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161018122307) do +ActiveRecord::Schema.define(version: 20170517225135) do create_table "accepted_offers", force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.integer "offer_id", limit: 4 t.integer "customer_id", limit: 4 t.string "devis", limit: 255 t.string "state", limit: 255 t.string "string", limit: 255 + t.decimal "qte", precision: 10, scale: 2, default: 1.0 end add_index "accepted_offers", ["customer_id"], name: "index_accepted_offers_on_customer_id", using: :btree @@ -157,6 +158,23 @@ ActiveRecord::Schema.define(version: 20161018122307) do t.datetime "updated_at", null: false end + create_table "customer_messages", force: :cascade do |t| + t.string "title", limit: 255 + t.text "message", limit: 65535 + t.string "tel", limit: 255 + t.integer "expediteur_id", limit: 4 + t.string "expediteur_mail", limit: 255 + t.string "destinataire_mail", limit: 255 + t.integer "destinataire_id", limit: 4 + t.integer "parent_id", limit: 4 + t.datetime "last_message_at" + t.string "remote_ip", limit: 255 + t.boolean "enabled", limit: 1 + t.boolean "readed", limit: 1 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "customer_newsgroups", force: :cascade do |t| t.integer "customer_id", limit: 4 t.integer "newsgroup_id", limit: 4 @@ -227,6 +245,8 @@ ActiveRecord::Schema.define(version: 20161018122307) do t.text "particulars_text", limit: 65535 t.float "capital", limit: 24 t.string "role_signataire", limit: 255 + t.boolean "referent", limit: 1, default: false + t.boolean "chef_reseau", limit: 1, default: false end create_table "data_files", force: :cascade do |t| @@ -487,17 +507,19 @@ ActiveRecord::Schema.define(version: 20161018122307) do add_index "need_categories", ["parent_id"], name: "index_need_categories_on_parent_id", using: :btree create_table "needs", force: :cascade do |t| - t.string "title", limit: 255 - t.text "description", limit: 65535 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "author_id", limit: 4 + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "author_id", limit: 4 t.datetime "deleted_at" - t.string "state", limit: 255 - t.integer "category_id", limit: 4 - t.string "devis", limit: 255 - t.integer "image_file_id", limit: 4 - t.text "note", limit: 65535 + t.string "state", limit: 255 + t.integer "category_id", limit: 4 + t.string "devis", limit: 255 + t.integer "image_file_id", limit: 4 + t.text "note", limit: 65535 + t.integer "referent_negos_id", limit: 4 + t.integer "referent_technique_id", limit: 4 end add_index "needs", ["author_id"], name: "index_needs_on_author_id", using: :btree @@ -524,14 +546,26 @@ ActiveRecord::Schema.define(version: 20161018122307) do t.datetime "updated_at" end + create_table "offer_reseauxes", force: :cascade do |t| + t.integer "offer_id", limit: 4 + t.integer "reseaux_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "offer_reseauxes", ["offer_id"], name: "index_offer_reseauxes_on_offer_id", using: :btree + add_index "offer_reseauxes", ["reseaux_id"], name: "index_offer_reseauxes_on_reseaux_id", using: :btree + create_table "offers", force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.float "price", limit: 24 t.float "fee_percentage", limit: 24 t.integer "need_id", limit: 4 t.string "supplier", limit: 255 t.datetime "deleted_at" + t.decimal "qte", precision: 10, scale: 2, default: 1.0 + t.decimal "gain", precision: 10, scale: 2 end add_index "offers", ["deleted_at"], name: "index_offers_on_deleted_at", using: :btree @@ -554,6 +588,24 @@ ActiveRecord::Schema.define(version: 20161018122307) do t.datetime "updated_at" end + create_table "reseaux_customers", force: :cascade do |t| + t.integer "reseaux_id", limit: 4 + t.integer "customer_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "reseaux_customers", ["customer_id"], name: "index_reseaux_customers_on_customer_id", using: :btree + add_index "reseaux_customers", ["reseaux_id"], name: "index_reseaux_customers_on_reseaux_id", using: :btree + + create_table "reseauxes", force: :cascade do |t| + t.string "name", limit: 255 + t.text "description", limit: 65535 + t.integer "chef_reseau_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "sessions", force: :cascade do |t| t.string "session_id", limit: 255, null: false t.text "data", limit: 65535 @@ -616,10 +668,11 @@ ActiveRecord::Schema.define(version: 20161018122307) do create_table "wishes", force: :cascade do |t| t.integer "customer_id", limit: 4 t.integer "need_id", limit: 4 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.text "note", limit: 65535 t.string "devis", limit: 255 + t.decimal "qte", precision: 10, scale: 2, default: 1.0 end add_foreign_key "customer_newsgroups", "customers" @@ -630,4 +683,8 @@ ActiveRecord::Schema.define(version: 20161018122307) do add_foreign_key "domain_need_categories", "need_categories" add_foreign_key "domain_needs", "domains" add_foreign_key "domain_needs", "needs" + add_foreign_key "offer_reseauxes", "offers" + add_foreign_key "offer_reseauxes", "reseauxes" + add_foreign_key "reseaux_customers", "customers" + add_foreign_key "reseaux_customers", "reseauxes" end diff --git a/fichier-final.pdf b/fichier-final.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bf94b7a851f705e685205baf41b7cb4187e38891 GIT binary patch literal 827839 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