Commit 0d7c8c32 by François C.

Add app administation features

parent b2704620
from django.db import models from django.db import models
from outils.common_imports import * from outils.common_imports import *
from shelfs.models import Shelf, Shelfs
import glob import glob
class ThirdPartyAdmin(models.Model): class ThirdPartyAdmin(models.Model):
"""Class to manage third party and view logs""" """Class to manage third party and view logs"""
@staticmethod @staticmethod
def get_inventory_backups():
content = []
files = []
for file in glob.glob("data/inventories_backup/*.json"):
files.append(file)
files.sort()
if len(files) > 0:
shelfs_map = {}
for shelf in Shelfs.get_all('simple'):
shelfs_map[str(shelf['id'])] = shelf['name']
for f in files:
fn = f.split('/')[-1]
inv_file = fn.replace(".json","")
(timestamp, shelf_id) = inv_file.split('__')
(date, hms) = timestamp.split('--')
hms = hms.replace('-',':')
content.append({'file': fn, 'date': date, 'hms': hms, 'shelf_id': shelf_id, 'shelf_name': shelfs_map[str(shelf_id)] })
return content
@staticmethod
def merge_inventory_data(elts):
result = {'name': '',
'inventory_status': '',
'list_processed': [],
'total_price': 0 }
names = []
for elt in elts:
name = elt['name']
if elt['inventory_status'] == "":
name += " (Etape 1)"
else:
name += " (Etape 2)"
names.append(name)
result['list_processed'] += elt['list_processed']
result['name'] = ' // '.join(names)
# Retrieve product data (price at date)
# and compute total purchase price
i = 0
for inv_line in result['list_processed']:
line_price = round(inv_line['standard_price'] * inv_line['qty'], 2)
result['total_price'] += line_price
result['list_processed'][i]['line_price'] = line_price
i += 1
return result
@staticmethod
def get_inventory_backup(file_names):
data = []
result = {}
fn = file_names.split('|-|')
try:
for file_name in fn:
fpath = "data/inventories_backup/" + file_name
inventory_data = {}
with open(fpath) as json_file:
inventory_data = json.load(json_file)
data.append(inventory_data)
result = ThirdPartyAdmin.merge_inventory_data(data)
except Exception as e:
coop_logger.error("get_inventory_backup : %s", str(e))
return result
@staticmethod
def get_django_logs(): def get_django_logs():
content = [] content = []
for file in glob.glob("log/*.log"): for file in glob.glob("log/*.log"):
with open(file) as f: with open(file) as f:
content.append({'key' :file, 'value': f.readlines()}) content.append({'key' :file, 'value': f.readlines()})
return content return content
\ No newline at end of file
.page_body tr:hover {
background-color: #ffff99;
}
.page_body tr.selected {
background-color: #ff0099;
}
#displayed_results {
margin-top: 25px;
padding-top: 25px;
border-top: 3px dotted grey;
background-color: beige;
}
.select_file_cb {
z-index: 2000000;
}
\ No newline at end of file
...@@ -90,6 +90,28 @@ var createTabs = async function(params) { ...@@ -90,6 +90,28 @@ var createTabs = async function(params) {
return result; return result;
} }
var showListInDatatable = function(parent_div, list_data, colums_def, row_click_handler) {
// Init table for items to process
const d = new Date();
let table = $('<table>').attr('id', d.getTime())
$(parent_div).append(table);
let data_table = table.DataTable({
data: list_data,
columns: colums_def,
paging: false,
dom: 'lrtip', // Remove the search input from that table
language: {url : '/static/js/datatables/french.json'}
});
$('#' + d.getTime() + ' tbody').on('click', 'td.as-row-clickable', function () {
const clicked = $(this)
var row = data_table.row(this);
table.find('tr').removeClass('selected');
clicked.closest('tr').addClass('selected')
row_click_handler(row.data())
});
return data_table;
}
$('#back_to_admin_index').on('click', function() { $('#back_to_admin_index').on('click', function() {
const to_remove = window.location.href.split('/').pop(); const to_remove = window.location.href.split('/').pop();
const new_url = window.location.href.replace(to_remove, ""); const new_url = window.location.href.replace(to_remove, "");
......
const displayed_results = document.querySelector('#displayed_results');
let files_list_row_click_handler = function(data) {
load_content('/administration/retrieve_inventory_backup/' + data.file).then(rep => {
if (typeof rep.content !== "undefined") {
show_file_content(rep.content);
} else {
alert("La récupération du fichier n'a pas aboutie");
}
});
}
let content_file_row_click_handler = function(data) {
}
let show_file_content = function(data) {
let title = '<h3>Saisie du rayon ' + data.name + '</h3>',
info = $('<p>').addClass('info');
$(displayed_results).empty();
$(displayed_results).append(title);
info.append('Total HT : <b>' + data.total_price + ' €</b>')
$(displayed_results).append(info);
const columns = [
{data:"id", visible: false},
{
data:"barcode",
title:"Code-barre",
},
{
data:"name",
title:"Nom article",
},
{
data:"qty_available",
title:"Théorique",
},
{
data:"qty",
title:"Compté",
},
{
data:"standard_price",
title:"Achat HT",
},
{
data:"line_price",
title:"Total HT",
},
];
showListInDatatable(displayed_results, data.list_processed, columns, content_file_row_click_handler);
};
let get_selections_data = function() {
let files = [];
$('input.select_file_cb:checked').each(function(i,elt) {
files.push($(elt).val())
});
files_list_row_click_handler({file: files.join('|-|')})
}
let show_files_list = function (params) {
const columns = [
{
data: "file",
className: "dt-body-center",
orderable: false,
render: function (data) {
return `<input type="checkbox" class="select_file_cb" value="${data}">`;
},
width: "4%"
},
{
data:"date",
title:"Jour",
className: "as-row-clickable"
},
{
data:"hms",
title:"HMS",
className: "as-row-clickable"
},
{
data:"shelf_name",
title:"Rayon",
className: "as-row-clickable"
},
];
showListInDatatable(params.parentElt, params.data, columns, files_list_row_click_handler);
$(document).off('click.select_file');
$(document).on('click.select_file', '.select_file_cb', function(event){
event.stopPropagation();
get_selections_data();
});
};
// Chargement des données et traitement
load_content('/administration/retrieve_inventory_backups').then(rep => {
if (typeof rep.content !== "undefined") {
const params = {
parentElt: document.querySelector('[class="page_body"]'),
data: rep.content
};
show_files_list(params);
} else {
alert("La récupération des fichiers n'a pas aboutie");
}
});
\ No newline at end of file
...@@ -7,7 +7,9 @@ $(document).ready(function() { ...@@ -7,7 +7,9 @@ $(document).ready(function() {
let location = window.location.href.replace(/\/$/, ''); let location = window.location.href.replace(/\/$/, '');
$('.management_type_button').on('click', function() { $('.management_type_button').on('click', function() {
if (this.id == 'manage_django_logs') { if (this.id == 'manage_inventory_data') {
window.location.assign(location + "/inventory_backups");
} else if (this.id == 'manage_django_logs') {
window.location.assign(location + "/django_logs"); window.location.assign(location + "/django_logs");
} else if (this.id == 'manage_odoo_logs') { } else if (this.id == 'manage_odoo_logs') {
window.location.assign(location + "/odoo_logs"); window.location.assign(location + "/odoo_logs");
......
...@@ -6,7 +6,10 @@ from . import views ...@@ -6,7 +6,10 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.index, name='index'), url(r'^$', views.index, name='index'),
url(r'^django_logs$', views.django_logs, name='index'), url(r'^inventory_backups$', views.inventory_backups),
url(r'^odoo_logs$', views.odoo_logs, name='index'), url(r'^django_logs$', views.django_logs),
url(r'^retrieve_django_logs$', views.retrieve_django_logs, name='index'), url(r'^odoo_logs$', views.odoo_logs),
url(r'^retrieve_inventory_backups$', views.retrieve_inventory_backups),
url(r'^retrieve_inventory_backup/(.*)', views.retrieve_inventory_backup),
url(r'^retrieve_django_logs$', views.retrieve_django_logs),
] ]
\ No newline at end of file
...@@ -22,28 +22,61 @@ def index(request): ...@@ -22,28 +22,61 @@ def index(request):
return HttpResponse(template.render(context, request)) return HttpResponse(template.render(context, request))
def inventory_backups(request):
"""Manage inventory backups."""
if CagetteUser.are_credentials_ok(request) and CagetteUser.isAllowedToAdmin(request):
template = loader.get_template('admin/inventory_backups.html')
context = {
'title': "Sauvegardes saisies d'inventaire",
}
response = HttpResponse(template.render(context, request))
else:
response = HttpResponse('Not allowed', status=403)
return response
def django_logs(request): def django_logs(request):
""" Administration des créneaux des membres """ """ Administration des créneaux des membres """
template = loader.get_template('admin/django_logs.html') if CagetteUser.are_credentials_ok(request) and CagetteUser.isAllowedToAdmin(request):
template = loader.get_template('admin/django_logs.html')
context = {
'title': 'Logs Django', context = {
} 'title': 'Logs Django',
return HttpResponse(template.render(context, request)) }
response = HttpResponse(template.render(context, request))
else:
response = HttpResponse('Not allowed', status=403)
return response
def odoo_logs(request): def odoo_logs(request):
""" Administration des créneaux des membres """ """ Administration des créneaux des membres """
template = loader.get_template('admin/odoo_logs.html') if CagetteUser.are_credentials_ok(request) and CagetteUser.isAllowedToAdmin(request):
template = loader.get_template('admin/odoo_logs.html')
context = { context = {
'title': 'Logs Odoo', 'title': 'Logs Odoo',
} }
return HttpResponse(template.render(context, request)) response = HttpResponse(template.render(context, request))
else:
response = HttpResponse('Not allowed', status=403)
def retrieve_django_logs(request): def retrieve_django_logs(request):
if CagetteUser.are_credentials_ok(request) and CagetteUser.isAllowedToAdmin(request): if CagetteUser.are_credentials_ok(request) and CagetteUser.isAllowedToAdmin(request):
response = JsonResponse({'content': ThirdPartyAdmin.get_django_logs()}) response = JsonResponse({'content': ThirdPartyAdmin.get_django_logs()})
else: else:
response = JsonResponse({}, status=403) response = JsonResponse({}, status=403)
return response
def retrieve_inventory_backups(request):
if CagetteUser.are_credentials_ok(request) and CagetteUser.isAllowedToAdmin(request):
response = JsonResponse({'content': ThirdPartyAdmin.get_inventory_backups()})
else:
response = JsonResponse({}, status=403)
return response
def retrieve_inventory_backup(request, files):
if CagetteUser.are_credentials_ok(request) and CagetteUser.isAllowedToAdmin(request):
response = JsonResponse({'content': ThirdPartyAdmin.get_inventory_backup(files)})
else:
response = JsonResponse({}, status=403)
return response return response
\ No newline at end of file
...@@ -1366,6 +1366,9 @@ class CagetteUser(models.Model): ...@@ -1366,6 +1366,9 @@ class CagetteUser(models.Model):
@staticmethod @staticmethod
def isAllowedToAdmin(request): def isAllowedToAdmin(request):
"""Need to create an odoo Group called 'django admin'.""" """Need to create an odoo Group called 'django admin'."""
"""
In Odoo, create a group named 'django admin' and add Odoo user(s)
"""
answer = False answer = False
groups = CagetteUser.get_groups(request) groups = CagetteUser.get_groups(request)
......
...@@ -18,11 +18,15 @@ ...@@ -18,11 +18,15 @@
{% if is_connected %} {% if is_connected %}
{% if is_admin %} {% if is_admin %}
<div class="management_type_buttons txtcenter"> <div class="management_type_buttons txtcenter">
<button type="button" class="btn--primary management_type_button" id="manage_inventory_data">
Sauvegardes saisies d'inventaire
<span class="management_type_button_icons"><i class="fas fa-arrow-right"></i></span>
</button><br>
<button type="button" class="btn--primary management_type_button" id="manage_django_logs"> <button type="button" class="btn--primary management_type_button" id="manage_django_logs">
Logs Django Logs Django
<span class="management_type_button_icons"><i class="fas fa-arrow-right"></i></span> <span class="management_type_button_icons"><i class="fas fa-arrow-right"></i></span>
</button><br> </button><br>
<button type="button" class="btn--primary management_type_button" id="manage_odoo_logs"> <button type="button" class="btn--primary management_type_button" id="manage_odoo_logs" disabled>
Logs Odoo Logs Odoo
<span class="management_type_button_icons"><i class="fas fa-arrow-right"></i></span> <span class="management_type_button_icons"><i class="fas fa-arrow-right"></i></span>
</button><br> </button><br>
......
{% extends "base.html" %}
{% load static %}
{% block additionnal_css %}
<link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}">
<link rel="stylesheet" href="{% static 'css/diasg_tabs.css' %}">
<link rel="stylesheet" href="{% static 'css/admin_common.css' %}">
{% endblock %}
{% block additionnal_scripts %}
<script type="text/javascript" src="{% static 'js/download.js' %}"></script>
<script type="text/javascript" src="{% static 'js/datatables/jquery.dataTables.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/datatables/dataTables.plugins.js' %}"></script>
{% endblock %}
{% block content %}
<div id="admin_connexion_button">
{% include "common/conn_admin.html" %}
</div>
<div class="page_body">
<div id="back_to_admin_index">
<button type="button" class="btn--danger"><i class="fas fa-arrow-left"></i>&nbsp; Retour</button>
</div>
<h2>Sauvegardes des saisies d'inventaires</h2>
</div>
<div id="displayed_results">
</div>
<div>
<script src='{% static "js/all_common.js" %}?v='></script>
<script src='{% static "js/admin_common.js" %}?v='></script>
<script src='{% static "js/inventory_backups.js" %}?v='></script>
{% endblock %}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment