Support IT MAJ 1 рік тому
батько
коміт
0bbe460972

+ 4 - 0
.gitignore

@@ -167,3 +167,7 @@ static/uploads/Logo-Polyclinique-Majorelle_-_FV.png
 static/uploads/Logo-Polyclinique-Majorelle_-BLC.png
 gest_user/migrations/__pycache__/0022_auto_20240806_1302.cpython-312.pyc
 parc_info/migrations/__pycache__/0085_auto_20240806_1302.cpython-312.pyc
+gest_clin/migrations/__pycache__/0003_auto_20240924_0725.cpython-312.pyc
+gest_user/migrations/__pycache__/0023_auto_20240924_0725.cpython-312.pyc
+parc_info/migrations/__pycache__/0086_auto_20241202_1303.cpython-312.pyc
+parc_info/migrations/__pycache__/0087_alter_pic_pic_adresse_ip.cpython-312.pyc

+ 33 - 0
gest_clin/migrations/0003_auto_20240924_0725.py

@@ -0,0 +1,33 @@
+# Generated by Django 3.2.23 on 2024-09-24 07:25
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0025_auto_20240730_2241'),
+        ('gest_clin', '0002_auto_20231229_0916'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='clinique',
+            options={'ordering': ['CLIN_Nom'], 'verbose_name': 'Clinique', 'verbose_name_plural': 'Cliniques'},
+        ),
+        migrations.AlterModelOptions(
+            name='services',
+            options={'ordering': ['SERVICE_Nom'], 'verbose_name': 'Service', 'verbose_name_plural': 'Services'},
+        ),
+        migrations.AddField(
+            model_name='clinique',
+            name='CLIN_Grp',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='core.groupe', verbose_name='Groupe de Clinique'),
+        ),
+        migrations.AddField(
+            model_name='clinique',
+            name='CLIN_Serial',
+            field=models.CharField(choices=[('UNI', 'Unique'), ('Par Service', 'Par Service')], default='RAS', max_length=16, verbose_name='Type de Sérialisation'),
+        ),
+    ]

+ 11 - 0
gest_clin/models.py

@@ -3,9 +3,18 @@ from django.db import models
 from django.utils import timezone
 from django.template.defaultfilters import slugify
 
+from core.models import Groupe as Clinique_GRP
+
+SERILISATION = [
+	('UNI', 'Unique'),
+	('Par Service', 'Par Service'),
+]
+
 class Clinique(models.Model):
 	CLIN_Nom = models.CharField("Nom de Clinique", max_length=64, unique=True)
 	CLIN_Anag = models.CharField("Anagrame de Clinique", max_length=3, unique=True)
+	CLIN_Serial = models.CharField("Type de Sérialisation", max_length=16, choices=SERILISATION, default='RAS')
+	CLIN_Grp = models.ForeignKey(Clinique_GRP,verbose_name="Groupe de Clinique", blank = True, null = True, on_delete=models.PROTECT)
 	
 	def __str__(self):
 		return self.CLIN_Nom
@@ -13,6 +22,7 @@ class Clinique(models.Model):
 	class Meta:
 		verbose_name = "Clinique"
 		verbose_name_plural = "Cliniques"
+		ordering = ['CLIN_Nom', ]
 		
 class Batiments(models.Model):
 	BAT_Clin = models.ForeignKey(Clinique, on_delete=models.PROTECT)
@@ -37,4 +47,5 @@ class Services(models.Model):
 	class Meta:
 		verbose_name = "Service"
 		verbose_name_plural = "Services"
+		ordering = ['SERVICE_Nom', ]
 

+ 13 - 0
gest_user/api.py

@@ -143,6 +143,19 @@ def user_complete(request, id):
 	item.save()
 	return HttpResponse(item.id)
 
+def user_close(request, id):
+	try:
+		item = GES_User.objects.get(id = id)
+	except:
+		return HttpResponse('Error')
+
+	if item.GES_SUP == False :
+		item.GES_SUP = True
+	else :
+		item.GES_SUP = False
+	item.save()
+	return HttpResponse(item.id)
+
 def app_edit(request, id):
 	get_search = request.GET.get('get_search', '')
 	print(get_search)

+ 31 - 0
gest_user/migrations/0023_auto_20240924_0725.py

@@ -0,0 +1,31 @@
+# Generated by Django 3.2.23 on 2024-09-24 07:25
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('gest_user', '0022_auto_20240806_1302'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='ges_applink',
+            options={'ordering': ['GES_APPLink_APP']},
+        ),
+        migrations.AlterModelOptions(
+            name='ges_user',
+            options={'ordering': ['GES_Nom'], 'verbose_name': 'Les utilisateurs', 'verbose_name_plural': 'Les utilisateurs'},
+        ),
+        migrations.AddField(
+            model_name='ges_user',
+            name='GES_Date_Sup',
+            field=models.DateField(blank=True, null=True, verbose_name='Date de départ'),
+        ),
+        migrations.AddField(
+            model_name='ges_user',
+            name='GES_SUP',
+            field=models.BooleanField(default=False, verbose_name='Fermeture du compte réaliser'),
+        ),
+    ]

+ 8 - 2
gest_user/models.py

@@ -60,8 +60,10 @@ class GES_User(models.Model):
 	GES_Fonction = models.ForeignKey(GES_Fonction, verbose_name="Fonction", on_delete=models.PROTECT, blank=True, null=True)
 	GES_APPs = models.ManyToManyField(GES_APP, verbose_name="Applications", limit_choices_to={'GESAP_Actif': True},)
 	GES_Date = models.DateField("Date d'arrivée", blank=True, null=True)
+	GES_Date_Sup = models.DateField("Date de départ", blank=True, null=True)
 	GES_OK = models.BooleanField("Création complété", default = False)
-	ordering = ['GES_Service']
+	GES_SUP = models.BooleanField("Fermeture du compte réaliser", default = False)
+	
 
 	def save(self, *args, **kwargs) :
 		if self.GES_Motdepasse == "" :
@@ -74,6 +76,7 @@ class GES_User(models.Model):
 	class Meta:
 		verbose_name = "Les utilisateurs"
 		verbose_name_plural = "Les utilisateurs"
