Skip to content
Open
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
54 changes: 32 additions & 22 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
services:
projectr.backend:
build:
context: ./src
dockerfile: Dockerfile
context: .
dockerfile: src/Dockerfile

container_name: projectr-api
depends_on:
db:
condition: service_healthy
condition: service_started
seq:
condition: service_started

Expand All @@ -30,9 +30,9 @@ services:
- WhatsApp__BusinessAccountId=${WhatsApp__BusinessAccountId}
- WhatsApp__UseMock=${WhatsApp__UseMock}

- Cloudinary__CloudName=${Cloudinary__CloudName}
- Cloudinary__ApiKey=${Cloudinary__ApiKey}
- Cloudinary__ApiSecret=${Cloudinary__ApiSecret}
# - Cloudinary__CloudName=${Cloudinary__CloudName}
# - Cloudinary__ApiKey=${Cloudinary__ApiKey}
# - Cloudinary__ApiSecret=${Cloudinary__ApiSecret}

# Serilog Seq config
- Serilog__WriteTo__0__Name=Seq
Expand All @@ -43,25 +43,36 @@ services:
- "5001:5001"

db:
image: postgres:15
container_name: postgres
restart: always
image: mcr.microsoft.com/mssql/server:2022-latest
container_name: sqlserver
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: projectr

ports:
- "4400:80"
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ACCEPT_EULA=Y
- SA_PASSWORD=Test@1234
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
# test: ["CMD-SHELL", "timeout 5 bash -c '</dev/tcp/127.0.0.1/1433'"]
test: ["CMD-SHELL", "/opt/mssql-tools/bin/sqlcmd -U sa -P 'Test@1234' -Q 'SELECT 1'"]
interval: 10s
retries: 5
start_period: 30s
timeout: 10s
timeout: 30s

# ports:
# - "1433:1433"
# volumes:
# - sqlserver_data:/var/opt/mssql
# restart: always

# ports:
# - "4400:80"
# - "5432:5432"
# volumes:
# - postgres_data:/var/lib/postgresql/data
# healthcheck:
# test: [ "CMD-SHELL", "pg_isready -U postgres" ]
# interval: 10s
# retries: 5
# start_period: 30s
# timeout: 10s

networks:
- mynetwork
Expand All @@ -81,9 +92,8 @@ services:
- mynetwork

volumes:
postgres_data:
sqlserver_data:
seq_data:


networks:
mynetwork:
69 changes: 69 additions & 0 deletions src/Controllers/BusinessesAvailabilityController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using ProjectR.Backend.Application.Interfaces.Managers;
using ProjectR.Backend.Application.Models;

namespace ProjectR.Backend.Controllers
{
[Authorize]
[Route("api/[controller]")]
public class BusinessAvailabilityController : BaseController
{
private readonly IBusinessAvailabilityManager _manager;

public BusinessAvailabilityController(IBusinessAvailabilityManager manager)
{
_manager = manager;
}

[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(BusinessAvailabilityModel[]))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(BusinessAvailabilityModel[]))]
[HttpGet("GetByBusiness/{Id:guid}")]
public async Task<IActionResult> GetByBusiness(Guid Id, [FromQuery] bool includeAll = false)
{
BusinessAvailabilityModel[] result = await _manager.GetByBusinessId(Id, includeAll);
return Ok(result);
}

[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ResponseModel<BusinessAvailabilityModel>))]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ResponseModel<BusinessAvailabilityModel>))]
[HttpGet("{id:guid}")]
public async Task<IActionResult> Get(Guid id)
{
ResponseModel<BusinessAvailabilityModel> result = await _manager.GetByIdAsync(id);
return result.Status ? Ok(result) : BadRequest();
}

[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(ResponseModel<BusinessAvailabilityModel>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ResponseModel<BusinessAvailabilityModel>))]
[HttpPost]
public async Task<IActionResult> Add([FromBody] AddBusinessAvailabilityModel model)
{
if (model == null || !ModelState.IsValid)
{
return BadRequest(ModelState);
}

ResponseModel<BusinessAvailabilityModel> result = await _manager.AddAsync(model);
return result.Status ? Ok(result) : BadRequest(result);
}

[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(ResponseModel<BusinessAvailabilityModel>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ResponseModel<BusinessAvailabilityModel>))]
[HttpPut("{id:guid}")]
public async Task<IActionResult> Update(Guid id, [FromBody] UpdateBusinessAvailabilityModel model)
{
if (model == null || !ModelState.IsValid)
{
return BadRequest(ModelState);
}

ResponseModel<BusinessAvailabilityModel> result = await _manager.UpdateAsync(id, model);
return result.Status ? Ok(result) : BadRequest(result);
}
}
}
11 changes: 6 additions & 5 deletions src/Controllers/BusinessesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public async Task<IActionResult> Add([FromBody] AddBusinessModel business)
return BadRequest(ModelState);
}

