project:administrativa
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| project:administrativa [2012/10/18 21:52] – pasky | project:administrativa [2025/03/13 14:20] (current) – fix templatere plugin invocation root | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== BrmBüro ====== | ||
| + | <note warning> | ||
| + | |||
| + | {{template> | ||
| + | name=Institute of Cryptobureaucracy| | ||
| + | image=administrativa.jpg? | ||
| + | founder=[[user: | ||
| + | interested=[[user: | ||
| + | sw=Apache+PHP+Postgres| | ||
| + | hw=N/A| | ||
| + | status=active}} | ||
| + | |||
| + | {{: | ||
| + | |||
| + | **brmlab** existence involves some mundane adminsitrativa tasks, mainly tracking of membership fees and donations. So far, this is done manually and there result is a lot of laborous work and a lot of chaos. | ||
| + | |||
| + | Therefore, some simple software tool would do us a lot of good. It should: | ||
| + | |||
| + | * Track members database - including personal, payment and access information | ||
| + | * Can also provide LDAP interface for UNIX auth, automatically flash brmdoor, etc. | ||
| + | * Track payments made to our bank accounts and tie them to the members database | ||
| + | * We already have small accounting system implemented for our [[project: | ||
| + | * Project our current and expected financial balance so that we know how much we can our incomes expect to be (and compare them to our expenses) | ||
| + | * Keep the "paid until" attribute up-to-date and automatically send notifications and reminders in case payment is due | ||
| + | * Produce reports and donation certificates for tax purposes | ||
| + | |||
| + | ===== Status and Roadmap ===== | ||
| + | |||
| + | * Design and deploy dedicated members database instead of in-wiki membership roster | ||
| + | * [TODO] Where do we deploy it? brmko? Or somewhere " | ||
| + | * [TODO] SQL schema design; for starters, the information currently in membership roster | ||
| + | * [TODO] Simple web interface for querying and modifying the database | ||
| + | * Include accounting information in the database | ||
| + | * [TODO] Extend SQL schema to track incomes from members (or otherwise) | ||
| + | * [TODO] Gateway Fio e-mail notifications to the database | ||
| + | * [TODO] Automatic " | ||
| + | * [TODO] Automatic donation tax receipt generator | ||
| + | * [TODO] Simple " | ||
| + | * [not finished] LDAP interface for UNIX authentication | ||
| + | * slapd partialy configured on data.brm. scheme improvements needed | ||
| + | * [TODO] Possibly also some expense tracking and some-such | ||
| + | |||
| + | ===== General Architectural Overview ===== | ||
| + | |||
| + | <note important> | ||
| + | |||
| + | {{: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | ===== SW ===== | ||
| + | * Sklad: https:// | ||
| + | |||
| + | ==== Evidence plateb v bankovnictvi ==== | ||
| + | |||
| + | <code perl platby.pl> | ||
| + | # | ||
| + | |||
| + | # Copyright 2012 TMA | ||
| + | # License: GNU GPL version 2 | ||
| + | |||
| + | use strict; | ||
| + | use warnings; | ||
| + | use utf8; | ||
| + | |||
| + | my $status = ' | ||
| + | |||
| + | my ($fio, | ||
| + | my ($header, $body); | ||
| + | |||
| + | my $mul; | ||
| + | |||
| + | sub vreset() { | ||
| + | ($header, | ||
| + | ($fio, | ||
| + | } | ||
| + | |||
| + | sub process($) { | ||
| + | $status = $_[0]; | ||
| + | no warnings; | ||
| + | $date =~ s/ +\d+: | ||
| + | $date =~ s/^..., *(\d+) (...|\d+) (\d\d\d\d).*/ | ||
| + | $date =~ s/Jan/01/o; | ||
| + | $date =~ s/Feb/02/o; | ||
| + | $date =~ s/Mar/03/o; | ||
| + | $date =~ s/Apr/04/o; | ||
| + | $date =~ s/May/05/o; | ||
| + | $date =~ s/Jun/06/o; | ||
| + | $date =~ s/Jul/07/o; | ||
| + | $date =~ s/Aug/08/o; | ||
| + | $date =~ s/Sep/09/o; | ||
| + | $date =~ s/Oct/10/o; | ||
| + | $date =~ s/Nov/11/o; | ||
| + | $date =~ s/Dec/12/o; | ||
| + | $date =~ s/ /0/o; | ||
| + | $date =~ s/ | ||
| + | $date =~ s/ | ||
| + | print "-- $ARGV $.\n"; | ||
| + | print " | ||
| + | ($konto, $castka", | ||
| + | commanull($VS), | ||
| + | commanullq($zprava), | ||
| + | } | ||
| + | |||
| + | sub def_or_empty($) { defined$_[0]? | ||
| + | |||
| + | sub quot($) { | ||
| + | my ($x) = @_; | ||
| + | # ' needs to be doubled | ||
| + | $x =~ s/'/''/ | ||
| + | # replace suspicious characters by . | ||
| + | $x =~ s{[^][\na-zA-Z0-9 !@# | ||
| + | "' | ||
| + | } | ||
| + | |||
| + | sub commanull_($& | ||
| + | my ($x, $q) = (@_); | ||
| + | #print STDERR " | ||
| + | no warnings; | ||
| + | (length $x) ? ", ". $q->($x) : ", NULL" | ||
| + | } | ||
| + | |||
| + | sub commanull($) { commanull_($_[0], | ||
| + | |||
| + | sub commanullq($) { commanull_($_[0], | ||
| + | |||
| + | sub decimal($) { | ||
| + | my ($x) = @_; | ||
| + | $x =~ y/,/./; | ||
| + | $x =~ s/ //g; | ||
| + | $x | ||
| + | } | ||
| + | |||
| + | my %action = ( | ||
| + | endmail => sub { | ||
| + | #print " | ||
| + | /^From / and do {{ $status = ' | ||
| + | }, | ||
| + | header => sub { | ||
| + | $header .= $_." | ||
| + | #print " | ||
| + | /^From: automat(?: | ||
| + | /^$/ and $status = ($fio ? ' | ||
| + | /^Date: (.*)/ and $date = $1; | ||
| + | #print " | ||
| + | }, | ||
| + | body => sub { | ||
| + | /^From / or $body .= $_." | ||
| + | #print " | ||
| + | /^P..jem na kont.: (\d+)/ and ($konto, $mul) = ($1,1); | ||
| + | /^V.daj na kont.: (\d+)/ and ($konto, $mul) = ($1,-1); | ||
| + | /^..stka: ([0-9 ]+[, | ||
| + | /^VS: (\d+)/ and $VS = $1; | ||
| + | /^SS: (\d*)/ and $SS = $1; | ||
| + | /^Zpr.va p..jemci: (.*)/ and $zprava = $1; | ||
| + | / | ||
| + | /_____/ and process(' | ||
| + | /^From / and (process(' | ||
| + | #/ | ||
| + | #/ | ||
| + | #/^VS: (\d+)/ and $VS = $1; | ||
| + | #/^SS: (\d*)/ and $SS = $1; | ||
| + | #/ | ||
| + | #/ | ||
| + | #/_____/ and process; | ||
| + | } | ||
| + | ); | ||
| + | |||
| + | my ($drop, | ||
| + | my $SEP = ';'; | ||
| + | print <<EOF if $drop; | ||
| + | drop table if exists ucetni_data; | ||
| + | EOF | ||
| + | print <<EOF if $create; | ||
| + | CREATE TABLE IF NOT EXISTS ucetni_data ( | ||
| + | `id` int(11) NOT NULL AUTO_INCREMENT, | ||
| + | `konto` decimal(30, | ||
| + | `castka` decimal(30, | ||
| + | `datum` date NOT NULL, | ||
| + | `vs` int(11) DEFAULT NULL, | ||
| + | `ss` int(11) DEFAULT NULL, | ||
| + | `protiucet` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, | ||
| + | `zprava` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, | ||
| + | `comment` varchar(2000) COLLATE utf8_unicode_ci DEFAULT NULL, | ||
| + | PRIMARY KEY (`id`) | ||
| + | ) ENGINE=InnoDB | ||
| + | EOF | ||
| + | |||
| + | while (<>) { | ||
| + | chomp; | ||
| + | $action{$status}-> | ||
| + | } | ||
| + | |||
| + | process('' | ||
| + | </ | ||
| + | |||
| + | ==== Hlasování na VH ==== | ||
| + | |||
| + | <code perl hlas.pl> | ||
| + | # | ||
| + | |||
| + | # Copyright TMA 2014 | ||
| + | # Brmlab can use this free of charge as long as TMA is member. For other licensing options contact the author. | ||
| + | |||
| + | use strict; | ||
| + | use warnings; | ||
| + | use Data:: | ||
| + | |||
| + | my $x = 1; | ||
| + | # pocet volenych papalasu | ||
| + | my $funkci; | ||
| + | # prave voleny papalas | ||
| + | my $voleny_papalas = 0; | ||
| + | # kandidati na papalase | ||
| + | my @kand = (undef,); | ||
| + | # listky pro papalase | ||
| + | my @listky; | ||
| + | # stav programu | ||
| + | my $st; | ||
| + | # pocet listku a neplatnych | ||
| + | my ($listky, $neplatne_listky) = (0,0); | ||
| + | # stavova masina | ||
| + | my %sm; | ||
| + | %sm = ( | ||
| + | start => sub { | ||
| + | $funkci = $_; | ||
| + | return ' | ||
| + | }, | ||
| + | kand => sub { | ||
| + | return ' | ||
| + | push @kand,$_; | ||
| + | return ' | ||
| + | }, | ||
| + | listky => sub { | ||
| + | return ' | ||
| + | my $listek = [0,split]; | ||
| + | # doplnit nuly na konci listku | ||
| + | my @tmp = (0,) x scalar @kand; | ||
| + | @tmp[0 .. $#$listek] = @$listek; | ||
| + | $listek = [ @tmp ]; | ||
| + | # je listek platny? | ||
| + | my $ok = /^[0-9 ]*1[0-9 ]*$/; | ||
| + | @tmp = sort {$a< | ||
| + | my $i = 0; | ||
| + | # | ||
| + | while ($ok && scalar @tmp) { | ||
| + | #print "@tmp $i $ok\n"; | ||
| + | $ok = (++$i == shift@tmp); | ||
| + | } | ||
| + | # | ||
| + | #print "$ok listek $_\n"; | ||
| + | ++$neplatne_listky unless $ok; | ||
| + | ++$listky; | ||
| + | push @listky, $listek if $ok; | ||
| + | |||
| + | return ' | ||
| + | }, | ||
| + | volby => sub { | ||
| + | die "Nebyl odevzdan ani jeden platny hlasovaci listek." | ||
| + | #print Dumper(\@listky); | ||
| + | if (++$voleny_papalas > $funkci) { | ||
| + | exit; | ||
| + | } | ||
| + | my $kolo = 1; | ||
| + | my $papalas = undef; | ||
| + | my $max; | ||
| + | for my $i (1 .. $#kand) { | ||
| + | local$" | ||
| + | my @kandidat = prepocti($i); | ||
| + | #print "kolo $i, @kandidat\n"; | ||
| + | } | ||
| + | while ($kolo <= $#kand) { | ||
| + | my @kandidat = prepocti($kolo); | ||
| + | #print Dumper(kandidat=> | ||
| + | ($max, | ||
| + | for my $i (1 .. $#kandidat) { | ||
| + | if ($max < $kandidat[$i]) { | ||
| + | $max = $kandidat[$i]; | ||
| + | $papalas = $i; | ||
| + | } elsif ($max == $kandidat[$i]) { | ||
| + | undef $papalas; | ||
| + | } | ||
| + | } | ||
| + | # | ||
| + | last if defined $papalas; | ||
| + | # | ||
| + | $kolo++; | ||
| + | } | ||
| + | if (defined $papalas) { | ||
| + | print "Byl zvolen $kand[$papalas] v $kolo. kole volby poctem $max hlasu.\n"; | ||
| + | uprav($papalas); | ||
| + | $sm{volby}-> | ||
| + | } else { | ||
| + | $papalas = $_; | ||
| + | die "Chybi zaznam o losovani." | ||
| + | print "Byl vylosovan $kand[$papalas].\n"; | ||
| + | uprav($papalas); | ||
| + | } | ||
| + | return ' | ||
| + | }, | ||
| + | ); | ||
| + | $st = $sm{start}; | ||
| + | sub prepocti($) { | ||
| + | my ($kolo,) = (@_); | ||
| + | my @kandidat = (0,) x $#kand; | ||
| + | for my $listek (@listky) { | ||
| + | #{no warnings; | ||
| + | for my $i (1 .. $#$listek) { | ||
| + | ++$kandidat[int$i] if $listek-> | ||
| + | } | ||
| + | } | ||
| + | return @kandidat; | ||
| + | } | ||
| + | sub uprav($) { | ||
| + | my ($papalas,) = (@_); | ||
| + | for my $listek (@listky) { | ||
| + | #{no warnings; | ||
| + | # | ||
| + | my $poradi = $listek-> | ||
| + | next if $poradi == 0; | ||
| + | for my $i (1 .. $#$listek) { | ||
| + | $listek-> | ||
| + | } | ||
| + | $listek-> | ||
| + | # | ||
| + | } | ||
| + | } | ||
| + | |||
| + | while (<>) { | ||
| + | chomp; | ||
| + | $st = $sm{$st-> | ||
| + | } | ||
| + | END { | ||
| + | print " | ||
| + | my $platne_listky = $listky - $neplatne_listky; | ||
| + | print "Z toho $neplatne_listky hlasovacich listku neplatnych a $platne_listky platnych.\n"; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Priklad pouziti: | ||
| + | |||
| + | < | ||
| + | 2 | ||
| + | TMA | ||
| + | Mrkva | ||
| + | |||
| + | 0 1 | ||
| + | 1 2 | ||
| + | 2 1 | ||
| + | |||
| + | 0 | ||
| + | </ | ||
| + | |||
| + | (Pred posledni nulu je mozno vlozit radek s cislem vylosovaneho kandidata, je-li treba losovat.) | ||