+		ordering = ['GES_Nom']
 
 class GES_APPLink(models.Model):
 	GES_APPLink_User = models.ForeignKey(GES_User, on_delete=models.CASCADE)
@@ -83,6 +86,9 @@ class GES_APPLink(models.Model):
 	GES_APPLink_Sup = models.CharField("Info supplémentaire", max_length=16, blank=True)
 	GES_APPLink_Create = models.BooleanField("Crée", default = False)
 
+	class Meta:
+		ordering = ['GES_APPLink_APP']
+
 class GES_APPMat(models.Model):
 	GES_Fonction = models.ForeignKey(GES_Fonction, verbose_name="Fonction", on_delete=models.PROTECT, blank=True, null=True)
 	GES_Service = models.ManyToManyField(Clin_Services, verbose_name="Services")
@@ -104,7 +110,7 @@ class GES_User_form(forms.ModelForm):
 	class Meta:
 		model = GES_User
 		fields = '__all__'
-		exclude = ['GES_APPs','GES_OK',]
+		exclude = ['GES_APPs','GES_OK','GES_SUP']
 
 class GES_APPLink_form(forms.ModelForm):
 	class Meta:

+ 8 - 2
gest_user/templates/gest_user_api_get.html

@@ -1,7 +1,11 @@
 {% load crispy_forms_tags %}
 <div class="modal-dialog modal-lg" role="document">
 		<div class="modal-content">
-			{% if item.GES_OK == True %}
+			{% if item.GES_OK == True and item.GES_Date_Sup and item.GES_SUP == True%}
+				<div class="modal-header border-danger bg-danger">
+			{% elif item.GES_OK == True and item.GES_Date_Sup%}
+				<div class="modal-header border-warning bg-warning">
+			{% elif item.GES_OK == True %}
 				<div class="modal-header border-success bg-success">
 			{% else%}
 				<div class="modal-header">
@@ -18,7 +22,8 @@
 					<tr><td>Site : </td><td> {{item.GES_Site}} </td></tr>
 					<tr><td>Service : </td><td> {{item.GES_Service}} </td></tr>
 					<tr><td>Fonction : </td><td> {{item.GES_Fonction}} </td></tr>
-					<tr><td>Date d'arrivée : </td><td> {% if item.GES_Date %}{{item.GES_Date}}{% else %}&nbsp;{% endif %} </td></tr>
+					{% if item.GES_Date %}<tr><td>Date d'arrivée : </td><td> {% if item.GES_Date %}{{item.GES_Date}}{% else %}&nbsp;{% endif %} </td></tr>{% endif %}
+					{% if item.GES_Date_Sup %}<tr><td>Date de départ : </td><td> {% if item.GES_Date_Sup %}{{item.GES_Date_Sup}}{% else %}&nbsp;{% endif %} </td></tr>{% endif %}
 				</table>
 
 				<h4>Liste des applications sélectionnées avec le profil</h4>
@@ -72,6 +77,7 @@
 
 		<div class="modal-footer">
 			{% if item.isok == 1 and item.GES_OK == False %}<button type="button" class="btn btn-success" onclick="bt_edit_complete({{item.id}})"><i class="fas fa-check"></i> Finaliser</button>{% endif %}
+			{% if item.GES_OK == True and item.GES_Date_Sup and item.GES_SUP == False %}<button type="button" class="btn btn-danger" onclick="bt_edit_close({{item.id}})"><i class="fas fa-check"></i> Compte cloturé</button>{% endif %}
 			<a class="btn btn-dark" target="_blank" href="{% url 'gest_user_api_user_get_for_send' item.id %}" role="button"><i class="fa fa-print"></i> Pour impression</a>
 			<button type="button" class="btn btn-dark" onclick="bt_edit_info({{item.id}})"><i class="far fa-edit"></i> Mise à jour</button>
 		</div>

+ 11 - 3
gest_user/templates/gest_user_api_get_list.html

@@ -6,22 +6,30 @@
 			<th scope="col">Fonction</th>
 			<th scope="col">Nom</th>
 			<th scope="col">Prénom</th>
+			<th scope="col">Date d'arrivée</th>
+			<th scope="col">Date de départ</th>
 			<th scope="col">Applications</th>
 			<th scope="col">Outils</th>
 		</tr>
 	</thead>
-	<tbody>
+	
 		{% for item in data_query %}
-			{% if item.GES_OK == True %}
+			{% if item.GES_OK == True and item.GES_Date_Sup and item.GES_SUP == True %}
+				<tr class="table-danger">
+			{% elif item.GES_OK == True and item.GES_Date_Sup %}
+				<tr class="table-warning">
+			{% elif item.GES_OK == True %}
 				<tr class="table-success">
 			{% else %}
 				<tr>
 			{% endif %}
-				<td>{{item.get_GES_L_Site_display}}</td>
+				<td>{{item.GES_Site}}</td>
 				<td>{{item.GES_Service}}</td>
 				<td>{{item.GES_Fonction}}</td>
 				<td>{{item.GES_Nom}}</td>
 				<td>{{item.GES_Prenom}}</td>
+				<td>{% if item.GES_Date %}{{item.GES_Date}}{% else %}&nbsp;{% endif %}</td>
+				<td>{% if item.GES_Date_Sup %}{{item.GES_Date_Sup}}{% else %}&nbsp;{% endif %}</td>
 				<td>{% if item.GES_APPs != "" %}{% for apps in item.GES_APPs.all %}{{ apps.GESAP_Nom }}{% if not forloop.last %}, {% endif %}{% endfor %}{% else %}&nbsp;{% endif %}</td>
 				<td onmouseover="this.style.cursor='pointer';">
 					<a class="text-reset" target="_blank" href="{% url 'gest_user_api_user_get_for_send' item.id %}"><i class="fa fa-print"></i></a>

+ 35 - 2
gest_user/templates/gest_user_index.html

@@ -112,6 +112,17 @@ function bt_edit_complete(id){
 	});
 };
 
+function bt_edit_close(id){
+	var get_search = document.getElementById("id_PSearch").value
+	$.ajax({
+			type : 'GET',
+			url: '/user/api/close/'+id,
+			success: function(data) {
+				window.open("/user/liste?get_id="+data+"&get_search="+get_search, "_self" );
+			},
+	});
+};
+
 function bt_send_edit(){
 	document.getElementById("form_edit").submit();
 };
