diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py index 306744c9..65d2b5c3 100644 --- a/ereuse_devicehub/inventory/forms.py +++ b/ereuse_devicehub/inventory/forms.py @@ -30,6 +30,7 @@ from wtforms.fields import FormField from ereuse_devicehub.db import db from ereuse_devicehub.inventory.models import DeliveryNote, ReceiverNote, Transfer +from ereuse_devicehub.parser.models import PlaceholdersLog from ereuse_devicehub.parser.parser import ParseSnapshotLsHw from ereuse_devicehub.parser.schemas import Snapshot_lite from ereuse_devicehub.resources.action.models import Snapshot, Trade @@ -540,6 +541,11 @@ class NewDeviceForm(FlaskForm): device.placeholder = self.get_placeholder() db.session.add(device) + placeholder_log = PlaceholdersLog( + type="New device", source='Web form', placeholder=device.placeholder + ) + db.session.add(placeholder_log) + def reset_ids(self): if self.amount.data > 1: self.phid.data = None @@ -595,6 +601,10 @@ class NewDeviceForm(FlaskForm): and self.functionality.data != self._obj.functionality().name ): self._obj.set_functionality(self.functionality.data) + placeholder_log = PlaceholdersLog( + type="Update", source='Web form', placeholder=self._obj.placeholder + ) + db.session.add(placeholder_log) class TagDeviceForm(FlaskForm): @@ -1445,6 +1455,7 @@ class UploadPlaceholderForm(FlaskForm): _file = files[0] if _file.content_type == 'text/csv': + self.source = "CSV File: {}".format(_file.filename) delimiter = ';' data = pd.read_csv(_file).to_dict() head = list(data.keys())[0].split(delimiter) @@ -1458,6 +1469,7 @@ class UploadPlaceholderForm(FlaskForm): for k, v in x.items(): data[head[i]][k] = v[i] else: + self.source = "Excel File: {}".format(_file.filename) try: data = pd.read_excel(_file).to_dict() except ValueError: @@ -1514,7 +1526,10 @@ class UploadPlaceholderForm(FlaskForm): placeholder.pallet = "{}".format(data['Pallet'][i]) placeholder.info = "{}".format(data['Info'][i]) - self.placeholders.append(device) + placeholder_log = PlaceholdersLog( + type="Update", source=self.source, placeholder=device.placeholder + ) + self.placeholders.append((device, placeholder_log)) continue # create a new one @@ -1540,14 +1555,18 @@ class UploadPlaceholderForm(FlaskForm): device = snapshot_json['device'] device.placeholder = Placeholder(**json_placeholder) - self.placeholders.append(device) + placeholder_log = PlaceholdersLog( + type="New device", source=self.source, placeholder=device.placeholder + ) + self.placeholders.append((device, placeholder_log)) return True def save(self, commit=True): - for device in self.placeholders: + for device, placeholder_log in self.placeholders: db.session.add(device) + db.session.add(placeholder_log) if commit: db.session.commit() diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index fad3abad..52a1a04a 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -34,7 +34,7 @@ from ereuse_devicehub.inventory.forms import ( UploadSnapshotForm, ) from ereuse_devicehub.labels.forms import PrintLabelsForm -from ereuse_devicehub.parser.models import SnapshotsLog +from ereuse_devicehub.parser.models import PlaceholdersLog, SnapshotsLog from ereuse_devicehub.resources.action.models import Trade from ereuse_devicehub.resources.device.models import Computer, DataStorage, Device from ereuse_devicehub.resources.documents.device_row import ActionRow, DeviceRow @@ -880,7 +880,7 @@ class UploadPlaceholderView(GenericMixin): if lot_id: lots = self.context['lots'] lot = lots.filter(Lot.id == lot_id).one() - for device in snapshots: + for device, p in snapshots: lot.devices.add(device) db.session.add(lot) db.session.commit() @@ -889,6 +889,24 @@ class UploadPlaceholderView(GenericMixin): return flask.render_template(self.template_name, **self.context) +class PlaceholderLogListView(GenericMixin): + template_name = 'inventory/placeholder_log_list.html' + + def dispatch_request(self): + self.get_context() + self.context['page_title'] = "Placeholder Logs" + self.context['placeholders_log'] = self.get_placeholders_log() + + return flask.render_template(self.template_name, **self.context) + + def get_placeholders_log(self): + placeholder_log = PlaceholdersLog.query.filter( + PlaceholdersLog.owner == g.user + ).order_by(PlaceholdersLog.created.desc()) + + return placeholder_log + + devices.add_url_rule('/action/add/', view_func=NewActionView.as_view('action_add')) devices.add_url_rule('/action/trade/add/', view_func=NewTradeView.as_view('trade_add')) devices.add_url_rule( @@ -970,3 +988,6 @@ devices.add_url_rule( '/lot//upload-placeholder/', view_func=UploadPlaceholderView.as_view('lot_upload_placeholder'), ) +devices.add_url_rule( + '/placeholder-logs/', view_func=PlaceholderLogListView.as_view('placeholder_logs') +) diff --git a/ereuse_devicehub/migrations/versions/3e3a67f62972_placeholder_log.py b/ereuse_devicehub/migrations/versions/3e3a67f62972_placeholder_log.py new file mode 100644 index 00000000..b3850218 --- /dev/null +++ b/ereuse_devicehub/migrations/versions/3e3a67f62972_placeholder_log.py @@ -0,0 +1,65 @@ +"""placeholder log + +Revision ID: 3e3a67f62972 +Revises: aeca9fb50cc6 +Create Date: 2022-07-06 18:23:54.267003 + +""" +import citext +import sqlalchemy as sa +from alembic import context, op +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '3e3a67f62972' +down_revision = 'aeca9fb50cc6' +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(): + op.create_table( + 'placeholders_log', + sa.Column( + 'updated', + sa.TIMESTAMP(timezone=True), + server_default=sa.text('CURRENT_TIMESTAMP'), + nullable=False, + comment='The last time Devicehub recorded a change for \n this thing.\n ', + ), + sa.Column( + 'created', + sa.TIMESTAMP(timezone=True), + server_default=sa.text('CURRENT_TIMESTAMP'), + nullable=False, + comment='When Devicehub created this.', + ), + sa.Column('id', sa.BigInteger(), nullable=False), + sa.Column('source', citext.CIText(), nullable=True), + sa.Column('type', citext.CIText(), nullable=True), + sa.Column('severity', sa.SmallInteger(), nullable=False), + sa.Column('placeholder_id', sa.BigInteger(), nullable=True), + sa.Column('owner_id', postgresql.UUID(as_uuid=True), nullable=False), + sa.ForeignKeyConstraint( + ['placeholder_id'], + [f'{get_inv()}.placeholder.id'], + ), + sa.ForeignKeyConstraint( + ['owner_id'], + ['common.user.id'], + ), + sa.PrimaryKeyConstraint('id'), + ) + op.execute("CREATE SEQUENCE placeholders_log_seq START 1;") + + +def downgrade(): + op.drop_table('placeholders_log') + op.execute("DROP SEQUENCE placeholders_log_seq;") diff --git a/ereuse_devicehub/parser/models.py b/ereuse_devicehub/parser/models.py index 2da2f3ca..d8b4b62b 100644 --- a/ereuse_devicehub/parser/models.py +++ b/ereuse_devicehub/parser/models.py @@ -5,6 +5,7 @@ from sqlalchemy.dialects.postgresql import UUID from ereuse_devicehub.db import db from ereuse_devicehub.resources.action.models import Snapshot +from ereuse_devicehub.resources.device.models import Placeholder from ereuse_devicehub.resources.enums import Severity from ereuse_devicehub.resources.models import Thing from ereuse_devicehub.resources.user.models import User @@ -43,3 +44,48 @@ class SnapshotsLog(Thing): return self.snapshot.device.devicehub_id return '' + + +class PlaceholdersLog(Thing): + """A Placeholder log.""" + + __table_args__ = {'schema': ''} + id = Column(BigInteger, Sequence('placeholders_log_seq'), primary_key=True) + source = Column(CIText(), default='', nullable=True) + type = Column(CIText(), default='', nullable=True) + severity = Column(SmallInteger, default=Severity.Info, nullable=False) + + placeholder_id = Column(BigInteger, db.ForeignKey(Placeholder.id), nullable=True) + placeholder = db.relationship( + Placeholder, primaryjoin=placeholder_id == Placeholder.id + ) + owner_id = db.Column( + UUID(as_uuid=True), + db.ForeignKey(User.id), + nullable=False, + default=lambda: g.user.id, + ) + owner = db.relationship(User, primaryjoin=owner_id == User.id) + + def save(self, commit=False): + db.session.add(self) + + if commit: + db.session.commit() + + @property + def phid(self): + if self.placeholder: + return self.placeholder.phid + + return '' + + @property + def dhid(self): + if self.placeholder: + return self.placeholder.device.devicehub_id + + return '' + + def get_status(self): + return Severity(self.severity) diff --git a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html index 2eeb716a..96c9cf47 100644 --- a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html +++ b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html @@ -148,6 +148,15 @@ + + + +