Skip to content

Commit

Permalink
Add export cac form submissions option (#2183)
Browse files Browse the repository at this point in the history
* Add export cac form submissions

* update template name

* Fix lint issue

* update comment service to use the new document generation service method

* remove unnecessary checks

* remove unused import

* remove console logs

* remove problematic check

* Remove unused import

* Remove unused variable
  • Loading branch information
jadmsaadaot authored Sep 13, 2023
1 parent 2b89a3d commit 4d50737
Show file tree
Hide file tree
Showing 18 changed files with 237 additions and 44 deletions.
55 changes: 55 additions & 0 deletions met-api/migrations/versions/7ebd9ecfccdd_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
""" Add new document type and template for cac form submission export
Revision ID: 7ebd9ecfccdd
Revises: 3a88de1e3e7f
Create Date: 2023-09-12 14:58:03.712784
"""
from datetime import datetime
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = '7ebd9ecfccdd'
down_revision = '3a88de1e3e7f'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
document_type = sa.Table(
'generated_document_type',
sa.MetaData(),
sa.Column('id', sa.Integer),
sa.Column('name', sa.String),
sa.Column('description', sa.String),
sa.Column('created_date', sa.DateTime, default=datetime.utcnow)
)

document_template = sa.Table(
'generated_document_template',
sa.MetaData(),
sa.Column('id', sa.Integer),
sa.Column('type_id', sa.Integer),
sa.Column('hash_code', sa.String),
sa.Column('extension', sa.String),
sa.Column('created_date', sa.DateTime, default=datetime.utcnow)
)

op.bulk_insert(document_type, [
{'id': 2, 'name': 'cac_form_sheet', 'description': 'cac form submission export for staff'}
])

op.bulk_insert(document_template, [
{'id': 2, 'type_id': 2, 'hash_code': None, "extension": "xlsx"}
])
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.execute('DELETE FROM document_type WHERE id = 2')
op.execute('DELETE FROM document_template WHERE id = 2')
# ### end Alembic commands ###
Binary file not shown.
Binary file not shown.
5 changes: 5 additions & 0 deletions met-api/src/met_api/models/cac_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ class CACForm(BaseModel): # pylint: disable=too-few-public-methods, too-many-in
last_name = db.Column(db.String(50), nullable=False)
city = db.Column(db.String(50), nullable=False)
email = db.Column(db.String(50), nullable=False)

@classmethod
def get_all_by_engagement_id(cls, engagement_id):
"""Get cac form by engagement id."""
return db.session.query(CACForm).filter(CACForm.engagement_id == engagement_id).all()
33 changes: 32 additions & 1 deletion met-api/src/met_api/resources/cac_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
"""API endpoints for managing a cac form submission resource."""
from http import HTTPStatus

from flask import request
from flask import Response, request
from flask_cors import cross_origin
from flask_restx import Namespace, Resource

from met_api.exceptions.business_exception import BusinessException
from met_api.services.cac_form_service import CACFormService
from met_api.utils.roles import Role
from met_api.utils.tenant_validator import require_role
from met_api.utils.util import allowedorigins, cors_preflight


Expand All @@ -46,3 +48,32 @@ def post(engagement_id, widget_id):
return str(err), HTTPStatus.BAD_REQUEST
except KeyError as err:
return str(err), HTTPStatus.BAD_REQUEST


@cors_preflight('GET, OPTIONS')
@API.route('/sheet')
class GeneratedCommentsSheet(Resource):
"""Resource for exorting cac form submissions."""

@staticmethod
@cross_origin(origins=allowedorigins())
@require_role([Role.EXPORT_CAC_FORM_TO_SHEET.value, Role.EXPORT_ALL_CAC_FORM_TO_SHEET.value])
def get(engagement_id):
"""Export comments."""
try:

response = CACFormService().export_cac_form_submissions_to_spread_sheet(engagement_id)
response_headers = dict(response.headers)
headers = {
'content-type': response_headers.get('content-type'),
'content-disposition': response_headers.get('content-disposition'),
}
return Response(
response=response.content,
status=response.status_code,
headers=headers
)
except ValueError as err:
return str(err), HTTPStatus.INTERNAL_SERVER_ERROR
except KeyError as err:
return str(err), HTTPStatus.INTERNAL_SERVER_ERROR
43 changes: 43 additions & 0 deletions met-api/src/met_api/services/cac_form_service.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@

"""Service for cac form management."""
from typing import Optional
from met_api.constants.subscribe_types import SubscribeTypes
from met_api.models import CACForm as CACFormModel
from met_api.models.engagement import Engagement as EngagementModel
from met_api.models.widget import Widget as WidgetModal
from met_api.models.widgets_subscribe import WidgetSubscribe as WidgetSubscribeModel
from met_api.services import authorization
from met_api.services.document_generation_service import DocumentGenerationService
from met_api.utils.enums import GeneratedDocumentTypes, MembershipType
from met_api.utils.roles import Role


class CACFormService:
Expand Down Expand Up @@ -40,3 +46,40 @@ def create_form_submission(engagement_id, widget_id, form_data):
'created_by': cac_form.created_by,
'updated_by': cac_form.updated_by,
}