@@ -143,7 +154,6 @@ $(document).ready(function(){ onloading(); });
 
 {% block right_panel %}
 <div class="card-body">
-
 	<div id="div_id_PSearch" class="form-group">
 		<label for="id_PSearch" class=" requiredField">Recherche d'un Utilisateur (min 3 caractères) </label>
 		<div class=""><input type="text" name="PSearch" maxlength="128" class="textinput textInput form-control" required="" id="id_PSearch" oninput="get_list()" value="{{page.search}}"></div>
@@ -174,7 +184,30 @@ $(document).ready(function(){ onloading(); });
 			{% endfor %}
 			</tbody>
 		</table>
-		{% endif %}
+	{% endif %}
+	{% if planning_query_clos %}
+	<p>Agenda des comptes à cloturé :</p>
+	<table class="table table-hover">
+		<thead class="thead-dark">
+			<tr>
+				<th scope="col">&nbsp;</th>
+				<th scope="col">Service</th>
+				<th scope="col">Nom - Prénom</th>
+				<th scope="col">Date de départ</th>
+			</tr>
+		</thead>
+		<tbody>
+		{% for item in planning_query_clos%}
+		<tr>
+			<td onmouseover="this.style.cursor='pointer';"><i class="fas fa-search-plus" onclick="bt_get_info({{item.id}})"></i></td>
+			<td>{{item.GES_Service}}</td>
+			<td>{{item.GES_Nom}} {{item.GES_Prenom}}</td>
+			<td>{{item.GES_Date}}</td>
+		</tr>
+		{% endfor %}
+		</tbody>
+	</table>
+	{% endif %}
 
 </div>
 {% endblock %}

+ 1 - 0
gest_user/urls.py

