Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
00e61f6
Create ModerationQueue model
VadimKovalenkoSNF Oct 14, 2024
931bcbc
Create migration for moderation events table
VadimKovalenkoSNF Oct 14, 2024
9e8f4de
Update release notes
VadimKovalenkoSNF Oct 14, 2024
20cc873
Update moderationEvent model
VadimKovalenkoSNF Oct 17, 2024
cdc06c1
Merge branch 'main' into OSDEV-1229-create-moderation-events-table
VadimKovalenkoSNF Oct 17, 2024
052bbf3
Minor fix
VadimKovalenkoSNF Oct 17, 2024
057edaf
Minor fixes for source and status fields
VadimKovalenkoSNF Oct 18, 2024
eb0f2aa
Remove auto_now from status_change_date
VadimKovalenkoSNF Oct 18, 2024
a3e9675
Add null=true to status_change_date
VadimKovalenkoSNF Oct 18, 2024
b37d358
Prettify source and status
VadimKovalenkoSNF Oct 18, 2024
6f6b495
Source field can be blank and null
VadimKovalenkoSNF Oct 18, 2024
6de5f84
Remove production_location_list_item field
VadimKovalenkoSNF Oct 18, 2024
b35d539
Add claim_id
VadimKovalenkoSNF Oct 18, 2024
bb74602
Make migration
VadimKovalenkoSNF Oct 18, 2024
a974031
Rename claim_id to claim in ModerationEvent model
VadimKovalenkoSNF Oct 18, 2024
280cb74
Minor typo fix
VadimKovalenkoSNF Oct 18, 2024
6368f27
Fix string representation of model instance
VadimKovalenkoSNF Oct 18, 2024
1495853
Merge branch 'main' into OSDEV-1229-create-moderation-events-table
VadimKovalenkoSNF Oct 21, 2024
da93db5
Change length of status, request_type and source, index uuid
VadimKovalenkoSNF Oct 22, 2024
70e7991
Fix minor lint issues
VadimKovalenkoSNF Oct 22, 2024
5369b78
Move classes with text choices to the top
VadimKovalenkoSNF Oct 22, 2024
ed173d8
Add contributor id as foreign key, remove null=True
VadimKovalenkoSNF Oct 22, 2024
944345a
Minor field fixes
VadimKovalenkoSNF Oct 22, 2024
ecd5218
Fix contributor field
VadimKovalenkoSNF Oct 22, 2024
8ec2c59
Refactor source field
VadimKovalenkoSNF Oct 22, 2024
54b61f1
Revert src/django/api/models/__init__.py
VadimKovalenkoSNF Oct 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion doc/release/RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html

## Introduction
* Product name: Open Supply Hub
* Release date: November 2, 2024
* Release date: November 02, 2024

### Database changes
#### Migrations:
* 0158_create_moderation_events_table.py - This migration creates api_moderationevent table for Moderation Queue.

