misc: apply double-quote-string-fixer (#79788)

This commit is contained in:
Valentin Deniaud 2023-08-16 11:52:16 +02:00
parent 5b36982e20
commit f1941a3ad8
24 changed files with 300 additions and 300 deletions

6
debian/config.py vendored
View File

@ -14,7 +14,7 @@ STATIC_ROOT = os.path.join(VAR_DIR, 'collected-static')
MEDIA_ROOT = os.path.join(VAR_DIR, 'media')
ETC_DIR = '/etc/barbacompta/'
with open("/etc/barbacompta/secret") as fd:
with open('/etc/barbacompta/secret') as fd:
SECRET_KEY = fd.read()
DEBUG = False
@ -29,8 +29,8 @@ if os.path.exists('/etc/barbacompta/idp-metadata.xml'):
'first_name': '{attributes[first_name][0]}',
'last_name': '{attributes[last_name][0]}',
}
MELLON_SUPERUSER_MAPPING = {"is_superuser": ("true",)}
MELLON_USERNAME_TEMPLATE = "{attributes[username][0]}"
MELLON_SUPERUSER_MAPPING = {'is_superuser': ('true',)}
MELLON_USERNAME_TEMPLATE = '{attributes[username][0]}'
MELLON_PUBLIC_KEYS = ['/etc/barbacompta/saml.crt']
MELLON_PRIVATE_KEY = '/etc/barbacompta/saml.key'
MELLON_IDENTITY_PROVIDERS = [{'METADATA': '/etc/barbacompta/idp-metadata.xml'}]

View File

@ -32,8 +32,8 @@ def export_as_csv(modeladmin, request, queryset):
if not request.user.is_staff:
raise PermissionDenied
opts = modeladmin.model._meta
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = "attachment; filename=%s.csv" % str(opts).replace(".", "_")
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=%s.csv' % str(opts).replace('.', '_')
writer = csv.writer(response)
field_names = [field.name for field in opts.fields]
m2m_field_names = [m2m_field.name for m2m_field in opts.many_to_many]
@ -44,13 +44,13 @@ def export_as_csv(modeladmin, request, queryset):
values = [str(getattr(obj, field)) for field in field_names]
for m2m_field in m2m_field_names:
value = getattr(obj, m2m_field)
value = ",".join(map(str, value.all()))
value = ','.join(map(str, value.all()))
values.append(str(value))
writer.writerow(map(lambda x: str.encode(x, "utf8"), values))
writer.writerow(map(lambda x: str.encode(x, 'utf8'), values))
return response
export_as_csv.short_description = "Export selected objects as csv file"
export_as_csv.short_description = 'Export selected objects as csv file'
def export_references_as_fodt(modeladmin, request, queryset):
@ -73,7 +73,7 @@ def export_references_as_fodt(modeladmin, request, queryset):
return response
export_references_as_fodt.short_description = _("Export selected contracts as fodt file")
export_references_as_fodt.short_description = _('Export selected contracts as fodt file')
def export_invoices_as_zip(modeladmin, request, queryset):
@ -88,4 +88,4 @@ def export_invoices_as_zip(modeladmin, request, queryset):
return response
export_invoices_as_zip.short_description = _("Export selected invoices")
export_invoices_as_zip.short_description = _('Export selected invoices')

View File

@ -33,19 +33,19 @@ User = get_user_model()
class EOGestionAdminSite(admin.AdminSite):
@never_cache
def login(self, request, extra_context=None):
if "mellon" in settings.INSTALLED_APPS:
next_url = request.GET.get(REDIRECT_FIELD_NAME, settings.LOGIN_REDIRECT_URL or "/")
if 'mellon' in settings.INSTALLED_APPS:
next_url = request.GET.get(REDIRECT_FIELD_NAME, settings.LOGIN_REDIRECT_URL or '/')
query = urlencode({REDIRECT_FIELD_NAME: next_url})
url = f"/accounts/mellon/login/?{query}"
url = f'/accounts/mellon/login/?{query}'
return HttpResponseRedirect(url)
return super().login(request, extra_context=extra_context)
@never_cache
def logout(self, request, extra_context=None):
if "mellon" in settings.INSTALLED_APPS:
next_url = request.GET.get(REDIRECT_FIELD_NAME, settings.LOGIN_REDIRECT_URL or "/")
if 'mellon' in settings.INSTALLED_APPS:
next_url = request.GET.get(REDIRECT_FIELD_NAME, settings.LOGIN_REDIRECT_URL or '/')
query = urlencode({REDIRECT_FIELD_NAME: next_url})
url = f"/accounts/mellon/logout/?{query}"
url = f'/accounts/mellon/logout/?{query}'
return HttpResponseRedirect(url)
return super().logout(request, extra_context=extra_context)

View File

@ -85,7 +85,7 @@ class LigneBanquePopAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
qs = qs.prefetch_related("payments")
qs = qs.prefetch_related('payments')
return qs
def has_add_permission(self, request):

View File

@ -29,7 +29,7 @@ class Command(BaseCommand):
]
def add_arguments(self, parser):
parser.add_argument("args", nargs="+")
parser.add_argument('args', nargs='+')
def to_date(self, str):
try:
@ -38,13 +38,13 @@ class Command(BaseCommand):
return datetime.strptime(str, '%d/%m/%Y').date()
def make_csv_reader(self, csv_file):
for delimiter in [";", "\t"]:
for delimiter in [';', '\t']:
csv_file.seek(0)
csv_lines = csv.reader(csv_file, delimiter=delimiter)
first_line = next(csv_lines)
if first_line == self.HEADER:
return csv_lines
raise CommandError("Invalid CSV file header")
raise CommandError('Invalid CSV file header')
def load_one_file(self, csv_file_path, csv_lines):
counter = 0

View File

@ -14,8 +14,8 @@ class Command(BaseCommand):
can_import_django_settings = True
output_transaction = True
requires_system_checks = True
args = "<csv_file> <csv_file>..."
help = "Charge le solde courant"
args = '<csv_file> <csv_file>...'
help = 'Charge le solde courant'
@transaction.atomic
def handle(self, compte, montant, **options):

View File

@ -26,7 +26,7 @@ def solde(t=None):
if t is None:
t = date.today()
try:
s = SoldeBanquePop.objects.latest("date")
s = SoldeBanquePop.objects.latest('date')
except SoldeBanquePop.DoesNotExist:
return 0
m = s.montant
@ -50,10 +50,10 @@ class Commentaire(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
creation = models.DateTimeField(auto_now_add=True)
content_object = GenericForeignKey("content_type", "object_id")
content_object = GenericForeignKey('content_type', 'object_id')
def __str__(self):
return "Commentaire créé le %s" % self.creation
return 'Commentaire créé le %s' % self.creation
class LigneBanquePop(models.Model):
@ -78,7 +78,7 @@ class LigneBanquePop(models.Model):
]
def __str__(self):
return "%(date_valeur)s %(libelle)s %(montant)s" % self.__dict__
return '%(date_valeur)s %(libelle)s %(montant)s' % self.__dict__
def montant_non_affecte(self):
return self.montant - sum(x.montant_affecte for x in self.payments.all())

View File

