Skip to content

Commit

Permalink
feat: API changes for business as a host (bcgov#257)
Browse files Browse the repository at this point in the history
* feat: API changes for business as a host

* no message
  • Loading branch information
kris-daxiom authored Nov 1, 2024
1 parent a8fc071 commit cdb2ea5
Show file tree
Hide file tree
Showing 10 changed files with 278 additions and 2 deletions.
46 changes: 46 additions & 0 deletions strr-api/migrations/versions/20241031_2216_1ddad4ce0e21_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""empty message
Revision ID: 1ddad4ce0e21
Revises: 14f84cc80367
Create Date: 2024-10-31 22:16:54.409155
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = '1ddad4ce0e21'
down_revision = '14f84cc80367'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###

contacttype = postgresql.ENUM('INDIVIDUAL', 'BUSINESS', name='contacttype')
contacttype.create(op.get_bind(), checkfirst=True)

with op.batch_alter_table('property_contacts', schema=None) as batch_op:
batch_op.add_column(sa.Column('contact_type', contacttype, nullable=True))
batch_op.add_column(sa.Column('business_legal_name', sa.String(length=1000), nullable=True))

with op.batch_alter_table('property_contacts_history', schema=None) as batch_op:
batch_op.add_column(sa.Column('contact_type', contacttype, autoincrement=False, nullable=True))
batch_op.add_column(sa.Column('business_legal_name', sa.String(length=1000), autoincrement=False, nullable=True))

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('property_contacts_history', schema=None) as batch_op:
batch_op.drop_column('business_legal_name')
batch_op.drop_column('contact_type')

with op.batch_alter_table('property_contacts', schema=None) as batch_op:
batch_op.drop_column('business_legal_name')
batch_op.drop_column('contact_type')

# ### end Alembic commands ###
2 changes: 1 addition & 1 deletion strr-api/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "strr-api"
version = "0.0.18"
version = "0.0.19"
description = ""
authors = ["thorwolpert <[email protected]>"]
license = "BSD 3-Clause"
Expand Down
8 changes: 8 additions & 0 deletions strr-api/src/strr_api/models/rental.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,18 @@ class PropertyManager(Versioned, BaseModel):
class PropertyContact(Versioned, BaseModel):
"""Property Contacts"""

class ContactType(BaseEnum):
"""Enum of host residence option."""

INDIVIDUAL = auto() # pylint: disable=invalid-name
BUSINESS = auto() # pylint: disable=invalid-name

__tablename__ = "property_contacts"

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
is_primary = db.Column(db.Boolean, nullable=False, default=False)
contact_type = db.Column(db.Enum(ContactType), default=ContactType.INDIVIDUAL)
business_legal_name = db.Column(db.String(1000), nullable=True)

contact_id = db.Column(db.Integer, db.ForeignKey("contacts.id"), nullable=False)
property_id = db.Column(db.Integer, db.ForeignKey("rental_properties.id"), nullable=False)
Expand Down
14 changes: 13 additions & 1 deletion strr-api/src/strr_api/requests/RegistrationRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,25 @@ def __init__(self, phoneNumber, emailAddress, preferredName=None, extension=None
class Contact:
"""Contact payload object."""

def __init__(self, name, dateOfBirth, details, mailingAddress, socialInsuranceNumber=None, businessNumber=None):
def __init__(
self,
name,
dateOfBirth,
details,
mailingAddress,
socialInsuranceNumber=None,
businessNumber=None,
businessLegalName=None,
contactType=None,
):
self.name = ContactName(**name)
self.dateOfBirth = dateOfBirth
self.socialInsuranceNumber = socialInsuranceNumber
self.businessNumber = businessNumber
self.details = ContactDetails(**details)
self.mailingAddress = MailingAddress(**mailingAddress)
self.businessLegalName = businessLegalName
self.contactType = contactType


class Document:
Expand Down
3 changes: 3 additions & 0 deletions strr-api/src/strr_api/responses/RegistrationSerializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ def populate_host_registration_details(cls, registration_data: dict, registratio
"dateOfBirth": primary_property_contact.contact.date_of_birth,
"socialInsuranceNumber": primary_property_contact.contact.social_insurance_number,
"businessNumber": primary_property_contact.contact.business_number,
"contactType": primary_property_contact.contact_type,
"businessLegalName": primary_property_contact.business_legal_name,
"details": {
"preferredName": primary_property_contact.contact.preferredname,
"phoneNumber": primary_property_contact.contact.phone_number,
Expand Down Expand Up @@ -141,6 +143,7 @@ def populate_host_registration_details(cls, registration_data: dict, registratio
},
"dateOfBirth": secondary_property_contact.contact.date_of_birth,
"socialInsuranceNumber": secondary_property_contact.contact.social_insurance_number,
"contactType": secondary_property_contact.contact_type,
"businessNumber": secondary_property_contact.contact.business_number,
"details": {
"preferredName": secondary_property_contact.contact.preferredname,
Expand Down
11 changes: 11 additions & 0 deletions strr-api/src/strr_api/schemas/schemas/host-registration.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@
"businessNumber": {
"type": "string"
},
"businessLegalName": {
"type": "string"
},
"contactType": {
"type": "string",
"enum": [
"INDIVIDUAL",
"BUSINESS"
],
"default": "INDIVIDUAL"
},
"details": {
"type": "object",
"properties": {
Expand Down
3 changes: 3 additions & 0 deletions strr-api/src/strr_api/services/registration_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ def _create_host_registration(cls, registration_request: dict) -> RentalProperty

primary_property_contact = PropertyContact()
primary_property_contact.is_primary = True
primary_property_contact.contact_type = registration_request.primaryContact.contactType
primary_property_contact.business_legal_name = registration_request.primaryContact.businessLegalName
primary_property_contact.contact = Contact(
firstname=registration_request.primaryContact.name.firstName,
lastname=registration_request.primaryContact.name.lastName,
Expand All @@ -252,6 +254,7 @@ def _create_host_registration(cls, registration_request: dict) -> RentalProperty
if registration_request.secondaryContact:
secondary_property_contact = PropertyContact()
secondary_property_contact.is_primary = False
secondary_property_contact.contact_type = registration_request.secondaryContact.contactType
secondary_property_contact.contact = Contact(
firstname=registration_request.secondaryContact.name.firstName,
lastname=registration_request.secondaryContact.name.lastName,
Expand Down
87 changes: 87 additions & 0 deletions strr-api/tests/mocks/json/business_as_host.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"registration": {
"registrationType": "HOST",
"primaryContact": {
"contactType": "BUSINESS",
"businessLegalName": "Test Business",
"businessNumber": "123456789",
"name": {
"firstName": "The",
"middleName": "First",
"lastName": "Guy"
},
"dateOfBirth": "1986-10-23",
"details": {
"preferredName": "Mickey",
"phoneNumber": "604-999-9999",
"extension": "x64",
"faxNumber": "604-777-7777",
"emailAddress": "[email protected]"
},
"mailingAddress": {
"country": "CA",
"address": "12766 227st",
"addressLineTwo": "",
"city": "MAPLE RIDGE",
"province": "BC",
"postalCode": "V2X 6K6"
}
},
"secondaryContact": {
"contactType": "INDIVIDUAL",
"name": {
"firstName": "The",
"middleName": "Other",
"lastName": "Guy"
},
"dateOfBirth": "1986-10-23",
"details": {
"preferredName": "Mouse",
"phoneNumber": "604-888-8888",
"extension": "",
"faxNumber": "",
"emailAddress": "[email protected]"
},
"mailingAddress": {
"country": "CA",
"address": "12766 227st",
"addressLineTwo": "",
"city": "MAPLE RIDGE",
"province": "BC",
"postalCode": "V2X 6K6"
}
},
"unitDetails": {
"parcelIdentifier": "000-460-991",
"businessLicense": "7777777",
"businessLicenseExpiryDate": "2025-01-01",
"propertyType": "SINGLE_FAMILY_HOME",
"ownershipType": "OWN",
"rentalUnitSpaceType": "ENTIRE_HOME",
"hostResidence": "SAME_UNIT",
"isUnitOnPrincipalResidenceProperty": true,
"numberOfRoomsForRent": 1
},
"unitAddress": {
"nickname": "My Rental Property",
"country": "CA",
"address": "12166 GREENWELL ST MAPLE RIDGE",
"addressLineTwo": "",
"city": "MAPLE RIDGE",
"province": "BC",
"postalCode": "V2X 7N1"
},
"listingDetails": [
{
"url": "https://www.airbnb.ca/rooms/26359027"
}
],
"principalResidence": {
"isPrincipalResidence": true,
"agreedToRentalAct": true,
"nonPrincipalOption": "n/a",
"specifiedServiceProvider": "n/a",
"agreedToSubmit": true
}
}
}
60 changes: 60 additions & 0 deletions strr-api/tests/postman/strr-api.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,66 @@
},
"response": []
},
{
"name": "Host Registration - Business as a host",
"event": [
{
"listen": "test",
"script": {
"exec": [
"var jsonData = pm.response.json();",
"",
"pm.test(\"Status code is 201\", function () {",
" pm.response.to.have.status(201);",
"});",
"",
"pm.environment.set(\"application_number\",jsonData.header.applicationNumber)"
],
"type": "text/javascript",
"packages": {}
}
}
],
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{token}}",
"type": "string"
}
]
},
"method": "POST",
"header": [
{
"key": "Account-Id",
"value": "{{account_id}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"registration\": {\n \"registrationType\": \"HOST\",\n \"primaryContact\": {\n \"contactType\": \"BUSINESS\",\n \"businessLegalName\": \"Test Business\",\n \"businessNumber\": \"123456789\",\n \"name\": {\n \"firstName\": \"The\",\n \"middleName\": \"First\",\n \"lastName\": \"Guy\"\n },\n \"dateOfBirth\": \"1986-10-23\",\n \"details\": {\n \"preferredName\": \"Mickey\",\n \"phoneNumber\": \"604-999-9999\",\n \"extension\": \"x64\",\n \"faxNumber\": \"604-777-7777\",\n \"emailAddress\": \"[email protected]\"\n },\n \"mailingAddress\": {\n \"country\": \"CA\",\n \"address\": \"12766 227st\",\n \"addressLineTwo\": \"\",\n \"city\": \"MAPLE RIDGE\",\n \"province\": \"BC\",\n \"postalCode\": \"V2X 6K6\"\n }\n },\n \"secondaryContact\": {\n \"contactType\": \"INDIVIDUAL\",\n \"name\": {\n \"firstName\": \"The\",\n \"middleName\": \"Other\",\n \"lastName\": \"Guy\"\n },\n \"dateOfBirth\": \"1986-10-23\",\n \"details\": {\n \"preferredName\": \"Mouse\",\n \"phoneNumber\": \"604-888-8888\",\n \"extension\": \"\",\n \"faxNumber\": \"\",\n \"emailAddress\": \"[email protected]\"\n },\n \"mailingAddress\": {\n \"country\": \"CA\",\n \"address\": \"12766 227st\",\n \"addressLineTwo\": \"\",\n \"city\": \"MAPLE RIDGE\",\n \"province\": \"BC\",\n \"postalCode\": \"V2X 6K6\"\n }\n },\n \"unitDetails\": {\n \"parcelIdentifier\": \"000-460-991\",\n \"businessLicense\": \"7777777\",\n \"businessLicenseExpiryDate\": \"2025-01-01\",\n \"propertyType\": \"SINGLE_FAMILY_HOME\",\n \"ownershipType\": \"OWN\",\n \"rentalUnitSpaceType\": \"ENTIRE_HOME\",\n \"hostResidence\": \"SAME_UNIT\",\n \"isUnitOnPrincipalResidenceProperty\": true,\n \"numberOfRoomsForRent\": 1\n },\n \"unitAddress\": {\n \"nickname\": \"My Rental Property\",\n \"country\": \"CA\",\n \"address\": \"12166 GREENWELL ST MAPLE RIDGE\",\n \"addressLineTwo\": \"\",\n \"city\": \"MAPLE RIDGE\",\n \"province\": \"BC\",\n \"postalCode\": \"V2X 7N1\"\n },\n \"listingDetails\": [\n {\n \"url\": \"https://www.airbnb.ca/rooms/26359027\"\n }\n ],\n \"principalResidence\": {\n \"isPrincipalResidence\": true,\n \"agreedToRentalAct\": true,\n \"nonPrincipalOption\": \"n/a\",\n \"specifiedServiceProvider\": \"n/a\",\n \"agreedToSubmit\": true\n }\n }\n}\n",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{api_url}}/applications",
"host": [
"{{api_url}}"
],
"path": [
"applications"
]
}
},
"response": []
},
{
"name": "Update Application Payment Details",
"request": {
Expand Down
46 changes: 46 additions & 0 deletions strr-api/tests/unit/resources/test_registration_applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
CREATE_STRATA_HOTEL_REGISTRATION_REQUEST = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "../../mocks/json/strata_hotel_registration.json"
)
CREATE_HOST_REGISTRATION_BUSINESS_AS_HOST = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "../../mocks/json/business_as_host.json"
)

ACCOUNT_ID = 1234

Expand Down Expand Up @@ -480,3 +483,46 @@ def test_create_strata_hotel_registration_application_bad_request(session, clien
rv = client.post("/applications", json=json_data, headers=headers)

assert HTTPStatus.BAD_REQUEST == rv.status_code


@patch("strr_api.services.strr_pay.create_invoice", return_value=MOCK_INVOICE_RESPONSE)
def test_create_registration_application_with_business_as_a_host(session, client, jwt):
with open(CREATE_HOST_REGISTRATION_BUSINESS_AS_HOST) as f:
json_data = json.load(f)
headers = create_header(jwt, [PUBLIC_USER], "Account-Id")
headers["Account-Id"] = ACCOUNT_ID
rv = client.post("/applications", json=json_data, headers=headers)

assert HTTPStatus.CREATED == rv.status_code


@patch("strr_api.services.strr_pay.create_invoice", return_value=MOCK_INVOICE_RESPONSE)
def test_approve_registration_application_with_business_as_a_host(session, client, jwt):
with open(CREATE_HOST_REGISTRATION_BUSINESS_AS_HOST) as f:
headers = create_header(jwt, [PUBLIC_USER], "Account-Id")
headers["Account-Id"] = ACCOUNT_ID
json_data = json.load(f)

rv = client.post("/applications", json=json_data, headers=headers)
response_json = rv.json
application_number = response_json.get("header").get("applicationNumber")

application = Application.find_by_application_number(application_number=application_number)
application.payment_status = PaymentStatus.COMPLETED.value
application.save()

staff_headers = create_header(jwt, [STRR_EXAMINER], "Account-Id")
status_update_request = {"status": Application.Status.FULL_REVIEW_APPROVED}
rv = client.put(f"/applications/{application_number}/status", json=status_update_request, headers=staff_headers)
assert HTTPStatus.OK == rv.status_code
response_json = rv.json
assert response_json.get("header").get("status") == Application.Status.FULL_REVIEW_APPROVED
assert response_json.get("header").get("reviewer").get("username") is not None
assert response_json.get("header").get("registrationId") is not None
assert response_json.get("header").get("registrationNumber") is not None
assert response_json.get("header").get("hostStatus") == "Approved"
assert response_json.get("header").get("examinerStatus") == "Approved – Examined"
assert response_json.get("header").get("examinerActions") == ApplicationSerializer.EXAMINER_ACTIONS.get(
Application.Status.FULL_REVIEW_APPROVED
)
assert response_json.get("header").get("hostActions") == []

0 comments on commit cdb2ea5

Please sign in to comment.