Revert "Cleaned doc folder as it was unused"

This reverts commit 8716f2a01e.
This commit is contained in:
Théo DURR 2022-12-15 22:29:55 +01:00
parent 8716f2a01e
commit 6ce70abae5
No known key found for this signature in database
GPG Key ID: 708858E9F7281E30
116 changed files with 5882 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,3 @@
A Pen created at CodePen.io. You can find this one at https://codepen.io/anon/pen/PKVVXY.
This page was used to generate the color palette of the sith.

View File

@ -0,0 +1,74 @@
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: #424242;
font-size: 16px;
}
body {
display: flex;
flex-direction: column;
align-items: center;
font-size: .875rem;
}
.form {
margin: 5rem 0;
width: 30rem;
background: #FAFAFA;
padding: 2rem;
border-radius: .25rem;
box-shadow: 0 4px 5px hsla(0, 0%, 0%, .5);
}
.form-group {
display: flex;
flex-flow: column nowrap;
}
.form-group:not(:first-child) {
margin-top: 1rem;
}
.color-display {
display: flex;
align-items: center;
}
.color-group {
display: flex;
align-items: center;
justify-content: space-between;
}
.color-group > .color-code {
flex: 1 0 auto;
margin-left: 1rem;
}
.color-hue {
height: 2rem;
align-self: stretch;
background-image: linear-gradient(to right, red, yellow, lime, cyan, blue, magenta, red)
}
.form-input {
width: 100%;
margin: 0;
}
.color-preview {
height: 5rem;
width: 5rem;
background-color: lightgrey;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
}
.color-text {
font-size: 3rem;
}

View File

@ -0,0 +1,422 @@
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Color Theory Palette creator</title>
<style>
/* NOTE: The styles were added inline because Prefixfree needs access to your styles and they must be inlined if they are on local disk! */
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: #424242;
font-size: 16px;
}
body {
display: flex;
flex-direction: column;
align-items: center;
font-size: .875rem;
}
.form {
margin: 5rem 0;
width: 30rem;
background: #FAFAFA;
padding: 2rem;
border-radius: .25rem;
box-shadow: 0 4px 5px hsla(0, 0%, 0%, .5);
}
.form-group {
display: flex;
flex-flow: column nowrap;
}
.form-group:not(:first-child) {
margin-top: 1rem;
}
.color-display {
display: flex;
align-items: center;
}
.color-group {
display: flex;
align-items: center;
justify-content: space-between;
}
.color-group > .color-code {
flex: 1 0 auto;
margin-left: 1rem;
}
.color-hue {
height: 2rem;
align-self: stretch;
background-image: linear-gradient(to right, red, yellow, lime, cyan, blue, magenta, red)
}
.form-input {
width: 100%;
margin: 0;
}
.color-preview {
height: 5rem;
width: 5rem;
background-color: lightgrey;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
}
.color-text {
font-size: 3rem;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
</head>
<body>
<form name="color-theory" class="form">
<div class="form-group">
<div class="color-hue"></div>
<input type="range" name="first-color" class="form-input" min="0" max="359" value="220">
</div>
<div class="form-group">
<fieldset class="first-color">
<legend>First color</legend>
<div class="color-group">
<div class="color-preview"></div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="second-color">
<legend>Second color</legend>
<div class="color-group">
<div class="color-preview"></div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
</div>
<div class="form-group">
<fieldset class="primary-color">
<legend>Primary color</legend>
<div class="color-group">
<div class="color-preview"></div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="complementary-color">
<legend>Secondary color</legend>
<div class="color-group">
<div class="color-preview"></div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
</div>
<div class="form-group">
<fieldset class="text-on-primary">
<legend>Text on primary color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="text-on-complementary">
<legend>Text on complementary color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
</div>
<div class="form-group">
<fieldset class="complementary-neutral-light">
<legend>Complementary neutral light color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="complementary-neutral">
<legend>Complementary neutral color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="complementary-neutral-dark">
<legend>Complementary neutral dark color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="primary-neutral-light">
<legend>Primary neutral light color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="primary-neutral">
<legend>Primary neutral color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="primary-neutral-dark">
<legend>Primary neutral dark color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
</div>
<div class="form-group">
<fieldset class="white">
<legend>"White" color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="black">
<legend>"Black" color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
</div>
<div class="form-group">
<fieldset class="primary-light">
<legend>Primary light color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="primary-color">
<legend>Primary color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
<fieldset class="primary-dark">
<legend>Primary dark color</legend>
<div class="color-group">
<div class="color-preview">
<span class="color-text">Ab</span>
</div>
<input type="text" class="color-code" readonly>
</div>
</fieldset>
</div>
</form>
<template id="scss-template">
<style type="text/scss">
//From https://github.com/tallys/color-theory
//Pick a color
// THIS IS SET IN THE THEME FILE AT THE TOP LEVEL
// $first-color: hsl(17, 100%, 50%);
// Find the complement
$second-color: complement($first-color);
//Check if you have a cool color on your hands. Cool colors will overpower warm colors when mixing.
@function is-cool-color($color) {
@return hue($color) < 310 and hue($color) > 140;
}
@function is-high-key-value($color) {
@return hue($color) > 20 and hue($color) < 190;
}
@function is-highest-key-value($color) {
@return hue($color) > 30 and hue($color) <90;
}
//Establish a relationship (similar lighting conditions) between colors.
@function harmonious-mix($mix, $base) {
@if (is-cool-color($mix)){
@if is-high-key-value($base) {
@return mix($mix, $base, 11%);
}
@else {
@return mix($mix, $base, 16%);
}
}
@else {
@if is-high-key-value($base) {
@return mix($mix, $base, 13%);
}
@else {
@return mix($mix, $base, 23%);
}
}
}
@function mix-neutral($color) {
@if (is-highest-key-value($color)) {
@if is-high-key-value(complement($color)) {
@return mix(complement($color), $color, 19%);
}
@else {
@return mix(complement($color), $color, 13%);
}
}
@else if (is-high-key-value($color)) {
@if is-high-key-value(complement($color)) {
@return mix(complement($color), $color, 31%);
}
@else {
@return mix(complement($color), $color, 23%);
}
}
@else {
@if is-highest-key-value(complement($color)) {
@return mix(complement($color), $color, 31%);
}
@if is-high-key-value(complement($color)) {
@return mix(complement($color), $color, 26%);
}
@else {
@return mix(complement($color), $color, 23%);
}
}
}
@function pick-contrast-of($color) {
@if is-high-key-value($color){
@if lightness($color) < 30% {
@return lighten(complement($color), 86);
}
@else if lightness($color) > 70% {
@return darken(complement($color), 68);
}
@else {
@return darken(complement($color), 53);
}
} @else {
@if lightness($color) < 30% {
@return lighten(complement($color), 86);
}
@else if lightness($color) > 70% {
@return darken(complement($color), 68);
}
@else {
@return lighten(complement($color), 53);
}
}
}
$primary-color: harmonious-mix($second-color, $first-color);
$complementary-color: harmonious-mix($first-color, $second-color);
// Complementary Neutrals, highlight, midtone, shadow
$complementary-neutral: mix-neutral($complementary-color);
$complementary-neutral-light: lighten($complementary-neutral, 33);
$complementary-neutral-dark: darken($complementary-neutral, 33);
// Primary neutrals, highlight, midtone, shadow`
$primary-neutral: mix-neutral($primary-color);
$primary-neutral-light: lighten($primary-neutral, 33);
$primary-neutral-dark: darken($primary-neutral, 33);
// Primary tint and shade
$primary-light: mix($primary-neutral-light, $primary-color, 45%);
$primary-dark: mix($primary-neutral-dark, $primary-color, 45%);
$complementary-light: mix($complementary-neutral-light, $complementary-color, 45%);
// Pure neutrals, highlight, midtone, shadow
$white: lighten($primary-neutral-light, 15);
$neutral-gray: grayscale($primary-neutral);
$primary-gray: mix($primary-color, $complementary-color, 30);
$complementary-gray: mix($complementary-color, $primary-color, 63);
$black: grayscale($complementary-neutral-dark);
// Analogous Colors
$analogous-color: adjust-hue($complementary-color, -40);
$complementary-analogous: mix($analogous-color, $complementary-color, 66);
.first-color {color: unquote( 'hsl(') hue($first-color), saturation($first-color), lightness($first-color) unquote(')')}
.second-color {color: unquote( 'hsl(') hue($second-color), saturation($second-color), lightness($second-color) unquote(')')}
.primary-color {color: unquote( 'hsl(') hue($primary-color), saturation($primary-color), lightness($primary-color) unquote(')')}
.complementary-color {color: unquote( 'hsl(') hue($complementary-color), saturation($complementary-color), lightness($complementary-color) unquote(')')}
.primary-neutral-light {color: unquote( 'hsl(') hue($primary-neutral-light), saturation($primary-neutral-light), lightness($primary-neutral-light) unquote(')')}
.primary-neutral {color: unquote( 'hsl(') hue($primary-neutral), saturation($primary-neutral), lightness($primary-neutral) unquote(')')}
.primary-neutral-dark {color: unquote( 'hsl(') hue($primary-neutral-dark), saturation($primary-neutral-dark), lightness($primary-neutral-dark) unquote(')')}
.complementary-neutral-light {color: unquote( 'hsl(') hue($complementary-neutral-light), saturation($complementary-neutral-light), lightness($complementary-neutral-light) unquote(')')}
.complementary-neutral {color: unquote( 'hsl(') hue($complementary-neutral), saturation($complementary-neutral), lightness($complementary-neutral) unquote(')')}
.complementary-neutral-dark {color: unquote( 'hsl(') hue($complementary-neutral-dark), saturation($complementary-neutral-dark), lightness($complementary-neutral-dark) unquote(')')}
.white {color: unquote( 'hsl(') hue($white), saturation($white), lightness($white) unquote(')')}
.black {color: unquote( 'hsl(') hue($black), saturation($black), lightness($black) unquote(')')}
.primary-light {color: unquote( 'hsl(') hue($primary-light), saturation($primary-light), lightness($primary-light) unquote(')')}
.primary-dark {color: unquote( 'hsl(') hue($primary-dark), saturation($primary-dark), lightness($primary-dark) unquote(')')}
.complementary-light {color: unquote( 'hsl(') hue($complementary-light), saturation($complementary-light), lightness($complementary-light) unquote(')')}
.primary-gray {color: unquote( 'hsl(') hue($primary-gray), saturation($primary-gray), lightness($primary-gray) unquote(')')}
.neutral-gray {color: unquote( 'hsl(') hue($neutral-gray), saturation($neutral-gray), lightness($neutral-gray) unquote(')')}
.complementary-gray {color: unquote( 'hsl(') hue($complementary-gray), saturation($complementary-gray), lightness($complementary-gray) unquote(')')}
</style>
</template>
<script src='https://cdnjs.cloudflare.com/ajax/libs/sass.js/0.10.3/sass.sync.js'></script>
<script src="js/index.js"></script>
</body>
</html>

View File

@ -0,0 +1,103 @@
/* jshint esversion: 6 */
// This is using Sass.js to use Sass built-in color mixing functions
const firstColorChooser = document.forms['color-theory']['first-color'];
const firstColor = document.querySelector('.first-color');
const secondColor = document.querySelector('.second-color');
let hue = undefined;
let comp = undefined;
updateColors();
Sass.options({
precision: 1
});
computeScss();
document.forms['color-theory']['first-color'].addEventListener('input', updateColors);
document.forms['color-theory']['first-color'].addEventListener('change', computeScss);
function updateColors(ev) {
hue = parseInt(firstColorChooser.value);
comp = (hue + 180) % 360;
setColorPreview([firstColor], `hsl(${hue}, 100%, 50%)`);
setColorPreview([secondColor], `hsl(${comp}, 100%, 50%)`);
}
function setColorPreview(fieldsets, color) {
Array.from(fieldsets).forEach(fieldset => {
const preview = fieldset.querySelector('.color-preview');
preview.style.backgroundColor = fieldset.querySelector('.color-code').value = color;
const text = fieldset.querySelector('.color-text')
if(text)
text.style.color = computeTextColor(window.getComputedStyle(preview).backgroundColor);
});
}
function setColorText(fieldsets, bg, text) {
Array.from(fieldsets).forEach(fieldset => {
fieldset.querySelector('.color-preview').style.backgroundColor = bg;
fieldset.querySelector('.color-text').style.color = fieldset.querySelector('.color-code').value = text;
});
}
function computeScss() {
Sass.compile(
`$first-color: hsl(${hue}, 100%, 50%);` +
document.querySelector('#scss-template').content.firstElementChild.textContent, computedScssHandler);
}
function computedScssHandler(result) {
let colors = {};
result.text.split('\n\n').forEach(rule => {
const color = /\.([\w\-]+) {\s*color: (hsl\() (\d{1,3}(?:\.\d+)?)deg(.*) (\));\s*}/.exec(rule).splice(1, 5).join('').split('hsl');
colors[color[0]] = `hsl${color[1]}`;
});
for (let colorName in colors)
if (document.querySelector(`.${colorName}`)) setColorPreview(document.querySelectorAll(`.${colorName}`), colors[colorName]);
const primaryTextColor = computeTextColor(window.getComputedStyle(document.querySelector('.primary-color .color-preview')).backgroundColor);
const complementaryTextColor = computeTextColor(window.getComputedStyle(document.querySelector('.complementary-color .color-preview')).backgroundColor);
setColorText([document.querySelector('.text-on-primary')], document.querySelector('.primary-color .color-preview').style.backgroundColor, primaryTextColor);
setColorText([document.querySelector('.text-on-complementary')], document.querySelector('.complementary-color .color-preview').style.backgroundColor, complementaryTextColor)
}
function computeTextColor(colorStr) {
const black = [0, 0, 0, .87];
const white = [255, 255, 255, 1];
[, , r, g, b, a] = /(rgba?)\((\d{1,3}), (\d{1,3}), (\d{1,3})(?:, (\d(?:\.\d+)))?\)/.exec(colorStr);
const color = [parseInt(r), parseInt(g), parseInt(b), parseFloat(a == undefined ? 1 : a)]
const blackContrast = computeConstrastRatio(black, color);
const whiteContrast = computeConstrastRatio(white, color);
return blackContrast < whiteContrast ? `hsl(0, 0%, 100%)` : `hsla(0, 0%, 0%, 0.87)`
}
function computeConstrastRatio([fr, fg, fb, fa], [br, bg, bb, ba]) {
if (fa < 1) {
fr = fr * fa + br * (1 - fa);
fg = fg * fa + bg * (1 - fa);
fb = fb * fa + bb * (1 - fa);
fa = 1;
}
const fl = luminance([fr, fg, fb]);
const bl = luminance([br, bg, bb]);
if (fl < bl)
return (bl + .05) / (fl + .05);
else
return (fl + .05) / (bl + .05);
}
function luminance([r, g, b]) {
return .2126 * colorComponent(r) + .7152 * colorComponent(g) + .0722 * colorComponent(b);
}
function colorComponent(color) {
const c = color / 255;
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
}

View File

@ -0,0 +1,16 @@
<!--
Copyright (c) 2017 by Captain Anonymous (https://codepen.io/anon/pen/PKVVXY)
Fork of an original work by Jean-Baptiste Lenglet (https://codepen.io/Magador/pen/YZjWxe)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-->

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
doc/Guide de Tresorerie.pdf Normal file

Binary file not shown.

View File

@ -0,0 +1,124 @@
<?php
// --------------- VARIABLES A MODIFIER ---------------
// Ennonciation de variables
$pbx_site = '1520411'; //variable de test 1999888
$pbx_rang = '001'; //variable de test 32
$pbx_identifiant = '650995411'; //variable de test 3
$pbx_cmd = 'CMD_1'; //variable de test cmd_test1
$pbx_porteur = 'skia@git.an'; //variable de test test@test.fr
$pbx_total = '510'; //variable de test 100
// Suppression des points ou virgules dans le montant
$pbx_total = str_replace(",", "", $pbx_total);
$pbx_total = str_replace(".", "", $pbx_total);
// Paramétrage des urls de redirection après paiement
$pbx_effectue = 'http://www.votre-site.extention/page-de-confirmation';
$pbx_annule = 'http://www.votre-site.extention/page-d-annulation';
$pbx_refuse = 'http://www.votre-site.extention/page-de-refus';
// Paramétrage de l'url de retour back office site
$pbx_repondre_a = 'http://www.votre-site.extention/page-de-back-office-site';
// Paramétrage du retour back office site
$pbx_retour = 'Amount:M;BasketID:R;Auto:A;Error:E;Sig:K';
// Connection à la base de données
// mysql_connect...
// On récupère la clé secrète HMAC (stockée dans une base de données par exemple) et que lon renseigne dans la variable $keyTest;
//$keyTest = '0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF';
$keyTest = '2d21b1f0d5b64bce056b342b5259db312dfc0176dcafb33eb804b6aaaa3acc07320742954ef3b052f36942b09f86ccb9d24c8814586c1a0d24319fd8985c19e5';
// --------------- TESTS DE DISPONIBILITE DES SERVEURS ---------------
/*
$serveurs = array('tpeweb.paybox.com', //serveur primaire
'tpeweb1.paybox.com'); //serveur secondaire
$serveurOK = "";
//phpinfo(); <== voir paybox
foreach($serveurs as $serveur){
$doc = new DOMDocument();
$doc->loadHTMLFile('https://'.$serveur.'/load.html');
$server_status = "";
$element = $doc->getElementById('server_status');
if($element){
$server_status = $element->textContent;}
if($server_status == "OK"){
// Le serveur est prêt et les services opérationnels
$serveurOK = $serveur;
break;}
// else : La machine est disponible mais les services ne le sont pas.
}
//curl_close($ch); <== voir paybox
if(!$serveurOK){
die("Erreur : Aucun serveur n'a été trouvé");}
// Activation de l'univers de préproduction
//$serveurOK = 'preprod-tpeweb.paybox.com';
//Création de l'url cgi paybox
$serveurOK = 'https://'.$serveurOK.'/cgi/MYchoix_pagepaiement.cgi';
// echo $serveurOK;
*/
// --------------- TRAITEMENT DES VARIABLES ---------------
// On récupère la date au format ISO-8601
$dateTime = date("c");
$dateTime = "2016-07-26T15:38:11+02:00";
// On crée la chaîne à hacher sans URLencodage
$msg = "PBX_SITE=".$pbx_site.
"&PBX_RANG=".$pbx_rang.
"&PBX_IDENTIFIANT=".$pbx_identifiant.
"&PBX_TOTAL=".$pbx_total.
"&PBX_DEVISE=978".
"&PBX_CMD=".$pbx_cmd.
"&PBX_PORTEUR=".$pbx_porteur.
// "&PBX_REPONDRE_A=".$pbx_repondre_a.
"&PBX_RETOUR=".$pbx_retour.
// "&PBX_EFFECTUE=".$pbx_effectue.
// "&PBX_ANNULE=".$pbx_annule.
// "&PBX_REFUSE=".$pbx_refuse.
"&PBX_HASH=SHA512".
"&PBX_TIME=".$dateTime;
// echo $msg;
// Si la clé est en ASCII, On la transforme en binaire
$binKey = pack("H*", $keyTest);
// On calcule lempreinte (à renseigner dans le paramètre PBX_HMAC) grâce à la fonction hash_hmac et //
// la clé binaire
// On envoi via la variable PBX_HASH l'algorithme de hachage qui a été utilisé (SHA512 dans ce cas)
// Pour afficher la liste des algorithmes disponibles sur votre environnement, décommentez la ligne //
// suivante
// print_r(hash_algos());
echo $msg, "\n\n";
var_dump($binKey);
$hmac = strtoupper(hash_hmac('sha512', $msg, $binKey));
// La chaîne sera envoyée en majuscule, d'où l'utilisation de strtoupper()
// On crée le formulaire à envoyer
// ATTENTION : l'ordre des champs est extrêmement important, il doit
// correspondre exactement à l'ordre des champs dans la chaîne hachée
?>
<!------------------ ENVOI DES INFORMATIONS A PAYBOX (Formulaire) ------------------>
<form method="POST" action="<?php echo $serveurOK; ?>">
<input type="hidden" name="PBX_SITE" value="<?php echo $pbx_site; ?>">
<input type="hidden" name="PBX_RANG" value="<?php echo $pbx_rang; ?>">
<input type="hidden" name="PBX_IDENTIFIANT" value="<?php echo $pbx_identifiant; ?>">
<input type="hidden" name="PBX_TOTAL" value="<?php echo $pbx_total; ?>">
<input type="hidden" name="PBX_DEVISE" value="978">
<input type="hidden" name="PBX_CMD" value="<?php echo $pbx_cmd; ?>">
<input type="hidden" name="PBX_PORTEUR" value="<?php echo $pbx_porteur; ?>">
<input type="hidden" name="PBX_RETOUR" value="<?php echo $pbx_retour; ?>">
<input type="hidden" name="PBX_HASH" value="SHA512">
<input type="hidden" name="PBX_TIME" value="<?php echo $dateTime; ?>">
<input type="hidden" name="PBX_HMAC" value="<?php echo $hmac; ?>">
<input type="submit" value="Envoyer">
</form>

View File

@ -0,0 +1,63 @@
package signver;
import java.security.interfaces.RSAPublicKey;
import java.security.Signature;
import java.security.KeyFactory;
import java.security.spec.X509EncodedKeySpec;
import java.io.FileInputStream;
import java.io.DataInputStream;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.net.URLCodec;
public class SignVer {
// verification signature RSA des donnees avec cle publique
private static boolean verify( byte[] dataBytes, byte[] sigBytes, String sigAlg, RSAPublicKey pubKey) throws Exception
{
Signature sig = Signature.getInstance(sigAlg);
sig.initVerify(pubKey);
sig.update(dataBytes);
return sig.verify(sigBytes);
}
// chargement de la cle AU FORMAT der :
// openssl rsa -inform PEM -in pbx_pubkey.pem -outform DER -pubin -out /tmp/pubkey.der
private static RSAPublicKey getPubKey(String pubKeyFile) throws Exception
{
FileInputStream fis = new FileInputStream(pubKeyFile);
DataInputStream dis = new DataInputStream(fis);
byte[] pubKeyBytes = new byte[fis.available()];
dis.readFully(pubKeyBytes);
fis.close();
dis.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// extraction cle
X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubKeyBytes);
RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(pubSpec);
return pubKey;
}
// exemple de verification de la signature
public static void main(String[] unused) throws Exception {
String sData = ""; // donnees signees URL encodees
String sSig = ""; // signature Base64 et URL encodee
// decodage ...
byte[] dataBytes = URLCodec.decodeUrl(sData.getBytes());
byte[] sigBytes = Base64.decodeBase64( URLCodec.decodeUrl(sSig.getBytes()));
// lecture de la cle publique
RSAPublicKey pubK = getPubKey("/tmp/pubkey.der");
// verification signature
boolean result = verify(dataBytes, sigBytes, "SHA1withRSA", pubK);
// affichage resultat
System.out.println("Resultat de la verification de signature : " + result);
}
}

View File

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCvDYKaLH2xz4goZYXZWoHo6wyMb24A1iF7s70tB/g3XthEVS+/
Wov+ZGqNTMLc0L+HZAJjcEc9h8Br5jPLR4VhaoKi+rezDxTQweaC24ydJWFKRhyX
Bhm2Wfnhppgzv9EqZKOrFaTlLQHu0F+KWEd7LngP4xcW9qjt19MfEmk0swIDAQAB
AoGABqXztNlFuNAR8r7QU43tayQqKNc+jUeUo/cSkzg/RBMVEZtOoezVbkbwCQfG
Ss6ex4yTzqT//6U9OJvYkbrYpOdq2BinuRv9n/NlKhCJ/Ym9s/DS8D6xdEX/R5lg
mIURQYl9uHS6VVnLq79j38BsjIhDAvjuSzZGZUa4v0iBTHkCQQDWp4iPqv2jUzBW
UgDP6C+QFqLgYKuYxF+yyBCXO0XzaHaEJUBuxuvTU/kuIifk3lhXnV5r0sXJd2Ax
aQkoJXc1AkEA0MU+4SSYPYADQm1gcXXuR4Kjb0/QhIGRiotxVu2nLGS7aULe1D8p
XoLpSQCv3j5amtXVx1yTWuaEYZqHVeQxRwJAdOprh1UrMXpuKZYgux1MSr8JmA0P
afYL6eTupHC0eQ+8/d0Ma0oNyN1EK8yOzioNFCuy8ierc0CCNGdxhVxiwQJAP/cv
fOwpeS5v0TqSAjGQAHkWelSKHw9T+I8g+vF19zQl9+p1O7LeigayU5vSRtX0DNzX
022Z+JAIn58pODfioQJBALQGN2kFCSk935VnMUJ4X5qFCKiXBgebuARUSw6tDEpY
gFdqyJE4WQ4uWVz0D9M27lCa8wj7pYrOhB/UiMKbuqY=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvDYKaLH2xz4goZYXZWoHo6wyM
b24A1iF7s70tB/g3XthEVS+/Wov+ZGqNTMLc0L+HZAJjcEc9h8Br5jPLR4VhaoKi
+rezDxTQweaC24ydJWFKRhyXBhm2Wfnhppgzv9EqZKOrFaTlLQHu0F+KWEd7LngP
4xcW9qjt19MfEmk0swIDAQAB
-----END PUBLIC KEY-----

View File

@ -0,0 +1,11 @@
<?php
$montant=$_GET['montant'];
$ref_com=$_GET['ref'];
$auto=$_GET['auto'];
$trans=$_GET['trans'];
print ("<center><b><h2>Votre transaction a été acceptée</h2></center></b><br>");
print ("<br><b>MONTANT : </b>$montant\n");
print ("<br><b>REFERENCE : </b>$ref_com\n");
print ("<br><b>AUTO : </b>$auto\n");
print ("<br><b>TRANS : </b>$trans\n");
?>

View File

@ -0,0 +1,11 @@
<?php
$montant=$_GET['montant'];
$ref_com=$_GET['ref'];
#$auto=$_GET['auto'];
$trans=$_GET['trans'];
print ("<center><b><h2>Votre transaction a été annulée</h2></center></b><br>");
print ("<br><b>MONTANT : </b>$montant\n");
print ("<br><b>REFERENCE : </b>$ref_com\n");
#print ("<br><b>AUTO : </b>$auto\n");
print ("<br><b>TRANS : </b>$trans\n");
?>

View File

@ -0,0 +1,79 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Exemple_mail_ticket_client</title>
<style>
<!--
/* Font Definitions */
@font-face
{font-family:"Bernard MT Condensed";
panose-1:0 0 0 0 0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman";}
a:link, span.MsoHyperlink
{color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{color:purple;
text-decoration:underline;}
p
{font-size:12.0pt;
font-family:"Times New Roman";}
p.style1, li.style1, div.style1
{margin-right:0cm;
margin-left:0cm;
font-size:9.0pt;
font-family:"Bernard MT Condensed";}
@page Section1
{size:595.3pt 841.9pt;
margin:70.85pt 70.85pt 70.85pt 70.85pt;}
div.Section1
{page:Section1;}
-->
</style>
</head>
<body lang=FR link=blue vlink=purple>
<div class=Section1>
<p class=style1 align=center style='text-align:center'><b><i><span
style='font-size:10.0pt;font-family:Arial;color:#333399'>Merci de votre
commande</span></i></b></p>
<p class=style1 align=center style='text-align:center'><b><i><span
style='font-size:10.0pt;font-family:Arial;color:#333399'>Celle-ci sera traitée
dans les meilleurs délais</span></i></b></p>
<p class=style1 align=center style='text-align:center'><b><i><span
style='font-size:10.0pt;font-family:Arial;color:#333399'>Cordialement,</span></i></b></p>
<p align=center style='text-align:center'><img width=200 height=50
src="Boutique.fr/Images/votre_logo.jpg" alt="Votre Enseigne"></p>
<p align=center style='margin-top:0cm;margin-right:0cm;margin-bottom:6.0pt;
margin-left:0cm;text-align:center'><b><span style='font-size:8.0pt;font-family:
Arial;color:#FF9900'>Gardez les références de votre commande et n'hésitez pas à
nous contacter si vous avez des questions :</span></b></p>
<p align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center'><b><span
style='font-size:8.0pt;font-family:Arial;color:#FF9900'>tel : 00 00 00 00 00</span></b></p>
<p align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center'><b><span
style='font-size:8.0pt;font-family:Arial;color:#FF9900'>courriel : <a
href="mailto:contact@maboutique.fr"><span style='color:#FF9900;text-decoration:
none'>contact@maboutique.fr</span></a></span></b></p>
</div>
</body>
</html>

View File

@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe+hkicNP7ROHUssGNtHwiT2Ew
HFrSk/qwrcq8v5metRtTTFPE/nmzSkRnTs3GMpi57rBdxBBJW5W9cpNyGUh0jNXc
VrOSClpD5Ri2hER/GcNrxVRP7RlWOqB1C03q4QYmwjHZ+zlM4OUhCCAtSWflB4wC
Ka1g88CjFwRw/PB9kwIDAQAB
-----END PUBLIC KEY-----

View File

@ -0,0 +1,11 @@
<?php
$montant=$_GET['montant'];
$ref_com=$_GET['ref'];
#$auto=$_GET['auto'];
$trans=$_GET['trans'];
print ("<center><b><h2>Votre transaction a été refusée</h2></center></b><br>");
print ("<br><b>MONTANT : </b>$montant\n");
print ("<br><b>REFERENCE : </b>$ref_com\n");
#print ("<br><b>AUTO : </b>$auto\n");
print ("<br><b>TRANS : </b>$trans\n");
?>

View File

@ -0,0 +1,102 @@
///// script PHP de vérification de la signature Paybox.
///// Ce code peut s'executer dans un contexte Apache/PHP.
///// Il affiche alors une page web qui permet de vérifier et signer des données.
<html>
<head>
<title>formulaire d'exemple pour test signature</title>
</head>
<body>
<?php
$status = "GUY";
function LoadKey( $keyfile, $pub=true, $pass='' ) { // chargement de la clé (publique par défaut)
$fp = $filedata = $key = FALSE; // initialisation variables
$fsize = filesize( $keyfile ); // taille du fichier
if( !$fsize ) return FALSE; // si erreur on quitte de suite
$fp = fopen( $keyfile, 'r' ); // ouverture fichier
if( !$fp ) return FALSE; // si erreur ouverture on quitte
$filedata = fread( $fp, $fsize ); // lecture contenu fichier
fclose( $fp ); // fermeture fichier
if( !$filedata ) return FALSE; // si erreur lecture, on quitte
if( $pub )
$key = openssl_pkey_get_public( $filedata ); // recuperation de la cle publique
else // ou recuperation de la cle privee
$key = openssl_pkey_get_private( array( $filedata, $pass ));
return $key; // renvoi cle ( ou erreur )
}
// comme precise la documentation Paybox, la signature doit être
// obligatoirement en dernière position pour que cela fonctionne
function GetSignedData( $qrystr, &$data, &$sig ) { // renvoi les donnes signees et la signature
$pos = strrpos( $qrystr, '&' ); // cherche dernier separateur
$data = substr( $qrystr, 0, $pos ); // et voila les donnees signees
$pos= strpos( $qrystr, '=', $pos ) + 1; // cherche debut valeur signature
$sig = substr( $qrystr, $pos ); // et voila la signature
$sig = base64_decode( urldecode( $sig )); // decodage signature
}
// $querystring = chaine entière retournée par Paybox lors du retour au site (méthode GET)
// $keyfile = chemin d'accès complet au fichier de la clé publique Paybox
function PbxVerSign( $qrystr, $keyfile ) { // verification signature Paybox
$key = LoadKey( $keyfile ); // chargement de la cle
if( !$key ) return -1; // si erreur chargement cle
// penser à openssl_error_string() pour diagnostic openssl si erreur
GetSignedData( $qrystr, $data, $sig ); // separation et recuperation signature et donnees
return openssl_verify( $data, $sig, $key ); // verification : 1 si valide, 0 si invalide, -1 si erreur
}
if( !isset( $_POST['data'] )) // pour alimentation par defaut quand premier affichage du formulaire
$_POST['data'] = 'arg1=aaaa&arg2=bbbb&arg3=cccc&arg4=dddd';
if( isset( $_POST['signer']) ) { // si on a demande la signature
$key = LoadKey( 'TestK004.prv.pem', false ); // chargement de la cle prive (de test, sans mot de passe)
if( $key ) {
openssl_sign( $_POST['data'], $signature, $key ); // generation de la signature
openssl_free_key( $key ); // liberation ressource (confidentialite cle prive)
$status = "OK";
}
else $status = openssl_error_string(); // diagnostic erreur
$_POST['signeddata'] = $_POST['data']; // construction chaine data + signature
$_POST['signeddata'] .= '&sig=';
$_POST['signeddata'] .= urlencode( base64_encode( $signature ));
}
if( isset( $_POST['verifier']) ) { // si on a demande la verification
$CheckSig = PbxVerSign( $_POST['signeddata'], 'TestK004.pub.pem' );
if( $CheckSig == 1 ) $status = "Signature valide";
else if( $CheckSig == 0 ) $status = "Signature invalide : donnees alterees ou signature falsifiee";
else $status = "Erreur lors de la vérification de la signature";
}
?>
<form action="testsign.php" method="POST">
<table border="0" cellpadding="3" cellspacing="0" align="center">
<tr>
<td>status = <?php echo $status; ?></td>
</tr>
<tr>
<td><input type="text" name="data" size="80"value="<?= $_POST['data'] ?>"></td>
<td><input type="submit" name="signer" value="signer"/></td>
</tr>
<tr>
<td><input type="text" name="signeddata" size="80"value="<?= $_POST['signeddata'] ?>"></td>
<td><input type="submit" name="verifier" value="verifier"/></td>
</tr>
</table>
</form>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,206 @@
/* CSS Document */
/* feuille de style par d?faut pour les pages
de choix de paiement et de paiement
paybox system*/
th { /* headers de tables (dans choix paiement les ent?tes de table en bleu )*/
color: black;
background-color: #2890D6;
font-size: 16px;
font-weight: bold;
}
td {/* cellules */
font-size: 13px;
}
h2 {/*le texte 'paiement de' et '?'*/
margin:0;
padding: 0;
}
.pbx_table_logo td {/*les cellules de la table logo (la table a la classe "pbx_table_logo")*/
background-color: #FFFFFF;
text-align: center;
}
.pbx_h1{/* le premier bloc de texte dans choixpaiement */
font-size: 14px;
font-family: verdana;
font-weight:normal;
}
.pbx_h2{/* le second bloc de texte dans choixpaiement (choisisseze un moyen...)*/
font-family: verdana;
font-size:12px;
font-weight:bold;
}
.pbx_h3{/* l'ent?te reprenant le libell? du type de moyen de paiement*/
font-family: verdana;
font-size:12;
font-weight:normal;
}
.pbx_h4{/* nom d'enseigne, en page de paiement*/
color:#444;
display: block;
margin: 8px 0 0 0;
padding: 0;
border-top: 1px solid #ccc;
padding: 5px;
display: block;
background-color: #f5f5f5;
height: 35px;
line-height: 35px;
font-size: 12px;
font-weight: normal;
text-shadow: none;
}
.pbx_copyright h5{/*mention paybox en bas de page (choix et paiement)*/
font-size:10px;
font-weight: normal;
}
a {
text-decoration: none;
color : gray;
font-weight: bold;
font-style: italic;
padding: 0 5px;
}
#tabledevises {
color: #AAA;
}
a:hover {
color : #222;
}
body { color: #555555;
font-family: arial,verdana,sans-serif;
padding : 0px;
margin: 0;
}
#idframe_pay {
border-color: #CCCCCC;
border-radius: 6px 6px 6px 6px;
border-style: solid;
border-width: 1px;
margin: 20px;
position: relative;
}
#idframe_pay table {
border-spacing:0;
border-collapse:collapse;
width: 100%;
}
#idframe_pay h2 {
width: 100%;
background: url("main_header_background.png") repeat scroll 0 0 transparent;
border-color: #CCCCCC;
border-radius: 5px 5px 0 0;
border-style: solid;
border-width: 0 0 1px 0;
box-shadow: 1px 1px 0 0 #888888 inset;
color: #EEEEEE;
font-weight: bold;
text-shadow: 1px 1px 1px #444444;
font-size: 16px;
font-weight: bold;
text-align: center;
padding: 8px 0 0 0;
}
/*
#idframe_pay td {
vertical-align: top;
}
*/
.pbx-align-center {
text-align: center;
padding: 20px 10px;
width: 50%;
}
.pbx-align-right {
text-align: right;
padding: 2px 10px;
width: 50%;
white-space: nowrap;
}
.pbx-align-button-right img {
vertical-align:middle;
}
.pbx-align-left {
text-align: left;
padding: 2px 10px;
width: 50%;
}
.pbx-align-left img {
vertical-align:middle;
}
.pbx-align-very-left {
text-align: left;
padding: 2px 10px;
width: 100%;
}
.pbx-no-padding {
padding: 0;
}
.pbx-align-button-right {
text-align: right;
padding: 2px 10px;
width: 50%;
}
.pbx-align-button-left {
text-align: left;
padding: 2px 10px;
width: 50%;
}
#Devises{
left:0px;
top:0px;
}
#pbx-numero-carte, #pbx-numero-carte-input {
padding-top: 30px
}
#pbx-maxicheque-vide {
display: none;
}
#pbx-maxicheque-frame {
padding: 0 220px;
}
#blocCarte1 {
display: inline-block;
}
#zoneResultConsult {
border: 1px solid #CCCCCC;
border-radius: 10px 10px 10px 10px;
display: block;
margin: 20px;
padding: 20px;
}