#### Scheme changes
* [OSDEV-1229](https://opensupplyhub.atlassian.net/browse/OSDEV-1229) - Created Moderation Events Postgres table to track moderation events in the database.

### Database changes
#### Migrations:
Expand All @@ -30,6 +37,8 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
* *Describe what's new here. The changes that can impact user experience should be listed in this section.*

### Release instructions:
* Ensure that the following commands are included in the `post_deployment` command:
* `migrate`
* Run `Deploy to AWS` pipeline for an existing environment with the flag clear OpenSearch set to true - to let the tokenizer parse full text into words with new configurations.


Expand Down
42 changes: 42 additions & 0 deletions src/django/api/migrations/0158_create_moderation_event_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Generated by Django 3.2.17 on 2024-10-22 11:43

import django.contrib.postgres.indexes
from django.db import migrations, models
import django.db.models.deletion
import uuid


class Migration(migrations.Migration):

dependencies = [
('api', '0157_delete_endpoint_switcher_for_list_uploads'),
]

operations = [
migrations.CreateModel(
name='ModerationEvent',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, help_text='Unique identifier to make moderation event table more reusable across the app.', unique=True)),
('created_at', models.DateTimeField(auto_now_add=True, help_text='Date when the moderation queue entry was created.')),
('updated_at', models.DateTimeField(auto_now=True, db_index=True, help_text='Date when the moderation queue entry was last updated.')),
('status_change_date', models.DateTimeField(blank=True, help_text='Date when the moderation decision was made.', null=True)),
('request_type', models.CharField(choices=[('CREATE', 'Create'), ('UPDATE', 'Update'), ('CLAIM', 'Claim')], help_text='Type of moderation record.', max_length=6)),
('raw_data', models.JSONField(default=dict, help_text='Key-value pairs of the non-parsed row and header for the moderation data.')),
('cleaned_data', models.JSONField(default=dict, help_text='Key-value pairs of the parsed row and header for the moderation data.')),
('geocode_result', models.JSONField(default=dict, help_text='Result of the geocode operation.')),
('status', models.CharField(choices=[('PENDING', 'Pending'), ('RESOLVED', 'Resolved')], default='PENDING', help_text='Moderation status of the production location.', max_length=8)),
('source', models.CharField(blank=True, choices=[('API', 'API'), ('SLC', 'SLC')], default='', help_text='Source type of production location. If request_type is CLAIM, no source type.', max_length=3)),
],
),
migrations.AddField(
model_name='moderationevent',
name='claim',
field=models.OneToOneField(help_text='Linked claim id for this production location.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='moderation_event', to='api.facilityclaim'),
),
migrations.AddField(
model_name='moderationevent',
name='contributor',
field=models.ForeignKey(help_text='Linked contributor responsible for this moderation event.', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='moderation_events', to='api.contributor'),
),
]
61 changes: 31 additions & 30 deletions src/django/api/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,77 +1,78 @@
# flake8: noqa: F401