business.UserId = UserId;
ResponseModel<BusinessModel> result = await _businessManager.AddAsync(business);
return result.Status ? Ok(result) : BadRequest(result);
}
Expand Down Expand Up @@ -89,13 +90,13 @@ public async Task<IActionResult> Delete([FromRoute] Guid id)
}

[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(ResponseModel<BusinessModel>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ResponseModel<BusinessModel>))]
[HttpGet("GetByUser")]
public async Task<IActionResult> GetByUserId()
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ResponseModel<BusinessModel>))]
[HttpGet("/Userbusinesses")]
public async Task<IActionResult> GetUserBusinesses()
{
BaseResponseModel result = await _businessManager.GetByUserId(UserId);
return result.Status ? Ok(result) : BadRequest(result);
BusinessModel[] result = await _businessManager.GetBusinessByUserAsync(UserId);
return Ok(result);
}

[Consumes("multipart/form-data")]
Expand Down
73 changes: 49 additions & 24 deletions src/Controllers/IndustryController.cs
Original file line number Diff line number Diff line change
@@ -1,57 +1,82 @@
using Microsoft.AspNetCore.Mvc;
using ProjectR.Backend.Application.Interfaces.Managers;
using ProjectR.Backend.Application.Models;
using ProjectR.Backend.Domain.Entities;
using ProjectR.Backend.Infrastructure.Managers;

namespace ProjectR.Backend.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class IndustryController : ControllerBase
public class IndustryController : BaseController
{
private readonly IIndustryManager _manager;
private readonly IIndustryManager _industryManager;

public IndustryController(IIndustryManager manager)
public IndustryController(IIndustryManager industryManager)
{
_manager = manager;
_industryManager = industryManager;
}

[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(ResponseModel<IndustryModel>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ResponseModel<IndustryModel>))]
[HttpPost]
public async Task<IActionResult> Create([FromBody] IndustryModel industry)
public async Task<IActionResult> Add([FromBody] AddIndustryModel industry)
{
var id = await _manager.CreateIndustryAsync(industry.Name, industry.Description);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please adjust the INDUSTRY controller to follow the convention of the other controllers?

return CreatedAtAction(nameof(GetById), new { id }, null);
}

[HttpGet("{id}")]
public async Task<IActionResult> GetById(Guid id)
{
var industry = await _manager.GetIndustryByIdAsync(id);
if (industry == null)
if (industry == null || !ModelState.IsValid)
{
return NotFound();
return BadRequest(ModelState);
}
return Ok(industry);

ResponseModel<IndustryModel> result = await _industryManager.AddAsync(industry);
return result.Status ? Ok(result) : BadRequest(result);
}

[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ResponseModel<IndustryModel>))]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ResponseModel<IndustryModel>))]
[HttpGet("{id:guid}")]
public async Task<IActionResult> Get(Guid id)
{
ResponseModel<IndustryModel> result = await _industryManager.GetByIdAsync(id);
return result.Status ? Ok(result) : BadRequest();
}

[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ResponseModel<IndustryModel[]>))]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ResponseModel<IndustryModel[]>))]
[HttpGet]
public async Task<IActionResult> GetAll()
{
var industries = await _manager.GetAllIndustriesAsync();
return Ok(industries);
IndustryModel[] result = await _industryManager.GetAllAsync();
return Ok(result);
}

[HttpPut("{id}")]
public async Task<IActionResult> Update(Guid id, [FromBody] IndustryModel industry)
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(ResponseModel<IndustryModel>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ResponseModel<IndustryModel>))]
[HttpPut]
public async Task<IActionResult> Update([FromBody] IndustryModel industry)
{
await _manager.UpdateIndustryAsync(id, industry.Name, industry.Description);
return NoContent();
if (industry == null || !ModelState.IsValid)
{
return BadRequest(ModelState);
}

ResponseModel<IndustryModel> result = await _industryManager.UpdateAsync(industry);
return result.Status ? Ok(result) : BadRequest(result);

}

