up styles, handle owner of products on controllers

This commit is contained in:
Tykayn 2025-02-26 16:33:36 +01:00 committed by tykayn
parent 457cafdaef
commit e973573fd7
33 changed files with 773 additions and 818 deletions

View File

@ -15,486 +15,487 @@ 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 = {};
.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 {
$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();
};
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);
};
/**
* 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.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 () {
console.log('$scope.categories', $scope.categories)
$scope.categories.forEach(category => {
if (category.products && category.products.length) {
$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 () {
console.log('$scope.categories', $scope.categories)
$scope.categories.forEach(category => {
if (category.products && category.products.length) {
category.products.forEach(product => {
product.enabled = false
});
}
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.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();
};
$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) => {
// http related calls
$scope.fetchProductsFromDB = function () {
console.log('fetch products...');
$http.get('logged/get-my-products').then((rep) => {
console.log('rep.data', rep.data)
let customCategories = [];
for (let c of rep.data.categories) {
c.hidden = false;
customCategories = Object.create(rep.data.categories);
}
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;
});
};
console.log('rep.data', rep.data)
let customCategories = [];
for (let c of rep.data.categories) {
c.hidden = false;
customCategories = Object.create(rep.data.categories);
}
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) {
/**
* 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();
})
;
};
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.sellingOk = false;
$scope.sellingError = false;
$scope.tempMessage = {};
$scope.showTemporaryMessage = function () {
$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,
};
$scope.sellingOk = true;
$timeout.cancel($scope.tempMessage);
$scope.tempMessage = $timeout(function () {
console.log('hide message');
$scope.sellingOk = false;
}, 2000)
console.log('show message');
if ($scope.sellingOk) {
$scope.sellingOk = false;
return;
}
};
$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) {
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.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,
};
// $scope.expenses=[];
$scope.expenses = exampleExpenses;
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 },
];
/**
* 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,
};
// $scope.expenses=[];
$scope.expenses = exampleExpenses;
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,
})
}
/**
* 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) => {
$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.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();
}]);
};
$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();
}]);

View File

@ -1,15 +1,15 @@
@import 'pages/libs';
@import 'fonts/all';
@import 'split/override_libs';
@import 'split/custom_vars';
@import 'split/formulaires';
@import 'split/typo';
@import 'pages/global';
@import 'pages/nav';
@import 'pages/demo';
@import 'pages/home';
@import 'pages/forms';
@import 'pages/history';
@import 'pages/dashboard';
@import 'pages/special';
// @import 'pages/responsive';
@use 'split/bootstrap.min.css';
@use 'pages/libs';
@use 'fonts/all';
@use 'split/override_libs';
@use 'split/custom_vars';
@use 'split/formulaires';
@use 'split/typo';
@use 'pages/global';
@use 'pages/nav';
@use 'pages/demo';
@use 'pages/home';
@use 'pages/forms';
@use 'pages/history';
@use 'pages/dashboard';
@use 'pages/special';

6
assets/styles/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,10 @@
@use "sass:color";
@use "../split/custom_vars";
#caisse-now {
min-height: 90vh;
width: 70vw;
padding-left: 0;
padding-left: 1vw;
.product-box {
display: inline-block;
@ -29,25 +32,25 @@
-webkit-border-radius: 1rem;
-moz-border-radius: 1rem;
border-radius: 1rem;
border-color: $all-text-color;
border-color: custom_vars.$all-text-color;
box-shadow: 5px 3px 10px 2px #ddd;
border-width: 0;
&.btn-primary {
background-color: $deepblue;
background-color: custom_vars.$deepblue;
}
&:hover {
background: $lightblue;
background: custom_vars.$lightblue;
}
}
.badge-default {
background: $lightblue;
background: custom_vars.$lightblue;
}
.badge-success {
background: mix(green, $lightblue);
background: color.mix(green, custom_vars.$lightblue);
}
}
@ -87,7 +90,7 @@
}
.category-listing {
border: solid 1px $grey;
border: solid 1px custom_vars.$grey;
padding: 1rem;
margin: 0.5rem;
border-radius: 0.25rem;
@ -132,4 +135,12 @@
#main_options {
width: 100%;
}
#other_time,
#categories_visibility {
display: block;
padding-top: 1rem;
padding-bottom: 5rem;
min-height: 500px;
}

View File

@ -41,9 +41,13 @@ form {
padding: 1rem 2rem;
border-radius: 0.5rem;
border: solid 1px #ccc;
background: blue;
margin-bottom: 0.5rem;
}
button.delete-button {
float: right;
min-width: 20rem;
}
}
.btn-remove-all {

View File

@ -1,3 +1,5 @@
@use "../split/custom_vars";
body {
background: #F5F5F5;
font: 18px/1.5 sans-serif;
@ -23,7 +25,7 @@ p {
}
a {
color: $primary;
color: custom_vars.$primary;
}
a:hover {
@ -127,10 +129,10 @@ code {
}
.header-block {
background: $darkblue;
background: custom_vars.$darkblue;
.btn-default {
color: $grey;
color: custom_vars.$grey;
}
.btn {
@ -144,7 +146,7 @@ code {
}
#menu-dashboard .nav .logo-home.btn-default {
background: $darkblue;
background: custom_vars.$darkblue;
height: 52px;
font-size: 1em;
}

View File

@ -1,9 +1,10 @@
@import '../split/custom_vars';
@use "sass:color";
@use '../split/custom_vars';
body {
margin: 0;
padding: 0;
color: $all-text-color;
color: custom_vars.$all-text-color;
font-family: "Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 1rem;
line-height: 2rem;
@ -47,10 +48,9 @@ body {
#portfolio,
#mainNav,
.masthead,
{
padding-left: 300px !important;
}
.masthead {
padding-left: 10vw !important;
}
}
.bg-img {
@ -74,23 +74,23 @@ body {
}
.bg-color {
background: $deepblue;
color: $light;
background: custom_vars.$deepblue;
color: custom_vars.$light;
a {
color: $lightblue;
color: custom_vars.$lightblue;
}
padding: 1rem;
}
.logo-main {
color: $logo-color;
color: custom_vars.$logo-color;
}
.big-footer {
background: $dark;
color: $light;
background: custom_vars.$dark;
color: custom_vars.$light;
height: 10em;
padding: 1em;
box-sizing: border-box;
@ -102,8 +102,8 @@ body {
}
thead {
background: $darkblue;
color: $light;
background: custom_vars.$darkblue;
color: custom_vars.$light;
}
ul {
@ -191,13 +191,13 @@ input {
}
#menu-dashboard {
background: $dark;
background: custom_vars.$dark;
display: flex;
position: fixed;
left: 0;
top: 0;
min-height: 100vh;
width: 13vw;
width: 10vw;
min-width: 300px;
overflow-x: auto;
z-index: 10;
@ -212,10 +212,10 @@ input {
width: 100%;
min-width: 300px;
display: block;
border-right: solid 2px mix($dark, $grey);
border-right: solid 2px color.mix(custom_vars.$dark, custom_vars.$grey);
.btn {
color: $light;
color: custom_vars.$light;
}
.logo-home {
@ -224,11 +224,11 @@ input {
}
.btn-default {
color: $light;
color: custom_vars.$light;
&:hover {
background: mix($deepblue, $light);
color: $dark;
background: color.mix(custom_vars.$deepblue, custom_vars.$light);
color: custom_vars.$dark;
font-weight: 600;
}
}
@ -242,7 +242,7 @@ input {
i.fa {
float: left;
margin-right: 1em;
color: $light;
color: custom_vars.$light;
}
}
@ -251,13 +251,13 @@ input {
&:focus {
background: transparent;
border: none;
color: $lightblue;
color: custom_vars.$lightblue;
}
&:focus {
background: transparent;
border: none;
color: $lightblue;
color: custom_vars.$lightblue;
}
}
@ -271,7 +271,7 @@ input {
}
.btn-success {
background-color: $deepblue;
background-color: custom_vars.$deepblue;
font-weight: 800;
}
@ -302,8 +302,8 @@ table td {
}
input[type=submit] {
background: $primary;
color: $light;
background: custom_vars.$primary;
color: custom_vars.$light;
display: block;
margin-top: 1em;
padding: 1em;
@ -311,7 +311,7 @@ table td {
width: 100%;
&:hover {
background: $lightblue;
background: custom_vars.$lightblue;
}
}
}
@ -324,6 +324,7 @@ table td {
#bodyland {
min-height: 100vh;
padding-bottom: 10rem;
.container {
min-height: 90vh;

View File

@ -1,7 +1,9 @@
@use "../split/custom_vars";
.main-section {
padding: 1rem;
display: flex;
color: $light;
color: custom_vars.$light;
justify-content: center;
h1 {
@ -9,7 +11,7 @@
}
h2 {
color: $light !important;
color: custom_vars.$light !important;
}
>div {
@ -20,7 +22,7 @@
}
.product-values {
color: $light;
color: custom_vars.$light;
padding: 4rem;
padding-top: 25vh;
}
@ -32,7 +34,7 @@
h4,
h5,
h6 {
color: $light;
color: custom_vars.$light;
}
font-size: 1.5rem;

View File

@ -1,5 +1,3 @@
@import '~font-awesome/css/font-awesome.css';
//@import '~bootstrap-sass/assets/stylesheets/bootstrap';
@import '~intro.js/minified/introjs.min.css';
@import '~intro.js/themes/introjs-dark.css';
@import "~bootstrap/scss/bootstrap";
@import '~intro.js/themes/introjs-dark.css';

View File

@ -3,187 +3,4 @@
padding-left: 5em;
}
#caisse-now {
margin-left: -1em;
}
}
// @media all and(max-width: 1200px) {
// #caisse-now{
// margin-left: 0;
// }
// .big-footer{
// padding-left: 0;
// }
// nav {
// min-width: auto;
// }
// html, body {
// font-size: 1.2rem;
// }
// .bg-shader {
// height: 100%;
// min-height: 100vh;
// }
// .product-values-block {
// padding: 1em;
// }
// #homepage {
// .main-section {
// padding: 2rem;
// }
// .btn {
// display: block;
// width: 100%;
// font-size: 1.25em;
// }
// }
// #caisse-now {
// .product-box {
// width: 100%;
// &.active{
// .product-button{
// background: greenyellow;
// }
// }
// }
// .product-button {
// min-width: calc(100% - 56px)
// }
// .listing-products {
// .btn, button {
// font-size: 1rem;
// padding: 0.2em;
// border-radius: 0.3em;
// }
// }
// }
// }
// @media all and(max-width: 1200px) {
// #bodyland {
// .container {
// min-height: 100vh;
// width: 80vw;
// }
// }
// #menu-dashboard {
// font-size: 1rem;
// width: 19vw;
// min-width: 200px;
// .nav {
// min-width: 200px;
// }
// }
// form {
// margin-top: 3em;
// select {
// width: 100%;
// margin: 1em 0;
// }
// + ul {
// margin-top: 1em;
// list-style-type: none;
// a {
// display: block;
// .fa {
// margin-right: 1em;
// }
// }
// }
// }
// }
// @media all and(max-width: 600px) {
// #menu_button{
// }
// html, body {
// font-size: 1rem;
// }
// #menu-dashboard .nav .logo-home.btn-default {
// height: auto;
// font-size: 2em;
// }
// #menu-dashboard {
// width: 100vw;
// visibility: hidden;
// &.shown {
// visibility: visible;
// }
// .nav {
// min-width: 200px;
// min-height: 100vh;
// overflow: auto;
// a {
// font-size: 2rem;
// }
// }
// }
// .main-section > div {
// padding-top: 0;
// }
// .product-values {
// padding: 0;
// }
// .bigger-text, #homepage, .hint, .product-values-block {
// font-size: 1.25rem;
// line-height: 2rem;
// }
// .category-listing {
// width: calc(100vw - 4rem);
// height: 25vh;
// min-height: auto;
// float: left;
// clear: both;
// overflow: auto;
// }
// .sellings {
// input {
// width: 100%;
// }
// }
// .client-now {
// input {
// width: 50%;
// }
// }
// .sellings, .client-now {
// input {
// font-size: 1.5rem;
// padding: 0.5rem;
// }
// }
// .big-footer {
// font-size: 1rem;
// }
// #caisse-now .product-box {
// margin-bottom: 0.25rem;
// }
// #caisse-now .listing-products button {
// padding: 0.5rem 1rem;
// .express-button {
// padding: 0.5rem 1rem;
// }
// }
// }
}

6
assets/styles/split/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,12 @@
@use "sass:color";
$dark: #222;
$light: #dedede;
$deepblue: #1b6d85;
$darkblue: mix(#000, $deepblue);
$darkblue: color.mix(#000, $deepblue);
$lightblue: lightblue;
$grey: #e3e3e3;
$logo-color: mix($deepblue, $light);
$all-text-color: mix($deepblue, $light);
$logo-color: color.mix($deepblue, $light);
$all-text-color: color.mix($deepblue, $light);
$primary: $deepblue;
$btn-primary-bg: $deepblue;

View File

@ -1,3 +1,5 @@
@use "custom_vars";
.current-selling {
ul {
list-style-type: none;
@ -17,7 +19,7 @@ table {
}
.btn-primary {
background: $deepblue;
background: custom_vars.$deepblue;
}
.product-box {

View File

@ -1,5 +1,8 @@
@use "sass:color";
@use "custom_vars";
h2, h3, h4, h5, h6 {
color: mix($dark, $all-text-color);
color: color.mix(custom_vars.$dark, custom_vars.$all-text-color);
}
h1, .h1, h2, .h2, h3, .h3 {

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250226145218 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE festvial');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE festvial (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, date_creation DATE DEFAULT NULL, chiffre_affaire DOUBLE PRECISION DEFAULT NULL, clients_count INT DEFAULT NULL, commentaire VARCHAR(500) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' ');
}
}

View File

@ -121,21 +121,14 @@ final class DefaultController extends AbstractController
// récupérer les produits de l'user connecté
$user = $this->getUser();
// $products = $this->getUser()->getProducts();
$activeFest = $user->getActiveFestival();
return $this->json([
'categories' => $user->getGroupOfProducts(),
'products' => $user->getProducts(),
// mock land
'lastFestival' => ['id' => 1,
'name' => 'le festival de mock',
'dateCreation' => '2025-02-16',
'commentaire' => 'MOCK: hop le commentaire de festival',
'chiffreAffaire' => '1234',
'fondDeCaisseAvant' => '100',
'fondDeCaisseAprès' => '150',
'sold' => 123
],
'history' => [],
'lastFestival' => $activeFest,
'history' => $activeFest->getSellings(),
]);
}
@ -274,6 +267,10 @@ final class DefaultController extends AbstractController
$productFound->addSelling($newSelling);
$entityManager->persist($productFound);
}
else {
return $this->json(['message' => 'Produit '.$product['id'].' non trouvé'], 403);
}
}
@ -285,6 +282,8 @@ final class DefaultController extends AbstractController
->setOwner($loggedUser);
$currentFestival->updateChiffreAffaire();
$entityManager->persist($newSelling);
$entityManager->persist($currentFestival);
@ -296,19 +295,8 @@ final class DefaultController extends AbstractController
$response = [
'message' => 'yes',
'newChiffreAffaire' => $currentFestival->getChiffreAffaire(),
'newChiffreAffaire' => 12,
'clientsCount' => $currentFestival->getClientsCount(),
// 'clientsCount' => 12,
'clientsCount' => count($currentFestival->getSellings()),
'activeFestival' => $currentFestival,
// 'activeFestival' => ['id' => 1,
// 'name' => 'le festival de mock',
// 'dateCreation' => '2025-02-16',
// 'commentaire' => 'MOCK: hop le commentaire de festival',
// 'chiffreAffaire' => '1234',
// 'fondDeCaisseAvant' => '100',
// 'fondDeCaisseAprès' => '150',
// 'sold' => 123
// ],
];
// prendre en compte l'ajout de nouveaux produits si on a une valeur dans le POST

View File

@ -53,11 +53,17 @@ final class ExpenseController extends AbstractController
#[Route('/{id}/edit', name: 'app_expense_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Expense $expense, EntityManagerInterface $entityManager): Response
{
$userFound = $this->getUser();
if (!$userFound || $expense->getUser() !== $userFound) {
throw $this->createAccessDeniedException('Vous n\'êtes pas autorisé à modifier cette dépense.');
}
$form = $this->createForm(Expense1Type::class, $expense);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
$this->addFlash('success', 'La dépense a été modifiée avec succès.');
return $this->redirectToRoute('app_expense_index', [], Response::HTTP_SEE_OTHER);
}
@ -71,9 +77,15 @@ final class ExpenseController extends AbstractController
#[Route('/{id}', name: 'app_expense_delete', methods: ['POST'])]
public function delete(Request $request, Expense $expense, EntityManagerInterface $entityManager): Response
{
$userFound = $this->getUser();
if (!$userFound || $expense->getUser() !== $userFound) {
throw $this->createAccessDeniedException('Vous n\'êtes pas autorisé à supprimer cette dépense.');
}
if ($this->isCsrfTokenValid('delete'.$expense->getId(), $request->getPayload()->getString('_token'))) {
$entityManager->remove($expense);
$entityManager->flush();
$this->addFlash('success', 'La dépense a été supprimée avec succès.');
}
return $this->redirectToRoute('app_expense_index', [], Response::HTTP_SEE_OTHER);

View File

@ -45,6 +45,11 @@ final class FestivalController extends AbstractController
#[Route('/{id}', name: 'app_festival_show', methods: ['GET'])]
public function show(Festival $festival): Response
{
$userFound = $this->getUser();
if (!$userFound || $festival->getUser() !== $userFound) {
throw $this->createAccessDeniedException('Vous n\'êtes pas autorisé à consulter ce festival.');
}
return $this->render('festival/show.html.twig', [
'festival' => $festival,
]);
@ -53,6 +58,11 @@ final class FestivalController extends AbstractController
#[Route('/{id}/edit', name: 'app_festival_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Festival $festival, EntityManagerInterface $entityManager): Response
{
$userFound = $this->getUser();
if (!$userFound || $festival->getUser() !== $userFound) {
throw $this->createAccessDeniedException('Vous n\'êtes pas autorisé à modifier ce festival.');
}
$form = $this->createForm(Festival1Type::class, $festival);
$form->handleRequest($request);
@ -71,10 +81,17 @@ final class FestivalController extends AbstractController
#[Route('/{id}', name: 'app_festival_delete', methods: ['POST'])]
public function delete(Request $request, Festival $festival, EntityManagerInterface $entityManager): Response
{
$userFound = $this->getUser();
if (!$userFound || $festival->getUser() !== $userFound) {
throw $this->createAccessDeniedException('Vous n\'êtes pas autorisé à supprimer ce festival.');
}
if ($this->isCsrfTokenValid('delete'.$festival->getId(), $request->getPayload()->getString('_token'))) {
$entityManager->remove($festival);
$entityManager->flush();
}
$this->addFlash('success', 'Le festival a été supprimé avec succès.');
return $this->redirectToRoute('app_festival_index', [], Response::HTTP_SEE_OTHER);
}

View File

@ -52,6 +52,11 @@ final class ProductController extends AbstractController
#[Route('/{id}', name: 'app_product_show', methods: ['GET'])]
public function show(Product $product): Response
{
$userFound = $this->getUser();
if (!$userFound || $product->getUser() !== $userFound) {
throw $this->createAccessDeniedException('Vous n\'êtes pas autorisé à consulter ce produit.');
}
return $this->render('product/show.html.twig', [
'product' => $product,
]);
@ -60,6 +65,11 @@ final class ProductController extends AbstractController
#[Route('/{id}/edit', name: 'app_product_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Product $product, EntityManagerInterface $entityManager): Response
{
$userFound = $this->getUser();
if (!$userFound || $product->getUser() !== $userFound) {
throw $this->createAccessDeniedException('Vous n\'êtes pas autorisé à modifier ce produit.');
}
$form = $this->createForm(Product1Type::class, $product);
$form->handleRequest($request);
@ -71,6 +81,7 @@ final class ProductController extends AbstractController
}
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
$this->addFlash('success', 'Le produit a été modifié avec succès.');
return $this->redirectToRoute('app_product_index', [], Response::HTTP_SEE_OTHER);
}
@ -84,9 +95,15 @@ final class ProductController extends AbstractController
#[Route('/{id}', name: 'app_product_delete', methods: ['POST'])]
public function delete(Request $request, Product $product, EntityManagerInterface $entityManager): Response
{
$userFound = $this->getUser();
if (!$userFound || $product->getUser() !== $userFound) {
throw $this->createAccessDeniedException('Vous n\'êtes pas autorisé à supprimer ce produit.');
}
if ($this->isCsrfTokenValid('delete'.$product->getId(), $request->getPayload()->getString('_token'))) {
$entityManager->remove($product);
$entityManager->flush();
$this->addFlash('success', 'Le produit a été supprimé avec succès.');
}
return $this->redirectToRoute('app_product_index', [], Response::HTTP_SEE_OTHER);

View File

@ -14,6 +14,9 @@ class SecurityController extends AbstractController
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
if ($error) {
$this->addFlash('error', 'Identifiants invalides.');
}
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();

View File

@ -26,6 +26,7 @@ final class SellingController extends AbstractController
#[Route('/new', name: 'app_selling_new', methods: ['GET', 'POST'])]
public function new(Request $request, EntityManagerInterface $entityManager): Response
{
$selling = new Selling();
$form = $this->createForm(Selling1Type::class, $selling);
$form->handleRequest($request);
@ -46,6 +47,11 @@ final class SellingController extends AbstractController
#[Route('/{id}', name: 'app_selling_show', methods: ['GET'])]
public function show(Selling $selling): Response
{
$userFound = $this->getUser();
if (!$userFound || $selling->getUser() !== $userFound) {
throw $this->createAccessDeniedException('Vous n\'êtes pas autorisé à consulter cette vente.');
}
return $this->render('selling/show.html.twig', [
'selling' => $selling,
]);
@ -54,6 +60,11 @@ final class SellingController extends AbstractController
#[Route('/{id}/edit', name: 'app_selling_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Selling $selling, EntityManagerInterface $entityManager): Response
{
$userFound = $this->getUser();
if (!$userFound || $selling->getUser() !== $userFound) {
throw $this->createAccessDeniedException('Vous n\'êtes pas autorisé à modifier cette vente.');
}
$form = $this->createForm(Selling1Type::class, $selling);
$form->handleRequest($request);

View File

@ -45,6 +45,7 @@ final class SerieFestivalController extends AbstractController
#[Route('/{id}', name: 'app_serie_festival_show', methods: ['GET'])]
public function show(SerieFestival $serieFestival): Response
{
return $this->render('serie_festival/show.html.twig', [
'serie_festival' => $serieFestival,
]);

View File

@ -269,6 +269,18 @@ class Festival
return $this;
}
public function updateChiffreAffaire(): static
{
$total = 0;
foreach ($this->sellings as $selling) {
$total += $selling->getPaidByCustomer();
}
$this->setChiffreAffaire($total);
return $this;
}
public function getChiffreAffaire(): ?float
{
return $this->chiffreAffaire;

View File

@ -12,6 +12,7 @@ use \App\Entity\Product;
use \App\Entity\Selling;
use ApiPlatform\Metadata\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;
use App\Repository\GroupOfProductsRepository;
#[ApiResource(paginationEnabled: false)]
#[ORM\Entity(repositoryClass: GroupOfProductsRepository::class)]
@ -40,7 +41,7 @@ class GroupOfProducts
private ?Collection $sellings = null;
#[ORM\ManyToOne(inversedBy: 'groupOfProducts')]
private ?User $owner = null;
private ?User $user = null;
public function __construct()
@ -132,14 +133,14 @@ class GroupOfProducts
return $this;
}
public function getOwner(): ?User
public function getUser(): ?User
{
return $this->owner;
return $this->user;
}
public function setOwner(?User $owner): static
public function setUser(?User $user): static
{
$this->owner = $owner;
$this->user = $user;
return $this;
}

View File

@ -13,6 +13,7 @@ use ApiPlatform\Metadata\Put;
use Symfony\Component\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\SellingRepository;
#[ApiResource(
operations: [
@ -72,7 +73,8 @@ class Selling
#[ORM\ManyToOne(inversedBy: 'sellings')]
#[Groups(['selling:read', 'selling:write'])]
private ?User $owner = null;
private ?User $user = null;
#[ORM\Column(type: Types::DATE_MUTABLE)]
#[Groups(['selling:read', 'selling:write'])]
@ -218,14 +220,18 @@ class Selling
return $this;
}
public function getOwner(): ?User
public function getuser(): ?User
{
return $this->owner;
return $this->user;
}
public function setOwner(?User $owner): static
public function setuser(?User $user): static
{
$this->owner = $owner;
$this->user = $user;
return $this;
}

View File

@ -87,13 +87,13 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
/**
* @var Collection<int, GroupOfProducts>
*/
#[ORM\OneToMany(targetEntity: GroupOfProducts::class, mappedBy: 'owner')]
#[ORM\OneToMany(targetEntity: GroupOfProducts::class, mappedBy: 'user')]
private Collection $groupOfProducts;
/**
* @var Collection<int, Selling>
*/
#[ORM\OneToMany(targetEntity: Selling::class, mappedBy: 'owner')]
#[ORM\OneToMany(targetEntity: Selling::class, mappedBy: 'user')]
private Collection $sellings;
@ -381,7 +381,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
{
if (!$this->groupOfProducts->contains($groupOfProduct)) {
$this->groupOfProducts->add($groupOfProduct);
$groupOfProduct->setOwner($this);
$groupOfProduct->setUser($this);
}
return $this;
@ -391,8 +391,8 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
{
if ($this->groupOfProducts->removeElement($groupOfProduct)) {
// set the owning side to null (unless already changed)
if ($groupOfProduct->getOwner() === $this) {
$groupOfProduct->setOwner(null);
if ($groupOfProduct->getUser() === $this) {
$groupOfProduct->setUser(null);
}
}
@ -411,7 +411,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
{
if (!$this->sellings->contains($selling)) {
$this->sellings->add($selling);
$selling->setOwner($this);
$selling->setUser($this);
}
return $this;
@ -421,8 +421,8 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
{
if ($this->sellings->removeElement($selling)) {
// set the owning side to null (unless already changed)
if ($selling->getOwner() === $this) {
$selling->setOwner(null);
if ($selling->getUser() === $this) {
$selling->setUser(null);
}
}

View File

@ -29,7 +29,9 @@ class Product1Type extends AbstractType
])
->add('sellings', EntityType::class, [
'class' => Selling::class,
'choice_label' => 'date',
'choice_label' => function(Selling $selling) {
return $selling->getDate()->format('Y-m-d');
},
'multiple' => true,
'required' => false,
])

View File

@ -20,26 +20,7 @@
logged
{% endif %}
">
<!-- Navigation-->
{# <nav class="navbar navbar-expand-lg bg-secondary text-uppercase fixed-top" id="mainNav">#}
{# <div class="container">#}
{# <a class="navbar-brand" href="/#page-top">{% trans %}menu.title{% endtrans %}</a>#}
{# <button class="navbar-toggler text-uppercase font-weight-bold bg-primary text-white rounded" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">#}
{# Menu#}
{# <i class="fas fa-bars"></i>#}
{# </button>#}
{# <div class="collapse navbar-collapse" id="navbarResponsive">#}
{# <ul class="navbar-nav ms-auto">#}
{# #}
{# <li class="nav-item mx-0 mx-lg-1"><a class="nav-link py-3 px-0 px-lg-3 rounded" href="/#about">About</a></li>#}
{# <li class="nav-item mx-0 mx-lg-1"><a class="nav-link py-3 px-0 px-lg-3 rounded" href="/#contact">Contact</a></li>#}
{# </ul>#}
{# </div>#}
{# </div>#}
{# </nav>#}
{% include 'default/login-choices.html.twig' %}
<!-- Portfolio Section-->
<section class="page-section portfolio" id="portfolio">
@ -48,6 +29,16 @@ logged
{% block navigation %}
{% endblock %}
<div id="bodyland">
{% for label, messages in app.flashes %}
{% for message in messages %}
<div class="alert alert-{{ label }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endfor %}
{% block bigMain %}
{% include 'default/header.html.twig' %}

View File

@ -1,4 +1,7 @@
<form method="post" action="{{ path('app_festival_delete', {'id': festival.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ festival.id) }}">
<button class="btn">Delete</button>
<button class="btn btn-danger delete-button">
<i class="fas fa-trash"></i>
Delete
</button>
</form>

View File

@ -4,60 +4,55 @@
<form>
<div class="new-display">
<div class="row">
</div>
<div class="row">
<div class="col-xs-12 col-sm-6">
<button class="btn btn-warning btn-remove-all marged-v" ng-click="removeAll()" ng-disable="!CurrentSellingTotal()">
<i class="fa fa-trash"></i> enlever tout
</button>
<div class="col-xs-12 col-sm-6">
<button class="btn btn-warning btn-remove-all marged-v" ng-click="removeAll()" ng-disable="!CurrentSellingTotal()">
<i class="fa fa-trash"></i> enlever tout
</button>
</div>
</div>
<div ng-repeat="group in activeSellingFiltered track by $index">
<div class="row">
<div class="col-xs-10">
<input class="group-name" type="text" ng-model="group.name">
</div>
<div class="col-xs-2">
<span class="btn btn-warning remove-item"
ng-click="removeGroupeProducts(group.groupId)">
<i class="fa fa-trash"></i>
</span>
</div>
<div ng-repeat="group in activeSellingFiltered track by $index">
<div class="row">
<div class="col-xs-10">
<input class="group-name" type="text" ng-model="group.name">
</div>
<div class="row">
<div class="col-xs-7 col-xs-offset-2 ">
<span ng-if="group.count > 1">
<strong>
{{group.unitPrice}}
€ </strong>
</span>
<span class="badge badge-default" ng-if="group.count">
<i class="fa fa-times"></i> {{group.count}}
</span>
</div>
<div class="col-xs-3 text-right">
<div class="col-xs-2">
<span class="btn btn-warning remove-item"
ng-click="removeGroupeProducts(group.groupId)">
<i class="fa fa-trash"></i>
</span>
</div>
</div>
<div class="row">
<div class="col-xs-7 col-xs-offset-2 ">
<span ng-if="group.count > 1">
<strong>
{{group.totalPrice}}
{{group.unitPrice}}
€ </strong>
</div>
</span>
<span class="badge badge-default" ng-if="group.count">
<i class="fa fa-times"></i> {{group.count}}
</span>
</div>
<div class="col-xs-3 text-right">
<strong>
{{group.totalPrice}}
€ </strong>
</div>
</div>
</div>
</div>
<hr>
{% endverbatim %}
{% include 'logged/angular/totals.html.twig' %}
{% include 'logged/angular/validate-button.html.twig' %}
{% include 'logged/angular/pause-selling.html.twig' %}
{% endverbatim %}
{% include 'logged/angular/totals.html.twig' %}
{% include 'logged/angular/validate-button.html.twig' %}
{% include 'logged/angular/pause-selling.html.twig' %}
</form>
</form>
</div>
</div>

View File

@ -1,13 +1,13 @@
<!--ok loading done-->
<div id="loaded" ng-if="initLoadDone">
<!--caisse IHM-->
<div id="load_ok" class="row">
<div id="listing-products" class="listing-products col-xs-12 col-md-8">
<div id="load_ok" class="columns">
<div id="listing-products" class="listing-products">
{% include 'logged/angular/messages.html.twig' %}
{% include 'logged/angular/listing-products.html.twig' %}
</div>
<div id="sellings" class="sellings col-xs-12 col-md-4">
<div id="sellings" class="sellings">
<div class="list-sell" ng-class="{'bg-success text-success': sellingOk }">

View File

@ -3,6 +3,8 @@
{% block title %}Product index{% endblock %}
{% block body %}
<h1>Product index</h1>
<table class="table">
@ -14,6 +16,7 @@
<th>Stock</th>
<th>Image</th>
<th>Comment</th>
<th>Utilisateur-ice</th>
<th>actions</th>
</tr>
</thead>
@ -24,8 +27,13 @@
<td>{{ product.name }}</td>
<td>{{ product.price }}</td>
<td>{{ product.stock }}</td>
<td>{{ product.image }}</td>
<td>
<a href="{{ path('app_product_show', {'id': product.id}) }}">
<img src="{{ product.image }}" alt="{{ product.name }}" style="width: 100px; height: 100px;">
</a>
</td>
<td>{{ product.comment }}</td>
<td>{{ product.user.name }}, {{ product.user.email }}</td>
<td>
<a href="{{ path('app_product_show', {'id': product.id}) }}">show</a>
<a href="{{ path('app_product_edit', {'id': product.id}) }}">edit</a>

View File

@ -1,4 +1,7 @@
<form method="post" action="{{ path('app_serie_festival_delete', {'id': serie_festival.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ serie_festival.id) }}">
<button class="btn">Delete</button>
<button class="btn btn-danger delete-button">
<i class="fas fa-trash"></i>
Delete
</button>
</form>