@classmethod
def export_cac_form_submissions_to_spread_sheet(cls, engagement_id):
"""Export comments to spread sheet."""
engagement: Optional[EngagementModel] = EngagementModel.find_by_id(engagement_id)
if not engagement:
raise KeyError('Engagement not found')

one_of_roles = (
MembershipType.TEAM_MEMBER.name,
Role.EXPORT_CAC_FORM_TO_SHEET.value
)
authorization.check_auth(one_of_roles=one_of_roles, engagement_id=engagement.id)

cac_forms = CACFormModel.get_all_by_engagement_id(engagement_id)
formatted_comments = [
{
'understand': form.understand,
'termsOfReference': form.terms_of_reference,
'firstName': form.first_name,
'lastName': form.last_name,
'city': form.city,
'email': form.email,
}
for form in cac_forms]

data = {
'forms': formatted_comments
}

document_options = {
'document_type': GeneratedDocumentTypes.CAC_FORM_SHEET.value,
'template_name': 'cac_forms_sheet.xlsx',
'convert_to': 'csv',
'report_name': 'cac_form_submissions'
}
return DocumentGenerationService().generate_document(data=data, options=document_options)
11 changes: 9 additions & 2 deletions met-api/src/met_api/services/comment_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from met_api.services.document_generation_service import DocumentGenerationService
from met_api.utils.roles import Role
from met_api.utils.token_info import TokenInfo
from met_api.utils.enums import MembershipStatus
from met_api.utils.enums import GeneratedDocumentTypes, MembershipStatus


class CommentService:
Expand Down Expand Up @@ -179,4 +179,11 @@ def export_comments_to_spread_sheet(cls, survey_id):
data = {
'comments': formatted_comments
}
return DocumentGenerationService().generate_comment_sheet(data=data)
document_options = {
'document_type': GeneratedDocumentTypes.COMMENT_SHEET.value,
'template_name': 'staff_comments_sheet.xlsx',
'convert_to': 'csv',
'report_name': 'comments_sheet'
}

return DocumentGenerationService().generate_document(data=data, options=document_options)
52 changes: 32 additions & 20 deletions met-api/src/met_api/services/document_generation_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

from met_api.models.generated_document_template import GeneratedDocumentTemplate
from met_api.services.cdogs_api_service import CdogsApiService
from met_api.utils.enums import GeneratedDocumentTypes


class DocumentGenerationService: # pylint:disable=too-few-public-methods
Expand All @@ -30,42 +29,55 @@ def __init__(self):
"""Initiate the class."""
self.cdgos_api_service = CdogsApiService()

def generate_comment_sheet(self, data):
def generate_document(self, data, options):
"""Generate comment sheet."""
comment_sheet_template: GeneratedDocumentTemplate = GeneratedDocumentTemplate() \
.get_template_by_type(type_id=GeneratedDocumentTypes.COMMENT_SHEET)
if comment_sheet_template is None:
if not options:
raise ValueError('Options not provided')

document_type = options.get('document_type')
if not document_type:
raise ValueError('Document type not provided')

document_template: GeneratedDocumentTemplate = GeneratedDocumentTemplate() \
.get_template_by_type(type_id=document_type)
if document_template is None:
raise ValueError('Template not saved in DB')

template_cached = False
if comment_sheet_template.hash_code:
current_app.logger.info('Checking if template %s is cached', comment_sheet_template.hash_code)
template_cached = self.cdgos_api_service.check_template_cached(comment_sheet_template.hash_code)
if document_template.hash_code:
current_app.logger.info('Checking if template %s is cached', document_template.hash_code)
template_cached = self.cdgos_api_service.check_template_cached(document_template.hash_code)