@@ -18,6 +18,7 @@ urlpatterns = [
 	re_path('api/app/remove/(?P<id>\d+)', api.app_remove, name='gest_user_api_app_remove'),
 	re_path('api/edit/(?P<id>\d+)', api.user_edit, name='gest_user_api_user_edit'),
 	re_path('api/complete/(?P<id>\d+)', api.user_complete, name='gest_user_api_user_complete'),
+	re_path('api/close/(?P<id>\d+)', api.user_close, name='gest_user_api_user_close'),
 
 	# client
 	path('liste', views.index, name='gest_user_index'),

+ 3 - 1
gest_user/views.py

@@ -37,10 +37,12 @@ def index(request):
 	page.p_right = "Les Outils :"
 
 	planning_query = GES_User.objects.exclude(GES_Date = None).filter(GES_OK = False).order_by('GES_Date', 'GES_Service', 'GES_Nom', 'GES_Prenom')
+	planning_query_clos = GES_User.objects.exclude(GES_Date_Sup = None).exclude(GES_OK = False).filter(GES_SUP = False).order_by('GES_Date', 'GES_Service', 'GES_Nom', 'GES_Prenom')
 	
 	html = template.render({
 			'page': page,
 			'planning_query': planning_query,
+			'planning_query_clos': planning_query_clos,
 			'user': request.user,
 		}, request)
 		
@@ -131,7 +133,7 @@ def app_edit(request, id):
 				print("hoo un apta")
 				item = GES_APPLink.objects.get(id = id)
 				data = get_data_value("dernier-apta")
-				if item.GES_APPLink_Sup > data :
+				if int(item.GES_APPLink_Sup) > int(data) :
 					print ("need update compteur")
 					data = update_data_value("dernier-apta", item.GES_APPLink_Sup)
 

+ 6 - 1
parc_info/admin.py

@@ -6,11 +6,16 @@ from .models import *
 @admin.register(PIC)
 class PICAdmin(ImportExportModelAdmin):
 	list_display = ('PIC_Nom_netbios', 'PIC_Utilisateur', 'PIC_NUnic', 'PIC_L_Statut', 'PIC_Site', 'PIC_Service', 'PIC_L_Chassi_Type')
-	list_filter = ('PIC_Site', 'PIC_Deg', 'PIC_with_Snow', 'PIC_L_Chassi_Type', 'PIC_L_Statut', 'PIC_Service','PIC_CPU','PIC_RAM')
+	list_filter = ('PIC_Site', 'PIC_Deg', 'PIC_L_Chassi_Type', 'PIC_L_Statut', 'PIC_Service','PIC_CPU','PIC_RAM')
 	search_fields = ['PIC_Nom_netbios', 'PIC_Adresse_IP', 'PIC_Utilisateur', 'PIC_Service__SERVICE_Nom', 'PIC_Service__SERVICE_Anag','PIC_Precisions']
 	exclude =('PIC_L_Service',)
 	pass
 
+@admin.register(VLAN)
+class VLANAdmin(admin.ModelAdmin):
+	list_display = ('VLAN_Nom', 'VLAN_Site', 'VLAN_IN', 'VLAN_Des', 'VLAN_Plag', 'VLAN_Route')
+	pass
+
 @admin.register(PIC_History)
 class PIC_HistoryAdmin(admin.ModelAdmin):
 	list_display = ('H_PIC', 'H_Date', 'H_Commentaire')

+ 6 - 2
parc_info/api.py

@@ -188,7 +188,9 @@ def user_get_list(request):
 	template = loader.get_template('parc_info_api_user_get_list.html')
 
 	get_search = request.GET.get('get_search', '')
-	if get_search :
+	get_filtre = request.GET.get('get_filtre', '')
+	
+	if get_search:
 		#print(get_search)
 		data_query_1 = PIC.objects.exclude(PIC_L_Statut__in = ['INAPTE', 'EN STOCK']).filter(Q(PIC_Nom_netbios__icontains=get_search)
 										|Q(PIC_Site__CLIN_Anag__icontains=get_search)
@@ -211,7 +213,9 @@ def user_get_list(request):
 										|Q(PIC_L_Chassi_Type__icontains=get_search)
 										).order_by('PIC_Site__CLIN_Anag','PIC_Service__SERVICE_Nom','PIC_NUnic')
 		data_query = list(chain(data_query_1, data_query_2))
-
+	
+	elif get_filtre != "ALL" :
+		data_query = PIC.objects.exclude(PIC_L_Statut = 'INAPTE').filter(PIC_L_Chassi_Type = get_filtre).order_by('PIC_Site__CLIN_Anag','PIC_Service__SERVICE_Nom','PIC_NUnic','PIC_L_Statut')
 	else :
 		#print("not get_search")
 		data_query = PIC.objects.exclude(PIC_L_Statut__in = ['INAPTE', 'EN STOCK']).order_by('PIC_Site__CLIN_Anag','PIC_Service__SERVICE_Nom','PIC_NUnic','PIC_L_Statut')

+ 134 - 0
parc_info/apps.py

@@ -1,3 +1,4 @@
+import sys
 from django.apps import AppConfig
 
 
@@ -5,3 +6,136 @@ class ParcInfoConfig(AppConfig):
 	default_auto_field = 'django.db.models.BigAutoField'
 	name = 'parc_info'
 	verbose_name  = 'Parc Informatique'
+
+	def ready(self):
+
+		if 'migrate' in sys.argv:
+			return
+		
+		print("-- Démarage de la gestion du Parc --")
+		print(">> Vérification des variables d'environement")
+
+		from core.models import Data
+		try :
+			data = Data.objects.get(d_titre_slugify = "range-imp")
+		except:
+			data = Data()
+			data.d_titre = "range-imp"
+			data.d_type = "IMP"
+			data.d_variable = "900;999"
+			data.save()
+		try :
+			data = Data.objects.get(d_titre_slugify = "range-pc")
+		except:
+			data = Data()
+			data.d_titre = "range-pc"
+			data.d_type = "PC"
+			data.d_variable = "1;899"
+			data.save()
+
+		print(">> Vérification des pages")
+
+		from core.models import Page
+		try :
+			page = Page.objects.get(p_titre_slugify = "parc")
+		except :
+			page = Page()
+
+		page.p_titre = "Parc"
+		page.p_icone = "fas fa-map-marked-alt"
+		page.p_adresse = "/parc"
+		page.p_menu_position = "haut"
+		page.p_menu_est_parent = "True"
+		page.p_type = "sys"
+		page.p_menu_poid = 90
+		page.p_publier = False
+		
+		page.save()
+
+		tmp_page_parent = page
+
+		try :
+			page = Page.objects.get(p_titre_slugify = "les-equipements-utilisateurs")
+		except :
+			page = Page()
+
+		page.p_titre = "Les équipements utilisateurs"
+		page.p_icone = "fas fa-desktop"
+		page.p_adresse = "/parc/clients"
+		page.p_menu_position = "haut"
+		page.p_menu_est_parent = "False"
+		page.p_menu_parent = tmp_page_parent
+		page.p_type = "sys"
+		page.p_menu_poid = 90
+		page.p_publier = True
+
+		page.save()
+
+		try :
+			page = Page.objects.get(p_titre_slugify = "les-serveurs")
+		except :
+			page = Page()
+
+		page.p_titre = "Les serveurs"
+		page.p_icone = "fas fa-server"
+		page.p_adresse = "/parc/serveurs"
+		page.p_menu_position = "haut"
+		page.p_menu_est_parent = "False"
+		page.p_menu_parent = tmp_page_parent
+		page.p_type = "sys"
+		page.p_menu_poid = 90
+		page.p_publier = True
+
+		page.save()
+
+		try :
+			page = Page.objects.get(p_titre_slugify = "les-switchs")
+		except :
+			page = Page()
+
+		page.p_titre = "Les switchs"
+		page.p_icone = "fas fa-ethernet"
+		page.p_adresse = "/parc/switch"
+		page.p_menu_position = "haut"
+		page.p_menu_est_parent = "False"
+		page.p_menu_parent = tmp_page_parent
+		page.p_type = "sys"
+		page.p_menu_poid = 90
+		page.p_publier = True
+
+		page.save()
+
+		try :
+			page = Page.objects.get(p_titre_slugify = "listing-des-imprimantes")
+		except :
+			page = Page()
+
+		page.p_titre = "Listing des imprimantes"
+		page.p_icone = "fas fa-print"
+		page.p_adresse = "/parc/clients/imp"
+		page.p_menu_position = "haut"
+		page.p_menu_est_parent = "False"
+		page.p_menu_parent = tmp_page_parent
+		page.p_type = "sys"
+		page.p_menu_poid = 90
+		page.p_publier = True
+
+		page.save()
+
+		try :
+			page = Page.objects.get(p_titre_slugify = "inventaire")
+		except :
+			page = Page()
+
+		page.p_titre = "Inventaire par services"
+		page.p_titre_slugify = "inventaire"
+		page.p_icone = "fas fa-boxes"
+		page.p_adresse = "/parc/clients/stat/par-services"
+		page.p_menu_position = "haut"
+		page.p_menu_est_parent = "False"
+		page.p_menu_parent = tmp_page_parent
+		page.p_type = "sys"
+		page.p_menu_poid = 90
+		page.p_publier = True
+
+		page.save()

+ 26 - 0
parc_info/migrations/0086_auto_20241202_1303.py

@@ -0,0 +1,26 @@
+# Generated by Django 3.2.23 on 2024-12-02 13:03
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('parc_info', '0085_auto_20240806_1302'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='pic',
+            name='PIC_with_Snow',
+        ),
+        migrations.RemoveField(
+            model_name='pis',
+            name='PIS_with_Snow',
+        ),
+        migrations.AlterField(
+            model_name='pic',
+            name='PIC_Adresse_Mac',
+            field=models.CharField(blank=True, max_length=64, null=True, verbose_name='Adresse MAC'),
+        ),
+    ]

+ 18 - 0
parc_info/migrations/0087_alter_pic_pic_adresse_ip.py

@@ -0,0 +1,18 @@
+# Generated by Django 3.2.23 on 2024-12-02 15:41
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('parc_info', '0086_auto_20241202_1303'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='pic',
+            name='PIC_Adresse_IP',
+            field=models.CharField(default='DHCP', max_length=64, verbose_name='Adresse IP'),
+        ),
+    ]

+ 2 - 4
parc_info/models.py

@@ -79,7 +79,6 @@ class PIC(models.Model):
 	PIC_Deg = models.BooleanField("Poste avec procédure dégradé", default=False)
 
 	PIC_is_for_Cadre = models.BooleanField("Poste utiliser pas des RUS ou Cadre", default=False)
