From c4da428fc9ec439389b7473ba5638d9f82085475 Mon Sep 17 00:00:00 2001 From: luxagraf Date: Sun, 13 Jan 2019 11:51:02 -0600 Subject: updated income and resume apps --- app/income/models.py | 13 ++++++-- app/income/parser.py | 42 +++++++++++++----------- app/income/views.py | 14 +++++--- app/resume/admin.py | 18 +++++++--- app/resume/migrations/0004_job_resume.py | 37 +++++++++++++++++++++ app/resume/migrations/0005_job_slug.py | 18 ++++++++++ app/resume/migrations/0006_auto_20190112_1257.py | 22 +++++++++++++ app/resume/migrations/0007_auto_20190113_1128.py | 18 ++++++++++ app/resume/migrations/0008_auto_20190113_1139.py | 24 ++++++++++++++ app/resume/migrations/0009_job_body_html.py | 18 ++++++++++ app/resume/migrations/0010_auto_20190113_1147.py | 25 ++++++++++++++ app/resume/models.py | 37 +++++++++++++++++++++ app/resume/urls.py | 29 +++++++++------- app/resume/views.py | 10 ++++-- app/utils/util.py | 11 +++++++ 15 files changed, 292 insertions(+), 44 deletions(-) create mode 100644 app/resume/migrations/0004_job_resume.py create mode 100644 app/resume/migrations/0005_job_slug.py create mode 100644 app/resume/migrations/0006_auto_20190112_1257.py create mode 100644 app/resume/migrations/0007_auto_20190113_1128.py create mode 100644 app/resume/migrations/0008_auto_20190113_1139.py create mode 100644 app/resume/migrations/0009_job_body_html.py create mode 100644 app/resume/migrations/0010_auto_20190113_1147.py (limited to 'app') diff --git a/app/income/models.py b/app/income/models.py index 688d1d7..e5a351b 100644 --- a/app/income/models.py +++ b/app/income/models.py @@ -69,6 +69,9 @@ class InvoiceItem(models.Model): time_end = models.DateTimeField(null=True, blank=True) work_done = models.TextField(null=True, blank=True) + class Meta: + ordering = ('time_start',) + def __str__(self): return str(self.time_start) @@ -89,6 +92,12 @@ class InvoiceItem(models.Model): half_period_seconds = period_seconds / 2 remainder = td.total_seconds() % period_seconds if remainder >= half_period_seconds: - return timedelta(seconds=td.total_seconds() + (period_seconds - remainder)) + tdr = timedelta(seconds=td.total_seconds() + (period_seconds - remainder)) + hours, remainder = divmod(tdr.total_seconds(), 3600) + r = remainder/3600 + return float(hours)+r else: - return timedelta(seconds=td.total_seconds() - remainder) + tdr = timedelta(seconds=td.total_seconds() - remainder) + hours, remainder = divmod(tdr.total_seconds(), 3600) + r = remainder/3600 + return float(hours)+r diff --git a/app/income/parser.py b/app/income/parser.py index 9524902..b19d039 100644 --- a/app/income/parser.py +++ b/app/income/parser.py @@ -1,19 +1,23 @@ -with open('timesheet.csv', newline='') as csvfile: - reader = csv.reader(csvfile, delimiter=';') - counter = 0 - f = "%Y-%m-%d %H:%M:%S" - for row in reader: - if counter > 0: - timer = row[0]+' '+row[1] - timerer = row[0]+' '+row[2] - time_start = datetime.datetime.strptime(timer, f) - time_end = datetime.datetime.strptime(timerer, f) - print(row[4]) - print(timerer, time_end) - InvoiceItem.objects.get_or_create( - time_start=time_start, - time_end=time_end, - work_done=row[4] - ) - counter = counter +1 -f = "%Y-%m-%d %H:%M:%S" +import csv +import datetime +from .models import InvoiceItem + + +def read_timesheet(): + with open('timesheet.csv', newline='') as csvfile: + reader = csv.reader(csvfile, delimiter=';') + counter = 0 + f = "%Y-%m-%d %H:%M:%S" + for row in reader: + if counter > 0: + print(row[4]) + timer = row[0]+' '+row[1] + timerer = row[0]+' '+row[2] + time_start = datetime.datetime.strptime(timer, f) + time_end = datetime.datetime.strptime(timerer, f) + InvoiceItem.objects.get_or_create( + time_start=time_start, + time_end=time_end, + work_done=row[4] + ) + counter = counter + 1 diff --git a/app/income/views.py b/app/income/views.py index 2c3e34a..fc22c0d 100644 --- a/app/income/views.py +++ b/app/income/views.py @@ -20,8 +20,7 @@ class MonthlyInvoiceView(DetailView): total_time = [] for item in context['object_list']: total_time.append(item.rounded_total) - duration = (sum(total_time, datetime.timedelta())) - hours = duration.total_seconds() // 3600 + hours = (sum(total_time)) context['total_hours'] = hours context['total_billed'] = int(hours * 100) context['invoice_number'] = self.object.id+21 @@ -37,10 +36,17 @@ class DownloadMonthlyInvoiceView(MonthlyInvoiceView): logger = logging.getLogger('weasyprint') logger.addHandler(logging.FileHandler('weasyprint.log')) self.object = self.get_object() # assign the object to the view - c = {'object': self.object} + context = self.get_context_data() + c = { + 'object': self.object, + 'object_list': context['object_list'], + 'total_hours': context['total_hours'], + 'total_billed': context['total_billed'], + 'invoice_number': self.object.id+23 + } t = render_to_string('details/invoice.html', c).encode('utf-8') html = HTML(string=t, base_url=self.request.build_absolute_uri()) - pdf = html.write_pdf(stylesheets=[CSS(settings.MEDIA_ROOT + 'site/media/pdf_gen.css')], presentational_hints=True) + pdf = html.write_pdf(stylesheets=[CSS(settings.MEDIA_ROOT + '/pdf_gen.css')], presentational_hints=True) response = HttpResponse(pdf, content_type='application/pdf') response['Content-Disposition'] = 'inline; filename="invoice.pdf"' return response diff --git a/app/resume/admin.py b/app/resume/admin.py index 93b186e..0a7594d 100644 --- a/app/resume/admin.py +++ b/app/resume/admin.py @@ -1,15 +1,23 @@ from django.contrib import admin -from .models import Publisher, PubItem +from .models import Publisher, PubItem, Job, Resume -class PublisherAdmin(admin.ModelAdmin): +@admin.register(Job) +class JobAdmin(admin.ModelAdmin): + pass + + +@admin.register(Resume) +class ResumeAdmin(admin.ModelAdmin): pass +@admin.register(Publisher) +class PublisherAdmin(admin.ModelAdmin): + pass + +@admin.register(PubItem) class PubItemAdmin(admin.ModelAdmin): list_display = ('title', 'pub_date', 'publisher', 'admin_link') pass - -admin.site.register(Publisher, PublisherAdmin) -admin.site.register(PubItem, PubItemAdmin) diff --git a/app/resume/migrations/0004_job_resume.py b/app/resume/migrations/0004_job_resume.py new file mode 100644 index 0000000..e056fec --- /dev/null +++ b/app/resume/migrations/0004_job_resume.py @@ -0,0 +1,37 @@ +# Generated by Django 2.1.1 on 2019-01-12 12:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('resume', '0003_auto_20151211_1925'), + ] + + operations = [ + migrations.CreateModel( + name='Job', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('employer', models.CharField(max_length=200)), + ('date_start', models.DateField(verbose_name='Date Start')), + ('date_end', models.DateField(blank=True, null=True, verbose_name='Date End')), + ('body_markdown', models.TextField(blank=True, null=True)), + ], + options={ + 'ordering': ('-date_end',), + }, + ), + migrations.CreateModel( + name='Resume', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('profile', models.TextField()), + ('skills', models.TextField()), + ('experience', models.ManyToManyField(to='resume.Job')), + ], + ), + ] diff --git a/app/resume/migrations/0005_job_slug.py b/app/resume/migrations/0005_job_slug.py new file mode 100644 index 0000000..d18baeb --- /dev/null +++ b/app/resume/migrations/0005_job_slug.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.1 on 2019-01-12 12:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('resume', '0004_job_resume'), + ] + + operations = [ + migrations.AddField( + model_name='job', + name='slug', + field=models.CharField(blank=True, max_length=50), + ), + ] diff --git a/app/resume/migrations/0006_auto_20190112_1257.py b/app/resume/migrations/0006_auto_20190112_1257.py new file mode 100644 index 0000000..9ee8f1b --- /dev/null +++ b/app/resume/migrations/0006_auto_20190112_1257.py @@ -0,0 +1,22 @@ +# Generated by Django 2.1.1 on 2019-01-12 12:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('resume', '0005_job_slug'), + ] + + operations = [ + migrations.RemoveField( + model_name='job', + name='slug', + ), + migrations.AddField( + model_name='resume', + name='slug', + field=models.CharField(blank=True, max_length=50), + ), + ] diff --git a/app/resume/migrations/0007_auto_20190113_1128.py b/app/resume/migrations/0007_auto_20190113_1128.py new file mode 100644 index 0000000..a635258 --- /dev/null +++ b/app/resume/migrations/0007_auto_20190113_1128.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.1 on 2019-01-13 11:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('resume', '0006_auto_20190112_1257'), + ] + + operations = [ + migrations.AlterField( + model_name='job', + name='employer', + field=models.CharField(max_length=200, null=True), + ), + ] diff --git a/app/resume/migrations/0008_auto_20190113_1139.py b/app/resume/migrations/0008_auto_20190113_1139.py new file mode 100644 index 0000000..29d975d --- /dev/null +++ b/app/resume/migrations/0008_auto_20190113_1139.py @@ -0,0 +1,24 @@ +# Generated by Django 2.1.1 on 2019-01-13 11:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('resume', '0007_auto_20190113_1128'), + ] + + operations = [ + migrations.RenameField( + model_name='resume', + old_name='experience', + new_name='jobs', + ), + migrations.AlterField( + model_name='job', + name='employer', + field=models.CharField(blank=True, default='', max_length=200), + preserve_default=False, + ), + ] diff --git a/app/resume/migrations/0009_job_body_html.py b/app/resume/migrations/0009_job_body_html.py new file mode 100644 index 0000000..fdeea15 --- /dev/null +++ b/app/resume/migrations/0009_job_body_html.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.1 on 2019-01-13 11:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('resume', '0008_auto_20190113_1139'), + ] + + operations = [ + migrations.AddField( + model_name='job', + name='body_html', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/app/resume/migrations/0010_auto_20190113_1147.py b/app/resume/migrations/0010_auto_20190113_1147.py new file mode 100644 index 0000000..879bd55 --- /dev/null +++ b/app/resume/migrations/0010_auto_20190113_1147.py @@ -0,0 +1,25 @@ +# Generated by Django 2.1.1 on 2019-01-13 11:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('resume', '0009_job_body_html'), + ] + + operations = [ + migrations.AlterField( + model_name='job', + name='body_html', + field=models.TextField(blank=True, default=''), + preserve_default=False, + ), + migrations.AlterField( + model_name='job', + name='body_markdown', + field=models.TextField(blank=True, default=''), + preserve_default=False, + ), + ] diff --git a/app/resume/models.py b/app/resume/models.py index 68f9a7e..390a277 100644 --- a/app/resume/models.py +++ b/app/resume/models.py @@ -1,6 +1,7 @@ from django.db import models from django.utils.encoding import force_text from django.urls import reverse +from django.template.defaultfilters import slugify from utils.util import markdown_to_html @@ -53,3 +54,39 @@ class PubItem(models.Model): if self.body_markdown: self.body_html = markdown_to_html(self.body_markdown) super(PubItem, self).save() + + +class Job(models.Model): + title = models.CharField(max_length=200) + employer = models.CharField(max_length=200, blank=True) + date_start = models.DateField('Date Start') + date_end = models.DateField('Date End', null=True, blank=True) + body_markdown = models.TextField(blank=True) + body_html = models.TextField(blank=True) + + class Meta: + ordering = ('-date_end',) + + def __str__(self): + return '{} - {}'.format(self.title, self.employer) # py3.1+ only + + def save(self, *args, **kwargs): + if self.body_markdown: + self.body_html = markdown_to_html(self.body_markdown) + super(Job, self).save() + + +class Resume(models.Model): + title = models.CharField(max_length=200) + slug = models.CharField(max_length=50, blank=True) + profile = models.TextField() + skills = models.TextField() + jobs = models.ManyToManyField(Job) + + def __str__(self): + return self.title + + def save(self, *args, **kwargs): + if self._state.adding and not self.slug: + self.slug = slugify(self.title) + super(Resume, self).save() diff --git a/app/resume/urls.py b/app/resume/urls.py index 0d8b40a..47e07ad 100644 --- a/app/resume/urls.py +++ b/app/resume/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import path, re_path from django.views.generic.base import RedirectView from . import views @@ -6,34 +6,39 @@ from . import views app_name = "resume" urlpatterns = [ - url( - r'pubs/(?P\d+)/$', + path( + r'', + views.ResumeView.as_view(), + name='resume', + ), + path( + r'pubs//', views.PublisherListView.as_view(), name='list', ), - url( - r'pubs/(?P[-\w]+)/(?P\d+)/$', + path( + r'pubs///', views.ByPublisherListView.as_view(), name='list_by_publisher', ), - url( - r'pubs/(?P[-\w]+)/(?P[-\w]+)$', + path( + r'pubs//', views.PubItemDetailView.as_view(), name='detail', ), # redirect /slug/ to /slug/1/ for live server - url( + path( r'pubs/(?P[-\w]+)/$', RedirectView.as_view(url="/resume/pubs/%(publisher)s/1/", permanent=False), name="live_publisher_redirect" ), - url( - r'pubs/$', + path( + r'pubs/', RedirectView.as_view(url="/resume/pubs/1/", permanent=False), name="live_redirect" ), - url( - r'^(?P[-\w]+)(?:/(?P[-\w]+))$', + path( + r'/', views.PageView.as_view(), name="pages" ), diff --git a/app/resume/views.py b/app/resume/views.py index 15acf14..9cdd8e7 100644 --- a/app/resume/views.py +++ b/app/resume/views.py @@ -2,7 +2,7 @@ from django.views.generic.detail import DetailView from django.views.generic.base import TemplateView from utils.views import PaginatedListView -from .models import PubItem, Publisher +from .models import PubItem, Publisher, Resume from pages.models import Page @@ -32,9 +32,10 @@ class ByPublisherListView(PaginatedListView): context['publisher'] = Publisher.objects.get(slug=self.kwargs['publisher']) return context + class PubItemDetailView(DetailView): model = PubItem - template_name = "details/resume.html" + template_name = "details/pubs.html" slug_field = "slug" @@ -51,3 +52,8 @@ class PageView(DetailView): def get_template_names(self): return ["details/%s.html" % self.object.slug, 'details/page.html'] + + +class ResumeView(DetailView): + model = Resume + template_name = "details/resume.html" diff --git a/app/utils/util.py b/app/utils/util.py index 6678fc9..714403b 100644 --- a/app/utils/util.py +++ b/app/utils/util.py @@ -110,3 +110,14 @@ def parse_video(s): if soup.find('video'): return True return False + +def parse_reg_bio_page(): + content = requests.get("https://www.theregister.co.uk/Author/Scott-Gilbertson/") + soup = BeautifulSoup(content, 'html.parser') + try: + image = soup.find_all('img')[0]['id'] + img_pk = image.split('image-')[1] + return apps.get_model('photos', 'LuxImage').objects.get(pk=img_pk) + except IndexError: + return None + -- cgit v1.2.3-70-g09d2