diff --git a/.github/workflows/build-validator.yml b/.github/workflows/build-validator.yml new file mode 100644 index 0000000..47405c5 --- /dev/null +++ b/.github/workflows/build-validator.yml @@ -0,0 +1,29 @@ +name: Validate Build + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + name: Build + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@master + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22.0 + + - name: Install Dependencies + run: | + cd functions + npm install + + - name: Build + run: | + cd functions + npm run build \ No newline at end of file diff --git a/functions/src/data/firebase/Firebase.ts b/functions/src/data/firebase/Firebase.ts index 31e25e0..23d1868 100644 --- a/functions/src/data/firebase/Firebase.ts +++ b/functions/src/data/firebase/Firebase.ts @@ -1,9 +1,11 @@ import { initializeApp } from "firebase-admin/app" import { firestore } from "firebase-admin" import { getStorage } from "firebase-admin/storage" +// import { getDownloadURL } from "firebase-admin/storage" initializeApp() +// export {getDownloadURL} export const database = firestore() export const storage = getStorage() export { File } from '@google-cloud/storage' \ No newline at end of file diff --git a/functions/src/data/firebase/index.ts b/functions/src/data/firebase/index.ts index 0075b07..87d4261 100644 --- a/functions/src/data/firebase/index.ts +++ b/functions/src/data/firebase/index.ts @@ -1,3 +1,4 @@ export { database } from "./Firebase" export { storage } from "./Firebase" -export { File } from './Firebase' \ No newline at end of file +export { File } from './Firebase' +// export {getDownloadURL} from './Firebase' \ No newline at end of file diff --git a/functions/src/data/franchise/get/franchise/GetFranchiseRepository.ts b/functions/src/data/franchise/get/franchise/GetFranchiseRepository.ts new file mode 100644 index 0000000..3f3b4ec --- /dev/null +++ b/functions/src/data/franchise/get/franchise/GetFranchiseRepository.ts @@ -0,0 +1,24 @@ +import { database } from '@data/firebase'; + +export async function GetFranchiseRepository(): Promise { + try { + let franchises = [] + const franchisesSnapshot = await database.collection('franchises').get(); + if (franchisesSnapshot.empty) { + console.log("No franchises."); + return []; + } + for (const doc of franchisesSnapshot.docs) { + const data = doc.id; + // console.log("GetFranchiseRepository data: ", JSON.stringify(data)); + franchises.push(data.toLowerCase()) + } + // console.log("GetFranchiseRepository franchises: ", franchises) + return franchises + } catch (error) { + console.error('Error fetching franchises data:', error); + throw error; + } +} + + diff --git a/functions/src/data/franchise/index.ts b/functions/src/data/franchise/index.ts new file mode 100644 index 0000000..21f7e85 --- /dev/null +++ b/functions/src/data/franchise/index.ts @@ -0,0 +1 @@ +export {GetFranchiseRepository} from "./get/franchise/GetFranchiseRepository" \ No newline at end of file diff --git a/functions/src/data/image/get/image/DTO/ImageDTO.ts b/functions/src/data/image/get/image/DTO/ImageDTO.ts new file mode 100644 index 0000000..36ad4ec --- /dev/null +++ b/functions/src/data/image/get/image/DTO/ImageDTO.ts @@ -0,0 +1,3 @@ +export type ImageDTO = { + image: string | [] +} \ No newline at end of file diff --git a/functions/src/data/image/get/image/GetImageRepository.ts b/functions/src/data/image/get/image/GetImageRepository.ts new file mode 100644 index 0000000..5db213d --- /dev/null +++ b/functions/src/data/image/get/image/GetImageRepository.ts @@ -0,0 +1,28 @@ +import { storage } from "@data/firebase"; +import { ImageDTO } from "@data/image"; + +export async function GetImageRepository(image: string): Promise { + try { + const imageRef = storage.bucket().file(image); + if (!imageRef) { + console.log('Image does not exist in Firebase Storage'); + return { image: [] }; // Empty Base64 string if image doesn't exist + } + + const [fileBuffer] = await imageRef.download(); + if (!fileBuffer) { + console.log('Failed to download image from Firebase Storage'); + return { image: [] }; // Empty Base64 string if download fails + } + + // Convert file buffer to Base64 + const base64Image = fileBuffer.toString('base64'); + const imageResult: ImageDTO = { + image: base64Image, + }; + return imageResult; + } catch (error) { + console.error('Error fetching image data:', error); + throw error; + } +} diff --git a/functions/src/data/image/index.ts b/functions/src/data/image/index.ts new file mode 100644 index 0000000..3f81dd8 --- /dev/null +++ b/functions/src/data/image/index.ts @@ -0,0 +1,2 @@ +export { ImageDTO } from "./get/image/DTO/ImageDTO" +export { GetImageRepository } from "./get/image/GetImageRepository" \ No newline at end of file diff --git a/functions/src/data/place/get/place/DTO/PlaceDTO.ts b/functions/src/data/place/get/place/DTO/PlaceDTO.ts index 4f64caa..eb15602 100644 --- a/functions/src/data/place/get/place/DTO/PlaceDTO.ts +++ b/functions/src/data/place/get/place/DTO/PlaceDTO.ts @@ -6,5 +6,5 @@ export type PlaceDTO = { id: string, displayName: LocalizedTextDTO, addressComponents: AddressComponentsDTO[], - location: LatLngDTO + location: LatLngDTO | null } \ No newline at end of file diff --git a/functions/src/data/place/get/places/DTO/GetPlacesRepositoryRequest.ts b/functions/src/data/place/get/places/DTO/GetPlacesRepositoryRequest.ts new file mode 100644 index 0000000..8763a34 --- /dev/null +++ b/functions/src/data/place/get/places/DTO/GetPlacesRepositoryRequest.ts @@ -0,0 +1,5 @@ +export type GetPlacesRepositoryRequest = { + searchText: string + nextPageToken?: string + userLocation?: { latitude: number, longitude: number } +} \ No newline at end of file diff --git a/functions/src/data/place/get/places/DTO/GetPlacesRepositoryResponse.ts b/functions/src/data/place/get/places/DTO/GetPlacesRepositoryResponse.ts index bd6d781..be9eb55 100644 --- a/functions/src/data/place/get/places/DTO/GetPlacesRepositoryResponse.ts +++ b/functions/src/data/place/get/places/DTO/GetPlacesRepositoryResponse.ts @@ -1,6 +1,6 @@ import { PlaceDTO } from "../../place/DTO/PlaceDTO"; export type GetPlacesRepositoryResponse = { - places: PlaceDTO[], + places: PlaceDTO[] | [], nextPageToken?: string } \ No newline at end of file diff --git a/functions/src/data/place/get/places/GetPlacesRepository.ts b/functions/src/data/place/get/places/GetPlacesRepository.ts index 0c9870d..6eaabbd 100644 --- a/functions/src/data/place/get/places/GetPlacesRepository.ts +++ b/functions/src/data/place/get/places/GetPlacesRepository.ts @@ -1,21 +1,64 @@ import { PlaceDTO } from "../place/DTO/PlaceDTO" import { AddressComponentsDTO } from "../place/DTO/AddressComponentsDTO" import { GetPlacesRepositoryResponse } from "./DTO/GetPlacesRepositoryResponse" +import { GetPlacesRepositoryRequest } from "./DTO/GetPlacesRepositoryRequest" +import { locationRestrictionOfNZ } from "@shared/constants" +import { database } from "@data/firebase" -export const locationRestrictionOfNZ = { - rectangle: { - low: { - latitude: -47.0, - longitude: 166.0, - }, - high: { - latitude: -34.0, - longitude: 178.0, - }, +export function GetPlacesRepository(request: GetPlacesRepositoryRequest): Promise +export function GetPlacesRepository(placesIds: string[]): Promise + +export async function GetPlacesRepository(param: GetPlacesRepositoryRequest | string[]): Promise { + if (Array.isArray(param)) { + return await _GetPlacesFromFirestore(param) + } else { + const request = param as GetPlacesRepositoryRequest + return await _GetPlacesFromGoogle(request.searchText, request.nextPageToken, request.userLocation) + } +} + +async function _GetPlacesFromFirestore( + placesIds: string[] +): Promise { + try { + const placesSnapshot = await database + .collection('places') + .where("id", "in", placesIds) + .get(); + + if (placesSnapshot.empty) { + console.log("Places data are undefined for the given places IDs."); + return { places: [], nextPageToken: undefined }; + } else { + const matchedPlaces = placesSnapshot.docs.map((doc) => { + const data = doc.data() as PlaceDTO; + return { + id: data.id, + displayName: { + text: data.displayName.text, + languageCode: data.displayName.languageCode, + }, + addressComponents: data.addressComponents.map((component: AddressComponentsDTO) => { + return { + longText: component.longText, + shortText: component.shortText, + types: component.types, + languageCode: data.displayName.languageCode, + } + }), + location: null, + }; + }); + + return { places: matchedPlaces, nextPageToken: undefined }; + } + } catch (error) { + console.error("Error fetching places:", error); + throw error; } } -export async function GetPlacesRepository( +async function _GetPlacesFromGoogle( searchText: string, nextPageToken?: string, userLocation?: { latitude: number, longitude: number } @@ -86,9 +129,7 @@ export async function GetPlacesRepository( } - const data = await response.json() - - throw new Error(data) + throw new Error(response.statusText) } catch (error) { throw error diff --git a/functions/src/data/place/index.ts b/functions/src/data/place/index.ts index b3d21da..55912d3 100644 --- a/functions/src/data/place/index.ts +++ b/functions/src/data/place/index.ts @@ -3,5 +3,4 @@ export { PostPlaceRepositoryRequest } from './post/place/DTO/PostPlaceRepository export { PlaceDTO } from './get/place/DTO/PlaceDTO' export { GetPlacesRepository } from './get/places/GetPlacesRepository' export { GetPlaceRepository } from './get/place/GetPlaceRepository' -export { PostPlaceRepository } from './post/place/PostPlaceRepository' -export { locationRestrictionOfNZ } from './get/places/GetPlacesRepository' \ No newline at end of file +export { PostPlaceRepository } from './post/place/PostPlaceRepository' \ No newline at end of file diff --git a/functions/src/data/place/post/place/DTO/PostPlaceRepositoryRequest.ts b/functions/src/data/place/post/place/DTO/PostPlaceRepositoryRequest.ts index 8413e1a..d596c18 100644 --- a/functions/src/data/place/post/place/DTO/PostPlaceRepositoryRequest.ts +++ b/functions/src/data/place/post/place/DTO/PostPlaceRepositoryRequest.ts @@ -19,5 +19,5 @@ export interface PostPlaceRepositoryRequest { id: string; displayName: displayName, addressComponents: AddressComponentsDTO[], - location: LatLngDTO + location: LatLngDTO | null } diff --git a/functions/src/data/surcharge/get/DTO/GetSurchargesRepositoryResponse.ts b/functions/src/data/surcharge/get/DTO/GetSurchargesRepositoryResponse.ts index e8b4721..c1a8189 100644 --- a/functions/src/data/surcharge/get/DTO/GetSurchargesRepositoryResponse.ts +++ b/functions/src/data/surcharge/get/DTO/GetSurchargesRepositoryResponse.ts @@ -3,11 +3,14 @@ import { Timestamp } from "firebase-admin/firestore"; export enum SurchargeStatus { REPORTED = 'REPORTED', CONFIRMED = 'CONFIRMED', - UNKNOWN = 'UNKNOWN' + UNKNOWN = 'UNKNOWN', + AUTO_GENERATED = 'AUTO_GENERATED', + REJECTED = 'REJECTED' } export type GetSurchargesRepositoryResponse = { id: string + image?: string placeInformation: string reportedDate: Timestamp rate: number diff --git a/functions/src/data/surcharge/get/getSurchargesRepository.ts b/functions/src/data/surcharge/get/getSurchargesRepository.ts index c8e7f11..a087e08 100644 --- a/functions/src/data/surcharge/get/getSurchargesRepository.ts +++ b/functions/src/data/surcharge/get/getSurchargesRepository.ts @@ -1,5 +1,6 @@ import { GetSurchargesRepositoryResponse, SurchargeStatus } from './DTO/GetSurchargesRepositoryResponse' import { database } from "@data/firebase" +// import { storage, getDownloadURL } from "@data/firebase" export function GetSurchargesRepository(placeId: string): Promise export function GetSurchargesRepository(placeIds: string[]): Promise @@ -36,7 +37,6 @@ async function _GetSurcharge(placeId: string): Promise { try { - const surcharges = await database - .collection('surcharges') - .get() - if (!surcharges){ - console.log('There is no surcharges data yet') - return {} - } else{ - const AllSurcharges = surcharges.docs.map((surcharge) => { - const data = surcharge.data() + const surcharges = await database.collection('surcharges').get(); + + if (surcharges.empty) { + console.log('There is no surcharges data yet'); + return {}; + } + + // Fetch all surcharges and handle image retrieval + const AllSurcharges = await Promise.all( + surcharges.docs.map(async (surcharge) => { + const data = surcharge.data(); + // const fileName = data.image; + // const file = storage.bucket().file(fileName); + // const url = await getDownloadURL(file) return { id: surcharge.id, - placeInformation: data.placeInformation, // Convert Firestore reference to string + image: data.image, // Download url + placeInformation: data.placeInformation, // Convert Firestore reference to string if necessary rate: data.rate, reportedDate: data.reportedDate, // Keep as Firestore Timestamp totalAmount: data.totalAmount, surchargeAmount: data.surchargeAmount, - surchargeStatus: data.surchargeStatus - } + surchargeStatus: data.surchargeStatus, + }; }) - console.log("All surcharges fetched successfully:", AllSurcharges); - return AllSurcharges - } + ); + + console.log('All surcharges fetched successfully:'); + return AllSurcharges; } catch (error) { - console.error("Error fetching surcharges:", error); + console.error('Error fetching surcharges:', error); throw error; } } \ No newline at end of file diff --git a/functions/src/data/surcharge/index.ts b/functions/src/data/surcharge/index.ts index e412cc4..fb05121 100644 --- a/functions/src/data/surcharge/index.ts +++ b/functions/src/data/surcharge/index.ts @@ -1,5 +1,7 @@ export { GetSurchargesRepository } from './get/getSurchargesRepository' export { PostSurchargeRepo } from "./post/postSurchargeRepository" export {SurchargeStatus} from "./post/DTO/PostSurchargeRepositoryRequest" +export { PutSurchargeRepository } from "./put/PutSurchargeRepository" export { GetSurchargesRepositoryResponse } from './get/DTO/GetSurchargesRepositoryResponse' -export { PostSurchargeRepositoryRequest } from './post/DTO/PostSurchargeRepositoryRequest' \ No newline at end of file +export { PostSurchargeRepositoryRequest } from './post/DTO/PostSurchargeRepositoryRequest' +export { PutSurchargeRepositoryRequest } from './put/DTO/PutSurchargeRepositoryRequest' \ No newline at end of file diff --git a/functions/src/data/surcharge/put/DTO/PutSurchargeRepositoryRequest.ts b/functions/src/data/surcharge/put/DTO/PutSurchargeRepositoryRequest.ts new file mode 100644 index 0000000..3eb578b --- /dev/null +++ b/functions/src/data/surcharge/put/DTO/PutSurchargeRepositoryRequest.ts @@ -0,0 +1,16 @@ +export enum SurchargeStatus { + REPORTED = 'REPORTED', + CONFIRMED = 'CONFIRMED', + UNKNOWN = 'UNKNOWN', + AUTO_GENERATED = 'AUTO_GENERATED', + REJECTED = 'REJECTED' +} + +export type PutSurchargeRepositoryRequest = { + id: string, + rate?: number, + surchargeAmount?: number, + totalAmount?: number, + surchargeStatus: SurchargeStatus, + action: string +} \ No newline at end of file diff --git a/functions/src/data/surcharge/put/PutSurchargeRepository.ts b/functions/src/data/surcharge/put/PutSurchargeRepository.ts new file mode 100644 index 0000000..ed53733 --- /dev/null +++ b/functions/src/data/surcharge/put/PutSurchargeRepository.ts @@ -0,0 +1,66 @@ +import { SurchargeStatus } from "@domain/surcharge"; +import { PutSurchargeRepositoryRequest } from "./DTO/PutSurchargeRepositoryRequest"; +import { database } from "@data/firebase" +import { storage } from "@data/firebase"; + +export async function PutSurchargeRepository(request: PutSurchargeRepositoryRequest): Promise { + try { + console.log("PutSurchargeRepository ID: ", request.id) + const dbRef = database.collection('surcharges') + const docRef = dbRef.doc(request.id) + const doc = await docRef.get() + const surcharge = doc.data() + + if (!docRef || !surcharge ) { + throw new Error("Surcharge data is undefined for the given id in PutSurchargeRepository.") + } else { + function newFolder(surchargeImage: string, status: SurchargeStatus){ + if (request.action === "CONFIRM" && status === SurchargeStatus.REPORTED){ + return `confirmed/${surchargeImage.substring(9)}` // from "reported/..." to "confirmed/.." + } else if (request.action === "REJECT" && status === SurchargeStatus.REPORTED){ + return `rejected/${surchargeImage.substring(9)}` // from "reported/..." to "rejected/.." + } else if (request.action === "CONFIRM" && status === SurchargeStatus.REJECTED){ + return `confirmed/${surchargeImage.substring(9)}` // from "rejected/..." to "confirmed/.." + } else if (request.action === "REJECT" && status === SurchargeStatus.CONFIRMED){ + return `rejected/${surchargeImage.substring(10)}` // from "confirmed/..." to "rejected/.." + } else return surchargeImage + } + + try { + const imageRef = storage.bucket().file(surcharge.image); + const [fileBuffer] = await imageRef.download(); + const newFileRef = storage.bucket().file(newFolder(surcharge.image, surcharge.surchargeStatus)); + await newFileRef.save(fileBuffer, { contentType: 'image/jpeg' }); + await imageRef.delete(); + console.log(`Image moved to ${newFileRef.name} and deleted from the previous location.`); + } catch (error) { + console.error("An error occurred while moving the image:", error); + } + + + await docRef.set({ + image: newFolder(surcharge.image, surcharge.surchargeStatus), + placeInformation: surcharge.placeInformation, + rate: request.rate ?? surcharge.rate, + reportedDate: surcharge.reportedDate, + surchargeAmount: request.surchargeAmount ?? surcharge.surchargeAmount, + surchargeStatus: request.surchargeStatus, + totalAmount: request.totalAmount ?? surcharge.totalAmount + }); + + // return { + // image: imageNameWithNewFolder, + // placeInformation: surcharge.placeInformation, + // rate: request.rate ?? surcharge.rate, + // reportedDate: surcharge.reportedDate, + // surchargeAmount: request.surchargeAmount ?? surcharge.surchargeAmount, + // surchargeStatus: request.surchargeStatus, + // totalAmount: request.totalAmount ?? surcharge.totalAmount + // } + console.log("Surcharge confirmed in PutSurchargeRepository:"); + } + } catch (error) { + console.error("Error updating surcharge:", error); + throw error; // Re-throw the error for higher-level handling if needed + } +} \ No newline at end of file diff --git a/functions/src/domain/image/get/image/entity/GetImageUsecaseRequest.ts b/functions/src/domain/image/get/image/entity/GetImageUsecaseRequest.ts new file mode 100644 index 0000000..3786101 --- /dev/null +++ b/functions/src/domain/image/get/image/entity/GetImageUsecaseRequest.ts @@ -0,0 +1,3 @@ +export interface GetImageUsecaseRequest { + image: string +} \ No newline at end of file diff --git a/functions/src/domain/image/get/image/entity/GetImageUsecaseResponse.ts b/functions/src/domain/image/get/image/entity/GetImageUsecaseResponse.ts new file mode 100644 index 0000000..dbb7a5b --- /dev/null +++ b/functions/src/domain/image/get/image/entity/GetImageUsecaseResponse.ts @@ -0,0 +1,3 @@ +export interface GetImageUsecaseResponse { + image: string | [] +} \ No newline at end of file diff --git a/functions/src/domain/image/get/image/getImageUsecase.ts b/functions/src/domain/image/get/image/getImageUsecase.ts new file mode 100644 index 0000000..12fd13c --- /dev/null +++ b/functions/src/domain/image/get/image/getImageUsecase.ts @@ -0,0 +1,11 @@ +import { GetImageUsecaseRequest } from "./entity/GetImageUsecaseRequest"; +import { GetImageUsecaseResponse } from "./entity/GetImageUsecaseResponse"; +import { GetImageRepository } from '@data/image' + +export const getImageUsecase = async (request: GetImageUsecaseRequest): Promise => { + const result = await GetImageRepository(request.image); + + return { + image: result.image, + }; +}; diff --git a/functions/src/domain/image/index.ts b/functions/src/domain/image/index.ts new file mode 100644 index 0000000..bcd9c74 --- /dev/null +++ b/functions/src/domain/image/index.ts @@ -0,0 +1 @@ +export { getImageUsecase } from "./get/image/getImageUsecase" \ No newline at end of file diff --git a/functions/src/domain/place/get/place/entity/GetPlaceUsecaseResponse.ts b/functions/src/domain/place/get/place/entity/GetPlaceUsecaseResponse.ts index 2dfb8d9..bedcc45 100644 --- a/functions/src/domain/place/get/place/entity/GetPlaceUsecaseResponse.ts +++ b/functions/src/domain/place/get/place/entity/GetPlaceUsecaseResponse.ts @@ -20,7 +20,9 @@ type addressComponents = { export enum SurchargeStatus{ REPORTED = 'REPORTED', CONFIRMED = 'CONFIRMED', - UNKNOWN = 'UNKNOWN' + UNKNOWN = 'UNKNOWN', + AUTO_GENERATED = 'AUTO_GENERATED', + REJECTED = 'REJECTED' } export type GetPlaceUsecaseResponse = { @@ -28,7 +30,10 @@ export type GetPlaceUsecaseResponse = { displayName: displayName, addressComponents: addressComponents[], location?: LatLng, + image?: string, rate?: number, reportedDate?: Timestamp, + totalAmount?: number, + surchargeAmount?: number, surchargeStatus?: SurchargeStatus } \ No newline at end of file diff --git a/functions/src/domain/place/get/place/getPlaceUsecase.ts b/functions/src/domain/place/get/place/getPlaceUsecase.ts index 61487f9..04c04ed 100644 --- a/functions/src/domain/place/get/place/getPlaceUsecase.ts +++ b/functions/src/domain/place/get/place/getPlaceUsecase.ts @@ -3,10 +3,25 @@ import { GetPlaceUsecaseRequest } from "./entity/GetPlaceUsecaseRequest"; import { GetPlaceUsecaseResponse } from "./entity/GetPlaceUsecaseResponse"; import { GetSurchargesRepository } from '@data/surcharge' import { SurchargeStatus } from "@data/surcharge" +import { GetFranchiseRepository } from "@data/franchise"; export const getPlaceUsecase = async (request: GetPlaceUsecaseRequest): Promise => { const result = await GetPlaceRepository(request.id); const surchargeData = await GetSurchargesRepository(request.id); + const franchisesNames = await GetFranchiseRepository() + + const name = result.displayName.text + let rate = surchargeData?.rate ?? undefined + let status = surchargeData?.surchargeStatus ?? SurchargeStatus.UNKNOWN + + franchisesNames.forEach(element => { + if (status === SurchargeStatus.UNKNOWN) { + if(name.toLowerCase().includes(element)){ + status = SurchargeStatus.AUTO_GENERATED + rate = 0.0 + } + } + }) return { id: result.id, @@ -24,8 +39,8 @@ export const getPlaceUsecase = async (request: GetPlaceUsecaseRequest): Promise< latitude: result.location?.latitude ?? 0, longitude: result.location?.longitude ?? 0, }, - rate: surchargeData?.rate ?? undefined, + rate: rate, reportedDate: surchargeData?.reportedDate ?? undefined, // Default to 0 if reportedDate is undefined - surchargeStatus: surchargeData?.surchargeStatus ?? SurchargeStatus.UNKNOWN, + surchargeStatus: status, }; }; diff --git a/functions/src/domain/place/get/places/GetPlacesUsecase.ts b/functions/src/domain/place/get/places/GetPlacesUsecase.ts new file mode 100644 index 0000000..a2ae659 --- /dev/null +++ b/functions/src/domain/place/get/places/GetPlacesUsecase.ts @@ -0,0 +1,152 @@ +import { GetSurchargesRepository, SurchargeStatus } from "@data/surcharge" +import { GetPlacesUsecaseRequest } from "./entity/GetPlacesUsecaseRequest" +import { GetPlacesUsecaseResponse } from "./entity/GetPlacesUsecaseResponse" +import { GetPlacesRepository } from "@data/place" +import { GetFranchiseRepository } from "@data/franchise" +import { locationRestrictionOfNZ } from "@shared/constants" + +export async function GetPlacesUsecase(request: GetPlacesUsecaseRequest | string[]): Promise { + let resultPlaces; + + if (Array.isArray(request)) { + + try { + const allSurcharges = await GetSurchargesRepository({}) + const allSurchargesIds = allSurcharges.map((surcharge) => { + return surcharge.id + }) + resultPlaces = await GetPlacesRepository(allSurchargesIds) + + // const resultSurcharges = await GetSurchargesRepository(resultPlaceIds) + + const placesWithSurcharges = resultPlaces.places.map((place) => { + return { + id: place.id, + displayName: { + text: place.displayName.text, + languageCode: place.displayName.languageCode, + }, + addressComponents: place.addressComponents.map((component) => ({ + longText: component.longText, + shortText: component.shortText, + types: component.types, + languageCode: component.languageCode, + })), + location: place.location + ? { + latitude: place.location.latitude, + longitude: place.location.longitude, + } + : undefined, + image: allSurcharges.find((surcharge) => surcharge.id === place.id)?.image, + rate: allSurcharges.find((surcharge) => surcharge.id === place.id)?.rate, + totalAmount: allSurcharges.find((surcharge) => surcharge.id === place.id)?.totalAmount, + reportedDate: allSurcharges.find((surcharge) => surcharge.id === place.id)?.reportedDate, + surchargeAmount: allSurcharges.find((surcharge) => surcharge.id === place.id)?.surchargeAmount, + surchargeStatus: allSurcharges.find((surcharge) => surcharge.id === place.id)?.surchargeStatus as SurchargeStatus, + } + }) + + return { + places: placesWithSurcharges, + nextPageToken: undefined, + } + + } catch (error) { + throw error + } + + } else { + + if (request.userLocation) { + if (!isPointInRectangle(request.userLocation, locationRestrictionOfNZ)) { + throw new Error("User location is out of New Zealand") + } + } + resultPlaces = await GetPlacesRepository( + { + searchText: request.searchText, + nextPageToken: request.nextPageToken, + userLocation: request.userLocation, + } + ) + } + + const resultPlaceIds = resultPlaces.places.map((place) => { + return place.id + }) + + try { + + const [resultSurcharges, franchisesNames] = await Promise.all( + [GetSurchargesRepository(resultPlaceIds), GetFranchiseRepository()] + ) + + const placesWithSurcharges = resultPlaces.places.map((place) => { + + const name = place.displayName.text + + let rate = resultSurcharges.find((surcharge) => surcharge.id === place.id)?.rate + let status = resultSurcharges.find((surcharge) => surcharge.id === place.id)?.surchargeStatus as SurchargeStatus ?? SurchargeStatus.UNKNOWN + + franchisesNames.forEach(element => { + if (status === SurchargeStatus.UNKNOWN) { + if(name.toLowerCase().includes(element)){ + status = SurchargeStatus.AUTO_GENERATED + rate = 0.0 + } + } + }) + + return { + id: place.id, + displayName: { + text: place.displayName.text, + languageCode: place.displayName.languageCode, + }, + addressComponents: place.addressComponents.map((component) => ({ + longText: component.longText, + shortText: component.shortText, + types: component.types, + languageCode: component.languageCode, + })), + location: place.location + ? { + latitude: place.location.latitude, + longitude: place.location.longitude, + } + : undefined, + rate: rate, + surchargeStatus: status + } + }) + + return { + places: placesWithSurcharges, + nextPageToken: resultPlaces.nextPageToken, + } + + } catch (error) { + throw error + } +} + +function isPointInRectangle( + userLocation: { latitude: number, longitude: number }, + locationRestrictionOfNZ: { rectangle: { low: { latitude: number, longitude: number }, high: { latitude: number, longitude: number } } } +): boolean { + + const { latitude, longitude } = userLocation + + const { + low: { latitude: latLow, longitude: lonLow }, + high: { latitude: latHigh, longitude: lonHigh }, + } = locationRestrictionOfNZ.rectangle + + return ( + latitude >= latLow && + latitude <= latHigh && + longitude >= lonLow && + longitude <= lonHigh + ) +} \ No newline at end of file diff --git a/functions/src/domain/place/get/places/getPlacesUsecase.ts b/functions/src/domain/place/get/places/getPlacesUsecase.ts deleted file mode 100644 index 7679859..0000000 --- a/functions/src/domain/place/get/places/getPlacesUsecase.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { GetSurchargesRepository, SurchargeStatus } from "@data/surcharge" -import { GetPlacesUsecaseRequest } from "./entity/GetPlacesUsecaseRequest" -import { GetPlacesUsecaseResponse } from "./entity/GetPlacesUsecaseResponse" -import { GetPlacesRepository } from "@data/place" - -import { locationRestrictionOfNZ } from "@data/place" - -export const getPlacesUsecase = async (request: GetPlacesUsecaseRequest): Promise => { - - if (request.userLocation) { - if (!isPointInRectangle(request.userLocation, locationRestrictionOfNZ)) { - throw new Error("User location is out of New Zealand") - } - } - - const resultPlaces = await GetPlacesRepository(request.searchText, request.nextPageToken, request.userLocation) - - const resultPlaceIds = resultPlaces.places.map((place) => { - return place.id - }) - - try { - - const resultSurcharges = await GetSurchargesRepository(resultPlaceIds) - - const placesWithSurcharges = resultPlaces.places.map((place) => { - return { - id: place.id, - displayName: { - text: place.displayName.text, - languageCode: place.displayName.languageCode, - }, - addressComponents: place.addressComponents.map((component) => ({ - longText: component.longText, - shortText: component.shortText, - types: component.types, - languageCode: component.languageCode, - })), - location: place.location - ? { - latitude: place.location.latitude, - longitude: place.location.longitude, - } - : undefined, - rate: resultSurcharges.find((surcharge) => surcharge.id === place.id)?.rate, - surchargeStatus: resultSurcharges.find((surcharge) => surcharge.id === place.id)?.surchargeStatus as SurchargeStatus, - } - }) - - return { - places: placesWithSurcharges, - nextPageToken: resultPlaces.nextPageToken, - } - - } catch (error) { - throw error - } -} - -function isPointInRectangle( - userLocation: { latitude: number, longitude: number }, - locationRestrictionOfNZ: { rectangle: { low: { latitude: number, longitude: number }, high: { latitude: number, longitude: number } } } -): boolean { - - const { latitude, longitude } = userLocation - - const { - low: { latitude: latLow, longitude: lonLow }, - high: { latitude: latHigh, longitude: lonHigh }, - } = locationRestrictionOfNZ.rectangle - - return ( - latitude >= latLow && - latitude <= latHigh && - longitude >= lonLow && - longitude <= lonHigh - ) -} \ No newline at end of file diff --git a/functions/src/domain/place/index.ts b/functions/src/domain/place/index.ts index 2d0b7da..a0467ac 100644 --- a/functions/src/domain/place/index.ts +++ b/functions/src/domain/place/index.ts @@ -1,2 +1,2 @@ -export { getPlacesUsecase } from "./get/places/getPlacesUsecase" +export { GetPlacesUsecase } from "./get/places/GetPlacesUsecase" export { getPlaceUsecase } from "./get/place/getPlaceUsecase" \ No newline at end of file diff --git a/functions/src/domain/surcharge/get/entity/GetSurchargeUsecaseResponse.ts b/functions/src/domain/surcharge/get/entity/GetSurchargeUsecaseResponse.ts index 20fcd71..e62b957 100644 --- a/functions/src/domain/surcharge/get/entity/GetSurchargeUsecaseResponse.ts +++ b/functions/src/domain/surcharge/get/entity/GetSurchargeUsecaseResponse.ts @@ -1,10 +1,14 @@ export enum SurchargeStatus{ REPORTED = 'REPORTED', CONFIRMED = 'CONFIRMED', - UNKNOWN = 'UNKNOWN' + UNKNOWN = 'UNKNOWN', + AUTO_GENERATED = 'AUTO_GENERATED', + REJECTED = 'REJECTED' } export type GetSurchargeUsecaseResponse = { + id: string, + image?: string, placeInformation: string; rate: number, reportedDate: number diff --git a/functions/src/domain/surcharge/get/getSurchargeUsecase.ts b/functions/src/domain/surcharge/get/getSurchargeUsecase.ts index d93f8c6..cab744c 100644 --- a/functions/src/domain/surcharge/get/getSurchargeUsecase.ts +++ b/functions/src/domain/surcharge/get/getSurchargeUsecase.ts @@ -7,6 +7,7 @@ export const getSurchargeUsecase = async (request: GetSurchargeUsecaseRequest): const result = await GetSurchargesRepository(request.placeId) return { + id: result.id, placeInformation: result.placeInformation, rate: result.rate, reportedDate: result.reportedDate.toMillis(), diff --git a/functions/src/domain/surcharge/get/getSurchargesUsecase.ts b/functions/src/domain/surcharge/get/getSurchargesUsecase.ts index 97babf1..79cb65b 100644 --- a/functions/src/domain/surcharge/get/getSurchargesUsecase.ts +++ b/functions/src/domain/surcharge/get/getSurchargesUsecase.ts @@ -6,17 +6,19 @@ export const getSurchargesUsecase = async (): Promise { return { - placeInformation: surcharge.placeInformation, - rate: surcharge.rate, - reportedDate: surcharge.reportedDate.toMillis(), - totalAmount: surcharge.totalAmount, - surchargeAmount: surcharge.surchargeAmount, - surchargeStatus: surcharge.surchargeStatus + id: surcharge.id, + image: surcharge.image, + placeInformation: surcharge.placeInformation, + rate: surcharge.rate, + reportedDate: surcharge.reportedDate.toMillis(), + totalAmount: surcharge.totalAmount, + surchargeAmount: surcharge.surchargeAmount, + surchargeStatus: surcharge.surchargeStatus } }) return result } catch (error) { - console.error("Error posting surcharge:", error); + console.error("Error at getSurchargesUsecase:", error); throw error; } diff --git a/functions/src/domain/surcharge/helpers/rateCalculatorHelper.ts b/functions/src/domain/surcharge/helpers/rateCalculatorHelper.ts index 62d0d69..e27e59d 100644 --- a/functions/src/domain/surcharge/helpers/rateCalculatorHelper.ts +++ b/functions/src/domain/surcharge/helpers/rateCalculatorHelper.ts @@ -1,19 +1,14 @@ export function rateCalculatorHelper( - rate: number | undefined, totalAmount: number, surchargeAmount: number ): number { - if (typeof rate === 'undefined' || rate <= 0) { - const purchaseAmount = totalAmount - surchargeAmount; - - if (purchaseAmount <= 0) { - throw new Error('Invalid input: purchaseAmount amount must be greater than 0.'); - } - if (surchargeAmount <= 0) { - throw new Error('Invalid input: surchargeAmount amount must be greater than 0.'); - } - return Math.round((surchargeAmount / purchaseAmount) * 100); + if (surchargeAmount <= 0 || totalAmount <= 0) { + throw new Error('Invalid input: surchargeAmount and totalAmount must be greater than 0.'); } - - return rate; + const purchaseAmount = totalAmount - surchargeAmount + if (purchaseAmount <= 0) { + throw new Error('Invalid input: purchaseAmount amount must be greater than 0.'); + } + const rate = (surchargeAmount / purchaseAmount) * 100 + return Number(rate.toFixed(1)) } diff --git a/functions/src/domain/surcharge/index.ts b/functions/src/domain/surcharge/index.ts index 8adb4c4..cb74466 100644 --- a/functions/src/domain/surcharge/index.ts +++ b/functions/src/domain/surcharge/index.ts @@ -1,6 +1,9 @@ export { getSurchargeUsecase } from "./get/getSurchargeUsecase" export { getSurchargesUsecase } from "./get/getSurchargesUsecase" export { postSurchargeUsecase } from "./post/postSurchargeUsecase" -export { PostSurchargeUsecaseRequest } from './post/entity/PostSurchargeUsecaseRequest' +export { putSurchargeUsecase } from "./put/putSurchargeUsecase" export { GetSurchargeUsecaseResponse } from './get/entity/GetSurchargeUsecaseResponse' export { GetSurchargeUsecaseRequest } from './get/entity/GetSurchargeUsecaseRequest' +export { PostSurchargeUsecaseRequest } from './post/entity/PostSurchargeUsecaseRequest' +export { PutSurchargeUsecaseRequest } from "./put/entity/PutSurchargeUsecaseRequest" +export { SurchargeStatus } from './put/entity/SurchargeStatus' \ No newline at end of file diff --git a/functions/src/domain/surcharge/post/RateCalculator.ts b/functions/src/domain/surcharge/post/RateCalculator.ts index de7ab61..7fee235 100644 --- a/functions/src/domain/surcharge/post/RateCalculator.ts +++ b/functions/src/domain/surcharge/post/RateCalculator.ts @@ -3,5 +3,6 @@ export function RateCalculator( surchargeAmount: number ): number { const purchaseAmount = totalAmount - surchargeAmount - return Math.round((surchargeAmount / purchaseAmount) * 100) + const rate = (surchargeAmount / purchaseAmount) * 100 + return Number(rate.toFixed(1)) } \ No newline at end of file diff --git a/functions/src/domain/surcharge/put/entity/PutSurchargeUsecaseRequest.ts b/functions/src/domain/surcharge/put/entity/PutSurchargeUsecaseRequest.ts new file mode 100644 index 0000000..50842db --- /dev/null +++ b/functions/src/domain/surcharge/put/entity/PutSurchargeUsecaseRequest.ts @@ -0,0 +1,6 @@ +export type PutSurchargeUsecaseRequest = { + id: string, + surchargeAmount? : number, + totalAmount? : number, + action: string +} \ No newline at end of file diff --git a/functions/src/domain/surcharge/put/entity/SurchargeStatus.ts b/functions/src/domain/surcharge/put/entity/SurchargeStatus.ts new file mode 100644 index 0000000..23db250 --- /dev/null +++ b/functions/src/domain/surcharge/put/entity/SurchargeStatus.ts @@ -0,0 +1,7 @@ +export enum SurchargeStatus { + REPORTED = 'REPORTED', + CONFIRMED = 'CONFIRMED', + UNKNOWN = 'UNKNOWN', + AUTO_GENERATED = 'AUTO_GENERATED', + REJECTED = 'REJECTED' + } \ No newline at end of file diff --git a/functions/src/domain/surcharge/put/putSurchargeUsecase.ts b/functions/src/domain/surcharge/put/putSurchargeUsecase.ts new file mode 100644 index 0000000..8e5f419 --- /dev/null +++ b/functions/src/domain/surcharge/put/putSurchargeUsecase.ts @@ -0,0 +1,71 @@ +import { PutSurchargeUsecaseRequest } from "@domain/surcharge" +// import { GetSurchargesRepository } from "@data/surcharge" +import { PutSurchargeRepository } from "@data/surcharge" +import { SurchargeStatus } from "./entity/SurchargeStatus" +import { rateCalculatorHelper } from "../helpers/rateCalculatorHelper"; + +export const putSurchargeUsecase = async ( + request: PutSurchargeUsecaseRequest +): Promise<{ id: string; surchargeAmount?: number; totalAmount?: number; rate?: number; surchargeStatus: SurchargeStatus; action: string }> => { + let newRate: number | undefined = undefined; + + if (request.totalAmount && request.surchargeAmount) { + newRate = rateCalculatorHelper( + request.totalAmount, + request.surchargeAmount + ); + return await returnUpdatedSurcharge( + request.id, + newRate, + request.totalAmount, + request.surchargeAmount, + request.action + ); + } else { + return await returnUpdatedSurcharge( + request.id, + undefined, + undefined, + undefined, + request.action + ); + } +}; + +async function returnUpdatedSurcharge( + id: string, + rate: number | undefined, + totalAmount: number | undefined, + surchargeAmount: number | undefined, + action: string +): Promise<{ + id: string; + surchargeAmount?: number; + totalAmount?: number; + rate?: number; + surchargeStatus: SurchargeStatus; + action: string +}> { + let status = SurchargeStatus.REPORTED + if(action === "CONFIRM"){ + status = SurchargeStatus.CONFIRMED + } else if(action === "REJECT"){ + status = SurchargeStatus.REJECTED + } + const updatedSurcharge = { + id: id, + surchargeAmount: surchargeAmount, + totalAmount: totalAmount, + rate: rate, + surchargeStatus: status, + action: action + }; + + console.log( + "putSurchargeUsecase surchargeAmount and totalAmount:", + updatedSurcharge + ); + + await PutSurchargeRepository(updatedSurcharge); + return updatedSurcharge; +} \ No newline at end of file diff --git a/functions/src/index.ts b/functions/src/index.ts index be89366..50d4c41 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -2,8 +2,9 @@ require('module-alias/register') import express from "express"; import { onRequest } from "firebase-functions/v2/https"; -import { getPlaceInterface, getPlacesInterface } from "@interface/place"; -import { getSurchargeInterface, postSurchargeInterface, getSurchargesInterface } from "@interface/surcharge"; +import { getPlaceInterface, getPlacesInterface, getPlacesWithSurchargesInterface } from "@interface/place"; +import { getSurchargeInterface, postSurchargeInterface, getSurchargesInterface, putSurchargeInterface } from "@interface/surcharge"; +import { getImageInterface } from "@interface/image"; import { AdminAuth } from "@shared/authentication"; import { MobileAuth } from "@shared/authentication"; import { WrappingResponse } from "@shared/middleware"; @@ -33,7 +34,9 @@ const admin = express() admin.use(cors(corsOptions)) admin.use(AdminAuth) admin.get("/surcharges", getSurchargesInterface) -//admin.put("/surcharge", putSurchargeInterface) +admin.put("/surcharge", putSurchargeInterface) +admin.get("/image", getImageInterface) +admin.get("/places", getPlacesWithSurchargesInterface); exports.admin = onRequest(admin) // For Mobile APIs diff --git a/functions/src/interface/image/get/image/getImageInterface.ts b/functions/src/interface/image/get/image/getImageInterface.ts new file mode 100644 index 0000000..62cddd9 --- /dev/null +++ b/functions/src/interface/image/get/image/getImageInterface.ts @@ -0,0 +1,24 @@ +import express from "express"; +import { getImageUsecase } from "@domain/image"; +import { Response } from "./model/GetImageInterfaceResponse"; + +export const getImageInterface = async (request: express.Request, response: Response) => { + const image = (request.query.image as string) || undefined; + + if (!image) { + response.status(400).send({ message: "Missing image name" }); + return; + } + + try { + const result = await getImageUsecase({ image: image }); + // console.log("getImageInterface result: ", result.image) + + response.status(200).send({ + image: result.image, + }); + } catch (error) { + console.error("Error fetching image data:", error); + response.status(500).send({ message: "Internal server error" }); + } +}; diff --git a/functions/src/interface/image/get/image/model/GetImageInterfaceResponse.ts b/functions/src/interface/image/get/image/model/GetImageInterfaceResponse.ts new file mode 100644 index 0000000..d4565e8 --- /dev/null +++ b/functions/src/interface/image/get/image/model/GetImageInterfaceResponse.ts @@ -0,0 +1,10 @@ +import express from "express" + +export interface GetPlaceInterfaceResponse { + image: string +} + +export interface Response extends express.Response { + status(status: number): any + send(data: GetPlaceInterfaceResponse): any +} \ No newline at end of file diff --git a/functions/src/interface/image/index.ts b/functions/src/interface/image/index.ts new file mode 100644 index 0000000..63c2d36 --- /dev/null +++ b/functions/src/interface/image/index.ts @@ -0,0 +1 @@ +export { getImageInterface } from "./get/image/getImageInterface" \ No newline at end of file diff --git a/functions/src/interface/place/get/places/getPlacesInterface.ts b/functions/src/interface/place/get/places/getPlacesInterface.ts index 5700e72..d57182e 100644 --- a/functions/src/interface/place/get/places/getPlacesInterface.ts +++ b/functions/src/interface/place/get/places/getPlacesInterface.ts @@ -1,5 +1,5 @@ import express from "express" -import { getPlacesUsecase } from "@domain/place" +import { GetPlacesUsecase } from "@domain/place" import { Response } from "./model/GetPlacesInterfaceResponse" export const getPlacesInterface = async (request: express.Request, response: Response) => { @@ -22,7 +22,7 @@ export const getPlacesInterface = async (request: express.Request, response: Res } try { - const places = await getPlacesUsecase({ searchText, nextPageToken, userLocation: userLocation() }) + const places = await GetPlacesUsecase({ searchText, nextPageToken, userLocation: userLocation() }) response.status(200).send({ places: places.places.map((place) => { @@ -52,12 +52,15 @@ export const getPlacesInterface = async (request: express.Request, response: Res }) } catch (error: unknown) { + if (error instanceof Error) { if (error.message === "User location is out of New Zealand") { response.status(403).send({ message: error.message }) return } } - response.status(500).send({ message: error }) + + response.status(404).send() + } } \ No newline at end of file diff --git a/functions/src/interface/place/get/places/getPlacesWithSurchargesInterface.ts b/functions/src/interface/place/get/places/getPlacesWithSurchargesInterface.ts new file mode 100644 index 0000000..b6d83f6 --- /dev/null +++ b/functions/src/interface/place/get/places/getPlacesWithSurchargesInterface.ts @@ -0,0 +1,44 @@ +import express from "express" +import { GetPlacesUsecase } from "@domain/place" +import { Response } from "./model/GetPlacesInterfaceResponse" + +export const getPlacesWithSurchargesInterface = async (request: express.Request, response: Response) => { + + try { + const places = await GetPlacesUsecase([]) + + response.status(200).send({ + places: places.places.map((place) => { + return { + id: place.id, + displayName: { + text: place.displayName.text, + languageCode: place.displayName.languageCode + }, + addressComponents: place.addressComponents.map((component) => { + return { + longText: component.longText, + shortText: component.shortText, + types: component.types, + languageCode: component.languageCode + } + }), + location: place.location ? { + latitude: place.location.latitude, + longitude: place.location.longitude + } : undefined, + image: place.image, + surchargeStatus: place.surchargeStatus, + totalAmount: place.totalAmount, + surchargeAmount: place.surchargeAmount, + reportedDate: place.reportedDate, + rate: place.rate + } + }), + nextPageToken: places.nextPageToken + }) + + } catch (error: unknown) { + response.status(500).send({ message: error }) + } +} \ No newline at end of file diff --git a/functions/src/interface/place/index.ts b/functions/src/interface/place/index.ts index 2ab68b5..f004a87 100644 --- a/functions/src/interface/place/index.ts +++ b/functions/src/interface/place/index.ts @@ -1,2 +1,3 @@ export { getPlaceInterface } from "./get/place/getPlaceInterface" -export { getPlacesInterface } from "./get/places/getPlacesInterface" \ No newline at end of file +export { getPlacesInterface } from "./get/places/getPlacesInterface" +export { getPlacesWithSurchargesInterface } from "./get/places/getPlacesWithSurchargesInterface" \ No newline at end of file diff --git a/functions/src/interface/surcharge/get/getSurchargesInterface.ts b/functions/src/interface/surcharge/get/getSurchargesInterface.ts index 3b34d76..88fde73 100644 --- a/functions/src/interface/surcharge/get/getSurchargesInterface.ts +++ b/functions/src/interface/surcharge/get/getSurchargesInterface.ts @@ -1,4 +1,4 @@ -import { getSurchargesUsecase } from "@domain/surcharge"; +import { getSurchargesUsecase } from "@domain/surcharge" import { Response, Request } from "express"; export const getSurchargesInterface = async (req: Request, res: Response) => { @@ -6,6 +6,8 @@ export const getSurchargesInterface = async (req: Request, res: Response) => { const surcharges = await getSurchargesUsecase(); res.status(200).send( surcharges.map((surcharge) => ({ + id: surcharge.id, + image: surcharge.image, placeInformation: surcharge.placeInformation, rate: surcharge.rate, reportedDate: surcharge.reportedDate, diff --git a/functions/src/interface/surcharge/index.ts b/functions/src/interface/surcharge/index.ts index 8d67ad6..7ccf6c2 100644 --- a/functions/src/interface/surcharge/index.ts +++ b/functions/src/interface/surcharge/index.ts @@ -1,3 +1,6 @@ export { getSurchargeInterface } from "./get/getSurchargeInterface" -export { getSurchargesInterface } from "./get/getSurchargesInterface" export { postSurchargeInterface } from "./post/postSurchargeInterface" +export { putSurchargeInterface } from "./put/putSurchargeInterface" +export { PostSurchargeInterfaceRequest } from "./post/models/PostSurchargeInterfaceRequest" +export { PutSurchargeInterfaceRequest } from "./put/models/PutSurchargeInterfaceRequest" +export { getSurchargesInterface } from "./get/getSurchargesInterface" diff --git a/functions/src/interface/surcharge/put/models/PutSurchargeInterfaceRequest.ts b/functions/src/interface/surcharge/put/models/PutSurchargeInterfaceRequest.ts new file mode 100644 index 0000000..be42c16 --- /dev/null +++ b/functions/src/interface/surcharge/put/models/PutSurchargeInterfaceRequest.ts @@ -0,0 +1,6 @@ +export type PutSurchargeInterfaceRequest = { + id: string, + surchargeAmount? : number, + totalAmount? : number, + action: string +} \ No newline at end of file diff --git a/functions/src/interface/surcharge/put/putSurchargeInterface.ts b/functions/src/interface/surcharge/put/putSurchargeInterface.ts new file mode 100644 index 0000000..b01b520 --- /dev/null +++ b/functions/src/interface/surcharge/put/putSurchargeInterface.ts @@ -0,0 +1,20 @@ +import { PutSurchargeInterfaceRequest } from "@interface/surcharge" +import { Request, Response } from "express"; +import { putSurchargeUsecase } from "@domain/surcharge" + +export const putSurchargeInterface = async (req: Request, res: Response): Promise => { + try { + let { id, surchargeAmount, totalAmount, action } = req.body; + const surcharge: PutSurchargeInterfaceRequest = { + id: id, + surchargeAmount: surchargeAmount, + totalAmount: totalAmount, + action: action, + }; + await putSurchargeUsecase(surcharge); + res.status(200).send({ message: "Surcharge successfully confirmed." }); + } catch (error) { + console.error("Error in putSurchargeInterface:", error); + res.status(500).send({ message: "An error occurred while verifying the surcharge." }); + } +}; diff --git a/functions/src/shared/authentication/AdminAuth.ts b/functions/src/shared/authentication/AdminAuth.ts index 6c5570a..58b7333 100644 --- a/functions/src/shared/authentication/AdminAuth.ts +++ b/functions/src/shared/authentication/AdminAuth.ts @@ -8,13 +8,20 @@ export const AdminAuth = async ( next: NextFunction ) => { - const idToken = request.headers.authorization + const authorization = request.headers.authorization - if (!idToken) { - response.status(400).send({ message: 'Bad request' }) + if (!authorization) { + response.status(401).send() return } + const [scheme, idToken] = authorization.split(' ') + + if (scheme !== 'Bearer') { + response.status(401).send() + return + } + try { await admin.auth().verifyIdToken(idToken) next() diff --git a/functions/src/shared/constants/LocationRestrictions.ts b/functions/src/shared/constants/LocationRestrictions.ts new file mode 100644 index 0000000..96f5e29 --- /dev/null +++ b/functions/src/shared/constants/LocationRestrictions.ts @@ -0,0 +1,12 @@ +export const locationRestrictionOfNZ = { + rectangle: { + low: { + latitude: -47.0, + longitude: 166.0, + }, + high: { + latitude: -34.0, + longitude: 178.0, + }, + } +} \ No newline at end of file diff --git a/functions/src/shared/constants/index.ts b/functions/src/shared/constants/index.ts new file mode 100644 index 0000000..b54577a --- /dev/null +++ b/functions/src/shared/constants/index.ts @@ -0,0 +1 @@ +export { locationRestrictionOfNZ } from "./LocationRestrictions" \ No newline at end of file diff --git a/functions/src/shared/types/place/Place.ts b/functions/src/shared/types/place/Place.ts index 544f274..4c3599d 100644 --- a/functions/src/shared/types/place/Place.ts +++ b/functions/src/shared/types/place/Place.ts @@ -6,5 +6,5 @@ export type Place = { id: string, displayName: LocalizedText, addressComponents: AddressComponents[], - location?: LatLng + location?: LatLng | null } \ No newline at end of file diff --git a/functions/src/shared/types/surcharge/SurchargeStatus.ts b/functions/src/shared/types/surcharge/SurchargeStatus.ts index d23552f..ee5b728 100644 --- a/functions/src/shared/types/surcharge/SurchargeStatus.ts +++ b/functions/src/shared/types/surcharge/SurchargeStatus.ts @@ -1,5 +1,7 @@ export enum SurchargeStatus { REPORTED = 'REPORTED', CONFIRMED = 'CONFIRMED', - UNKNOWN = 'UNKNOWN' + UNKNOWN = 'UNKNOWN', + AUTO_GENERATED = 'AUTO_GENERATED', + REJECTED = 'REJECTED' } \ No newline at end of file