Add shipping label rendering
parent
fb04881aa3
commit
406d9e700d
|
@ -13,7 +13,7 @@ RUN apk add --no-cache --virtual .build-deps gcc python3-dev musl-dev postgresql
|
||||||
pip3 install --no-cache-dir psycopg2==2.8.4 pycparser==2.20 cffi==1.14.0 bcrypt==3.1.7 && \
|
pip3 install --no-cache-dir psycopg2==2.8.4 pycparser==2.20 cffi==1.14.0 bcrypt==3.1.7 && \
|
||||||
apk del --no-cache .build-deps
|
apk del --no-cache .build-deps
|
||||||
|
|
||||||
RUN apk add --no-cache py3-pillow cairo pango glib font-noto
|
RUN apk add --no-cache py3-pillow cairo pango glib font-noto gdk-pixbuf-dev
|
||||||
|
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
RUN pip3 install --no-cache-dir -r requirements.txt
|
RUN pip3 install --no-cache-dir -r requirements.txt
|
||||||
|
|
|
@ -316,8 +316,8 @@ class FaceshieldRequestAdmin(ModelView):
|
||||||
output.headers["Content-type"] = "text/csv"
|
output.headers["Content-type"] = "text/csv"
|
||||||
return output
|
return output
|
||||||
|
|
||||||
@flask_admin.actions.action('create_shipment', 'Create Kurjerzy shipment')
|
@flask_admin.actions.action('shipping_create', 'Kurjerzy / Create shipment')
|
||||||
def action_create_shipment(self, ids):
|
def action_shipping_create(self, ids):
|
||||||
from shipping.kurjerzy import Kurjerzy
|
from shipping.kurjerzy import Kurjerzy
|
||||||
|
|
||||||
models = self.get_query().filter(FaceshieldRequest.id.in_(ids)).all()
|
models = self.get_query().filter(FaceshieldRequest.id.in_(ids)).all()
|
||||||
|
@ -342,6 +342,11 @@ class FaceshieldRequestAdmin(ModelView):
|
||||||
if created:
|
if created:
|
||||||
flash('%d shipments created' % (created,), 'info')
|
flash('%d shipments created' % (created,), 'info')
|
||||||
|
|
||||||
|
@flask_admin.actions.action('shipping_print', 'Kurjerzy / Print shipping labels')
|
||||||
|
def action_shipping_print(self, ids):
|
||||||
|
models = self.get_query().filter(FaceshieldRequest.id.in_(ids)).all()
|
||||||
|
return render_pdf(HTML(string=self.render('shipping_label.html', models=models)))
|
||||||
|
|
||||||
class FilteredFaceshieldRequestAdmin(FaceshieldRequestAdmin):
|
class FilteredFaceshieldRequestAdmin(FaceshieldRequestAdmin):
|
||||||
def get_query(self):
|
def get_query(self):
|
||||||
return super(FilteredFaceshieldRequestAdmin, self).get_query().filter(~FaceshieldRequest.status.in_([Status.rejected, Status.spam, Status.fulfilled, Status.delegated]))
|
return super(FilteredFaceshieldRequestAdmin, self).get_query().filter(~FaceshieldRequest.status.in_([Status.rejected, Status.spam, Status.fulfilled, Status.delegated]))
|
||||||
|
|
|
@ -2,8 +2,9 @@ from datetime import datetime
|
||||||
import enum
|
import enum
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
|
from flask import current_app
|
||||||
from jinja2 import Markup
|
from jinja2 import Markup
|
||||||
from formity.extensions import db
|
from formity.extensions import db, cache
|
||||||
from sqlalchemy import event
|
from sqlalchemy import event
|
||||||
from sqlalchemy.ext.hybrid import hybrid_property
|
from sqlalchemy.ext.hybrid import hybrid_property
|
||||||
from formity.utils import get_diff
|
from formity.utils import get_diff
|
||||||
|
@ -94,6 +95,24 @@ class FaceshieldRequest(db.Model):
|
||||||
return self.faceshield_full_delivered // 150
|
return self.faceshield_full_delivered // 150
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@cache.memoize(timeout=10 * 60)
|
||||||
|
def fetch_shipping_info(self):
|
||||||
|
if self.shipping_provider == 'kurjerzy':
|
||||||
|
from shipping.kurjerzy import Kurjerzy
|
||||||
|
k = Kurjerzy(current_app)
|
||||||
|
k.authenticate()
|
||||||
|
return k.shipment_info(self.shipping_id)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def refresh_shipping_info(self):
|
||||||
|
cache.delete_memoized(self.fetch_shipping_info, self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def shipping_info(self):
|
||||||
|
return self.fetch_shipping_info()
|
||||||
|
|
||||||
|
|
||||||
def changelog_default_user_id():
|
def changelog_default_user_id():
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
return current_user.get_id() if current_user and current_user.get_id() else 'nobody'
|
return current_user.get_id() if current_user and current_user.get_id() else 'nobody'
|
||||||
|
|
|
@ -134,9 +134,14 @@ class Kurjerzy:
|
||||||
|
|
||||||
def shipment_info(self, id):
|
def shipment_info(self, id):
|
||||||
print('fetching shipment_info(%r)' % (id,))
|
print('fetching shipment_info(%r)' % (id,))
|
||||||
return self.send_query(r'query($id: Int) { shipments(ids:[$id]) { id, labelRef, labelSource, status, tracking { statuses } } }', {
|
result = self.send_query(r'query($id: Int) { shipments(ids:[$id]) { id, labelRef, labelSource, status, tracking { statuses } } }', {
|
||||||
'id': id,
|
'id': id,
|
||||||
})['data']['shipments']
|
})
|
||||||
|
|
||||||
|
try:
|
||||||
|
return result['data']['shipments'][0]
|
||||||
|
except IndexError:
|
||||||
|
return None
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
k = Kurjerzy({})
|
k = Kurjerzy({})
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<head>
|
<head>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
{% block css %}
|
||||||
@page {
|
@page {
|
||||||
margin: 0cm;
|
margin: 0cm;
|
||||||
size: 4in 6in;
|
size: 4in 6in;
|
||||||
|
@ -61,9 +62,11 @@ html, body {
|
||||||
display: inline;
|
display: inline;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
{% endblock %}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
{% block content %}
|
||||||
{% for model in models %}
|
{% for model in models %}
|
||||||
{% for label_id in range(model.label_count) %}
|
{% for label_id in range(model.label_count) %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
@ -83,5 +86,6 @@ html, body {
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
{% extends "label.html" %}
|
||||||
|
{% block css %}{{ super() }}
|
||||||
|
|
||||||
|
.shipping {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: initial;
|
||||||
|
}
|
||||||
|
.shipping .inner {
|
||||||
|
width: 6in;
|
||||||
|
height: 4in;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.shipping .inner img {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
{% for model in models %}
|
||||||
|
<div class="container shipping">
|
||||||
|
<div class="inner">
|
||||||
|
<img src="{{ model.shipping_info['labelSource'] }}" alt="label {{ model.id }}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue