remove v1

This commit is contained in:
Tykayn 2025-02-13 18:14:53 +01:00 committed by tykayn
parent 501795a8fa
commit e23013825b
16590 changed files with 20531 additions and 19312449 deletions

0
assets/js/parts/caisseCtrl.js Executable file
View file

11
assets/js/parts/dashboard.js Executable file
View file

@ -0,0 +1,11 @@
/**
* test to import things
*/
export class DashboardStuff{
sayHi(){
console.log('hiiiiiiii! from dashboard stuff');
}
sayHo(){
console.log('hoooo');
}
};

View file

@ -0,0 +1,98 @@
let introJs = require('intro.js');
var $ = require('jquery');
$(document).ready(function () {
let massimportExample = 'catégorie: livre\n' +
' les moutaines;5€\n' +
' la laine des moutons;6€\n' +
' star wars spécial noël;7€\n' +
'catégorie: poster\n' +
' super bannière A2;10€\n' +
' Sébastien Chabal sexy;10€\n' +
'catégorie: dessin à la demande\n' +
' dessin A4 crayon;20€\n' +
' dessin A4 aquarelle;150€';
$('[data-toggle="popover"]').popover();
$('#menu_button').on('click', function () {
$('#menu-dashboard').toggleClass('shown');
});
// use example in mass import
$('#use_example').on('click', function () {
$('#produits').val(massimportExample);
// $('#filling_zone input').click();
});
// intro js
$('#introjs_start').on('click', function () {
function startIntro() {
var intro = introJs();
intro.setOptions({
steps: [
{
element: document.querySelector('#caisse-now'),
position: 'right',
intro : "Ceci est l'écran principal de la CaisseBliss, <strong>votre tableau de bord</strong> liste les produits que vous souhaitez vendre actuellement. Utilisez les flèches du clavier pour continuer la visite guidée."
},
{
element: document.querySelector('#main_options'),
position: 'bottom',
intro : "Les options d'affichage des boutons de produit permettent de visualiser ou non les stocks restants de vos produits, le nombre de produit vendus sur le festival en cours, et d'activer ou non le bouton de caddie de <strong>vente express</strong> à utiliser pour les clients qui n'achètent qu'un seul produit à la fois."
},
{
element: document.querySelector('#client-now'),
position: 'bottom',
intro : "<strong>L'espace commentaire </strong> lié à la vente en cours vous permet de prendre une note que vous retrouverez plus tard dans votre historique de vente. Il peut servir à savoir à qui vous faites une dédicace dans un livre par exemple."
},{
element: document.querySelector('#listing-products'),
intro : "<strong>La liste des produits </strong> les range par colonne de catégorie. Vous n'avez qu'a appuyer sur un produit pour l'ajouter à la liste de vente en cours. Et vous pouvez scroller horizontalement vos colonnes"
},{
element: document.querySelector('#sellings'),
intro : "<strong>La liste de vente </strong> permet de modifier le prix des produits si vous faites des remises spéciales pour un client particulier, et vous calcule le rendu de monnaie si le client ne paie pas l'appoint."
},{
element: document.querySelector('#choice-categories'),
intro : "<strong>Les options de catégories </strong> permettent d'afficher ou masquer certaines catégories si vous ne vendez pas tous vos produits à chaque festival."
},
{
element: document.querySelector('#menu-dashboard'),
intro : "<strong>Le menu latéral</strong> vous permet de gérer vos produits, stocks, catégories. Conforme au RGPD par design de logiciel libre, Caisse Bliss vous permet d'exporter vos données et respecte votre vie privée"
},
{
element: document.querySelector('#menu_festivals'),
position: 'right',
intro : "<strong>Les festivals</strong> vous permettent de séparer vos ventes lors de différents évènements et d'obtenir des statistiques détaillées afin de vous permettre de connaître la rentabilité de chaque évènement"
},
{
element: document.querySelector('#menu_series'),
position: 'right',
intro : "<strong>Les séries de festivals</strong> permettent de relier des évènements similaires d'une édition à une autre. Par exemple Festival Harajuku 2018 et 2019, Japan Expo de toutes les années. Et ce afin de pouvoir voir des statistiques groupées dans la partie Historique."
},
{
element: document.querySelector('#menu_previsionnel'),
position: 'right',
intro : "<strong>La page de prévisionnel</strong> n'est pas reliée à vos ventes de produits mais permet de voir si votre commerce est viable en fonction de ce que vous gagnez et dépensez habituellement. Toujours utile."
}, {
element: document.querySelector('.user-info-link'),
position: 'right',
intro : "Vous pouvez modifier vos informations de compte utilisateur (email, pseudo, mot de passe...) en cliquant sur votre pseudo"
},
]
});
intro.start();
}
startIntro()
})
// demo login
$('#demo_login_btn').on('click', function (){
$('#username').val('demo');
$('#password').val('demo');
$('#_submit').click();
})
// $('#introjs_start').click();
let inputClient = document.querySelector('.client-now input');
inputClient ? inputClient.focus() : false;
});

