Commit 20b4c4a0 by Damien Moulard

INV: display ongoing inventory start datetime + shelfs module linting

parent 04aedf66
Pipeline #2163 passed with stage
in 1 minute 31 seconds
...@@ -6,7 +6,7 @@ from products.models import CagetteProducts ...@@ -6,7 +6,7 @@ from products.models import CagetteProducts
from inventory.models import CagetteInventory from inventory.models import CagetteInventory
import os import os
from datetime import date from datetime import date, datetime
from openpyxl import Workbook from openpyxl import Workbook
from openpyxl.styles import Alignment, Font from openpyxl.styles import Alignment, Font
from statistics import * from statistics import *
...@@ -14,6 +14,7 @@ from statistics import * ...@@ -14,6 +14,7 @@ from statistics import *
# Prefix for temp shelf inventory files # Prefix for temp shelf inventory files
tmp_inv_file_prefix = 'temp/inventory_shelf_' tmp_inv_file_prefix = 'temp/inventory_shelf_'
default_inventory_start_datetime = "0001-01-01 00:00:00"
def as_text(value): def as_text(value):
""" Utils """ """ Utils """
...@@ -106,6 +107,7 @@ class Shelf(models.Model): ...@@ -106,6 +107,7 @@ class Shelf(models.Model):
# Inventory all done # Inventory all done
f['inventory_status'] = '' f['inventory_status'] = ''
f['date_last_inventory'] = date.today().strftime("%Y-%m-%d") f['date_last_inventory'] = date.today().strftime("%Y-%m-%d")
f['ongoing_inv_start_datetime'] = default_inventory_start_datetime # Reset
if 'last_inventory_id' in params: if 'last_inventory_id' in params:
f['last_inventory_id'] = params['last_inventory_id'] f['last_inventory_id'] = params['last_inventory_id']
...@@ -180,6 +182,18 @@ class Shelf(models.Model): ...@@ -180,6 +182,18 @@ class Shelf(models.Model):
res['error'] = "L'enregistrement n'a pas pu se réaliser" res['error'] = "L'enregistrement n'a pas pu se réaliser"
return res return res
def set_begin_inventory_datetime(self):
res = {}
now = datetime.now().isoformat()
f = {'ongoing_inv_start_datetime': now}
try:
res["update"] = self.o_api.update('product.shelfs', self.id, f)
res["inventory_begin_datetime"] = now
except Exception as e:
res['error'] = str(e)
return res
def save_tmp_inventory(self, inventory_data): def save_tmp_inventory(self, inventory_data):
"""Save inventory data in a json temp file""" """Save inventory data in a json temp file"""
......
...@@ -12,21 +12,23 @@ var validation_msg = $('#validation_msg'), ...@@ -12,21 +12,23 @@ var validation_msg = $('#validation_msg'),
process_all_items_msg = $('#process_all_items_msg'), process_all_items_msg = $('#process_all_items_msg'),
faq_content = $("#FAQ_modal_content"), faq_content = $("#FAQ_modal_content"),
issues_reporting = $("#issues_reporting"), issues_reporting = $("#issues_reporting"),
add_product_form = $("#add_product_form"), add_product_form = $("#add_product_form");
add_product_input = $("#add_product_input");
var shelf, var shelf = null,
parent_location = '/shelfs', parent_location = '/shelfs',
originView = "shelf", // or custom_list (create from order view) originView = "shelf", // or custom_list (create from order view)
list_to_process = [], list_to_process = [],
table_to_process, table_to_process = null,
table_processed, table_processed = null,
editing_item = null, // Store the item currently being edited editing_item = null, // Store the item currently being edited
editing_origin, // Keep track of where editing_item comes from editing_origin = "", // Keep track of where editing_item comes from
processed_row_counter = 0, // Keep count of the order the item were added in processed list processed_row_counter = 0, // Keep count of the order the item were added in processed list
search_chars = [], search_chars = [],
user_comments = '', user_comments = '',
adding_product = false; // True if modal to add a product is open adding_product = false, // True if modal to add a product is open.
// datetime for which shelf's ongoing_inv_start_datetime is considered null
default_inventory_start_datetime = "0001-01-01 00:00:00";
/* UTILS */ /* UTILS */
...@@ -95,7 +97,7 @@ function handle_blinking_effect(element) { ...@@ -95,7 +97,7 @@ function handle_blinking_effect(element) {
element.addEventListener('animationend', onAnimationEnd); element.addEventListener('animationend', onAnimationEnd);
element.addEventListener('webkitAnimationEnd', onAnimationEnd); element.addEventListener('webkitAnimationEnd', onAnimationEnd);
function onAnimationEnd(e) { function onAnimationEnd() {
element.classList.remove('blink_me'); element.classList.remove('blink_me');
} }
} }
...@@ -169,7 +171,7 @@ function clearLineEdition() { ...@@ -169,7 +171,7 @@ function clearLineEdition() {
} }
// Validate product edition // Validate product edition
function validateEdition(form) { function validateEdition() {
if (editing_item != null) { if (editing_item != null) {
if (editProductInfo(editing_item)) { if (editProductInfo(editing_item)) {
clearLineEdition(); clearLineEdition();
...@@ -405,10 +407,12 @@ function confirmProcessAllItems() { ...@@ -405,10 +407,12 @@ function confirmProcessAllItems() {
openModal(); openModal();
// Iterate over all rows in table of items to process // Iterate over all rows in table of items to process
table_to_process.rows().every(function (rowIdx, tableLoop, rowLoop) { table_to_process.rows().every(function () {
var data = this.data(); var data = this.data();
editProductInfo(data, 0); editProductInfo(data, 0);
return 1;
}); });
// Reset data // Reset data
...@@ -446,7 +450,6 @@ function send() { ...@@ -446,7 +450,6 @@ function send() {
var url = "../do_" + originView + "_inventory"; var url = "../do_" + originView + "_inventory";
var call_begin_at = new Date().getTime(); var call_begin_at = new Date().getTime();
$.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });
$.ajax({ $.ajax({
type: "PUT", type: "PUT",
url: url, url: url,
...@@ -480,7 +483,7 @@ function send() { ...@@ -480,7 +483,7 @@ function send() {
// Clear local storage before leaving // Clear local storage before leaving
localStorage.removeItem(originView + '_' + shelf.id); localStorage.removeItem(originView + '_' + shelf.id);
}, },
error: function(jqXHR, textStatus) { // 500 error has been thrown or web server sent a timeout error: function(jqXHR) { // 500 error has been thrown or web server sent a timeout
if (jqXHR.status == 504) { if (jqXHR.status == 504) {
/* /*
django is too long to respond. django is too long to respond.
...@@ -547,6 +550,35 @@ function exit_adding_product() { ...@@ -547,6 +550,35 @@ function exit_adding_product() {
adding_product = false; adding_product = false;
} }
/**
* Set the ongoing inventory start datetime.
* This operation is invisible to the user.
*/
function set_begin_inventory_datetime() {
if (originView === 'shelf' &&
(
shelf.ongoing_inv_start_datetime === default_inventory_start_datetime
|| shelf.ongoing_inv_start_datetime === undefined
)
) {
$.ajax({
type: "POST",
url: "/shelfs/"+shelf.id+"/set_begin_inventory_datetime",
dataType: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function(data) {
shelf.ongoing_inv_start_datetime = data.res.inventory_begin_datetime;
// Update local storage
localStorage.setItem(originView + "_" + shelf.id, JSON.stringify(shelf));
},
error: function() {
console.log("Impossible de mettre à jour la date de début d'inventaire");
}
});
}
}
// Add a product that's not in the list // Add a product that's not in the list
function open_adding_product() { function open_adding_product() {
if (originView == 'shelf') { if (originView == 'shelf') {
...@@ -563,7 +595,6 @@ function do_add_product() { ...@@ -563,7 +595,6 @@ function do_add_product() {
}; };
openModal(); openModal();
$.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: "../"+shelf.id+"/add_product", url: "../"+shelf.id+"/add_product",
...@@ -571,7 +602,7 @@ function do_add_product() { ...@@ -571,7 +602,7 @@ function do_add_product() {
traditional: true, traditional: true,
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
data: JSON.stringify(prod_data), data: JSON.stringify(prod_data),
success: function(data) { success: function() {
exit_adding_product(); exit_adding_product();
closeModal(); closeModal();
alert('Produit ajouté !'); alert('Produit ajouté !');
...@@ -618,8 +649,6 @@ function saveIssuesReport() { ...@@ -618,8 +649,6 @@ function saveIssuesReport() {
// Get shelf data from server if not in local storage // Get shelf data from server if not in local storage
function get_shelf_data() { function get_shelf_data() {
$.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });
var url = (originView == 'shelf') ? '../' + shelf.id : '../get_custom_list_data?id=' + shelf.id; var url = (originView == 'shelf') ? '../' + shelf.id : '../get_custom_list_data?id=' + shelf.id;
$.ajax({ $.ajax({
...@@ -631,6 +660,7 @@ function get_shelf_data() { ...@@ -631,6 +660,7 @@ function get_shelf_data() {
success: function(data) { success: function(data) {
shelf = data.res; shelf = data.res;
init(); init();
set_begin_inventory_datetime();
}, },
error: function(data) { error: function(data) {
if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') { if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
...@@ -646,7 +676,6 @@ function init() { ...@@ -646,7 +676,6 @@ function init() {
// Products passed at page loading // Products passed at page loading
// TODO: get products by ajax for better ui experience (? -> warning js at loading) // TODO: get products by ajax for better ui experience (? -> warning js at loading)
// TODO : What happens if products are being put or removed from the self before the end of the inventory ? // TODO : What happens if products are being put or removed from the self before the end of the inventory ?
//console.log(shelf)
list_to_process = products; list_to_process = products;
initLists(); initLists();
...@@ -703,7 +732,7 @@ function init() { ...@@ -703,7 +732,7 @@ function init() {
$(document).on('click', 'button#add_product_to_shelf', open_adding_product); $(document).on('click', 'button#add_product_to_shelf', open_adding_product);
$(document).on('click', 'button#open_issues_report', openIssuesReport); $(document).on('click', 'button#open_issues_report', openIssuesReport);
$(document).on('click', 'button#open_faq', openFAQ); $(document).on('click', 'button#open_faq', openFAQ);
$(document).on('click', 'button#process_all_items', function (e) { $(document).on('click', 'button#process_all_items', function () {
openModal(process_all_items_msg.html(), confirmProcessAllItems, 'Confirmer', false); openModal(process_all_items_msg.html(), confirmProcessAllItems, 'Confirmer', false);
}); });
...@@ -720,7 +749,7 @@ function init() { ...@@ -720,7 +749,7 @@ function init() {
handle_blinking_effect(container_edition); handle_blinking_effect(container_edition);
// Disable mousewheel on an input number field when in focus // Disable mousewheel on an input number field when in focus
$('#edition_input').on('focus', function (e) { $('#edition_input').on('focus', function () {
$(this).on('wheel.disableScroll', function (e) { $(this).on('wheel.disableScroll', function (e) {
e.preventDefault(); e.preventDefault();
/* /*
...@@ -733,7 +762,7 @@ function init() { ...@@ -733,7 +762,7 @@ function init() {
*/ */
}); });
}) })
.on('blur', function (e) { .on('blur', function () {
$(this).off('wheel.disableScroll'); $(this).off('wheel.disableScroll');
}); });
...@@ -815,6 +844,8 @@ function init() { ...@@ -815,6 +844,8 @@ function init() {
$(document).ready(function() { $(document).ready(function() {
// Get Route parameter // Get Route parameter
$.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });
var pathArray = window.location.pathname.split('/'); var pathArray = window.location.pathname.split('/');
shelf = {id: pathArray[pathArray.length-1]}; shelf = {id: pathArray[pathArray.length-1]};
...@@ -834,7 +865,9 @@ $(document).ready(function() { ...@@ -834,7 +865,9 @@ $(document).ready(function() {
if (stored_shelf != null) { if (stored_shelf != null) {
shelf = stored_shelf; shelf = stored_shelf;
init(); init();
set_begin_inventory_datetime();
} else { } else {
// Get shelf info if not coming from shelves list // Get shelf info if not coming from shelves list
get_shelf_data(); get_shelf_data();
......
...@@ -6,8 +6,8 @@ Informations affichées : ...@@ -6,8 +6,8 @@ Informations affichées :
*/ */
var parent_location = '/shelfs', var parent_location = '/shelfs',
shelf, shelf = null,
table_products, table_products = null,
search_chars = []; search_chars = [];
/* UTILS */ /* UTILS */
...@@ -54,7 +54,7 @@ function initList() { ...@@ -54,7 +54,7 @@ function initList() {
title:"Delta (dernier inv.)", title:"Delta (dernier inv.)",
width: "10%", width: "10%",
className:"dt-body-center", className:"dt-body-center",
render: function (data, type, full, meta) { render: function (data, type) {
if (type == "sort" || type == 'type') if (type == "sort" || type == 'type')
return data; return data;
...@@ -70,7 +70,7 @@ function initList() { ...@@ -70,7 +70,7 @@ function initList() {
title:"Pertes (dernier inv.)", title:"Pertes (dernier inv.)",
width: "10%", width: "10%",
className:"dt-body-center", className:"dt-body-center",
render: function (data, type, full, meta) { render: function (data, type) {
if (type == "sort" || type == 'type') if (type == "sort" || type == 'type')
return data; return data;
......
...@@ -6,7 +6,6 @@ var main_content = $('#main-content'), ...@@ -6,7 +6,6 @@ var main_content = $('#main-content'),
shelf_sort_order = create_form.find('input[name="sort_order"]'), shelf_sort_order = create_form.find('input[name="sort_order"]'),
shelf_name = create_form.find('input[name="name"]'), shelf_name = create_form.find('input[name="name"]'),
description = create_form.find('textarea[name="description"]'), description = create_form.find('textarea[name="description"]'),
eye = '<i class="fas fa-eye"></i>',
delete_icon = '<i class="fas fa-trash"></i>', delete_icon = '<i class="fas fa-trash"></i>',
add_icon = '<i class="fas fa-plus-circle"></i>', add_icon = '<i class="fas fa-plus-circle"></i>',
edit_icon = '<i class="fas fa-edit"></i>', edit_icon = '<i class="fas fa-edit"></i>',
...@@ -136,6 +135,8 @@ var update_shelf = function() { ...@@ -136,6 +135,8 @@ var update_shelf = function() {
rData.res.p_nb = data.p_nb; rData.res.p_nb = data.p_nb;
this.data(rData.res).draw(); this.data(rData.res).draw();
} }
return 1;
}); });
closeModal(); closeModal();
} else alert(rData.res.error); } else alert(rData.res.error);
...@@ -202,12 +203,6 @@ var downloadInventoryReport = function() { ...@@ -202,12 +203,6 @@ var downloadInventoryReport = function() {
} }
}; };
var rowUpdate = function (row, rdata) {
//console.log(row, rdata)
};
// TODO put datatable common methods such as following in a file useable for all modules // TODO put datatable common methods such as following in a file useable for all modules
var rowGetData = function(clicked) { var rowGetData = function(clicked) {
var row = shelfs_table.row(clicked.parents('tr')); var row = shelfs_table.row(clicked.parents('tr'));
...@@ -216,7 +211,7 @@ var rowGetData = function(clicked) { ...@@ -216,7 +211,7 @@ var rowGetData = function(clicked) {
return row.data(); return row.data();
}; };
function coop_init_datatable(params, data, domsel, cols, action_btn) { function coop_init_datatable(params, data, domsel, cols) {
var buttons = []; var buttons = [];
var columns = []; var columns = [];
...@@ -277,10 +272,6 @@ function coop_init_datatable(params, data, domsel, cols, action_btn) { ...@@ -277,10 +272,6 @@ function coop_init_datatable(params, data, domsel, cols, action_btn) {
rowId : "id", rowId : "id",
data : data, data : data,
language: {url : '/static/js/datatables/french.json'}, language: {url : '/static/js/datatables/french.json'},
createdRow: function(row, rdata, index) {
rowUpdate(row, rdata);
},
initComplete: function() { initComplete: function() {
/* /*
if (! coop_is_connected()) if (! coop_is_connected())
...@@ -317,7 +308,7 @@ var init_and_fill_selfs_list = function() { ...@@ -317,7 +308,7 @@ var init_and_fill_selfs_list = function() {
data:"last_inventory_id", data:"last_inventory_id",
title:"Rapport dernier inventaire", title:"Rapport dernier inventaire",
className: "action", className: "action",
render: function (data, type, full, meta) { render: function (data) {
if (typeof data != "undefined" && data != 0) { if (typeof data != "undefined" && data != 0) {
return download_icon; return download_icon;
} else { } else {
......
...@@ -13,11 +13,28 @@ function init_datatable() { ...@@ -13,11 +13,28 @@ function init_datatable() {
className:"dt-body-center" className:"dt-body-center"
}, },
{data:"name", title:"Nom"}, {data:"name", title:"Nom"},
{data:"description", title:"Description", orderable: false}, // {data:"description", title:"Description", orderable: false},
{
data:"ongoing_inv_start_datetime",
title:"Début inventaire en cours",
render: function (data, type) {
// Sort on data, not rendering
if (type == "sort" || type == 'type')
return data;
if (data == '0001-01-01 00:00:00')
return "";
else {
var date = new Date(data);
return `${date.toLocaleDateString('fr-FR')} ${date.toLocaleTimeString('fr-FR')}`;
}
}
},
{ {
data:"date_last_inventory", data:"date_last_inventory",
title:"Date dernier inventaire", title:"Dernier inventaire",
render: function (data, type, full, meta) { render: function (data, type) {
// Sort on data, not rendering // Sort on data, not rendering
if (type == "sort" || type == 'type') if (type == "sort" || type == 'type')
return data; return data;
...@@ -36,7 +53,7 @@ function init_datatable() { ...@@ -36,7 +53,7 @@ function init_datatable() {
{ {
data:"shelf_value", data:"shelf_value",
title:"Valeur théorique du rayon", title:"Valeur théorique du rayon",
render: function (data, type, full, meta) { render: function (data, type) {
if (type == "sort" || type == 'type') if (type == "sort" || type == 'type')
return data; return data;
...@@ -51,44 +68,45 @@ function init_datatable() { ...@@ -51,44 +68,45 @@ function init_datatable() {
width: "5%", width: "5%",
className:"dt-body-center" className:"dt-body-center"
}, },
{ /* NOT IN USE */
data:"last_inv_delta_percentage", // {
title:"Delta (dernier inv.)", // data:"last_inv_delta_percentage",
width: "5%", // title:"Delta (dernier inv.)",
className:"dt-body-center", // width: "5%",
render: function (data, type, full, meta) { // className:"dt-body-center",
if (type == "sort" || type == 'type') // render: function (data, type) {
return data; // if (type == "sort" || type == 'type')
// return data;
if (data == -99999999) {
return '/'; // if (data == -99999999) {
} else { // return '/';
return data + ' %'; // } else {
} // return data + ' %';
} // }
}, // }
{ // },
data:"last_inv_losses_percentage", // {
title:"Pertes (dernier inv.)", // data:"last_inv_losses_percentage",
width: "5%", // title:"Pertes (dernier inv.)",
className:"dt-body-center", // width: "5%",
render: function (data, type, full, meta) { // className:"dt-body-center",
if (type == "sort" || type == 'type') // render: function (data, type) {
return data; // if (type == "sort" || type == 'type')
// return data;
if (data == -99999999) {
return '/'; // if (data == -99999999) {
} else { // return '/';
return data + ' %'; // } else {
} // return data + ' %';
} // }
}, // }
// },
{ {
data:"inventory_status", data:"inventory_status",
title:"Inventaire à faire", title:"Inventaire à faire",
className:"dt-body-center", className:"dt-body-center",
width: "15%", width: "15%",
render: function (data, type, full, meta) { render: function (data) {
if (data == '') if (data == '')
return "<button class='btn--primary do_shelf_inventory'>Inventaire en rayon</button>"; return "<button class='btn--primary do_shelf_inventory'>Inventaire en rayon</button>";
else else
...@@ -144,11 +162,13 @@ function get_shelfs_extra_data() { ...@@ -144,11 +162,13 @@ function get_shelfs_extra_data() {
} }
function set_null_to_extra_data() { function set_null_to_extra_data() {
shelfs_table.rows().every(function (rowIdx, tableLoop, rowLoop) { shelfs_table.rows().every(function () {
var d = this.data(); var d = this.data();
d.shelf_value = -2; d.shelf_value = -2;
this.invalidate(); // invalidate the data DataTables has cached for this row this.invalidate(); // invalidate the data DataTables has cached for this row
return 1;
}); });
shelfs_table.draw(); shelfs_table.draw();
...@@ -157,7 +177,6 @@ function set_null_to_extra_data() { ...@@ -157,7 +177,6 @@ function set_null_to_extra_data() {
var getRowData = function(clicked) { var getRowData = function(clicked) {
var row = shelfs_table.row(clicked.parents('tr')); var row = shelfs_table.row(clicked.parents('tr'));
return row.data(); return row.data();
}; };
......
...@@ -17,7 +17,7 @@ function init_datatable() { ...@@ -17,7 +17,7 @@ function init_datatable() {
{ {
data:"date_last_inventory", data:"date_last_inventory",
title:"Date dernier inventaire", title:"Date dernier inventaire",
render: function (data, type, full, meta) { render: function (data, type) {
// Sort on data, not rendering // Sort on data, not rendering
if (type == "sort" || type == 'type') if (type == "sort" || type == 'type')
return data; return data;
...@@ -37,7 +37,7 @@ function init_datatable() { ...@@ -37,7 +37,7 @@ function init_datatable() {
title:"", title:"",
className:"dt-body-center", className:"dt-body-center",
width: "15%", width: "15%",
render: function (data, type, full, meta) { render: function () {
return "<button class='btn--success do_export_sales_data'>Export Ventes</button>"; return "<button class='btn--success do_export_sales_data'>Export Ventes</button>";
} }
} }
......
...@@ -14,6 +14,7 @@ urlpatterns = [ ...@@ -14,6 +14,7 @@ urlpatterns = [
url(r'^(?P<shelf_id>\d+)$', views.shelf_data), url(r'^(?P<shelf_id>\d+)$', views.shelf_data),
url(r'^(?P<shelf_id>\d+)/products$', views.products), url(r'^(?P<shelf_id>\d+)/products$', views.products),
url(r'^(?P<shelf_id>\d+)/add_product$', views.add_product), url(r'^(?P<shelf_id>\d+)/add_product$', views.add_product),
url(r'^(?P<shelf_id>\d+)/set_begin_inventory_datetime$', views.set_begin_inventory_datetime),
url(r'^do_shelf_inventory$', views.do_shelf_inventory), url(r'^do_shelf_inventory$', views.do_shelf_inventory),
url(r'^(?P<shelf_id>\d+)/last_inventory_report$', views.get_last_inventory_report), url(r'^(?P<shelf_id>\d+)/last_inventory_report$', views.get_last_inventory_report),
url(r'^shelf_inventory_FAQ', views.shelf_inventory_FAQ), url(r'^shelf_inventory_FAQ', views.shelf_inventory_FAQ),
......
...@@ -61,6 +61,15 @@ def shelf_data(request, shelf_id): ...@@ -61,6 +61,15 @@ def shelf_data(request, shelf_id):
else: else:
return JsonResponse({'res': shelf}) return JsonResponse({'res': shelf})
def set_begin_inventory_datetime(request, shelf_id):
""" Set the ongoing inventory start datetime. Set it to now. """
res = Shelf(shelf_id).set_begin_inventory_datetime()
if 'error' in res:
return JsonResponse(res, status=500)
else:
return JsonResponse({'res': res})
def all(request): def all(request):
"""Get all shelves data""" """Get all shelves data"""
......
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