diff --git a/server/AyaNova/Controllers/WorkOrderController.cs b/server/AyaNova/Controllers/WorkOrderController.cs index 56859ecd..ab4833d4 100644 --- a/server/AyaNova/Controllers/WorkOrderController.cs +++ b/server/AyaNova/Controllers/WorkOrderController.cs @@ -98,7 +98,7 @@ namespace AyaNova.Api.Controllers return Ok(ApiOkResponse.Response(o)); } - /// + /// /// Get Customer view of WorkOrder /// /// @@ -202,6 +202,26 @@ namespace AyaNova.Api.Controllers } + /// + /// Get list of billable work orders for accounting integrations + /// + /// Only work orders set to this status (use 0 to ignore status) + /// List of billable workorders with related data + [HttpGet("accounting-list-billable/{workOrderStatusId}")] + public async Task GetAccountingListBillable([FromRoute] long workOrderStatusId) + { + if (!serverState.IsOpen) + return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); + WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); + if (!Authorized.HasReadFullRole(HttpContext.Items, biz.BizType)) + return StatusCode(403, new ApiNotAuthorizedResponse()); + if (!ModelState.IsValid) + return BadRequest(new ApiErrorResponse(ModelState)); + var o = await biz.GetAccountingListBillable(workOrderStatusId); + if (o == null) return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); + return Ok(ApiOkResponse.Response(o)); + } + #endregion WorkOrderTopLevel routes diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index c119ee85..e8374674 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -333,6 +333,50 @@ namespace AyaNova.Biz return ret; } + + //////////////////////////////////////////////////////////////////////////////////////////////// + // GET accounting billable list + // + internal async Task> GetAccountingListBillable(long workOrderStatusId) + { + + //if a specific status is requested then it doesn't matter if it's locked or not but if a specific status is not requested then any locked status is acceptable + string statusFragment=workOrderStatusId==0?"and aworkorderstatus.locked=true":$"and aworkorder.laststatusid={workOrderStatusId}"; + + var ret = new List(); + using (var command = ct.Database.GetDbConnection().CreateCommand()) + { + await ct.Database.OpenConnectionAsync(); + command.CommandText = @$"select + aworkorder.id, aworkorder.customerid, aworkorder.serial, aworkorder.servicedate, + acustomer.name as customername, aproject.name as projectname, + aworkorderstatus.name as statusname, aworkorderstatus.color + from aworkorder + left join acustomer on (aworkorder.customerid=acustomer.id) + left join aworkorderstatus on (aworkorder.laststatusid = aworkorderstatus.id) + left join aproject on (aworkorder.projectid=aproject.id) + where + aworkorder.invoicenumber is null + {statusFragment} + order by aworkorder.serial asc"; + using (var dr = await command.ExecuteReaderAsync()) + if (dr.HasRows) + { + if (await dr.ReadAsync()) + { + // o.LastWorkOrderViz = dr.GetInt64(0); + // o.LastServiceDateViz = dr.GetDateTime(1); + } + } + + await ct.Database.CloseConnectionAsync(); + } + + + + return ret; + } + //////////////////////////////////////////////////////////////////////////////////////////////// //UPDATE // diff --git a/server/AyaNova/models/dto/WorkOrderAccountingListItem.cs b/server/AyaNova/models/dto/WorkOrderAccountingListItem.cs new file mode 100644 index 00000000..3b157f49 --- /dev/null +++ b/server/AyaNova/models/dto/WorkOrderAccountingListItem.cs @@ -0,0 +1,18 @@ +using System; + +namespace AyaNova.Models +{ + + public class WorkOrderAccountingListItem + { + public long Id { get; set; } + public long CustomerId; + public string CustomerName; + public string WorkorderStatusName; + public long Serial { get; set; } + public DateTime? ServiceDate { get; set; } + public string Color { get; set; } + public string ProjectName { get; set; } + } + +}