BIN
doc/MLD.pdf Normal file

Binary file not shown.

20
doc/Makefile Normal file
View File

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

206
doc/SYNTAX.html Normal file
View File

@ -0,0 +1,206 @@
<p>Cette page vise à documenter la syntaxe <em>Markdown</em> utilisée sur le site.</p>
<h1>Markdown-AE Documentation</h1>
<p>Le Markdown le plus standard se trouve documenté ici:
<a href="https://daringfireball.net/projects/markdown/syntax">https://daringfireball.net/projects/markdown/syntax</a> .<br>
Si cette page n'est pas exhaustive vis à vis de la syntaxe du site AE,
elle a au moins le mérite de bien documenter le Markdown original.</p>
<p>Le réel parseur du site AE est une version tunée de <a href="https://github.com/lepture/mistune">mistune</a>.<br>
Les plus aventureux pourront aller lire ses <a href="https://github.com/lepture/mistune/blob/master/tests/fixtures">tests</a>
afin d'en connaître la syntaxe le plus finement possible.<br>
En pratique, cette page devrait déjà résumer une bonne partie.</p>
<h2>Basique</h2>
<ul>
<li><p>Mettre le texte en <strong>gras</strong> : <code>**texte**</code></p>
</li>
<li><p>Mettre le texte en <em>italique</em> : <code>*texte*</code></p>
</li>
<li><p><u>Souligner</u> le texte : <code>__texte__</code></p>
</li>
<li><p><del>Barrer du texte</del> : <code>~~texte~~</code></p>
</li>
<li><p>On peut bien sûr tout <del><strong><em><u>combiner</u></em></strong></del> : <code>~~***__texte__***~~</code></p>
</li>
<li><p><sup>Mettre du texte</sup> en exposant : <code>&lt;sup&gt;texte&lt;/sup&gt;</code></p>
</li>
<li><p><sub>Mettre du texte</sub> en indice : <code>&lt;sub&gt;texte&lt;/sub&gt;</code></p>
</li>
</ul>
<h2>Liens</h2>
<ul>
<li>Les liens simples sont détectés automatiquement : <code>http://www.site.com</code></li>
</ul>
<p><a href="http://www.site.com">http://www.site.com</a></p>
<ul>
<li>Il est possible de nommer son lien : <code>[nom du lien](http://www.site.com)</code></li>
</ul>
<p><a href="http://www.site.com">nom du lien</a></p>
<ul>
<li>Les liens peuvent être internes au site de l'AE, on peut dès lors éviter d'entrer
l'adresse complète d'une page : <code>[nom du lien](page://nomDeLaPage)</code></li>
</ul>
<p><a href="/page/nomDeLaPage/">nom du lien</a></p>
<ul>
<li>On peut également utiliser une image pour les liens :
<code>[nom du lien]![images/imageDuSiteAE.png](/chemin/vers/image.png titre optionnel)(options)</code></li>
</ul>
<p>[nom du lien]<img src="/chemin/vers/image.png titre optionnel" alt="images/imageDuSiteAE.png">(options)</p>
<h2>Titres</h2>
<ul>
<li>Plusieurs niveaux de titres sont possibles</li>
</ul>
<pre><code># Titre de niveau 1
## Titre de niveau 2
### Titre de niveau 3
etc...
</code></pre>
<h1>Titre de niveau 1</h1>
<h2>Titre de niveau 2</h2>
<h3>Titre de niveau 3</h3>
<p>Si le titre de votre section commence par un tilde (~) alors le texte sous la section est
affiché par défaut caché et il est consultable grace à un bouton +/-</p>
<h2>~Test</h2>
<h2>Paragraphes et sauts de ligne</h2>
<p>Un nouveau paragraphe se fait avec deux retours à la ligne.</p>
<p>Un saut de ligne se force avec au moins deux espaces en fin de ligne.</p>
<h2>Listes</h2>
<p>Il est possible de créer des listes :</p>
<ul>
<li>ordonnées :</li>
</ul>
<pre><code>1. élément
2. élément
3. élément
</code></pre>
<ol>
<li>élément</li>
<li>élément</li>
<li>élément</li>
</ol>
<p>Vous pouvez marquer plus simplement comme suit, les numéros se faisant tout seuls:</p>
<pre><code>1. élément
1. élément
1. élément
</code></pre>
<ol>
<li>élément</li>
<li>élément</li>
<li>élément</li>
</ol>
<ul>
<li>non ordonnées :</li>
</ul>
<pre><code> * élément
* élément
* élément
</code></pre>
<ul>
<li>élément</li>
<li>élément</li>
<li>élément</li>
</ul>
<h2>Tableaux</h2>
<p>Un tableau est obtenu en respectant la syntaxe suivante :</p>
<pre><code>| Titre | Titre2 | Titre3 |
|-------|--------|--------|
| test | test | test |
| test | test | test |
</code></pre>
<table>
<thead><tr>
<th>Titre</th>
<th>Titre2</th>
<th>Titre3</th>
</tr>
</thead>
<tbody>
<tr>
<td>test</td>
<td>test</td>
<td>test</td>
</tr>
<tr>
<td>test</td>
<td>test</td>
<td>test</td>
</tr>
</tbody>
</table>
<p>L'alignement dans les cellules est géré comme suit, avec les ':' sur la ligne en dessous du titre:</p>
<pre><code>| Titre | Titre2 | Titre3 |
|:-------|:------:|-------:|
| gauche | centre | droite |
</code></pre>
<table>
<thead><tr>
<th style="text-align:left">Titre</th>
<th style="text-align:center">Titre2</th>
<th style="text-align:right">Titre3</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">gauche</td>
<td style="text-align:center">centre</td>
<td style="text-align:right">droite</td>
</tr>
</tbody>
</table>
<h2>Images et contenus</h2>
<p>Une image est insérée ainsi : <code>![texte alternatif](/chemin/vers/image.png "titre optionnel")</code>
<img src="/static/core/img/logo.png" alt="texte alternatif" title="titre optionnel"></p>
<p>On peut lui spécifier ses dimensions de plusieurs manières:</p>
<pre><code>![image à 50%](/static/core/img/logo.png?50% "Image à 50%")
![image de 350 pixels de large](/static/core/img/logo.png?350 "Image de 350 pixels")
![image de 350x100 pixels](/static/core/img/logo.png?350x100 "Image de 350x100 pixels")
</code></pre>
<p><img src="/static/core/img/logo.png" alt="image à 50%" title="Image à 50%" style="width: 50%; "><br>
Image à 50% de la largeur de la page.</p>
<p><img src="/static/core/img/logo.png" alt="image de 350 pixels de large" title="Image de 350 pixels" style="width: 350px; "><br>
Image de 350 pixels de large.</p>
<p><img src="/static/core/img/logo.png" alt="image de 350x100 pixels" title="Image de 350x100 pixels" style="width: 350px; height: 100px; "><br>
Image de 350x100 pixels.</p>
<p>( devrait pouvoir détecter si vidéo ou non )</p>
<h2>Blocs de citations</h2>
<p>Un bloc de citation se crée ainsi :</p>
<pre><code>&gt; Ceci est
&gt; un bloc de
&gt; citation
</code></pre>
<blockquote><p>Ceci est
un bloc de
citation</p>
</blockquote>
<p>Il est possible d'intégrer de la syntaxe Markdown-AE dans un tel bloc.</p>
<h2>Note de bas de page</h2>
<p>On les créer comme ça<sup class="footnote-ref" id="fnref-key"><a href="#fn-key">1</a></sup>:</p>
<h2>échapper des caractères</h2>
<ul>
<li>Il est possible d'ignorer un caractère spécial en l'échappant à l'aide d'un \</li>
<li>L'échappement de blocs de codes complet se fera à l'aide de balises &lt;nosyntax&gt;&lt;/nosyntax&gt;</li>
</ul>
<h2>Autres ( hérité de l'ancien wiki )</h2>
<ul>
<li>Une ligne peut être crée avec une ligne contenant 4 tirets ( - ).</li>
<li>Une barre de progression est crée ainsi :<blockquote><p>[[[70]]]</p>
</blockquote>
</li>
<li>Notes en pied de page :<blockquote><p>((note))</p>
</blockquote>
</li>
</ul>
<div class="footnotes">
<hr>
<ol><li id="fn-key"><p>ceci est le contenu de ma clef</p>
<pre><code>Je fais une note[^clef].
[^clef]: je note ensuite ou je veux le contenu de ma clef qui apparaîtra quand même en bas
</code></pre>
<p>Vous pouvez utiliser des numéros pour nommer vos clef si vous avez la flemme.</p>
<pre><code>Note plus complexe[^1]
[^1]:
je peux même faire des blocks
sur plusieurs lignes, comme d'habitude!
</code></pre><p><a href="#fnref-key" class="footnote">&#8617;</a></p></li>
</ol>
</div>

223
doc/SYNTAX.md Normal file
View File

@ -0,0 +1,223 @@
Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
# Markdown-AE Documentation
Le Markdown le plus standard se trouve documenté ici:
https://daringfireball.net/projects/markdown/syntax .
Si cette page n'est pas exhaustive vis à vis de la syntaxe du site AE,
elle a au moins le mérite de bien documenter le Markdown original.
Le réel parseur du site AE est une version tunée de [mistune](https://github.com/lepture/mistune).
Les plus aventureux pourront aller lire ses [tests](https://github.com/lepture/mistune/blob/master/tests/fixtures)
afin d'en connaître la syntaxe le plus finement possible.
En pratique, cette page devrait déjà résumer une bonne partie.
## Basique
* Mettre le texte en **gras** : `**texte**`
* Mettre le texte en *italique* : `*texte*`
* __Souligner__ le texte : `__texte__`
* ~~Barrer du texte~~ : `~~texte~~`
* On peut bien sûr tout ~~***__combiner__***~~ : `~~***__texte__***~~`
* <sup>Mettre du texte</sup> en exposant : `<sup>texte</sup>`
* <sub>Mettre du texte</sub> en indice : `<sub>texte</sub>`
## Liens
* Les liens simples sont détectés automatiquement : `http://www.site.com`
http://www.site.com
* Il est possible de nommer son lien : `[nom du lien](http://www.site.com)`
[nom du lien](http://www.site.com)
* Les liens peuvent être internes au site de l'AE, on peut dès lors éviter d'entrer
l'adresse complète d'une page : `[nom du lien](page://nomDeLaPage)`
[nom du lien](page://nomDeLaPage)
* On peut également utiliser une image pour les liens :
`[nom du lien]![images/imageDuSiteAE.png](/chemin/vers/image.png titre optionnel)(options)`
[nom du lien]![images/imageDuSiteAE.png](/chemin/vers/image.png titre optionnel)(options)
## Titres
* Plusieurs niveaux de titres sont possibles
```
# Titre de niveau 1
## Titre de niveau 2
### Titre de niveau 3
etc...
```
# Titre de niveau 1
## Titre de niveau 2
### Titre de niveau 3
Si le titre de votre section commence par un tilde (~) alors le texte sous la section est
affiché par défaut caché et il est consultable grace à un bouton +/-
## ~Test
## Paragraphes et sauts de ligne
Un nouveau paragraphe se fait avec deux retours à la ligne.
Un saut de ligne se force avec au moins deux espaces en fin de ligne.
## Listes
Il est possible de créer des listes :
* ordonnées :
```
1. élément
2. élément
3. élément
```
1. élément
1. élément
1. élément
Vous pouvez marquer plus simplement comme suit, les numéros se faisant tout seuls:
```
1. élément
1. élément
1. élément
```
1. élément
1. élément
1. élément
* non ordonnées :
```
* élément
* élément
* élément
```
* élément
* élément
* élément
## Tableaux
Un tableau est obtenu en respectant la syntaxe suivante :
```
| Titre | Titre2 | Titre3 |
|-------|--------|--------|
| test | test | test |
| test | test | test |
```
| Titre | Titre2 | Titre3 |
|-------|--------|--------|
| test | test | test |
| test | test | test |
L'alignement dans les cellules est géré comme suit, avec les ':' sur la ligne en dessous du titre:
```
| Titre | Titre2 | Titre3 |
|:-------|:------:|-------:|
| gauche | centre | droite |
```
| Titre | Titre2 | Titre3 |
|:-------|:------:|-------:|
| gauche | centre | droite |
## Images et contenus
Une image est insérée ainsi : `![texte alternatif](/chemin/vers/image.png "titre optionnel")`
![texte alternatif](/static/core/img/logo.png "titre optionnel")
On peut lui spécifier ses dimensions de plusieurs manières:
```
![image à 50%](/static/core/img/logo.png?50% "Image à 50%")
![image de 350 pixels de large](/static/core/img/logo.png?350 "Image de 350 pixels")
![image de 350x100 pixels](/static/core/img/logo.png?350x100 "Image de 350x100 pixels")
```
![image à 50%](/static/core/img/logo.png?50% "Image à 50%")
Image à 50% de la largeur de la page.
![image de 350 pixels de large](/static/core/img/logo.png?350 "Image de 350 pixels")
Image de 350 pixels de large.
![image de 350x100 pixels](/static/core/img/logo.png?350x100 "Image de 350x100 pixels")
Image de 350x100 pixels.
( devrait pouvoir détecter si vidéo ou non )
## Blocs de citations
Un bloc de citation se crée ainsi :
```
> Ceci est
> un bloc de
> citation
```
> Ceci est
> un bloc de
> citation
Il est possible d'intégrer de la syntaxe Markdown-AE dans un tel bloc.
## Note de bas de page
On les créer comme ça[^key]:
[^key]: ceci est le contenu de ma clef
```
Je fais une note[^clef].
[^clef]: je note ensuite ou je veux le contenu de ma clef qui apparaîtra quand même en bas
```
Vous pouvez utiliser des numéros pour nommer vos clef si vous avez la flemme.
```
Note plus complexe[^1]
[^1]:
je peux même faire des blocks
sur plusieurs lignes, comme d'habitude!
```
## échapper des caractères
* Il est possible d'ignorer un caractère spécial en l'échappant à l'aide d'un \
* L'échappement de blocs de codes complet se fera à l'aide de balises <nosyntax></nosyntax>
## Autres ( hérité de l'ancien wiki )
* Une ligne peut être crée avec une ligne contenant 4 tirets ( - ).
* Une barre de progression est crée ainsi :
> [[[70]]]
* Notes en pied de page :
> ((note))

1
doc/TO_Skia_LoJ/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_minted-Rapport/

Binary file not shown.

Binary file not shown.

13
doc/TO_Skia_LoJ/Makefile Normal file
View File

@ -0,0 +1,13 @@
CC=pdflatex
all: rapport clean
rapport: Rapport.tex
@echo "Compiling "$<
$(CC) -shell-escape $<
$(CC) -shell-escape $<
clean:
@echo "Cleaning folder"
rm *.aux; rm *.log; rm *.out; rm *.toc; rm *.snm; rm *.nav; rm *.lof

BIN
doc/TO_Skia_LoJ/Rapport.pdf Normal file

Binary file not shown.

490
doc/TO_Skia_LoJ/Rapport.tex Normal file
View File

@ -0,0 +1,490 @@
%%
%
% Skia
% skia@libskia.so
%
%%
\documentclass[a4paper]{report}
%packages
\usepackage[utf8]{inputenc}
\usepackage[francais]{babel}
\usepackage{graphicx}\graphicspath{{pix/}}
\usepackage{float}
\usepackage{scrextend}
\usepackage[T1]{fontenc}
\usepackage{color}
\usepackage{fancyhdr}
%Options: Sonny, Lenny, Glenn, Conny, Rejne, Bjarne, Bjornstrup
\usepackage[Bjornstrup]{fncychap}
\usepackage{minted}
\usepackage[colorlinks=true,linkcolor=black]{hyperref}
\usepackage{pdfpages}
%\usepackage{titlesec, blindtext, color}
%pdf metadata
\hypersetup{
unicode=true,
colorlinks=true,
citecolor=black,
filecolor=black,
linkcolor=black,
urlcolor=black,
pdfauthor={Skia <skia@libskia.so>},
pdftitle={},
pdfcreator={pdftex},
pdfsubject={},
pdfkeywords={},
}
\definecolor{keywords}{RGB}{200,0,90}
\definecolor{comments}{RGB}{50,50,253}
\definecolor{red}{RGB}{160,0,0}
\definecolor{brown}{RGB}{160,100,100}
\definecolor{green}{RGB}{0,200,0}
\definecolor{darkgreen}{RGB}{0,130,0}
\definecolor{gray}{RGB}{100,100,100}
%inner meta
\title{Sith: Développement de nouvelles applications}
\author{Florent \textsc{Jacquet}\\
Guillaume \textsc{Renaud}}
\date{Dernière version: \today}
\begin{document}
% \maketitle
\includepdf[pages={1}]{Couvertures.pdf}
\tableofcontents
\chapter*{Remerciements}
\section*{Guillaume \textsc{Renaud}}
\par Je remercie tout d'abord Monsieur Frédéric \textsc{Lassabe} qui nous a permis d'effectuer cette TO52 lors de notre cursus à
l'UTBM, nous permettant ainsi de mêler nôtre travail scolaire à nôtre envie de participer à l'amélioration de la vie
associative de l'UTBM.
\par Je tiens aussi à remercier Florent \textsc{Jacquet} qui m'a aidé tout au long de ce travail et à qui j'ai pu poser mes
différentes questions pour apprendre et comprendre plus rapidement que si j'avais été seul.
\section*{Florent \textsc{Jacquet}}
\par Je remercie également Frédéric \textsc{Lassabe} , non seulement pour la TO, mais également pour la précédente TW. Sans ces
deux UV hors emploi du temps, jamais un projet comme ce site de l'AE n'aurait pu voir le jour. Cela a demandé beaucoup
d'investissement, et il est plus qu'appréciable de pouvoir obtenir quelques crédits en retour.
\par Je tiens également à remercier l'ensemble de l'équipe info de l'AE qui s'est motivée ce semestre à organiser des
réunions hebdomadaires afin de reprendre le projet du mieux possible. C'est maintenant à eux que va être confié le
projet, et il est agréable de constater qu'ils n'ont pas attendu le dernier moment pour se pencher sur la question.
\chapter*{Introduction}
\addcontentsline{toc}{chapter}{Introduction}
\par Après le développement de la base du nouveau site de l'AE, le projet \emph{Sith}, au Printemps 2016, la mise en
production a pu avoir lieu avec succès fin Août 2016.
\par Mais le site était encore très incomplet, et il était nécessaire d'y ajouter un grand nombre de fonctionnalités
moins critiques, celles-ci n'ayant pas de rapport avec l'argent, mais tout de même très utiles pour le fonctionnement
de l'AE.
\par Parmis elles, se trouvait notamment une application de gestion des stocks, qui a été confiée à Guillaume, puisqu'elle
concernait en premier lieu le \emph{Bureau des Festivités} et qu'il en était le président. Il était donc parmis les
mieux placé pour évaluer le besoin et développer l'outil, d'autant qu'il fallait le concevoir depuis le début, ces
fonctions n'étant pas du tout présentes dans l'ancien site.
\par Du reste, Florent a eu la responsabilité de développer les autres applications, ou bien de gérer leur développement
lors qu'il était fait par quelqu'un d'autre.
\chapter{Eboutic}
\label{sec:eboutic}
\par Développeur principal: Florent
\section{But}
\label{sub:but}
\par Fournir une boutique en ligne, avec paiement sécurisé, compatible avec l'API de paiement du Crédit Agricole.
\begin{itemize}
\item Gérer les cotisations
\item Gérer les rechargements de compte AE
\item Gérer différents groupes de vente
\end{itemize}
\section{Principaux problèmes}
\label{sec:principaux_problemes}
\subsection{Interaction avec l'API}
\label{sub:interaction_avec_l_api}
\par C'est la principale contrainte de cette application. On doit interagir avec les serveurs du Crédit Agricole, et
pour cela, ces derniers n'aident pas beaucoup.
\par Ils fournissent un PDF peu clair\footnote{disponible dans le dossier \url{doc/Etransaction/} des sources du site}
expliquant l'implémentation d'un site marchand, en plus des nombreux autres PDF de documentation disponibles à l'adresse
\url{https://e-transactions.avem-groupe.com/pages/global.php?page=telechargement}.
\par Une implémentation de référence uniquement en PHP, et contenant que peut de fonctionnalités par rapport à ce
que dit le PDF peut aussi être obtenue, mais n'est guère utile excepté pour la vérification cryptographique de la
signature de la réponse. Mais encore, il faut arriver à traduire les fonctions propres à PHP, et ce n'est pas toujours
une mince affaire, mais fort heureusement, les algorithmes sont encore assez standards et l'on trouve vite de l'aide
quant à ces fonctions.
\par De plus, certaines informations concernants les numéros d'identification de marchand son incohérents
d'une documentation à l'autre, et le plus simple à ce niveau est encore de contacter le support.
\subsection{Accès concurrentiels}
\label{sub:acces_concurrentiels}
\par En production, le projet Sith tourne à l'aide d'\textbf{uWSGI}, qui s'occupe lui de gérer les différents processus du
logiciel. Cela se traduit par des accès concurrentiels à la base de donnée lors de l'appel de deux pages simultanément
qui ont besoin d'accèder aux mêmes ressources.
\par Le problème n'en est la plupart du temps pas un, mais il devient très critique lorsque la page appelée permet par
exemple de recharger un compte AE. Il ne faut alors surtout faire l'opération en double.
\par Pour protéger ces accès en double, on peut alors utiliser des transactions, et \textbf{Django} fournit une
abstraction très pratique: \verb-with transaction.atomic():-.
\par L'Eboutic, avec sa réponse de la banque, est très sujette à ces accès concurrents, et cela a posé quelques
problèmes dans les débuts. La plupart ont été résolu, mais il arrive encore dans les comptoirs d'avoir une vente en
double, sans pour autant avoir le débit du compte qui soit doublé. Cela ne pose pas foncièrement de problèmes, puisque
le solde du compte est tout de même valide, et c'est un problème très compliqué à debugger, puisqu'il survient très
rarement, mais il faudrait tout de même arriver à le résoudre un jour.
\chapter{Le SAS}
\label{sec:le_sas}
\par Développeur principal: Florent
\section{But}
\label{sub:but}
\par Fournir un système de galerie de photo:
\begin{itemize}
\item Upload en ligne via un formulaire pour tous les cotisants.
\item Modération pour l'équipe du SAS.
\item Système d'identification des membres pour retrouver rapidement ses photos.
\item Affichage des photos dans les différents album et sur la page "photo" du profil d'un utilisateur.
\end{itemize}
\section{Principaux problèmes}
\label{sec:principaux_problemes}
\subsection{Gestion des fichiers}
\label{sub:gestion_des_fichiers}
\par L'envoie en grande quantité de photos nécéssite une gestion des fichiers solide, en même temps qu'un formulaire
d'envoie efficace, capable d'envoyer plusieurs dizaines de photos en une seule action de l'utilisateur.
\par L'envoie est donc fait à l'aide de requêtes AJAX pour envoyer les photos une par une et éviter alors le timeout.
\par Concernant les fichiers une fois envoyé, ils sont en réalité traités par la classe \verb#SithFile# qui gère tous
les fichiers du site. Cela ne fait qu'une seule classe à développer, de même qu'un seul système de fichier avec une
seule arborescence, ce qui est beaucoup plus robuste.
\par La difficulté a aussi été de permettre le déplacement des fichiers, par couper-coller, tout en faisant de même dans
le système de fichier réel, afin d'avoir une arborescence cohérente même en cas de perte de la base de données.
\subsection{Optimisation des pages}
\label{sub:optimisation_des_pages}
\par La génération d'un grand nombre de requêtes SQL est un des principaux problèmes de ralentissement d'un site. Le
SAS, avec ses très nombreuses photos, qui requierent une validation des droits, a posé un gros problème à ce niveau.
\par Certaines pages ont pu mettre jusqu'à plus de 10 secondes à générer, ce qui est inconcevable pour une galerie de
photos, mais ce temps à pu être réduit à moins de 3 secondes.
\par L'astuce à été d'utiliser des actions utilisateurs, comme l'upload de nouvelles photos, pour faire plus de
traitement que nécessaire, afin de mettre en "cache" une grande partie des actions, comme par exemple la génération des
miniatures des albums.
\par Une autre technique pour gagner du temps est de mettre en cache certaines requêtes en forcant les \emph{QuerySet}
à s'évaluer dans une \emph{list} \textbf{Python} que l'on stocke afin d'obtenir sa longueur, au lieu de lancer d'abord
un \emph{count}, puis une itération des résultats, qui en utilisant directement l'ORM, conduit à réaliser deux
requêtes SQL.
\par Enfin, le passage à \textbf{HTTP/2} permettrait d'améliorer encore les performances côté utilisateur puisqu'il n'y
aurait plus qu'un seul \emph{socket} d'ouvert pour transférer toutes les photos d'une page par exemple, sans avoir
pour autant à toucher au code.
\chapter{Les élections}
\label{sec:les_elections}
\par Développeur principal: Antoine
\section{But}
\label{sub:but}
\par Fournir un système d'élections:
\begin{itemize}
\item Gestion des différentes élections comprenants à chaque fois une liste de postes pour lesquels les gens
candidatent, ainsi qu'une gestion des listes, pour pouvoir classifier et répartir les candidatures.
\item Gestion d'une page de vote, permettant aux gens autorisés de pouvoir voter.
\item Affichage des résultats une fois le vote terminé.
\item Pas compatible avec la législation française: trop contraignant et pas utile, puisque validation officiel en
AG.
\end{itemize}
\section{Principaux problèmes}
\label{sec:principaux_problemes}
\subsection{Automatisation d'un widget particulier pour les formulaires}
\label{sub:automatisation_d_un_widget_particulier_pour_les_formulaires}
\par La demande est venue du \textbf{BdF} qui a voulu autoriser pour certains poste un nombre de vote supérieur à 1.
Cela signifie que l'on passe d'un choix simple, type \verb#radio# à un choix multiple, type \verb#checkbox#, tout cela
étant paramètrable dans l'élection.
\par Ce genre de choix n'étant pas disponible dans \textbf{Django} de base, il a fallut développer le \emph{widget} à
utiliser dans le formulaire qui permette cette configuration tout en validant bien les données reçues par rapport au
modèle, et éviter ainsi de pouvoir "tricher" en envoyant des requêtes erronées.
\subsection{Revue du code d'un autre développeur}
\label{sub:revue_du_code_d_un_autre_developpeur}
\par \emph{Antoine} étant le principal développeur de cette application, un gros travail de revue de code a dû être
effectuer afin de garantir une certaine cohérence avec le reste du projet.
\par C'est un travail très long et fastidieux, car il faut bien revérifier chaque ligne, sur chaque fichier, tout en
faisant des commentaire lorsque quelque chose ne va pas. \textbf{Gitlab} a, à ce niveau, grandement facilité la tâche, à
l'aide de ses outils de \emph{merge request} assez avancés.
\par En plus du code en lui-même, il a fallut porter une attention particulière aux migrations. Ces fichiers générés
automatiquement par \textbf{Django} sont responsables du maintient d'une base de donnée cohérente malgré les évolutions
des modèles. Même si le code parait donc valide, il est impératif de surveiller que la chaîne de dépendance des dites
migrations ne soit pas cassée, au risque de problèmes potentiels au moment de la mise en production, ce qui entraînent à
coup sûr un \emph{downtime}.
\chapter{Les stocks}
\label{sub:les_stocks}
\par Développeur principal: Guillaume
\vskip 2em
\par Cette application s'occupe de la gestion des stocks des comptoirs de type « BAR ». Elle permet de suivre les
quantités restantes afin de pouvoir déterminer de manière automatisée quels sont les produits qu'il faut acheter et en
quelle quantité.
\section{Liste des modèles}
\label{sec:liste_des_modeles}
\subsection{Stock}
\par Un Stock possède un nom et est lié à la classe Counter. Ainsi, chaque Comptoir peut avoir son propre Stock.
\subsection{StockItem}
\par Un StockItem possède un nom, une quantité unitaire, une quantité effective, une quantité minimale et est lié à la
classe Stock ainsi qu'à la classe ProductType. De cette manière, chaque élément appartient à un Stock et il est
catégorisé de la même manière que les Products (qui sont les objets utilisés pour la vente dans les comptoirs).
\subsection{ShoppingList}
\par Une ShoppingList possède un nom, une date, un booléen (fait ou à faire), un commentaire et est liée à un Stock.
Chaque ShoppingList est donc liée à un Stock ce qui permet d'avoir des listes de courses spécifique à chaque comptoir.
\subsection{ShoppingListItem}
\par Un ShoppingListItem possède un nom, une quantité demandée, une quantité achetée et est lié à la classe StockItem, à
la classe ShoppingList et à la classe ProductType. Cela permet de pouvoir faire plusieurs listes de courses différentes
en même temps et d'en garder un historique.
\section{Fonctionnement}
\label{sec:fonctionnement}
\par Au départ, si le comptoir de type « BAR » n'a pas de stock, la seule chose qu'il est possible de faire est d'en
créer un. Ensuite, il va falloir créer les objets StockItem en indiquant pour chacun les quantités qu'il y a dans le
stock.
\par De plus, la personne (généralement le Responsable du lieu de vie) qui aura la responsabilité d'informatiser les
stocks devra aussi définir la quantité unitaire, effective et minimale.
\par Par exemple, les Cheeseburger vendus aux différents comptoirs sont achetés par boite de 6, la quantité unitaire
sera donc 6, la quantité effective correspondra au nombre de boites restantes dans le stock (c'est à dire dans la
réserve du lieu de vie, une boite sortie du stock est considérée comme consommée) et enfin, la quantité minimale servira
de valeur seuil.
\par Une fois l'état de la réserve retranscrit dans le site, il reste encore gérer les stocks de manière quotidienne.
Pour ce faire, l'application se décompose en 3 parties :
\begin{itemize}
\item Création automatique des listes de courses
\item Approvisionnement du stock
\item Prise d'éléments dans le stock
\end{itemize}
\par Lorsque l'on accède à la partie qui s'occupe de la gestion des listes de courses, il y a un bouton permettant de
créer une liste de courses en fonction de l'état des stocks à cet instant, puis un premier tableau contenant les listes
de courses qu'il faut faire et enfin un second tableau servant d'historique des listes de courses déjà effectuées.
\par Pour chaque liste de course ainsi créée, qu'elle soit « faite » ou « à faire », il est possible de cliquer sur son
nom pour voir le détail de ce qu'elle comprend.
\subsection{Création automatique des listes de courses}
\par En cliquant sur le bouton permettant de créer une nouvelle liste de courses, il faut remplir un formulaire. Les
informations à donner dans ce formulaire sont le nom de la liste de course (par exemple, une liste spéciale pour
Leclerc), ensuite, apparaissent tous les StockItem ayant une quantité effective inférieure au seuil fixé par leur
quantité minimale. Il faut donc donner pour chacun de ces éléments une quantité à acheter. Enfin, un dernier champ de
commentaire peut être compléter, il sert à demander l'achat d'éléments qui n'apparaissent pas dans le Stock, par
exemple, des couteaux, fourchettes ou encore tasses...
\par Lors de la validation de ce formulaire, la liste de courses est créée et est ajoutée au tableau contenant les
listes de courses à faire.
\subsection{Approvisionnement du stock}
\par Au retour des courses, il faut ranger les produits achetés dans la réserve. À ce moment-là, il faut aussi mettre à
jour le stock. Une opération « Mettre à jour le stock » est disponible pour chaque liste de courses du tableau « À
faire ».
\par En effectuant cette action, il va falloir indiquer les quantités effectivement achetées. En effet, les quantités
demandées ne sont pas forcément celles achetées, c'est donc les quantités effectives qu'il faut ajouter au stock. Une
fois ce formulaire validé, la liste de couses passera de l'état « à faire » à l'état « faite ».
\subsection{Prise d'éléments dans le stock}
\par La réserve étant accessible aux barmen afin qu'ils puissent réapprovisionner les réfrigérateurs à tout moment,
l'interface permettant de prendre des éléments dans le stock a été ajoutée dans les onglets de l'interface des ventes
(là où le barman inscrit le code du compte du client qui souhaite commander quelque chose). Ainsi, en revenant de la
réserve, le barman doit indiquer le nombre de chaque produit qu'il a rapporté.
\par Dans un souci de simplicité pour le gérant du lieu de vie, ce formulaire de prise des éléments dans le stock est
aussi accessible depuis son interface de gestion.
\section{Améliorations à apporter}
\label{sec:amelioration_a_apporter}
\begin{itemize}
\item Il n'est pas encore possible de modifier les quantités demandées pour un ou plusieurs des produits d'une liste
de course. Il faudrait rendre cela possible car actuellement, il faut supprimer la liste de courses et la
refaire en changeant les quantités souhaitées.
\item Il faudrait améliorer la manière dont on ajoute les éléments non définis en tant que StockItem dans la liste
de course. Un objet ShoppingListItem avec une référence « Null » vers la classe StockItem pourrait être créé à
la place de compléter le champ de commentaires.
\item Dans les améliorations sur le long terme, il faudrait que la décrémentation des quantités de chaque élément
dans le stock soit automatique. En repensant une partie de l'architecture de l'application, on pourrait faire en
sorte que chaque vente faite au comptoir face diminuer les quantités restantes (cela remplacerait le formulaire
de « Prise d'éléments dans le stock », mais cela ne serait pas applicable à tous les produits mis en vente. Par
exemple, pour les cacahuètes que nous vendons au bol et non par paquet)
\item Avec le système de notifications qui a été mis en place sur le site, on pourrait faire en sorte que le ou les
responsables des lieux de vie reçoivent une notification lorsque la liste de courses contient plus de 5 éléments
\end{itemize}
\chapter{La laverie}
\label{sec:la_laverie}
\par Développeur principal: Florent
\section{But}
\label{sub:but}
\par Cette application doit fournir un système de gestion de laverie. Cela comprend:
\begin{itemize}
\item Un système de planning et de réservation de créneaux
\item Un système de vente de jetons de laverie, lié aux comptoirs et au compte AE, permettant aux permanenciers de
cliquer les jetons en même temps qu'ils vérifient l'état de la cotisation.
\item Un système d'inventaire, pour gérer les différentes machines dans les différents lieux, et gérer également le
retour des jetons après utilisation.
\end{itemize}
\section{Principaux problèmes}
\label{sec:principaux_problemes}
\subsection{Génération de plannings}
\label{sub:generation_de_plannings}
\par Il y a là beaucoup de cas à prendre en compte. Lorsque que quelqu'un veut réserver directement un "Lavage +
Séchage", un simple "Lavage", ou un simple "Séchage", il faut toujours vérifier la disponibilité des créneaux en
fonction du nombre de machine de chaque type présent dans la laverie en question \footnote{Belfort ou Sevenans, en
l'occurrence}, et cela représente vite un grand nombre de combinaisons à vérifier.
\par De plus, la réservation doit rester ergonomique, et s'afficher dans un format le plus lisible possible pour un
humain. Là dessus, un tableau est le plus approprié, avec chaque jour représenté par une colonne, et chaque créneau par
une ligne.\\
Mais cela ne représente malheureusement pas la temporalité, et la génération du tableau devient alors plutôt compliquée,
et d'autant plus si l'on veut qu'il soit sémantiquement correct en HTML.
\subsection{Gestion des timezones}
\label{sub:gestion_des_timezones}
\par La gestion et le stockage des crénaux implique l'utilisation de champs de type \verb#DateTime#. \textbf{Django} les
gère très bien, particulièrement au niveau des \emph{timezones}, où ce dernier n'hésite pas à lancer un warning lorsque
l'objet \emph{date} passé ne contient pas d'information de fuseau horaire.
\par Mais avec notre décalage d'une heure par rapport au temps UTC, tous les horaires se retrouvent décalés, et gérer
cela convenablement sans sortir d'avertissement a été plutôt compliqué. La solution a été de forcer un peu partout la
\emph{timezone} à UTC, afin de ne pas créer de décalage, mais en conservant tout de même l'information de fuseau
horaire, et sans tout casser lors du passage à l'heure d'hiver.
\chapter{La communication}
\label{sec:la_communication}
\par Développeur principal: Florent
\section{But}
\label{sub:but}
\par Cette application a plusieurs but:
\begin{itemize}
\item Donner la possibilité au responsable communication d'éditer les différents textes, messages, et pages
statiques du site.
\item Fournir un système de news.
\item Fournir un système de newsletter: le Weekmail.
\end{itemize}
\section{Principaux problèmes}
\label{sec:principaux_problemes}
\subsection{Envoie de mails}
\label{sub:envoie_de_mails}
\par Un outil de \emph{newsletter} nécessite l'envoie de mail. C'est là quelque chose de relativement compliqué à
tester, d'autant plus lorsqu'il s'agit de mailing-list contenant l'intégralité des étudiants de l'UTBM.
\par \textbf{Django} fournit toutefois un outil très pratique: il contient plusieurs \emph{backend} d'emails, dont entre
autre un \emph{SMTP}, et un \emph{console}. Le \emph{SMTP} est bien évidemment utilisé en production pour envoyer
effectivement les mails, mais il est compliqué à utiliser en développement, car il suppose que le développeur a à sa
disposition un serveur de ce type. On utilise alors le backend \emph{console}, qui affiche simplement dans le thread
d'execution de \textbf{Django} une version texte de l'email envoyé, avec d'une part les entêtes, d'autre part le corps
de message.
\par Mais autant pour tester l'envoie d'un mail unique à une adresse unique, cela fonctionne parfaitement bien, ce n'est
toutefois pas suffisant pour tester un envoie massif à plusieurs mailings, avec en plus encore d'autres adresses en
\emph{Bcc} pour les gens ne faisant pas partie des mailings "classiques", mais souhaitant quand même recevoir le
\textbf{Weekmail}.
\subsection{Amélioration de l'outil de recherche}
\label{sub:amelioration_de_l_outil_de_recherche}
\par Pour la gestion de l'AE, il est nécessaire de pouvoir rechercher et trouver efficacement n'importe quel membre, en
tapant au choix son nom, prénom, ou surnom, voire une combinaison de ces trois champs.
\par Mais une fonction de recherche aussi complexe est très difficile a mettre en place efficacement sans un traitement
préalable, d'où la nécessité d'indexer les entrées à chercher. Un indexeur étant très complexe, mais également très
courant, il n'a pas été difficile de trouver une application déjà existante fournissant ces fonctionnalités.
\par Le choix s'est porté sur \textbf{Haystack}, en l'utilisant avec l'indexeur \textbf{Whoosh}, plutôt efficace pour
des bases raisonnables, et surtout écrit en pure \textbf{Python}, donc ne nécessitant pas d'installation compliquée en
parallèle du site.
\par Le résultat est plutôt satisfaisant, mais il faudrait encore améliorer les résultats en utilisant les fonctions de
\emph{boost} pour certains champs. De plus, une certaine lenteur se fait encore sentir avec certaines recherches trop
communes ou générales.
\chapter{Conclusions personnelles}
\section{Florent}
\label{sec:skia}
\par Développer de nouvelles application m'a permis d'apréhender d'autres problématiques, comme la gestion des fichiers
dans le SAS, ou bien des contraintes de concurrence et d'atomicité sur l'Eboutic.
\par Mais la plus grosse partie de mon travail ce semestre a surtout été de superviser une équipe de développement
naissante, de relire les "Merge request", et de m'assurer de la cohérence du code des contributeurs avec le reste du
projet.
\par J'ai églament pu approfondir mon utilisation de Gitlab à travers ses outils de gestion de projet, de revue de code,
et de gestion des permissions sur les différentes branches.
\section{Guillaume}
\label{sec:lo_j}
\par Je suis très heureux d'avoir pu participer à ce projet de TO52 sur le développement de modules sur le site de
l'Association des Étudiants. J'ai pu apprendre à travailler avec un nouvel environnement informatique tout en
contribuant au développement d'outils pour l'association dont je suis Président, le Bureau des Festivités.
\subsection{Django}
\par Ayant déjà travaillé avec le framework Spring et Java durant mon stage ST40, j'ai pu m'appuyer sur des notions
générales afin d'apprendre et de comprendre le fonctionnement du Python et de Django que je ne connaissais pas du tout.
\par Mon apprentissage a été assez long au départ, car il y avait beaucoup d'informations à intégrer. Django est un
framework très pratique qui permet d'effectuer de nombreuses tâches assez rébarbatives de manière automatique certes,
mais encore faut-il comprendre ce qu'il se passe en arrière-plan. C'est cet apprentissage qui m'a pris le plus de temps.
\par Mon deuxième point de difficulté a été les formulaires. Là encore, Django est très pratique dès lors qu'il s'agit
de faire un formulaire avec tous les champs d'un même Model. Cependant, il m'a fallu de l'aide et du temps pour
comprendre comment faire pour ajouter d'autres champs en plus de ceux du Model au formulaire et pour comprendre comment
récupérer les valeurs associées à chacun d'eux.
\subsection{Git}
\par J'ai eu aussi à apprendre le fonctionnement de Git que j'avais déjà pu manipuler quelque peu mais il me manquait
quand même beaucoup d'éléments.
\par Aujourd'hui, je pense pouvoir dire que j'ai progressé dans ce domaine mais il me reste encore bien des choses à
apprendre pour être capable de l'utiliser de manière efficace.
\includepdf[pages={2}]{Couvertures.pdf}
\end{document}

View File

@ -0,0 +1,18 @@
LATEX := pdflatex
TARGET := slide.pdf
.PHONY: all clean distclean
all: $(TARGET) clean
%.pdf: %.tex
echo "Building pdf"
$(LATEX) --shell-escape $<
rm -f $@
$(LATEX) --shell-escape $<
clean:
rm -f *.log *.nav *.snm *.aux *.out *.toc *.pyg
distclean: clean
rm -f $(TARGET)

View File

@ -0,0 +1,133 @@
%%
%% This is file `beamercolorthememetropolis.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% beamercolorthememetropolis.dtx (with options: `package')
%% ---------------------------------------------------------------------------
%% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of
%% contributors can be found at
%%
%% https://github.com/matze/mtheme/graphs/contributors
%%
%% and the original template was based on the HSRM theme by Benjamin Weiss.
%%
%% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0
%% International License (https://creativecommons.org/licenses/by-sa/4.0/).
%% ---------------------------------------------------------------------------
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{beamercolorthememetropolis}[2016/02/21 Metropolis color theme]
\RequirePackage{pgfopts}
\pgfkeys{
/metropolis/color/block/.cd,
.is choice,
transparent/.code=\metropolis@block@transparent,
fill/.code=\metropolis@block@fill,
}
\pgfkeys{
/metropolis/color/background/.cd,
.is choice,
dark/.code=\metropolis@colors@dark,
light/.code=\metropolis@colors@light,
}
\newcommand{\metropolis@color@setdefaults}{
\pgfkeys{/metropolis/color/.cd,
background=light,
block=transparent,
}
}
\definecolor{mDarkBrown}{HTML}{604c38}
\definecolor{mDarkTeal}{HTML}{23373b}
\definecolor{mLightBrown}{HTML}{EB811B}
\definecolor{mLightGreen}{HTML}{14B03D}
\newcommand{\metropolis@colors@dark}{
\setbeamercolor{normal text}{%
fg=black!2,
bg=mDarkTeal
}
}
\newcommand{\metropolis@colors@light}{
\setbeamercolor{normal text}{%
fg=mDarkTeal,
bg=black!2
}
}
\setbeamercolor{alerted text}{%
fg=mLightBrown
}
\setbeamercolor{example text}{%
fg=mLightGreen
}
\setbeamercolor{titlelike}{use=normal text, parent=normal text}
\setbeamercolor{author}{use=normal text, parent=normal text}
\setbeamercolor{date}{use=normal text, parent=normal text}
\setbeamercolor{institute}{use=normal text, parent=normal text}
\setbeamercolor{structure}{use=normal text, fg=normal text.fg}
\setbeamercolor{palette primary}{%
use=normal text,
fg=normal text.bg,
bg=normal text.fg
}
\setbeamercolor{frametitle}{%
use=palette primary,
parent=palette primary
}
\setbeamercolor{progress bar}{%
use=alerted text,
fg=alerted text.fg,
bg=alerted text.fg!50!black!30
}
\setbeamercolor{title separator}{
use=progress bar,
parent=progress bar
}
\setbeamercolor{progress bar in head/foot}{%
use=progress bar,
parent=progress bar
}
\setbeamercolor{progress bar in section page}{
use=progress bar,
parent=progress bar
}
\newcommand{\metropolis@block@transparent}{
\setbeamercolor{block title}{%
use=normal text,
fg=normal text.fg,
bg=
}
\setbeamercolor{block body}{
bg=
}
}
\newcommand{\metropolis@block@fill}{
\setbeamercolor{block title}{%
use=normal text,
fg=normal text.fg,
bg=normal text.bg!80!fg
}
\setbeamercolor{block body}{
use={block title, normal text},
bg=block title.bg!50!normal text.bg
}
}
\setbeamercolor{block title alerted}{%
use={block title, alerted text},
bg=block title.bg,
fg=alerted text.fg
}
\setbeamercolor{block title example}{%
use={block title, example text},
bg=block title.bg,
fg=example text.fg
}
\setbeamercolor{block body alerted}{use=block body, parent=block body}
\setbeamercolor{block body example}{use=block body, parent=block body}
\setbeamercolor{footnote}{fg=normal text.fg!90}
\setbeamercolor{footnote mark}{fg=.}
\metropolis@color@setdefaults
\ProcessPgfPackageOptions{/metropolis/color}
\mode<all>
\endinput
%%
%% End of file `beamercolorthememetropolis.sty'.

View File

@ -0,0 +1,283 @@
%%
%% This is file `beamerfontthememetropolis.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% beamerfontthememetropolis.dtx (with options: `package')
%% ---------------------------------------------------------------------------
%% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of
%% contributors can be found at
%%
%% https://github.com/matze/mtheme/graphs/contributors
%%
%% and the original template was based on the HSRM theme by Benjamin Weiss.
%%
%% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0
%% International License (https://creativecommons.org/licenses/by-sa/4.0/).
%% ---------------------------------------------------------------------------
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{beamerfontthememetropolis}[2016/02/21 Metropolis font theme]
\RequirePackage{etoolbox}
\RequirePackage{ifxetex}
\RequirePackage{ifluatex}
\RequirePackage{pgfopts}
\ifboolexpr{bool {xetex} or bool {luatex}}{
\RequirePackage[no-math]{fontspec}
\newcounter{fontsnotfound}
\newcommand{\checkfont}[1]{%
\suppressfontnotfounderror=1%
\font\x = "#1" at 10pt
\selectfont
\ifx\x\nullfont%
\stepcounter{fontsnotfound}%
\fi%
\suppressfontnotfounderror=0%
}
\newcommand{\iffontsavailable}[3]{%
\setcounter{fontsnotfound}{0}%
\expandafter\forcsvlist\expandafter%
\checkfont\expandafter{#1}%
\ifnum\value{fontsnotfound}=0%
#2%
\else%
#3%
\fi%
}
\iffontsavailable{Fira Sans Light,%
Fira Sans Light Italic,%
Fira Sans,%
Fira Sans Italic}%
{%
\setsansfont[ItalicFont={Fira Sans Light Italic},%
BoldFont={Fira Sans},%
BoldItalicFont={Fira Sans Italic}]%
{Fira Sans Light}%
}{%
\iffontsavailable{Fira Sans Light OT,%
Fira Sans Light Italic OT,%
Fira Sans OT,%
Fira Sans Italic OT}%
{%
\setsansfont[ItalicFont={Fira Sans Light Italic OT},%
BoldFont={Fira Sans OT},%
BoldItalicFont={Fira Sans Italic OT}]%
{Fira Sans Light OT}%
}{%
\PackageWarning{beamerthememetropolis}{%
Could not find Fira Sans fonts%
}
}
}
\iffontsavailable{Fira Mono, Fira Mono Bold}{%
\setmonofont[BoldFont={Fira Mono Medium}]{Fira Mono}%
}{%
\iffontsavailable{Fira Mono OT, Fira Mono Bold OT}{%
\setmonofont[BoldFont={Fira Mono Medium OT}]{Fira Mono OT}%
}{%
\PackageWarning{beamerthememetropolis}{%
Could not find Fira Mono fonts%
}
}
}
\AtBeginEnvironment{tabular}{%
\addfontfeature{Numbers={Monospaced}}%
}
}{%
\PackageWarning{beamerthememetropolis}{%
You need to compile with XeLaTeX or LuaLaTeX to use the Fira fonts%
}
}
\setbeamerfont{title}{size=\Large,%
series=\bfseries}
\setbeamerfont{author}{size=\small}
\setbeamerfont{date}{size=\small}
\setbeamerfont{section title}{size=\Large,%
series=\bfseries}
\setbeamerfont{block title}{size=\normalsize,%
series=\bfseries}
\setbeamerfont{block title alerted}{size=\normalsize,%
series=\bfseries}
\setbeamerfont*{subtitle}{size=\large}
\setbeamerfont{frametitle}{size=\large,%
series=\bfseries}
\setbeamerfont{caption}{size=\small}
\setbeamerfont{caption name}{series=\bfseries}
\setbeamerfont{description item}{series=\bfseries}
\setbeamerfont{page number in head/foot}{size=\scriptsize}
\setbeamerfont{bibliography entry author}{size=\normalsize,%
series=\normalfont}
\setbeamerfont{bibliography entry title}{size=\normalsize,%
series=\bfseries}
\setbeamerfont{bibliography entry location}{size=\normalsize,%
series=\normalfont}
\setbeamerfont{bibliography entry note}{size=\small,%
series=\normalfont}
\setbeamerfont{standout}{size=\Large,%
series=\bfseries}
\pgfkeys{
/metropolis/font/titleformat title/.cd,
.is choice,
regular/.code={%
\let\metropolis@titleformat\@empty%
\setbeamerfont{title}{shape=\normalfont}%
},
smallcaps/.code={%
\let\metropolis@titleformat\@empty%
\setbeamerfont{title}{shape=\scshape}%
},
allsmallcaps/.code={%
\let\metropolis@titleformat\lowercase%
\setbeamerfont{title}{shape=\scshape}%
\PackageWarning{beamerthememetropolis}{%
Be aware that titleformat title=allsmallcaps can lead to problems%
}
},
allcaps/.code={%
\let\metropolis@titleformat\uppercase%
\setbeamerfont{title}{shape=\normalfont}
\PackageWarning{beamerthememetropolis}{%
Be aware that titleformat title=allcaps can lead to problems%
}
},
}
\pgfkeys{
/metropolis/font/titleformat subtitle/.cd,
.is choice,
regular/.code={%
\let\metropolis@subtitleformat\@empty%
\setbeamerfont{subtitle}{shape=\normalfont}%
},
smallcaps/.code={%
\let\metropolis@subtitleformat\@empty%
\setbeamerfont{subtitle}{shape=\scshape}%
},
allsmallcaps/.code={%
\let\metropolis@subtitleformat\lowercase%
\setbeamerfont{subtitle}{shape=\scshape}%
\PackageWarning{beamerthememetropolis}{%
Be aware that titleformat subtitle=allsmallcaps can lead to problems%
}
},
allcaps/.code={%
\let\metropolis@subtitleformat\uppercase%
\setbeamerfont{subtitle}{shape=\normalfont}%
\PackageWarning{beamerthememetropolis}{%
Be aware that titleformat subtitle=allcaps can lead to problems%
}
},
}
\pgfkeys{
/metropolis/font/titleformat section/.cd,
.is choice,
regular/.code={%
\let\metropolis@sectiontitleformat\@empty%
\setbeamerfont{section title}{shape=\normalfont}%
},
smallcaps/.code={%
\let\metropolis@sectiontitleformat\@empty%
\setbeamerfont{section title}{shape=\scshape}%
},
allsmallcaps/.code={%
\let\metropolis@sectiontitleformat\MakeLowercase%
\setbeamerfont{section title}{shape=\scshape}%
\PackageWarning{beamerthememetropolis}{%
Be aware that titleformat section=allsmallcaps can lead to problems%
}
},
allcaps/.code={%
\let\metropolis@sectiontitleformat\MakeUppercase%
\setbeamerfont{section title}{shape=\normalfont}%
\PackageWarning{beamerthememetropolis}{%
Be aware that titleformat section=allcaps can lead to problems%
}
},
}
\pgfkeys{
/metropolis/font/titleformat frame/.cd,
.is choice,
regular/.code={%
\let\metropolis@frametitleformat\@empty%
\setbeamerfont{frametitle}{shape=\normalfont}%
},
smallcaps/.code={%
\let\metropolis@frametitleformat\@empty%
\setbeamerfont{frametitle}{shape=\scshape}%
},
allsmallcaps/.code={%
\let\metropolis@frametitleformat\MakeLowercase%
\setbeamerfont{frametitle}{shape=\scshape}%
\PackageWarning{beamerthememetropolis}{%
Be aware that titleformat frame=allsmallcaps can lead to problems%
}
},
allcaps/.code={%
\let\metropolis@frametitleformat\MakeUppercase%
\setbeamerfont{frametitle}{shape=\normalfont}
\PackageWarning{beamerthememetropolis}{%
Be aware that titleformat frame=allcaps can lead to problems%
}
},
}
\pgfkeys{
/metropolis/font/.cd,
titleformattitle/.code=\pgfkeysalso{titleformat title=#1},
titleformatsubtitle/.code=\pgfkeysalso{titleformat subtitle=#1},
titleformatsection/.code=\pgfkeysalso{titleformat section=#1},
titleformatframe/.code=\pgfkeysalso{titleformat frame=#1},
}
\newcommand{\metropolis@font@setdefaults}{
\pgfkeys{/metropolis/font/.cd,
titleformat title=regular,
titleformat subtitle=regular,
titleformat section=regular,
titleformat frame=regular,
}
}
\def\metropolis@titleformat#1{#1}
\def\metropolis@subtitleformat#1{#1}
\def\metropolis@sectiontitleformat#1{#1}
\def\metropolis@frametitleformat#1{#1}
\patchcmd{\beamer@title}%
{\def\inserttitle{#2}}%
{\def\inserttitle{\metropolis@titleformat{#2}}}%
{}%
{\PackageError{beamerfontthememetropolis}{Patching title failed}}
\patchcmd{\beamer@subtitle}%
{\def\insertsubtitle{#2}}%
{\def\insertsubtitle{\metropolis@subtitleformat{#2}}}%
{}%
{\PackageError{beamerfontthememetropolis}{Patching subtitle failed}}
\patchcmd{\sectionentry}
{\def\insertsectionhead{#2}}
{\def\insertsectionhead{\metropolis@sectiontitleformat{#2}}}
{}
{\PackageError{beamerfontthememetropolis}{Patching section title failed}}
\patchcmd{\beamer@section}
{\def\insertsectionhead{\hyperlink{Navigation\the\c@page}{#1}}}
{\def\insertsectionhead{\hyperlink{Navigation\the\c@page}{%
\metropolis@sectiontitleformat{#1}}}}
{}
{\PackageError{beamerfontthememetropolis}{Patching section title failed}}
\patchcmd{\beamer@@frametitle}
{\beamer@ifempty{#2}{}{%
\gdef\insertframetitle{{#2\ifnum\beamer@autobreakcount>0\relax{}\space%
\usebeamertemplate*{frametitle continuation}\fi}}%
\gdef\beamer@frametitle{#2}%
\gdef\beamer@shortframetitle{#1}%
}}
{\beamer@ifempty{#2}{}{%
\gdef\insertframetitle{{\metropolis@frametitleformat{#2}\ifnum%
\beamer@autobreakcount>0\relax{}\space%
\usebeamertemplate*{frametitle continuation}\fi}}%
\gdef\beamer@frametitle{#2}%
\gdef\beamer@shortframetitle{#1}%
}}
{}
{\PackageError{beamerfontthememetropolis}{Patching frame title failed}}
\metropolis@font@setdefaults
\ProcessPgfPackageOptions{/metropolis/font}
\endinput
%%
%% End of file `beamerfontthememetropolis.sty'.

View File

@ -0,0 +1,281 @@
%%
%% This is file `beamerinnerthememetropolis.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% beamerinnerthememetropolis.dtx (with options: `package')
%% ---------------------------------------------------------------------------
%% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of
%% contributors can be found at
%%
%% https://github.com/matze/mtheme/graphs/contributors
%%
%% and the original template was based on the HSRM theme by Benjamin Weiss.
%%
%% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0
%% International License (https://creativecommons.org/licenses/by-sa/4.0/).
%% ---------------------------------------------------------------------------
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{beamerinnerthememetropolis}[2016/02/21 Metropolis inner theme]
\RequirePackage{etoolbox}
\RequirePackage{keyval}
\RequirePackage{calc}
\RequirePackage{pgfopts}
\RequirePackage{tikz}
\pgfkeys{
/metropolis/inner/sectionpage/.cd,
.is choice,
none/.code=\metropolis@disablesectionpage,
simple/.code={\metropolis@enablesectionpage
\setbeamertemplate{section page}[simple]},
progressbar/.code={\metropolis@enablesectionpage
\setbeamertemplate{section page}[progressbar]},
}
\pgfkeys{
/metropolis/inner/subsectionpage/.cd,
.is choice,
none/.code=\metropolis@disablesubsectionpage,
simple/.code={\metropolis@enablesubsectionpage
\setbeamertemplate{section page}[simple]},
progressbar/.code={\metropolis@enablesubsectionpage
\setbeamertemplate{section page}[progressbar]},
}
\newcommand{\metropolis@inner@setdefaults}{
\pgfkeys{/metropolis/inner/.cd,
sectionpage=progressbar,
subsectionpage=none
}
}
\setbeamertemplate{title page}{
\begin{minipage}[b][\paperheight]{\textwidth}
\ifx\inserttitlegraphic\@empty\else\usebeamertemplate*{title graphic}\fi
\vfill%
\ifx\inserttitle\@empty\else\usebeamertemplate*{title}\fi
\ifx\insertsubtitle\@empty\else\usebeamertemplate*{subtitle}\fi
\usebeamertemplate*{title separator}
\ifx\beamer@shortauthor\@empty\else\usebeamertemplate*{author}\fi
\ifx\insertdate\@empty\else\usebeamertemplate*{date}\fi
\ifx\insertinstitute\@empty\else\usebeamertemplate*{institute}\fi
\vfill
\vspace*{1mm}
\end{minipage}
}
\def\maketitle{%
\ifbeamer@inframe
\titlepage
\else
\frame[plain,noframenumbering]{\titlepage}
\fi
}
\def\titlepage{%
\usebeamertemplate{title page}
}
\setbeamertemplate{title graphic}{
\vbox to 0pt {
\vspace*{2em}
\inserttitlegraphic%
}%
\nointerlineskip%
}
\setbeamertemplate{title}{
\raggedright%
\linespread{1.0}%
\inserttitle%
\par%
\vspace*{0.5em}
}
\setbeamertemplate{subtitle}{
\insertsubtitle%
\par%
\vspace*{0.5em}
}
\setbeamertemplate{title separator}{
\begin{tikzpicture}
\draw[fg, fill=fg] (0,0) rectangle (\textwidth, 0.4pt);
\end{tikzpicture}%
\par%
}
\setbeamertemplate{author}{
\vspace*{2em}
\insertauthor%
\par%
\vspace*{0.25em}
}
\setbeamertemplate{date}{
\insertdate%
\par%
}
\setbeamertemplate{institute}{
\vspace*{3mm}
\insertinstitute%
\par%
}
\defbeamertemplate{section page}{simple}{
\begin{center}
\usebeamercolor[fg]{section title}
\usebeamerfont{section title}
\insertsectionhead\par
\ifx\insertsubsection\@empty\else
\usebeamercolor[fg]{subsection title}
\usebeamerfont{subsection title}
\insertsubsection
\fi
\end{center}
}
\defbeamertemplate{section page}{progressbar}{
\centering
\begin{minipage}{22em}
\raggedright
\usebeamercolor[fg]{section title}
\usebeamerfont{section title}
\insertsectionhead\\[-1ex]
\usebeamertemplate*{progress bar in section page}
\par
\ifx\insertsubsection\@empty\else%
\usebeamercolor[fg]{subsection title}%
\usebeamerfont{subsection title}%
\insertsubsection
\fi
\end{minipage}
\par
\vspace{\baselineskip}
}
\newcommand{\metropolis@disablesectionpage}{
\AtBeginSection{
% intentionally empty
}
}
\newcommand{\metropolis@enablesectionpage}{
\AtBeginSection{
\ifbeamer@inframe
\sectionpage
\else
\frame[plain,c,noframenumbering]{\sectionpage}
\fi
}
}
\setbeamertemplate{subsection page}{%
\usebeamertemplate*{section page}
}
\newcommand{\metropolis@disablesubsectionpage}{
\AtBeginSubsection{
% intentionally empty
}
}
\newcommand{\metropolis@enablesubsectionpage}{
\AtBeginSubsection{
\ifbeamer@inframe
\subsectionpage
\else
\frame[plain,c,noframenumbering]{\subsectionpage}
\fi
}
}
\newlength{\metropolis@progressonsectionpage}
\setbeamertemplate{progress bar in section page}{
\setlength{\metropolis@progressonsectionpage}{%
\textwidth * \ratio{\insertframenumber pt}{\inserttotalframenumber pt}%
}%
\begin{tikzpicture}
\draw[bg, fill=bg] (0,0) rectangle (\textwidth, 0.4pt);
\draw[fg, fill=fg] (0,0) rectangle (\metropolis@progressonsectionpage, 0.4pt);
\end{tikzpicture}%
}
\def\inserttotalframenumber{100}
\newlength{\metropolis@blocksep}
\newlength{\metropolis@blockadjust}
\setlength{\metropolis@blocksep}{0.75ex}
\setlength{\metropolis@blockadjust}{0.25ex}
\providecommand{\metropolis@strut}{%
\vphantom{ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz()}%
}
\newcommand{\metropolis@block}[1]{
\par\vskip\medskipamount%
\setlength{\parskip}{0pt}
\ifbeamercolorempty[bg]{block title#1}{%
\begin{beamercolorbox}[rightskip=0pt plus 4em]{block title#1}}{%
\ifbeamercolorempty[bg]{block title}{%
\begin{beamercolorbox}[rightskip=0pt plus 4em]{block title#1}%
}%
{%
\begin{beamercolorbox}[
sep=\dimexpr\metropolis@blocksep-\metropolis@blockadjust\relax,
leftskip=\metropolis@blockadjust,
rightskip=\dimexpr\metropolis@blockadjust plus 4em\relax
]{block title#1}%
}}%
\usebeamerfont*{block title#1}%
\metropolis@strut%
\insertblocktitle%
\metropolis@strut%
\end{beamercolorbox}%
\nointerlineskip%
\ifbeamercolorempty[bg]{block body#1}{%
\begin{beamercolorbox}[vmode]{block body#1}}{
\ifbeamercolorempty[bg]{block body}{%
\begin{beamercolorbox}[vmode]{block body#1}%
}{%
\begin{beamercolorbox}[sep=\metropolis@blocksep, vmode]{block body#1}%
\vspace{-\metropolis@parskip}
}}%
\usebeamerfont{block body#1}%
\setlength{\parskip}{\metropolis@parskip}%
}
\setbeamertemplate{block begin}{\metropolis@block{}}
\setbeamertemplate{block alerted begin}{\metropolis@block{ alerted}}
\setbeamertemplate{block example begin}{\metropolis@block{ example}}
\setbeamertemplate{block end}{\end{beamercolorbox}\vspace*{0.2ex}}
\setbeamertemplate{block alerted end}{\end{beamercolorbox}\vspace*{0.2ex}}
\setbeamertemplate{block example end}{\end{beamercolorbox}\vspace*{0.2ex}}
\setbeamertemplate{itemize items}{\textbullet}
\setbeamertemplate{caption label separator}{: }
\setbeamertemplate{caption}[numbered]
\setbeamertemplate{footnote}{%
\parindent 0em\noindent%
\raggedright
\usebeamercolor{footnote}\hbox to 0.8em{\hfil\insertfootnotemark}\insertfootnotetext\par%
}
\newlength{\metropolis@parskip}
\setlength{\metropolis@parskip}{0.5em}
\setlength{\parskip}{\metropolis@parskip}
\linespread{1.15}
\define@key{beamerframe}{c}[true]{% centered
\beamer@frametopskip=0pt plus 1fill\relax%
\beamer@framebottomskip=0pt plus 1fill\relax%
\beamer@frametopskipautobreak=0pt plus .4\paperheight\relax%
\beamer@framebottomskipautobreak=0pt plus .6\paperheight\relax%
\def\beamer@initfirstlineunskip{}%
}
\providebool{metropolis@standout}
\define@key{beamerframe}{standout}[true]{%
\booltrue{metropolis@standout}
\begingroup
\setkeys{beamerframe}{c}
\setkeys{beamerframe}{noframenumbering}
\ifbeamercolorempty[bg]{palette primary}{
\setbeamercolor{background canvas}{
use=palette primary,
bg=-palette primary.fg
}
}{
\setbeamercolor{background canvas}{
use=palette primary,
bg=palette primary.bg
}
}
\centering
\usebeamercolor[fg]{palette primary}
\usebeamerfont{standout}
}
\apptocmd{\beamer@reseteecodes}{%
\ifbool{metropolis@standout}{
\endgroup
\boolfalse{metropolis@standout}
}{}
}{}{}
\metropolis@inner@setdefaults
\ProcessPgfPackageOptions{/metropolis/inner}
\endinput
%%
%% End of file `beamerinnerthememetropolis.sty'.

View File

@ -0,0 +1,126 @@
%%
%% This is file `beamerouterthememetropolis.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% beamerouterthememetropolis.dtx (with options: `package')
%% ---------------------------------------------------------------------------
%% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of
%% contributors can be found at
%%
%% https://github.com/matze/mtheme/graphs/contributors
%%
%% and the original template was based on the HSRM theme by Benjamin Weiss.
%%
%% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0
%% International License (https://creativecommons.org/licenses/by-sa/4.0/).
%% ---------------------------------------------------------------------------
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{beamerouterthememetropolis}[2016/02/21 Metropolis outer theme]
\RequirePackage{etoolbox}
\RequirePackage{calc}
\RequirePackage{pgfopts}
\pgfkeys{
/metropolis/outer/numbering/.cd,
.is choice,
none/.code=\setbeamertemplate{frame numbering}[none],
counter/.code=\setbeamertemplate{frame numbering}[counter],
fraction/.code=\setbeamertemplate{frame numbering}[fraction],
}
\pgfkeys{
/metropolis/outer/progressbar/.cd,
.is choice,
none/.code={%
\setbeamertemplate{headline}[plain]
\setbeamertemplate{frametitle}[plain]
\setbeamertemplate{footline}[plain]
},
head/.code={\pgfkeys{/metropolis/outer/progressbar=none}
\addtobeamertemplate{headline}{}{%
\usebeamertemplate*{progress bar in head/foot}
}
},
frametitle/.code={\pgfkeys{/metropolis/outer/progressbar=none}
\addtobeamertemplate{frametitle}{}{%
\usebeamertemplate*{progress bar in head/foot}
}
},
foot/.code={\pgfkeys{/metropolis/outer/progressbar=none}
\addtobeamertemplate{footline}{}{%
\usebeamertemplate*{progress bar in head/foot}%
}
},
}
\newcommand{\metropolis@outer@setdefaults}{
\pgfkeys{/metropolis/outer/.cd,
numbering=counter,
progressbar=none,
}
}
\setbeamertemplate{navigation symbols}{}
\defbeamertemplate{frame footer}{none}{}
\defbeamertemplate{frame footer}{custom}[1]{ #1 }
\defbeamertemplate{frame numbering}{none}{}
\defbeamertemplate{frame numbering}{counter}{\insertframenumber}
\defbeamertemplate{frame numbering}{fraction}{
\insertframenumber/\inserttotalframenumber
}
\defbeamertemplate{headline}{plain}{}
\defbeamertemplate{footline}{plain}{%
\begin{beamercolorbox}[wd=\textwidth, sep=3ex]{footline}%
\usebeamerfont{page number in head/foot}%
\usebeamertemplate*{frame footer}
\hfill%
\usebeamertemplate*{frame numbering}
\end{beamercolorbox}%
}
\newlength{\metropolis@frametitle@padding}
\setlength{\metropolis@frametitle@padding}{2.2ex}
\newcommand{\metropolis@frametitlestrut@start}{
\rule{0pt}{\metropolis@frametitle@padding +%
\totalheightof{%
\ifcsdef{metropolis@frametitleformat}{\metropolis@frametitleformat X}{X}%
}%
}%
}
\newcommand{\metropolis@frametitlestrut@end}{
\rule[-\metropolis@frametitle@padding]{0pt}{\metropolis@frametitle@padding}
}
\defbeamertemplate{frametitle}{plain}{%
\nointerlineskip%
\begin{beamercolorbox}[%
wd=\paperwidth,%
sep=0pt,%
leftskip=\metropolis@frametitle@padding,%
rightskip=\metropolis@frametitle@padding,%
]{frametitle}%
\metropolis@frametitlestrut@start\insertframetitle\metropolis@frametitlestrut@end%
\end{beamercolorbox}%
}
\newlength{\metropolis@progressinheadfoot}
\setbeamertemplate{progress bar in head/foot}{
\nointerlineskip
\setlength{\metropolis@progressinheadfoot}{%
\paperwidth * \ratio{\insertframenumber pt}{\inserttotalframenumber pt}%
}%
\begin{beamercolorbox}[wd=\paperwidth]{progress bar in head/foot}
\begin{tikzpicture}
\draw[bg, fill=bg] (0,0) rectangle (\paperwidth, 0.4pt);
\draw[fg, fill=fg] (0,0) rectangle (\metropolis@progressinheadfoot, 0.4pt);
\end{tikzpicture}%
\end{beamercolorbox}
}
\AtBeginDocument{%
\apptocmd{\appendix}{%
\pgfkeys{%
/metropolis/outer/.cd,
numbering=none,
progressbar=none}
}{}{}
}
\metropolis@outer@setdefaults
\ProcessPgfPackageOptions{/metropolis/outer}
\endinput
%%
%% End of file `beamerouterthememetropolis.sty'.

View File

@ -0,0 +1,105 @@
%%
%% This is file `beamerthememetropolis.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% beamerthememetropolis.dtx (with options: `package')
%% ---------------------------------------------------------------------------
%% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of
%% contributors can be found at
%%
%% https://github.com/matze/mtheme/graphs/contributors
%%
%% and the original template was based on the HSRM theme by Benjamin Weiss.
%%
%% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0
%% International License (https://creativecommons.org/licenses/by-sa/4.0/).
%% ---------------------------------------------------------------------------
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{beamerthememetropolis}
[2016/02/21 v1.1 Metropolis Beamer theme]
\RequirePackage{etoolbox}
\RequirePackage{pgfopts}
\pgfkeys{/metropolis/.cd,
.search also={
/metropolis/inner,
/metropolis/outer,
/metropolis/color,
/metropolis/font,
}
}
\pgfkeys{
/metropolis/titleformat plain/.cd,
.is choice,
regular/.code={%
\let\metropolis@plaintitleformat\@empty%
\setbeamerfont{standout}{shape=\normalfont}%
},
smallcaps/.code={%
\let\metropolis@plaintitleformat\@empty%
\setbeamerfont{standout}{shape=\scshape}%
},
allsmallcaps/.code={%
\let\metropolis@plaintitleformat\MakeLowercase%
\setbeamerfont{standout}{shape=\scshape}%
\PackageWarning{beamerthememetropolis}{%
Be aware that titleformat plain=allsmallcaps can lead to problems%
}
},
allcaps/.code={%
\let\metropolis@plaintitleformat\MakeUppercase%
\setbeamerfont{standout}{shape=\normalfont}%
\PackageWarning{beamerthememetropolis}{%
Be aware that titleformat plain=allcaps can lead to problems%
}
},
}
\pgfkeys{
/metropolis/titleformat/.code=\pgfkeysalso{
font/titleformat title=#1,
font/titleformat subtitle=#1,
font/titleformat section=#1,
font/titleformat frame=#1,
titleformat plain=#1,
}
}
\pgfkeys{/metropolis/.cd,
usetitleprogressbar/.code=\pgfkeysalso{outer/progressbar=frametitle},
noslidenumbers/.code=\pgfkeysalso{outer/numbering=none},
usetotalslideindicator/.code=\pgfkeysalso{outer/numbering=fraction},
nosectionslide/.code=\pgfkeysalso{inner/sectionpage=none},
darkcolors/.code=\pgfkeysalso{color/background=dark},
blockbg/.code=\pgfkeysalso{color/block=fill, inner/block=fill},
}
\newcommand{\metropolis@setdefaults}{
\pgfkeys{/metropolis/.cd,
titleformat plain=regular,
}
}
\useinnertheme{metropolis}
\useoutertheme{metropolis}
\usecolortheme{metropolis}
\usefonttheme{metropolis}
\AtEndPreamble{%
\@ifpackageloaded{pgfplots}{%
\RequirePackage{pgfplotsthemetol}
}{}
}
\newcommand{\metroset}[1]{\pgfkeys{/metropolis/.cd,#1}}
\def\metropolis@plaintitleformat#1{#1}
\newcommand{\plain}[2][]{%
\PackageWarning{beamerthememetropolis}{%
The syntax `\plain' may be deprecated in a future version of Metropolis.
Please use a frame with [standout] instead.
}
\begin{frame}[standout]{#1}
\metropolis@plaintitleformat{#2}
\end{frame}
}
\newcommand{\mreducelistspacing}{\vspace{-\topsep}}
\metropolis@setdefaults
\ProcessPgfOptions{/metropolis}
\endinput
%%
%% End of file `beamerthememetropolis.sty'.

View File

@ -0,0 +1,123 @@
%%
%% This is file `pgfplotsthemetol.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% pgfplotsthemetol.dtx (with options: `package')
%% ---------------------------------------------------------------------------
%% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of
%% contributors can be found at
%%
%% https://github.com/matze/mtheme/graphs/contributors
%%
%% and the original template was based on the HSRM theme by Benjamin Weiss.
%%
%% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0
%% International License (https://creativecommons.org/licenses/by-sa/4.0/).
%% ---------------------------------------------------------------------------
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{pgfplotsthemetol}
[2015/06/16 PGFplots colors based on Paul Tol's SRON technical note]
\definecolor{TolDarkPurple}{HTML}{332288}
\definecolor{TolDarkBlue}{HTML}{6699CC}
\definecolor{TolLightBlue}{HTML}{88CCEE}
\definecolor{TolLightGreen}{HTML}{44AA99}
\definecolor{TolDarkGreen}{HTML}{117733}
\definecolor{TolDarkBrown}{HTML}{999933}
\definecolor{TolLightBrown}{HTML}{DDCC77}
\definecolor{TolDarkRed}{HTML}{661100}
\definecolor{TolLightRed}{HTML}{CC6677}
\definecolor{TolLightPink}{HTML}{AA4466}
\definecolor{TolDarkPink}{HTML}{882255}
\definecolor{TolLightPurple}{HTML}{AA4499}
\pgfplotscreateplotcyclelist{mbarplot cycle}{%
{draw=TolDarkBlue, fill=TolDarkBlue!70},
{draw=TolLightBrown, fill=TolLightBrown!70},
{draw=TolLightGreen, fill=TolLightGreen!70},
{draw=TolDarkPink, fill=TolDarkPink!70},
{draw=TolDarkPurple, fill=TolDarkPurple!70},
{draw=TolDarkRed, fill=TolDarkRed!70},
{draw=TolDarkBrown, fill=TolDarkBrown!70},
{draw=TolLightRed, fill=TolLightRed!70},
{draw=TolLightPink, fill=TolLightPink!70},
{draw=TolLightPurple, fill=TolLightPurple!70},
{draw=TolLightBlue, fill=TolLightBlue!70},
{draw=TolDarkGreen, fill=TolDarkGreen!70},
}
\pgfplotscreateplotcyclelist{mlineplot cycle}{%
{TolDarkBlue, mark=*, mark size=1.5pt},
{TolLightBrown, mark=square*, mark size=1.3pt},
{TolLightGreen, mark=triangle*, mark size=1.5pt},
{TolDarkBrown, mark=diamond*, mark size=1.5pt},
}
\pgfplotsset{
compat=1.9,
mlineplot/.style={
mbaseplot,
xmajorgrids=true,
ymajorgrids=true,
major grid style={dotted},
axis x line=bottom,
axis y line=left,
legend style={
cells={anchor=west},
draw=none
},
cycle list name=mlineplot cycle,
},
mbarplot base/.style={
mbaseplot,
bar width=6pt,
axis y line*=none,
},
mbarplot/.style={
mbarplot base,
ybar,
xmajorgrids=false,
ymajorgrids=true,
area legend,
legend image code/.code={%
\draw[#1] (0cm,-0.1cm) rectangle (0.15cm,0.1cm);
},
cycle list name=mbarplot cycle,
},
horizontal mbarplot/.style={
mbarplot base,
xmajorgrids=true,
ymajorgrids=false,
xbar stacked,
area legend,
legend image code/.code={%
\draw[#1] (0cm,-0.1cm) rectangle (0.15cm,0.1cm);
},
cycle list name=mbarplot cycle,
},
mbaseplot/.style={
legend style={
draw=none,
fill=none,
cells={anchor=west},
},
x tick label style={
font=\footnotesize
},
y tick label style={
font=\footnotesize
},
legend style={
font=\footnotesize
},
major grid style={
dotted,
},
axis x line*=bottom,
},
disable thousands separator/.style={
/pgf/number format/.cd,
1000 sep={}
},
}
\endinput
%%
%% End of file `pgfplotsthemetol.sty'.

Binary file not shown.

View File

@ -0,0 +1,158 @@
\documentclass[10pt]{beamer}
\beamertemplatenavigationsymbolsempty
\usepackage[utf8]{inputenc}
\usepackage{default}
\usepackage{graphicx}
\graphicspath{{pictures/}}
\usepackage[french]{babel}
\usepackage[T1]{fontenc}
\usetheme{metropolis}
%\usecolortheme{dove}
\begin{document}
\begin{frame}
\frametitle{Université de Technologie de Belfort-Montbéliard\\
Département informatique}
\vskip 4em
\begin{center}
{\LARGE Développement de nouveaux modules sur le projet Sith}\\
\end{center}
\vskip 4em
Florent \textsc{Jacquet}\\
Guillaume \textsc{Renaud}\\
{\scriptsize TO52 - A16}
\end{frame}
\begin{frame}
\frametitle{Sommaire}
\tableofcontents
\end{frame}
\section{Les nouvelles applications}
\subsection{Eboutic}
\begin{frame}[fragile]\frametitle{Eboutic}
\begin{itemize}
\item Fournir une boutique
\item Paiement en ligne en lien avec l'API du Credit Agricole
\item Gestion des cotisations et rechargements
\item Attention aux accès concurrentiels: pas visibles pendant le développement, car mono-thread, mais problèmes
à la mise en production
\end{itemize}
\end{frame}
\subsection{Le SAS}
\begin{frame}[fragile]\frametitle{Le SAS - Stock à Souvenirs}
\begin{itemize}
\item Galerie de photos
\item Upload simple pour tout le monde, même pour plusieurs dizaines de photos
\item Modération et gestion des droits basée sur la gestion des fichiers, ce qui a permis d'améliorer ces
derniers
\item Problèmes d'optimisation de certaines pages qui mettaient plus de 9 secondes à générer (plus que 2s
maintenant)
\end{itemize}
\end{frame}
\subsection{Les élections}
\begin{frame}[fragile]\frametitle{Les élections}
\begin{itemize}
\item Grosse partie "gestion": c'est Sli qui a principalement développé l'application
\item Revue des \textsc{merges request} et choix de design
\item Problèmatique de législation vite ignorées puisque validation officielle en AG
\end{itemize}
\end{frame}
\subsection{La laverie}
\begin{frame}[fragile]\frametitle{La laverie}
\begin{itemize}
\item Gestion d'un planning de reservation en prenant bien en compte les différents états (hors-service, ...) de
chaque machine
\item Génération de formulaires dynamiques en fonction des réservations (factory design pattern)
\end{itemize}
\end{frame}
\subsection{La communication}
\begin{frame}[fragile]\frametitle{La communication}
\begin{itemize}
\item Dynamise le site avec tous les textes paramètrables
\item Fourni un système de news
\item Fourni une newsletter
\end{itemize}
\begin{itemize}
\item Envoie de mails en masse
\item Beaucoup de templates
\end{itemize}
\end{frame}
\section{La gestion des stocks}
\subsection{Fonctionnement}
\begin{frame}[fragile]{Fonctionnement}
\begin{itemize}
\item Création automatique des listes de courses
\item Approvisionnement des stocks
\item Prise d'éléments dans le stock
\end{itemize}
\end{frame}
\subsection{Améliorations et difficultés}
\begin{frame}[fragile]\frametitle{Améliorations et difficultés}
\begin{itemize}
\item Mise à jour quantité liste de courses
\item Mise à jour automatique du stock selon les ventes
\item Ajout au système de notifications
\end{itemize}
\textbf{Difficultés}
\begin{itemize}
\item Découverte du design pattern "factory" pour les formulaires dynamiques
\item Apprentissage de Python, en plus du framework
\end{itemize}
\end{frame}
\section{Le rôle de mainteneur}
\subsection{Réviser les merge requests}
\begin{frame}[fragile]\frametitle{Réviser les merge requests}
\begin{itemize}
\item Long et fastidieux
\item Nécessaire pour maintenir une base de code cohérente
\item Permet de retrouver les bugs des nouveaux contributeurs
\item Oriente les contributeurs sur la bonne voie et la marche à suivre avec Django/Jinja2/etc...
\end{itemize}
\end{frame}
\subsection{Gestion des bugs, des tickets, de la mise en production...}
\begin{frame}[fragile]\frametitle{Gestion des bugs, des tickets, de la mise en production...}
\begin{itemize}
\item Ouverture/fermeture des tickets
\item Mailing list/IRC
\item Mise en production, gestion des migrations
\item Restauration de la base de tests régulièrement
\end{itemize}
\par Organisation de la passation
\end{frame}
\section{Conclusion}
\begin{frame}[fragile]\frametitle{Conclusion}
\begin{itemize}
\item Apprentissage Django/Git
\item Nouvelle mise en pratique des concepts de base de données relationnelles
\item Utilisation poussée de Gitlab
\item Formation de nouveaux contributeurs
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\begin{center}
\textbf{Merci de votre attention}\\
Questions?\\
Remarques?\\
\end{center}
\end{frame}
\end{document}

1
doc/TW_Skia/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_minted-Rapport

13
doc/TW_Skia/Makefile Normal file
View File

@ -0,0 +1,13 @@
CC=pdflatex
all: rapport clean
rapport: Rapport.tex
@echo "Compiling "$<
$(CC) -shell-escape $<
$(CC) -shell-escape $<
clean:
@echo "Cleaning folder"
rm *.aux; rm *.log; rm *.out; rm *.toc; rm *.snm; rm *.nav; rm *.lof

BIN
doc/TW_Skia/Rapport.pdf Normal file

Binary file not shown.

683
doc/TW_Skia/Rapport.tex Normal file
View File

@ -0,0 +1,683 @@
%%
%
% Skia
% skia@libskia.so
%
%%
\documentclass[a4paper]{report}
%packages
\usepackage[utf8]{inputenc}
\usepackage[francais]{babel}
\usepackage{graphicx}\graphicspath{{pix/}}
\usepackage{float}
\usepackage{scrextend}
\usepackage[T1]{fontenc}
\usepackage{color}
\usepackage{fancyhdr}
%Options: Sonny, Lenny, Glenn, Conny, Rejne, Bjarne, Bjornstrup
\usepackage[Bjornstrup]{fncychap}
\usepackage{minted}
\usepackage[colorlinks=true,linkcolor=black]{hyperref}
\usepackage{pdfpages}
\usepackage{titlesec, blindtext, color}
%pdf metadata
\hypersetup{
unicode=true,
colorlinks=true,
citecolor=black,
filecolor=black,
linkcolor=black,
urlcolor=black,
pdfauthor={Skia <skia@libskia.so>},
pdftitle={},
pdfcreator={pdftex},
pdfsubject={},
pdfkeywords={},
}
\definecolor{keywords}{RGB}{200,0,90}
\definecolor{comments}{RGB}{50,50,253}
\definecolor{red}{RGB}{160,0,0}
\definecolor{brown}{RGB}{160,100,100}
\definecolor{green}{RGB}{0,200,0}
\definecolor{darkgreen}{RGB}{0,130,0}
\definecolor{gray}{RGB}{100,100,100}
%inner meta
\title{Architecture de Sith: le nouveau site AE}
\author{Skia (Florent JACQUET)}
\date{Dernière version: \today}
\begin{document}
\maketitle
\tableofcontents
\chapter{Introduction}
\par Il y a longtemps, au début des années 2000, l'Association des Étudiants a mis en place un site internet qui n'a eu de
cesse d'évoluer au fil des ans. Grâce aux différents contributeurs qui s'y sont plongés, et qui ont pu y ajouter leurs
bouts de code plus ou moins utiles, le site possède désormais un ensemble de fonctionnalités impressionnant.
\par De la comptabilité à la gestion de la laverie, en passant par le forum ou le Matmatronch', le site de l'AE prend
actuellement en charge la quasi totalité de la gestion de l'argent, et c'est là un de ses rôles les plus importants.
\par Mais les vieilles technologies qu'il emploie, et l'entretien plus ou moins aléatoire qu'il a subit, en font un
outil très difficile à maintenir à l'heure actuelle, et le besoin d'une refonte s'imposait de plus en plus.
\par Le choix de technologies récentes, maintenues, et éprouvées a donc été fait, et le développement a pu commencer dès
Novembre 2015, avec l'objectif d'une mise en production dans l'été 2016, au moins dans une version incluant
l'intégralité des fonctions liées à l'argent, qui sont les plus critiques.
\par Soutenant les projets libres, j'ai décidé de placer le projet sous licence MIT, assurant ainsi une pérénité aux
source. Si quelqu'un dans le futur souhaite le relicencier sous GPL (ou autre licence plus restrictive que la MIT, voire
contagieuse), cela reste possible, mais je n'impose au départ que très peu de restrictions \footnote{La seule condition
en réalité, est de toujours garder à sa place une copie de la licence originale, à savoir le fichier LICENSE à la racine
du site.} .
\chapter{Les technologies}
\label{cha:les_technologies}
\par C'est là un des choix les plus important lors d'un tel projet, puisqu'il se fait au début, et qu'il n'est ensuite plus
possible de revenir en arrière. Le PHP vieillissant, et
piègeux\footnote{\url{https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/}} a donc été mis de côté au profit
d'un language plus stable, le \emph{Python} dans sa version 3.
\section{Python3}
\label{sec:python3}
\par Le site étant développé en \emph{Python}, il est impératif d'avoir un environnement de développement approprié à ce
language. L'outil \verb#virtualenv# permet d'installer un environnement \emph{Python} de manière locale, sans avoir besoin des
droits root pour installer des packages. De plus cela permet d'avoir sur sa machine plusieurs environnements différents,
adaptés à chaque projet, avec chacun des versions différentes des même paquets.
\par La procédure pour installer son \verb#virtualenv# est décrite dans le fichier \verb#README# situé à la racine du
projet.
\section{Django}
\label{sec:django}
\par \emph{Django} est un framework web pour \emph{Python}, apparu en 2005, et fournissant un grand nombre de
fonctionnalités pour développer un site rapidement et simplement. Cela inclut entre autre un serveur Web, pour les
échanges HTTP, un parseur d'URL, pour le routage des différentes URI du site, un ORM\footnote{Object-Relational Mapper}
pour la gestion de la base de donnée, ou encore un moteur de templates, pour les rendus HTML.
\par La version 1.8 de \emph{Django} a été choisie pour le développement de ce projet, car c'est une version LTS (Long Term
Support), c'est à dire qu'elle restera stable et maintenue plus longtemps que les autres (au moins jusqu'en Avril 2018).
\par La documentation est disponible à cette addresse: \url{https://docs.djangoproject.com/en/1.8/}. Bien que ce rapport
présente dans les grandes lignes le fonctionnement de \emph{Django}, il n'est pas et ne se veut pas exhaustif, et la
documentation restera donc toujours la référence à ce sujet.
\subsection{Le fichier de management et l'organisation d'un projet}
\label{sub:Le fichier de management et l'organisation d'un projet}
\par Lors de la création d'un projet \emph{Django}, plusieurs fichiers sont créés. Ces fichiers sont essentiels pour le projet,
mais ne contiennent en général pas de code à proprement parler. Ce n'est pas là qu'on y développe quoi que ce soit.
\subsubsection{manage.py}
\label{ssub:manage.py}
\par Le fichier \verb-manage.py-, situé à la racine, permet de lancer toutes les tâches d'administration du site. Parmis
elles:
\begin{itemize}
\item \textbf{startapp} \\
Créer une application.
\item \textbf{makemigrations} \\
Parser les modèles pour créer les fichiers de migration de la base de donnée.
\item \textbf{migrate} \\
Appliquer les migrations sur la base de données.
\item \textbf{runserver} \\
Pour lancer le serveur Web, et donc le site en lui même, dans une version de développement.
\item \textbf{makemessages} \\
Pour générer les fichiers de traduction, dans le dossier \verb#locale#.
\item \textbf{compilemessages} \\
Pour compiler les fichiers de traduction, dans le dossier \verb#locale#, et passer de \verb#django.po# à
\verb#django.mo#, sa version binaire, optimisée pour l'utilisation.
\end{itemize}
\subsubsection{Un premier dossier}
\label{ssub:Un premier dossier}
\par Un premier dossier est toujours créé, du nom du projet, et contenant plusieurs fichiers: \verb#settings.py#,
\verb#urls.py#, et \verb#wsgi.py#.
\par \verb#settings.py# est un fichier \emph{Python} servant à définir un grand nombre de constantes paramètrant le
fonctionnement du site. L'avantage par rapport à un fichier de configuration classique est que ce dernier est
executable, et on peut donc y mettre de la logique, afin d'avoir des paramètres dynamiques.
\par \verb#urls.py# est le fichier principale contenant les routes du site, c'est à dire les URLs existantes. Il se
charge en général d'inclure les fichiers \verb#urls.py# de chaque application afin de garder une architecture modulaire
et simple.
\par \verb#wsgi.py# contient quant à lui les paramètres pour la mise en production du site en tant qu'application WSGI
(Web Server Gateway Interface) pour tourner derrière un serveur Web.
\subsection{Organisation d'une application}
\label{sub:organisation_d_une_application}
\par Lorsque l'on créer une application avec \verb#./manage.py startapp#, on obtient une fois de plus un dossier type.
On trouve dans celui-ci un certain nombre de fichiers:
\begin{itemize}
\item \textbf{\_\_init\_\_.py} \\
Permet de définir le dossier comme un package \emph{Python}. Ce fichier est généralement vide.
\item \textbf{models.py} \\
C'est là que l'on définit tous les modèles, c'est à dire toutes les classes qui définissent des tables dans la base
de donnée.
\item \textbf{views.py} \\
Les vues y sont définies.
\item \textbf{admin.py} \\
C'est là que l'on déclare quels modèles doivent apparaîtrent dans l'interface fournie par le module
d'administration.
\item \textbf{tests.py} \\
Ce dernier fichier sert à écrire les tests fonctionnels, unitaires, ou d'intégation à l'aide de la librairie de
test de \emph{Django}.
\item \textbf{migrations} \\
Ce dossier sert à stocker les fichiers de migration de la base de donnée générés par \verb#./manage.py makemigrations#.
\end{itemize}
\vskip 1em
\par On rajoute par la suite généralement plusieurs fichiers:
\begin{itemize}
\item \textbf{urls.py} \\
Pour y définir toutes les URLs de l'application, et ensuite inclure ce fichier dans le fichier \verb#urls.py#
global au projet.
\item \textbf{templates} \\
Celui-ci est un dossier, et on y remet en général un sous dossier du nom de l'application afin de s'en servir de
namespace pour les templates.
\end{itemize}
\vskip 1em
\par Dans le cas où un fichier \emph{Python} deviendrait trop gros ou trop complexe, il est toujours possible de le diviser en
plusieurs fichiers que l'on met dans un dossier du même nom que ce fichier de départ, et contenant en plus un fichier
\verb#__init__.py#. De plus, pour faciliter les imports depuis ce dossier, on peut mettre dans \verb#__init__.py# la
ligne\footnote{Un exemple est disponible dans l'application core}:
\mint{python}|from .[nom_de_fichier_sans_le_.py] import *|
\subsection{Les modèles avec l'ORM}
\label{sub:les_modèles_avec_l_orm}
\subsubsection{Le modèle en lui même}
\label{ssub:Le modèle en lui même}
\par Rien ne vaudra un bon exemple pour comprendre comment sont construits les modèles avec \emph{Django}:
\begin{addmargin}[-7em]{0em}
\begin{minted}{python}
class Club(models.Model): # (1)
"""
The Club class, made as a tree to allow nice tidy organization
""" # (2)
name = models.CharField(_('name'), max_length=30) # (3)
parent = models.ForeignKey('Club', related_name='children', null=True, blank=True) # (4)
unix_name = models.CharField(_('unix name'), max_length=30, unique=True,
validators=[ # (5)
validators.RegexValidator(
r'^[a-z0-9][a-z0-9._-]*[a-z0-9]$',
_('Enter a valid unix name. This value may contain only '
'letters, numbers ./-/_ characters.')
),
],
error_messages={ # (6)
'unique': _("A club with that unix name already exists."),
},
)
address = models.CharField(_('address'), max_length=254)
email = models.EmailField(_('email address'), unique=True)
owner_group = models.ForeignKey(Group, related_name="owned_club",
default=settings.SITH_GROUP_ROOT_ID) # (7)
edit_groups = models.ManyToManyField(Group, related_name="editable_club", blank=True) # (8)
view_groups = models.ManyToManyField(Group, related_name="viewable_club", blank=True)
home = models.OneToOneField(SithFile, related_name='home_of_club', verbose_name=_("home"), null=True, blank=True,
on_delete=models.SET_NULL) # (9)
\end{minted}
\end{addmargin}
\par Explications:
\begin{description}
\item[(1)] Un modèle hérite toujours de \verb#models.Model#. Il peut y avoir des intermédiaires, mais \verb#Model#
sera toujours en haut.
\item[(2)] Toujours penser à commenter le modèle.
\item[(3)] Un premier attribut: \verb#name#, de type \verb#CharField#. Il constitue une colonne dans la base de
donnée une fois que \verb#./manage.py migrate# a été appliqué.
\item[(4)] Une \verb#ForeignKey#, l'une des relations les plus utilisées. \verb#related_name# précise le nom qui sert
de retour vers cette classe depuis la classe pointée. Ici, elle est même récursive, puisque l'on pointe vers la
classe que l'on est en train de définir, ce qui donne au final une structure d'arbre.
\item[(5)] On peut toujours préciser des \verb#validators#, afin que le modèle soit contraint, et que \emph{Django}
maintienne toujours des informations cohérentes dans la base.
\item[(6)] Un message d'erreur peut être précisé pour expliciter à l'utilisateur les problèmes rencontrés.
\item[(7)] On utilise ici le champ \verb#default# pour préciser une valeur par défaut au modèle, et celui-ci est
affecté à une valeur contenue dans les \verb#settings# de \emph{Django}.
\item[(8)] Les \verb#ManyToManyField# permettent de générer automatiquement une table intermédiaire de manière
transparente afin d'avoir des relations doubles dans les deux classes mises en jeu.
\item[(9)] Le \verb#OneToOneField# est très utilisé pour étendre une table avec des informations supplémentaires
sans toucher à la table originale.
\item[PRIMARY KEY] Les plus observateurs d'entre vous auront remarqué qu'il n'y a pas ici de \verb#PRIMARY KEY# de précisé. En
effet, \emph{Django} s'en occupe automatiquement en rajoutant un champ \verb#id# jouant ce rôle. On peut alors y
accèder en l'appelant par son nom, \verb#id# la plupart du temps, sauf s'il a été personnalisé, ou bien par
l'attribut générique \verb#pk#, toujours présent pour désigner la \verb#PRIMARY KEY# d'un modèle, quelle qu'elle
soit.
\end{description}
\subsubsection{Les migrations}
\label{ssub:Les migrations}
\par Les migrations sont à lancer à chaque fois que l'on modifie un modèle. Elles permettent de conserver la base de
donnée tout en la faisant évoluer dans sa structure, pour ajouter ou supprimer une colonne dans une table par exemple.
\par Lancer la commande \verb#./manage.py makemigrations [nom de l'appli]# va permettre de générer un fichier \emph{Python}
automatiquement, qui sera mis à la suite des précédents, et qui sera appliqué sur la base au moment du lancement de
\verb#./manage.py migrate#.
\subsection{Les vues}
\label{sub:les_vues}
\par Les vues sont les parties de code s'occupant de l'interface avec l'utilisateur. Elles sont appelées par les URLs,
et renvoient des réponses HTTP en fonction du traitement effectué.
\subsubsection{Les URL}
\label{ssub:Les URL}
\par Les URLs sont définies par application, et centralisées dans le dossier du projet. Il s'agit à chaque fois d'une
liste d'appel à la fonction \verb#url()#, qui comprends toujours une expression rationnelle décrivant l'URL, une
fonction passée en tant que callback qui sera appelé au moment où l'URL est résolue, et enfin un nom, permettant de s'y
référer dans les fonctions de résolution inverse, comme dans les templates par exemple. Nous détaillerons cette
utilisation plus tard.
\par Pour garder une organisation claire, les URLs sont classées par espaces de noms (namespace) afin d'avoir à éviter
de préfixer tous les noms pour s'y retrouver. Le namespace d'une URL est généralement le même nom que celui de
l'application dans laquelle elle se trouve.
\subsubsection{Les fonctions de vue}
\label{ssub:Les fonctions de vue}
\par Une fonction de vue prend toujours en paramètre une variable \verb#request# et renvoie toujours un objet
\verb#HTTPResponse#, contenant un code de retour HTTP, ainsi qu'une chaîne de caractères contenant la réponse en elle
même.
\par Entre temps, le traitement des informations permet de mettre à jour, de créer, ou de supprimer les objets définis
dans les modèles, par le biais des paramètres passé dans la requête. Ainsi, on peut accèder aux informations des
variables \verb#GET# et \verb#POST# très facilement en appelant respectivement \verb#request.GET['ma_clef']# et
\verb#request.POST['ma_clef']#, ces deux variables fonctionnant comme des dictionnaires.
\subsubsection{Des vues basées sur des classes}
\label{ssub:Des vues basées sur des classes}
\par Les vues avec \emph{Django} peuvent aussi être définies comme des classes. Elles héritent alors à ce moment là
toutes de la classe \verb#View#, mais ont toutefois souvent beaucoup d'intermédiaires et n'héritent donc pas directement
de cette dernière.
\par L'avantage de ces vues sous forme de classe est de pouvoir séparer toute la chaîne de traitement entre les
différentes méthodes, et ainsi permettre, en jouant avec l'héritage, de fournir alors très peu d'informations à la
classe, tout en lui permettant d'effectuer un travail correct.
\par Ainsi, on retrouve de base, dans les filles de \verb#View#, un grand nombre de classes prédéfinies pour la plupart
des comportement. \verb#DetailView#, \verb#CreateView#, \verb#ListView#, sont quelques exemples de classes renvoyant
respectivement un objet en détails, un formulaire pour créer un nouvel objet, et enfin une liste d'objets. Il existe
cependant un bon nombre de ces vues fournissant d'autres fonctionnalités, et si malgré tout, aucune ne peut convenir, il
reste possible de se baser sur l'une d'elle et surcharger l'une de ses fonctions pour l'adapter à ses besoins.
\par L'écosystème des \verb#class-based views# étant toutefois assez complexe et riche, un site web a été créé afin
d'offrir un bon résumé de la situation: \emph{Classy class-based views}, accessible à l'adresse
\url{http://ccbv.co.uk/}.
\section{Jinja2}
\label{sec:jinja2}
\par \emph{Jinja2} est un moteur de template écrit en \emph{Python} qui s'inspire fortement de la syntaxe des templates de
\emph{Django}, mais qui apporte toutefois son lot d'améliorations non négligeables. En effet, l'ajout des macros, par
exemple, permet de factoriser une grande partie du code.
\par Un moteur de template permet de générer du contenu textuel de manière procédural en fonction des données à
afficher. Cela permet en pratique de pouvoir inclure du code proche de \emph{Python} dans la syntaxe au milieu d'un
document contenant principalement du HTML. Ainsi, si on a une liste d'objets, on peut facilement executer une boucle
\verb#for# afin de faire afficher simplement tous les objets selon le même format.
\noindent De même, il est facile d'inclure un \verb#if# pour décider à l'execution d'afficher ou non un lien en fonction
des droits que l'utilisateur possède sur le site, par exemple.
\par En plus des structures conditionnelles classiques, un moteur de templates permet de formater des données plus
simplement, comme par exemple des dates, en fonction de la langue actuellement utilisée par l'utilisateur.
\par Enfin, bien utilisés, les templates permettent d'utiliser des fonctions d'inclusion, ce qui permet de hiérarchiser
les fichiers, et de s'assurer de l'unité de certaines parties du site. Ainsi, les \emph{headers}, les \emph{footers}, et
autres menus que l'on retrouve sur toutes les pages du site sont définis chacun dans un seul fichier et inclus dans
tous les autres.
\subsection{Exemple de template Jinja2}
\label{sub:exemple_de_template_jinja2}
\begin{addmargin}[-4em]{0em}
\begin{minted}{jinja}
{% extends "core/base.jinja" %} {# (1) #}
{% block title %} {# (2) #}
{% trans user_name=user.get_display_name() %}{{ user_name }}'s tools{% endtrans %} {# (3) #}
{% endblock %}
{% block content %}
<h3>{% trans %}User Tools{% endtrans %}</h3> {# (4) #}
<p><a href="{{ url('core:user_profile', user_id=request.user.id) }}{# (5) #}">
{% trans %}Back to profile{% endtrans %}</a>
</p>
<h4>{% trans %}Sith management{% endtrans %}</h4>
<ul>
{% if user.is_root %} {# (6) #}
<li><a href="{{ url('core:group_list') }}">{% trans %}Groups{% endtrans %}</a></li>
{% endif %}
{% if user.is_in_group(settings.SITH_GROUP_ACCOUNTING_ADMIN_ID) %}
<li><a href="{{ url('accounting:bank_list') }}">Accounting</a></li>
{% endif %}
{% if user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user.is_root %}
<li><a href="{{ url('subscription:subscription') }}">Subscriptions</a></li>
<li><a href="{{ url('counter:admin_list') }}">Counters management</a></li>
{% endif %}
</ul>
<h4>{% trans %}Club tools{% endtrans %}</h4>
<ul>
{% for m in user.memberships.filter(end_date=None).all() %} {# (7) #}
<li><a href="{{ url('club:tools', club_id=m.club.id) }}">{{ m.club }}</a></li>
{% endfor %}
</ul>
{% endblock %}
\end{minted}
\end{addmargin}
\begin{description}
\item[(1)] Nous faisons ici une extension d'un template existant afin de bénéficier des blocs déjà défini, et afin
d'intégrer le contenu de ce template dans celui déjà défini.
\item[(2)] \verb#title# est un bloc défini dans le template \verb#base.jinja#. Le redéfinir joue alors le même rôle
qu'une surcharge de méthode dans de l'héritage, et permet de remplacer le contenu du bloc, tout en conservant sa
place dans le template parent.
\item[(3)] La variable \verb#user# faisant ici partie du contexte, nous pouvons donc appeler une de ses méthodes
pour obtenir un contenu dynamiquement.
\item[(4)] Les blocs \verb#{% trans %}# et \verb#{% endtrans %}# permettent de définir les chaînes qui vont ensuite
être traduites.
\item[(5)] L'appel à la fonction \verb#url()# permet de résoudre la route afin d'obtenir l'adresse appropriée en
fonction des arguments passé. Cette fonction fait généralement partie du contexte global, et est donc accessible
dans tous les templates.
\item[(6)] Les structures conditionnelles permettent d'afficher ou pas un élément en fonction de la valeur d'une
variable ou du retour d'une fonction.
\item[(7)] Le \verb#for# permet, comme en Python, d'itérer sur les éléments d'une liste. Ici, on fait même une
requête via l'ORM de \emph{Django} en utilisant un filtre pour obtenir directement des valeurs depuis la base de
donnée de manière transparente.
\end{description}
\subsection{Le contexte}
\label{sub:le_contexte}
\par Le contexte dans lequel le template s'execute influe beaucoup sur la capacité de \emph{Jinja} à s'adapter
dynamiquement au contenu. Plus on a de variables disponibles, plus on va pouvoir générer un contenu s'y adaptant.
\par Il est possible de définir le contexte global, et donc ce qui est accessible dans tous les templates, comme il est
possible d'ajouter manuellement et spécifiquement des variables au contexte pour un template particulier, dans une vue
particulière.
\chapter{Organisation du projet}
\label{cha:organisation_du_projet}
\par Après cette présentations des différentes technologies employées dans le projet, passons maintenant à une partie plus
spécifique à Sith en lui même.
\section{Les options spécifiques}
\label{sec:les_options_sp_cifiques}
\subsection{Django-jinja}
\label{sub:django_jinja}
\par \emph{Jinja} n'étant pas inclus de base dans \emph{Django}, le paquet \emph{Django-jinja} a été mis en place afin
de bénéficier au mieux des performances de chacun, comme les filtres personnalisés de \emph{Django} dans la puissance des
macros de \emph{Jinja}. Tout cela se trouve dans la variable \verb#TEMPLATES#.
\par \emph{Jinja} a été ajouté afin de s'occuper uniquement des fichiers ayant l'extension \verb#.jinja# dans les
dossiers \verb#templates# de chaque application.
\par Un certain nombre de variables et fonctions ont été ajoutés au contexte global. Parmis elles, l'ensemble des
filtres que \emph{Django} fournit, mais aussi un filtre pour passer de \emph{Markdown} à \emph{HTML}, l'ensemble du
contenu de \verb#settings#, et enfin des fonction utiles dont voici la liste:
\begin{itemize}
\item \textbf{can\_edit\_prop} permet, en fonction d'une variable \verb#user# et d'un objet, de savoir si
l'utilisateur donnée peut modifier les propriétés de cet objet.
\item \textbf{can\_edit} permet, en fonction d'une variable \verb#user# et d'un objet, de savoir si
l'utilisateur donnée peut éditer l'objet.
\item \textbf{can\_view} permet, en fonction d'une variable \verb#user# et d'un objet, de savoir si
l'utilisateur donnée peut voir l'objet.
\end{itemize}
\subsection{Le fichier \textbf{settings\_custom.py}}
\label{sub:le_fichier_settings_custom.py}
\par Afin de faciliter la configuration des différentes instances du projet, un fichier \verb#settings_custom.py# a été
créé à côté de \verb#settings.py#. Celui-ci est automatiquement inclu à la fin de \verb#settings.py#, pour que tout ce
qui est défini dans le \verb#_custom# vienne remplacer les valeurs par défaut. Seul \verb#settings.py# est versionné
dans \emph{Git}, et est exhaustif concernant la configuration et les variables requises. \verb#settings_custom.py# quant
à lui n'est même pas obligatoire, et s'il existe, ne peut contenir que quelques variables qui diffèrent de la
configuration par défaut\footnote{Typiquement, ajouter \textbf{DEBUG=True} }.
\section{Les commandes ajoutées}
\label{sec:les_commandes_ajoutees}
\par Si cela ne suffit pas, il est possible d'enrichir de nouvelles commandes le script \verb#manage.py#. Cela a été fait
pour \emph{Sith}, afin de pouvoir très rapidement déployer un environnement en ayant déjà les quelques données
nécéssaires au fonctionnement du projet, comme le groupe \verb#root# par exemple.
\subsection{setup}
\label{sub:setup}
\par La fonction \verb#setup# s'occupe simplement de supprimer le fichier \verb#db.sqlite3#, qui est le fichier de base
de donnée utilisé pour le développement, et relance une procédure de migration pour reconstruire une base de donnée
propre avant de la peupler.
\par Cette commande permet donc de s'assurer que la base de donnée utilisée est neuve et non corrompue.
\subsection{populate}
\label{sub:populate}
\par \verb#populate# permet de remplir la base de donnée avec dans un premier temps les données \textbf{nécessaires} au
bon fonctionnement du site. Cela comprend notamment un superutilisateur, les groupes définis dans
\verb#settings.SITH_GROUP_*_ID#, dont le groupe \verb#root# fait partie, une première page de Wiki, ainsi qu'un club
racine, l'AE dans notre cas.
\par Cette fonction prend un éventuel argument, \verb#--prod#, qui lui permet de mettre en place le strict minimum
énoncé précédemment. Sinon, elle continue en ajoutant un certain nombre de données pratiques pour le développement,
comme un certain nombre d'utilisateurs avec différents droits, de nouvelles pages dans le Wiki, de nouveaux clubs, des
comptoirs et des produits, ou encore des données de comptabilité.
\par L'argument \verb#--prod# peut, en outre, être passé directement depuis la fonction \verb#setup#.
\chapter{Les applications}
\label{cha:les_applications}
\par Chaque application va être détaillée ici. Cela permet de mettre en valeur le rôle de chacune, et de signaler les
éventuelles particularités qui peuvent s'y trouver.
\section{Core}
\label{sec:core}
\subsection{Résumé}
\label{sub:resume}
\par L'application \emph{Core} est de loin la plus importante de toutes. C'est elle qui gère les utilisateurs ainsi que
leurs droits. Le CMS y est aussi définit pour tout ce qui est pages de Wiki, pages statiques, ou l'ajout du filtre
\verb#markdown# pour les templates.
\subsection{Liste des modèles}
\label{sub:liste_des_modeles}
\begin{itemize}
\item \textbf{Group} \\
Ce modèle se subdivise en deux: RealGroup et MetaGroup, décrivants respectivement un vrai groupe géré à la main
dans la liste des groupes, et un meta-groupe, géré automatiquement, en général par les clubs, ou bien par les
cotisations.
\item \textbf{User} \\
Le modèle des utilisateurs, qui est ensuite décliné ou référencé dans beaucoup d'applications pour les
utilisations spécifiques. C'est toutefois ici que sont déclarés les fonctions de gestion des droits des
utilisateurs, afin de pouvoir les utiliser partout ailleurs.
\item \textbf{AnonymousUser} \\
Cette classe n'est pas un modèle stocké en base, puisqu'elle sert à instancier la variable \verb#user#
lorsqu'aucun utilisateur n'est connecté au site.
\item \textbf{Page} \\
Décrit une entité page, servant dans le Wiki ou pour les pages statiques du site. Cette classe s'occupe des
méta-données de la page, comme ses droits, mais son contenu est en réalité stocké dans un objet \verb#PageRev#.
\item \textbf{PageRev} \\
Décrit une révision de page. Utiliser une autre classe avec une \verb#ForeignKey# permet de gérer facilement un
historique des révisions.
\end{itemize}
\subsection{La gestion des droits}
\label{sub:la_gestion_des_droits}
\par La gestion des droits est implémentée de manière globale dans l'application Core.
\par On trouve en effet dans \verb#views/__init__.py# un certain nombre de mixins \footnote{Un mixin est, dans
\emph{Django}, un terme désignant une classe abstraite qui ne peut pas servir de parente seule. Elle permet de
surcharger certaines méthodes d'une autre classe abstraite afin de l'adapter à un comportement plus spécifique, mais
reste totalement inutile quand elle est seule. La gestion des droits est un bon exemple puisqu'elle ne s'occupe pas
vraiment de traitement des données comme les autres vues le feraient, elle permet simplement d'ajouter une condition à une
autre classe où cette dernière renverrait un \emph{403 Forbidden} } s'occupant de cela, en se basant sur
un modèle général permettant de rendre compatible rapidement n'importe quel modèle que l'on voudrait protéger. Il suffit
alors de déclarer dans la classe une certain nombre de méthodes et/ou d'attributs, le reste étant simplement déjà pris
en charge par les mixins suivants:
\begin{itemize}
\item \textbf{CanCreateMixin} \\
Cette classe est à mettre en parente d'une classe héritant de \verb#CreateView#, afin d'empêcher quelqu'un
n'ayant pas les droits de créer un objet.\\
Méthode correspondante à créer dans les modèles: \\
\verb#def can_be_created_by(user):# \\
(Attention, ce n'est pas une méthode prenant \verb#self# en premier paramètre!)
\item \textbf{CanEditPropMixin} \\
Cette classe protège l'objet pour l'édition avancée. Par exemple: éditer les droits sur une page, ou éditer les
droits accordé à un utilisateur. \\
Attribut correspondant à créer dans les modèles: \\
\verb#owner_group = models.ForeignKey(Group, # \\
\verb# related_name="owned_user", default=settings.SITH_GROUP_ROOT_ID)# \\
Méthode correspondante à créer dans les modèles: \\
\verb#def is_owned_by(self, user):# \\
\item \textbf{CanEditMixin} \\
Cette classe protège l'objet pour l'édition non avancée. Par exemple: éditer une page, ou éditer le profil d'un
utilisateur. \\
Attribut correspondant à créer dans les modèles: \\
\verb#edit_groups = models.ManyToManyField(Group, # \\
\verb# related_name="editable_user", blank=True)# \\
Méthode correspondante à créer dans les modèles: \\
\verb#def can_be_edited_by(self, user):# \\
\item \textbf{CanViewMixin} \\
Cette classe protège l'objet pour la vue. Par exemple: consulter une page, ou voir le profil d'un utilisateur. \\
Attribut correspondant à créer dans les modèles: \\
\verb#view_groups = models.ManyToManyField(Group, # \\
\verb# related_name="viewable_user", blank=True)# \\
Méthode correspondante à créer dans les modèles: \\
\verb#def can_be_viewed_by(self, user):# \\
\end{itemize}
\par Pour savoir si l'on doit implémenter les méthodes, les attributs, ou les deux, il faut simplement se poser la
question de savoir si l'objet en question requiert une gestion des droits à l'échelle de la classe ou à l'échelle de
l'objet, et si cette gestion peut être calculé par de la logique.
\par Si on a besoin d'une gestion pour la classe, ou si du code peut être implémenter pour déterminer qui peut avoir tel
droit, alors la méthode suffira. Mais si on a besoin d'une gestion au niveau de l'objet, alors il faudra certainement
recourir aux attributs.
\par Exemples:
\begin{itemize}
\item Les comptes en banque sont gérés uniquement par les personnes faisant partie du groupe \verb#admin-compta#.
Ils ont donc tous les mêmes droits, c'est une gestion au niveau de la classe, donc les méthodes suffisent.
\item Les classeurs de comptabilité sont gérés par les trésoriers des clubs, ils n'ont pas tous les mêmes droits,
mais cela peut tout de même se calculer en fonction des postes dans les clubs correspondants. On a donc besoin
des méthodes uniquement.
\item Les pages n'appartiennent pas forcément à un club, ni à une quelconque entité, mais ont tout de même besoin de
gestion des droits au niveau de l'objet. L'ajout des attributs est donc nécessaire pour pouvoir gérer cela au
cas par cas.
\end{itemize}
\section{Subscription}
\label{sec:subscription}
\subsection{Résumé}
\label{sub:resume}
\par Cette application ajoute le support des cotisations. Elle fournit également les interfaces de cotisation.
\subsection{Liste des modèles}
\label{sub:liste_des_modeles}
\begin{itemize}
\item \textbf{Subscription} \\
Un modèle cotisation, pour stocker ces dernières. Cette classe fait automatiquement les calculs de début et de
fin de cotisation en fonction de la date du jour, du type de cotisation, et de la durée en semestre de
cotisation.
\end{itemize}
\section{Accounting}
\label{sec:accounting}
\subsection{Résumé}
\label{sub:resume}
\par Cette application sert à gérer la comptabilité. Elle est architecturée de façon hiérarchique, avec en haut, les
comptes bancaires réels, qui contiennent eux des comptes de clubs, permettant de les diviser en plusieurs petits comptes
en interne, et enfin les classeurs de trésorerie, propres à chaque compte club, permettant de faire les comptes en
triant par semestre.
\par De plus, cette application définit un nouveau type de champ dans la base de donnée: le champ \verb#CurrencyField#,
permettant de stocker de valeurs monétaires.
\subsection{Liste des modèles}
\label{sub:liste_des_modeles}
\begin{itemize}
\item \textbf{BankAccount} \\
Le modèle des comptes bancaires.
\item \textbf{ClubAccount} \\
Le modèle des comptes clubs.
\item \textbf{GeneralJournal} \\
Le modèle des classeurs de comptabilité, généralement semestriels, mais ils peuvent toutefois fonctionner en
année pour les activités plus longues comme le Gala.
\item \textbf{AccountingType} \\
Le modèle pour stocker les types comptables, servant à remplir les opérations.
\item \textbf{SimpleAccountingType} \\
Le modèle pour stocker les types comptables simplifiés, servant à remplir les opérations.
\item \textbf{Label} \\
Le modèle pour stocker les étiquettes, servant à classifer les opérations.
\item \textbf{Operation} \\
Le modèle des opérations, servant à remplir les classeurs comptables. Une opération peut être un débit ou un
crédit, et permet ensuite d'éditer des factures, par exemple.
\end{itemize}
\section{Counter}
\label{sec:counter}
\subsection{Résumé}
\label{sub:resume}
\par Cette application s'occupe de la gestion des comptoirs. Elle définit ainsi des produits, et ajoute également le
support du compte AE pour les utilisateurs.
\subsection{Liste des modèles}
\label{sub:liste_des_modeles}
\begin{itemize}
\item \textbf{Customer} \\
Ce modèle étend l'utilisateur pour lui rajouter un compte AE. Il est lié à la classe \verb#User# par un
\verb#OneToOneField#.
\item \textbf{ProductType} \\
Ce modèle ajoute des types de produits afin de catégoriser ces derniers.
\item \textbf{Product} \\
Ce modèle décrit les produits pouvant être vendus dans les différents comptoirs.
\item \textbf{Counter} \\
Ce modèle décrit les comptoirs, qui permettent de générer des recharges de compte et des ventes de produits.
\item \textbf{Refilling} \\
Ce modèle permet de stocker les rechargements de compte.
\item \textbf{Selling} \\
Ce modèle permet d'enregistrer toutes les ventes de produits.
\end{itemize}
\section{Club}
\label{sec:club}
\subsection{Résumé}
\label{sub:resume}
\par Cette application permet de générer les clubs et les adhésions des utilisateurs à ceux-ci.
\subsection{Liste des modèles}
\label{sub:liste_des_modeles}
\begin{itemize}
\item \textbf{Club} \\
Le modèle des clubs.
\item \textbf{Membership} \\
Le modèle des adhésions. Stocker cela dans un modèle à part permet de conserver un historique des personnes
ayant eu un rôle quelconque dans un club quelconque.
\end{itemize}
\chapter{Conclusion}
\par Encore une fois, ce rapport ne se veut absolument pas exhaustif sur quoi que ce soit.
\par Concernant \emph{Python}, \emph{Django}, ou \emph{Jinja}, les documentations respectives sont toujours très bien
faites, et permettront de répondre à toutes les questions techniques concernant les technologies.
\par Concernant le projet \emph{Sith} en lui-même, ce rapport n'est pas non plus exhaustif. Pour cela, lire le code des
différentes sections sera le meilleur moyen de comprendre le fonctionnement des différentes applications. Pour obtenir plus
rapidement un résumé à jour des sources, le fichier \verb#Doxyfile# présent à la racine du site permet de regénérer de
la documentation exhaustive rapidement à l'aide de \emph{Doxygen} (voir la section correspondante dans le README).
\par J'espère toutefois que même s'il n'est pas complet, ce rapport permettra à tout futur contributeur de rentrer plus
rapidement dans le projet.
\par L'idéal serait également de maintenir à jour ce rapport du mieux possible en même temps que le développement
avance, même si je ne me fais guère d'illusions en pratique.
\section{Pour le futur...}
\label{sec:pour_le_futur}
\par En l'état actuel des choses, un grand nombre d'éléments sont encore manquants au site:
\begin{itemize}
\item Une API REST pour pouvoir facilement intégrer d'autres outils autour du site.
\item Du CSS, pour qu'il soit un peu plus joli à regarder.
\item Du Javascript, et particulièrement de l'AJAX pour améliorer l'ergonomie de certaines pages.
\item Un grand nombre de vues pour aider à gérer les données plus efficacement, ou à les gérer tout court dans
certains cas.
\item Quelques applications utiles à qui existent sur le site actuel, mais que je n'ai pas encore eu le temps de
développer: un forum, une galerie de photos, une gestion basique des fichiers pour uploader des documents dans
les pages ou le forum, un système de news, une newsletter (Weekmail), une gestion des sondages et des élections,
etc...
\end{itemize}
\section{Apports personnels}
\label{sec:apports_personnels}
\par Même s'il est vrai que j'ai beaucoup appris en développant ce site, cela reste avant tout un travail de quantité
plus que de qualité: on définit des modèles, puis les vues correspondantes en terminant par les templates, et on répète
l'opération pour l'application suivante.
\par Mais j'ai tout de même pu mettre en place de l'intégration continue pour ce projet, ce qui a été certes, très
rapide, mais toutefois très enrichissant, étant donnée que ces méthodes sont très en vogue ces derniers temps.
\par J'ai également pu me familiariser d'avantage avec le fonctionnement d'un ORM, et la magie noire que cela permet de
faire \footnote{Je trouve toujours magique de pouvoir faire une requête SQL au milieu d'un template sans que cela
paraisse affreux :)}.
\par Enfin, j'espère que ce projet va, en plus d'être correctement mené au bout, pouvoir être repris par la suite par
les futurs membres de l'équipe info de l'AE, et pourquoi pas par d'autres contributeurs...
\vskip 3em
\emph{Skia <skia@libskia.so> - 2016}
\end{document}

View File

@ -0,0 +1,29 @@
Introduction
============
Le but de ce projet est de fournir à l'Association des Étudiants de l'UTBM une plate-forme pratique et centralisée de ses services. Le Sith de l'AE tient à jour le registre des cotisations à l'association, prend en charge la trésorerie, les ventes de produits et services, la diffusion dévénements, la gestion de la laverie et bien plus encore. Il est conçu de manière suffisamment générique pour être facilement adaptable à une autre association.
C'est un projet bénévole qui tire ses origines des années 2000. Il s'agit de la troisième version du site de l'association initiée en 2015. C'est une réécriture complète en rupture totale des deux versions qui l'ont précédée.
Pourquoi réécrire le site
-------------------------
L'ancienne version du site, sobrement baptisée `ae2 <https://github.com/ae-utbm/sith2>`_ présentait un nombre impressionnant de fonctionnalités. Il avait été écrit en PHP et se basait sur son propre framework maison.
Malheureusement, son entretiens était plus ou moins hasardeux et son framework reposait sur des principes assez différents de ce qui se fait aujourd'hui, rendant la maintenance difficile. De plus, la version de PHP qu'il utilisait était plus que déprécié et à l'heure de l'arrivée de PHP 7 et de sa non rétrocompatibilité il était vital de faire quelque chose. Il a donc été décidé de le réécrire.
La philosophie du projet
------------------------
Pour éviter les erreurs du passé, ce projet met l'accent sur la maintenabilité. Le choix des technologies ne s'est donc pas fait uniquement sur le fait qu'elle soit récentes, mais également sur leur robustesse, leur fiabilité et leur potentiel à être maintenu loin dans le futur.
La maintenabilité passe également par le choix minutieux des dépendances qui doivent eux aussi passer l'épreuve du temps pour éviter qu'elles ne mettent le projet en danger.
Cela passe également par la minimisation des frameworks employés de manière à réduire un maximum les connaissances nécessaires pour contribuer au projet et donc simplifier la prise en main. La simplicité est à privilégier si elle est possible.
Le projet doit être simple à installer et à déployer.
Le projet étant à destination d'étudiants, il est préférable de minimiser les ressources utilisées par l'utilisateur final. Il faut qu'il soit au maximum économe en bande passante et calcul côté client.
Le projet est un logiciel libre et est sous licence GPL. Aucune dépendance propriétaire ne sera acceptée.

178
doc/about/tech.rst Normal file
View File

@ -0,0 +1,178 @@
Technologies utilisées
======================
Bien choisir ses technologies est crucial puisqu'une fois que le projet est suffisamment avancé, il est très difficile voir impossible de revenir en arrière.
En novembre 2015, plusieurs choix s'offraient à nous :
* Continuer avec du PHP
* S'orienter vers un langage web plus moderne et à la mode comme le Python ou le Ruby
* Baser le site sur un framework Javascript
Le PHP 5, bientôt 7, de l'époque étant assez discutable comme `cet article <https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/>`__ et l'ancien site ayant laissé un goût amer à certains développeurs, celui-ci a été mis de côté.
L'écosystème Javascript étant à peine naissant et les frameworks allant et venant en seulement quelques mois, il était impossible de prédire avec certitude si ceux-ci passeraient l'épreuve du temps, il était inconcevable de tout parier là dessus.
Ne restait plus que le Python et le Ruby avec les frameworks Django et Ruby On Rails. Ruby ayant une réputation d'être très "cutting edge", c'est Python, un langage bien implanté et ayant fait ses preuves, qui a été retenu.
Backend
-------
Python 3
~~~~~~~~
`Site officiel <https://www.python.org/>`__
Le python est un langage de programmation interprété multi paradigme sorti en 1991. Il est très populaire pour sa simplicité d'utilisation, sa puissance, sa stabilité, sécurité ainsi que sa grande communauté de développeur. Sa version 3, non rétro compatible avec sa version 2, a été publiée en 2008.
.. note::
Puisque toutes les dépendances du backend sont des packages Python, elles sont toutes ajoutées directement dans le fichier **requirements.txt** à la racine du projet.
Django
~~~~~~
| `Site officiel <https://www.djangoproject.com/>`__
| `Documentation <https://docs.djangoproject.com/en/1.11/>`__
Django est un framework web pour Python apparu en 2005. Il fourni un grand nombre de fonctionnalités pour développer un site rapidement et simplement. Cela inclu entre autre un serveur Web de développement, un parseur d'URLs pour le routage des différentes URI du site, un ORM (Object-Relational Mapper) pour la gestion de la base de donnée ainsi qu'un moteur de templates pour le rendu HTML. Django propose une version LTS (Long Term Support) qui reste stable et est maintenu sur des cycles plus longs, ce sont ces versions qui sont utilisées.
PostgreSQL / SQLite
~~~~~~~~~~~~~~~~~~~
| `Site officiel PostgreSQL <https://www.postgresql.org/>`__
| `Site officiel SQLite <https://www.sqlite.org/index.html>`__
Comme la majorité des sites internet, le Sith de l'AE enregistre ses données dans une base de donnée. Nous utilisons une base de donnée relationnelle puisque c'est la manière typique d'utiliser Django et c'est ce qu'utilise son ORM. Dans la pratique il arrive rarement dans le projet de se soucier de ce qui fonctionne derrière puisque le framework abstrait les requêtes au travers de son ORM. Cependant, il arrive parfois que certaines requêtes, lorsqu'on cherche à les optimiser, ne fonctionnent que sur un seul backend.
Le principal à retenir ici est :
* Sur la version de production nous utilisons PostgreSQL, c'est cette version qui doit fonctionner en priorité
* Sur les versions de développement, pour faciliter l'installation du projet, nous utilisons la technologie SQLite qui ne requiert aucune installation spécifique. Certaines instructions ne sont pas supportées par cette technologie et il est parfois nécessaire d'installer PostgreSQL pour le développement de certaines parties du site.
Frontend
--------
Jinja2
~~~~~~
`Site officiel <https://jinja.palletsprojects.com/en/2.10.x/>`__
Jinja2 est un moteur de template écrit en Python qui s'inspire fortement de la syntaxe des templates de Django. Ce moteur apporte toutefois son lot d'améliorations non négligeables. Il permet par exemple l'ajout de macros, sortes de fonctions écrivant du HTML.
Un moteur de templates permet de générer du contenu textuel de manière procédural en fonction des données à afficher, cela permet de pouvoir inclure du code proche du Python dans la syntaxe au milieu d'un document contenant principalement du HTML. On peut facilement faire des boucles ou des conditions ainsi même que de l'héritage de templates.
Attention : le rendu est fait côté serveur, si on souhaite faire des modifications côté client, il faut utiliser du Javascript, rien ne change à ce niveau là.
Exemple d'utilisation d'un template Jinja2
.. sourcecode:: html+jinja
<title>{% block title %}{% endblock %}</title>
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
jQuery
~~~~~~
`Site officiel <https://jquery.com/>`__
jQuery est une bibliothèque JavaScript libre et multiplateforme créée pour faciliter l'écriture de scripts côté client dans le code HTML des pages web. La première version est lancée en janvier 2006 par John Resig.
C'est une vieille technologie et certains feront remarquer à juste titre que le Javascript moderne permet d'utiliser assez simplement la majorité de ce que fourni jQuery sans rien avoir à installer. Cependant, de nombreuses dépendances du projet utilisent encore jQuery qui est toujours très implanté aujourd'hui. Le sucre syntaxique qu'offre cette libraire reste très agréable à utiliser et économise parfois beaucoup de temps. Ça fonctionne et ça fonctionne très bien. C'est maintenu, léger et pratique, il n'y a pas de raison particulière de s'en séparer.
Sass
~~~~
`Site officiel <https://sass-lang.com/>`__
Sass (Syntactically Awesome Stylesheets) est un langage dynamique de génération de feuilles CSS apparu en 2006. C'est un langage de CSS "amélioré" qui permet l'ajout de variables (à une époque où le CSS ne les supportait pas), de fonctions, mixins ainsi qu'une syntaxe pour imbriquer plus facilement et proprement les règles sur certains éléments. Le Sass est traduit en CSS directement côté serveur et le client ne reçoit que du CSS.
C'est une technologie stable, mature et pratique qui ne nécessite pas énormément d'apprentissage.
Fontawesome
~~~~~~~~~~~
`Site officiel <https://fontawesome.com>`__
Fontawesome regroupe tout un ensemble d'icônes libres de droits utilisables facilement sur n'importe quelle page web. Ils sont simple à modifier puisque modifiables via le CSS et présentent l'avantage de fonctionner sur tous les navigateurs contrairement à un simple icône unicode qui s'affiche lui différemment selon la plate-forme.
.. note::
C'est une dépendance capricieuse qu'il évolue très vite et qu'il faut très souvent mettre à jour.
.. warning::
Il a été décidé de **ne pas utiliser** de CDN puisque le site ralentissait régulièrement. Il est préférable de fournir cette dépendance avec le site.
Documentation
-------------
Sphinx
~~~~~~
`Site officiel <https://www.sphinx-doc.org/en/master/>`__
Sphinx est un outil qui permet la création de documentations intelligentes et très jolies. C'est cet outil qui permet d'écrire le documentation que vous êtes en train de lire actuellement. Développé en 2008 pour la communauté Python, c'est l'outil le plus répandu. Il est utilisé pour la documentation officielle de Python, pour celle de Django, Jinja2 et bien d'autres.
ReadTheDocs
~~~~~~~~~~~
`Site officiel <https://www.sphinx-doc.org/en/master/>`__
C'est un site d'hébergement de documentations utilisant Sphinx. Il propose la génération de documentation à partir de sources et leur hébergement gracieusement pour tout projet open source. C'est le site le plus utilisé et sur lequel sont hébergées bon nombre de documentations comme par exemple celle de Django. La documentation sur ce site est automatiquement générée à chaque nouvelle modification du projet.
reStructuredText
~~~~~~~~~~~~~~~~
`Site officiel <http://docutils.sourceforge.net/rst.html>`__
C'est un langage de balisage léger utilisé notamment dans la documentation du langage Python. C'est le langage dans lequel est écrit l'entièreté de la documentation ci-présente pour que Sphinx puisse la lire et la mettre en forme.
Workflow
--------
Git
~~~
`Site officiel <https://git-scm.com/>`__
Git est un logiciel de gestion de versions écrit par Linus Torsvald pour les besoins du noyau linux en 2005. C'est ce logiciel qui remplace svn anciennement utilisé pour gérer les sources du projet (rappelez vous, l'ancien site date d'avant 2005). Git est plus complexe à utiliser mais est bien plus puissant, permet de gérer plusieurs version en parallèle et génère des codebases vraiment plus légères puisque seules les modifications sont enregistrées (contrairement à svn qui garde une copie de la codebase par version).
GitLab
~~~~~~
| `Site officiel <https://about.gitlab.com/>`__
| `Instance de l'AE <https://github.com/ae-utbm/>`__
GitLab est une alternative libre à GitHub. C'est une plate-forme avec interface web permettant de déposer du code géré avec Git offrant également de l'intégration continue et du déploiement automatique.
C'est au travers de cette plate-forme que le Sith de l'AE est géré, sur une instance hébergée directement sur nos serveurs.
Sentry
~~~~~~
| `Site officiel <https://sentry.io>`__
| `Instance de l'AE <https://ae2.utbm.fr>`__
Sentry est une plate-forme libre qui permet de se tenir informer des bugs qui ont lieu sur le site. À chaque crash du logiciel (erreur 500), une erreur est envoyée sur la plate-forme et est indiqué précisément à quelle ligne de code celle-ci a eu lieu, à quelle heure, combien de fois, avec quel navigateur la page a été visitée et même éventuellement un commentaire de l'utilisateur qui a rencontré le bug.
Poetry
~~~~~~~~~~
`Utiliser Poetry <https://python-poetry.org/docs/basic-usage/>`__
Poetry est un utilitaire qui permet de créer et gérer des environements Python de manière simple et intuitive. Il permet également de gérer et mettre à jour le fichier de dépendances.
L'avantage d'utiliser poetry (et les environnements virtuels en général) est de pouvoir gérer plusieurs projets différents en parallèles puisqu'il permet d'avoir sur sa machine plusieurs environnements différents et donc plusieurs versions d'une même dépendance dans plusieurs projets différent sans impacter le système sur lequel le tout est installé.
Black
~~~~~
`Site officiel <https://black.readthedocs.io/en/stable/>`__
Pour faciliter la lecture du code, il est toujours appréciable d'avoir une norme d'écriture cohérente. C'est généralement à l'étape de relecture des modifications par les autres contributeurs que sont repérées ces fautes de normes qui se doivent d'être corrigées pour le bien commun.
Imposer une norme est très fastidieux, que ce soit pour ceux qui relisent ou pour ceux qui écrivent. C'est pour cela que nous utilisons black qui est un formateur automatique de code. Une fois l'outil lancé, il parcours la codebase pour y repérer les fautes de norme et les corrige automatiquement sans que l'utilisateur ai à s'en soucier. Bien installé, il peut effectuer ce travail à chaque sauvegarde d'un fichier dans son éditeur, ce qui est très agréable pour travailler.

36
doc/about/versioning.rst Normal file
View File

@ -0,0 +1,36 @@
Le versioning
=============
Dans le monde du développement, nous faisons face à un problème relativement étrange pour un domaine aussi avancé : on est brouillon.
On teste, on envoie, ça marche pas, on reteste, c'est ok. Par contre, on a oublie plein d'exceptions. Et on refactor. Ça marche mieux mais c'est moins rapide, etc, etc.
Et derrière tout ça, on fait des trucs qui marchent puis on se retrouve dans la mouise parce qu'on a effacé un morceau de code qui nous aurait servi plus tard.
Pour palier à ce problème, le programmeur a créé un principe révolutionnaire (ouais... à mon avis, on s'est inspiré d'autres trucs, mais on va dire que c'est nous les créateurs) : le Versioning (*Apparition inexpliquée*).
D'après projet-isika (c'est pas wikipedia ouais, ils étaient pas clairs eux), le versioning (ou versionnage en français mais c'est quand même vachement dégueu comme mot) consiste à travailler directement sur le code source d'un projet, en gardant toutes les versions précédentes. Les outils du versioning aident les développeurs à travailler parallèlement sur différentes parties du projet et à revenir facilement aux étapes précédentes de leur travail en cas de besoin. Lutilisation dun logiciel de versioning est devenue quasi-indispensable pour tout développeur, même sil travaille seul.
Un versioning pour les gouverner tous
-------------------------------------
On va vite fait passer sur les différents logiciels de contrôle de version avant de revenir à l'essentiel, le vrai, le beau, l'unique et l'ultime : Git.
**Source Code Control System (SCCS)**) : Développé en 1972 dans les labos d'IBM, il a été porté sur Unix pour ensuite donner naissance à RCS.
**GNU RCS (Revision Control System)** : RCS est à l'origine un projet universitaire, initié au début des années 1980, et maintenu pendant plus d'une décennie par Walter F. Tichy au sein de l'université Purdue.
Ce logiciel représente à l'époque une alternative libre au système SCCS, et une évolution technique, notamment par son interface utilisateur, plus conviviale, et une récupération des données, plus rapide, par l'amélioration du stockage des différentes versions. Ce gain de performance provient d'un algorithme appelé en anglais « reverse differences » (ou plus simplement « deltas ») et consiste à stocker la copie complète des versions les plus récentes et conserver uniquement les changements réalisés.
**CVS (Concurrent Versions System)** : En gros, c'est la première fois qu'on essaie de fusionner des versions *concurrentes* (dis-donc, quel hasard que ce soit des concurrents vu le nom du système !) de fichiers sources. C'était pas forcément compliqué : en gros, il y avait un serveur qui prenait à chaque fois la dernière version de chaque fichier, les développeurs devaient toujours avoir la dernière version du fichier s'ils voulaient éditer celui-ci. Si c'était pas le cas, le serveur les envoyait paitre.
**SVN (Subversion)** : En gros, c'est comme CVS mais avec quelques améliorations du fait du refactoring complet fait par Apache. Subversion permet notamment le renommage et le déplacement de fichiers ou de répertoires sans en perdre l'historique. On a aussi un versioning sur les metadatas (genre les changements de permissions des fichiers.
**Git** : Enfin le voilà. Le versioning ultime. Créé par Linus Torvalds en 2005, il permet notamment au bordel qu'est Linux d'être maintenu par des développeurs du monde entier grâce à un système original de version : en gros, chaque ordinateur a une version du code source et il n'y a pas forcément un serveur central qui garde tout (et demande un compte à chaque fois. Bon, maintenant on est de retour au format minitel avec Github mais on va vous montrer comment s'en sortir). Il y a également un système de branche pour pouvoir gérer différentes versions du code en parallèle. Tout est fait sous forme de petits fichiers de versioning qui vont faire des copies des fichiers correspondant à la modification proposée. Bref, c'est trop bien et on a pas fait mieux.
C'est pas forcément utile de comprendre le fonctionnement interne de Git pour développer (la preuve, je n'ai pas franchement chercher au tréfond du bousin) mais c'est en revanche indispensable de comprendre comment l'utiliser avant de faire n'importe quoi. Du coup, on va voir ci-dessous comment utiliser Git et comment on l'utilise sur le site AE.
TLDR
----
Un système de versioning permet de faire de la merde dans votre code et de pouvoir revenir en arrière malgré tout. Ça permet aussi de coder à plusieurs.
Git est le meilleur système de gestion de version (ou système de versioning) que vous pourrez trouver à l'heure actuelle. Utilisez-le.

7
doc/apps/core.rst Normal file
View File

@ -0,0 +1,7 @@
Documentation de core
=====================
.. toctree::
:maxdepth: 2
core/models.rst

4
doc/apps/core/models.rst Normal file
View File

@ -0,0 +1,4 @@
Classes liées aux utilisateurs
==============================
.. autoclass:: core.models.User

64
doc/conf.py Normal file
View File

@ -0,0 +1,64 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
import django
sys.path.insert(0, os.path.abspath(".."))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sith.settings")
django.setup()
# -- Project information -----------------------------------------------------
project = "Sith AE UTBM"
copyright = (
"2019, Bartuccio Antoine (Sli), Brunet Pierre (Krohpil), Jacquet Florent (Skia)"
)
author = "Bartuccio Antoine (Sli), Brunet Pierre (Krohpil), Jacquet Florent (Skia)"
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ["sphinx.ext.autodoc", "sphinx_copybutton", "sphinx.ext.autosectionlabel"]
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = "fr"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "sphinx_rtd_theme"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]

4
doc/contacts Normal file
View File

@ -0,0 +1,4 @@
Contacts de la banque pour pouvoir coder et mettre en place la boutique en ligne:
* Marc Delfils : Marc.DELFILS@ca-franchecomte.fr
* Estelle Mesny : Estelle.MESNY@ca-franchecomte.fr

87
doc/devenv/populate.rst Normal file
View File

@ -0,0 +1,87 @@
Générer l'environnement avec populate
=====================================
Lors de l'installation du site en local (via la commande `setup`), la commande **populate** est appelée.
Cette commande génère entièrement la base de données de développement. Elle se situe dans `core/management/commands/populate.py`.
Utilisations :
.. code-block:: shell
./manage.py setup # Génère la base de test
./manage.py setup --prod # Ne génère que le schéma de base et les données strictement nécessaires au fonctionnement
Les données générées du site dev
================================
Par défaut, la base de données du site de prod contient des données nécessaires au fonctionnement du site comme les groupes (voir :ref:`groups-list`), un utilisateur root, les clubs de base et quelques autres instances indispensables. En plus de ces données par défaut, la base de données du site de dev contient des données de test (*fixtures*) pour remplir le site et le rendre exploitable.
**Voici les clubs générés pour le site de dev :**
* AE
- Bibo'UT
- Carte AE
- Guy'UT
+ Woenzel'UT
- Troll Penché
* BdF
* Laverie
**Voici utilisateurs générés pour le site de dev :**
Le mot de passe de tous les utilisateurs est **plop**.
* **root** -> Dans le groupe Root et cotisant
* **skia** -> responsable info AE et cotisant, barmen MDE
* **public** -> utilisateur non cotisant et sans groupe
* **subscriber** -> utilisateur cotisant et sans groupe
* **old_subscriber** -> utilisateur anciennement cotisant et sans groupe
* **counter** -> administrateur comptoir
* **comptable** -> administrateur comptabilité
* **guy** -> utilisateur non cotisant et sans groupe
* **rbatsbak** -> utilisateur non cotisant et sans groupe
* **sli** -> cotisant avec carte étudiante attachée au compte, barmen MDE
* **krophil** -> cotisant avec des plein d'écocups, barmen foyer
* **comunity** -> administrateur communication
* **tutu** -> administrateur pédagogie
Ajouter des fixtures
====================
.. role:: python(code)
:language: python
Les fixtures sont contenus dans *core/management/commands/populate.py* après la ligne 205 : :python:`if not options["prod"]:`.
Pour ajouter une fixtures, il faut :
* importer la classe à instancier en début de fichier
* créer un objet avec les attributs nécessaires en fin de fichier
* enregistrer l'objet dans la base de données
.. code-block:: python
# Exemple pour ajouter un utilisateur
# Importation de la classe
import core.models import User
# [...]
# Création de l'objet
jesus = User(
username="jc",
last_name="Jesus",
first_name="Christ",
email="son@god.cloud",
date_of_birth="2020-24-12",
is_superuser=False,
is_staff=True,
)
jesus.set_password("plop")
# Enregistrement dans la base de donnée
jesus.save()

View File

@ -0,0 +1,55 @@
.. _add_subscription:
Ajouter une nouvelle cotisation
===============================
Il arrive régulièrement que le type de cotisation proposé varie en prix et en durée au cours des années. Le projet étant pensé pour être utilisé par d'autres associations dans la mesure du possible, ces cotisations sont configurables directement dans les paramètres du projet.
Comprendre la configuration
---------------------------
Pour modifier les cotisations disponnibles, tout se gère dans la configuration avec la variable *SITH_SUBSCRIPTIONS*. Dans cet exemple, nous allons ajouter une nouvelle cotisation d'un mois.
.. code-block:: python
from django.utils.translation import gettext_lazy as _
SITH_SUBSCRIPTIONS = {
# Voici un échantillon de la véritable configuration à l'heure de l'écriture.
# Celle-ci est donnée à titre d'exemple pour mieux comprendre comment cela fonctionne.
"un-semestre": {"name": _("One semester"), "price": 15, "duration": 1},
"deux-semestres": {"name": _("Two semesters"), "price": 28, "duration": 2},
"cursus-tronc-commun": {
"name": _("Common core cursus"),
"price": 45,
"duration": 4,
},
"cursus-branche": {"name": _("Branch cursus"), "price": 45, "duration": 6},
"cursus-alternant": {"name": _("Alternating cursus"), "price": 30, "duration": 6},
"membre-honoraire": {"name": _("Honorary member"), "price": 0, "duration": 666},
"un-jour": {"name": _("One day"), "price": 0, "duration": 0.00555333},
# On rajoute ici notre cotisation
# Elle se nomme "Un mois"
# Coûte 6€
# Dure 1 mois (on résonne en semestre, ici c'est 1/6 de semestre)
"un-mois": {"name": _("One month"), "price": 6, "duration": 0.166}
}
Créer une migration
-------------------
La modification de ce paramètre est étroitement lié à la génération de la base de données. Cette variable est utilisé dans l'objet *Subscription* pour générer les *subscription_type*. Le modifier requiers de générer une migration de basse de données.
.. code-block:: bash
./manage.py makemigrations subscription
.. note::
N'oubliez pas d'appliquer black sur le fichier de migration généré.
Rajouter la traduction pour la cotisation
-----------------------------------------
Comme on peut l'observer, la cotisation a besoin d'un nom qui est internationalisé. Il est donc nécessaire de le traduire en français. Pour rajouter notre traduction de *"One month"* il faut se référer à cette partie de la documentation : :ref:`translations`.

53
doc/frequent/weekmail.rst Normal file
View File

@ -0,0 +1,53 @@
Modifier le weekmail
====================
Le site est capable de générer des mails automatiques composé de lagrégation d'articles composé par les administrateurs de clubs. Le contenu est inséré dans un template standardisé et contrôlé directement dans le code. Il arrive régulièrement que l'équipe communication souhaite modifier ce template. Que ce soit les couleurs, l'agencement ou encore la bannière ou le footer, voici tout ce qu'il y a à savoir sur le fonctionnement du weekmail en commençant par la classe qui le contrôle.
.. autoclass:: com.models.Weekmail
:members:
Modifier la bannière et le footer
---------------------------------
Comme on peut l'observer plus haut, ces éléments sont contrôlés par les méthodes *get_banner* et *get_footer* de la classe *Weekmail*. Les modifier est donc très simple, il suffit de modifier le contenu de la fonction et de rajouter les nouvelles images dans les statics.
Les images sont à ajouter dans dans **core/static/com/img** et sont à nommer selon le type (banner ou footer), le semestre (Automne ou Printemps) et l'année.
Exemple : *weekmail_bannerA18.jpg* pour la bannière de l'automne 2018.
.. code-block:: python
# Sélectionner le fichier de bannière pour le weekmail de l'automne 2018
def get_banner(self):
return "http://" + settings.SITH_URL + static("com/img/weekmail_bannerA18.jpg")
.. note::
Penser à prendre les images au format **jpg** et que les images soient le plus léger possible, c'est bien mieux pour l'utilisateur final.
.. note::
Pensez à laisser les anciennes images dans le dossier pour que les anciens weekmails ne soient pas affectés par les changements.
Modifier le template
--------------------
Comme on peut le voir dans la documentation de la classe, il existe deux templates différents. Un des templates est en texte pur et sert pour le rendu dégradé des lecteurs de mails ne supportant pas le HTML et un autre fait un rendu en HTML.
Ces deux templates sont respectivement accessibles aux emplacements suivants :
* com/templates/com/weekmail_renderer_html.jinja
* com/templates/com/weekmail_renderer_text.jinja
.. note::
Pour le rendu HTML, pensez à utiliser le CSS et le javascript le plus simple possible pour que le rendu se fasse correctement dans les clients mails qui sont souvent capricieux.
.. note::
Le CSS est inclus statiquement pour que toute modification ultérieure de celui-ci n'affecte pas les versions précédemment envoyées.
.. warning::
Si vous souhaitez ajouter du contenu, n'oubliez pas de bien inclure ce contenu dans les deux templates.

24
doc/header Normal file
View File

@ -0,0 +1,24 @@
# -*- coding:utf-8 -*
#
# Copyright 2016,2017
# - Skia <skia@libskia.so>
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License a published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#

101
doc/index.rst Normal file
View File

@ -0,0 +1,101 @@
.. Sith AE UTBM documentation master file, created by
sphinx-quickstart on Thu Aug 8 19:24:14 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Bienvenue sur la documentation du Sith de l'AE
==============================================
.. include:: ../README.rst
.. toctree::
:maxdepth: 2
:caption: À propos du projet:
about/introduction
about/tech
about/versioning
.. toctree::
:maxdepth: 2
:caption: Bien démarrer
start/install
start/structure
start/hello_world
start/translations
start/devtools
.. toctree::
:maxdepth: 2
:caption: La surcouche "Site AE"
overlay/rights
overlay/groups
.. toctree::
:maxdepth: 2
:caption: Contenu de l'environnement de développement
devenv/populate
.. toctree::
:maxdepth: 1
:caption: Modifications fréquentes
frequent/subscriptions
frequent/weekmail
.. toctree::
:maxdepth: 3
:caption: Documentation des apps
apps/core
.. toctree::
:maxdepth: 2
:caption: Divers
misc/md_syntax
misc/helpers
misc/direnv
misc/prod
Documentations complémentaires
------------------------------
Python et Django
~~~~~~~~~~~~~~~~
* `Apprendre Python <https://openclassrooms.com/fr/courses/235344-apprenez-a-programmer-en-python>`__
* `Apprendre Django <https://openclassrooms.com/fr/courses/1871271-developpez-votre-site-web-avec-le-framework-django>`__
* `Documentation de Django <https://docs.djangoproject.com/fr/1.11/>`__
* `Classy Class-Based Views <http://ccbv.co.uk/projects/Django/1.11/>`__
HTML/Jinja/JS/(S)CSS
~~~~~~~~~~~~~~~~~~~~
* `Cours sur le javascript <https://openclassrooms.com/fr/courses/2984401-apprenez-a-coder-avec-javascript>`__
* `Cours sur jQuery <https://openclassrooms.com/fr/courses/1631636-simplifiez-vos-developpements-javascript-avec-jquery>`__
* `Cours sur le HTML et CSS <https://openclassrooms.com/fr/courses/1631636-simplifiez-vos-developpements-javascript-avec-jquery>`__
* `Documentation sur les grilles CSS <https://developer.mozilla.org/fr/docs/Web/CSS/CSS_Grid_Layout>`__
* `Guide pour le SASS <https://sass-lang.com/guide>`__
* `Documentation de fontawesome <https://fontawesome.com/how-to-use/on-the-web/referencing-icons/basic-use>`__
* `Documentation pour Jinja2 <https://jinja.palletsprojects.com/en/2.10.x/>`__
Git
~~~
* `Cours sur Git <https://openclassrooms.com/fr/courses/2342361-gerez-votre-code-avec-git-et-github>`__
* `Livre sur Git <http://www.git-scm.com/book/fr/v2>`__
Documents téléchargeables
-------------------------
* :download:`Rapport de la TW de Skia sur la création du site <TW_Skia/Rapport.pdf>`
* :download:`Rapport sur la TO de Skia et LoJ <TO_Skia_LoJ/Rapport.pdf>`
* :download:`Manuel du service E-transactions <Etransaction/Manuel_Integration_E-transactions_Internet_V6.6_FR.pdf>`
* :download:`Guide de trésorerie <Guide de Tresorerie.pdf>`

35
doc/make.bat Normal file
View File

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

31
doc/misc/direnv.rst Normal file
View File

@ -0,0 +1,31 @@
.. _direnv:
Utiliser direnv
===============
Pour éviter d'avoir à sourcer l'environnement à chaque fois qu'on rentre dans le projet, il est possible d'utiliser l'utilitaire `direnv <https://direnv.net/>`__.
.. sourcecode:: bash
# Installation de l'utilitaire
# Debian et Ubuntu
sudo apt install direnv
# Mac
brew install direnv
# Installation dans la config
# Si sur bash
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
# Si sur ZSH
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc
exit # On redémarre le terminal
# Une fois dans le dossier du projet site AE
direnv allow .
Une fois que cette configuration a été appliquée, aller dans le dossier du site applique automatiquement l'environnement virtuel, cela fait beaucoup moins de temps perdu pour tout le monde.
Direnv est un utilitaire très puissant et qui peut s'avérer pratique dans bien des situations, n'hésitez pas à aller vous renseigner plus en détail sur celui-ci.

17
doc/misc/helpers.rst Normal file
View File

@ -0,0 +1,17 @@
Commandes utiles
================
Appliquer le header de licence sur tout le projet
-------------------------------------------------
.. code-block:: bash
for f in $(find . -name "*.py" ! -path "*migration*" ! -path "./env/*" ! -path "./doc/*"); do cat ./doc/header "$f" > /tmp/temp && mv /tmp/temp "$f"; done
Compter le nombre de lignes de code
-----------------------------------
.. code-block:: bash
sudo apt install cloc
cloc --exclude-dir=doc,env .

Some files were not shown because too many files have changed in this diff Show More