from .api.api_block import (
from api.models.api.api_block import (
ApiBlock,
HistoricalApiBlock,
)
from .api.api_limit import (
from api.models.api.api_limit import (
ApiLimit,
HistoricalApiLimit,
)
from .contributor.contributor import (
from api.models.contributor.contributor import (
Contributor,
HistoricalContributor
)
from .contributor.contributor_manager import ContributorManager
from .contributor.contributor_notifications import (
from api.models.contributor.contributor_manager import ContributorManager
from api.models.contributor.contributor_notifications import (
ContributorNotifications,
HistoricalContributorNotifications
)
from .facility.facility import (
from api.models.facility.facility import (
Facility,
HistoricalFacility,
)
from .facility.facility_activity_report import (
from api.models.facility.facility_activity_report import (
FacilityActivityReport,
HistoricalFacilityActivityReport,
)
from .facility.facility_alias import (
from api.models.facility.facility_alias import (
FacilityAlias,
HistoricalFacilityAlias,
)
from .facility.facility_claim import (
from api.models.facility.facility_claim import (
FacilityClaim,
HistoricalFacilityClaim,
)
from .facility.facility_claim_review_note import (
from api.models.facility.facility_claim_review_note import (
FacilityClaimReviewNote,
HistoricalFacilityClaimReviewNote,
)
from .facility.facility_claim_attachments import (
from api.models.facility.facility_claim_attachments import (
FacilityClaimAttachments
)
from .facility.facility_list import FacilityList
from .facility.facility_list_item import FacilityListItem
from .facility.facility_list_item_temp import FacilityListItemTemp
from .facility.facility_location import FacilityLocation
from api.models.facility.facility_list import FacilityList
from api.models.facility.facility_list_item import FacilityListItem
from api.models.facility.facility_list_item_temp import FacilityListItemTemp
from api.models.facility.facility_location import FacilityLocation

from .facility.facility_match import (
from api.models.facility.facility_match import (
FacilityMatch,
HistoricalFacilityMatch,
)
from .facility.facility_match_temp import (
from api.models.facility.facility_match_temp import (
FacilityMatchTemp,
HistoricalFacilityMatchTemp,
)
from .download_log import DownloadLog
from .embed_config import EmbedConfig
from .embed_field import EmbedField
from .event import Event
from .extended_field import (
from api.models.download_log import DownloadLog
from api.models.embed_config import EmbedConfig
from api.models.embed_field import EmbedField
from api.models.event import Event
from api.models.extended_field import (
ExtendedField,
HistoricalExtendedField
)
from .nonstandart_field import NonstandardField
from .product_type import ProductType
from .production_type import ProductionType
from .request_log import RequestLog
from .sector import Sector
from .source import Source
from .user import (
from api.models.nonstandart_field import NonstandardField
from api.models.product_type import ProductType
from api.models.production_type import ProductionType
from api.models.request_log import RequestLog
from api.models.sector import Sector
from api.models.source import Source
from api.models.user import (
EmailAsUsernameUserManager,
get_default_burst_rate,
get_default_sustained_rate,
get_default_data_upload_rate,
User,
)
from .version import Version
from api.models.version import Version
from api.models.moderation_event import ModerationEvent
128 changes: 128 additions & 0 deletions src/django/api/models/moderation_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import uuid
from django.db import models
from api.models.contributor.contributor import Contributor
from api.models.facility.facility_claim import FacilityClaim


class ModerationEvent(models.Model):
'''
Data that is needed for moderation queue.
'''
class RequestType(models.TextChoices):
CREATE = 'CREATE', 'Create'
UPDATE = 'UPDATE', 'Update'
CLAIM = 'CLAIM', 'Claim'

class Status(models.TextChoices):
PENDING = 'PENDING', 'Pending'
RESOLVED = 'RESOLVED', 'Resolved'

class Source(models.TextChoices):
API = 'API', 'API'
SLC = 'SLC', 'SLC'

uuid = models.UUIDField(
default=uuid.uuid4,
editable=False,
unique=True,
db_index=True,
help_text=(
'Unique identifier to make moderation '
'event table more reusable across the app.'
)
)

created_at = models.DateTimeField(
auto_now_add=True,
help_text='Date when the moderation queue entry was created.'
)

updated_at = models.DateTimeField(
auto_now=True,
help_text='Date when the moderation queue entry was last updated.',
db_index=True
)

status_change_date = models.DateTimeField(
blank=True,
null=True,
help_text='Date when the moderation decision was made.'
)

contributor = models.ForeignKey(
Contributor,
on_delete=models.PROTECT,
null=True,
related_name='moderation_events',
help_text='Linked contributor responsible for this moderation event.'
)

claim = models.OneToOneField(
FacilityClaim,
on_delete=models.SET_NULL,
null=True,
related_name='moderation_event',
help_text='Linked claim id for this production location.'
)

request_type = models.CharField(
max_length=6,
null=False,
choices=RequestType.choices,
help_text='Type of moderation record.'
)

raw_data = models.JSONField(
null=False,
blank=False,
default=dict,
help_text=(
'Key-value pairs of the non-parsed row and '
'header for the moderation data.'
)
)

cleaned_data = models.JSONField(
null=False,
blank=False,
default=dict,
help_text=(
'Key-value pairs of the parsed row and '
'header for the moderation data.'
)
)

geocode_result = models.JSONField(
null=False,
blank=False,
default=dict,
help_text=(
'Result of the geocode operation.'
)
)

status = models.CharField(
max_length=8,
choices=Status.choices,
default=Status.PENDING,
null=False,
help_text='Moderation status of the production location.'
)

source = models.CharField(
max_length=3,
choices=Source.choices,
blank=True,
default='',
help_text=(
'Source type of production location.'
' If request_type is CLAIM, no source type.'
)
)

def __str__(self):
return (
f'ModerationEvent entry {self.uuid} '
f'with request type {self.request_type} '
f'and status {self.status}'
)