@ -34,7 +34,7 @@ def month_before(date):
return date.replace(month=date.month - 1)
@register.inclusion_tag("eo_banque/finances.html")
@register.inclusion_tag('eo_banque/finances.html')
@cache
def finances(month=3):
dates = [date.today().replace(day=1)]
@ -82,8 +82,8 @@ def finances(month=3):
@register.inclusion_tag('eo_banque/total.html', takes_context=True)
def total(context):
qs = context["cl"].get_queryset(context["request"])
ls = [ligne[0] for ligne in qs.values_list("montant")]
qs = context['cl'].get_queryset(context['request'])
ls = [ligne[0] for ligne in qs.values_list('montant')]
credit = sum(montant for montant in ls if montant > 0)
debit = sum(montant for montant in ls if montant < 0)
total = sum(ls)
@ -91,14 +91,14 @@ def total(context):
def iso_year_start(iso_year):
"The gregorian calendar date of the first day of the given ISO year"
'The gregorian calendar date of the first day of the given ISO year'
fourth_jan = date(iso_year, 1, 4)
delta = timedelta(fourth_jan.isoweekday() - 1)
return fourth_jan - delta
def iso_to_gregorian(iso_year, iso_week, iso_day):
"Gregorian calendar date for the given ISO year, week and day"
'Gregorian calendar date for the given ISO year, week and day'
year_start = iso_year_start(iso_year)
return year_start + timedelta(iso_day - 1, 0, 0, 0, 0, 0, iso_week - 1)
@ -123,16 +123,16 @@ def week_start_and_end(year, month):
]
@register.inclusion_tag("admin/date_hierarchy.html")
@register.inclusion_tag('admin/date_hierarchy.html')
def eo_banque_date_hierarchy(cl):
if cl.date_hierarchy:
field_name = cl.date_hierarchy
year_field = "%s__year" % field_name
month_field = "%s__month" % field_name
day_field = "%s__day" % field_name
field_generic = "%s__" % field_name
field_gte = "%s__gte" % field_name
field_lte = "%s__lte" % field_name
year_field = '%s__year' % field_name
month_field = '%s__month' % field_name
day_field = '%s__day' % field_name
field_generic = '%s__' % field_name
field_gte = '%s__gte' % field_name
field_lte = '%s__lte' % field_name
year_lookup = cl.params.get(year_field)
month_lookup = cl.params.get(month_field)
day_lookup = cl.params.get(day_field)

View File

