Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 20 additions & 7 deletions docs/STORAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ Notes: This meets the requirement (2)
Parent level: `facilityId` (dynamic)
Level: `spaceId` (dynamic)

Key: `metadata_generic`
Key: `metadata`
Value: `videre.stays.lpms.facility.Item`
Description: Contains generic data for each item (name, photos etc)

Key: `metadata`
Key: `metadata_impl`
Value: `videre.stays.lpms.facility.Space`
Description: Contains specific metadata for Spaces (views, sleeping arrangements etc).

Expand Down Expand Up @@ -185,12 +185,25 @@ Notes: This meets the requirement (4)
#### otherItems

Parent level: `facilityId` (dynamic)
Level: `otherItems`
Level: `otherItemdId` (dynamic)

Key: `itemId` (dynamic)
Key: `metadata` (dynamic)
Value: `videre.stays.lpms.facility.Item`
Description: Contains generic data for the item (name, photos, etc)

##### rates

Parent level: `facilityId.otherItemdId` (dynamic)
Level: `rates`

Key: `default`
Value: `videre.stays.lpms.Rates`
Description: Contains the `Rates` message protobuf describing the rate for this item.

Key: `YYYY-MM-DD` (dynamic)
Value: `videre.stays.lpms.Rates`
Description: Contains the `Rates` message protobuf for a per-day override of rates.

# CRUD

