Invoice management system, microservice architecture.
The services implement Vertical Slice Architecture, YARP reverse proxy, RabbitMq message broker, request-response pattern, minimal api,
PFD file generation, miniIO object storage, integration and unit tests.
👷 Frameworks, Libraries and Technologies
Gateway service: Single entry point to the application.
Identity service: User authentication.
Company service: Manages interactions with companies.
Invoice service: Manages interaction with the invoices.
FileGenerator service: Generates PDF files.
Storage service: Stores invoices in MinIO storage.
🐳 List of docker containers
gateway.api - reverse proxy gateway container.
rabbitmq - message broker container.
minio - object storage for storage service.
storage.api - asp.net app container for storage service.
file-generator.api - asp.net app container for file generator service.
identity.api - asp.net app container for identity service.
identity.api.database - postgresql database container for identity service.
company.api - asp.net app container for company service.
company.api.database - postgresql database container for company service.
invoice.api - asp.net app container for invoice service.
invoice.api.database - postgresql database container for invoice service.
Allows you to run all integration and unit tests.
> dotnet test # donet SKD is required
Build and start Docker images based on the configuration defined in the docker-compose.yml
> make up # docker-compose up --build
Stop and remove containers
> make down # docker-compose down
🖨️ Swagger UI documentation (local access)
Identity service
http://localhost:8000/swagger/index.html
Company service
http://localhost:8001/swagger/index.html
Invoice service
http://localhost:8002/swagger/index.html
Storage service
http://localhost:8080/swagger/index.html
🔧 Implementation features
POST
/auth/register
(allows you to register)
name
type
data type
email
required
string
password
required
string
http code
content-type
response
201
application/json
{"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "email": "string"}
400
application/json
array
409
application/json
string
POST
/auth/login
(allows you to login, issues accessToken and refreshToken)
name
type
data type
email
required
string
password
required
string
http code
content-type
response
200
application/json
{"accessToken": "string", "refreshToken": "string", "refreshTokenExpires": "2024-04-21T17:42:12.146Z", "accessTokenType": "string"}
400
application/json
array
404
application/json
string
POST
/auth/refresh
(allows to refresh access and refresh tokens)
name
type
data type
"refreshToken"
required
string
http code
content-type
response
200
application/json
{"accessToken": "string", "refreshToken": "string", "refreshTokenExpires": "2024-04-21T17:43:47.494Z", "accessTokenType": "string"}
400
application/json
array
401
application/json
string
POST
/auth/logout
(allows to logout and deactivates refresh tokens)
name
type
data type
"refreshToken"
required
string
http code
content-type
response
204
application/json
NoContent
400
application/json
array
401
application/json
string
Functionality that allows to manage and interact with companies
Create new companies (🔒Token required )
POST
/company
(allows to create new companies 🔒️[token required])
name
type
data type
"name"
required
string
"taxNumber"
required
string
"city"
required
string
"street"
required
string
"houseNumber"
required
string
"postalCode"
required
string
http code
content-type
response
201
application/json
{"companyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "taxNumber": "string", "city": "string", "street": "string", "houseNumber": "string", "postalCode": "string"}
400
application/json
array
401
application/json
string
403
application/json
string
Update your companies (🔒Token required )
PUT
/company
(allows to update your companies 🔒️[token required])
name
type
data type
"companyId"
required
uuid
"name"
not required
string
"taxNumber"
not required
string
"city"
not required
string
"street"
not required
string
"houseNumber"
not required
string
"postalCode"
not required
string
http code
content-type
response
200
application/json
{"companyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "taxNumber": "string", "city": "string", "street": "string", "houseNumber": "string", "postalCode": "string"}
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
Delete your companies (🔒Token required )
DELETE
/company/{ id:uuid }
(allows to delete your companies 🔒️[token required])
http code
content-type
response
204
application/json
NoContent
401
application/json
string
403
application/json
string
404
application/json
string
Get all your companies (🔒Token required )
GET
/company
(allows you to get all your companies 🔒️[token required])
name
type
data type
PageNumber
not required
int32
PageSize
not required
int32
http code
content-type
response
200
application/json
{"items": [ { "companyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "taxNumber": "string", "city": "string", "street": "string", "houseNumber": "string", "postalCode": "string" } ], "pageNumber": 0, "totalPages": 0, "totalItemsCount": 0 }
401
application/json
string
403
application/json
string
Get one your company (🔒Token required )
GET
/company/{ id:uuid }
(allows you to get one your company 🔒️[token required])
http code
content-type
response
200
application/json
{"companyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "taxNumber": "string", "city": "string", "street": "string", "houseNumber": "string", "postalCode": "string"}
401
application/json
string
403
application/json
string
Functionality that allows to manage and interact with invoices
Create invoices (🔒Token required )
POST
/invoice
(allows to create new invoices 🔒️[token required])
name
type
data type
"sellerCompanyId"
required
uuid
"buyerCompanyId"
required
uuid
"termsOfPayment"
required
int
"paymentType"
required
string
"status"
required
string
http code
content-type
response
201
application/json
{ "invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "sellerCompanyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "buyerCompanyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "number": "string", "totalNetPrice": 0, "totalGrossPrice": 0, "termsOfPayment": 0, "paymentType": "string", "status": "string", "itemsId": ["3fa85f64-5717-4562-b3fc-2c963f66afa6"] }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
Update your unfinished invoices (🔒Token required )
PUT
/invoice
(allows to update your invoices 🔒️[token required])
name
type
data type
"invoiceId"
required
uuid
"status"
required
string
http code
content-type
response
200
application/json
{ "invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "sellerCompanyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "buyerCompanyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "number": "string", "totalNetPrice": 0, "totalGrossPrice": 0, "termsOfPayment": 0, "paymentType": "string", "status": "string", "itemsId": ["3fa85f64-5717-4562-b3fc-2c963f66afa6"] }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
Delete your unfinished invoices (🔒Token required )
DELETE
/invoice/{ id:uuid }
(allows to delete your invoices 🔒️[token required])
http code
content-type
response
204
application/json
NoContent
401
application/json
string
403
application/json
string
404
application/json
string
Finalize your unfinished invoices (🔒Token required )
PATCH
/invoice/lock/{ id:uuid }
(allows to finalize your invoices 🔒️[token required])
http code
content-type
response
200
application/json
string
401
application/json
string
403
application/json
string
404
application/json
string
Get all your invoices (🔒Token required )
GET
/invoice
(allows you to get all your invoices 🔒️[token required])
name
type
data type
PageNumber
not required
int32
PageSize
not required
int32
http code
content-type
response
200
application/json
[ { "invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "sellerCompanyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "buyerCompanyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "number": "string", "totalNetPrice": 0, "totalGrossPrice": 0, "termsOfPayment": 0, "paymentType": "string", "status": "string", "itemsId": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] } ]
401
application/json
string
403
application/json
string
Get one your invoice (🔒Token required )
GET
/invoice/{ id:uuid }
(allows you to get one your company 🔒️[token required])
http code
content-type
response
200
application/json
[ { "invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "sellerCompanyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "buyerCompanyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "number": "string", "totalNetPrice": 0, "totalGrossPrice": 0, "termsOfPayment": 0, "paymentType": "string", "status": "string", "itemsId": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] } ]
401
application/json
string
403
application/json
string
Functionality that allows to manage and interact with invoice items
Create new items on your unfinished invoice (🔒Token required )
POST
/item
(allows to create new items 🔒️[token required])
name
type
data type
"invoiceId"
required
uuid
"name"
required
string
"amount"
required
int
"unit"
required
string
"vat"
required
string
"netPrice"
required
decimal
http code
content-type
response
201
application/json
{ "invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "itemId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "amount": 0, "unit": "string", "vat": "string", "netPrice": 0, "sumNetPrice": 0, "sumGrossPrice": 0 }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
Update items on your unfinished invoice (🔒Token required )
PUT
/item
(allows to update your items 🔒️[token required])
name
type
data type
"itemId"
required
uuid
"name"
not required
string
"amount"
not required
int
"netPrice"
not required
decimal
http code
content-type
response
200
application/json
{ "invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "itemId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "amount": 0, "unit": "string", "vat": "string", "netPrice": 0, "sumNetPrice": 0, "sumGrossPrice": 0 }
400
application/json
array
401
application/json
string
403
application/json
string
404
application/json
string
Delete items on your unfinished invoice (🔒Token required )
DELETE
/item/{ id:uuid }
(allows to delete your items 🔒️[token required])
http code
content-type
response
204
application/json
NoContent
401
application/json
string
403
application/json
string
404
application/json
string
Get all items by invoice (🔒Token required )
GET
/item/all-by-invoice/{ id:uuid }
(allows you to get items by invoice 🔒️[token required])
http code
content-type
response
200
application/json
[ { "invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "itemId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "amount": 0, "unit": "string", "vat": "string", "netPrice": 0, "sumNetPrice": 0, "sumGrossPrice": 0 } ]
401
application/json
string
403
application/json
string
404
application/json
string
Get one item by id (🔒Token required )
GET
/item/{ id:uuid }
(allows you to get one item 🔒️[token required])
http code
content-type
response
200
application/json
[ { "invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "itemId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "amount": 0, "unit": "string", "vat": "string", "netPrice": 0, "sumNetPrice": 0, "sumGrossPrice": 0 } ]
401
application/json
string
403
application/json
string
404
application/json
string
PDF file is created automatically when the invoice is finalized
Get names of all your PDF files (🔒Token required )
GET
/storage
(allows to get names of all your PDF files 🔒️[token required])
http code
content-type
response
200
application/json
[ "string", "string", ]
401
application/json
string
403
application/json
string
404
application/json
string
Download your PDF file by name (🔒Token required )
GET
/storage/{ fileName:string }
(allows to download your PDF file 🔒️[token required])
http code
content-type
response
200
application/pdf
PDFfile
401
application/json
string
403
application/json
string
404
application/json
string