@ -75,11 +75,11 @@ class PaymentInlineFormset(BaseInlineFormSet):
super().__init__(*args, **kwargs)
for form in self.forms:
if form.instance.id is None:
field = form.fields["ligne_banque_pop"]
if not hasattr(field, "parent_instance"):
field = form.fields['ligne_banque_pop']
if not hasattr(field, 'parent_instance'):
field.queryset = models.encaissements_avec_solde_non_affecte()
field = form.fields["facture"]
if not hasattr(field, "parent_instance"):
field = form.fields['facture']
if not hasattr(field, 'parent_instance'):
field.queryset = models.Facture.objects.avec_solde()
@ -96,7 +96,7 @@ class LigneInline(SelectRelatedMixin, SortableInlineAdminMixin, admin.TabularInl
form = forms.LigneForm
model = models.Ligne
original = False
verbose_name_plural = "Lignes de facture (vous pouvez les réordonner par drag&drop)"
verbose_name_plural = 'Lignes de facture (vous pouvez les réordonner par drag&drop)'
formfield_overrides = {
TextField: {
'widget': Textarea(attrs={'cols': 30, 'rows': 1}),
@ -156,7 +156,7 @@ def show_client(obj):
url = reverse('admin:eo_facture_client_change', args=[obj.client.id])
return format_html('<a href="{0}">{1}</a>', url, obj.client)
else:
return ""
return ''
show_client.short_description = 'Client'
@ -169,7 +169,7 @@ class ContratAdmin(LookupAllowed, admin.ModelAdmin):
PrestationInline,
]
list_display = [
"__str__",
'__str__',
show_client,
'column_montant',
'pourcentage_facture',
@ -226,7 +226,7 @@ class ContratAdmin(LookupAllowed, admin.ModelAdmin):
'opts': self.model._meta,
}
return render(request, "admin/eo_facture/contrat/duplicate.html", context=context)
return render(request, 'admin/eo_facture/contrat/duplicate.html', context=context)
def facturer_echeance(self, request, object_id):
if request.method != 'POST':
@ -284,7 +284,7 @@ def index(facture):
return format_html('{0}', ordinal(facture.index()))
index.short_description = "Ordre"
index.short_description = 'Ordre'
class FactureAdmin(LookupAllowed, admin.ModelAdmin):
@ -333,7 +333,7 @@ class FactureAdmin(LookupAllowed, admin.ModelAdmin):
def column_code(self, obj):
if obj.montant < 0:
return "Avoir %s" % obj.code()
return 'Avoir %s' % obj.code()
else:
return obj.code()
@ -364,16 +364,16 @@ class FactureAdmin(LookupAllowed, admin.ModelAdmin):
from django.db import connection
qs = super().get_queryset(request)
qs = qs.prefetch_related("lignes__facture__client")
qs = qs.prefetch_related("payments__ligne_banque_pop")
qs = qs.prefetch_related("contrat__factures")
if connection.vendor == "postgresql":
qs = qs.extra({"year": "EXTRACT(year FROM emission)"})
elif connection.vendor == "sqlite":
qs = qs.extra({"year": "strftime('%Y', emission)"})
qs = qs.prefetch_related('lignes__facture__client')
qs = qs.prefetch_related('payments__ligne_banque_pop')
qs = qs.prefetch_related('contrat__factures')
if connection.vendor == 'postgresql':
qs = qs.extra({'year': 'EXTRACT(year FROM emission)'})
elif connection.vendor == 'sqlite':
qs = qs.extra({'year': "strftime('%Y', emission)"})
else:
qs = qs.extra({"year": "YEAR(emission)"})
qs = qs.order_by("-year", "-proforma", "-ordre")
qs = qs.extra({'year': 'YEAR(emission)'})
qs = qs.order_by('-year', '-proforma', '-ordre')
return qs
def save_model(self, request, obj, form, change):
@ -383,7 +383,7 @@ class FactureAdmin(LookupAllowed, admin.ModelAdmin):
def add_simple(self, request):
context = {}
if request.method == "POST":
if request.method == 'POST':
form = forms.RapidFactureForm(request=request, data=request.POST)
if form.is_valid():
return http.HttpResponseRedirect(
@ -398,11 +398,11 @@ class FactureAdmin(LookupAllowed, admin.ModelAdmin):
'opts': self.model._meta,
}
return render(request, "admin/eo_facture/facture/add_simple.html", context=context)
return render(request, 'admin/eo_facture/facture/add_simple.html', context=context)
def sheet(self, request):
workbook = ods.Workbook()
ws = workbook.add_sheet("Factures")
ws = workbook.add_sheet('Factures')
for i, header_name in enumerate(
['Référence', 'Nom client', 'Date', 'Montant HT', 'Montant TTC', 'TVA']
):
@ -447,9 +447,9 @@ class FactureAdmin(LookupAllowed, admin.ModelAdmin):
name='eo_facture_facture_send_to_chorus',
),
url(
r"^sheet/$",
r'^sheet/$',
self.admin_site.admin_view(self.sheet),
name="eo_facture_facture_sheet",
name='eo_facture_facture_sheet',
),
url(
r'^(.+)/cancel/',

View File

@ -31,8 +31,8 @@ class PercentagePerYear(list):
class EuroField(models.DecimalField):
def __init__(self, *args, **kwargs):
kwargs["max_digits"] = 8
kwargs["decimal_places"] = 2
kwargs['max_digits'] = 8
kwargs['decimal_places'] = 2
super().__init__(*args, **kwargs)
@ -51,22 +51,22 @@ def check_percentage_per_year(value):
years = [a for a, b in value]
percentages = [b for a, b in value]
# ordered
assert years == sorted(years), "years are not ordered"
assert years == sorted(years), 'years are not ordered'
# sum equals 100
assert sum(percentages) == 1, "percentage does not sum to 100"
assert sum(percentages) == 1, 'percentage does not sum to 100'
# no duplicate year
assert len(years) == len(set(years)), "years are not unique"
assert len(years) == len(set(years)), 'years are not unique'
# consecutive
assert years == list(range(years[0], years[0] + len(years))), 'years are not consecutive'
def parse_percentage_per_year(value):
msg = _("field must be numeric values separated by commas")
values = value.split(",")
msg = _('field must be numeric values separated by commas')
values = value.split(',')
decimals = []
for value in values:
try:
year, decimal = value.split(":")
year, decimal = value.split(':')
except ValueError:
raise ValidationError(msg)
try:
@ -92,7 +92,7 @@ class PercentagePerYearFormField(forms.Field):
if isinstance(PercentagePerYear, value):
return value
if not isinstance(str, value):
raise ValidationError(self.default_error_messages["invalid"])
raise ValidationError(self.default_error_messages['invalid'])
return parse_percentage_per_year(value)
@ -114,7 +114,7 @@ class PercentagePerYearField(models.Field):
default_validators = [check_percentage_per_year]
def __init__(self, *args, **kwargs):
kwargs["max_length"] = 64
kwargs['max_length'] = 64
super().__init__(*args, **kwargs)
def from_db_value(self, value, expression, connection):
@ -125,12 +125,12 @@ class PercentagePerYearField(models.Field):
return value
if value is not None:
percentage_per_year = []
pairs = value.split(",")
pairs = value.split(',')
for pair in pairs:
try:
year, percentage = map(value.__class__.strip, pair.split(":"))
year, percentage = map(value.__class__.strip, pair.split(':'))
except ValueError:
raise ValidationError(PercentagePerYearFormField.default_error_messages["invalid"])
raise ValidationError(PercentagePerYearFormField.default_error_messages['invalid'])
year = int(year)
percentage = Decimal(percentage) / Decimal(100)
percentage_per_year.append((year, percentage))
@ -150,10 +150,10 @@ class PercentagePerYearField(models.Field):
return super().get_prep_value(value)
def get_internal_type(self):
return "CharField"
return 'CharField'
def formfield(self, **kwargs):
defaults = {"form_class": PercentagePerYearFormField}
defaults = {'form_class': PercentagePerYearFormField}
defaults.update(kwargs)
return super().formfield(**kwargs)

View File

@ -26,7 +26,7 @@ from django.db.transaction import atomic
from . import models
pourcentages = [(Decimal(i) / 100, "%s %%" % i) for i in range(0, 101, 5)]
pourcentages = [(Decimal(i) / 100, '%s %%' % i) for i in range(0, 101, 5)]
class RapidFactureForm(forms.Form):
@ -51,7 +51,7 @@ class RapidFactureForm(forms.Form):
except ValidationError as e:
raise forms.ValidationError('clean facture %s' % facture.code(), *e.args)
facture.save()
self.cleaned_data["facture"] = facture
self.cleaned_data['facture'] = facture
lignes = []
errors = []
if solde:
@ -73,8 +73,8 @@ class RapidFactureForm(forms.Form):
try:
ligne.clean()
except ValidationError as e:
error = "Il y a un problème avec la ligne « %s »: " % prestation.intitule
error += "; ".join(map(lambda x: x.rstrip("."), e.messages))
error = 'Il y a un problème avec la ligne « %s »: ' % prestation.intitule
error += '; '.join(map(lambda x: x.rstrip('.'), e.messages))
errors.append(error)
if errors:
raise forms.ValidationError(errors)
@ -87,7 +87,7 @@ class RapidFactureForm(forms.Form):
class DuplicateContractForm(forms.Form):
contrat = forms.ModelChoiceField(queryset=models.Contrat.objects.all())
new_intitule = forms.CharField(max_length=150, label="Nouvel intitulé")
new_intitule = forms.CharField(max_length=150, label='Nouvel intitulé')
def __init__(self, request=None, *args, **kwargs):
self.request = request
@ -109,7 +109,7 @@ class DuplicateContractForm(forms.Form):
except ValidationError as e:
raise forms.ValidationError('clean contrat %s' % contrat.intitule, *e.args)
new_contrat.save()
self.cleaned_data["new_contrat"] = new_contrat
self.cleaned_data['new_contrat'] = new_contrat
for prestation in contrat.prestations.all():
new_prestation = prestation.duplicate()
new_prestation.contrat = new_contrat
@ -121,14 +121,14 @@ class LigneForm(forms.ModelForm):
class Meta:
fields = '__all__'
model = models.Ligne
localized_fields = ("quantite", "prix_unitaire_ht", "taux_tva")
localized_fields = ('quantite', 'prix_unitaire_ht', 'taux_tva')
class PrestationForm(forms.ModelForm):
class Meta:
fields = '__all__'
model = models.Prestation
localized_fields = ("quantite", "prix_unitaire_ht")
localized_fields = ('quantite', 'prix_unitaire_ht')
class FactureForm(forms.ModelForm):
@ -189,17 +189,17 @@ class FactureForm(forms.ModelForm):
class Meta:
fields = '__all__'
model = models.Facture
localized_fields = ("taux_tva",)
localized_fields = ('taux_tva',)
class ClientForm(forms.ModelForm):
class Meta:
fields = '__all__'
model = models.Client
localized_fields = ("tva",)
localized_fields = ('tva',)
widgets = {
"adresse": widgets.AdminTextareaWidget(attrs={"rows": 4}),
"contacts": widgets.AdminTextareaWidget(attrs={"rows": 4}),
'adresse': widgets.AdminTextareaWidget(attrs={'rows': 4}),
'contacts': widgets.AdminTextareaWidget(attrs={'rows': 4}),
}
@ -215,7 +215,7 @@ class ContratForm(forms.ModelForm):
class Meta:
fields = '__all__'
model = models.Contrat
localized_fields = ("tva", "montant_sous_traite")
localized_fields = ('tva', 'montant_sous_traite')
class Media:
js = ['facture.js']
@ -225,4 +225,4 @@ class PaymentForm(forms.ModelForm):
class Meta:
fields = '__all__'
model = models.Payment
localized_fields = ("montant_affecte",)
localized_fields = ('montant_affecte',)

View File

@ -42,13 +42,13 @@ from . import facturx, fields, taggit, validators
User = get_user_model()
validate_telephone = RegexValidator(r"[. 0-9]*")
validate_telephone = RegexValidator(r'[. 0-9]*')
DEFAULT_TVA = getattr(settings, "TVA", "20")
DEFAULT_TVA = getattr(settings, 'TVA', '20')
def accounting_rounding(amount):
return amount.quantize(Decimal("0.01"), ROUND_HALF_UP)
return amount.quantize(Decimal('0.01'), ROUND_HALF_UP)
def today():
@ -122,11 +122,11 @@ class Client(models.Model):
def one_hundred_percent_this_year():
return "%s:100" % now().date().year
return '%s:100' % now().date().year
class Contrat(models.Model):
client = models.ForeignKey(Client, related_name="contrats", on_delete=models.CASCADE, null=True)
client = models.ForeignKey(Client, related_name='contrats', on_delete=models.CASCADE, null=True)
intitule = models.CharField(max_length=150)
description = models.TextField(blank=True)
public_description = models.TextField(
@ -372,7 +372,7 @@ class Prestation(models.Model):
ordering = ('contrat', 'id')
DELAI_PAIEMENT = getattr(settings, "DELAI_PAIEMENT", 45)
DELAI_PAIEMENT = getattr(settings, 'DELAI_PAIEMENT', 45)
def today_plus_delai():
@ -416,7 +416,7 @@ class Facture(models.Model):
)
intitule = models.CharField(max_length=150, verbose_name='Intitulé', blank=True)
notes = models.TextField(blank=True)
emission = models.DateField(verbose_name="Émission", default=today, db_index=True)
emission = models.DateField(verbose_name='Émission', default=today, db_index=True)
echeance = models.DateField(verbose_name=echeance_verbose_name, default=today_plus_delai)
taux_tva = models.DecimalField(
max_digits=4, decimal_places=2, default=Decimal(DEFAULT_TVA), blank=True, null=True
@ -426,7 +426,7 @@ class Facture(models.Model):
verbose_name='Montant sous-traité',
help_text='indiquer une somme pas un pourcentage, hors-taxe',
)
paid = models.BooleanField(blank=True, verbose_name="Soldée", default=False, db_index=True)
paid = models.BooleanField(blank=True, verbose_name='Soldée', default=False, db_index=True)
creator = models.ForeignKey(User, verbose_name='Créateur', on_delete=models.CASCADE)
account_on_previous_period = models.BooleanField(
verbose_name='Mettre cette facture sur l\'exercice précédent', default=False
@ -459,9 +459,9 @@ class Facture(models.Model):
ctx = {}
ctx.update(self.__dict__)
ctx.update({'year': self.emission.year})
if ctx["ordre"] is None:
return "Ordre is missing"
format = getattr(settings, "FACTURE_CODE_FORMAT", "F%(year)s%(ordre)04d")
if ctx['ordre'] is None:
return 'Ordre is missing'
format = getattr(settings, 'FACTURE_CODE_FORMAT', 'F%(year)s%(ordre)04d')
return format % ctx
@property
@ -478,13 +478,13 @@ class Facture(models.Model):
def clean(self):
if not (self.contrat or self.client):
raise ValidationError("La facture doit avoir un client ou un contrat")
raise ValidationError('La facture doit avoir un client ou un contrat')
if self.contrat:
if not self.intitule:
self.intitule = self.contrat.intitule
if self.client:
if self.client != self.contrat.client and self.contrat.client is not None:
raise ValidationError("Le client de la facture et du contrat doivent être identiques.")
raise ValidationError('Le client de la facture et du contrat doivent être identiques.')
else:
self.client = self.contrat.client
if self.contrat.periodicite and not self.annulation:
@ -506,7 +506,7 @@ class Facture(models.Model):
)
else:
if not self.intitule:
raise ValidationError("La facture doit avoir un intitulé")
raise ValidationError('La facture doit avoir un intitulé')
if self.numero_d_echeance is not None:
raise ValidationError(
'Un numéro d\'échéance ne peut être défini que pour un contrat récurrent.'
@ -516,7 +516,7 @@ class Facture(models.Model):
for ligne in self.lignes.all():
ligne.clean()
except ValidationError:
raise ValidationError("Il y a un problème avec les lignes de cette facture")
raise ValidationError('Il y a un problème avec les lignes de cette facture')
self.update_paid(save=False)
self.numero_engagement = self.numero_engagement.strip()
if (
@ -544,7 +544,7 @@ class Facture(models.Model):
amount_by_vat[ligne.tva] += ligne.montant
vat = Decimal(0)
for vat_percentage, amount in amount_by_vat.items():
var_ratio = vat_percentage / Decimal("100")
var_ratio = vat_percentage / Decimal('100')
vat += accounting_rounding(var_ratio * amount)
return vat
@ -627,7 +627,7 @@ class Facture(models.Model):
facture_avoir.ordre = None
facture_avoir.annulation = self
facture_avoir.proforma = True
facture_avoir.intitule = "AVOIR POUR LA FACTURE " + self.intitule
facture_avoir.intitule = 'AVOIR POUR LA FACTURE ' + self.intitule
facture_avoir.paid = False
facture_avoir.creator = creator
facture_avoir.account_on_previous_period = False
@ -679,14 +679,14 @@ class Facture(models.Model):
periode = property(periode)
class Meta:
ordering = ("-id",)
ordering = ('-id',)
unique_together = [
('contrat', 'numero_d_echeance'),
]
class Ligne(models.Model):
facture = models.ForeignKey(Facture, related_name="lignes", on_delete=models.CASCADE)
facture = models.ForeignKey(Facture, related_name='lignes', on_delete=models.CASCADE)
intitule = models.TextField(blank=True)
prix_unitaire_ht = models.DecimalField(max_digits=8, decimal_places=2, default=Decimal('0'))
quantite = models.DecimalField(max_digits=8, decimal_places=3, default=Decimal('1.0'))
@ -711,9 +711,9 @@ class Ligne(models.Model):
def clean(self):
errors = []
if self.taux_tva and self.taux_tva < 0:
errors.append("Le taux de tva doit être une valeur positive ou nulle.")
errors.append('Le taux de tva doit être une valeur positive ou nulle.')
if self.prix_unitaire_ht < 0:
errors.append("Le prix unitaire hors taxe doit être une valeur positive ou nulle.")
errors.append('Le prix unitaire hors taxe doit être une valeur positive ou nulle.')
if self.facture.contrat and not self.facture.proforma:
facture = self.facture
contrat = facture.contrat
@ -728,17 +728,17 @@ class Ligne(models.Model):
raise ValidationError(errors)
class Meta:
ordering = ("order",)
ordering = ('order',)
def __str__(self):
if self.facture.client:
return "%s pour %s %s" % (
return '%s pour %s %s' % (
self.intitule,
self.montant,
self.facture.client.monnaie,
)
else:
return "%s pour %s" % (self.intitule, self.montant)
return '%s pour %s' % (self.intitule, self.montant)
def encaissements_avec_solde_non_affecte():
@ -775,7 +775,7 @@ class Payment(models.Model):
self.montant_affecte = min(self.ligne_banque_pop.montant, self.facture.montant_ttc)
except (banque_models.LigneBanquePop.DoesNotExist, Facture.DoesNotExist):
pass
aggregate = models.Sum("montant_affecte")
aggregate = models.Sum('montant_affecte')
# from the ligne de banque pov
try:
other_payments = self.ligne_banque_pop.payments
@ -784,7 +784,7 @@ class Payment(models.Model):
except banque_models.LigneBanquePop.DoesNotExist:
pass
else:
deja_affecte = other_payments.aggregate(aggregate).get("montant_affecte", 0)
deja_affecte = other_payments.aggregate(aggregate).get('montant_affecte', 0)
if deja_affecte + self.montant_affecte > self.ligne_banque_pop.montant:
raise ValidationError(
'Le montant affecté aux différentes factures '
@ -796,7 +796,7 @@ class Payment(models.Model):
except Facture.DoesNotExist:
pass
else:
deja_affecte = other_payments.aggregate(aggregate).get("montant_affecte") or 0
deja_affecte = other_payments.aggregate(aggregate).get('montant_affecte') or 0
if (
self.montant_affecte is not None
and deja_affecte + self.montant_affecte > self.facture.montant_ttc

View File

@ -156,17 +156,17 @@ class StringWithHref(str):
def client_and_link(c):
if c is not None:
s = str(c)
url = reverse("admin:eo_facture_client_change", args=(c.id,))
url = reverse('admin:eo_facture_client_change', args=(c.id,))
return StringWithHref(s, url)
else:
return ""
return ''
def dict_of_list():
return defaultdict(lambda: [])
@register.inclusion_tag("eo_facture/table.html")
@register.inclusion_tag('eo_facture/table.html')
@cache
def income_by_clients(year=None):
if not year:
@ -218,7 +218,7 @@ def income_by_clients(year=None):
pareto[client] = running_total
return dict(
title="Chiffre d'affaire prévisionnel par client pour %s" % year,
name="previsional-income-by-client-%s" % year,
name='previsional-income-by-client-%s' % year,
headers=[
('client', 'Client'),
('income', 'Chiffre d\'affaire'),
@ -291,12 +291,12 @@ def a_facturer():
def ago(date):
ago = timesince(date)
# selects only the first part of the returned string
return ago.split(",")[0]
return ago.split(',')[0]
@register.filter(is_safe=True)
def amountformat(value, use_l10n=True):
return number_format(Decimal(value).quantize(Decimal("0.01")), force_grouping=True)
return number_format(Decimal(value).quantize(Decimal('0.01')), force_grouping=True)
# invalidate impayees() cache when Payment set changes

View File

@ -22,13 +22,13 @@ from datetime import date, datetime
from django.utils.encoding import force_text
NS = {
"fo": "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
"office": "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
"style": "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
"number": "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
"table": "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
"text": "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
"xlink": "http://www.w3.org/1999/xlink",
'fo': 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0',
'office': 'urn:oasis:names:tc:opendocument:xmlns:office:1.0',
'style': 'urn:oasis:names:tc:opendocument:xmlns:style:1.0',
'number': 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0',
'table': 'urn:oasis:names:tc:opendocument:xmlns:table:1.0',
'text': 'urn:oasis:names:tc:opendocument:xmlns:text:1.0',
'xlink': 'http://www.w3.org/1999/xlink',
}
for prefix, uri in NS.items():
@ -36,7 +36,7 @@ for prefix, uri in NS.items():
def is_number(value):
if isinstance(value, str) and (value.startswith("0") or value.startswith("+")):
if isinstance(value, str) and (value.startswith('0') or value.startswith('+')):
return False
try:
float(value)
@ -55,96 +55,96 @@ class Workbook:
return sheet
def get_content_node(self):
root = ET.Element("{%s}document-content" % NS["office"])
ET.SubElement(root, "{%s}scripts" % NS["office"])
ET.SubElement(root, "{%s}font-face-decls" % NS["office"])
root = ET.Element('{%s}document-content' % NS['office'])
ET.SubElement(root, '{%s}scripts' % NS['office'])
ET.SubElement(root, '{%s}font-face-decls' % NS['office'])
body = ET.SubElement(root, "{%s}body" % NS["office"])
spreadsheet = ET.SubElement(body, "{%s}spreadsheet" % NS["office"])
body = ET.SubElement(root, '{%s}body' % NS['office'])
spreadsheet = ET.SubElement(body, '{%s}spreadsheet' % NS['office'])
for sheet in self.sheets:
spreadsheet.append(sheet.get_node())
return root
def get_styles_node(self):
root = ET.Element("{%s}document-styles" % NS["office"])
ET.SubElement(root, "{%s}font-face-decls" % NS["office"])
automatic_styles = ET.SubElement(root, "{%s}styles" % NS["office"])
style = ET.SubElement(automatic_styles, "{%s}style" % NS["style"])
style.attrib["{%s}name" % NS["style"]] = "Default"
root = ET.Element('{%s}document-styles' % NS['office'])
ET.SubElement(root, '{%s}font-face-decls' % NS['office'])
automatic_styles = ET.SubElement(root, '{%s}styles' % NS['office'])
style = ET.SubElement(automatic_styles, '{%s}style' % NS['style'])
style.attrib['{%s}name' % NS['style']] = 'Default'
def define_number_style():
node = ET.SubElement(automatic_styles, '{%s}number-style' % NS['number'])
node.attrib["{%s}name" % NS["style"]] = "NumberFormat"
node.attrib['{%s}name' % NS['style']] = 'NumberFormat'
sub_node = ET.SubElement(node, '{%s}number' % NS['number'])
sub_node.attrib['{%s}decimal-places' % NS['number']] = '2'
sub_node.attrib['{%s}min-decimal-places' % NS['number']] = '2'
sub_node.attrib['{%s}min-integer-digits' % NS['number']] = '1'
sub_node.attrib['{%s}grouping' % NS['number']] = 'true'
style = ET.SubElement(automatic_styles, "{%s}style" % NS["style"])
style.attrib["{%s}name" % NS["style"]] = 'Number'
style.attrib["{%s}family" % NS["style"]] = "table-cell"
style.attrib["{%s}data-style-name" % NS["style"]] = "NumberFormat"
style.attrib["{%s}parent-style" % NS["style"]] = "Default"
style = ET.SubElement(automatic_styles, '{%s}style' % NS['style'])
style.attrib['{%s}name' % NS['style']] = 'Number'
style.attrib['{%s}family' % NS['style']] = 'table-cell'
style.attrib['{%s}data-style-name' % NS['style']] = 'NumberFormat'
style.attrib['{%s}parent-style' % NS['style']] = 'Default'
define_number_style()
def define_date_style(name, strftime_string):
node = ET.SubElement(automatic_styles, "{%s}date-style" % NS["number"])
node.attrib["{%s}name" % NS["style"]] = name + "NumberFormat"
for part in re.findall(r"%?.", strftime_string):
if part == "%Y":
ET.SubElement(node, "{%s}year" % NS["number"]).attrib["{%s}style" % NS["number"]] = "long"
elif part == "%m":
ET.SubElement(node, "{%s}month" % NS["number"]).attrib[
"{%s}style" % NS["number"]
] = "long"
elif part == "%d":
ET.SubElement(node, "{%s}day" % NS["number"]).attrib["{%s}style" % NS["number"]] = "long"
elif part == "%H":
ET.SubElement(node, "{%s}hours" % NS["number"]).attrib[
"{%s}style" % NS["number"]
] = "long"
elif part == "%M":
ET.SubElement(node, "{%s}minutes" % NS["number"]).attrib[
"{%s}style" % NS["number"]
] = "long"
elif part == "%S":
ET.SubElement(node, "{%s}seconds" % NS["number"]).attrib[
"{%s}style" % NS["number"]
] = "long"
node = ET.SubElement(automatic_styles, '{%s}date-style' % NS['number'])
node.attrib['{%s}name' % NS['style']] = name + 'NumberFormat'
for part in re.findall(r'%?.', strftime_string):
if part == '%Y':
ET.SubElement(node, '{%s}year' % NS['number']).attrib['{%s}style' % NS['number']] = 'long'
elif part == '%m':
ET.SubElement(node, '{%s}month' % NS['number']).attrib[
'{%s}style' % NS['number']
] = 'long'
elif part == '%d':
ET.SubElement(node, '{%s}day' % NS['number']).attrib['{%s}style' % NS['number']] = 'long'
elif part == '%H':
ET.SubElement(node, '{%s}hours' % NS['number']).attrib[
'{%s}style' % NS['number']
] = 'long'
elif part == '%M':
ET.SubElement(node, '{%s}minutes' % NS['number']).attrib[
'{%s}style' % NS['number']
] = 'long'
elif part == '%S':
ET.SubElement(node, '{%s}seconds' % NS['number']).attrib[
'{%s}style' % NS['number']
] = 'long'
else:
ET.SubElement(node, "{%s}text" % NS["number"]).text = part
style = ET.SubElement(automatic_styles, "{%s}style" % NS["style"])
style.attrib["{%s}name" % NS["style"]] = name
style.attrib["{%s}family" % NS["style"]] = "table-cell"
style.attrib["{%s}data-style-name" % NS["style"]] = name + "NumberFormat"
style.attrib["{%s}parent-style" % NS["style"]] = "Default"
ET.SubElement(node, '{%s}text' % NS['number']).text = part
style = ET.SubElement(automatic_styles, '{%s}style' % NS['style'])
style.attrib['{%s}name' % NS['style']] = name
style.attrib['{%s}family' % NS['style']] = 'table-cell'
style.attrib['{%s}data-style-name' % NS['style']] = name + 'NumberFormat'
style.attrib['{%s}parent-style' % NS['style']] = 'Default'
style = ET.SubElement(automatic_styles, "{%s}style" % NS["style"])
style.attrib["{%s}name" % NS["style"]] = name + "Column"
style.attrib["{%s}family" % NS["style"]] = "table-column"
ET.SubElement(style, "{%s}table-column-properties" % NS["style"]).attrib[
"{%s}column-width" % NS["style"]
] = "80mm"
style = ET.SubElement(automatic_styles, '{%s}style' % NS['style'])
style.attrib['{%s}name' % NS['style']] = name + 'Column'
style.attrib['{%s}family' % NS['style']] = 'table-column'
ET.SubElement(style, '{%s}table-column-properties' % NS['style']).attrib[
'{%s}column-width' % NS['style']
] = '80mm'
define_date_style("Date", '%d/%m/%Y')
define_date_style("DateTime", '%d/%m/%Y %H:%M')
define_date_style('Date', '%d/%m/%Y')
define_date_style('DateTime', '%d/%m/%Y %H:%M')
return root
def get_styles(self):
return ET.tostring(self.get_styles_node(), "utf-8")
return ET.tostring(self.get_styles_node(), 'utf-8')
def get_content(self):
return ET.tostring(self.get_content_node(), "utf-8")
return ET.tostring(self.get_content_node(), 'utf-8')
def save(self, output):
with zipfile.ZipFile(output, "w") as z:
z.writestr("content.xml", self.get_content())
z.writestr("styles.xml", self.get_styles())
z.writestr("mimetype", "application/vnd.oasis.opendocument.spreadsheet")
with zipfile.ZipFile(output, 'w') as z:
z.writestr('content.xml', self.get_content())
z.writestr('styles.xml', self.get_styles())
z.writestr('mimetype', 'application/vnd.oasis.opendocument.spreadsheet')
z.writestr(
"META-INF/manifest.xml",
'META-INF/manifest.xml',
"""<?xml version="1.0" encoding="UTF-8"?>
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">
<manifest:file-entry manifest:full-path="/" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>
@ -168,15 +168,15 @@ class WorkSheet:
self.cells[row][column] = WorkCell(self, value, **kwargs)
def get_node(self):
root = ET.Element("{%s}table" % NS["table"])
root.attrib["{%s}name" % NS["table"]] = self.name
ET.SubElement(root, "{%s}table-column" % NS["table"])
root = ET.Element('{%s}table' % NS['table'])
root.attrib['{%s}name' % NS['table']] = self.name
ET.SubElement(root, '{%s}table-column' % NS['table'])
for i in range(0, max(self.cells.keys()) + 1):
row = ET.SubElement(root, "{%s}table-row" % NS["table"])
row = ET.SubElement(root, '{%s}table-row' % NS['table'])
for j in range(0, max(self.cells.get(i).keys()) + 1):
cell = self.cells.get(i, {}).get(j, None)
if not cell:
ET.SubElement(row, "{%s}table-cell" % NS["table"])
ET.SubElement(row, '{%s}table-cell' % NS['table'])
else:
row.append(cell.get_node())
return root
@ -185,39 +185,39 @@ class WorkSheet:
class WorkCell:
def __init__(self, worksheet, value):
if value is None:
value = ""
value = ''
self.worksheet = worksheet
self.native_value = value
value = force_text(value)
for i in range(0x20): # remove control characters
char = chr(i)
if char in ("\t", "\r", "\n"):
if char in ('\t', '\r', '\n'):
# only allow tab, carriage return and line feed.
continue
value = value.replace(char, "")
value = value.replace(char, '')
# fffe and ffff are also invalid characters
value = value.replace("\ufffe", "").replace("\uffff", "")
value = value.replace('\ufffe', '').replace('\uffff', '')
self.value = value
def get_node(self):
root = ET.Element("{%s}table-cell" % NS["table"])
p = ET.SubElement(root, "{%s}p" % NS["text"])
root = ET.Element('{%s}table-cell' % NS['table'])
p = ET.SubElement(root, '{%s}p' % NS['text'])
p.text = self.value
value = self.native_value
if is_number(value):
root.attrib["{%s}value-type" % NS["office"]] = "float"
root.attrib["{%s}value" % NS["office"]] = self.value
root.attrib["{%s}style-name" % NS["table"]] = "Number"
root.attrib['{%s}value-type' % NS['office']] = 'float'
root.attrib['{%s}value' % NS['office']] = self.value
root.attrib['{%s}style-name' % NS['table']] = 'Number'
elif isinstance(value, datetime):
root.attrib["{%s}style-name" % NS["table"]] = "DateTime"
root.attrib["{%s}value-type" % NS["office"]] = "date"
root.attrib["{%s}date-value" % NS["office"]] = value.strftime("%Y-%m-%dT%H:%M:%S")
p.text = value.strftime("%d/%m/%Y %H:%M:%S")
root.attrib['{%s}style-name' % NS['table']] = 'DateTime'
root.attrib['{%s}value-type' % NS['office']] = 'date'
root.attrib['{%s}date-value' % NS['office']] = value.strftime('%Y-%m-%dT%H:%M:%S')
p.text = value.strftime('%d/%m/%Y %H:%M:%S')
elif isinstance(value, date):
root.attrib["{%s}style-name" % NS["table"]] = "Date"
root.attrib["{%s}value-type" % NS["office"]] = "date"
root.attrib["{%s}date-value" % NS["office"]] = value.strftime("%Y-%m-%d")
p.text = value.strftime("%d/%m/%Y")
root.attrib['{%s}style-name' % NS['table']] = 'Date'
root.attrib['{%s}value-type' % NS['office']] = 'date'
root.attrib['{%s}date-value' % NS['office']] = value.strftime('%Y-%m-%d')
p.text = value.strftime('%d/%m/%Y')
else:
root.attrib["{%s}value-type" % NS["office"]] = "string"
root.attrib['{%s}value-type' % NS['office']] = 'string'
return root

View File

@ -86,11 +86,11 @@ LOGGING = {
# timezone as the operating system.
# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = "Europe/Paris"
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 = "fr-fr"
LANGUAGE_CODE = 'fr-fr'
SITE_ID = 1
@ -110,28 +110,28 @@ LOCALE_PATHS = (os.path.join(BASE_DIR, 'eo_gestion', 'locale'),)
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/"
MEDIA_URL = "/media/"
MEDIA_URL = '/media/'
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = "/static/"
STATIC_URL = '/static/'
STATICFILES_FINDERS = list(global_settings.STATICFILES_FINDERS) + ['gadjo.finders.XStaticFinder']
# Make this unique, and don't share it with anybody.
SECRET_KEY = "5w+ifr2ho!#x06q7dshr08wd#gt0wwp@wvbvw33kmtb+x$(9ts"
SECRET_KEY = '5w+ifr2ho!#x06q7dshr08wd#gt0wwp@wvbvw33kmtb+x$(9ts'
MIDDLEWARE = (
"django.middleware.common.CommonMiddleware",
"django.middleware.http.ConditionalGetMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
'django.middleware.common.CommonMiddleware',
'django.middleware.http.ConditionalGetMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
ROOT_URLCONF = "eo_gestion.urls"
ROOT_URLCONF = 'eo_gestion.urls'
# Templates
TEMPLATES = [
@ -157,17 +157,17 @@ TEMPLATES = [
]
INSTALLED_APPS = (
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.sites",
"django.contrib.messages",
"django.contrib.staticfiles",
"django.contrib.humanize",
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
# Uncomment the next line to enable the admin:
"django.contrib.admin",
"eo_gestion.eo_facture",
"eo_gestion.eo_banque",
'django.contrib.admin',
'eo_gestion.eo_facture',
'eo_gestion.eo_banque',
'eo_gestion.eo_conges',
'eo_gestion.chorus',
'taggit',
@ -180,7 +180,7 @@ AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
LOGIN_REDIRECT_URL = "/"
LOGIN_REDIRECT_URL = '/'
# timeout used in python-requests call, in seconds
# timeout just after web server, which is usually 30s,
@ -207,7 +207,7 @@ WORKERS_CALENDAR_CONFIG = {
],
}
local_settings_file = os.environ.get("BARBACOMPTA_SETTINGS_FILE", "local_settings.py")
local_settings_file = os.environ.get('BARBACOMPTA_SETTINGS_FILE', 'local_settings.py')
if os.path.exists(local_settings_file):
with open(local_settings_file) as fd:
exec(fd.read())

View File

@ -162,7 +162,7 @@ class SortableAdminMixin(SortableAdminBase):
first_order_direction, first_order_field_index = self._get_first_ordering(request)
if first_order_field_index == self.default_order_field_index:
self.enable_sorting = True
self.order_by = f"{first_order_direction}{self.default_order_field}"
self.order_by = f'{first_order_direction}{self.default_order_field}'
else:
self.enable_sorting = False
return super().get_changelist(request, **kwargs)
@ -178,9 +178,9 @@ class SortableAdminMixin(SortableAdminBase):
first_order_direction = self.default_order_direction
else:
first_order_field_index = None
first_order_direction = ""
for p in order_var.split("."):
none, prefix, index = p.rpartition("-")
first_order_direction = ''
for p in order_var.split('.'):
none, prefix, index = p.rpartition('-')
try:
index = int(index)
except ValueError:
@ -316,8 +316,8 @@ class SortableAdminMixin(SortableAdminBase):
# noinspection PyProtectedMember
raise model.MultipleObjectsReturned(
"Detected non-unique values in field '{rank_field}' used for sorting this model.\n"
"Consider to run \n python manage.py reorder {model._meta.label}\n"
"to adjust this inconsistency."
'Consider to run \n python manage.py reorder {model._meta.label}\n'
'to adjust this inconsistency.'
)
move_qs = model.objects.filter(**move_filter).order_by(order_by)
@ -398,7 +398,7 @@ class SortableAdminMixin(SortableAdminBase):
queryset_size = queryset.count()
page_size = page.end_index() - page.start_index() + 1
if queryset_size > page_size:
msg = _(f"The target page size is {page_size}. It is too small for {queryset_size} items.")
msg = _(f'The target page size is {page_size}. It is too small for {queryset_size} items.')
self.message_user(request, msg, level=messages.ERROR)
return

View File

@ -2,8 +2,8 @@
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "eo_gestion.settings")
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'eo_gestion.settings')
from django.core.management import execute_from_command_line

View File

@ -29,11 +29,11 @@ def test_references(app):
if i % 3 == 1:
contract.tags.add(gi)
response = app.get("/api/references/")
response = app.get('/api/references/')
assert any(row['tags'] for row in response.json['data'])
response_gru = app.get("/api/references/", params={'tags': 'GRU'})
response_gru = app.get('/api/references/', params={'tags': 'GRU'})
assert len(response_gru.json['data']) == 12
response_gi = app.get("/api/references/", params={'tags': 'Gestion d\'identité'})
response_gi = app.get('/api/references/', params={'tags': 'Gestion d\'identité'})
assert len(response_gi.json['data']) == 18
response_gru_and_gi = app.get("/api/references/", params={'tags': ['GRU', 'Gestion d\'identité']})
response_gru_and_gi = app.get('/api/references/', params={'tags': ['GRU', 'Gestion d\'identité']})
assert len(response_gru_and_gi.json['data']) == 30

View File

@ -19,27 +19,27 @@ import pytest
@pytest.fixture
def homepage(app):
response = app.get("/").follow()
response = app.get('/').follow()
response.form.set("username", "admin")
response.form.set("password", "admin")
response.form.set('username', 'admin')
response.form.set('password', 'admin')
return response.form.submit().follow()
def test_misc(homepage):
clients = homepage.click("Clients")
clients = homepage.click('Clients')
str(clients)
ajouter_un_client = homepage.click("Ajouter un client")
ajouter_un_client = homepage.click('Ajouter un client')
str(ajouter_un_client)
contrats = homepage.click("Contrats")
contrats = homepage.click('Contrats')
contrat_2c210afd24c11596eeaf94bfb = contrats.click('2c210afd24c11596eeaf94bfb', href='change')
str(contrat_2c210afd24c11596eeaf94bfb)
ajouter_un_contrat = homepage.click("Ajouter un contrat")
ajouter_un_contrat = homepage.click('Ajouter un contrat')
str(ajouter_un_contrat)
compte_en_banque = homepage.click("Compte en banque")
compte_en_banque = homepage.click('Compte en banque')
str(compte_en_banque)
factures = homepage.click("Factures")
factures = homepage.click('Factures')
factures_00137 = factures.click('F20190137')
str(factures_00137)
rapid = factures.click('Rapid')
@ -47,10 +47,10 @@ def test_misc(homepage):
def test_ods_export(app):
response = app.get("/eo_facture/facture/").follow()
response = app.get('/eo_facture/facture/').follow()
response.form.set("username", "admin")
response.form.set("password", "admin")
response.form.set('username', 'admin')
response.form.set('password', 'admin')
factures = response.form.submit().follow()
@ -59,9 +59,9 @@ def test_ods_export(app):
def test_odt_export(app):
response = app.get("/eo_facture/contrat/").follow()
response.form.set("username", "admin")
response.form.set("password", "admin")
response = app.get('/eo_facture/contrat/').follow()
response.form.set('username', 'admin')
response.form.set('password', 'admin')
contracts = response.form.submit().follow()
form = contracts.forms['changelist-form']
@ -74,9 +74,9 @@ def test_odt_export(app):
def test_zip_export(app):
response = app.get("/eo_facture/facture/").follow()
response.form.set("username", "admin")
response.form.set("password", "admin")
response = app.get('/eo_facture/facture/').follow()
response.form.set('username', 'admin')
response.form.set('password', 'admin')
factures = response.form.submit().follow()
form = factures.forms['changelist-form']

View File

@ -21,30 +21,30 @@ from django.core.management import call_command
User = get_user_model()
DATA = ["tests/fixture.json"]
DATA = ['tests/fixture.json']
@pytest.fixture(scope="session")
@pytest.fixture(scope='session')
def django_db_setup(django_db_setup, django_db_blocker, django_db_keepdb, django_db_createdb):
with django_db_blocker.unblock():
if not django_db_keepdb or django_db_createdb or User.objects.count() == 0:
for data in DATA:
call_command("loaddata", data)
call_command('loaddata', data)
admin, _ = User.objects.update_or_create(
username="admin",
defaults=dict(email="admin@example.com", is_superuser=True, is_staff=True),
username='admin',
defaults=dict(email='admin@example.com', is_superuser=True, is_staff=True),
)
admin.set_password("admin")
admin.set_password('admin')
admin.save()
yield
@pytest.fixture
def app(db, freezer):
freezer.move_to("2019-01-01")
freezer.move_to('2019-01-01')
wtm = django_webtest.WebTestMixin()
wtm._patch_settings()
try:
return django_webtest.DjangoTestApp(extra_environ={"HTTP_HOST": "localhost"})
return django_webtest.DjangoTestApp(extra_environ={'HTTP_HOST': 'localhost'})
finally:
wtm._unpatch_settings()

View File

@ -16,7 +16,7 @@
import os
ALLOWED_HOSTS = ["localhost"]
ALLOWED_HOSTS = ['localhost']
DATABASES = {
'default': {

View File

@ -44,8 +44,8 @@ class TestLoggedIn:
response.form['periodicite'] = 'annuelle'
response.form['periodicite_debut'] = '2018-12-01'
response = response.form.submit('_continue').follow()
response.forms["contrat_form"]['periodicite_debut'] = '2018-12-02'
response = response.forms["contrat_form"].submit('_continue').follow()
response.forms['contrat_form']['periodicite_debut'] = '2018-12-02'
response = response.forms['contrat_form'].submit('_continue').follow()
# Créer la facture de première échéance
response = app.get('/')

View File

@ -135,7 +135,7 @@ def test_conges_no_match_error(mocked_get_events, app, settings):
login(app)
resp = app.get('/conges/2023/01/')
assert escape("Aucun·e coopérateurice trouvé·e pour les évènements : xxx, yyy") in resp.text
assert escape('Aucun·e coopérateurice trouvé·e pour les évènements : xxx, yyy') in resp.text
assert 'le 06/01' in resp.text

View File

@ -42,13 +42,13 @@ def test_limitations(db):
def test_facture_avoir(app):
response = app.get("/eo_facture/facture/").follow()
response = app.get('/eo_facture/facture/').follow()
response.form.set("username", "admin")
response.form.set("password", "admin")
response.form.set('username', 'admin')
response.form.set('password', 'admin')
homepage = response.form.submit().follow()
factures_page = homepage.click("Factures")
factures_page = homepage.click('Factures')
facture_0137_page = factures_page.click('F20190137')
assert 'F20190137' in facture_0137_page.html.find('div', {'class': 'breadcrumbs'}).text
@ -57,7 +57,7 @@ def test_facture_avoir(app):
facture = [x for x in Facture.objects.all() if x.code() == 'F20190137'][0]
assert facture.factures_avoir.count() == 0
assert 'Annuler' in [li.a.text for li in facture_0137_page.html.find_all('li')]
facture_avoir_page = facture_0137_page.click("Annuler")
facture_avoir_page = facture_0137_page.click('Annuler')
facture_avoir_page = facture_avoir_page.follow()
assert facture.factures_avoir.count() == 1
facture_avoir = facture.factures_avoir.first()
@ -96,7 +96,7 @@ def test_facture_avoir(app):
assert facture_avoir.code() == 'F20190237'
assert 'Imprimer' in [li.a.text for li in facture_avoir_page.html.find_all('li')]
factur_x_page = app.get("/eo_facture/facture/%s/view_pdf/F20190137.pdf?facturx" % facture_avoir.id)
factur_x_page = app.get('/eo_facture/facture/%s/view_pdf/F20190137.pdf?facturx' % facture_avoir.id)
factur_x_pdf = factur_x_page.body
_, factur_x_xml = facturx.get_facturx_xml_from_pdf(io.BytesIO(factur_x_pdf))
root = ET.fromstring(factur_x_xml)
@ -174,32 +174,32 @@ def test_facture_filename(app, settings):
settings.FACTURE_DIR = tmpdir
facture = [x for x in Facture.objects.all() if x.code() == 'F20190137'][0]
response = app.get("/eo_facture/facture/").follow()
response.form.set("username", "admin")
response.form.set("password", "admin")
response = app.get('/eo_facture/facture/').follow()
response.form.set('username', 'admin')
response.form.set('password', 'admin')
homepage = response.form.submit().follow()
# facture F20190137
factures_page = homepage.click("Factures")
factures_page = homepage.click('Factures')
facture_0137_page = factures_page.click(facture.code())
assert (
'/view_pdf/F20190137.pdf'
in [li.a['href'] for li in facture_0137_page.html.find_all('li') if li.text == 'Imprimer'][0]
)
app.get("/eo_facture/facture/%s/view_pdf/" % facture.id)
assert os.path.exists(os.path.join(tmpdir, "F20190137-c3f42bb0d75d379.pdf"))
app.get('/eo_facture/facture/%s/view_pdf/' % facture.id)
assert os.path.exists(os.path.join(tmpdir, 'F20190137-c3f42bb0d75d379.pdf'))
# facture avoir proforma
facture_avoir_page = facture_0137_page.click("Annuler")
facture_avoir_page = facture_0137_page.click('Annuler')
facture_avoir_page = facture_avoir_page.follow()
facture_avoir = facture.factures_avoir.first()
assert (
'/view_pdf/Devis n°%s du 2019-10-09-AVOIR.pdf' % facture_avoir.id
in [li.a['href'] for li in facture_avoir_page.html.find_all('li') if li.text == 'Imprimer'][0]
)
app.get("/eo_facture/facture/%s/view_pdf/" % facture_avoir.id)
app.get('/eo_facture/facture/%s/view_pdf/' % facture_avoir.id)
assert os.path.exists(
os.path.join(tmpdir, "Devis n°%s du 2019-10-09-c3f42bb0d75d379-AVOIR.pdf" % facture_avoir.id)
os.path.join(tmpdir, 'Devis n°%s du 2019-10-09-c3f42bb0d75d379-AVOIR.pdf' % facture_avoir.id)
)
# facture avoir
@ -211,8 +211,8 @@ def test_facture_filename(app, settings):
'/view_pdf/F20190237-AVOIR.pdf'
in [li.a['href'] for li in facture_avoir_page.html.find_all('li') if li.text == 'Imprimer'][0]
)
app.get("/eo_facture/facture/%s/view_pdf/" % facture_avoir.id)
assert os.path.exists(os.path.join(tmpdir, "F20190237-c3f42bb0d75d379-AVOIR.pdf"))
app.get('/eo_facture/facture/%s/view_pdf/' % facture_avoir.id)
assert os.path.exists(os.path.join(tmpdir, 'F20190237-c3f42bb0d75d379-AVOIR.pdf'))
def test_facture_pdf(app):