499
assets/js/parts/main.js Executable file
View file

@ -0,0 +1,499 @@
require('../../../node_modules/canvasjs/dist/canvasjs.3');
// JS is equivalent to the normal "bootstrap" package
// no need to set this to a variable, just require it
require('bootstrap-sass');
// or you can include specific pieces
// require('bootstrap-sass/javascripts/bootstrap/tooltip');
// require('bootstrap-sass/javascripts/bootstrap/popover');
require('./globalActions');
require('./dashboard');
var PrevisionnelCtrl = require('./previsionnel');
var stuff = ['initialstuff'];
// TODO split controllers in other files
angular
.module('caisse', [])
.controller('CaisseCtrl', ['$scope', '$http', '$timeout', '$rootScope', function ($scope, $http, $timeout,$rootScope) {
$scope.productsFromDB = []; // loaded products
$scope.categories = []; // product categories
$scope.sellingComment = ""; // comment about the client or the current selling
$scope.initLoadDone = false; // becames true after first init of product loading
$scope.recentSellings = [];
$scope.lesParams = {};
$scope.countProductsSoldForActiveFestival = {};
$scope.simpleDisplay = false;
$scope.paidAmount = 0;
$scope.pausedSelling = [];
$scope.show_config = {
expressSelling: true,
stock_count: false,
sold : false,
};
$scope.activeItemsSold = []; // list of products ID to sell
$scope.activeSelling = []; // list of products to sell
$scope.activeSellingFiltered = []; // list of products to sell
$scope.activeFestival = { // an event where selling take place
id : null,
name : "le festival",
productComment : "",
dateCreation : new Date(),
chiffreAffaire: 0,
clientsCount : 0,
commentaire : ""
};
/**
* change to simple display
*/
$scope.toggleSimpleDisplay = function () {
// debugger;
$scope.simpleDisplay = !$scope.simpleDisplay;
}
/**
* set the right paid amount
*/
$scope.setRightAmountPaid = function () {
// debugger;
$scope.paidAmount += $scope.sumOfList($scope.activeSelling);
}
/**
* deduplicate the active selling items in the view,
* show a count for each of them when there are more than one
*/
$scope.refreshDeduplicateSellings = () => {
let soldObjectsIdsCount = {}
$scope.activeSellingFiltered = {};
$scope.activeSelling.forEach(elem => {
let groupId = elem.id;
let group = soldObjectsIdsCount[groupId];
if (group) { // sort elements by the product id corresponding
group.count++;
group.totalPrice += (elem.price * 1);
group.sellings.push(elem);
} else {
soldObjectsIdsCount[groupId] = {
groupId : groupId,
count : 1,
name : elem.name,
unitPrice : elem.price * 1,
totalPrice: elem.price * 1,
sellings : [elem],
}
}
});
$scope.activeSellingFiltered = soldObjectsIdsCount;
$scope.setRightAmountPaid();
};
/**
* get the sum of products prices
* @param list
* @returns {number}
*/
$scope.sumOfList = function (list) {
let counter = 0;
for (let i = 0; i < list.length; i++) {
counter += list[i].price * 1;
}
return counter;
};
/**
* sum of current selling list prices
* @returns {number}
* @constructor
*/
$scope.CurrentSellingTotal = function () {
return $scope.sumOfList($scope.activeSelling);
};
$scope.categoriesVisibleCount = function () {
let count = 0;
$scope.categories.forEach(function (elem) {
elem.hidden ? count++ : "";
});
return count;
}
$scope.regenActiveSellingIds = function () {
$scope.activeItemsSold = [];
$scope.paidAmount = 0;
for (let obj in $scope.activeSelling) {
$scope.activeItemsSold.push(obj.id);
}
};
$scope.stuff = stuff;
$scope.setActiveSelling = function (selling) {
$scope.activeSelling = selling;
};
$scope.pauseSelling = function (selling) {
$scope.pausedSelling.push(selling);
};
/**
* add to current sell list
* @param product
*/
$scope.addProduct = function (product) {
product.stockCount--;
product.enabled = true;
$scope.activeSelling.push(product);
$scope.activeItemsSold.push(product.id);
$scope.regenActiveSellingIds();
$scope.refreshDeduplicateSellings();
$scope.setRightAmountPaid();
};
/**
* remove from current sell list
* @param product
*/
$scope.removeProduct = function (product, index) {
product.stockCount++;
$scope.activeSelling.splice($index, 1);
$scope.regenActiveSellingIds();
$scope.refreshDeduplicateSellings();
};
/**
* remove all products of a certain group id in the active Selling
* @param productId
* @returns {*}
*/
$scope.removeGroupeProducts = function (productId) {
console.log("##### removeGroupeProducts", productId);
console.log("$scope.activeSelling", $scope.activeSelling);
$scope.activeSelling = $scope.activeSelling.filter(elem => elem.id != productId)
console.log("$scope.activeSelling", $scope.activeSelling);
$scope.regenActiveSellingIds();
$scope.refreshDeduplicateSellings();
}
$scope.removeAll = function () {
$scope.categories.forEach(category => {
if (category.products && category.products.length) {
category.products.forEach(product => {
product.enabled = false
});
}
});
$scope.activeSelling = [];
$scope.regenActiveSellingIds();
$scope.refreshDeduplicateSellings();
};
$scope.pauseSelling = function () {
$scope.pausedSelling.push(angular.copy($scope.activeSelling));
$scope.activeSelling = [];
};
$scope.setBackPausedSelling = function (sellingList, index) {
$scope.activeSelling = angular.copy(sellingList);
$scope.pausedSelling.splice(index, 1);
};
$scope.clearSellingComment = function () {
console.log(' $scope.sellingComment', $scope.sellingComment);
// $scope.sellingComment = '';
// document.querySelector('.client-now input').focus();
document.querySelector('.client-now input').select();
};
$scope.clearCurrentSelling = function () {
$scope.paidAmount = 0;
$scope.clearSellingComment();
$scope.activeSelling = [];
$scope.removeAll();
};
// http related calls
$scope.fetchProductsFromDB = function () {
console.log('fetch products...');
$http.get('logged/get-my-products').then((rep) => {
console.log('ok', rep);
customCategories = [];
for (let c of rep.data.categories) {
c.hidden = false;
customCategories.push(c);
}
console.log('customCategories', customCategories);
$scope.categories = customCategories;
$scope.productsFromDB = customCategories;
// $scope.recentSellings = rep.data.history;
// festoche
$scope.activeFestival.id = rep.data.lastFestival.id;
$scope.activeFestival.name = rep.data.lastFestival.name;
$scope.activeFestival.dateCreation = rep.data.lastFestival.dateCreation;
$scope.activeFestival.commentaire = rep.data.lastFestival.commentaire;
$scope.activeFestival.chiffreAffaire = rep.data.lastFestival.chiffreAffaire;
$scope.activeFestival.fondDeCaisseAvant = rep.data.lastFestival.fondDeCaisseAvant;
$scope.activeFestival.fondDeCaisseApres = rep.data.lastFestival.fondDeCaisseApres;
$scope.activeFestival.clientsCount = rep.data.lastFestival.clientsCount;
// stat count for items
$scope.countProductsSoldForActiveFestival = rep.data.lastFestival.sold;
console.log(' $scope.countProductsSoldForActiveFestival', $scope.countProductsSoldForActiveFestival);
//done
$scope.initLoadDone = true;
}, (err) => {
console.log(err);
$scope.initLoadDone = true;
});
};
/**
* sell one product, assuming the client has the right amount of money
* @param product
*/
$scope.expressSell = function (product) {
$scope.removeAll();
$scope.addProduct(product);
$scope.sendForm();
};
$scope.recentId = 0;
$scope.logger = function (stuff) {
console.log('logger #####', stuff);
};
$scope.sendForm = function () {
let sellingComment = $scope.sellingComment;
$scope.sellingComment = sellingComment;
console.log('########### SEND FORM');
console.log('$scope.sellingComment', $scope.sellingComment);
let lesParams = {
paidByClient : $scope.paidAmount,
sellingComment: $scope.sellingComment,
activeSelling : $scope.activeSelling,
activeFestival: $scope.activeFestival
};
$scope.recentSellings.push({
id : $scope.recentId++,
amount : $scope.CurrentSellingTotal(),
paidAmount: $scope.paidAmount,
products :
angular
.copy($scope.activeSelling)
});
$scope.lesParams = lesParams;
$http({
method : 'POST',
url : 'logged/add-selling',
headers: {
'Content-Type': 'application/json'
},
data : lesParams // pass in data as strings
}).then(function (rep) {
console.log('########### OK form',rep);
// if successful, bind success message to message
$scope.successMessage = rep.data.message;
$scope.activeFestival.chiffreAffaire = rep.data.newChiffreAffaire;
$scope.activeFestival.clientsCount = rep.data.clientsCount;
$scope.countProductsSoldForActiveFestival = rep.data.activeFestival.sold;
$scope.showTemporaryMessage();
$scope.clearCurrentSelling();
console.log(rep);
if (!rep.success) {
// if not successful, bind errors to error variables
$scope.errors = rep.errors;
}
}, function (rep) {
console.log('nope! ', rep.data);
$scope.showTemporaryErrorMessage();
})
;
};
$scope.sellingOk = false;
$scope.sellingError = false;
$scope.tempMessage = {};
$scope.showTemporaryMessage = function () {
console.log('show message');
if ($scope.sellingOk) {
$scope.sellingOk = false;
return;
}
$scope.sellingOk = true;
$timeout.cancel($scope.tempMessage);
$scope.tempMessage = $timeout(function () {
console.log('hide message');
$scope.sellingOk = false;
}, 2000)
};
$scope.showTemporaryErrorMessage = function () {
console.log('show message');
if ($scope.sellingError) {
$scope.sellingError = false;
return;
}
$scope.sellingError = true;
$timeout.cancel($scope.tempMessage);
$scope.tempMessage = $timeout(function () {
console.log('hide message');
$scope.sellingError = false;
}, 2000)
};
$scope.init = (function () {
$scope.fetchProductsFromDB();
})();
}])
.controller('previsionnelCtrl', ['$scope', '$http', '$timeout', function ($scope, $http, $timeout) {
$scope.config = {
initialLoadingDone : false,
loading : false,
lines : 24,
debounceTime : 300, // miliseconds to wait before updating model and saving changes
/**
* expenses kind of the user
*/
disponibility : 5000,
averageMonthlyEarnings: 600,
warningThershold : 2000,
showDelays : false,
showRepeats : false,
monthsBeforeNoMoney : null,
};
let exampleExpenses = [
{name: "appart", amount: 800, delay: 0, repeat: $scope.config.lines, enabled: true},
{name: "assurance voiture", amount: 50, delay: 0, repeat: $scope.config.lines, enabled: true},
{name: "internet", amount: 20, delay: 0, repeat: $scope.config.lines, enabled: true},
{name: "elec", amount: 100, delay: 0, repeat: $scope.config.lines, enabled: true},
{name: "chat", amount: 20, delay: 0, repeat: $scope.config.lines, enabled: true},
{name: "transports", amount: 70, delay: 0, repeat: $scope.config.lines, enabled: false},
];
// $scope.expenses=[];
$scope.expenses = exampleExpenses;
/**
* sum of all monthly expenses, ignoring delay
* @returns {number}
*/
$scope.sumMonthlyExpenses = () => {
let sum = 0;
$scope.expenses.forEach((elem) => {
if (elem.enabled) {
sum += elem.amount;
}
})
return sum;
};
$scope.previsionTable = [];
$scope.calculatePrevisionTable = () => {
let turns = $scope.config.lines;
let monthly = $scope.sumMonthlyExpenses();
let available = $scope.config.disponibility;
let previsionTable = [];
let changedNoMoneyConfig = false;
$scope.config.monthsBeforeNoMoney = null;
for (let i = 0; i <= turns; i++) {
// TODO take in account delays in expenses
available = available - monthly + $scope.config.averageMonthlyEarnings;
let newLine = {
expense : monthly,
available: available,
};
if (available <= 0 && !changedNoMoneyConfig) {
$scope.config.monthsBeforeNoMoney = i;
changedNoMoneyConfig = true;
}
previsionTable.push(newLine);
}
$scope.previsionTable = previsionTable;
$scope.makeGraphPointsOfPrevisionTable(previsionTable);
return previsionTable;
};
$scope.graphPointsPrevision = [];
$scope.makeGraphPointsOfPrevisionTable = (previsionTable) => {
console.log("previsionTable", previsionTable);
$scope.graphPointsPrevision = [];
for (let i = 0; i < previsionTable.length; i++) {
$scope.graphPointsPrevision.push({
label: previsionTable[i].available + " euros restants dans " + i + " mois",
y : previsionTable[i].available,
x : i,
})
}
}
$scope.updateconf = (rep) => {
// update view calculs
$scope.calculatePrevisionTable();
$scope.updateCanevas()
// flags
$scope.config.loading = false;
$scope.config.initialLoadingDone = true;
$scope.config.disponibility = rep.data.disponibility;
$scope.config.averageMonthlyEarnings = rep.data.averageMonthlyEarnings;
// default data when user has nothing saved
console.log('rep.data.expenses.length', rep.data.expenses.length)
if (!rep.data.expenses.length) {
$scope.expenses = exampleExpenses;
} else {
$scope.expenses = rep.data.expenses;
}
};
// http related calls
$scope.fetchExpenses = () => {
console.log('fetch expenses...');
$scope.config.loading = true;
$http.get('logged/get-my-expenses').then((rep) => {
console.log('logged/get-my-expenses', rep.data.expenses);
$scope.updateconf(rep)
},
$scope.manageError)
};
$scope.save = function () {
if ($scope.config.loading) {
console.log('already saving');
return;
}
console.log('update expenses...');
$scope.config.loading = true;
$http.post('logged/save-my-expenses', {
expenses: $scope.expenses,
config : $scope.config
})
.then((rep) => {
console.log('logged/save-my-expenses', rep);
$scope.updateconf(rep)
},
$scope.manageError)
};
$scope.addExpense = function () {
$scope.expenses.push({
name : "",
repeat: 0,
delay : 0,
amount: 0,
})
};
$scope.init = function () {
$scope.fetchExpenses();
};
$scope.manageError = (error) => {
console.error(error);
$scope.config.loading = false;
};
$scope.updateCanevas = function () {
var dataPoints = $scope.graphPointsPrevision;
var chartContainer = new CanvasJS.Chart("simulationPrevision", {
title: {
text: "Euros disponibles dans le temps"
},
// animationEnabled: true,
data : [
{
// Change type to "doughnut", "line", "splineArea", etc.
type : "splineArea",
dataPoints: dataPoints
}
]
});
chartContainer.render();
};
$scope.init();
}]);

