Initial commit
This commit is contained in:
commit
f6d262ab8a
|
@ -0,0 +1,3 @@
|
|||
include VERSION
|
||||
include MANIFEST
|
||||
prune synchro/data/migrations
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from distutils.command.sdist import sdist
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
VERSION='0.1'
|
||||
|
||||
def get_version():
|
||||
if os.path.exists('VERSION'):
|
||||
version_file = open('VERSION', 'r')
|
||||
version = version_file.read()
|
||||
version_file.close()
|
||||
return version
|
||||
if os.path.exists('.git'):
|
||||
p = subprocess.Popen(['git','describe','--dirty'], stdout=subprocess.PIPE)
|
||||
result = p.communicate()[0]
|
||||
return result.split()[0].replace('-','.')
|
||||
return VERSION
|
||||
|
||||
|
||||
class eo_sdist(sdist):
|
||||
|
||||
def run(self):
|
||||
print "creating VERSION file"
|
||||
if os.path.exists('VERSION'):
|
||||
os.remove('VERSION')
|
||||
version = get_version()
|
||||
version_file = open('VERSION', 'w')
|
||||
version_file.write(version)
|
||||
version_file.close()
|
||||
sdist.run(self)
|
||||
print "removing VERSION file"
|
||||
if os.path.exists('VERSION'):
|
||||
os.remove('VERSION')
|
||||
|
||||
setup(name='synchro-orleans',
|
||||
version=get_version(),
|
||||
license='AGPLv3',
|
||||
description='',
|
||||
url='https://dev.entrouvert.org/projects/orleans',
|
||||
download_url='ssh://git@repos.entrouvert.org/orleans.git',
|
||||
author="Entr'ouvert",
|
||||
author_email="info@entrouvert.com",
|
||||
packages=find_packages(os.path.dirname(__file__) or '.'),
|
||||
scripts=['synchro-orleans-manage.py'],
|
||||
include_package_data = True,
|
||||
install_requires=[
|
||||
'django >= 1.5.1, < 1.6',
|
||||
'south >= 0.8, < 0.9',
|
||||
],
|
||||
cmdclass={'sdist': eo_sdist},
|
||||
)
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "synchro.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
|
@ -0,0 +1,50 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from models import Personne, Famille, Facture, Enfant, LiaisonNameidFamille
|
||||
|
||||
|
||||
class PersonnesInline(admin.TabularInline):
|
||||
model = Famille.personnes.through
|
||||
verbose_name_plural = u'Parents'
|
||||
raw_id_fields = ('personne',)
|
||||
|
||||
class KidsInline(admin.TabularInline):
|
||||
model = Enfant
|
||||
verbose_name_plural = u'Enfants'
|
||||
extra = 2
|
||||
|
||||
class FamilleAdmin(admin.ModelAdmin):
|
||||
inlines = [PersonnesInline, KidsInline]
|
||||
exclude = ('personnes', )
|
||||
|
||||
admin.site.register(Famille, FamilleAdmin)
|
||||
|
||||
|
||||
class PersonneAdmin(admin.ModelAdmin):
|
||||
search_fields = ['id', 'nom', 'prenom']
|
||||
list_display = ('id', 'nom', 'prenom', 'sexe')
|
||||
list_filter = ['sexe']
|
||||
|
||||
admin.site.register(Personne, PersonneAdmin)
|
||||
|
||||
|
||||
class EnfantAdmin(admin.ModelAdmin):
|
||||
search_fields = ['id', 'nom', 'prenom']
|
||||
list_display = ('id', 'nom', 'prenom', 'sexe', 'date_naissance', 'famille')
|
||||
list_filter = ['sexe', 'date_naissance']
|
||||
raw_id_fields = ('famille',)
|
||||
|
||||
admin.site.register(Enfant, EnfantAdmin)
|
||||
|
||||
class LiaisonNameidFamilleAdmin(admin.ModelAdmin):
|
||||
list_display = ('name_id', 'famille', 'link_date')
|
||||
search_fields = ('name_id',)
|
||||
raw_id_fields = ('famille', )
|
||||
|
||||
class FactureAdmin(admin.ModelAdmin):
|
||||
list_display = ('id', 'date_generation', 'date_limite_paie', 'prelevement_automatique', 'famille', 'montant', 'solde', 'active',)
|
||||
list_filter = ['prelevement_automatique', 'date_generation', 'date_limite_paie',]
|
||||
raw_id_fields = ('famille',)
|
||||
|
||||
admin.site.register(Facture, FactureAdmin)
|
||||
admin.site.register(LiaisonNameidFamille, LiaisonNameidFamilleAdmin)
|
|
@ -0,0 +1,22 @@
|
|||
from os import path
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db.models import get_model
|
||||
from django.conf import settings
|
||||
|
||||
from synchro.data.models import Facture
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
||||
help = """Synchronizes the invoices state: if a file corresponding to a
|
||||
invoice is present the invoice becomes active and inactive if not."""
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
||||
for invoice in Facture.objects.all():
|
||||
active = path.exists(settings.INVOICES_LOCATION_PATTERN.format(invoice_id = invoice.id))
|
||||
|
||||
if active != invoice.active:
|
||||
invoice.active = active
|
||||
invoice.save()
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db.models import get_model
|
||||
from django.conf import settings
|
||||
|
||||
from optparse import make_option
|
||||
from os import path
|
||||
from glob import glob
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Synchronises the database with CSV the exports from Concerto'
|
||||
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option('-s', '--source', dest = 'source',
|
||||
help = """directory containing the source CSV files.
|
||||
Should also contain a subdirectory called 'pdf' with the files respecting the
|
||||
pattern 'facture-xxx.pdf', where 'xxx' is the invoice number
|
||||
"""
|
||||
),
|
||||
)
|
||||
|
||||
option_list = option_list + (
|
||||
make_option('-d', '--database', dest = 'database',
|
||||
help = 'database the data will be imported into',
|
||||
),
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
source = options['source']
|
||||
database = options['database']
|
||||
|
||||
if database:
|
||||
settings.DATABASES['default']['NAME'] = database
|
||||
if not source:
|
||||
raise CommandError('specify the source directory with the option \'-s\'')
|
||||
|
||||
if path.exists(source):
|
||||
for source_file in map(lambda f: path.join(source, '%s.csv' % f),
|
||||
('personne', 'famille', 'enfant', 'facture')):
|
||||
file_name = path.basename(source_file)
|
||||
name, ext = path.splitext(file_name)
|
||||
model = get_model('data', name)
|
||||
if model:
|
||||
model.objects.synchronize(source_file)
|
||||
else:
|
||||
self.stdout.write('there is no model corresponding to file %s' % file_name)
|
||||
else:
|
||||
raise CommandError('the path %s doesn\'t exist' % source)
|
|
@ -0,0 +1,354 @@
|
|||
from csv import reader
|
||||
import shutil
|
||||
from os import path
|
||||
from datetime import datetime
|
||||
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
|
||||
SEXES = (
|
||||
('G', 'Homme'),
|
||||
('F', 'Femme'),
|
||||
)
|
||||
|
||||
BOOLEANS = {'O': True,
|
||||
'N': False
|
||||
}
|
||||
|
||||
INVOICES_DIR = 'factures'
|
||||
|
||||
INPUT_DATE_FORMAT = '%Y-%m-%d'
|
||||
|
||||
class PersonneManager(models.Manager):
|
||||
|
||||
attribute_mappings = {
|
||||
'ID_PER': 'id',
|
||||
'LIB_NOM_PERSONNE': 'nom',
|
||||
'LIB_PRENOM_PERSONNE': 'prenom',
|
||||
'TYP_SEXE': 'sexe',
|
||||
'NUM_TELDOM_PER': 'telephone_domicile',
|
||||
'NUM_TELPORT_PER': 'telephone_portable',
|
||||
'NUM_ALLOC_PER': 'numero_allocation',
|
||||
'LIB_NOM_ALL': 'regime',
|
||||
'LIB_NOM_CAI': 'cai',
|
||||
'LIB_PAYS': 'pays',
|
||||
'COD_POSTAL': 'code_postal',
|
||||
'LIB_COMMUNE': 'commune',
|
||||
'NUM_VOIE_ADR': 'voie',
|
||||
'NUM_BAT_ADR': 'batiment',
|
||||
'LIB_NOM_BTQ': 'btq',
|
||||
'NUM_APPT_ADR': 'appartement',
|
||||
'LIB_NOM_RUE': 'rue',
|
||||
'LIB_COMP_ADR': 'complement_adresse',
|
||||
}
|
||||
|
||||
def synchronize(self, source_file):
|
||||
|
||||
with open(source_file) as source:
|
||||
csv_reader = reader(source, delimiter = ';')
|
||||
caption = csv_reader.next()
|
||||
attrs = map(lambda e: self.attribute_mappings[e], caption)
|
||||
|
||||
for row in csv_reader:
|
||||
params = dict(zip(attrs, row))
|
||||
|
||||
# transform all inputs to unicode
|
||||
for key, value in params.iteritems():
|
||||
params[key] = value.decode('utf-8')
|
||||
|
||||
obj_id = params['id']
|
||||
try:
|
||||
obj = self.get(pk = obj_id)
|
||||
obj_id = params.pop('id')
|
||||
updated = False
|
||||
for attr, value in params.iteritems():
|
||||
if getattr(obj, attr) != value:
|
||||
setattr(obj, attr, value)
|
||||
updated = True
|
||||
if updated:
|
||||
print 'Updating person %s' % obj_id
|
||||
obj.save()
|
||||
except models.ObjectDoesNotExist:
|
||||
print 'Creating person %s' % obj_id
|
||||
self.create(**params)
|
||||
|
||||
class FamilleManager(models.Manager):
|
||||
|
||||
attribute_mappings = {
|
||||
'ID_FAM': 'id',
|
||||
'LOGIN': 'login',
|
||||
'PASSWORD': 'password',
|
||||
'COD_SECRET_FAM': 'code_secret',
|
||||
'QF_CCAS': 'qf_ccas',
|
||||
'QF_VO': 'qf_vo',
|
||||
'LIB_PAYS_ADR': 'pays',
|
||||
'COD_POSTAL_ADR': 'code_postal',
|
||||
'LIB_COMMUNE_ADR': 'commune',
|
||||
'NUM_VOIE_ADR': 'voie',
|
||||
'NUM_BAT_ADR': 'batiment',
|
||||
'LIB_NOM_BTQ': 'btq',
|
||||
'NUM_APPT_ADR': 'appartement',
|
||||
'LIB_NOM_RUE': 'rue',
|
||||
'LIB_COMP_ADR': 'complement_adresse',
|
||||
'NB_ENFANTS_CHARGE': 'nombre_enfants',
|
||||
'ID_PER1': 'pers1',
|
||||
'ID_PER2': 'pers2'
|
||||
}
|
||||
|
||||
def synchronize(self, source_file):
|
||||
|
||||
with open(source_file) as source:
|
||||
csv_reader = reader(source, delimiter = ';')
|
||||
caption = csv_reader.next()
|
||||
attrs = map(lambda e: self.attribute_mappings[e], caption)
|
||||
|
||||
for row in csv_reader:
|
||||
params = dict(zip(attrs, row))
|
||||
obj_id = params['id']
|
||||
pers1 = params.pop('pers1')
|
||||
pers2 = params.pop('pers2')
|
||||
|
||||
# transform all inputs to unicode
|
||||
for key, value in params.iteritems():
|
||||
params[key] = unicode(value, 'utf-8')
|
||||
|
||||
try:
|
||||
obj = self.get(pk = obj_id)
|
||||
obj_id = params.pop('id')
|
||||
updated = False
|
||||
for attr, value in params.iteritems():
|
||||
if getattr(obj, attr) != value:
|
||||
setattr(obj, attr, value)
|
||||
updated = True
|
||||
if updated:
|
||||
print 'Updating family %s' % obj_id
|
||||
obj.save()
|
||||
except models.ObjectDoesNotExist:
|
||||
print 'Creating family: %s' % obj_id
|
||||
obj = self.create(**params)
|
||||
|
||||
for person in (pers1, pers2):
|
||||
try:
|
||||
member = Personne.objects.get(pk = person)
|
||||
if not LiaisonParentFamille.objects.filter(famille = obj,
|
||||
personne = member):
|
||||
LiaisonParentFamille.objects.create(famille = obj,
|
||||
personne = member)
|
||||
except:
|
||||
pass
|
||||
|
||||
class FactureManager(models.Manager):
|
||||
|
||||
attribute_mappings = {
|
||||
'ID_FAC': 'id',
|
||||
'ID_FAM': 'famille',
|
||||
'MNT_FACTURE_FAC': 'montant',
|
||||
'TYP_MONNAIE_FAC': 'devise',
|
||||
'MNT_REGLE_FAC': 'montant_regle',
|
||||
'MNT_SOLDE_FAC': 'solde',
|
||||
'DAT_GENERATION_FAC': 'date_generation',
|
||||
'DAT_LIMITEPAIE_FAC': 'date_limite_paie',
|
||||
'LIB_PRENOM_PER_PAYEUR': 'prenom_payeur',
|
||||
'LIB_NOM_PER_PAYEUR': 'nom_payeur',
|
||||
'ON_PRELEVAUTO_INS': 'prelevement_automatique',
|
||||
'DAT_DEBUT_PGE': 'debut_pge',
|
||||
'DAT_FIN_PGE': 'fin_pge'
|
||||
}
|
||||
|
||||
def synchronize(self, source_file):
|
||||
|
||||
with open(source_file) as source:
|
||||
source_pdf_directory = path.join(path.dirname(source_file), INVOICES_DIR)
|
||||
csv_reader = reader(source, delimiter = ';')
|
||||
caption = csv_reader.next()
|
||||
attrs = map(lambda e: self.attribute_mappings[e], caption)
|
||||
|
||||
for row in csv_reader:
|
||||
params = dict(zip(attrs, row))
|
||||
params['prelevement_automatique'] = params['prelevement_automatique'] == 'O' or False
|
||||
params['date_generation'] = datetime.strptime(params['date_generation'],
|
||||
INPUT_DATE_FORMAT)
|
||||
params['date_limite_paie'] = datetime.strptime(params['date_limite_paie'],
|
||||
INPUT_DATE_FORMAT)
|
||||
params['debut_pge'] = datetime.strptime(params['debut_pge'],
|
||||
INPUT_DATE_FORMAT)
|
||||
params['fin_pge'] = datetime.strptime(params['fin_pge'],
|
||||
INPUT_DATE_FORMAT)
|
||||
params['active'] = path.exists(settings.INVOICES_LOCATION_PATTERN.format(invoice_id = params['id']))
|
||||
family = Famille.objects.get(pk = params.pop('famille'))
|
||||
params['famille'] = family
|
||||
|
||||
try:
|
||||
obj = self.get(pk = params['id'])
|
||||
params.pop('id')
|
||||
updated = False
|
||||
for attr, value in params.iteritems():
|
||||
if getattr(obj, attr) != value:
|
||||
setattr(obj, attr, value)
|
||||
updated = True
|
||||
if updated:
|
||||
print "Updating invoice"
|
||||
obj.save()
|
||||
except models.ObjectDoesNotExist:
|
||||
print 'Creating invoice: %s' % params['id']
|
||||
obj = self.create(**params)
|
||||
|
||||
class KidManager(models.Manager):
|
||||
|
||||
attribute_mappings = {
|
||||
'ID_FAM': 'famille',
|
||||
'ID_PER': 'id',
|
||||
'LIB_NOM_PER': 'nom',
|
||||
'LIB_PRENOM_PER': 'prenom',
|
||||
'TYP_SEXE_PER': 'sexe',
|
||||
'DAT_NAISSANCE': 'date_naissance'
|
||||
}
|
||||
|
||||
def synchronize(self, source_file):
|
||||
|
||||
with open(source_file) as source:
|
||||
csv_reader = reader(source, delimiter = ';')
|
||||
caption = csv_reader.next()
|
||||
attrs = map(lambda e: self.attribute_mappings[e], caption)
|
||||
print attrs
|
||||
|
||||
for row in csv_reader:
|
||||
params = dict(zip(attrs, row))
|
||||
# transform all inputs to unicode
|
||||
for key, value in params.iteritems():
|
||||
params[key] = value.decode('utf-8')
|
||||
try:
|
||||
params['date_naissance'] = datetime.strptime(params['date_naissance'],
|
||||
INPUT_DATE_FORMAT)
|
||||
except ValueError:
|
||||
params.pop('date_naissance')
|
||||
obj_id = params['id']
|
||||
family_id = params.pop('famille')
|
||||
family = Famille.objects.get(pk = family_id)
|
||||
params['famille'] = family
|
||||
|
||||
try:
|
||||
obj = self.get(pk = obj_id)
|
||||
obj_id = params.pop('id')
|
||||
updated = False
|
||||
for attr, value in params.iteritems():
|
||||
if getattr(obj, attr) != value:
|
||||
setattr(obj, attr, value)
|
||||
updated = True
|
||||
if updated:
|
||||
print 'Updating kid %s' % obj_id
|
||||
obj.save()
|
||||
except models.ObjectDoesNotExist:
|
||||
print 'Creating kid %s' % obj_id
|
||||
obj = self.create(**params)
|
||||
|
||||
|
||||
class Personne(models.Model):
|
||||
id = models.AutoField(primary_key = True)
|
||||
nom = models.CharField(max_length = 256, null = True, blank = True)
|
||||
prenom = models.CharField(max_length = 256, null = True, blank = True)
|
||||
sexe = models.CharField(choices = SEXES, max_length = 1, null = True)
|
||||
telephone_domicile = models.CharField(max_length = 32, null = True, blank = True)
|
||||
telephone_portable = models.CharField(max_length = 32, null = True, blank = True)
|
||||
numero_allocation = models.CharField(max_length = 32, null = True, blank = True)
|
||||
regime = models.CharField(max_length = 32, null = True, blank = True)
|
||||
cai = models.CharField(max_length = 32, null = True, blank = True)
|
||||
pays = models.CharField(max_length = 32, null = True, blank = True)
|
||||
code_postal = models.CharField(max_length = 16, null = True, blank = True)
|
||||
commune = models.CharField(max_length = 32, null = True, blank = True)
|
||||
voie = models.CharField(max_length = 32, null = True, blank = True)
|
||||
batiment = models.CharField(max_length = 32, null = True, blank = True)
|
||||
btq = models.CharField(max_length = 32, null = True, blank = True)
|
||||
appartement = models.CharField(max_length = 32, null = True, blank = True)
|
||||
rue = models.CharField(max_length = 64, null = True, blank = True)
|
||||
complement_adresse = models.CharField(max_length = 64, null = True, blank = True)
|
||||
email = models.EmailField(null = True, blank = True)
|
||||
name_id = models.CharField(max_length = 256, null = True, blank = True, db_index = True)
|
||||
objects = PersonneManager()
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s %s' % (self.prenom, self.nom)
|
||||
|
||||
def is_federated(self):
|
||||
return self.name_id is not None and len(self.name_id) > 0
|
||||
is_federated.boolean = True
|
||||
|
||||
class LiaisonParentFamille(models.Model):
|
||||
famille = models.ForeignKey('Famille')
|
||||
personne = models.ForeignKey(Personne)
|
||||
|
||||
class LiaisonNameidFamille(models.Model):
|
||||
"""
|
||||
model used to grant permissions to a nameid to see all informations about
|
||||
the family(children, invoices, etc)
|
||||
"""
|
||||
name_id = models.CharField(max_length = 256, db_index = True)
|
||||
famille = models.ForeignKey('Famille')
|
||||
link_date = models.DateTimeField(auto_now_add = True)
|
||||
|
||||
class Meta:
|
||||
|
||||
unique_together = ('name_id', 'famille')
|
||||
|
||||
class Famille(models.Model):
|
||||
id = models.AutoField(primary_key = True)
|
||||
login = models.CharField(max_length = 32, null = True, blank = True)
|
||||
password = models.CharField(max_length = 128, null = True, blank = True)
|
||||
code_secret = models.CharField(max_length = 128, null = True, blank = True)
|
||||
qf_ccas = models.CharField(max_length = 128, null = True, blank = True)
|
||||
qf_vo = models.CharField(max_length = 128, null = True, blank = True)
|
||||
pays = models.CharField(max_length = 128, null = True, blank = True)
|
||||
code_postal = models.CharField(max_length = 16, null = True, blank = True)
|
||||
commune = models.CharField(max_length = 32, null = True, blank = True)
|
||||
voie = models.CharField(max_length = 32, null = True, blank = True)
|
||||
batiment = models.CharField(max_length = 32, null = True, blank = True)
|
||||
btq = models.CharField(max_length = 32, null = True, blank = True)
|
||||
appartement = models.CharField(max_length = 32, null = True, blank = True)
|
||||
rue = models.CharField(max_length = 64, null = True, blank = True)
|
||||
complement_adresse = models.CharField(max_length = 64, null = True, blank = True)
|
||||
nombre_enfants = models.IntegerField(default = 0)
|
||||
personnes = models.ManyToManyField(Personne, through = LiaisonParentFamille)
|
||||
objects = FamilleManager()
|
||||
|
||||
def __unicode__(self):
|
||||
personnes = u' et '.join([u'%s (%s)' % (p, p.id) for p in self.personnes.all()])
|
||||
return u'Famille %s de %s' % (self.id, personnes)
|
||||
|
||||
|
||||
class Facture(models.Model):
|
||||
id = models.AutoField(primary_key = True)
|
||||
famille = models.ForeignKey(Famille)
|
||||
montant = models.DecimalField(max_digits = 6, decimal_places = 2)
|
||||
devise = models.CharField(max_length = 3)
|
||||
montant_regle = models.DecimalField(max_digits = 6, decimal_places = 2)
|
||||
solde = models.DecimalField(max_digits = 6, decimal_places = 2)
|
||||
date_generation = models.DateField()
|
||||
date_limite_paie = models.DateField()
|
||||
prenom_payeur = models.CharField(max_length = 128)
|
||||
nom_payeur = models.CharField(max_length = 128)
|
||||
prelevement_automatique = models.BooleanField()
|
||||
debut_pge = models.DateField()
|
||||
fin_pge = models.DateField()
|
||||
paye = models.BooleanField(default = False)
|
||||
objects = FactureManager()
|
||||
active = models.BooleanField(default = False)
|
||||
|
||||
def __unicode__(self):
|
||||
return 'Facture %s (Famille %s)' % (self.id, self.famille.id)
|
||||
|
||||
# def active(self):
|
||||
# return path.exists(settings.INVOICES_LOCATION_PATTERN.format(invoide_id = self.id))
|
||||
# active.boolean = True
|
||||
|
||||
|
||||
class Enfant(models.Model):
|
||||
id = models.AutoField(primary_key = True)
|
||||
famille = models.ForeignKey(Famille)
|
||||
prenom = models.CharField(max_length = 128, null = True, blank = True)
|
||||
nom = models.CharField(max_length = 128, null = True, blank = True)
|
||||
sexe = models.CharField(choices = SEXES, max_length = 1, null = True)
|
||||
date_naissance = models.DateField(null = True, blank = True)
|
||||
objects = KidManager()
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s %s' % (self.prenom, self.nom)
|
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
This file demonstrates writing tests using the unittest module. These will pass
|
||||
when you run "manage.py test".
|
||||
|
||||
Replace this with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
"""
|
||||
self.assertEqual(1 + 1, 2)
|
|
@ -0,0 +1 @@
|
|||
# Create your views here.
|
|
@ -0,0 +1,168 @@
|
|||
from os import path
|
||||
from os import environ
|
||||
|
||||
DEBUG = True
|
||||
TEMPLATE_DEBUG = DEBUG
|
||||
|
||||
ADMINS = (
|
||||
# ('Your Name', 'your_email@example.com'),
|
||||
)
|
||||
|
||||
MANAGERS = ADMINS
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': environ.get('DATABASE_ENGINE', 'django.db.backends.sqlite3'),
|
||||
'NAME': environ.get('DATABASE_NAME', 'test_orleans'),
|
||||
# The following settings are not used with sqlite3:
|
||||
'USER': '',
|
||||
'PASSWORD': '',
|
||||
'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
|
||||
'PORT': '', # Set to empty string for default.
|
||||
}
|
||||
}
|
||||
|
||||
# Hosts/domain names that are valid for this site; required if DEBUG is False
|
||||
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = environ.get('ALLOWED_HOSTS', [])
|
||||
|
||||
# Local time zone for this installation. Choices can be found here:
|
||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||
# although not all choices may be available on all operating systems.
|
||||
# In a Windows environment this must be set to your system time zone.
|
||||
TIME_ZONE = 'Europe/Paris'
|
||||
|
||||
# Language code for this installation. All choices can be found here:
|
||||
# http://www.i18nguy.com/unicode/language-identifiers.html
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
# If you set this to False, Django will make some optimizations so as not
|
||||
# to load the internationalization machinery.
|
||||
USE_I18N = True
|
||||
|
||||
# If you set this to False, Django will not format dates, numbers and
|
||||
# calendars according to the current locale.
|
||||
USE_L10N = True
|
||||
|
||||
# If you set this to False, Django will not use timezone-aware datetimes.
|
||||
USE_TZ = True
|
||||
|
||||
# Absolute filesystem path to the directory that will hold user-uploaded files.
|
||||
# Example: "/var/www/example.com/media/"
|
||||
MEDIA_ROOT = ''
|
||||
|
||||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
||||
# trailing slash.
|
||||
# Examples: "http://example.com/media/", "http://media.example.com/"
|
||||
MEDIA_URL = ''
|
||||
|
||||
# Absolute path to the directory static files should be collected to.
|
||||
# Don't put anything in this directory yourself; store your static files
|
||||
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
|
||||
# Example: "/var/www/example.com/static/"
|
||||
STATIC_ROOT = ''
|
||||
|
||||
# URL prefix for static files.
|
||||
# Example: "http://example.com/static/", "http://static.example.com/"
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
# Additional locations of static files
|
||||
STATICFILES_DIRS = (
|
||||
# Put strings here, like "/home/html/static" or "C:/www/django/static".
|
||||
# Always use forward slashes, even on Windows.
|
||||
# Don't forget to use absolute paths, not relative paths.
|
||||
)
|
||||
|
||||
# List of finder classes that know how to find static files in
|
||||
# various locations.
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
||||
)
|
||||
|
||||
# Make this unique, and don't share it with anybody.
|
||||
SECRET_KEY = environ.get('SECRET_KEY', 'q9ii%jyg@5ll#ak9^b3wquza9z)szk+%@*8in+f4e7_94oc-7*')
|
||||
|
||||
# List of callables that know how to import templates from various sources.
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.Loader',
|
||||
'django.template.loaders.app_directories.Loader',
|
||||
# 'django.template.loaders.eggs.Loader',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
# Uncomment the next line for simple clickjacking protection:
|
||||
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'synchro.urls'
|
||||
|
||||
# Python dotted path to the WSGI application used by Django's runserver.
|
||||
WSGI_APPLICATION = 'synchro.wsgi.application'
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
|
||||
# Always use forward slashes, even on Windows.
|
||||
# Don't forget to use absolute paths, not relative paths.
|
||||
)
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
# Uncomment the next line to enable the admin:
|
||||
'django.contrib.admin',
|
||||
# Uncomment the next line to enable admin documentation:
|
||||
# 'django.contrib.admindocs',
|
||||
'synchro.data',
|
||||
'south',
|
||||
)
|
||||
|
||||
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer'
|
||||
|
||||
# A sample logging configuration. The only tangible logging
|
||||
# performed by this configuration is to send an email to
|
||||
# the site admins on every HTTP 500 error when DEBUG=False.
|
||||
# See http://docs.djangoproject.com/en/dev/topics/logging for
|
||||
# more details on how to customize your logging configuration.
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse'
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler'
|
||||
}
|
||||
},
|
||||
'loggers': {
|
||||
'django.request': {
|
||||
'handlers': ['mail_admins'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
INVOICES_LOCATION_PATTERN = path.join(path.dirname(__file__), 'invoices', 'facture-{invoice_id}.pdf')
|
||||
|
||||
try:
|
||||
from local_settings import *
|
||||
except ImportError:
|
||||
pass
|
|
@ -0,0 +1,17 @@
|
|||
from django.conf.urls import patterns, include, url
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
from django.contrib import admin
|
||||
admin.autodiscover()
|
||||
|
||||
urlpatterns = patterns('',
|
||||
# Examples:
|
||||
# url(r'^$', 'synchro.views.home', name='home'),
|
||||
# url(r'^synchro/', include('synchro.foo.urls')),
|
||||
|
||||
# Uncomment the admin/doc line below to enable admin documentation:
|
||||
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
|
||||
# Uncomment the next line to enable the admin:
|
||||
url(r'^', include(admin.site.urls)),
|
||||
)
|
|
@ -0,0 +1,32 @@
|
|||
"""
|
||||
WSGI config for synchro project.
|
||||
|
||||
This module contains the WSGI application used by Django's development server
|
||||
and any production WSGI deployments. It should expose a module-level variable
|
||||
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
|
||||
this application via the ``WSGI_APPLICATION`` setting.
|
||||
|
||||
Usually you will have the standard Django WSGI application here, but it also
|
||||
might make sense to replace the whole Django WSGI application with a custom one
|
||||
that later delegates to the Django one. For example, you could introduce WSGI
|
||||
middleware here, or combine a Django application with an application of another
|
||||
framework.
|
||||
|
||||
"""
|
||||
import os
|
||||
|
||||
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
|
||||
# if running multiple sites in the same mod_wsgi process. To fix this, use
|
||||
# mod_wsgi daemon mode with each site in its own daemon process, or use
|
||||
# os.environ["DJANGO_SETTINGS_MODULE"] = "synchro.settings"
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "synchro.settings")
|
||||
|
||||
# This application object is used by any WSGI server configured to use this
|
||||
# file. This includes Django's development server, if the WSGI_APPLICATION
|
||||
# setting points here.
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
application = get_wsgi_application()
|
||||
|
||||
# Apply WSGI middleware here.
|
||||
# from helloworld.wsgi import HelloWorldApplication
|
||||
# application = HelloWorldApplication(application)
|
Reference in New Issue