feat: Fixes merge conflicts
This commit is contained in:
@@ -47,6 +47,7 @@ jobs:
|
||||
type=ref,event=branch
|
||||
type=semver,pattern={{version}}
|
||||
type=sha
|
||||
type=raw,value=prod
|
||||
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If
|
||||
# the build succeeds, it pushes the image to GitHub Packages. It uses the `context` parameter to define the build's context
|
||||
# as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)"
|
||||
|
||||
67
README.md
Normal file
67
README.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# vapor-po
|
||||
|
||||
The website for generating purchase orders.
|
||||
|
||||
## Usage
|
||||
|
||||
Generally the app should be ran through a docker container or docker-compose file. Examples are in
|
||||
the `./docker` folder.
|
||||
|
||||
Images get built in the `CI` environment when a tag is pushed to the repository.
|
||||
|
||||
### Getting Started
|
||||
|
||||
When the application is first launched an admin user should be created in the running container.
|
||||
Attach to the container using `docker exec` or `docker compose exec`, then run:
|
||||
|
||||
```
|
||||
./App generate-admin --username "admin" --password "super-secret --confirmPassword "super-secret"
|
||||
```
|
||||
|
||||
You can then login and generate user, employees, vendors, etc.
|
||||
|
||||
After the setup has been completed, then you should generate a mock purchase order and set the `id`
|
||||
to the value you would like new purchase orders to start from. This should be done through calling
|
||||
the api, as the web interface does not allow users to enter an id value.
|
||||
|
||||
#### Example
|
||||
|
||||
These examples use `httpie`, note the port is used for local development, in a production
|
||||
environment you would just use the FQDN of where the application is running.
|
||||
|
||||
**Login**
|
||||
|
||||
```
|
||||
http :8080/api/v1/login username="admin" password="super-secret" \
|
||||
| jq '.["token"]' \
|
||||
| pbcopy
|
||||
```
|
||||
|
||||
**Set the token as environment variable**
|
||||
|
||||
```
|
||||
export API_TOKEN=<clipboard contents>
|
||||
```
|
||||
|
||||
**Get the employees to copy an id to use for the purchase order**
|
||||
|
||||
```
|
||||
http -A bearer -a "$API_TOKEN" :8080/api/v1/employees
|
||||
```
|
||||
|
||||
**Get the vendor branches to copy an id to use for the purchase order**
|
||||
|
||||
```
|
||||
http -A bearer -a "$API_TOKEN" :8080/api/v1/vendors/branches
|
||||
```
|
||||
|
||||
**Generate first po**
|
||||
|
||||
```
|
||||
http -A bearer -a "$API_TOKEN" :8080/api/v1/purchase-orders \
|
||||
id:="60000" \
|
||||
materials="Test" \
|
||||
customer="Testy McTestface" \
|
||||
createdForID="<employee-id>"
|
||||
vendorBranchID="<vendor-branch-id>"
|
||||
```
|
||||
@@ -1,6 +1,9 @@
|
||||
import Dependencies
|
||||
import Foundation
|
||||
|
||||
/// Represents an employee database model.
|
||||
///
|
||||
/// Employee's are who purchase orders can be generated for.
|
||||
public struct Employee: Codable, Equatable, Identifiable, Sendable {
|
||||
public var id: UUID
|
||||
public var active: Bool
|
||||
@@ -31,6 +34,8 @@ public struct Employee: Codable, Equatable, Identifiable, Sendable {
|
||||
}
|
||||
|
||||
public extension Employee {
|
||||
/// Represents the required fields for generating a new employee in the
|
||||
/// database.
|
||||
struct Create: Codable, Sendable, Equatable {
|
||||
public let firstName: String
|
||||
public let lastName: String
|
||||
@@ -47,6 +52,8 @@ public extension Employee {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the required fields for updating an existing employee in the
|
||||
/// database.
|
||||
struct Update: Codable, Sendable, Equatable {
|
||||
public let firstName: String?
|
||||
public let lastName: String?
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import Dependencies
|
||||
import Foundation
|
||||
|
||||
/// Represents a purchase order database model.
|
||||
///
|
||||
/// A purchase order is generated on behalf of an `Employee` and issued to
|
||||
/// a `VendorBranch`. It includes information about the customer / job it was created
|
||||
/// for, the materials that were purchased, etc.
|
||||
public struct PurchaseOrder: Codable, Equatable, Identifiable, Sendable {
|
||||
|
||||
public let id: Int
|
||||
@@ -41,6 +46,7 @@ public struct PurchaseOrder: Codable, Equatable, Identifiable, Sendable {
|
||||
|
||||
public extension PurchaseOrder {
|
||||
|
||||
/// Represents the required fields for generating a new purchase order in the database.
|
||||
struct Create: Codable, Sendable, Equatable {
|
||||
|
||||
public let id: Int?
|
||||
@@ -73,6 +79,9 @@ public extension PurchaseOrder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the required fields for generating a new purchase order in the database,
|
||||
/// without the user information who is issuing the request, which get's parsed from the
|
||||
/// currently authenticated user's session and is used to generate the full `Create` request.
|
||||
struct CreateIntermediate: Codable, Sendable, Equatable {
|
||||
|
||||
public let id: Int?
|
||||
@@ -115,6 +124,8 @@ public extension PurchaseOrder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the context to search or filter purchase orders based on the
|
||||
/// given parameters.
|
||||
enum SearchContext: Sendable, Equatable {
|
||||
case customer(String)
|
||||
case vendor(VendorBranch.ID)
|
||||
|
||||
@@ -4,6 +4,9 @@ import Foundation
|
||||
|
||||
public extension SiteRoute {
|
||||
|
||||
/// Represents api routes that can be interacted with.
|
||||
///
|
||||
/// These routes return json information, as opposed to html like the view routes.
|
||||
enum Api: Sendable, Equatable {
|
||||
|
||||
case employee(EmployeeRoute)
|
||||
|
||||
@@ -2,6 +2,7 @@ import CasePathsCore
|
||||
import Foundation
|
||||
@preconcurrency import URLRouting
|
||||
|
||||
/// Represents all the routes that our server can handle.
|
||||
public enum SiteRoute: Sendable {
|
||||
case api(SiteRoute.Api)
|
||||
case health
|
||||
|
||||
@@ -4,6 +4,10 @@ import Foundation
|
||||
|
||||
public extension SiteRoute {
|
||||
// swiftlint:disable type_body_length
|
||||
|
||||
/// Represents view routes that can be interacted with.
|
||||
///
|
||||
/// These routes return html and are used to generate the web interface.
|
||||
enum View: Sendable, Equatable {
|
||||
|
||||
case employee(SiteRoute.View.EmployeeRoute)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import Dependencies
|
||||
import Foundation
|
||||
|
||||
/// Represents a user database model.
|
||||
///
|
||||
/// User's are who can login to the system and generate purchase orders, manage
|
||||
/// employees, vendors, etc.
|
||||
///
|
||||
public struct User: Codable, Equatable, Identifiable, Sendable {
|
||||
|
||||
public var id: UUID
|
||||
@@ -26,6 +31,7 @@ public struct User: Codable, Equatable, Identifiable, Sendable {
|
||||
|
||||
public extension User {
|
||||
|
||||
/// Represents the fields needed to generate a new user in the database.
|
||||
struct Create: Codable, Sendable, Equatable {
|
||||
public let username: String
|
||||
public let email: String
|
||||
@@ -45,6 +51,7 @@ public extension User {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the fields needed for new user to login.
|
||||
struct Login: Codable, Sendable, Equatable {
|
||||
public let username: String?
|
||||
public let email: String?
|
||||
@@ -61,6 +68,7 @@ public extension User {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the fields needed to reset the password of a user.
|
||||
struct ResetPassword: Codable, Equatable, Sendable {
|
||||
public let password: String
|
||||
public let confirmPassword: String
|
||||
@@ -74,6 +82,8 @@ public extension User {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a user token that can be used to authenticate a user, typically
|
||||
/// used for interacting with api routes remotely.
|
||||
struct Token: Codable, Equatable, Identifiable, Sendable {
|
||||
public let id: UUID
|
||||
public let userID: User.ID
|
||||
@@ -90,6 +100,7 @@ public extension User {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the fields needed to update a user's attributes in the database.
|
||||
struct Update: Codable, Equatable, Sendable {
|
||||
public let username: String?
|
||||
public let email: String?
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import Dependencies
|
||||
import Foundation
|
||||
|
||||
/// Represents a vendor item in the database.
|
||||
///
|
||||
/// A vendor is parent item that contains one or more branches where purchase orders
|
||||
/// can be issued to. It is primarily a name space to group related branches together.
|
||||
public struct Vendor: Codable, Equatable, Identifiable, Sendable {
|
||||
public var id: UUID
|
||||
public var name: String
|
||||
@@ -25,6 +29,7 @@ public struct Vendor: Codable, Equatable, Identifiable, Sendable {
|
||||
|
||||
public extension Vendor {
|
||||
|
||||
/// Represents the fields required to generate a new vendor in the database.
|
||||
struct Create: Codable, Sendable, Equatable {
|
||||
public let name: String
|
||||
|
||||
@@ -33,6 +38,7 @@ public extension Vendor {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the fields required to update a vendor in the database.
|
||||
struct Update: Codable, Sendable, Equatable {
|
||||
public let name: String
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import Dependencies
|
||||
import Foundation
|
||||
|
||||
/// Represents a vendor branch database model.
|
||||
///
|
||||
/// A vendor branch is who purchase orders can be issued to on behalf an `Employee`.
|
||||
/// They are associated with a particular `Vendor`.
|
||||
public struct VendorBranch: Codable, Equatable, Identifiable, Sendable {
|
||||
public var id: UUID
|
||||
public var name: String
|
||||
@@ -24,6 +28,8 @@ public struct VendorBranch: Codable, Equatable, Identifiable, Sendable {
|
||||
}
|
||||
|
||||
public extension VendorBranch {
|
||||
|
||||
/// Represents the fields required to generate a new vendor branch in the database.
|
||||
struct Create: Codable, Sendable, Equatable {
|
||||
public let name: String
|
||||
public let vendorID: Vendor.ID
|
||||
@@ -34,6 +40,10 @@ public extension VendorBranch {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the details of a vendor branch, which includes the parent vendor item.
|
||||
///
|
||||
/// This is used in several of the views / api routes that require information about both the
|
||||
/// vendor branch and it's associated parent vendor item.
|
||||
struct Detail: Codable, Equatable, Identifiable, Sendable {
|
||||
public var id: UUID
|
||||
public var name: String
|
||||
@@ -56,6 +66,7 @@ public extension VendorBranch {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the fields that are used to update attributes of a vendor branch in the database.
|
||||
struct Update: Codable, Sendable, Equatable {
|
||||
public let name: String?
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@ services:
|
||||
app:
|
||||
image: hhe-po:latest
|
||||
build:
|
||||
context: .
|
||||
context: ..
|
||||
dockerfile: ./docker/Dockerfile
|
||||
environment:
|
||||
<<: *shared_environment
|
||||
volumes:
|
||||
@@ -30,12 +31,20 @@ services:
|
||||
- '8080:8080'
|
||||
labels:
|
||||
- dev.orbstack.domains=po.local
|
||||
healthcheck:
|
||||
test: curl --fail -s http://0.0.0.0:8080/health || exit 1
|
||||
interval: 1m30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
deploy:
|
||||
replicas: 3
|
||||
# user: '0' # uncomment to run as root for testing purposes even though Dockerfile defines 'vapor' user.
|
||||
command: ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]
|
||||
migrate:
|
||||
image: hhe-po:latest
|
||||
build:
|
||||
context: .
|
||||
context: ..
|
||||
dockerfile: ./docker/Dockerfile
|
||||
environment:
|
||||
<<: *shared_environment
|
||||
command: ["migrate", "--yes"]
|
||||
@@ -46,7 +55,8 @@ services:
|
||||
revert:
|
||||
image: hhe-po:latest
|
||||
build:
|
||||
context: .
|
||||
context: ..
|
||||
dockerfile: ./docker/Dockerfile
|
||||
environment:
|
||||
<<: *shared_environment
|
||||
command: ["migrate", "--revert", "--yes"]
|
||||
|
||||
Reference in New Issue
Block a user