163
assets/js/parts/previsionnel.js Executable file
View file

@ -0,0 +1,163 @@
export var PrevisionnelCtrl = function ($scope, $http, $timeout) {
$scope.config = {
initialLoadingDone : false,
loading : false,
lines : 24,
debounceTime : 300, // miliseconds to wait before updating model and saving changes
/**
* expenses kind of the user
*/
disponibility : 5000,
averageMonthlyEarnings: 600,
warningThershold : 2000,
showDelays : false,
showRepeats : false,
monthsBeforeNoMoney : null,
};
let exampleExpenses = [
{name: "appart", amount: 800, delay: 0, repeat: $scope.config.lines, enabled: true},
{name: "assurance voiture", amount: 50, delay: 0, repeat: $scope.config.lines, enabled: true},
{name: "internet", amount: 20, delay: 0, repeat: $scope.config.lines, enabled: true},
{name: "elec", amount: 100, delay: 0, repeat: $scope.config.lines, enabled: true},
{name: "chat", amount: 20, delay: 0, repeat: $scope.config.lines, enabled: true},
{name: "transports", amount: 70, delay: 0, repeat: $scope.config.lines, enabled: false},
];
// $scope.expenses=[];
$scope.expenses = exampleExpenses;
/**
* sum of all monthly expenses, ignoring delay
* @returns {number}
*/
$scope.sumMonthlyExpenses = () => {
let sum = 0;
$scope.expenses.forEach((elem) => {
if (elem.enabled) {
sum += elem.amount;
}
})
return sum;
};
$scope.previsionTable = [];
$scope.calculatePrevisionTable = () => {
let turns = $scope.config.lines;
let monthly = $scope.sumMonthlyExpenses();
let available = $scope.config.disponibility;
let previsionTable = [];
let changedNoMoneyConfig = false;
$scope.config.monthsBeforeNoMoney = null;
for (let i = 0; i <= turns; i++) {
// TODO take in account delays in expenses
available = available - monthly + $scope.config.averageMonthlyEarnings;
let newLine = {
expense : monthly,
available: available,
};
if (available <= 0 && !changedNoMoneyConfig) {
$scope.config.monthsBeforeNoMoney = i;
changedNoMoneyConfig = true;
}
previsionTable.push(newLine);
}
$scope.previsionTable = previsionTable;
$scope.makeGraphPointsOfPrevisionTable(previsionTable);
return previsionTable;
};
$scope.graphPointsPrevision = [];
$scope.makeGraphPointsOfPrevisionTable = (previsionTable) => {
console.log("previsionTable", previsionTable);
$scope.graphPointsPrevision = [];
for (let i = 0; i < previsionTable.length; i++) {
$scope.graphPointsPrevision.push({
label: previsionTable[i].available + " euros restants dans " + i + " mois",
y : previsionTable[i].available,
x : i,
})
}
}
$scope.updateconf = (rep) => {
// update view calculs
$scope.calculatePrevisionTable();
$scope.updateCanevas()
// flags
$scope.config.loading = false;
$scope.config.initialLoadingDone = true;
$scope.config.disponibility = rep.data.disponibility;
$scope.config.averageMonthlyEarnings = rep.data.averageMonthlyEarnings;
// default data when user has nothing saved
console.log('rep.data.expenses.length', rep.data.expenses.length)
if (!rep.data.expenses.length) {
$scope.expenses = exampleExpenses;
} else {
$scope.expenses = rep.data.expenses;
}
};
// http related calls
$scope.fetchExpenses = () => {
console.log('fetch expenses...');
$scope.config.loading = true;
$http.get('get-my-expenses').then((rep) => {
console.log('get-my-expenses', rep.data.expenses);
$scope.updateconf(rep)
},
$scope.manageError)
};
$scope.save = function () {
if ($scope.config.loading) {
console.log('already saving');
return;
}
console.log('update expenses...');
$scope.config.loading = true;
$http.post('save-my-expenses', {
expenses: $scope.expenses,
config : $scope.config
})
.then((rep) => {
console.log('save-my-expenses', rep);
$scope.updateconf(rep)
},
$scope.manageError)
};
$scope.addExpense = function () {
$scope.expenses.push({
name : "",
repeat: 0,
delay : 0,
amount: 0,
})
};
$scope.init = function () {
$scope.fetchExpenses();
};
$scope.manageError = (error) => {
console.error(error);
$scope.config.loading = false;
}
$scope.updateCanevas = function () {
var dataPoints = $scope.graphPointsPrevision;
var chartContainer = new CanvasJS.Chart("simulationPrevision", {
title: {
text: "Euros disponibles dans le temps"
},
// animationEnabled: true,
data : [
{
// Change type to "doughnut", "line", "splineArea", etc.
type : "splineArea",
dataPoints: dataPoints
}
]
});
chartContainer.render();
}
$scope.init();
};