-	PIC_with_Snow = models.BooleanField("Sync avec Snow", default=False)
 	PIC_with_Office = models.BooleanField("Office installé sur le poste", default=False)
 
 	PIC_Nom_netbios = models.CharField("Nom NETBIOS", max_length=64, blank=True, null=True)
@@ -89,8 +88,8 @@ class PIC(models.Model):
 	PIC_Service = models.ForeignKey(Clin_Services, verbose_name="Service", on_delete=models.PROTECT, blank=True, null=True)
 	PIC_Local = models.CharField("Localisation", max_length=64, blank=True, null=True)
 
-	PIC_Adresse_IP = models.CharField("Adresse IP", max_length=32, default="DHCP" )
-	PIC_Adresse_Mac = models.CharField("Adresse MAC", max_length=18, blank=True, null=True)
+	PIC_Adresse_IP = models.CharField("Adresse IP", max_length=64, default="DHCP" )
+	PIC_Adresse_Mac = models.CharField("Adresse MAC", max_length=64, blank=True, null=True)
 
 	PIC_OS = models.CharField("OS", max_length=64, blank=True, null=True)
 	PIC_Marque = models.CharField("Marque", max_length=64, blank=True, null=True)
@@ -146,7 +145,6 @@ class PIS(models.Model):
 	PIS_Nom_netbios = models.CharField("Nom NETBIOS", max_length=64, blank=True, null=True)
 	PIS_Friendly_Name = models.CharField("Friendly Name", max_length=64, blank=True, null=True)
 	PIS_OS = models.CharField("OS", max_length=64, blank=True, null=True)
-	PIS_with_Snow = models.BooleanField("Sync avec Snow", default=False)
 	PIS_with_Web = models.BooleanField("Portail web", default=False)
 	PIS_Adresse_IP = models.CharField("Adresse IP", max_length=64, blank=True, null=True)
 	PIS_Adresse_Mac = models.CharField("Adresse MAC", max_length=64, blank=True, null=True)

+ 70 - 70
parc_info/templates/parc_info_api_user_get.html

@@ -1,75 +1,75 @@
 <div class="modal-dialog" role="document">
