From f1941a3ad8fd726321ce19b2e0ce22a2a5911a6c Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Wed, 16 Aug 2023 11:52:16 +0200 Subject: [PATCH] misc: apply double-quote-string-fixer (#79788) --- debian/config.py | 6 +- eo_gestion/actions.py | 14 +- eo_gestion/admin.py | 12 +- eo_gestion/eo_banque/admin.py | 2 +- .../management/commands/load-csv-banquepop.py | 6 +- .../management/commands/nouveau-solde.py | 4 +- eo_gestion/eo_banque/models.py | 8 +- .../eo_banque/templatetags/eo_banque.py | 24 +-- eo_gestion/eo_facture/admin.py | 48 ++--- eo_gestion/eo_facture/fields.py | 30 +-- eo_gestion/eo_facture/forms.py | 28 +-- eo_gestion/eo_facture/models.py | 54 +++--- .../eo_facture/templatetags/eo_facture.py | 12 +- eo_gestion/ods.py | 182 +++++++++--------- eo_gestion/settings.py | 50 ++--- eo_gestion/vendor/adminsortable2/admin.py | 14 +- manage.py | 4 +- tests/base/test_api.py | 8 +- tests/base/test_homepage.py | 36 ++-- tests/conftest.py | 16 +- tests/settings.py | 2 +- tests/test_admin.py | 4 +- tests/test_conges.py | 2 +- tests/test_factures_avoir.py | 34 ++-- 24 files changed, 300 insertions(+), 300 deletions(-) diff --git a/debian/config.py b/debian/config.py index 6b80606..1f728ca 100644 --- a/debian/config.py +++ b/debian/config.py @@ -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'}] diff --git a/eo_gestion/actions.py b/eo_gestion/actions.py index 53aa24b..04b0660 100644 --- a/eo_gestion/actions.py +++ b/eo_gestion/actions.py @@ -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') diff --git a/eo_gestion/admin.py b/eo_gestion/admin.py index 2966213..7e3a76f 100644 --- a/eo_gestion/admin.py +++ b/eo_gestion/admin.py @@ -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) diff --git a/eo_gestion/eo_banque/admin.py b/eo_gestion/eo_banque/admin.py index c26f585..4046c12 100644 --- a/eo_gestion/eo_banque/admin.py +++ b/eo_gestion/eo_banque/admin.py @@ -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): diff --git a/eo_gestion/eo_banque/management/commands/load-csv-banquepop.py b/eo_gestion/eo_banque/management/commands/load-csv-banquepop.py index a575285..0672b1b 100644 --- a/eo_gestion/eo_banque/management/commands/load-csv-banquepop.py +++ b/eo_gestion/eo_banque/management/commands/load-csv-banquepop.py @@ -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 diff --git a/eo_gestion/eo_banque/management/commands/nouveau-solde.py b/eo_gestion/eo_banque/management/commands/nouveau-solde.py index 9f21b82..fcf82f8 100644 --- a/eo_gestion/eo_banque/management/commands/nouveau-solde.py +++ b/eo_gestion/eo_banque/management/commands/nouveau-solde.py @@ -14,8 +14,8 @@ class Command(BaseCommand): can_import_django_settings = True output_transaction = True requires_system_checks = True - args = " ..." - help = "Charge le solde courant" + args = ' ...' + help = 'Charge le solde courant' @transaction.atomic def handle(self, compte, montant, **options): diff --git a/eo_gestion/eo_banque/models.py b/eo_gestion/eo_banque/models.py index 28304d5..04ecd95 100644 --- a/eo_gestion/eo_banque/models.py +++ b/eo_gestion/eo_banque/models.py @@ -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()) diff --git a/eo_gestion/eo_banque/templatetags/eo_banque.py b/eo_gestion/eo_banque/templatetags/eo_banque.py index 44adb10..89e3e92 100644 --- a/eo_gestion/eo_banque/templatetags/eo_banque.py +++ b/eo_gestion/eo_banque/templatetags/eo_banque.py @@ -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) diff --git a/eo_gestion/eo_facture/admin.py b/eo_gestion/eo_facture/admin.py index 2e8a1d1..35ccad0 100644 --- a/eo_gestion/eo_facture/admin.py +++ b/eo_gestion/eo_facture/admin.py @@ -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('{1}', 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/', diff --git a/eo_gestion/eo_facture/fields.py b/eo_gestion/eo_facture/fields.py index bf3ea6b..f8de423 100644 --- a/eo_gestion/eo_facture/fields.py +++ b/eo_gestion/eo_facture/fields.py @@ -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) diff --git a/eo_gestion/eo_facture/forms.py b/eo_gestion/eo_facture/forms.py index 5227b78..c1adb40 100644 --- a/eo_gestion/eo_facture/forms.py +++ b/eo_gestion/eo_facture/forms.py @@ -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',) diff --git a/eo_gestion/eo_facture/models.py b/eo_gestion/eo_facture/models.py index 9eb8f34..8159fc2 100644 --- a/eo_gestion/eo_facture/models.py +++ b/eo_gestion/eo_facture/models.py @@ -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 diff --git a/eo_gestion/eo_facture/templatetags/eo_facture.py b/eo_gestion/eo_facture/templatetags/eo_facture.py index 773c267..35ab3fb 100644 --- a/eo_gestion/eo_facture/templatetags/eo_facture.py +++ b/eo_gestion/eo_facture/templatetags/eo_facture.py @@ -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 diff --git a/eo_gestion/ods.py b/eo_gestion/ods.py index 8e8db6d..6119281 100644 --- a/eo_gestion/ods.py +++ b/eo_gestion/ods.py @@ -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', """ @@ -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 diff --git a/eo_gestion/settings.py b/eo_gestion/settings.py index 36c5b84..1af58b1 100644 --- a/eo_gestion/settings.py +++ b/eo_gestion/settings.py @@ -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()) diff --git a/eo_gestion/vendor/adminsortable2/admin.py b/eo_gestion/vendor/adminsortable2/admin.py index 4d17d63..29646bf 100644 --- a/eo_gestion/vendor/adminsortable2/admin.py +++ b/eo_gestion/vendor/adminsortable2/admin.py @@ -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 diff --git a/manage.py b/manage.py index 36c7900..8c107ce 100755 --- a/manage.py +++ b/manage.py @@ -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 diff --git a/tests/base/test_api.py b/tests/base/test_api.py index 4f2d57c..70f919b 100644 --- a/tests/base/test_api.py +++ b/tests/base/test_api.py @@ -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 diff --git a/tests/base/test_homepage.py b/tests/base/test_homepage.py index 53e4915..e4ef380 100644 --- a/tests/base/test_homepage.py +++ b/tests/base/test_homepage.py @@ -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'] diff --git a/tests/conftest.py b/tests/conftest.py index 60c5b61..c0c6a1c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -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() diff --git a/tests/settings.py b/tests/settings.py index 0d89b52..60e2178 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -16,7 +16,7 @@ import os -ALLOWED_HOSTS = ["localhost"] +ALLOWED_HOSTS = ['localhost'] DATABASES = { 'default': { diff --git a/tests/test_admin.py b/tests/test_admin.py index 827b5da..c8d8273 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -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('/') diff --git a/tests/test_conges.py b/tests/test_conges.py index a1abafa..42d6bb9 100644 --- a/tests/test_conges.py +++ b/tests/test_conges.py @@ -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 diff --git a/tests/test_factures_avoir.py b/tests/test_factures_avoir.py index 2903fad..293f6f0 100644 --- a/tests/test_factures_avoir.py +++ b/tests/test_factures_avoir.py @@ -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):