From 0998adc956fda5fa8c2658c11b285b74e56fa17e Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 27 May 2022 11:30:48 +0200 Subject: [PATCH 01/22] add model transfer --- ereuse_devicehub/inventory/models.py | 33 +++++++ .../versions/054a3aea9f08_transfer.py | 92 +++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 ereuse_devicehub/inventory/models.py create mode 100644 ereuse_devicehub/migrations/versions/054a3aea9f08_transfer.py diff --git a/ereuse_devicehub/inventory/models.py b/ereuse_devicehub/inventory/models.py new file mode 100644 index 00000000..ad725faf --- /dev/null +++ b/ereuse_devicehub/inventory/models.py @@ -0,0 +1,33 @@ +from uuid import uuid4 + +from citext import CIText +from sqlalchemy import Boolean, Column +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import backref, relationship +from teal.db import CASCADE_OWN + +from ereuse_devicehub.db import db +from ereuse_devicehub.resources.models import Thing + + +class Transfer(Thing): + """ + The transfer is a transfer of possession of devices between + a user and a code (not system user) + """ + + id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4) + code = Column(CIText(), default='', nullable=False) + closed = Boolean(default=False) + date = Column(db.TIMESTAMP(timezone=True)) + description = Column(CIText(), default='', nullable=True) + lot_id = db.Column( + UUID(as_uuid=True), + db.ForeignKey('lot.id', use_alter=True, name='lot_trade'), + nullable=True, + ) + lot = relationship( + 'Lot', + backref=backref('transfer', lazy=True, uselist=False, cascade=CASCADE_OWN), + primaryjoin='Transfer.lot_id == Lot.id', + ) diff --git a/ereuse_devicehub/migrations/versions/054a3aea9f08_transfer.py b/ereuse_devicehub/migrations/versions/054a3aea9f08_transfer.py new file mode 100644 index 00000000..a6b4767e --- /dev/null +++ b/ereuse_devicehub/migrations/versions/054a3aea9f08_transfer.py @@ -0,0 +1,92 @@ +"""transfer + +Revision ID: 054a3aea9f08 +Revises: 8571fb32c912 +Create Date: 2022-05-27 11:07:18.245322 + +""" +import citext +import sqlalchemy as sa +from alembic import context, op +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '054a3aea9f08' +down_revision = '8571fb32c912' +branch_labels = None +depends_on = None + + +def get_inv(): + INV = context.get_x_argument(as_dictionary=True).get('inventory') + if not INV: + raise ValueError("Inventory value is not specified") + return INV + + +def upgrade(): + # creating transfer table + op.create_table( + 'transfer', + sa.Column( + 'updated', + sa.TIMESTAMP(timezone=True), + server_default=sa.text('CURRENT_TIMESTAMP'), + nullable=False, + ), + sa.Column( + 'created', + sa.TIMESTAMP(timezone=True), + server_default=sa.text('CURRENT_TIMESTAMP'), + nullable=False, + ), + sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), + sa.Column('code', citext.CIText(), nullable=False), + sa.Column('closed', sa.Boolean(), nullable=False), + sa.Column( + 'description', + citext.CIText(), + nullable=False, + comment='A comment about the action.', + ), + sa.Column('date', sa.TIMESTAMP(timezone=True), nullable=True), + sa.Column('lot_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.ForeignKeyConstraint(['lot_id'], [f'{get_inv()}.lot.id']), + sa.PrimaryKeyConstraint('id'), + schema=f'{get_inv()}', + ) + + # creating index + op.create_index( + op.f('ix_transfer_created'), + 'transfer', + ['created'], + unique=False, + schema=f'{get_inv()}', + ) + op.create_index( + op.f('ix_transfer_updated'), + 'transfer', + ['updated'], + unique=False, + schema=f'{get_inv()}', + ) + op.create_index( + 'ix_transfer_id', + 'transfer', + ['id'], + unique=False, + postgresql_using='hash', + schema=f'{get_inv()}', + ) + + +def downgrade(): + op.drop_index( + op.f('ix_transfer_created'), table_name='transfer', schema=f'{get_inv()}' + ) + op.drop_index( + op.f('ix_transfer_updated'), table_name='transfer', schema=f'{get_inv()}' + ) + op.drop_index(op.f('ix_transfer_id'), table_name='transfer', schema=f'{get_inv()}') + op.drop_table('transfer', schema=f'{get_inv()}') From a8368e92b81922b36167276b0007fedbd7c19aef Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 27 May 2022 16:32:22 +0200 Subject: [PATCH 02/22] add html and form for transfers --- ereuse_devicehub/inventory/forms.py | 54 ++++++++++++++ ereuse_devicehub/inventory/views.py | 28 +++++++ .../templates/inventory/device_list.html | 11 +++ .../templates/inventory/new_transfer.html | 73 +++++++++++++++++++ 4 files changed, 166 insertions(+) create mode 100644 ereuse_devicehub/templates/inventory/new_transfer.html diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py index 1226dcbf..5523f00a 100644 --- a/ereuse_devicehub/inventory/forms.py +++ b/ereuse_devicehub/inventory/forms.py @@ -26,6 +26,7 @@ from wtforms import ( from wtforms.fields import FormField from ereuse_devicehub.db import db +from ereuse_devicehub.inventory.models import Transfer from ereuse_devicehub.resources.action.models import RateComputer, Snapshot, Trade from ereuse_devicehub.resources.action.rate.v1_0 import CannotRate from ereuse_devicehub.resources.action.schemas import Snapshot as SnapshotSchema @@ -1098,3 +1099,56 @@ class TradeDocumentForm(FlaskForm): db.session.commit() return self._obj + + +class TransferForm(FlaskForm): + code = StringField( + 'Code', + [validators.Optional()], + render_kw={'class': "form-control"}, + description="You need put a code for transfer the external user", + ) + date = DateField( + 'Date', + [validators.Optional()], + render_kw={'class': "form-control"}, + description="""Date when the transfer is closed""", + ) + description = TextAreaField( + 'Description', + render_kw={'class': "form-control"}, + ) + type = HiddenField() + + def __init__(self, *args, **kwargs): + lot_id = kwargs.pop('lot_id') + super().__init__(*args, **kwargs) + self._tmp_lot = Lot.query.filter(Lot.id == lot_id).one() + + def validate(self, extra_validators=None): + is_valid = super().validate(extra_validators) + + if self.type.data not in ['incoming', 'outgoing']: + is_valid = False + + return is_valid + + def save(self, commit=True): + self.newlot = Lot(name=self._tmp_lot.name) + self.newlot.devices = self._tmp_lot.devices + db.session.add(self.newlot) + + self._obj = Transfer(lot=self.newlot) + self.populate_obj(self._obj) + + if self.type.data == 'incoming': + self._obj.user_to = g.user + elif self.type.data == 'outgoing': + self._obj.user_from = g.user + + db.session.add(self._obj) + + if commit: + db.session.commit() + + return self._obj diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index 5ed4247a..e05239ff 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -22,6 +22,7 @@ from ereuse_devicehub.inventory.forms import ( TagDeviceForm, TradeDocumentForm, TradeForm, + TransferForm, UploadSnapshotForm, ) from ereuse_devicehub.labels.forms import PrintLabelsForm @@ -400,6 +401,29 @@ class NewTradeDocumentView(View): return flask.render_template(self.template_name, **self.context) +class NewTransferView(GenericMixView): + methods = ['POST', 'GET'] + template_name = 'inventory/new_transfer.html' + form_class = TransferForm + title = "Add new transfer" + + def dispatch_request(self, lot_id, type_id): + self.form = self.form_class(lot_id=lot_id, type=type_id) + self.get_context() + + if self.form.validate_on_submit(): + self.form.save() + new_lot_id = lot_id + if self.form.newlot.id: + new_lot_id = self.form.newlot.id + messages.success('Transfer created successfully!') + next_url = url_for('inventory.lotdevicelist', lot_id=new_lot_id) + return flask.redirect(next_url) + + self.context.update({'form': self.form, 'title': self.title}) + return flask.render_template(self.template_name, **self.context) + + class ExportsView(View): methods = ['GET'] decorators = [login_required] @@ -557,3 +581,7 @@ devices.add_url_rule( devices.add_url_rule( '/export//', view_func=ExportsView.as_view('export') ) +devices.add_url_rule( + '/lot//transfer//', + view_func=NewTransferView.as_view('new_transfer'), +) diff --git a/ereuse_devicehub/templates/inventory/device_list.html b/ereuse_devicehub/templates/inventory/device_list.html index 54376fa5..ff091717 100644 --- a/ereuse_devicehub/templates/inventory/device_list.html +++ b/ereuse_devicehub/templates/inventory/device_list.html @@ -78,6 +78,17 @@ {% endif %}
+ {% if lot and lot.is_temporary %} + + {% endif %}