-		<div class="modal-content">
-			{% if item.PIC_L_Statut == "PREPROD" %}
-				<div class="modal-header border-success bg-success">
-			{% elif item.PIC_L_Statut == "EN STOCK" %}
-				<div class="modal-header border-info bg-info">
-			{% elif item.PIC_L_Statut == "HS" %}
-				<div class="modal-header border-warning bg-warning">
-			{% elif item.PIC_L_Statut == "ADEPROD" %}
-				<div class="modal-header border-danger bg-danger">
-			{% else%}
-				<div class="modal-header">
-			{% endif %}
-			
-				<h5 class="modal-title">Détail d'un poste utilisateur</h5>
-				<button type="button" class="btn btn-sm btn-dark close" data-dismiss="modal" aria-label="Close">
-				<span aria-hidden="true">&times;</span>
-				</button>
-			</div>
-			<div class="modal-body">
-				<table class="table table-sm">
-					<tr><td>Site : </td><td>{{item.PIC_Site}}</td></tr>
-					<tr><td>Type de chassi : </td><td>{{item.get_PIC_L_Chassi_Type_display}}</td></tr>
-					<tr><td>Service : </td><td>{{item.PIC_Service}}</td></tr>
-					<tr><td>Nom NETBIOS : </td><td>{{item.PIC_Nom_netbios}}</td></tr>
-					<tr><td>Utilisateur : </td><td>{{item.PIC_Utilisateur}}</td></tr>
-					{%if item.PIC_OS != None %}<tr><td>OS : </td><td>{{item.PIC_OS}}</td></tr>{% endif %}
-					<tr><td>Adresse IP : </td><td>{{item.PIC_Adresse_IP}}</td></tr>
-					{%if item.PIC_L_Chassi_Type != "IMP" %}<tr><td>Adresse MAC : </td><td>{{item.PIC_Adresse_Mac}}</td></tr>{% endif %}
-					{%if item.PIC_Marque != "" %}<tr><td>Marque : </td><td>{{item.PIC_Marque}}</td></tr>{% endif %}
-					{%if item.PIC_Type != "" %}<tr><td>Modèle : </td><td>{{item.PIC_Type}}</td></tr>{% endif %}
-					{%if item.PIC_SN != "" %}<tr><td>SN : </td><td>{{item.PIC_SN}}</td></tr>{% endif %}
-					{%if item.PIC_CPU != None %}<tr><td>CPU : </td><td>{{item.PIC_CPU}}</td></tr>{% endif %}
-					{%if item.PIC_RAM != 0 %}<tr><td>RAM : </td><td>{{item.PIC_RAM}} Go</td></tr>{% endif %}
-					<tr><td>Localisation : </td><td>{{item.PIC_Local}}</td></tr>
-					{%if item.PIC_Precisions != "" %}<tr><td>Precisions : </td><td>{{item.PIC_Precisions}}</td></tr>{% endif %}
-					{%if item.PIC_Commentaires != "" %}<tr><td>Commentaires : </td><td>{{item.PIS_Commentaires}}</td></tr>{% endif %}
-				</table>
-				{% if item.accessoir %}
-				<h6>Accessoires lié au poste</h6>
-				<table class="table table-sm">
-					{% for accessoir in item.accessoir %}
-						<tr>
-							<td>
-								{% if accessoir.Accessory_N_slugify == "double-ecrans"%}
-									<i class="{{accessoir.Accessory_icone}}"></i><i class="{{accessoir.Accessory_icone}}"></i>
-								{% else %}
-									<i class="{{accessoir.Accessory_icone}}"></i>
-								{% endif %}
-							</td>
-							<td>{{accessoir.Accessory_Nom}}</td>
-						</tr>
-					{% endfor %}
-				</table>
-				{% endif %}
-			</div>
-			{% if item.PIC_L_Statut == "PREPROD" %}
-				<div class="modal-footer border-success bg-success">
-			{% elif item.PIC_L_Statut == "EN STOCK" %}
-				<div class="modal-footer border-info bg-info">
-			{% elif item.PIC_L_Statut == "HS" %}
-				<div class="modal-footer border-warning bg-warning">
-			{% elif item.PIC_L_Statut == "ADEPROD" %}
-				<div class="modal-footer border-danger bg-danger">
-			{% else%}
-				<div class="modal-footer">
+	<div class="modal-content">
+		{% if item.PIC_L_Statut == "PREPROD" %}
+			<div class="modal-header border-success bg-success">
+		{% elif item.PIC_L_Statut == "EN STOCK" %}
+			<div class="modal-header border-info bg-info">
+		{% elif item.PIC_L_Statut == "HS" %}
+			<div class="modal-header border-warning bg-warning">
+		{% elif item.PIC_L_Statut == "ADEPROD" %}
+			<div class="modal-header border-danger bg-danger">
+		{% else%}
+			<div class="modal-header">
+		{% endif %}
+		
+			<h5 class="modal-title">Détail d'un poste utilisateur</h5>
+			<button type="button" class="btn btn-sm btn-dark close" data-dismiss="modal" aria-label="Close">
+			<span aria-hidden="true">&times;</span>
+			</button>
+		</div>
+		<div class="modal-body">
+			<table class="table table-sm">
+				<tr><td>Site : </td><td>{{item.PIC_Site}}</td></tr>
+				<tr><td>Type de chassi : </td><td>{{item.get_PIC_L_Chassi_Type_display}}</td></tr>
+				<tr><td>Service : </td><td>{{item.PIC_Service}}</td></tr>
+				<tr><td>Nom NETBIOS : </td><td>{{item.PIC_Nom_netbios}}</td></tr>
+				<tr><td>Utilisateur : </td><td>{{item.PIC_Utilisateur}} {% if item.PIC_Utilisateur != item.PIC_Utilisateur_Fq and item.PIC_Utilisateur_Fq != none %} - {{item.PIC_Utilisateur_Fq}} (Fq){% endif %}</td></tr>
+				{%if item.PIC_OS != None %}<tr><td>OS : </td><td>{{item.PIC_OS}}</td></tr>{% endif %}
+				<tr><td>Adresse IP : </td><td>{{item.PIC_Adresse_IP}}</td></tr>
+				{%if item.PIC_L_Chassi_Type != "IMP" %}<tr><td>Adresse MAC : </td><td>{{item.PIC_Adresse_Mac}}</td></tr>{% endif %}
+				{%if item.PIC_Marque != "" %}<tr><td>Marque : </td><td>{{item.PIC_Marque}}</td></tr>{% endif %}
+				{%if item.PIC_Type != "" %}<tr><td>Modèle : </td><td>{{item.PIC_Type}}</td></tr>{% endif %}
+				{%if item.PIC_SN != "" %}<tr><td>SN : </td><td>{{item.PIC_SN}}</td></tr>{% endif %}
+				{%if item.PIC_CPU != None %}<tr><td>CPU : </td><td>{{item.PIC_CPU}}</td></tr>{% endif %}
+				{%if item.PIC_RAM != 0 %}<tr><td>RAM : </td><td>{{item.PIC_RAM}} Go</td></tr>{% endif %}
+				<tr><td>Localisation : </td><td>{{item.PIC_Local}}</td></tr>
+				{%if item.PIC_Precisions != "" %}<tr><td>Precisions : </td><td>{{item.PIC_Precisions}}</td></tr>{% endif %}
+				{%if item.PIC_Commentaires != "" %}<tr><td>Commentaires : </td><td>{{item.PIS_Commentaires}}</td></tr>{% endif %}
+			</table>
+			{% if item.accessoir %}
+			<h6>Accessoires lié au poste</h6>
+			<table class="table table-sm">
+				{% for accessoir in item.accessoir %}
+					<tr>
+						<td>
+							{% if accessoir.Accessory_N_slugify == "double-ecrans"%}
+								<i class="{{accessoir.Accessory_icone}}"></i><i class="{{accessoir.Accessory_icone}}"></i>
+							{% else %}
+								<i class="{{accessoir.Accessory_icone}}"></i>
+							{% endif %}
+						</td>
+						<td>{{accessoir.Accessory_Nom}}</td>
+					</tr>
+				{% endfor %}
+			</table>
 			{% endif %}
-
-			{% if item.PIC_L_Chassi_Type == "IMP" and item.PIC_Adresse_IP != none %}<a class="btn btn-dark" href="http://{{item.PIC_Adresse_IP}}" target="_blank" role="button"><i class="fas fa-external-link-alt"></i> WebAdmin</a>{% endif %}
-			<button type="button" class="btn btn-dark" onclick="bt_get_user_hist({{item.id}})"><i class="fas fa-history"></i> Historiques</button>
-			<button type="button" class="btn btn-dark" onclick="bt_edit_user_info({{item.id}})"><i class="far fa-edit"></i> Mise à jour</button>
-			<button type="button" class="btn btn-dark" onclick="bt_edit_user_statut({{item.id}})"><i class="fas fa-tasks"></i> Changer Status</button>
 		</div>
+		{% if item.PIC_L_Statut == "PREPROD" %}
+			<div class="modal-footer border-success bg-success">
+		{% elif item.PIC_L_Statut == "EN STOCK" %}
+			<div class="modal-footer border-info bg-info">
+		{% elif item.PIC_L_Statut == "HS" %}
+			<div class="modal-footer border-warning bg-warning">
+		{% elif item.PIC_L_Statut == "ADEPROD" %}
+			<div class="modal-footer border-danger bg-danger">
+		{% else%}
+			<div class="modal-footer">
+		{% endif %}
+
+		{% if item.PIC_L_Chassi_Type == "IMP" and item.PIC_Adresse_IP != none %}<a class="btn btn-dark" href="http://{{item.PIC_Adresse_IP}}" target="_blank" role="button"><i class="fas fa-external-link-alt"></i> WebAdmin</a>{% endif %}
+		<button type="button" class="btn btn-dark" onclick="bt_get_user_hist({{item.id}})"><i class="fas fa-history"></i> Historiques</button>
+		<button type="button" class="btn btn-dark" onclick="bt_edit_user_info({{item.id}})"><i class="far fa-edit"></i> Mise à jour</button>
+		<button type="button" class="btn btn-dark" onclick="bt_edit_user_statut({{item.id}})"><i class="fas fa-tasks"></i> Changer Status</button>
 	</div>