if comment_sheet_template.hash_code is None or not template_cached:
if document_template.hash_code is None or not template_cached:
current_app.logger.info('Uploading new template')

template_name = options.get('template_name')
file_dir = os.path.dirname(os.path.realpath('__file__'))
comment_sheet_template_path = os.path.join(
document_template_path = os.path.join(
file_dir,
'src/met_api/generated_documents_carbone_templates/staff_comments_sheet.xlsx'
'src/met_api/generated_documents_carbone_templates/',
template_name
)
new_hash_code = self.cdgos_api_service.upload_template(template_file_path=comment_sheet_template_path)

if not os.path.exists(document_template_path):
raise ValueError('Template file does not exist')

new_hash_code = self.cdgos_api_service.upload_template(template_file_path=document_template_path)
if not new_hash_code:
raise ValueError('Unable to obtain valid hashcode')
comment_sheet_template.hash_code = new_hash_code
comment_sheet_template.save()
document_template.hash_code = new_hash_code
document_template.save()

options = {
generator_options = {
'cachereport': False,
'convertTo': 'csv',
'convertTo': options.get('convert_to', 'csv'),
'overwrite': True,
'reportName': 'comments_sheet'
'reportName': options.get('report_name', 'report')
}

current_app.logger.info('Generating comment_sheet')
current_app.logger.info('Generating document')
return self.cdgos_api_service.generate_document(
template_hash_code=comment_sheet_template.hash_code,
template_hash_code=document_template.hash_code,
data=data,
options=options
options=generator_options
)
1 change: 1 addition & 0 deletions met-api/src/met_api/utils/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class GeneratedDocumentTypes(IntEnum):
"""Document Types."""

COMMENT_SHEET = 1
CAC_FORM_SHEET = 2


class LoginSource(Enum):
Expand Down
2 changes: 2 additions & 0 deletions met-api/src/met_api/utils/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,6 @@ class Role(Enum):
VIEW_ALL_ENGAGEMENTS = 'view_all_engagements' # Allows user access to all engagements including draft
SHOW_ALL_COMMENT_STATUS = 'show_all_comment_status' # Allows user to see all comment status
EXPORT_TO_CSV = 'export_to_csv' # Allows users to export comments to csv
EXPORT_ALL_CAC_FORM_TO_SHEET = 'export_all_cac_form_to_sheet' # Allows users to export CAC form to csv
EXPORT_CAC_FORM_TO_SHEET = 'export_cac_form_to_sheet' # Allows users to export CAC form to csv
VIEW_ALL_SURVEY_RESULTS = 'view_all_survey_results' # Allows users to view results to all questions
1 change: 1 addition & 0 deletions met-web/src/apiManager/endpoints/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ const Endpoints = {
},
CACForm: {
CREATE: `${AppConfig.apiUrl}/engagements/engagement_id/cacform/widget_id`,
GET_SHEET: `${AppConfig.apiUrl}/engagements/engagement_id/cacform/sheet`,
},
};

Expand Down
1 change: 0 additions & 1 deletion met-web/src/components/common/FileUpload/Uploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ interface UploaderProps {
acceptedFormat?: Accept;
}
const Uploader = ({ margin = 2, height = '10em', helpText, acceptedFormat }: UploaderProps) => {
console.log(acceptedFormat);
const { handleAddFile } = useContext(FileUploadContext);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ const FormSignUpDrawer = () => {
} = methods;

useEffect(() => {
console.log('subscribeOptionToEdit', subscribeOptionToEdit);
if (subscribeOptionToEdit) {
const subscribeItem = subscribeOptionToEdit.subscribe_items[0];
setValue('description', subscribeItem.description);
Expand All @@ -94,10 +93,6 @@ const FormSignUpDrawer = () => {
}
}, []);

useEffect(() => {
console.log('initialRichDescription', initialRawEditorState);
}, [initialRawEditorState]);

const createSubscribeForm = async (data: FormSignUp) => {
const { description, richDescription, callToActionText, callToActionType } = await schema.validate(data);
if (!widget) {
Expand Down
Loading

0 comments on commit 4d50737

Please sign in to comment.