## Stubs (booking)
Expand Down Expand Up @@ -251,8 +264,8 @@ let items: ServiceItemData[];
const spaces = db.get('facilityId.spaces'); // insert correct leveldb query here
for (const space of object) {
// get generic metadata
const generic = db.get(`${facilityId}.${space}.metadata_generic`) as Item;
const specific = db.get(`${facilityId}.${space}.metadata`) as Space;
const generic = db.get(`${facilityId}.${space}.metadata`) as Item;
const specific = db.get(`${facilityId}.${space}.metadata_impl`) as Space;
generic.payload = Space.toBinary(specific);

items.push({
Expand All @@ -264,7 +277,7 @@ for (const space of object) {
// process all other items
const otherItems = db.get('facilityId.otherItems') as Item[];
for (const item of otherItems) {
const otherItem = db.get(`${facilityId}.otherItems.${item}`) as Item;
const otherItem = db.get(`${facilityId}.${item}.metadata`) as Item;
items.push({
item: utils.arrayify(utils.formatBytes32String(item)),
payload: Item.toBinary(otherItem)
Expand Down
11 changes: 5 additions & 6 deletions src/controllers/FacilityController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class FacilityController {
const { facilityId, spaceId, date } = req.params;

const repository = new SpaceAvailabilityRepository(facilityId, spaceId);
const numSpaces = await repository.getSpaceAvailabilityNumSpaces(
const numSpaces = await repository.getSpaceAvailability(
date as FormattedDate
);

Expand All @@ -40,10 +40,9 @@ export class FacilityController {
}

const repository = new SpaceAvailabilityRepository(facilityId, spaceId);
await repository.createAvailabilityByDate(
date as FormattedDate,
Number(numSpaces)
);
await repository.setAvailabilityByDate(date as FormattedDate, {
numSpaces: Number(numSpaces)
});

return res.json({ success: true });
} catch (e) {
Expand All @@ -62,7 +61,7 @@ export class FacilityController {
const { numSpaces } = req.body;

const repository = new SpaceAvailabilityRepository(facilityId, spaceId);
await repository.createDefaultAvailability(Number(numSpaces));
await repository.setAvailabilityDefault({ numSpaces: Number(numSpaces) });

return res.json({ success: true });
} catch (e) {
Expand Down
9 changes: 6 additions & 3 deletions src/controllers/StorageController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,14 @@ export class StorageController {

if (type === ItemType.SPACE) {
spaces[itemId] = [
['metadata_generic', generic as Item],
['metadata', (payload ? Space.fromBinary(payload) : {}) as Space]
['metadata', generic as Item],
[
'metadata_impl',
(payload ? Space.fromBinary(payload) : {}) as Space
]
];
} else {
otherItems[itemId] = [['metadata_generic', generic as Item]];
otherItems[itemId] = [['metadata', generic as Item]];
}
}

Expand Down
42 changes: 17 additions & 25 deletions src/repositories/SpaceAvailabilityRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Availability } from '../proto/lpms';

export class SpaceAvailabilityRepository {
private dbService: DBService;
private availableDB: AbstractSublevel<
private db: AbstractSublevel<
AbstractLevel<LevelDefaultTyping, string, FacilityItemValues>,
LevelDefaultTyping,
DefaultOrDateItemKey,
Expand All @@ -18,45 +18,37 @@ export class SpaceAvailabilityRepository {

constructor(facilityId: string, spaceId: string) {
this.dbService = DBService.getInstance();
this.availableDB = this.dbService.getSpaceAvailabilityDB(
facilityId,
spaceId
);
this.db = this.dbService.getSpaceAvailabilityDB(facilityId, spaceId);
}

public async getSpaceAvailabilityNumSpaces(
// --- availability getters / setters

public async getSpaceAvailability(
key: DefaultOrDateItemKey
): Promise<number> {
): Promise<Availability> {
try {
const availability: Availability = await this.availableDB.get(key);
return availability.numSpaces;
return await this.db.get(key);
} catch (e) {
if (e.status !== 404) {
throw e;
}
}

return 0;
}

public async createDefaultAvailability(numSpaces: number): Promise<void> {
const availability: Availability = {
numSpaces
return {
numSpaces: 0
};
}

await this.availableDB.put('default', availability);
public async setAvailabilityDefault(
availability: Availability
): Promise<void> {
await this.db.put('default', availability);
}

public async createAvailabilityByDate(
public async setAvailabilityByDate(
key: FormattedDate,
numSpaces = 1
availability: Availability
): Promise<void> {
const count = await this.getSpaceAvailabilityNumSpaces(key);

const availability: Availability = {
numSpaces: count + numSpaces
};

await this.availableDB.put(key, availability);
await this.db.put(key, availability);
}
}
4 changes: 2 additions & 2 deletions src/repositories/TokenRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ export class TokenRepository {
}
}

public async putUserTokens(
public async setUserTokens(
userId: string,
verifiedTokens: string[]
): Promise<void> {
await this.db.put(userId, verifiedTokens);
}

public async deleteUserTokens(userId: string): Promise<void> {
public async delUserTokens(userId: string): Promise<void> {
await this.db.del(String(userId));
}
}
Expand Down
68 changes: 32 additions & 36 deletions src/services/DBService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ export type ModifiersValues =
| DayOfWeekRateModifer
| OccupancyRateModifier
| LOSRateModifier;
export type ModifiersKey =
| 'day_of_week'
| 'occupancy'
| 'length_of_stay'
export type ModifiersKey = 'day_of_week' | 'occupancy' | 'length_of_stay';
export type FacilityValues = FacilityMetadata | string[];
export type FacilitySpaceValues = ItemMetadata | SpaceMetadata;
export type FacilityItemType = 'spaces' | 'otherItems';
Expand Down Expand Up @@ -138,58 +135,57 @@ export default class DBService {
}

public getFacilityModifiersDB(facilityId: string) {
return this.getFacilityDB(facilityId).sublevel<ModifiersKey, ModifiersValues>(
'modifiers',
{ valueEncoding: 'json' }
);
return this.getFacilityDB(facilityId).sublevel<
ModifiersKey,
ModifiersValues
>('modifiers', { valueEncoding: 'json' });
}

public getFacilityStubsDB(facilityId: string) {
return this.getFacilityDB(facilityId).sublevel<FacilityStubKey, FacilityStubValues>(
'stubs',
{ valueEncoding: 'json' }
);
return this.getFacilityDB(facilityId).sublevel<
FacilityStubKey,
FacilityStubValues
>('stubs', { valueEncoding: 'json' });
}

public getFacilityPiiDB(facilityId: string) {
return this.getFacilityDB(facilityId).sublevel<string, Person>(
'pii',
{ valueEncoding: 'json' }
);
return this.getFacilityDB(facilityId).sublevel<string, Person>('pii', {
valueEncoding: 'json'
});
}

public getSpaceAvailabilityDB(facilityId: string, itemId: string) {
return this.getFacilityItemDB(facilityId, 'spaces', itemId).sublevel<DefaultOrDateItemKey, Availability>(
'availability',
{ valueEncoding: 'json' }
);
return this.getFacilityItemDB(facilityId, 'spaces', itemId).sublevel<
DefaultOrDateItemKey,
Availability
>('availability', { valueEncoding: 'json' });
}

public getSpaceRatesDB(facilityId: string, spaceId: string) {
return this.getFacilityItemDB(facilityId, 'spaces', spaceId).sublevel<DefaultOrDateItemKey, Rates>(
'rates',
{ valueEncoding: 'json' }
);
return this.getFacilityItemDB(facilityId, 'spaces', spaceId).sublevel<
DefaultOrDateItemKey,
Rates
>('rates', { valueEncoding: 'json' });
}

public getSpaceRulesDB(facilityId: string, spaceId: string) {
return this.getFacilityItemDB(facilityId, 'spaces', spaceId).sublevel<RulesItemKey, Rules>(
'rules',
{ valueEncoding: 'json' }
);
return this.getFacilityItemDB(facilityId, 'spaces', spaceId).sublevel<
RulesItemKey,
Rules
>('rules', { valueEncoding: 'json' });
}

public getSpaceModifiersDB(facilityId: string, spaceId: string) {
return this.getFacilityItemDB(facilityId, 'spaces', spaceId).sublevel<ModifiersKey, ModifiersValues>(
'modifiers',
{ valueEncoding: 'json' }
);
return this.getFacilityItemDB(facilityId, 'spaces', spaceId).sublevel<
ModifiersKey,
ModifiersValues
>('modifiers', { valueEncoding: 'json' });
}

public getSpaceStubsDB(facilityId: string, spaceId: string) {
return this.getFacilityItemDB(facilityId, 'spaces', spaceId).sublevel<SpaceStubKey, SpaceStubValues>(
'stubs',
{ valueEncoding: 'json' }
);
return this.getFacilityItemDB(facilityId, 'spaces', spaceId).sublevel<
SpaceStubKey,
SpaceStubValues
>('stubs', { valueEncoding: 'json' });
}
}
28 changes: 20 additions & 8 deletions src/services/SpaceSearchService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DateTime } from 'luxon';
import { Ask } from 'src/proto/ask';
import { Space } from '../proto/facility';
import { AvailabilityDate } from './DBService';
import { FormattedDate } from './DBService';
import { SpaceAvailabilityRepository } from '../repositories/SpaceAvailabilityRepository';
import facilityRepository from '../repositories/FacilityRepository';

Expand Down Expand Up @@ -115,20 +115,32 @@ export default class SpaceSearchService {
spaceId
);

const defaultAvailable =
await availabilityRepository.getSpaceAvailabilityNumSpaces('default');
const defaultAvailable = await availabilityRepository.getSpaceAvailability(
'default'
);

let from = DateTime.fromObject(checkIn);
const to = DateTime.fromObject(checkOut);

while (from <= to) {
try {
const dailyBooks =
await availabilityRepository.getSpaceAvailabilityNumSpaces(
from.toFormat('yyyy-MM-dd') as AvailabilityDate
);
const dailyBooks = await availabilityRepository.getSpaceAvailability(
from.toFormat('yyyy-MM-dd') as FormattedDate
);

if (defaultAvailable - dailyBooks < spacesRequired) {
throw 'To be implemented';
// In order to determine if there is space availability, a routine would have to:
// Get total number of spaces, with *per-day override* having higher priority than
// default. This will be the 'capacity' - ie. HOW MANY OF THOSE SPACE TYPES ARE
// PRESENT FOR THE POINT OF CONSIDERING IF THEY CAN BE STAYED IN.
// Then get the number of that space type that are booked. This means get the
// facilityId.spaceId.stubs sublevel and get the YYYY-MM-DD-num_booked key
// this would be the number of daily booked.
// if the total number of spaces - booked spaces < spacesRequired, true false
if (
defaultAvailable.numSpaces - dailyBooks.numSpaces <
spacesRequired
) {
return false;
}
} catch (e) {
Expand Down
6 changes: 3 additions & 3 deletions src/services/TokenService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class TokenService {

verifiedTokens.push(refreshToken);

return await this.repository.putUserTokens(String(userId), verifiedTokens);
return await this.repository.setUserTokens(String(userId), verifiedTokens);
}

public getVerifiedUserTokens(tokens: Array<string>): string[] {
Expand All @@ -62,11 +62,11 @@ export class TokenService {
return i !== token;
});

return await this.repository.putUserTokens(String(userId), neededTokens);
return await this.repository.setUserTokens(String(userId), neededTokens);
}

public async revokeAllUserTokens(userId: number) {
return await this.repository.deleteUserTokens(String(userId));
return await this.repository.delUserTokens(String(userId));
}

public validateRefreshToken(refreshToken) {
Expand Down