mirror of
				https://forge.chapril.org/tykayn/caisse-bliss
				synced 2025-10-09 17:02:47 +02:00 
			
		
		
		
	
		
			
	
	
		
			500 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			500 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | 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(); | ||
|  |   }]); |