+</div>
 </div>

+ 0 - 1
parc_info/templates/parc_info_api_user_get_list.html

@@ -61,7 +61,6 @@
 
 				<td>
 					{% if item.PIC_Nom_netbios != none %}<span onmouseover="this.style.cursor='pointer';" onclick="bt_get_user_info({{item.id}})">{{item.PIC_Nom_netbios}}</span>{% if item.PIC_L_Chassi_Type != "IMP" and item.PIC_L_Chassi_Type != "CL" %}&nbsp;{% endif %}{% else %}&nbsp;{% endif %}
-					{% if item.PIC_with_Snow == True %}<i class="fas fa-snowflake" title="[SYNC with Snow]"></i>{% endif %}
 					{% if item.PIC_is_for_Cadre == True %}<i class="fas fa-user-tag" title="[Poste de cadre ou RUS]"></i>{% endif %}
 					{% if item.PIC_Deg == 1 %} <i class="fas fa-anchor" title="[Poste avec procédure Dégradé]"></i> {% endif %}
 				</td>

+ 12 - 3
parc_info/templates/parc_info_user_index.html

@@ -39,7 +39,7 @@ function user_get_list() {
 		$list_user_get_list.html('<h3> <i class="fas fa-spinner fa-pulse fa-fw"></i> Loading...</h3>');
 		$.ajax({
 			type : 'GET',
-			url: '/parc/api/clients/get_list?get_search='+get_search,
+			url: '/parc/api/clients/get_list?get_filtre='+'{{page.get_filtre}}&get_search='+get_search,
 			success: function(feeds) { 
 				$list_user_get_list.html(feeds);
 			}
@@ -49,7 +49,7 @@ function user_get_list() {
 		$list_user_get_list.html('<h3> <i class="fas fa-spinner fa-pulse fa-fw"></i> Loading...</h3>');
 		$.ajax({
 			type : 'GET',
-			url: '/parc/api/clients/get_list',
+			url: '/parc/api/clients/get_list?get_filtre='+'{{page.get_filtre}}',
 			success: function(feeds) { 
 				$list_user_get_list.html(feeds);
 			}
@@ -138,13 +138,22 @@ $(document).ready(function(){ onloading(); });
 <div class="card-body">
 
 	{% if page.search_see == "ok" %}
+		<h6>Recherche d'un client (min 3 caractères)</h6>
 		<div id="div_id_PSearch" class="form-group">
-			<label for="id_PSearch" class=" requiredField">Recherche d'un client (min 3 caractères) </label>
 			<div class=""><input type="text" name="PSearch" maxlength="128" class="textinput textInput form-control" required="" id="id_PSearch" oninput="user_get_list()" value="{{page.search}}"></div>
 		</div>
 	{% else %}
 		<input type="hidden" name="PSearch" id="id_PSearch">
 	{% endif %}
+	<h6>Filter par type de chassi</h6>
+	<div class="btn-group btn-group-sm" role="group" aria-label="Filtre">
+		<a class="btn btn-secondary{% if page.get_filtre == 'PC' %} active{% endif %}" href="{% url 'parc_info_user_show_list'%}?get_filtre=PC" role="button">PC</a>
+		<a class="btn btn-secondary{% if page.get_filtre == 'PORTABLE' %} active{% endif %}" href="{% url 'parc_info_user_show_list'%}?get_filtre=PORTABLE" role="button">Portable</a>
+		<a class="btn btn-secondary{% if page.get_filtre == 'CL' %} active{% endif %}" href="{% url 'parc_info_user_show_list'%}?get_filtre=CL" role="button">Client Léger</a>
+		<a class="btn btn-secondary{% if page.get_filtre == 'PANEL-PC' %} active{% endif %}" href="{% url 'parc_info_user_show_list'%}?get_filtre=PANEL-PC" role="button">Panel-PC</a>
+		<a class="btn btn-secondary{% if page.get_filtre == 'IMP' %} active{% endif %}" href="{% url 'parc_info_user_show_list'%}?get_filtre=IMP" role="button">Imprimante</a>
+		<a class="btn btn-secondary{% if page.get_filtre == 'ALL' %} active{% endif %}" href="{% url 'parc_info_user_show_list'%}" role="button">Tous</a>
+	</div>
 	<p>{{page.p_right|safe}}</p>
 	{% if services %}
 		<div class="d-grid gap-2 mb-2"><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#mo_services_info"><i class="fas fa-info-circle"></i> Liste des services</button></div>

+ 2 - 3
parc_info/urls.py

@@ -8,7 +8,8 @@ urlpatterns = [
 
 	path('maintenance/update', views.update, name='parc_info_update'),
 	path('import/snow', views.import_snow_data, name='parc_info_import_snow'),
-
+    path('import/desktop', views.import_desktop_data, name='parc_info_import_snow'),
+    
 	#api taches
 	# path('api/taches/get_list', api.taches_get_list, name='parc_info_api_taches_get_list'),
 	# re_path('api/taches/edit_taches/(?P<id_tache>\d+)', api.taches_edit_info, name='parc_info_api_taches_edit_info'),
@@ -59,7 +60,5 @@ urlpatterns = [
 	path('clients/deprod', views.user_show_list_deprod, name='parc_info_user_show_list_deprod'),
 	path('clients/imp', views.user_show_list_imp, name='parc_info_user_show_list_imp'),
 	path('clients/stat/par-services', views.stat_user_by_service, name='parc_info_stat_user_by_service'),
-	path('clients/stat/without-snow', views.stat_user_without_snow, name='parc_info_stat_user_without_snow'),
-	
 
 ]

+ 84 - 17
parc_info/views.py

@@ -275,6 +275,7 @@ def user_show_list(request):
 	template = loader.get_template('parc_info_user_index.html')
 
 	get_search = request.GET.get('get_search', '')
+	get_filtre = request.GET.get('get_filtre', '')
 	get_id = request.GET.get('get_id', '')
 
 	page = gen_page_base()
@@ -284,11 +285,16 @@ def user_show_list(request):
 	if get_id :
 		print(get_id)
 		page.item_id = get_id
+	if get_filtre :
+		page.get_filtre = get_filtre
+	else :
+		page.get_filtre = "ALL"
+	print(get_filtre)
 	
 	page.p_adresse = reverse('parc_info_user_show_list')
 	page.p_titre = "Listing des équipements utilisateurs"
 	page.p_contenu = "Listing des équipements utilisateurs présent dans le parc informatique"
-	page.p_right = "<h3>Menu</h3><p><a href='/parc/clients/enstock'>Listing des équipements en stock</a><br><a href='/parc/clients/aprep'>Listing des équipements en préparation</a><br><a href='/parc/clients/deprod'>Listing des équipements en inapt</a></p><h3>Les Outils</h3>"
+	page.p_right = "<h6>Menu</h6><p><a href='/parc/clients/enstock'>Listing des équipements en stock</a><br><a href='/parc/clients/aprep'>Listing des équipements en préparation</a><br><a href='/parc/clients/deprod'>Listing des équipements en inapt</a></p><h6>Les Outils</h6>"
 	page.search_see = "ok"
 
 	services = Clin_Services.objects.all()
@@ -576,20 +582,6 @@ def stat_user_by_service(request):
 		
 	return HttpResponse(html)
 
-@login_required(login_url='core_login')
-def stat_user_without_snow(request):
-	page = gen_page_base()
-	template = loader.get_template('parc_info_stat_user_without_snow.html')
-
-	item =  PIC.objects.exclude(PIC_L_Statut__in = ['INAPTE', 'EN STOCK']).filter(PIC_L_Chassi_Type__in = ['PC','PORTABLE','PANEL-PC']).filter(PIC_with_Snow = False).order_by('PIC_Site__CLIN_Anag','PIC_Service__SERVICE_Nom')
-
-	html = template.render({
-		'item': item,
-		'page': page,
-	}, request)
-		
-	return HttpResponse(html)
-
 def import_snow_data(request):
 
 	import openpyxl
@@ -616,7 +608,6 @@ def import_snow_data(request):
 				pass
 		
 		if need_update == 1:
-			item.PIC_with_Snow = True
 			item.PIC_Adresse_IP = str(row[1].value)
 			item.PIC_Marque = str(row[2].value)
 			item.PIC_Type = str(row[3].value)
@@ -641,7 +632,6 @@ def import_snow_data(request):
 			item.save()
 
 		elif need_update == 2:
-			item.PIS_with_Snow = True
 			item.PIS_Adresse_IP = str(row[1].value)
 			if str(row[2].value) == "VMware, Inc.":
 				item.PIS_Type = "MACHINE VIRTUELLE"
@@ -660,4 +650,81 @@ def import_snow_data(request):
 
 			item.save()
 
+	return HttpResponse("ok")
+
+def import_desktop_data(request):
+
+	import openpyxl
+	workbook = openpyxl.load_workbook(filename='./static/import/HPN+-+Export+Inventaire.xlsx', read_only=True)
+	
+	first_sheet = workbook.get_sheet_names()[0]
+	worksheet = workbook.get_sheet_by_name(first_sheet)
+
+	print(first_sheet)
+	for row in worksheet.iter_rows():
+
+		tmp_Nom_netbios = str(row[0].value)
+		if tmp_Nom_netbios == "Nom de l’ordinateur":
+			continue
+		else : 
+			print(tmp_Nom_netbios)		
+			
+		need_update = 0
+		try :
+			item = PIC.objects.exclude(PIC_L_Statut = 'INAPTE').get(PIC_Nom_netbios = tmp_Nom_netbios)
+			print("PC > ok exist")
+			need_update = 1
+		except:
+			pass
+			# try : 
+			# 	item = PIS.objects.exclude(PIS_Archive = True).get(PIS_Nom_netbios = tmp_Nom_netbios)
+			# 	print("SRV > ok exist")
+			# 	need_update = 2
+			# except:
+			# 	pass
+		
+		if need_update == 1:
+			item.PIC_Adresse_IP = str(row[2].value)
+			item.PIC_Adresse_Mac = str(row[1].value)
+			item.PIC_Marque = str(row[3].value)
+			item.PIC_Type = str(row[4].value)
+			item.PIC_OS = str(row[7].value)
+			item.PIC_SN = str(row[5].value)
+			tmp_Utilisateur = str(row[8].value)
+
+			tmp_Utilisateur = tmp_Utilisateur.split(',')
+			try :
+				tmp_sp_tmp_Utilisateur = tmp_Utilisateur[-1]
+				tmp_sp_tmp_Utilisateur = tmp_sp_tmp_Utilisateur.replace('\\', '').replace('(STJACQUES', '').replace(')', '')
+				item.PIC_Utilisateur_Fq = tmp_sp_tmp_Utilisateur
+			except :
+				pass
+
+			#tmp_PIC_CPU = str(row[9].value)
+			#tmp_PIC_CPU = tmp_PIC_CPU.split(' @')
+			#item.PIC_CPU = tmp_PIC_CPU[0]
+			#item.PIC_CPU = item.PIC_CPU.replace(' CPU', '').replace('11th Gen ', '')
+			item.PIC_RAM = int(float(int(row[6].value) / 1024))
+
+			item.save()
+
+		# elif need_update == 2:
+		# 	item.PIS_Adresse_IP = str(row[1].value)
+		# 	if str(row[2].value) == "VMware, Inc.":
+		# 		item.PIS_Type = "MACHINE VIRTUELLE"
+		# 		item.PIS_CPU = str(row[10].value)
+		# 	else:
+		# 		item.PIS_Type = str(row[2].value)
+		# 		item.PIS_SN = str(row[12].value)
+		# 		tmp_PIS_CPU = str(row[9].value)
+		# 		tmp_PIS_CPU = tmp_PIS_CPU.split(' @')
+		# 		item.PIS_CPU = tmp_PIS_CPU[0]
+		# 		item.PIS_CPU = item.PIS_CPU.replace(' CPU', '').replace('11th Gen ', '')
+
+		# 	item.PIS_OS = str(row[5].value)
+			
+		# 	item.PIS_RAM = int(float(row[11].value / 1024))
+
+		# 	item.save()
+
 	return HttpResponse("ok")

BIN
static/import/HPN+-+Export+Inventaire.xlsx