[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(ResponseModel<IndustryModel>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ResponseModel<IndustryModel>))]
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(Guid id)
public async Task<IActionResult> Delete([FromRoute] Guid id)
{
await _manager.DeleteIndustryAsync(id);
return NoContent();
BaseResponseModel result = await _industryManager.DeleteAsync(id);
return result.Status ? Ok(result) : BadRequest(result);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using ProjectR.Backend.Application.Models;

namespace ProjectR.Backend.Application.Interfaces.Managers
{
public interface IBusinessAvailabilityManager
{
Task<ResponseModel<BusinessAvailabilityModel>> GetByIdAsync(Guid id);
Task<ResponseModel<BusinessAvailabilityModel>> AddAsync(AddBusinessAvailabilityModel model);
Task<ResponseModel<BusinessAvailabilityModel>> UpdateAsync(Guid id, UpdateBusinessAvailabilityModel model);
Task<BusinessAvailabilityModel[]> GetByBusinessId(Guid businessId, bool includeAll = false);
/// <summary>
/// Check if the business has any availability set already within a date range
/// </summary>
/// <param name="businessId"></param>
/// <returns></returns>
Task<bool> HasActiveAvailabilityAsync(Guid businessId, DateTime startDate, DateTime endDate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ public interface IBusinessManager
Task<ResponseModel<BusinessModel>> GetByIdAsync(Guid id);
Task<ResponseModel<BusinessModel>> GetBySlugAsync(string slug);
Task<BusinessModel[]> GetAllAsync();
Task<BusinessModel[]> GetBusinessByUserAsync(Guid UserId);
Task<ResponseModel<BusinessModel[]>> AddAsync(AddBusinessModel[] businesses);
Task<ResponseModel<BusinessModel>> AddAsync(AddBusinessModel business);
Task<ResponseModel<BusinessModel>> UpdateAsync(BusinessModel business);
Task<ResponseModel<BusinessModel[]>> UpdateAsync(BusinessModel[] businesses);
Task<BaseResponseModel> DeleteAsync(BusinessModel[] businesses);
Task<BaseResponseModel> DeleteAsync(Guid id);
Task<ResponseModel<BusinessModel>> GetByUserId(Guid userId);
Task<bool> IsBusinessExist(Guid userId);
Task<ResponseModel<BusinessModel>> UploadLogoAsync(Guid id, IFormFile file);
Task<bool> IsBusinessExist(Guid userId, Guid BusinessId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ namespace ProjectR.Backend.Application.Interfaces.Managers
{
public interface IIndustryManager
{
Task<Guid> CreateIndustryAsync(string name, string? description);
Task<Industry?> GetIndustryByIdAsync(Guid id);
Task<List<Industry>> GetAllIndustriesAsync();
Task UpdateIndustryAsync(Guid id, string name, string? description);
Task DeleteIndustryAsync(Guid id);
Task<ResponseModel<IndustryModel>> AddAsync(AddIndustryModel industry);
Task<ResponseModel<IndustryModel>> GetByIdAsync(Guid id);
Task<IndustryModel[]> GetAllAsync();
Task<ResponseModel<IndustryModel>> UpdateAsync(IndustryModel industry);
Task<BaseResponseModel> DeleteAsync(Guid id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using ProjectR.Backend.Application.Models;

namespace ProjectR.Backend.Application.Interfaces.Repository
{
public interface IBusinessAvailabilityRepository
{
Task<BusinessAvailabilityModel?> GetByIdAsync(Guid id);
Task<BusinessAvailabilityModel[]> GetAllByBusinessIdAsync(Guid id, bool includeAll = false);
Task<BusinessAvailabilityModel> AddAsync(BusinessAvailabilityModel model);
Task<BusinessAvailabilityModel> UpdateAsync(Guid id, UpdateBusinessAvailabilityModel model);
Task<bool> HasActiveAvailabilityAsync(Guid businessId, DateTime startDate, DateTime endDate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ public interface IBusinessRepository
Task<BusinessModel?> GetByIdAsync(Guid id);
Task<BusinessModel?> GetBySlugAsync(string slug);
Task<BusinessModel[]> GetAllAsync();
Task<BusinessModel[]> GetBusinessByUserAsync(Guid UserId);
Task<BusinessModel[]> AddAsync(BusinessModel[] businessModels);
Task<BusinessModel> AddAsync(BusinessModel businessModel);
Task<BusinessModel[]> UpdateAsync(BusinessModel[] businessModels);
Task<BusinessModel> UpdateAsync(BusinessModel businessModel);
Task DeleteAsync(BusinessModel[] businessModels);
Task DeleteAsync(BusinessModel businessModel);
Task<bool> SlugExistsAsync(string shortLink, Guid? excludedId = null);
Task<BusinessModel?> GetByUserId(Guid userId);
Task<bool> IsBusinessExist(Guid userId);
Task<bool> IsBusinessExist(Guid userId, Guid BusinessId);
}
}
Loading
Loading