# Toozy Rest
:::success
Last update: 15 Februari 2020
:::
###### using: `nodejs` `koa` `jwt` `sequelize` `postgresql`
## Table of Content
[ToC]
## :memo: Todo
### Step 1: Fix and documentation database schema
- [ ] Fix database :rocket:
- [ ] Documentation it
### Step 2: Create Module
#### **System**
:::info
:bulb: Must have `.core.js` `.presenter.js` `.validation.js` `.routes.js` `.storage.js` `index.js` and optional can using `.constant.js` for text or whatever when can dynamic changed.
:::
- [ ] article
- [x] auth
- [x] Login
- [x] Register
- [x] RegisterVerification
- [x] RegisterRequestVerification
- [x] ForgotPassword
- [x] CheckForgotPassword
- [x] VerifyForgotPassword
- [ ] banner
- [ ] menu
- [ ] notification
- [ ] payment
- [ ] restaurant
- [x] role
- [x] Create
- [x] GetById
- [x] GetList
- [x] DeleteById
- [x] UpdateById
- [ ] table
- [ ] upload
- [ ] user
- [ ] verification
- [ ] voucher
#### **Lib**
:::info
:bulb: Must stand alone or only single initializing using `attach()` and all function is accessable directly.
:::
- [ ] docean (digitalocean)
- [ ] mailgun
- [ ] redis
- [ ] sendgrid
- [ ] socket.io
- [ ] transalation
- [ ] error.js
- [ ] jwt.js
- [ ] logger.js
- [ ] roles.js
## :memo: Database
### users
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` | :x: | :x: |
| email | `STRING` `NOTNULL` | :x: | :x: |
| telephone | `STRING` `NULL` | :x: | :x: |
| password | `STRING` `NOTNULL` | :x: | :x: |
| roleId | `UUID` `NOTNULL` | `roles` `id` | :heavy_check_mark: |
| vouchers | `UUID` `[]` | `vouchers` `id` | :heavy_check_mark: |
| status | `STRING` `REGISTERED` | :x: | :x: |
| avatar | `TEXT` `NOTNULL` | :x: | :x: |
### restaurants
| Name | Type | Reference | PK / FK |
| ----------- | ----------------------------------------------------------------------- | --------------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` `UNIQUE` | :x: | :x: |
| address | `STRING` `NOTNULL` | :x: | :x: |
| status | `BOOLEAN` `FALSE` | :x: | :x: |
| image | `ARRAY(STRING)` `NOTNULL` | :x: | :x: |
| tag | `ARRAY(UUID)` `NOTNULL` | `restaurantTags` `id` | :heavy_check_mark: |
| location | `JSONB` `NOTNULL` `{ longitude: number, latitude: number }` | :x: | :x: |
| operational | `JSONB` `NOTNULL` `Array({ day: string, open: string, close: string })` | :x: | :x: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
| point | `GEOMETRY` `NOTNULL` `POINT` | :x: | :x: |
### restaurantTags
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` `UNIQUE` | :x: | :x: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
### articles
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| title | `STRING` `NOTNULL` | :x: | :x: |
| description | `TEXT` `NOTNULL` | :x: | :x: |
| content | `STRING` `NOTNULL` | :x: | :x: |
| tags | `ARRAY(STRING)` `NOTNULL` | :x: | :x: |
| image | `STRING` `NOTNULL` | :x: | :x: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
### banners
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` | :x: | :x: |
| image | `STRING` `NOTNULL` | :x: | :x: |
| type | `UUID` `NOTNULL` | `bannerTypes` `id` | :heavy_check_mark: |
| tag | `ARRAY(UUID)` `NOTNULL` | `bannerTags` `id` | :heavy_check_mark: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
| value | `UUID` `NOTNULL` | :x: | :x: |
### bannerTags
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` `UNIQUE` | :x: | :x: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
### bannerTypes
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` `UNIQUE` | :x: | :x: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
### menu
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` | :x: | :x: |
| image | `STRING` `NOTNULL` | :x: | :x: |
| type | `STRING` `NOTNULL` | :x: | :x: |
| restoId | `UUID` `NOTNULL` | `restaurants` `id` | :heavy_check_mark: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
| status | `STRING` `NOTNULL` | :x: | :x: |
| price | `INTEGER` `NOTNULL` | :x: | :x: |
### menuTags
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` | :x: | :x: |
| restoId | `UUID` `NOTNULL` | `restaurants` `id` | :heavy_check_mark: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
| menuId | `ARRAY(UUID)` `NOTNULL` | `menu` `id` | :heavy_check_mark: |
| priority | `SMALLINT` `NOTNULL` `0` | :x: | :x: |
### payments
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| amount | `STRING` `NOTNULL` | :x: | :x: |
| discountCode | `STRING` `NULL` | :x: | :x: |
| total | `STRING` `NOTNULL` | :x: | :x: |
| method | `STRING` `NOTNULL` | :x: | :x: |
| createdTo | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
| status | `STRING` `NOTNULL` | :x: | :x: |
| product | `JSONB` `NULL` `ARRAY({ id: uuid, name: string, image: string, qty: number, price: string, type: string, note: string })` | :x: | :x: |
| data | `JSONB` `NULL` `{ name: string, uuid: uuid, type: string, tableId: uuid }` | :x: | :x: |
### roles
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` | :x: | :x: |
| roles | `ARRAY(STRING)` `NOTNULL` | :x: | :x: |
| slug | `STRING` `NOTNULL` | :x: | :x: |
### tables
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| code | `STRING` `NOTNULL` | :x: | :x: |
| restoId | `UUID` `NOTNULL` | `restaurants` `id` | :heavy_check_mark: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
### verifications
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| code | `STRING` `NOTNULL` | :x: | :x: |
| expiration | `SMALLINT` `NOTNULL` | :x: | :x: |
| type | `SMALLINT` `NOTNULL` | :x: | :x: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
### vouchers
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` | :x: | :x: |
| description | `STRING` `NOTNULL` | :x: | :x: |
| image | `STRING` `NOTNULL` | :x: | :x: |
| code | `STRING` `NOTNULL` `UNIQUE` | :x: | :x: |
| value | `INTEGER` `NOTNULL` | :x: | :x: |
| maxRedeem | `INTEGER` `NOTNULL` | :x: | :x: |
| maxValue | `INTEGER` `NULL` | :x: | :x: |
| status | `BOOLEAN` `NOTNULL` `TRUE` | :x: | :x: |
| type | `STRING` `NOTNULL` | :x: | :x: |
| tag | `ARRAY(UUID)` `NOTNULL` | `voucherTags` `id` | :heavy_check_mark: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
| validAt | `DATE` `NOTNULL` | :x: | :x: |
| expireAt | `DATE` `NOTNULL` | :x: | :x: |
| termsCondition | `ARRAY(STRING)` `NOTNULL` | :x: | :x: |
| queryCondition | `ARRAY(STRING)` `NOTNULL` `ARRAY({ value1: string, value2: string, condition: string, type: string })` | :x: | :x: |
### voucherTags
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` | :x: | :x: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
### waiters
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| name | `STRING` `NOTNULL` | :x: | :x: |
| restoId | `UUID` `NOTNULL` | `restaurants` `id` | :heavy_check_mark: |
| createdBy | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
### notifications
| Name | Type | Reference | PK / FK |
| --------- | --------------------- | --------------- | ------------------ |
| id | `UUID` | :x: | :heavy_check_mark: |
| userId | `UUID` `NOTNULL` | `users` `id` | :heavy_check_mark: |
| type | `SMALLINT` `NOTNULL` | :x: | :x: |
| data | `JSONB` `NOTNULL` `Object` | :x: | :x: |
## :memo: Flow
### Login
:::info
`Login` will check status is `ACTIVE`, if status `REGISTERED` will send new otp to user email.
:::
### Register
:::info
`Register` will create user with status `REGISTERED`, user must be verify email with `RegisterVerification`
:::
### Forgot Password
:::info
`ForgotPassword` will send verification by email, `CheckForgotPassword` use for check otp, `VerifyForgotPassword` use for check otp and change password
:::
## :memo: Changelog
| Date | Description | Version |
| ---------------- | ------------ | ------- |
| 15 Februari 2020 | add database | - |
| 17 Februari 2020 | - | - |